geonetwork-ui 2.3.0-dev.3efe236f → 2.3.0-dev.431347d3

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 (188) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +2 -2
  2. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +2 -2
  3. package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.mjs +9 -7
  4. package/esm2022/libs/feature/dataviz/src/lib/chart-view/chart-view.component.mjs +1 -1
  5. package/esm2022/libs/feature/dataviz/src/lib/service/data.service.mjs +35 -2
  6. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-license/form-field-license.component.mjs +64 -0
  7. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-resource-updated/form-field-resource-updated.component.mjs +15 -0
  8. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.mjs +104 -0
  9. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.mjs +25 -6
  10. package/esm2022/libs/feature/editor/src/lib/components/wizard-field/wizard-field.component.mjs +1 -1
  11. package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +23 -1
  12. package/esm2022/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.mjs +73 -20
  13. package/esm2022/libs/feature/map/src/lib/add-layer-from-wfs/add-layer-from-wfs.component.mjs +1 -1
  14. package/esm2022/libs/feature/map/src/lib/add-layer-from-wms/add-layer-from-wms.component.mjs +1 -1
  15. package/esm2022/libs/feature/map/src/lib/map-context/map-context.model.mjs +1 -1
  16. package/esm2022/libs/feature/map/src/lib/map-context/map-context.service.mjs +37 -8
  17. package/esm2022/libs/feature/map/src/lib/utils/map-utils.service.mjs +6 -2
  18. package/esm2022/libs/feature/record/src/lib/data-view/data-view.component.mjs +1 -1
  19. package/esm2022/libs/feature/record/src/lib/map-view/map-view.component.mjs +4 -3
  20. package/esm2022/libs/feature/record/src/lib/state/mdview.facade.mjs +1 -1
  21. package/esm2022/libs/feature/record/src/lib/state/mdview.reducer.mjs +1 -3
  22. package/esm2022/libs/feature/search/src/index.mjs +2 -1
  23. package/esm2022/libs/feature/search/src/lib/results-layout/results-layout.component.mjs +1 -1
  24. package/esm2022/libs/feature/search/src/lib/sort-by/sort-by.component.mjs +1 -1
  25. package/esm2022/libs/feature/search/src/lib/utils/service/fields.service.mjs +1 -1
  26. package/esm2022/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.mjs +1 -1
  27. package/esm2022/libs/ui/catalog/src/lib/organisations-filter/organisations-filter.component.mjs +1 -1
  28. package/esm2022/libs/ui/elements/src/lib/api-card/api-card.component.mjs +3 -2
  29. package/esm2022/libs/ui/elements/src/lib/downloads-list/downloads-list.component.mjs +2 -2
  30. package/esm2022/libs/ui/elements/src/lib/link-card/link-card.component.mjs +16 -3
  31. package/esm2022/libs/ui/elements/src/lib/record-api-form/record-api-form.component.mjs +98 -36
  32. package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +1 -6
  33. package/esm2022/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.mjs +3 -5
  34. package/esm2022/libs/ui/inputs/src/index.mjs +16 -15
  35. package/esm2022/libs/ui/inputs/src/lib/check-toggle/check-toggle.component.mjs +4 -3
  36. package/esm2022/libs/ui/inputs/src/lib/date-picker/date-picker.component.mjs +22 -0
  37. package/esm2022/libs/ui/inputs/src/lib/date-range-picker/date-range-picker.component.mjs +7 -5
  38. package/esm2022/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.mjs +19 -8
  39. package/esm2022/libs/ui/inputs/src/lib/previous-next-buttons/previous-next-buttons.component.mjs +29 -0
  40. package/esm2022/libs/ui/inputs/src/lib/text-input/text-input.component.mjs +5 -3
  41. package/esm2022/libs/ui/inputs/src/lib/ui-inputs.module.mjs +14 -11
  42. package/esm2022/libs/ui/layout/src/index.mjs +2 -1
  43. package/esm2022/libs/ui/layout/src/lib/block-list/block-list.component.mjs +76 -0
  44. package/esm2022/libs/ui/layout/src/lib/carousel/carousel.component.mjs +42 -18
  45. package/esm2022/libs/ui/layout/src/lib/ui-layout.module.mjs +3 -8
  46. package/esm2022/libs/util/shared/src/lib/links/link-classifier.service.mjs +2 -2
  47. package/esm2022/libs/util/shared/src/lib/links/link-utils.mjs +22 -1
  48. package/esm2022/translations/de.json +22 -14
  49. package/esm2022/translations/en.json +22 -14
  50. package/esm2022/translations/es.json +22 -14
  51. package/esm2022/translations/fr.json +22 -14
  52. package/esm2022/translations/it.json +22 -14
  53. package/esm2022/translations/nl.json +22 -14
  54. package/esm2022/translations/pt.json +22 -14
  55. package/fesm2022/geonetwork-ui.mjs +1520 -912
  56. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  57. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
  58. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts.map +1 -1
  59. package/libs/feature/dataviz/src/lib/service/data.service.d.ts +3 -1
  60. package/libs/feature/dataviz/src/lib/service/data.service.d.ts.map +1 -1
  61. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-license/form-field-license.component.d.ts +39 -0
  62. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-license/form-field-license.component.d.ts.map +1 -0
  63. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-resource-updated/form-field-resource-updated.component.d.ts +8 -0
  64. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-resource-updated/form-field-resource-updated.component.d.ts.map +1 -0
  65. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.d.ts +21 -0
  66. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.d.ts.map +1 -0
  67. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts +4 -0
  68. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts.map +1 -1
  69. package/libs/feature/editor/src/lib/fields.config.d.ts.map +1 -1
  70. package/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.d.ts +10 -5
  71. package/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.d.ts.map +1 -1
  72. package/libs/feature/map/src/lib/map-context/map-context.model.d.ts +7 -0
  73. package/libs/feature/map/src/lib/map-context/map-context.model.d.ts.map +1 -1
  74. package/libs/feature/map/src/lib/map-context/map-context.service.d.ts.map +1 -1
  75. package/libs/feature/map/src/lib/utils/map-utils.service.d.ts.map +1 -1
  76. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts.map +1 -1
  77. package/libs/feature/record/src/lib/state/mdview.facade.d.ts.map +1 -1
  78. package/libs/feature/record/src/lib/state/mdview.reducer.d.ts.map +1 -1
  79. package/libs/feature/search/src/index.d.ts +1 -0
  80. package/libs/feature/search/src/index.d.ts.map +1 -1
  81. package/libs/feature/search/src/lib/utils/service/fields.service.d.ts +3 -3
  82. package/libs/feature/search/src/lib/utils/service/fields.service.d.ts.map +1 -1
  83. package/libs/ui/elements/src/lib/api-card/api-card.component.d.ts.map +1 -1
  84. package/libs/ui/elements/src/lib/downloads-list/downloads-list.component.d.ts +1 -1
  85. package/libs/ui/elements/src/lib/link-card/link-card.component.d.ts +3 -1
  86. package/libs/ui/elements/src/lib/link-card/link-card.component.d.ts.map +1 -1
  87. package/libs/ui/elements/src/lib/record-api-form/record-api-form.component.d.ts +24 -4
  88. package/libs/ui/elements/src/lib/record-api-form/record-api-form.component.d.ts.map +1 -1
  89. package/libs/ui/elements/src/lib/ui-elements.module.d.ts +29 -30
  90. package/libs/ui/elements/src/lib/ui-elements.module.d.ts.map +1 -1
  91. package/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.d.ts +1 -2
  92. package/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.d.ts.map +1 -1
  93. package/libs/ui/inputs/src/index.d.ts +15 -14
  94. package/libs/ui/inputs/src/index.d.ts.map +1 -1
  95. package/libs/ui/inputs/src/lib/check-toggle/check-toggle.component.d.ts +1 -1
  96. package/libs/ui/inputs/src/lib/check-toggle/check-toggle.component.d.ts.map +1 -1
  97. package/libs/ui/inputs/src/lib/date-picker/date-picker.component.d.ts +9 -0
  98. package/libs/ui/inputs/src/lib/date-picker/date-picker.component.d.ts.map +1 -0
  99. package/libs/ui/inputs/src/lib/date-range-picker/date-range-picker.component.d.ts +1 -1
  100. package/libs/ui/inputs/src/lib/date-range-picker/date-range-picker.component.d.ts.map +1 -1
  101. package/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.d.ts +2 -1
  102. package/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.d.ts.map +1 -1
  103. package/libs/ui/inputs/src/lib/previous-next-buttons/previous-next-buttons.component.d.ts +12 -0
  104. package/libs/ui/inputs/src/lib/previous-next-buttons/previous-next-buttons.component.d.ts.map +1 -0
  105. package/libs/ui/inputs/src/lib/text-input/text-input.component.d.ts +2 -1
  106. package/libs/ui/inputs/src/lib/text-input/text-input.component.d.ts.map +1 -1
  107. package/libs/ui/inputs/src/lib/ui-inputs.module.d.ts +35 -35
  108. package/libs/ui/layout/src/index.d.ts +1 -0
  109. package/libs/ui/layout/src/index.d.ts.map +1 -1
  110. package/libs/ui/layout/src/lib/block-list/block-list.component.d.ts +25 -0
  111. package/libs/ui/layout/src/lib/block-list/block-list.component.d.ts.map +1 -0
  112. package/libs/ui/layout/src/lib/carousel/carousel.component.d.ts +13 -6
  113. package/libs/ui/layout/src/lib/carousel/carousel.component.d.ts.map +1 -1
  114. package/libs/ui/layout/src/lib/ui-layout.module.d.ts +4 -5
  115. package/libs/ui/layout/src/lib/ui-layout.module.d.ts.map +1 -1
  116. package/libs/util/shared/src/lib/links/link-utils.d.ts +18 -0
  117. package/libs/util/shared/src/lib/links/link-utils.d.ts.map +1 -1
  118. package/package.json +2 -2
  119. package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +1 -1
  120. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +1 -4
  121. package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +16 -10
  122. package/src/libs/common/fixtures/src/lib/link.fixtures.ts +8 -0
  123. package/src/libs/common/fixtures/src/lib/records.fixtures.ts +2 -2
  124. package/src/libs/feature/dataviz/src/lib/service/data.service.ts +51 -1
  125. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-license/form-field-license.component.css +0 -0
  126. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-license/form-field-license.component.html +8 -0
  127. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-license/form-field-license.component.ts +64 -0
  128. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-resource-updated/form-field-resource-updated.component.css +0 -0
  129. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-resource-updated/form-field-resource-updated.component.html +4 -0
  130. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-resource-updated/form-field-resource-updated.component.ts +15 -0
  131. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.css +0 -0
  132. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.html +14 -0
  133. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.ts +143 -0
  134. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +38 -33
  135. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +21 -0
  136. package/src/libs/feature/editor/src/lib/fields.config.ts +22 -0
  137. package/src/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.css +7 -0
  138. package/src/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.html +32 -18
  139. package/src/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.ts +72 -17
  140. package/src/libs/feature/map/src/lib/map-context/map-context.model.ts +7 -0
  141. package/src/libs/feature/map/src/lib/map-context/map-context.service.ts +34 -8
  142. package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +5 -1
  143. package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +2 -1
  144. package/src/libs/feature/record/src/lib/state/mdview.facade.ts +0 -1
  145. package/src/libs/feature/record/src/lib/state/mdview.reducer.ts +0 -2
  146. package/src/libs/feature/search/src/index.ts +1 -0
  147. package/src/libs/feature/search/src/lib/utils/service/fields.service.ts +2 -2
  148. package/src/libs/ui/elements/src/lib/api-card/api-card.component.ts +2 -1
  149. package/src/libs/ui/elements/src/lib/downloads-list/downloads-list.component.ts +1 -1
  150. package/src/libs/ui/elements/src/lib/link-card/link-card.component.html +38 -20
  151. package/src/libs/ui/elements/src/lib/link-card/link-card.component.ts +12 -0
  152. package/src/libs/ui/elements/src/lib/record-api-form/record-api-form.component.html +26 -10
  153. package/src/libs/ui/elements/src/lib/record-api-form/record-api-form.component.ts +125 -30
  154. package/src/libs/ui/elements/src/lib/ui-elements.module.ts +0 -2
  155. package/src/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.html +1 -1
  156. package/src/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.ts +0 -1
  157. package/src/libs/ui/inputs/src/index.ts +15 -14
  158. package/src/libs/ui/inputs/src/lib/check-toggle/check-toggle.component.ts +3 -0
  159. package/src/libs/ui/inputs/src/lib/date-picker/date-picker.component.css +3 -0
  160. package/src/libs/ui/inputs/src/lib/date-picker/date-picker.component.html +11 -0
  161. package/src/libs/ui/inputs/src/lib/date-picker/date-picker.component.ts +16 -0
  162. package/src/libs/ui/inputs/src/lib/date-range-picker/date-range-picker.component.ts +8 -1
  163. package/src/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.html +1 -0
  164. package/src/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.ts +14 -0
  165. package/src/libs/ui/inputs/src/lib/previous-next-buttons/previous-next-buttons.component.css +6 -0
  166. package/src/libs/ui/inputs/src/lib/previous-next-buttons/previous-next-buttons.component.html +26 -0
  167. package/src/libs/ui/inputs/src/lib/previous-next-buttons/previous-next-buttons.component.ts +32 -0
  168. package/src/libs/ui/inputs/src/lib/text-input/text-input.component.html +1 -0
  169. package/src/libs/ui/inputs/src/lib/text-input/text-input.component.ts +1 -0
  170. package/src/libs/ui/inputs/src/lib/ui-inputs.module.ts +3 -3
  171. package/src/libs/ui/layout/src/index.ts +1 -0
  172. package/src/libs/ui/layout/src/lib/block-list/block-list.component.css +23 -0
  173. package/src/libs/ui/layout/src/lib/block-list/block-list.component.html +20 -0
  174. package/src/libs/ui/layout/src/lib/block-list/block-list.component.ts +84 -0
  175. package/src/libs/ui/layout/src/lib/carousel/carousel.component.css +8 -4
  176. package/src/libs/ui/layout/src/lib/carousel/carousel.component.html +4 -4
  177. package/src/libs/ui/layout/src/lib/carousel/carousel.component.ts +45 -15
  178. package/src/libs/ui/layout/src/lib/ui-layout.module.ts +0 -2
  179. package/src/libs/util/shared/src/lib/links/link-classifier.service.ts +1 -1
  180. package/src/libs/util/shared/src/lib/links/link-utils.ts +21 -0
  181. package/translations/de.json +22 -14
  182. package/translations/en.json +22 -14
  183. package/translations/es.json +22 -14
  184. package/translations/fr.json +22 -14
  185. package/translations/it.json +22 -14
  186. package/translations/nl.json +22 -14
  187. package/translations/pt.json +22 -14
  188. package/translations/sk.json +22 -14
@@ -25,6 +25,10 @@ import WMTS from 'ol/source/WMTS'
25
25
  import { Geometry } from 'ol/geom'
26
26
  import Feature from 'ol/Feature'
27
27
  import { WfsEndpoint, WmtsEndpoint } from '@camptocamp/ogc-client'
28
+ import OGCVectorTile from 'ol/source/OGCVectorTile.js'
29
+ import { MVT } from 'ol/format'
30
+ import VectorTileLayer from 'ol/layer/VectorTile'
31
+ import OGCMapTile from 'ol/source/OGCMapTile.js'
28
32
 
29
33
  export const DEFAULT_BASELAYER_CONTEXT: MapContextLayerXyzModel = {
30
34
  type: MapContextLayerTypeEnum.XYZ,
@@ -33,6 +37,7 @@ export const DEFAULT_BASELAYER_CONTEXT: MapContextLayerXyzModel = {
33
37
  `https://b.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png`,
34
38
  `https://c.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png`,
35
39
  ],
40
+ attributions: `<span>© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <a href="https://carto.com/">Carto</a></span>`,
36
41
  }
37
42
 
38
43
  export const DEFAULT_VIEW: MapContextViewModel = {
@@ -78,19 +83,37 @@ export class MapContextService {
78
83
  const style = this.styleService.styles.default
79
84
  switch (type) {
80
85
  case MapContextLayerTypeEnum.OGCAPI:
81
- return new VectorLayer({
82
- source: new VectorSource({
83
- format: new GeoJSON(),
84
- url: layerModel.url,
85
- }),
86
- style,
87
- })
88
-
86
+ if (layerModel.layerType === 'vectorTiles') {
87
+ return new VectorTileLayer({
88
+ source: new OGCVectorTile({
89
+ url: layerModel.url,
90
+ format: new MVT(),
91
+ attributions: layerModel.attributions,
92
+ }),
93
+ })
94
+ } else if (layerModel.layerType === 'mapTiles') {
95
+ return new TileLayer({
96
+ source: new OGCMapTile({
97
+ url: layerModel.url,
98
+ attributions: layerModel.attributions,
99
+ }),
100
+ })
101
+ } else {
102
+ return new VectorLayer({
103
+ source: new VectorSource({
104
+ format: new GeoJSON(),
105
+ url: layerModel.url,
106
+ attributions: layerModel.attributions,
107
+ }),
108
+ style,
109
+ })
110
+ }
89
111
  case MapContextLayerTypeEnum.XYZ:
90
112
  return new TileLayer({
91
113
  source: new XYZ({
92
114
  url: 'url' in layerModel ? layerModel.url : undefined,
93
115
  urls: 'urls' in layerModel ? layerModel.urls : undefined,
116
+ attributions: layerModel.attributions,
94
117
  }),
95
118
  })
96
119
  case MapContextLayerTypeEnum.WMS:
@@ -99,6 +122,7 @@ export class MapContextService {
99
122
  url: layerModel.url,
100
123
  params: { LAYERS: layerModel.name },
101
124
  gutter: 20,
125
+ attributions: layerModel.attributions,
102
126
  }),
103
127
  })
104
128
  case MapContextLayerTypeEnum.WMTS: {
@@ -123,6 +147,7 @@ export class MapContextService {
123
147
  tileGrid,
124
148
  projection: matrixSet.crs,
125
149
  dimensions,
150
+ attributions: layerModel.attributions,
126
151
  })
127
152
  )
128
153
  })
@@ -148,6 +173,7 @@ export class MapContextService {
148
173
  })
149
174
  },
150
175
  strategy: bboxStrategy,
176
+ attributions: layerModel.attributions,
151
177
  })
152
178
  )
153
179
  })
@@ -26,6 +26,7 @@ import {
26
26
  MapContextLayerWmsModel,
27
27
  } from '../map-context/map-context.model'
28
28
  import Collection from 'ol/Collection'
29
+ import { defaults as defaultControls } from 'ol/control.js'
29
30
  import MapBrowserEvent from 'ol/MapBrowserEvent'
30
31
  import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
31
32
  import { ProxyService } from '../../../../../../libs/util/shared/src'
@@ -47,7 +48,10 @@ export class MapUtilsService {
47
48
 
48
49
  createEmptyMap(): Map {
49
50
  return new Map({
50
- controls: [],
51
+ controls: defaultControls({
52
+ attribution: true,
53
+ attributionOptions: { collapsible: false },
54
+ }),
51
55
  pixelRatio: 1,
52
56
  })
53
57
  }
@@ -196,7 +196,8 @@ export class MapViewComponent implements OnInit, OnDestroy {
196
196
  } else if (
197
197
  (link.type === 'service' &&
198
198
  (link.accessServiceProtocol === 'wfs' ||
199
- link.accessServiceProtocol === 'esriRest')) ||
199
+ link.accessServiceProtocol === 'esriRest' ||
200
+ link.accessServiceProtocol === 'ogcFeatures')) ||
200
201
  link.type === 'download'
201
202
  ) {
202
203
  return this.dataService.readAsGeoJson(link).pipe(
@@ -8,7 +8,6 @@ import { DatavizConfigurationModel } from '../../../../../../libs/common/domain/
8
8
  import {
9
9
  CatalogRecord,
10
10
  UserFeedback,
11
- UserFeedbackViewModel,
12
11
  } from '../../../../../../libs/common/domain/src/lib/model/record'
13
12
  import { AvatarServiceInterface } from '../../../../../../libs/api/repository/src'
14
13
 
@@ -82,7 +82,6 @@ const metadataViewReducer = createReducer(
82
82
  */
83
83
  on(MetadataViewActions.loadUserFeedbacks, (state) => ({
84
84
  ...state,
85
- error: null,
86
85
  allUserFeedbacksLoading: true,
87
86
  })),
88
87
  on(MetadataViewActions.addUserFeedback, (state) => ({
@@ -93,7 +92,6 @@ const metadataViewReducer = createReducer(
93
92
  MetadataViewActions.loadUserFeedbacksSuccess,
94
93
  (state, { userFeedbacks }) => ({
95
94
  ...state,
96
- error: null,
97
95
  userFeedbacks: userFeedbacks,
98
96
  addUserFeedbackLoading: false,
99
97
  allUserFeedbacksLoading: false,
@@ -8,6 +8,7 @@ export * from './lib/state/effects'
8
8
  export * from './lib/state/reducer'
9
9
  export * from './lib/utils/service/search.service'
10
10
  export * from './lib/utils/service/fields.service'
11
+ export * from './lib/utils/service/fields'
11
12
  export * from './lib/results-list/results-list.container.component'
12
13
  export * from './lib/filter-dropdown/filter-dropdown.component'
13
14
  export * from './lib/constants'
@@ -36,7 +36,7 @@ marker('search.filters.contact')
36
36
  providedIn: 'root',
37
37
  })
38
38
  export class FieldsService {
39
- private fields = {
39
+ protected fields = {
40
40
  publisher: new OrganizationSearchField(this.injector),
41
41
  format: new SimpleSearchField('format', this.injector, 'asc'),
42
42
  resourceType: new TranslatedSearchField(
@@ -76,7 +76,7 @@ export class FieldsService {
76
76
  return Object.keys(this.fields)
77
77
  }
78
78
 
79
- constructor(private injector: Injector) {}
79
+ constructor(protected injector: Injector) {}
80
80
 
81
81
  getAvailableValues(fieldName: string) {
82
82
  if (this.supportedFields.indexOf(fieldName) === -1)
@@ -26,7 +26,8 @@ export class ApiCardComponent implements OnInit, OnChanges {
26
26
 
27
27
  ngOnInit() {
28
28
  this.displayApiFormButton =
29
- this.link.accessServiceProtocol === 'ogcFeatures' ? true : false
29
+ this.link.accessServiceProtocol === 'ogcFeatures' ||
30
+ this.link.accessServiceProtocol === 'wfs'
30
31
  }
31
32
 
32
33
  ngOnChanges(changes: SimpleChanges) {
@@ -95,6 +95,6 @@ export class DownloadsListComponent {
95
95
  }
96
96
 
97
97
  isFromWfs(link: DatasetDistribution) {
98
- return link.type === 'service' && link.accessServiceProtocol === 'wfs'
98
+ return link.type === 'download' && link.accessServiceProtocol === 'wfs'
99
99
  }
100
100
  }
@@ -1,25 +1,43 @@
1
1
  <a
2
2
  [href]="link.url"
3
3
  target="_blank"
4
- class="flex flex-col justify-between group h-40 grow py-5 px-5 bg-white rounded border-gray-300 filter card-shadow overflow-hidden lg:w-80"
4
+ class="flex flex-col justify-between group grow py-5 px-5 bg-white rounded border-gray-300 filter card-shadow overflow-hidden"
5
+ [ngClass]="{ 'h-40': !compact }"
6
+ [title]="title"
5
7
  >
6
- <div class="max-h-24 overflow-hidden text-ellipsis">
7
- <p
8
- class="font-title font-medium text-21 text-black break-words mb-1 line-clamp-2"
9
- >
10
- {{ link.name }}
11
- </p>
12
- <p class="font-medium text-sm break-words">
13
- {{ link.description }}
14
- </p>
15
- <p
16
- *ngIf="!link.name && !link.description"
17
- class="font-medium text-sm break-words truncate"
18
- >
19
- {{ link.url }}
20
- </p>
21
- </div>
22
- <div>
23
- <mat-icon class="material-symbols-outlined card-icon">open_in_new</mat-icon>
24
- </div>
8
+ <ng-container *ngIf="!compact; else compactTpl">
9
+ <div class="max-h-24 overflow-hidden text-ellipsis">
10
+ <p
11
+ class="font-title font-medium text-21 text-black break-words mb-1 line-clamp-2"
12
+ >
13
+ {{ link.name }}
14
+ </p>
15
+ <p class="font-medium text-sm break-words">
16
+ {{ link.description }}
17
+ </p>
18
+ <p
19
+ *ngIf="!link.name && !link.description"
20
+ class="font-medium text-sm break-words truncate"
21
+ >
22
+ {{ link.url }}
23
+ </p>
24
+ </div>
25
+ <div>
26
+ <mat-icon class="material-symbols-outlined card-icon"
27
+ >open_in_new</mat-icon
28
+ >
29
+ </div>
30
+ </ng-container>
31
+ <ng-template #compactTpl>
32
+ <div class="flex items-center justify-between gap-4">
33
+ <p
34
+ class="overflow-hidden font-title font-medium text-21 text-black text-ellipsis whitespace-nowrap"
35
+ >
36
+ {{ link.name || link.description }}
37
+ </p>
38
+ <mat-icon class="material-symbols-outlined card-icon flex-shrink-0"
39
+ >open_in_new</mat-icon
40
+ >
41
+ </div>
42
+ </ng-template>
25
43
  </a>
@@ -1,12 +1,24 @@
1
1
  import { Component, ChangeDetectionStrategy, Input } from '@angular/core'
2
2
  import { DatasetDistribution } from '../../../../../../libs/common/domain/src/lib/model/record'
3
+ import { MatIconModule } from '@angular/material/icon'
4
+ import { CommonModule } from '@angular/common'
3
5
 
4
6
  @Component({
5
7
  selector: 'gn-ui-link-card',
6
8
  templateUrl: './link-card.component.html',
7
9
  styleUrls: ['./link-card.component.css'],
8
10
  changeDetection: ChangeDetectionStrategy.OnPush,
11
+ standalone: true,
12
+ imports: [CommonModule, MatIconModule],
9
13
  })
10
14
  export class LinkCardComponent {
11
15
  @Input() link: DatasetDistribution
16
+ @Input() compact = false
17
+
18
+ get title() {
19
+ if (this.link.name && this.link.description) {
20
+ return `${this.link.name} | ${this.link.description}`
21
+ }
22
+ return this.link.name || this.link.description || ''
23
+ }
12
24
  }
@@ -37,15 +37,31 @@
37
37
  </div>
38
38
  </div>
39
39
  </div>
40
- <div class="flex flex-col gap-3">
41
- <p class="text-sm" translate>record.metadata.api.form.offset</p>
42
- <gn-ui-text-input
43
- class="w-20"
44
- [value]="offset$ | async"
45
- (valueChange)="setOffset($event)"
46
- hint=""
47
- >
48
- </gn-ui-text-input>
40
+ <div class="flex flex-col gap-3 relative">
41
+ <p class="text-sm" [class.text-gray-600]="!supportOffset" translate>
42
+ record.metadata.api.form.offset
43
+ </p>
44
+ <div class="flex items-center">
45
+ <gn-ui-text-input
46
+ class="w-20"
47
+ [value]="offset$ | async"
48
+ [disabled]="!supportOffset"
49
+ (valueChange)="supportOffset ? setOffset($event) : null"
50
+ hint=""
51
+ >
52
+ </gn-ui-text-input>
53
+ <div
54
+ *ngIf="!supportOffset"
55
+ class="flex items-center gap-2 text-orange-500 z-10 ml-3"
56
+ >
57
+ <span
58
+ class="material-symbols-outlined"
59
+ matTooltip="Not supported on this service"
60
+ >
61
+ warning
62
+ </span>
63
+ </div>
64
+ </div>
49
65
  </div>
50
66
  <div class="flex flex-col gap-3">
51
67
  <p class="text-sm" translate>record.metadata.api.form.type</p>
@@ -55,7 +71,7 @@
55
71
  extraBtnClass="secondary min-w-full !w-40 !text-black"
56
72
  [showTitle]="false"
57
73
  class="text-black"
58
- [choices]="formatsList"
74
+ [choices]="outputFormats"
59
75
  (selectValue)="setFormat($event)"
60
76
  [selected]="format$ | async"
61
77
  ></gn-ui-dropdown-selector>
@@ -1,12 +1,23 @@
1
1
  import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
2
- import { DatasetServiceDistribution } from '../../../../../../libs/common/domain/src/lib/model/record'
3
- import { BehaviorSubject, combineLatest, map } from 'rxjs'
2
+ import { OgcApiEndpoint, WfsEndpoint } from '@camptocamp/ogc-client'
3
+ import {
4
+ DatasetServiceDistribution,
5
+ ServiceProtocol,
6
+ } from '../../../../../../libs/common/domain/src/lib/model/record'
7
+ import { mimeTypeToFormat } from '../../../../../../libs/util/shared/src'
8
+ import { BehaviorSubject, combineLatest, filter, map, switchMap } from 'rxjs'
4
9
 
5
10
  const DEFAULT_PARAMS = {
6
11
  OFFSET: '',
7
12
  LIMIT: '-1',
8
13
  FORMAT: 'json',
9
14
  }
15
+
16
+ interface OutputFormats {
17
+ itemFormats?: any[]
18
+ outputFormats?: any[]
19
+ }
20
+
10
21
  @Component({
11
22
  selector: 'gn-ui-record-api-form',
12
23
  templateUrl: './record-api-form.component.html',
@@ -15,39 +26,45 @@ const DEFAULT_PARAMS = {
15
26
  })
16
27
  export class RecordApiFormComponent {
17
28
  @Input() set apiLink(value: DatasetServiceDistribution) {
18
- this.apiBaseUrl = value ? value.url.href : undefined
29
+ this.outputFormats = [{ value: 'json', label: 'JSON' }]
30
+ this.accessServiceProtocol = value ? value.accessServiceProtocol : undefined
31
+ this.apiFeatureType = value ? value.name : undefined
32
+ if (value) {
33
+ this.apiBaseUrl = value.url.href
34
+ this.createEndpoint().then(() => this.parseOutputFormats())
35
+ }
19
36
  this.resetUrl()
20
37
  }
21
- offset$ = new BehaviorSubject('')
22
- limit$ = new BehaviorSubject('')
23
- format$ = new BehaviorSubject('')
38
+
39
+ offset$ = new BehaviorSubject(DEFAULT_PARAMS.OFFSET)
40
+ limit$ = new BehaviorSubject(DEFAULT_PARAMS.LIMIT)
41
+ format$ = new BehaviorSubject(DEFAULT_PARAMS.FORMAT)
42
+ endpoint$ = new BehaviorSubject<WfsEndpoint | OgcApiEndpoint | undefined>(
43
+ undefined
44
+ )
24
45
  apiBaseUrl: string
25
- formatsList = [
26
- { label: 'JSON', value: 'json' },
27
- { label: 'CSV', value: 'csv' },
28
- ]
29
- apiQueryUrl$ = combineLatest([this.offset$, this.limit$, this.format$]).pipe(
30
- map(([offset, limit, format]) => {
31
- let outputUrl
32
- if (this.apiBaseUrl) {
33
- const url = new URL(this.apiBaseUrl)
34
- const params = { offset: offset, limit: limit, f: format }
35
- for (const [key, value] of Object.entries(params)) {
36
- if (value && value !== '0') {
37
- url.searchParams.set(key, value)
38
- } else {
39
- url.searchParams.delete(key)
40
- }
41
- }
42
- outputUrl = url.toString()
43
- }
44
- return outputUrl
45
- })
46
+ apiFeatureType: string
47
+ supportOffset = true
48
+ accessServiceProtocol: ServiceProtocol | undefined
49
+ outputFormats = [{ value: 'json', label: 'JSON' }]
50
+ endpoint: WfsEndpoint | OgcApiEndpoint | undefined
51
+ firstCollection: string | undefined
52
+
53
+ apiQueryUrl$ = combineLatest([
54
+ this.offset$,
55
+ this.limit$,
56
+ this.format$,
57
+ // only compute the url if the endpoint was created
58
+ this.endpoint$.pipe(filter((endpoint) => !!endpoint)),
59
+ ]).pipe(
60
+ switchMap(([offset, limit, format]) =>
61
+ this.generateApiQueryUrl(offset, limit, format)
62
+ )
46
63
  )
64
+
47
65
  noLimitChecked$ = this.limit$.pipe(
48
66
  map((limit) => limit === '-1' || limit === '')
49
67
  )
50
-
51
68
  displayLimit$ = this.limit$.pipe(
52
69
  map((limit) => (limit !== '-1' ? limit : ''))
53
70
  )
@@ -57,8 +74,7 @@ export class RecordApiFormComponent {
57
74
  }
58
75
 
59
76
  setLimit(value: string) {
60
- const newLimit = value === '' ? '-1' : value
61
- this.limit$.next(newLimit)
77
+ this.limit$.next(value === '' ? '-1' : value)
62
78
  }
63
79
 
64
80
  setFormat(value: string | unknown) {
@@ -70,4 +86,83 @@ export class RecordApiFormComponent {
70
86
  this.limit$.next(DEFAULT_PARAMS.LIMIT)
71
87
  this.format$.next(DEFAULT_PARAMS.FORMAT)
72
88
  }
89
+
90
+ async parseOutputFormats() {
91
+ if (!this.endpoint) return
92
+ const apiUrl = this.apiBaseUrl.endsWith('?')
93
+ ? this.apiBaseUrl.slice(0, -1)
94
+ : this.apiBaseUrl
95
+ const outputFormats = await this.getOutputFormats(apiUrl)
96
+
97
+ const formatsList = outputFormats.itemFormats
98
+ ? this.mapFormats(outputFormats.itemFormats)
99
+ : this.mapFormats(outputFormats.outputFormats || [])
100
+
101
+ this.outputFormats = this.outputFormats
102
+ .concat(formatsList.filter(Boolean))
103
+ .filter(
104
+ (format, index, self) =>
105
+ index === self.findIndex((t) => t.value === format.value)
106
+ )
107
+ .sort((a, b) => a.label.localeCompare(b.label))
108
+ }
109
+
110
+ mapFormats(formats: any[]) {
111
+ return formats.map((format) => {
112
+ const normalizedFormat = mimeTypeToFormat(format)
113
+ return normalizedFormat
114
+ ? { label: normalizedFormat.toUpperCase(), value: normalizedFormat }
115
+ : null
116
+ })
117
+ }
118
+
119
+ async getOutputFormats(url: string): Promise<OutputFormats> {
120
+ if (!this.endpoint) return {}
121
+ if (this.endpoint instanceof WfsEndpoint) {
122
+ this.supportOffset = this.endpoint.supportsStartIndex()
123
+ return this.endpoint.getServiceInfo() as OutputFormats
124
+ } else {
125
+ return (await this.endpoint.getCollectionInfo(
126
+ this.firstCollection
127
+ )) as OutputFormats
128
+ }
129
+ }
130
+
131
+ async createEndpoint() {
132
+ if (!this.apiBaseUrl || !this.accessServiceProtocol) return
133
+ if (this.accessServiceProtocol === 'wfs') {
134
+ this.endpoint = new WfsEndpoint(this.apiBaseUrl)
135
+ await (this.endpoint as WfsEndpoint).isReady()
136
+ } else {
137
+ this.endpoint = new OgcApiEndpoint(this.apiBaseUrl)
138
+ this.firstCollection = (await this.endpoint.allCollections)[0].name
139
+ }
140
+ this.endpoint$.next(this.endpoint)
141
+ }
142
+
143
+ async generateApiQueryUrl(
144
+ offset: string,
145
+ limit: string,
146
+ format: string
147
+ ): Promise<string> {
148
+ if (!this.apiBaseUrl || !this.endpoint || !this.apiFeatureType) return ''
149
+
150
+ const options = {
151
+ outputFormat: format,
152
+ startIndex: offset ? Number(offset) : undefined,
153
+ maxFeatures: limit !== '-1' ? Number(limit) : undefined,
154
+ limit: limit !== '-1' ? Number(limit) : limit === '-1' ? -1 : undefined,
155
+ offset: offset !== '' ? Number(offset) : undefined,
156
+ }
157
+
158
+ if (this.endpoint instanceof WfsEndpoint) {
159
+ options.maxFeatures = limit !== '-1' ? Number(limit) : undefined
160
+ return this.endpoint.getFeatureUrl(this.apiFeatureType, options)
161
+ } else {
162
+ return await this.endpoint.getCollectionItemsUrl(
163
+ this.firstCollection,
164
+ options
165
+ )
166
+ }
167
+ }
73
168
  }
@@ -57,7 +57,6 @@ import { TimeSincePipe } from './user-feedback-item/time-since.pipe'
57
57
  DownloadItemComponent,
58
58
  DownloadsListComponent,
59
59
  ApiCardComponent,
60
- LinkCardComponent,
61
60
  RelatedRecordCardComponent,
62
61
  MetadataContactComponent,
63
62
  MetadataCatalogComponent,
@@ -80,7 +79,6 @@ import { TimeSincePipe } from './user-feedback-item/time-since.pipe'
80
79
  DownloadItemComponent,
81
80
  DownloadsListComponent,
82
81
  ApiCardComponent,
83
- LinkCardComponent,
84
82
  RelatedRecordCardComponent,
85
83
  MetadataContactComponent,
86
84
  MetadataCatalogComponent,
@@ -30,7 +30,7 @@
30
30
  ></gn-ui-user-feedback-item>
31
31
  </div>
32
32
 
33
- <div *ngIf="isActiveUserEditor" class="mt-2 flex flex-col">
33
+ <div *ngIf="activeUser" class="mt-2 flex flex-col">
34
34
  <hr class="-mx-4 my-4" />
35
35
  <div
36
36
  id="new-comment-buttons"
@@ -21,7 +21,6 @@ import { UserModel } from '../../../../../../libs/common/domain/src/lib/model/us
21
21
  export class UserFeedbackItemComponent implements OnInit {
22
22
  @Input() userFeedbackParent: UserFeedbackViewModel
23
23
  @Input() userFeedBacksAnswers: UserFeedbackViewModel[]
24
- @Input() isActiveUserEditor: boolean
25
24
  @Input() activeUser: UserModel
26
25
  @Input() isLastComment: boolean
27
26
  @Input() isAddUserFeedbackLoading: boolean
@@ -1,21 +1,22 @@
1
- export * from './lib/dropdown-selector/dropdown-selector.component'
2
- export * from './lib/dropdown-selector/dropdown-selector.model'
3
- export * from './lib/dropdown-multiselect/dropdown-multiselect.component'
4
- export * from './lib/dropdown-multiselect/dropdown-multiselect.model'
5
- export * from './lib/text-input/text-input.component'
6
- export * from './lib/chips-input/chips-input.component'
7
- export * from './lib/text-area/text-area.component'
8
1
  export * from './lib/autocomplete/autocomplete.component'
9
- export * from './lib/star-toggle/star-toggle.component'
10
2
  export * from './lib/button/button.component'
11
- export * from './lib/viewport-intersector/viewport-intersector.component'
12
3
  export * from './lib/check-toggle/check-toggle.component'
13
- export * from './lib/ui-inputs.module'
4
+ export * from './lib/checkbox/checkbox.component'
5
+ export * from './lib/chips-input/chips-input.component'
14
6
  export * from './lib/copy-text-button/copy-text-button.component'
7
+ export * from './lib/date-picker/date-picker.component'
8
+ export * from './lib/date-range-picker/date-range-picker.component'
15
9
  export * from './lib/drag-and-drop-file-input/drag-and-drop-file-input.component'
10
+ export * from './lib/dropdown-multiselect/dropdown-multiselect.component'
11
+ export * from './lib/dropdown-multiselect/dropdown-multiselect.model'
12
+ export * from './lib/dropdown-selector/dropdown-selector.component'
13
+ export * from './lib/dropdown-selector/dropdown-selector.model'
14
+ export * from './lib/editable-label/editable-label.directive'
16
15
  export * from './lib/navigation-button/navigation-button.component'
17
- export * from './lib/viewport-intersector/viewport-intersector.component'
18
- export * from './lib/checkbox/checkbox.component'
19
16
  export * from './lib/search-input/search-input.component'
20
- export * from './lib/date-range-picker/date-range-picker.component'
21
- export * from './lib/editable-label/editable-label.directive'
17
+ export * from './lib/star-toggle/star-toggle.component'
18
+ export * from './lib/text-area/text-area.component'
19
+ export * from './lib/text-input/text-input.component'
20
+ export * from './lib/ui-inputs.module'
21
+ export * from './lib/viewport-intersector/viewport-intersector.component'
22
+ export * from './lib/previous-next-buttons/previous-next-buttons.component'
@@ -5,12 +5,15 @@ import {
5
5
  Input,
6
6
  Output,
7
7
  } from '@angular/core'
8
+ import { FormsModule } from '@angular/forms'
8
9
 
9
10
  @Component({
10
11
  selector: 'gn-ui-check-toggle',
11
12
  templateUrl: './check-toggle.component.html',
12
13
  styleUrls: ['./check-toggle.component.css'],
13
14
  changeDetection: ChangeDetectionStrategy.OnPush,
15
+ standalone: true,
16
+ imports: [FormsModule],
14
17
  })
15
18
  export class CheckToggleComponent {
16
19
  @Input() title: string
@@ -0,0 +1,3 @@
1
+ mat-datepicker-toggle {
2
+ @apply text-primary;
3
+ }
@@ -0,0 +1,11 @@
1
+ <div
2
+ class="flex items-center justify-between pl-3 rounded-lg border border-gray-300 bg-white"
3
+ >
4
+ <input
5
+ [matDatepicker]="picker"
6
+ [value]="date"
7
+ (dateChange)="dateChange.emit($event.value)"
8
+ />
9
+ <mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle>
10
+ </div>
11
+ <mat-datepicker #picker></mat-datepicker>
@@ -0,0 +1,16 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core'
2
+ import { MatNativeDateModule } from '@angular/material/core'
3
+ import { MatDatepickerModule } from '@angular/material/datepicker'
4
+ import { MatIconModule } from '@angular/material/icon'
5
+
6
+ @Component({
7
+ selector: 'gn-ui-date-picker',
8
+ templateUrl: './date-picker.component.html',
9
+ styleUrls: ['./date-picker.component.css'],
10
+ standalone: true,
11
+ imports: [MatIconModule, MatNativeDateModule, MatDatepickerModule],
12
+ })
13
+ export class DatePickerComponent {
14
+ @Input() date: Date
15
+ @Output() dateChange = new EventEmitter<Date>()
16
+ }