geonetwork-ui 2.2.0 → 2.3.0-dev.179fba83

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 (218) hide show
  1. package/esm2022/libs/api/metadata-converter/src/index.mjs +5 -5
  2. package/esm2022/libs/api/metadata-converter/src/lib/base.converter.mjs +14 -0
  3. package/esm2022/libs/api/metadata-converter/src/lib/find-converter.mjs +15 -0
  4. package/esm2022/libs/api/metadata-converter/src/lib/gn4/atomic-operations.mjs +3 -3
  5. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.converter.mjs +52 -0
  6. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +7 -3
  7. package/esm2022/libs/api/metadata-converter/src/lib/gn4/index.mjs +4 -0
  8. package/esm2022/libs/api/metadata-converter/src/lib/iso19115-3/index.mjs +2 -0
  9. package/esm2022/libs/api/metadata-converter/src/lib/iso19115-3/iso19115-3.converter.mjs +123 -0
  10. package/esm2022/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.mjs +116 -0
  11. package/esm2022/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.mjs +138 -0
  12. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/index.mjs +2 -0
  13. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.mjs +242 -0
  14. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +58 -62
  15. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/utils/individual-name.mjs +18 -0
  16. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/utils/keyword.mapper.mjs +14 -0
  17. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/utils/role.mapper.mjs +48 -0
  18. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/utils/status.mapper.mjs +18 -0
  19. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/utils/update-frequency.mapper.mjs +64 -0
  20. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +75 -58
  21. package/esm2022/libs/api/metadata-converter/src/lib/xml-utils.mjs +76 -14
  22. package/esm2022/libs/api/repository/src/lib/gn4/gn4-repository.mjs +4 -4
  23. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
  24. package/esm2022/libs/data-access/gn4/src/openapi/api/records.api.service.mjs +35 -7
  25. package/esm2022/libs/data-access/gn4/src/openapi/model/models.mjs +1 -2
  26. package/esm2022/libs/feature/dataviz/src/lib/service/data.service.mjs +2 -2
  27. package/esm2022/libs/feature/editor/src/lib/services/editor.service.mjs +8 -8
  28. package/esm2022/libs/feature/map/src/lib/add-layer-from-catalog/add-layer-record-preview/add-layer-record-preview.component.mjs +6 -2
  29. package/esm2022/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.mjs +72 -0
  30. package/esm2022/libs/feature/map/src/lib/feature-map.module.mjs +7 -3
  31. package/esm2022/libs/feature/map/src/lib/layers-panel/layers-panel.component.mjs +12 -7
  32. package/esm2022/libs/feature/map/src/lib/map-context/map-context.model.mjs +2 -1
  33. package/esm2022/libs/feature/map/src/lib/map-context/map-context.service.mjs +52 -25
  34. package/esm2022/libs/feature/map/src/lib/utils/map-utils.service.mjs +12 -49
  35. package/esm2022/libs/feature/record/src/lib/map-view/map-view.component.mjs +6 -2
  36. package/esm2022/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.mjs +3 -3
  37. package/esm2022/libs/ui/elements/src/lib/metadata-info/metadata-info.component.mjs +3 -3
  38. package/esm2022/libs/ui/elements/src/lib/thumbnail/thumbnail.component.mjs +4 -3
  39. package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +6 -5
  40. package/esm2022/libs/ui/inputs/src/lib/button/button.component.mjs +2 -1
  41. package/esm2022/libs/ui/inputs/src/lib/files-drop/files-drop.directive.mjs +59 -0
  42. package/esm2022/libs/ui/inputs/src/lib/image-input/image-input.component.mjs +183 -0
  43. package/esm2022/libs/ui/inputs/src/lib/ui-inputs.module.mjs +10 -4
  44. package/esm2022/libs/util/shared/src/lib/utils/bytes-convert.mjs +4 -0
  45. package/esm2022/libs/util/shared/src/lib/utils/image-resize.mjs +60 -0
  46. package/esm2022/libs/util/shared/src/lib/utils/index.mjs +8 -6
  47. package/esm2022/translations/de.json +12 -0
  48. package/esm2022/translations/en.json +12 -0
  49. package/esm2022/translations/es.json +12 -0
  50. package/esm2022/translations/fr.json +12 -0
  51. package/esm2022/translations/it.json +12 -0
  52. package/esm2022/translations/nl.json +12 -0
  53. package/esm2022/translations/pt.json +12 -0
  54. package/fesm2022/geonetwork-ui.mjs +3910 -2866
  55. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  56. package/libs/api/metadata-converter/src/index.d.ts +4 -4
  57. package/libs/api/metadata-converter/src/index.d.ts.map +1 -1
  58. package/libs/api/metadata-converter/src/lib/{metadata-base.mapper.d.ts → base.converter.d.ts} +3 -3
  59. package/libs/api/metadata-converter/src/lib/base.converter.d.ts.map +1 -0
  60. package/libs/api/metadata-converter/src/lib/find-converter.d.ts +3 -0
  61. package/libs/api/metadata-converter/src/lib/find-converter.d.ts.map +1 -0
  62. package/libs/api/metadata-converter/src/lib/gn4/{gn4.metadata.mapper.d.ts → gn4.converter.d.ts} +5 -5
  63. package/libs/api/metadata-converter/src/lib/gn4/gn4.converter.d.ts.map +1 -0
  64. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  65. package/libs/api/metadata-converter/src/lib/gn4/index.d.ts +4 -0
  66. package/libs/api/metadata-converter/src/lib/gn4/index.d.ts.map +1 -0
  67. package/libs/api/metadata-converter/src/lib/iso19115-3/index.d.ts +2 -0
  68. package/libs/api/metadata-converter/src/lib/iso19115-3/index.d.ts.map +1 -0
  69. package/libs/api/metadata-converter/src/lib/iso19115-3/iso19115-3.converter.d.ts +9 -0
  70. package/libs/api/metadata-converter/src/lib/iso19115-3/iso19115-3.converter.d.ts.map +1 -0
  71. package/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.d.ts +20 -0
  72. package/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.d.ts.map +1 -0
  73. package/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.d.ts +21 -0
  74. package/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.d.ts.map +1 -0
  75. package/libs/api/metadata-converter/src/lib/iso19139/index.d.ts +2 -0
  76. package/libs/api/metadata-converter/src/lib/iso19139/index.d.ts.map +1 -0
  77. package/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.d.ts +11 -0
  78. package/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.d.ts.map +1 -0
  79. package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts +34 -6
  80. package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts.map +1 -1
  81. package/libs/api/metadata-converter/src/lib/iso19139/utils/individual-name.d.ts +8 -0
  82. package/libs/api/metadata-converter/src/lib/iso19139/utils/individual-name.d.ts.map +1 -0
  83. package/libs/api/metadata-converter/src/lib/iso19139/utils/keyword.mapper.d.ts.map +1 -0
  84. package/libs/api/metadata-converter/src/lib/iso19139/utils/role.mapper.d.ts.map +1 -0
  85. package/libs/api/metadata-converter/src/lib/iso19139/utils/status.mapper.d.ts.map +1 -0
  86. package/libs/api/metadata-converter/src/lib/iso19139/utils/update-frequency.mapper.d.ts.map +1 -0
  87. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts +39 -3
  88. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
  89. package/libs/api/metadata-converter/src/lib/xml-utils.d.ts +14 -1
  90. package/libs/api/metadata-converter/src/lib/xml-utils.d.ts.map +1 -1
  91. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts +2 -2
  92. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts.map +1 -1
  93. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +6 -4
  94. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  95. package/libs/data-access/gn4/src/openapi/api/records.api.service.d.ts +9 -5
  96. package/libs/data-access/gn4/src/openapi/api/records.api.service.d.ts.map +1 -1
  97. package/libs/data-access/gn4/src/openapi/model/models.d.ts +0 -1
  98. package/libs/data-access/gn4/src/openapi/model/models.d.ts.map +1 -1
  99. package/libs/feature/editor/src/lib/services/editor.service.d.ts.map +1 -1
  100. package/libs/feature/map/src/lib/add-layer-from-catalog/add-layer-record-preview/add-layer-record-preview.component.d.ts.map +1 -1
  101. package/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.d.ts +23 -0
  102. package/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.d.ts.map +1 -0
  103. package/libs/feature/map/src/lib/feature-map.module.d.ts +2 -1
  104. package/libs/feature/map/src/lib/feature-map.module.d.ts.map +1 -1
  105. package/libs/feature/map/src/lib/layers-panel/layers-panel.component.d.ts +2 -0
  106. package/libs/feature/map/src/lib/layers-panel/layers-panel.component.d.ts.map +1 -1
  107. package/libs/feature/map/src/lib/map-context/map-context.model.d.ts +10 -5
  108. package/libs/feature/map/src/lib/map-context/map-context.model.d.ts.map +1 -1
  109. package/libs/feature/map/src/lib/map-context/map-context.service.d.ts.map +1 -1
  110. package/libs/feature/map/src/lib/utils/map-utils.service.d.ts +2 -3
  111. package/libs/feature/map/src/lib/utils/map-utils.service.d.ts.map +1 -1
  112. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts.map +1 -1
  113. package/libs/ui/elements/src/lib/thumbnail/thumbnail.component.d.ts +1 -1
  114. package/libs/ui/elements/src/lib/thumbnail/thumbnail.component.d.ts.map +1 -1
  115. package/libs/ui/elements/src/lib/ui-elements.module.d.ts +20 -20
  116. package/libs/ui/inputs/src/lib/button/button.component.d.ts.map +1 -1
  117. package/libs/ui/inputs/src/lib/files-drop/files-drop.directive.d.ts +14 -0
  118. package/libs/ui/inputs/src/lib/files-drop/files-drop.directive.d.ts.map +1 -0
  119. package/libs/ui/inputs/src/lib/image-input/image-input.component.d.ts +44 -0
  120. package/libs/ui/inputs/src/lib/image-input/image-input.component.d.ts.map +1 -0
  121. package/libs/ui/inputs/src/lib/ui-inputs.module.d.ts +2 -1
  122. package/libs/ui/inputs/src/lib/ui-inputs.module.d.ts.map +1 -1
  123. package/libs/util/shared/src/lib/utils/bytes-convert.d.ts +2 -0
  124. package/libs/util/shared/src/lib/utils/bytes-convert.d.ts.map +1 -0
  125. package/libs/util/shared/src/lib/utils/image-resize.d.ts +3 -0
  126. package/libs/util/shared/src/lib/utils/image-resize.d.ts.map +1 -0
  127. package/libs/util/shared/src/lib/utils/index.d.ts +7 -5
  128. package/libs/util/shared/src/lib/utils/index.d.ts.map +1 -1
  129. package/package.json +2 -2
  130. package/src/libs/api/metadata-converter/src/index.ts +4 -4
  131. package/src/libs/api/metadata-converter/src/lib/{metadata-base.mapper.ts → base.converter.ts} +2 -2
  132. package/src/libs/api/metadata-converter/src/lib/find-converter.ts +16 -0
  133. package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +32 -5
  134. package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +11 -4
  135. package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +33 -7
  136. package/src/libs/api/metadata-converter/src/lib/fixtures/metawal.records.ts +580 -0
  137. package/src/libs/api/metadata-converter/src/lib/gn4/atomic-operations.ts +2 -2
  138. package/src/libs/api/metadata-converter/src/lib/gn4/{gn4.metadata.mapper.ts → gn4.converter.ts} +2 -2
  139. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +8 -2
  140. package/src/libs/api/metadata-converter/src/lib/gn4/index.ts +3 -0
  141. package/src/libs/api/metadata-converter/src/lib/iso19115-3/index.ts +1 -0
  142. package/src/libs/api/metadata-converter/src/lib/iso19115-3/iso19115-3.converter.ts +176 -0
  143. package/src/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.ts +329 -0
  144. package/src/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.ts +513 -0
  145. package/src/libs/api/metadata-converter/src/lib/iso19139/index.ts +1 -0
  146. package/src/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.ts +327 -0
  147. package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +121 -82
  148. package/src/libs/api/metadata-converter/src/lib/iso19139/utils/individual-name.ts +20 -0
  149. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +175 -95
  150. package/src/libs/api/metadata-converter/src/lib/xml-utils.ts +84 -16
  151. package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +2 -2
  152. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +9 -4
  153. package/src/libs/data-access/gn4/src/openapi/api/records.api.service.ts +43 -12
  154. package/src/libs/data-access/gn4/src/openapi/model/models.ts +0 -1
  155. package/src/libs/data-access/gn4/src/spec.yaml +1 -1
  156. package/src/libs/feature/dataviz/src/lib/service/data.service.ts +1 -1
  157. package/src/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.css +0 -0
  158. package/src/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.html +8 -0
  159. package/src/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.ts +70 -0
  160. package/src/libs/feature/editor/src/lib/services/editor.service.ts +27 -16
  161. package/src/libs/feature/map/src/lib/add-layer-from-catalog/add-layer-record-preview/add-layer-record-preview.component.ts +5 -1
  162. package/src/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.css +0 -0
  163. package/src/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.html +36 -0
  164. package/src/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.ts +80 -0
  165. package/src/libs/feature/map/src/lib/feature-map.module.ts +2 -0
  166. package/src/libs/feature/map/src/lib/layers-panel/layers-panel.component.html +8 -0
  167. package/src/libs/feature/map/src/lib/layers-panel/layers-panel.component.ts +5 -0
  168. package/src/libs/feature/map/src/lib/map-context/map-context.model.ts +10 -3
  169. package/src/libs/feature/map/src/lib/map-context/map-context.service.ts +60 -32
  170. package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +17 -61
  171. package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +5 -1
  172. package/src/libs/ui/elements/src/lib/thumbnail/thumbnail.component.ts +5 -3
  173. package/src/libs/ui/elements/src/lib/ui-elements.module.ts +1 -1
  174. package/src/libs/ui/inputs/src/lib/button/button.component.ts +1 -1
  175. package/src/libs/ui/inputs/src/lib/files-drop/files-drop.directive.ts +45 -0
  176. package/src/libs/ui/inputs/src/lib/image-input/image-input.component.css +0 -0
  177. package/src/libs/ui/inputs/src/lib/image-input/image-input.component.html +146 -0
  178. package/src/libs/ui/inputs/src/lib/image-input/image-input.component.ts +193 -0
  179. package/src/libs/ui/inputs/src/lib/ui-inputs.module.ts +3 -0
  180. package/src/libs/util/shared/src/lib/utils/bytes-convert.ts +3 -0
  181. package/src/libs/util/shared/src/lib/utils/image-resize.ts +72 -0
  182. package/src/libs/util/shared/src/lib/utils/index.ts +7 -5
  183. package/translations/de.json +12 -0
  184. package/translations/en.json +12 -0
  185. package/translations/es.json +12 -0
  186. package/translations/fr.json +12 -0
  187. package/translations/it.json +12 -0
  188. package/translations/nl.json +12 -0
  189. package/translations/pt.json +12 -0
  190. package/translations/sk.json +12 -0
  191. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.mjs +0 -52
  192. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.mjs +0 -14
  193. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/codelists/role.mapper.mjs +0 -48
  194. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/codelists/status.mapper.mjs +0 -18
  195. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/codelists/update-frequency.mapper.mjs +0 -64
  196. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/converter.mjs +0 -130
  197. package/esm2022/libs/api/metadata-converter/src/lib/metadata-base.mapper.mjs +0 -14
  198. package/esm2022/libs/data-access/gn4/src/openapi/model/inlineObject3.api.model.mjs +0 -13
  199. package/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.d.ts.map +0 -1
  200. package/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.d.ts.map +0 -1
  201. package/libs/api/metadata-converter/src/lib/iso19139/codelists/role.mapper.d.ts.map +0 -1
  202. package/libs/api/metadata-converter/src/lib/iso19139/codelists/status.mapper.d.ts.map +0 -1
  203. package/libs/api/metadata-converter/src/lib/iso19139/codelists/update-frequency.mapper.d.ts.map +0 -1
  204. package/libs/api/metadata-converter/src/lib/iso19139/converter.d.ts +0 -4
  205. package/libs/api/metadata-converter/src/lib/iso19139/converter.d.ts.map +0 -1
  206. package/libs/api/metadata-converter/src/lib/metadata-base.mapper.d.ts.map +0 -1
  207. package/libs/data-access/gn4/src/openapi/model/inlineObject3.api.model.d.ts +0 -18
  208. package/libs/data-access/gn4/src/openapi/model/inlineObject3.api.model.d.ts.map +0 -1
  209. package/src/libs/api/metadata-converter/src/lib/iso19139/converter.ts +0 -196
  210. package/src/libs/data-access/gn4/src/openapi/model/inlineObject3.api.model.ts +0 -18
  211. /package/libs/api/metadata-converter/src/lib/iso19139/{codelists → utils}/keyword.mapper.d.ts +0 -0
  212. /package/libs/api/metadata-converter/src/lib/iso19139/{codelists → utils}/role.mapper.d.ts +0 -0
  213. /package/libs/api/metadata-converter/src/lib/iso19139/{codelists → utils}/status.mapper.d.ts +0 -0
  214. /package/libs/api/metadata-converter/src/lib/iso19139/{codelists → utils}/update-frequency.mapper.d.ts +0 -0
  215. /package/src/libs/api/metadata-converter/src/lib/iso19139/{codelists → utils}/keyword.mapper.ts +0 -0
  216. /package/src/libs/api/metadata-converter/src/lib/iso19139/{codelists → utils}/role.mapper.ts +0 -0
  217. /package/src/libs/api/metadata-converter/src/lib/iso19139/{codelists → utils}/status.mapper.ts +0 -0
  218. /package/src/libs/api/metadata-converter/src/lib/iso19139/{codelists → utils}/update-frequency.mapper.ts +0 -0
@@ -22,9 +22,9 @@ import { LayerConfig, MapConfig } from '../../../../../../libs/util/app-config/s
22
22
  import { FeatureCollection } from 'geojson'
23
23
  import { fromLonLat } from 'ol/proj'
24
24
  import WMTS from 'ol/source/WMTS'
25
- import { removeSearchParams } from '../../../../../../libs/util/shared/src'
26
25
  import { Geometry } from 'ol/geom'
27
26
  import Feature from 'ol/Feature'
27
+ import { WfsEndpoint, WmtsEndpoint } from '@camptocamp/ogc-client'
28
28
 
29
29
  export const DEFAULT_BASELAYER_CONTEXT: MapContextLayerXyzModel = {
30
30
  type: MapContextLayerTypeEnum.XYZ,
@@ -77,6 +77,15 @@ export class MapContextService {
77
77
  const { type } = layerModel
78
78
  const style = this.styleService.styles.default
79
79
  switch (type) {
80
+ case MapContextLayerTypeEnum.OGCAPI:
81
+ return new VectorLayer({
82
+ source: new VectorSource({
83
+ format: new GeoJSON(),
84
+ url: layerModel.url,
85
+ }),
86
+ style,
87
+ })
88
+
80
89
  case MapContextLayerTypeEnum.XYZ:
81
90
  return new TileLayer({
82
91
  source: new XYZ({
@@ -87,44 +96,63 @@ export class MapContextService {
87
96
  case MapContextLayerTypeEnum.WMS:
88
97
  return new TileLayer({
89
98
  source: new TileWMS({
90
- url: removeSearchParams(layerModel.url, ['request', 'service']),
99
+ url: layerModel.url,
91
100
  params: { LAYERS: layerModel.name },
92
101
  gutter: 20,
93
102
  }),
94
103
  })
95
- case MapContextLayerTypeEnum.WMTS:
96
- return new TileLayer({
97
- source: new WMTS(layerModel.options),
104
+ case MapContextLayerTypeEnum.WMTS: {
105
+ // TODO: isolate this in utils service
106
+ const olLayer = new TileLayer({})
107
+ const endpoint = new WmtsEndpoint(layerModel.url)
108
+ endpoint.isReady().then(async (endpoint) => {
109
+ const layerName = endpoint.getSingleLayerName() ?? layerModel.name
110
+ const layer = endpoint.getLayerByName(layerName)
111
+ const matrixSet = layer.matrixSets[0]
112
+ const tileGrid = await endpoint.getOpenLayersTileGrid(layer.name)
113
+ const resourceUrl = layer.resourceLinks[0]
114
+ const dimensions = endpoint.getDefaultDimensions(layer.name)
115
+ olLayer.setSource(
116
+ new WMTS({
117
+ layer: layer.name,
118
+ style: layer.defaultStyle,
119
+ matrixSet: matrixSet.identifier,
120
+ format: resourceUrl.format,
121
+ url: resourceUrl.url,
122
+ requestEncoding: resourceUrl.encoding,
123
+ tileGrid,
124
+ projection: matrixSet.crs,
125
+ dimensions,
126
+ })
127
+ )
98
128
  })
99
- case MapContextLayerTypeEnum.WFS:
100
- return new VectorLayer({
101
- source: new VectorSource({
102
- format: new GeoJSON(),
103
- url: function (extent) {
104
- const urlObj = new URL(
105
- removeSearchParams(layerModel.url, [
106
- 'service',
107
- 'version',
108
- 'request',
109
- ])
110
- )
111
- urlObj.searchParams.set('service', 'WFS')
112
- urlObj.searchParams.set('version', '1.1.0')
113
- urlObj.searchParams.set('request', 'GetFeature')
114
- urlObj.searchParams.set('outputFormat', 'application/json')
115
- urlObj.searchParams.set('typename', layerModel.name)
116
- urlObj.searchParams.set('srsname', 'EPSG:3857')
117
- urlObj.searchParams.set('bbox', `${extent.join(',')},EPSG:3857`)
118
- urlObj.searchParams.set(
119
- 'maxFeatures',
120
- WFS_MAX_FEATURES.toString()
121
- )
122
- return urlObj.toString()
123
- },
124
- strategy: bboxStrategy,
125
- }),
129
+ return olLayer
130
+ }
131
+ case MapContextLayerTypeEnum.WFS: {
132
+ const olLayer = new VectorLayer({
126
133
  style,
127
134
  })
135
+ new WfsEndpoint(layerModel.url).isReady().then((endpoint) => {
136
+ const featureType =
137
+ endpoint.getSingleFeatureTypeName() ?? layerModel.name
138
+ olLayer.setSource(
139
+ new VectorSource({
140
+ format: new GeoJSON(),
141
+ url: function (extent: [number, number, number, number]) {
142
+ return endpoint.getFeatureUrl(featureType, {
143
+ maxFeatures: WFS_MAX_FEATURES,
144
+ asJson: true,
145
+ outputCrs: 'EPSG:3857',
146
+ extent,
147
+ extentCrs: 'EPSG:3857',
148
+ })
149
+ },
150
+ strategy: bboxStrategy,
151
+ })
152
+ )
153
+ })
154
+ return olLayer
155
+ }
128
156
  case MapContextLayerTypeEnum.GEOJSON: {
129
157
  if ('url' in layerModel) {
130
158
  return new VectorLayer({
@@ -12,7 +12,6 @@ import Source from 'ol/source/Source'
12
12
  import ImageWMS from 'ol/source/ImageWMS'
13
13
  import TileWMS from 'ol/source/TileWMS'
14
14
  import VectorSource from 'ol/source/Vector'
15
- import { optionsFromCapabilities } from 'ol/source/WMTS'
16
15
  import { defaults, DragPan, Interaction, MouseWheelZoom } from 'ol/interaction'
17
16
  import {
18
17
  mouseOnly,
@@ -20,23 +19,17 @@ import {
20
19
  platformModifierKeyOnly,
21
20
  primaryAction,
22
21
  } from 'ol/events/condition'
23
- import WMTSCapabilities from 'ol/format/WMTSCapabilities'
24
- import { from, Observable } from 'rxjs'
22
+ import { Observable } from 'rxjs'
25
23
  import { map } from 'rxjs/operators'
26
24
  import {
27
25
  MapContextLayerModel,
28
- MapContextLayerTypeEnum,
29
26
  MapContextLayerWmsModel,
30
- MapContextLayerWmtsModel,
31
27
  } from '../map-context/map-context.model'
32
28
  import Collection from 'ol/Collection'
33
29
  import MapBrowserEvent from 'ol/MapBrowserEvent'
34
- import {
35
- CatalogRecord,
36
- DatasetDistribution,
37
- } from '../../../../../../libs/common/domain/src/lib/model/record'
30
+ import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
38
31
  import { ProxyService } from '../../../../../../libs/util/shared/src'
39
- import { WmsEndpoint } from '@camptocamp/ogc-client'
32
+ import { WmsEndpoint, WmtsEndpoint } from '@camptocamp/ogc-client'
40
33
  import { LONLAT_CRS_CODES } from '../constant/projections'
41
34
  import { fromEPSGCode, register } from 'ol/proj/proj4'
42
35
  import proj4 from 'proj4/dist/proj4'
@@ -152,11 +145,14 @@ export class MapUtilsService {
152
145
  } else if (layer && layer.type === 'wms') {
153
146
  latLonExtent = await this.getWmsLayerExtent(layer)
154
147
  } else if (layer && layer.type === 'wmts') {
155
- if (layer.extent) {
156
- latLonExtent = layer.extent
157
- } else {
158
- return layer.options.tileGrid.getExtent()
159
- }
148
+ // TODO: isolate this in utils service
149
+ latLonExtent = await new WmtsEndpoint(layer.url)
150
+ .isReady()
151
+ .then((endpoint) => {
152
+ const layerName = endpoint.getSingleLayerName() ?? layer.name
153
+ const wmtsLayer = endpoint.getLayerByName(layerName)
154
+ return wmtsLayer.latLonBoundingBox
155
+ })
160
156
  } else {
161
157
  return null
162
158
  }
@@ -180,59 +176,19 @@ export class MapUtilsService {
180
176
  LONLAT_CRS_CODES.includes(crs)
181
177
  )
182
178
  if (lonLatCRS) {
183
- return boundingBoxes[lonLatCRS].map(parseFloat)
179
+ return boundingBoxes[lonLatCRS]
184
180
  } else {
185
181
  const availableEPSGCode = Object.keys(boundingBoxes)[0]
186
182
  register(proj4)
187
183
  const proj = await fromEPSGCode(availableEPSGCode)
188
- const bboxWithFiniteNumbers =
189
- boundingBoxes[availableEPSGCode].map(parseFloat)
190
- return transformExtent(bboxWithFiniteNumbers, proj, 'EPSG:4326')
184
+ return transformExtent(
185
+ boundingBoxes[availableEPSGCode],
186
+ proj,
187
+ 'EPSG:4326'
188
+ )
191
189
  }
192
190
  }
193
191
 
194
- getWmtsLayerFromCapabilities(
195
- link: DatasetDistribution
196
- ): Observable<MapContextLayerWmtsModel> {
197
- const getCapabilitiesUrl = new URL(link.url, window.location.toString())
198
- getCapabilitiesUrl.searchParams.set('SERVICE', 'WMTS')
199
- getCapabilitiesUrl.searchParams.set('REQUEST', 'GetCapabilities')
200
- return from(
201
- fetch(getCapabilitiesUrl.toString())
202
- .then(async function (response) {
203
- if (!response.ok) {
204
- throw new Error(`WMTS GetCapabilities HTTP request failed with code ${
205
- response.status
206
- } and body:
207
- ${await response.text()}`)
208
- }
209
- return response.text()
210
- })
211
- .then(function (text) {
212
- try {
213
- const result = new WMTSCapabilities().read(text)
214
- const options = optionsFromCapabilities(result, {
215
- layer: link.name,
216
- matrixSet: 'EPSG:3857',
217
- })
218
- const layerCap = result?.Contents?.Layer.find(
219
- (layer) => layer.Identifier === link.name
220
- )
221
- return {
222
- options,
223
- type: MapContextLayerTypeEnum.WMTS as 'wmts',
224
- ...(layerCap?.WGS84BoundingBox
225
- ? { extent: layerCap.WGS84BoundingBox }
226
- : {}),
227
- }
228
- } catch (e: any) {
229
- throw new Error(`WMTS GetCapabilities parsing failed:
230
- ${e.stack || e.message || e}`)
231
- }
232
- })
233
- )
234
- }
235
-
236
192
  prioritizePageScroll(interactions: Collection<Interaction>) {
237
193
  interactions.clear()
238
194
  interactions.extend(
@@ -188,7 +188,11 @@ export class MapViewComponent implements OnInit, OnDestroy {
188
188
  link.type === 'service' &&
189
189
  link.accessServiceProtocol === 'wmts'
190
190
  ) {
191
- return this.mapUtils.getWmtsLayerFromCapabilities(link)
191
+ return of({
192
+ url: link.url.toString(),
193
+ type: MapContextLayerTypeEnum.WMTS,
194
+ name: link.name,
195
+ })
192
196
  } else if (
193
197
  (link.type === 'service' &&
194
198
  (link.accessServiceProtocol === 'wfs' ||
@@ -1,3 +1,4 @@
1
+ import { CommonModule } from '@angular/common'
1
2
  import {
2
3
  ChangeDetectionStrategy,
3
4
  Component,
@@ -18,20 +19,21 @@ export const THUMBNAIL_PLACEHOLDER = new InjectionToken<string>(
18
19
  'thumbnail-placeholder'
19
20
  )
20
21
 
22
+ type FitOptions = 'cover' | 'contain' | 'scale-down'
21
23
  type ThumbnailImageObject = {
22
24
  url: string
23
- fit?: 'cover' | 'contain' | 'scale-down'
25
+ fit?: FitOptions
24
26
  }
25
27
 
26
28
  const DEFAULT_PLACEHOLDER =
27
29
  'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH5gkNDCUFYjA1nwAAA1pJREFUeNrtnW2TmjAURh8CLlTdrmun///3tZ22+zLuYlehH7jsMGogwRiiec4MM44K6D3x3hAwAIQQQgghhJDYSM5cPwNQAMgBpACUg22GTg2gArAD8A9AKY+9CsgALAF8YRsGALwDeAWw9yGgALCKoKWP+WU8iwxjUsudLBj83sZciIiPSwhoWz7pJ5dUZFQXlEXOZ/DNeTBt3JnhBpc9aacGsOn0BuoIUk3b+5trGnEC4B7Ak4sUlInRU+wB/JbgVxG18KrTBc01EmYmcTFJQUVPy/9zTh/4BthLDOqeenB2DdBtZBN58LsSNpcUoEtTJWM/GIvMhQDde9j6h2OhXAjo6/2Q/lgkLgSQC0IBFEABZEKyiaQv5AAv7fSlS+lPVxRwOXTnEtoTPAs04yfRHGMoz8F/HOiaJfKeggLc78dmOHsVS33y9SUXsDuLlsg6FOAw/fhYhwI0pJ7WoQASpoC9p3UoQEPpaR0K0LCB3fB1e6KfAhxRweAKgQ5PsQxJ+CzCJYC/A7+EWt4TzVCE77GgEsBPHA/G7QBswcE4b+noVRZ2QxkCCqAAQgEUQCiAAggFUAChAAogFEABhAJcfT9FAdOxQuB/ML9lAfdo/qWYy2MK8EiO5mrrliUCvdIudAEzWWzQzWuxwjRnAK9WwAzAWhZTCe3l7cryNQrQBL/txZhKGGrlwc36ogIPfvdzfhuQsDDM80EVZXUFwe+mEJ2EOwBfLfYTTFFWVxL8Qwl3nedSye1jjhEyCjAPflfCWiScU1iDKMrqyoJ/KOFxRDf1sCg/xCxgTPC7EnIHn6GYsiirKw2+ayYryorBn7YoKwb/qCgntywg1OBPdqSsGPyTRXnp07gvPgD8AAl6KIICCAVQAAlLwOg5MSNi9NyqJgKqAHpQoZNZxs5KgG7SDN7AZzgWOxcCtprn5/wVfLb+uWXsrASUPXlvHbmETGKQjBVgMitVJTuaaQS2t/GoEMeE3onEor2jlK4RvwN4G1u9T4n6zp6PMTWAXzCYdCq12OCOhdeYZzT3mIErAW1Fr+HmNOAt82KSesYIAJoRzR2aIVumo+Ms8WwT/HOOZlM0Y+Zzxv2zp/gCTzfzPOyGtdfgp7LEcDvbvSxbWXg/HUIIIYQQQogx/wHLoX7NoCMFPwAAAABJRU5ErkJggg=='
28
30
 
29
- type FitOptions = 'cover' | 'contain' | 'scale-down'
30
-
31
31
  @Component({
32
32
  selector: 'gn-ui-thumbnail',
33
33
  templateUrl: './thumbnail.component.html',
34
34
  changeDetection: ChangeDetectionStrategy.OnPush,
35
+ standalone: true,
36
+ imports: [CommonModule],
35
37
  })
36
38
  export class ThumbnailComponent implements OnInit, OnChanges {
37
39
  @Input() thumbnailUrl: string | string[]
@@ -46,6 +46,7 @@ import { ImageOverlayPreviewComponent } from './image-overlay-preview/image-over
46
46
  FormsModule,
47
47
  NgOptimizedImage,
48
48
  MarkdownParserComponent,
49
+ ThumbnailComponent,
49
50
  ],
50
51
  declarations: [
51
52
  MetadataInfoComponent,
@@ -61,7 +62,6 @@ import { ImageOverlayPreviewComponent } from './image-overlay-preview/image-over
61
62
  MetadataQualityItemComponent,
62
63
  SearchResultsErrorComponent,
63
64
  PaginationComponent,
64
- ThumbnailComponent,
65
65
  AvatarComponent,
66
66
  UserPreviewComponent,
67
67
  GnUiLinkifyDirective,
@@ -15,7 +15,7 @@ import { propagateToDocumentOnly } from '../../../../../../libs/util/shared/src'
15
15
  standalone: true,
16
16
  })
17
17
  export class ButtonComponent {
18
- private btnClass: string
18
+ private btnClass = 'gn-ui-btn-default'
19
19
 
20
20
  @Input() set type(
21
21
  value: 'primary' | 'secondary' | 'default' | 'outline' | 'light'
@@ -0,0 +1,45 @@
1
+ import { Directive, HostListener, Output, EventEmitter } from '@angular/core'
2
+
3
+ @Directive({
4
+ selector: '[gnUiFilesDrop]',
5
+ standalone: true,
6
+ })
7
+ export class FilesDropDirective {
8
+ @Output() dragFilesOver: EventEmitter<boolean> = new EventEmitter()
9
+ @Output() dropFiles: EventEmitter<File[]> = new EventEmitter()
10
+
11
+ dragEnterCounter = 0
12
+
13
+ @HostListener('dragenter', ['$event'])
14
+ _onDragEnter(event: DragEvent) {
15
+ event.preventDefault()
16
+ this.dragEnterCounter++
17
+ this.dragFilesOver.emit(true)
18
+ }
19
+
20
+ @HostListener('dragover', ['$event'])
21
+ _onDragOver(event: DragEvent) {
22
+ event.preventDefault()
23
+ }
24
+
25
+ @HostListener('dragleave', ['$event'])
26
+ _onDragLeave(event: DragEvent) {
27
+ event.preventDefault()
28
+ this.dragEnterCounter = Math.max(0, this.dragEnterCounter - 1)
29
+ if (this.dragEnterCounter === 0) {
30
+ this.dragFilesOver.emit(false)
31
+ }
32
+ }
33
+
34
+ @HostListener('drop', ['$event'])
35
+ _onDrop(event: DragEvent) {
36
+ event.preventDefault()
37
+ this.dragEnterCounter = 0
38
+ this.dragFilesOver.emit(false)
39
+
40
+ const files = Array.from(event.dataTransfer.files)
41
+ if (files.length > 0) {
42
+ this.dropFiles.emit(files)
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,146 @@
1
+ <ng-container *ngIf="previewUrl; then withImage; else withoutImage">
2
+ </ng-container>
3
+
4
+ <ng-template #withImage>
5
+ <div class="w-full h-full flex flex-col gap-2">
6
+ <div class="flex-1 group relative">
7
+ <img
8
+ class="w-full h-full object-cover border-2 border-gray-300 rounded-lg"
9
+ [alt]="altText"
10
+ loading="lazy"
11
+ [src]="previewUrl"
12
+ />
13
+ <gn-ui-button
14
+ [extraClass]="
15
+ 'bg-gray-200 absolute right-2 bottom-2 invisible group-hover:visible'
16
+ "
17
+ (buttonClick)="handleDelete()"
18
+ >
19
+ <mat-icon class="material-symbols-outlined">delete</mat-icon>
20
+ </gn-ui-button>
21
+ </div>
22
+ <input
23
+ *ngIf="showAltTextInput"
24
+ type="text"
25
+ class="py-3 px-2 border-2 border-gray-300 rounded-lg text-sm font-medium"
26
+ [placeholder]="'input.image.altTextPlaceholder' | translate"
27
+ [value]="altText"
28
+ (change)="handleAltTextChange($event)"
29
+ />
30
+ <div class="flex flex-row gap-2">
31
+ <gn-ui-button
32
+ [extraClass]="'bg-gray-200 font-bold'"
33
+ (buttonClick)="handleDelete()"
34
+ >
35
+ <mat-icon class="material-symbols-outlined me-1">delete</mat-icon>
36
+ {{ 'input.image.delete' | translate }}
37
+ </gn-ui-button>
38
+ <gn-ui-button
39
+ *ngIf="!showAltTextInput"
40
+ [extraClass]="'bg-gray-200 font-bold'"
41
+ (buttonClick)="toggleAltTextInput()"
42
+ >
43
+ <mat-icon class="material-symbols-outlined me-1">add</mat-icon>
44
+ {{ 'input.image.displayAltTextInput' | translate }}
45
+ </gn-ui-button>
46
+ </div>
47
+ </div>
48
+ </ng-template>
49
+
50
+ <ng-template #withoutImage>
51
+ <div class="w-full h-full flex flex-col gap-2">
52
+ <label
53
+ gnUiFilesDrop
54
+ class="block flex-1 border-2 border-dashed border-gray-300 rounded-lg p-6 flex flex-col items-center justify-center gap-4"
55
+ (dragFilesOver)="handleDragFilesOver($event)"
56
+ (dropFiles)="handleDropFiles($event)"
57
+ >
58
+ <div class="w-14 h-14 rounded-md bg-gray-200 grid">
59
+ <mat-icon
60
+ *ngIf="!dragFilesOver && !uploadProgress && !uploadError"
61
+ class="material-symbols-outlined place-self-center text-blue-500"
62
+ >image</mat-icon
63
+ >
64
+ <mat-icon
65
+ *ngIf="dragFilesOver && !uploadProgress && !uploadError"
66
+ class="material-symbols-outlined place-self-center text-blue-500"
67
+ >add_box</mat-icon
68
+ >
69
+ <div *ngIf="uploadProgress">
70
+ <mat-progress-spinner
71
+ class="place-self-center"
72
+ [diameter]="56"
73
+ [mode]="'determinate'"
74
+ [value]="uploadProgress"
75
+ ></mat-progress-spinner>
76
+ <span
77
+ class="text-sm font-medium relative inline-block width-[30px] bottom-[40px] left-[15px]"
78
+ >
79
+ {{ uploadProgress }}%
80
+ </span>
81
+ </div>
82
+ <mat-icon
83
+ *ngIf="uploadError"
84
+ class="material-symbols-outlined place-self-center text-rose-500"
85
+ >broken_image</mat-icon
86
+ >
87
+ </div>
88
+ <div class="flex flex-col items-center gap-1">
89
+ <p class="font-medium">{{ getPrimaryText() | translate }}</p>
90
+ <p
91
+ class="text-sm"
92
+ [class]="
93
+ uploadProgress || uploadError
94
+ ? 'font-bold text-blue-500 cursor-pointer'
95
+ : 'font-medium text-gray-500'
96
+ "
97
+ (click)="handleSecondaryTextClick()"
98
+ >
99
+ {{ getSecondaryText() | translate }}
100
+ </p>
101
+ </div>
102
+ <input
103
+ type="file"
104
+ class="hidden"
105
+ (change)="handleFileInput($event)"
106
+ [disabled]="showUrlInput || uploadProgress || uploadError"
107
+ />
108
+ </label>
109
+ <div *ngIf="!showUrlInput" class="flex-none">
110
+ <gn-ui-button
111
+ [extraClass]="'bg-gray-200 font-bold'"
112
+ (buttonClick)="displayUrlInput()"
113
+ >
114
+ <mat-icon class="material-symbols-outlined me-1">link</mat-icon>
115
+ {{ 'input.image.displayUrlInput' | translate }}
116
+ </gn-ui-button>
117
+ </div>
118
+ <div *ngIf="showUrlInput" class="flex-none flex flex-col gap-2">
119
+ <div class="h-2"></div>
120
+ <div class="flex gap-2 items-center">
121
+ <div class="flex-1 flex rounded-lg">
122
+ <span
123
+ class="material-symbols-outlined px-4 inline-flex items-center min-w-fit rounded-s-lg border-2 border-e-0 border-gray-300"
124
+ >link</span
125
+ >
126
+ <input
127
+ type="text"
128
+ class="py-3 ps-1 block w-full border-2 border-s-0 border-e-0 border-gray-300 text-sm font-medium"
129
+ placeholder="https://exemple.com/image.jpg"
130
+ (change)="handleUrlChange($event)"
131
+ />
132
+ <gn-ui-button
133
+ class="px-1 inline-flex items-center min-w-fit rounded-e-lg border-2 border-s-0 border-gray-300 text-white"
134
+ [extraClass]="
135
+ urlInputValue && !downloadError ? 'bg-blue-500' : 'bg-gray-500'
136
+ "
137
+ [disabled]="!urlInputValue || downloadError"
138
+ (buttonClick)="downloadUrl()"
139
+ >
140
+ <mat-icon class="material-symbols-outlined">arrow_upward</mat-icon>
141
+ </gn-ui-button>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ </div>
146
+ </ng-template>