geonetwork-ui 2.2.0-dev.c15a456d → 2.2.0-dev.ca028047

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 (210) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/gn4/atomic-operations.mjs +2 -1
  2. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +36 -2
  3. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.mjs +2 -1
  4. package/esm2022/libs/api/repository/src/lib/gn4/index.mjs +3 -1
  5. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
  6. package/esm2022/libs/feature/catalog/src/lib/organisations/organisations.component.mjs +4 -15
  7. package/esm2022/libs/feature/dataviz/src/lib/service/data.service.mjs +5 -4
  8. package/esm2022/libs/feature/editor/src/lib/record-form/record-form.component.mjs +5 -3
  9. package/esm2022/libs/feature/map/src/index.mjs +2 -1
  10. package/esm2022/libs/feature/map/src/lib/add-layer-from-catalog/add-layer-record-preview/add-layer-record-preview.component.mjs +1 -1
  11. package/esm2022/libs/feature/map/src/lib/add-layer-from-file/add-layer-from-file.component.mjs +106 -0
  12. package/esm2022/libs/feature/map/src/lib/add-layer-from-wfs/add-layer-from-wfs.component.mjs +64 -0
  13. package/esm2022/libs/feature/map/src/lib/add-layer-from-wms/add-layer-from-wms.component.mjs +63 -0
  14. package/esm2022/libs/feature/map/src/lib/constant/index.mjs +2 -1
  15. package/esm2022/libs/feature/map/src/lib/constant/projections.mjs +2 -0
  16. package/esm2022/libs/feature/map/src/lib/feature-map.module.mjs +26 -3
  17. package/esm2022/libs/feature/map/src/lib/geocoding/geocoding.component.mjs +93 -0
  18. package/esm2022/libs/feature/map/src/lib/geocoding.service.mjs +40 -0
  19. package/esm2022/libs/feature/map/src/lib/layers-panel/layers-panel.component.mjs +6 -3
  20. package/esm2022/libs/feature/map/src/lib/map-context/map-context.service.mjs +3 -1
  21. package/esm2022/libs/feature/map/src/lib/utils/index.mjs +1 -3
  22. package/esm2022/libs/feature/map/src/lib/utils/map-utils.service.mjs +60 -29
  23. package/esm2022/libs/feature/record/src/lib/map-view/map-view.component.mjs +29 -20
  24. package/esm2022/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.mjs +7 -4
  25. package/esm2022/libs/feature/search/src/lib/results-list/results-list.container.component.mjs +1 -1
  26. package/esm2022/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.mjs +4 -4
  27. package/esm2022/libs/ui/catalog/src/lib/organisation-preview/organisation-preview.component.mjs +1 -1
  28. package/esm2022/libs/ui/elements/src/index.mjs +4 -1
  29. package/esm2022/libs/ui/elements/src/lib/downloads-list/downloads-list.component.mjs +3 -3
  30. package/esm2022/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.mjs +27 -0
  31. package/esm2022/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.mjs +17 -0
  32. package/esm2022/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.mjs +10 -3
  33. package/esm2022/libs/ui/elements/src/lib/metadata-info/metadata-info.component.mjs +12 -6
  34. package/esm2022/libs/ui/elements/src/lib/related-record-card/related-record-card.component.mjs +3 -3
  35. package/esm2022/libs/ui/elements/src/lib/thumbnail/thumbnail.component.mjs +7 -3
  36. package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +15 -3
  37. package/esm2022/libs/ui/inputs/src/lib/button/button.component.mjs +2 -2
  38. package/esm2022/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.mjs +6 -3
  39. package/esm2022/libs/ui/inputs/src/lib/editable-label/editable-label.directive.mjs +46 -0
  40. package/esm2022/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.mjs +3 -3
  41. package/esm2022/libs/ui/inputs/src/lib/star-toggle/star-toggle.component.mjs +2 -2
  42. package/esm2022/libs/ui/inputs/src/lib/ui-inputs.module.mjs +8 -3
  43. package/esm2022/libs/ui/layout/src/lib/carousel/carousel.component.mjs +2 -2
  44. package/esm2022/libs/ui/search/src/lib/record-preview-card/record-preview-card.component.mjs +1 -1
  45. package/esm2022/libs/ui/search/src/lib/record-preview-feed/record-preview-feed.component.mjs +1 -1
  46. package/esm2022/libs/ui/search/src/lib/record-preview-list/record-preview-list.component.mjs +1 -1
  47. package/esm2022/libs/ui/search/src/lib/record-preview-row/record-preview-row.component.mjs +1 -1
  48. package/esm2022/libs/ui/search/src/lib/record-preview-title/record-preview-title.component.mjs +1 -1
  49. package/esm2022/libs/ui/search/src/lib/record-table/record-table.component.mjs +3 -3
  50. package/esm2022/libs/util/i18n/src/index.mjs +2 -1
  51. package/esm2022/libs/util/shared/src/lib/links/link-utils.mjs +29 -13
  52. package/esm2022/libs/util/shared/src/lib/utils/fuzzy-filter.mjs +27 -0
  53. package/esm2022/libs/util/shared/src/lib/utils/index.mjs +2 -1
  54. package/esm2022/translations/de.json +102 -87
  55. package/esm2022/translations/en.json +35 -20
  56. package/esm2022/translations/es.json +15 -0
  57. package/esm2022/translations/fr.json +19 -4
  58. package/esm2022/translations/it.json +27 -12
  59. package/esm2022/translations/nl.json +15 -0
  60. package/esm2022/translations/pt.json +15 -0
  61. package/fesm2022/geonetwork-ui.mjs +916 -298
  62. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  63. package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts +1 -0
  64. package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts.map +1 -1
  65. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  66. package/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.d.ts.map +1 -1
  67. package/libs/api/repository/src/lib/gn4/index.d.ts +2 -0
  68. package/libs/api/repository/src/lib/gn4/index.d.ts.map +1 -1
  69. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +10 -5
  70. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  71. package/libs/feature/catalog/src/lib/organisations/organisations.component.d.ts +0 -1
  72. package/libs/feature/catalog/src/lib/organisations/organisations.component.d.ts.map +1 -1
  73. package/libs/feature/dataviz/src/lib/service/data.service.d.ts +15 -2
  74. package/libs/feature/dataviz/src/lib/service/data.service.d.ts.map +1 -1
  75. package/libs/feature/editor/src/lib/record-form/record-form.component.d.ts.map +1 -1
  76. package/libs/feature/map/src/index.d.ts +1 -0
  77. package/libs/feature/map/src/index.d.ts.map +1 -1
  78. package/libs/feature/map/src/lib/add-layer-from-file/add-layer-from-file.component.d.ts +22 -0
  79. package/libs/feature/map/src/lib/add-layer-from-file/add-layer-from-file.component.d.ts.map +1 -0
  80. package/libs/feature/map/src/lib/add-layer-from-wfs/add-layer-from-wfs.component.d.ts +22 -0
  81. package/libs/feature/map/src/lib/add-layer-from-wfs/add-layer-from-wfs.component.d.ts.map +1 -0
  82. package/libs/feature/map/src/lib/add-layer-from-wms/add-layer-from-wms.component.d.ts +22 -0
  83. package/libs/feature/map/src/lib/add-layer-from-wms/add-layer-from-wms.component.d.ts.map +1 -0
  84. package/libs/feature/map/src/lib/constant/index.d.ts +1 -0
  85. package/libs/feature/map/src/lib/constant/index.d.ts.map +1 -1
  86. package/libs/feature/map/src/lib/constant/projections.d.ts.map +1 -0
  87. package/libs/feature/map/src/lib/feature-map.module.d.ts +16 -12
  88. package/libs/feature/map/src/lib/feature-map.module.d.ts.map +1 -1
  89. package/libs/feature/map/src/lib/geocoding/geocoding.component.d.ts +25 -0
  90. package/libs/feature/map/src/lib/geocoding/geocoding.component.d.ts.map +1 -0
  91. package/libs/feature/map/src/lib/geocoding.service.d.ts +18 -0
  92. package/libs/feature/map/src/lib/geocoding.service.d.ts.map +1 -0
  93. package/libs/feature/map/src/lib/map-context/map-context.service.d.ts +1 -0
  94. package/libs/feature/map/src/lib/map-context/map-context.service.d.ts.map +1 -1
  95. package/libs/feature/map/src/lib/utils/index.d.ts +0 -2
  96. package/libs/feature/map/src/lib/utils/index.d.ts.map +1 -1
  97. package/libs/feature/map/src/lib/utils/map-utils.service.d.ts +13 -11
  98. package/libs/feature/map/src/lib/utils/map-utils.service.d.ts.map +1 -1
  99. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts +1 -3
  100. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts.map +1 -1
  101. package/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.d.ts +2 -1
  102. package/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.d.ts.map +1 -1
  103. package/libs/ui/dataviz/src/lib/chart/chart.component.d.ts +1 -1
  104. package/libs/ui/elements/src/index.d.ts +3 -0
  105. package/libs/ui/elements/src/index.d.ts.map +1 -1
  106. package/libs/ui/elements/src/lib/downloads-list/downloads-list.component.d.ts +1 -1
  107. package/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.d.ts +10 -0
  108. package/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.d.ts.map +1 -0
  109. package/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.d.ts +8 -0
  110. package/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.d.ts.map +1 -0
  111. package/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.d.ts +1 -0
  112. package/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.d.ts.map +1 -1
  113. package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts +1 -0
  114. package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts.map +1 -1
  115. package/libs/ui/elements/src/lib/thumbnail/thumbnail.component.d.ts +3 -2
  116. package/libs/ui/elements/src/lib/thumbnail/thumbnail.component.d.ts.map +1 -1
  117. package/libs/ui/elements/src/lib/ui-elements.module.d.ts +13 -11
  118. package/libs/ui/elements/src/lib/ui-elements.module.d.ts.map +1 -1
  119. package/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.d.ts.map +1 -1
  120. package/libs/ui/inputs/src/lib/editable-label/editable-label.directive.d.ts +13 -0
  121. package/libs/ui/inputs/src/lib/editable-label/editable-label.directive.d.ts.map +1 -0
  122. package/libs/ui/inputs/src/lib/ui-inputs.module.d.ts +2 -1
  123. package/libs/ui/inputs/src/lib/ui-inputs.module.d.ts.map +1 -1
  124. package/libs/util/i18n/src/index.d.ts +1 -0
  125. package/libs/util/i18n/src/index.d.ts.map +1 -1
  126. package/libs/util/shared/src/lib/links/link-utils.d.ts +19 -7
  127. package/libs/util/shared/src/lib/links/link-utils.d.ts.map +1 -1
  128. package/libs/util/shared/src/lib/utils/fuzzy-filter.d.ts +9 -0
  129. package/libs/util/shared/src/lib/utils/fuzzy-filter.d.ts.map +1 -0
  130. package/libs/util/shared/src/lib/utils/index.d.ts +1 -0
  131. package/libs/util/shared/src/lib/utils/index.d.ts.map +1 -1
  132. package/package.json +4 -1
  133. package/src/libs/api/metadata-converter/src/lib/gn4/atomic-operations.ts +3 -0
  134. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +43 -0
  135. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.ts +1 -0
  136. package/src/libs/api/repository/src/lib/gn4/index.ts +2 -0
  137. package/src/libs/common/domain/src/lib/index.ts +2 -0
  138. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +12 -7
  139. package/src/libs/feature/catalog/src/lib/organisations/organisations.component.ts +3 -17
  140. package/src/libs/feature/dataviz/src/lib/service/data.service.ts +8 -5
  141. package/src/libs/feature/editor/src/lib/record-form/record-form.component.ts +2 -1
  142. package/src/libs/feature/map/src/index.ts +1 -0
  143. package/src/libs/feature/map/src/lib/add-layer-from-file/add-layer-from-file.component.css +0 -0
  144. package/src/libs/feature/map/src/lib/add-layer-from-file/add-layer-from-file.component.html +21 -0
  145. package/src/libs/feature/map/src/lib/add-layer-from-file/add-layer-from-file.component.ts +107 -0
  146. package/src/libs/feature/map/src/lib/add-layer-from-wfs/add-layer-from-wfs.component.css +0 -0
  147. package/src/libs/feature/map/src/lib/add-layer-from-wfs/add-layer-from-wfs.component.html +37 -0
  148. package/src/libs/feature/map/src/lib/add-layer-from-wfs/add-layer-from-wfs.component.ts +64 -0
  149. package/src/libs/feature/map/src/lib/add-layer-from-wms/add-layer-from-wms.component.css +0 -0
  150. package/src/libs/feature/map/src/lib/add-layer-from-wms/add-layer-from-wms.component.html +55 -0
  151. package/src/libs/feature/map/src/lib/add-layer-from-wms/add-layer-from-wms.component.ts +63 -0
  152. package/src/libs/feature/map/src/lib/constant/index.ts +1 -0
  153. package/src/libs/feature/map/src/lib/feature-map.module.ts +14 -0
  154. package/src/libs/feature/map/src/lib/geocoding/geocoding.component.css +0 -0
  155. package/src/libs/feature/map/src/lib/geocoding/geocoding.component.html +39 -0
  156. package/src/libs/feature/map/src/lib/geocoding/geocoding.component.ts +99 -0
  157. package/src/libs/feature/map/src/lib/geocoding.service.ts +59 -0
  158. package/src/libs/feature/map/src/lib/layers-panel/layers-panel.component.html +9 -3
  159. package/src/libs/feature/map/src/lib/map-context/map-context.service.ts +6 -0
  160. package/src/libs/feature/map/src/lib/utils/index.ts +0 -2
  161. package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +85 -50
  162. package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +18 -3
  163. package/src/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.html +12 -4
  164. package/src/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.ts +1 -0
  165. package/src/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.html +1 -0
  166. package/src/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.ts +1 -1
  167. package/src/libs/ui/elements/src/index.ts +3 -0
  168. package/src/libs/ui/elements/src/lib/downloads-list/downloads-list.component.html +4 -1
  169. package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.css +0 -0
  170. package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.html +30 -0
  171. package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.ts +15 -0
  172. package/src/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.css +264 -0
  173. package/src/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.html +1 -0
  174. package/src/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.ts +16 -0
  175. package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.html +93 -27
  176. package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.ts +7 -0
  177. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.css +4 -0
  178. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +59 -32
  179. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.ts +5 -0
  180. package/src/libs/ui/elements/src/lib/related-record-card/related-record-card.component.html +1 -1
  181. package/src/libs/ui/elements/src/lib/thumbnail/thumbnail.component.ts +4 -0
  182. package/src/libs/ui/elements/src/lib/ui-elements.module.ts +7 -0
  183. package/src/libs/ui/inputs/src/lib/button/button.component.css +1 -1
  184. package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.ts +7 -4
  185. package/src/libs/ui/inputs/src/lib/editable-label/editable-label.directive.ts +48 -0
  186. package/src/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.html +8 -3
  187. package/src/libs/ui/inputs/src/lib/star-toggle/star-toggle.component.css +1 -0
  188. package/src/libs/ui/inputs/src/lib/ui-inputs.module.ts +3 -0
  189. package/src/libs/ui/layout/src/lib/carousel/carousel.component.css +1 -1
  190. package/src/libs/ui/search/src/lib/record-table/record-table.component.html +2 -2
  191. package/src/libs/util/i18n/src/index.ts +1 -0
  192. package/src/libs/util/shared/src/lib/links/link-utils.ts +34 -11
  193. package/src/libs/util/shared/src/lib/utils/fuzzy-filter.ts +32 -0
  194. package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
  195. package/translations/de.json +102 -87
  196. package/translations/en.json +35 -20
  197. package/translations/es.json +15 -0
  198. package/translations/fr.json +19 -4
  199. package/translations/it.json +27 -12
  200. package/translations/nl.json +15 -0
  201. package/translations/pt.json +15 -0
  202. package/translations/sk.json +15 -0
  203. package/esm2022/libs/feature/map/src/lib/utils/map-utils-wms.service.mjs +0 -55
  204. package/esm2022/libs/feature/map/src/lib/utils/projections.mjs +0 -2
  205. package/libs/feature/map/src/lib/utils/map-utils-wms.service.d.ts +0 -17
  206. package/libs/feature/map/src/lib/utils/map-utils-wms.service.d.ts.map +0 -1
  207. package/libs/feature/map/src/lib/utils/projections.d.ts.map +0 -1
  208. package/src/libs/feature/map/src/lib/utils/map-utils-wms.service.ts +0 -58
  209. /package/libs/feature/map/src/lib/{utils → constant}/projections.d.ts +0 -0
  210. /package/src/libs/feature/map/src/lib/{utils → constant}/projections.ts +0 -0
@@ -1,32 +1,98 @@
1
- <div *ngIf="shownOrganization" class="mb-6 sm:mb-12">
2
- <p class="text-gray-700 text-xs mb-3 uppercase" translate>
3
- record.metadata.contact
4
- </p>
5
- <div class="flex mb-1">
1
+ <div class="py-5 px-5 rounded bg-gray-100 text-black mb-6">
2
+ <div class="grid gap-3">
3
+ <div>
4
+ <p class="text-sm font-medium" translate>record.metadata.contact</p>
5
+ </div>
6
6
  <div
7
- class="text-primary font-title text-21 mr-2 cursor-pointer hover:underline"
8
- (click)="onOrganizationClick()"
7
+ *ngIf="shownOrganization?.logoUrl?.href"
8
+ class="flex items-center justify-center border-solid border border-gray-300 rounded-md bg-white h-32 overflow-hidden"
9
9
  >
10
- {{ shownOrganization.name }}
10
+ <gn-ui-thumbnail
11
+ class="relative h-full w-full"
12
+ [thumbnailUrl]="shownOrganization.logoUrl.href"
13
+ fit="contain"
14
+ ></gn-ui-thumbnail>
15
+ </div>
16
+ <div class="grid gap-1">
17
+ <div class="flex">
18
+ <div
19
+ class="text-primary font-title text-21 mr-2 cursor-pointer hover:underline"
20
+ (click)="onOrganizationClick()"
21
+ data-cy="organization-name"
22
+ >
23
+ {{ shownOrganization?.name }}
24
+ </div>
25
+ </div>
26
+ <div *ngIf="shownOrganization?.website">
27
+ <a
28
+ [href]="shownOrganization.website"
29
+ target="_blank"
30
+ class="contact-website text-primary text-sm cursor-pointer hover:underline transition-all"
31
+ >{{ shownOrganization.website }}
32
+ <mat-icon
33
+ class="material-symbols-outlined !w-[12px] !h-[12px] !text-[12px] opacity-75 shrink-0"
34
+ >open_in_new</mat-icon
35
+ >
36
+ </a>
37
+ </div>
38
+ </div>
39
+ <div class="grid gap-5 py-3 overflow-hidden">
40
+ <div *ngIf="contacts[0]?.phone">
41
+ <div class="flex">
42
+ <mat-icon
43
+ class="material-symbols-outlined !w-5 !h-5 !text-[20px] opacity-75 shrink-0"
44
+ >call_outline</mat-icon
45
+ >
46
+ <div class="flex flex-col ml-2">
47
+ <p class="text-sm">{{ contacts[0].phone }}</p>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ <div *ngIf="contacts[0]?.email">
52
+ <div class="flex">
53
+ <mat-icon
54
+ class="material-symbols-outlined !w-5 !h-5 !text-[20px] opacity-75 shrink-0"
55
+ >
56
+ mail_outline</mat-icon
57
+ >
58
+ <a
59
+ *ngIf="contacts.length"
60
+ [href]="'mailto:' + contacts[0].email"
61
+ class="text-sm hover:underline ml-2"
62
+ target="_blank"
63
+ data-cy="contact-email"
64
+ >{{ contacts[0].email }}</a
65
+ >
66
+ </div>
67
+ </div>
68
+ <div *ngIf="contacts[0]?.firstName || contacts[0]?.lastName">
69
+ <div class="flex">
70
+ <mat-icon
71
+ class="material-symbols-outlined !w-5 !h-5 !text-[20px] opacity-75 shrink-0"
72
+ >person_outline</mat-icon
73
+ >
74
+ <div class="flex flex-col ml-2">
75
+ <p class="text-sm">
76
+ {{ contacts[0]?.firstName || '' }}
77
+ {{ contacts[0]?.lastName || '' }}
78
+ </p>
79
+ </div>
80
+ </div>
81
+ </div>
82
+ <div *ngIf="contacts[0]?.address">
83
+ <div class="flex">
84
+ <mat-icon
85
+ class="material-symbols-outlined !w-5 !h-5 !text-[20px] opacity-75 shrink-0"
86
+ >
87
+ location_on</mat-icon
88
+ >
89
+ <div class="flex flex-col ml-2">
90
+ <p *ngFor="let addressPart of address" class="text-sm">
91
+ {{ addressPart }}
92
+ </p>
93
+ </div>
94
+ </div>
95
+ </div>
11
96
  </div>
12
- </div>
13
- <a
14
- *ngIf="contacts.length"
15
- [href]="'mailto:' + contacts[0].email"
16
- class="text-gray-700 text-sm hover:underline"
17
- target="_blank"
18
- >{{ contacts[0].email }}</a
19
- >
20
- <div *ngIf="shownOrganization.website" class="mb-2">
21
- <a
22
- [href]="shownOrganization.website"
23
- target="_blank"
24
- class="contact-website text-primary text-sm cursor-pointer hover:underline transition-all"
25
- >{{ shownOrganization.website }}
26
- <mat-icon
27
- class="material-symbols-outlined !w-[12px] !h-[12px] !text-[12px] opacity-75"
28
- >open_in_new</mat-icon
29
- >
30
- </a>
31
97
  </div>
32
98
  </div>
@@ -34,6 +34,13 @@ export class MetadataContactComponent {
34
34
  )
35
35
  }
36
36
 
37
+ get address() {
38
+ const addressParts = this.contacts[0].address
39
+ .split(',')
40
+ .map((part) => part.trim())
41
+ return addressParts
42
+ }
43
+
37
44
  onOrganizationClick() {
38
45
  this.organizationClick.emit(this.shownOrganization)
39
46
  }
@@ -7,3 +7,7 @@
7
7
  padding-bottom: 10px;
8
8
  @apply border-b border-gray-300;
9
9
  }
10
+
11
+ :host ::ng-deep gn-ui-copy-text-button button mat-icon {
12
+ transform: scale(0.8);
13
+ }
@@ -1,32 +1,10 @@
1
- <p
2
- class="text-[28px] text-title text-center mb-6 font-title sm:text-left"
3
- translate
4
- >
5
- record.metadata.about
6
- </p>
7
1
  <div class="mb-6 md-description sm:mb-4 sm:pr-16">
8
2
  <gn-ui-content-ghost ghostClass="h-32" [showContent]="fieldReady('abstract')">
9
3
  <gn-ui-max-lines [maxLines]="6" *ngIf="metadata.abstract">
10
4
  <div>
11
- <p
12
- class="whitespace-pre-line break-words sm:mb-4 sm:pr-16"
13
- [innerHTML]="metadata.abstract"
14
- gnUiLinkify
15
- ></p>
16
- <ng-container *ngIf="metadata.keywords?.length">
17
- <p class="mb-3 font-medium text-primary text-sm" translate>
18
- record.metadata.keywords
19
- </p>
20
- <div class="sm:pb-4 sm:pr-16">
21
- <gn-ui-badge
22
- class="inline-block mr-2 mb-2 lowercase"
23
- (click)="onKeywordClick(keyword)"
24
- [clickable]="true"
25
- *ngFor="let keyword of metadata.keywords"
26
- >{{ keyword }}</gn-ui-badge
27
- >
28
- </div>
29
- </ng-container>
5
+ <gn-ui-markdown-parser
6
+ [textContent]="metadata.abstract"
7
+ ></gn-ui-markdown-parser>
30
8
  </div>
31
9
  </gn-ui-max-lines>
32
10
  </gn-ui-content-ghost>
@@ -97,12 +75,61 @@
97
75
  *ngIf="metadata.landingPage"
98
76
  [title]="'record.metadata.details' | translate"
99
77
  >
100
- <div class="py-5 px-5 rounded bg-gray-100 text-gray-700">
101
- <p class="text-sm" translate>record.metadata.sheet</p>
102
- <p class="text-primary font-medium mt-1" translate>
103
- <a [href]="metadata.landingPage" target="_blank">
104
- <span class="break-all" gnUiLinkify>{{ metadata.landingPage }}</span>
105
- </a>
106
- </p>
78
+ <div class="flex flex-col gap-4 mr-4 py-5 rounded text-gray-700">
79
+ <div *ngIf="metadata.recordUpdated">
80
+ <p class="text-sm" translate>record.metadata.updatedOn</p>
81
+ <p class="text-primary font-medium">
82
+ {{ metadata.recordUpdated && metadata.recordUpdated.toLocaleString() }}
83
+ </p>
84
+ </div>
85
+ <div *ngIf="metadata.landingPage">
86
+ <p class="text-sm" translate>record.metadata.sheet</p>
87
+ <p class="text-primary font-medium" translate>
88
+ <a [href]="metadata.landingPage" target="_blank">
89
+ <span class="break-all" gnUiLinkify>{{ metadata.landingPage }}</span>
90
+ </a>
91
+ </p>
92
+ </div>
93
+ <div *ngIf="metadata.ownerOrganization">
94
+ <p class="text-sm" translate>record.metadata.owner</p>
95
+ <p class="text-primary font-medium">
96
+ {{ metadata.ownerOrganization.name }}
97
+ </p>
98
+ </div>
99
+ <div *ngIf="metadata.uniqueIdentifier">
100
+ <p class="text-sm" translate>record.metadata.uniqueId</p>
101
+ <div class="flex flex-row content-align items-end gap-1">
102
+ <gn-ui-copy-text-button
103
+ [text]="metadata.uniqueIdentifier"
104
+ [tooltipText]="'tooltip.id.copy' | translate"
105
+ [displayText]="false"
106
+ ></gn-ui-copy-text-button>
107
+ <p class="text-primary font-medium">
108
+ {{ metadata.uniqueIdentifier }}
109
+ </p>
110
+ </div>
111
+ </div>
112
+ <div *ngIf="metadata.themes?.length">
113
+ <p class="text-sm mb-1" translate>record.metadata.themes</p>
114
+ <div class="sm:pb-4 sm:pr-16">
115
+ <gn-ui-badge
116
+ class="inline-block mr-2 lowercase"
117
+ *ngFor="let theme of metadata.themes"
118
+ >{{ theme }}</gn-ui-badge
119
+ >
120
+ </div>
121
+ </div>
122
+ <div *ngIf="metadata.keywords?.length">
123
+ <p class="text-sm mb-1" translate>record.metadata.keywords</p>
124
+ <div class="sm:pb-4 sm:pr-16">
125
+ <gn-ui-badge
126
+ class="inline-block mr-2 mb-2 lowercase"
127
+ (click)="onKeywordClick(keyword)"
128
+ [clickable]="true"
129
+ *ngFor="let keyword of metadata.keywords"
130
+ >{{ keyword }}</gn-ui-badge
131
+ >
132
+ </div>
133
+ </div>
107
134
  </div>
108
135
  </gn-ui-expandable-panel>
@@ -56,4 +56,9 @@ export class MetadataInfoComponent {
56
56
  onKeywordClick(keyword: string) {
57
57
  this.keyword.emit(keyword)
58
58
  }
59
+
60
+ copyText() {
61
+ navigator.clipboard.writeText(this.metadata.uniqueIdentifier)
62
+ ;(event.target as HTMLElement).blur()
63
+ }
59
64
  }
@@ -6,7 +6,7 @@
6
6
  <div class="h-52 bg-gray-100">
7
7
  <gn-ui-thumbnail
8
8
  class="h-52 w-full object-cover"
9
- [thumbnailUrl]="record.overviews?.[0].url.toString()"
9
+ [thumbnailUrl]="record.overviews?.[0]?.url.toString()"
10
10
  ></gn-ui-thumbnail>
11
11
  </div>
12
12
  <div class="flex flex-col justify-between h-44 px-5 pt-4 pb-6">
@@ -10,6 +10,8 @@ import {
10
10
  Optional,
11
11
  SimpleChanges,
12
12
  ViewChild,
13
+ Output,
14
+ EventEmitter,
13
15
  } from '@angular/core'
14
16
 
15
17
  export const THUMBNAIL_PLACEHOLDER = new InjectionToken<string>(
@@ -36,6 +38,7 @@ export class ThumbnailComponent implements OnInit, OnChanges {
36
38
  @Input() fit: FitOptions | FitOptions[] = 'cover'
37
39
  @ViewChild('imageElement') imgElement: ElementRef<HTMLImageElement>
38
40
  @ViewChild('containerElement') containerElement: ElementRef<HTMLDivElement>
41
+ @Output() placeholderShown = new EventEmitter<boolean>()
39
42
  imgUrl: string
40
43
  imgFit: FitOptions
41
44
  placeholderUrl = this.optionalPlaceholderUrl || DEFAULT_PLACEHOLDER
@@ -85,6 +88,7 @@ export class ThumbnailComponent implements OnInit, OnChanges {
85
88
  private setNewSrcImage(image: ThumbnailImageObject) {
86
89
  this.imgFit = image.fit
87
90
  this.imgUrl = image.url
91
+ this.placeholderShown.emit(this.isPlaceholder)
88
92
  }
89
93
 
90
94
  private setPlaceholder(): void {
@@ -29,6 +29,8 @@ import { GnUiLinkifyDirective } from './metadata-info/linkify.directive'
29
29
  import { PaginationButtonsComponent } from './pagination-buttons/pagination-buttons.component'
30
30
  import { MaxLinesComponent } from './max-lines/max-lines.component'
31
31
  import { RecordApiFormComponent } from './record-api-form/record-api-form.component'
32
+ import { MarkdownParserComponent } from './markdown-parser/markdown-parser.component'
33
+ import { ImageOverlayPreviewComponent } from './image-overlay-preview/image-overlay-preview.component'
32
34
 
33
35
  @NgModule({
34
36
  imports: [
@@ -65,6 +67,8 @@ import { RecordApiFormComponent } from './record-api-form/record-api-form.compon
65
67
  PaginationButtonsComponent,
66
68
  MaxLinesComponent,
67
69
  RecordApiFormComponent,
70
+ MarkdownParserComponent,
71
+ ImageOverlayPreviewComponent,
68
72
  ],
69
73
  exports: [
70
74
  MetadataInfoComponent,
@@ -84,7 +88,10 @@ import { RecordApiFormComponent } from './record-api-form/record-api-form.compon
84
88
  AvatarComponent,
85
89
  UserPreviewComponent,
86
90
  PaginationButtonsComponent,
91
+ MaxLinesComponent,
87
92
  RecordApiFormComponent,
93
+ MarkdownParserComponent,
94
+ ImageOverlayPreviewComponent,
88
95
  ],
89
96
  })
90
97
  export class UiElementsModule {}
@@ -1,5 +1,5 @@
1
1
  /* makes sure icons will not make the buttons grow vertically */
2
- :host /deep/ mat-icon.mat-icon {
2
+ :host ::ng-deep mat-icon.mat-icon {
3
3
  margin-top: -0.325em;
4
4
  margin-bottom: -0.325em;
5
5
  }
@@ -17,7 +17,10 @@ import {
17
17
  } from '@angular/cdk/overlay'
18
18
  import { take } from 'rxjs/operators'
19
19
  import { Choice } from './dropdown-multiselect.model'
20
- import { propagateToDocumentOnly } from '../../../../../../libs/util/shared/src'
20
+ import {
21
+ createFuzzyFilter,
22
+ propagateToDocumentOnly,
23
+ } from '../../../../../../libs/util/shared/src'
21
24
 
22
25
  @Component({
23
26
  selector: 'gn-ui-dropdown-multiselect',
@@ -74,9 +77,9 @@ export class DropdownMultiselectComponent {
74
77
  }
75
78
 
76
79
  get filteredChoicesByText() {
77
- return this.choices.filter((choice) =>
78
- choice.label.toLowerCase().includes(this.searchInputValue?.toLowerCase())
79
- )
80
+ if (!this.searchInputValue) return this.choices
81
+ const filter = createFuzzyFilter(this.searchInputValue)
82
+ return this.choices.filter((choice) => filter(choice.label))
80
83
  }
81
84
 
82
85
  get focusedIndex(): number | -1 {
@@ -0,0 +1,48 @@
1
+ import {
2
+ Directive,
3
+ ElementRef,
4
+ Renderer2,
5
+ AfterViewInit,
6
+ EventEmitter,
7
+ Output,
8
+ Input,
9
+ } from '@angular/core'
10
+
11
+ @Directive({
12
+ selector: '[gnUiEditableLabel]',
13
+ standalone: true,
14
+ })
15
+ export class EditableLabelDirective implements AfterViewInit {
16
+ @Output() editableLabelChanged = new EventEmitter<string>()
17
+ @Input() gnUiEditableLabel?: boolean
18
+
19
+ constructor(private el: ElementRef, private renderer: Renderer2) {}
20
+
21
+ ngAfterViewInit() {
22
+ if (this.gnUiEditableLabel !== false) {
23
+ const appendedInput = this.renderer.createElement('input')
24
+
25
+ this.renderer.setStyle(appendedInput, 'background', 'inherit')
26
+ this.renderer.setStyle(appendedInput, 'color', 'inherit')
27
+ this.renderer.setStyle(appendedInput, 'font', 'inherit')
28
+ this.renderer.setStyle(appendedInput, 'border', 'inherit')
29
+ this.renderer.setStyle(appendedInput, 'width', '100%')
30
+ this.renderer.setStyle(appendedInput, 'padding', 'inherit')
31
+ this.renderer.setStyle(appendedInput, 'margin', '0')
32
+ this.renderer.setStyle(appendedInput, 'height', 'inherit')
33
+ this.renderer.setStyle(appendedInput, 'line-height', 'inherit')
34
+ this.renderer.setStyle(appendedInput, 'text-decoration', 'inherit')
35
+
36
+ const hostContent = this.el.nativeElement.textContent || ''
37
+ const formattedContent = hostContent.replace(/\s+/g, ' ').trim()
38
+ this.renderer.setProperty(appendedInput, 'value', formattedContent)
39
+ this.renderer.setProperty(this.el.nativeElement, 'innerHTML', '')
40
+
41
+ this.renderer.listen(appendedInput, 'input', (event) => {
42
+ this.editableLabelChanged.emit(event.target.value)
43
+ })
44
+
45
+ this.renderer.appendChild(this.el.nativeElement, appendedInput)
46
+ }
47
+ }
48
+ }
@@ -1,6 +1,11 @@
1
1
  <button
2
- class="group flex items-center justify-center backdrop-blur p-1 bg-primary-opacity-50 text-white rounded"
2
+ class="group flex items-center justify-center gap-1 backdrop-blur p-1 bg-primary-opacity-30 text-white rounded content-center"
3
3
  >
4
- <mat-icon class="material-symbols-outlined align-middle">{{ icon }}</mat-icon>
5
- <span class="mx-2 hidden group-hover:inline">{{ label }}</span>
4
+ <mat-icon class="material-symbols-outlined align-middle w-[18px]">{{
5
+ icon
6
+ }}</mat-icon>
7
+ <span
8
+ class="mx-2 mt-0.5 text-[16px] tracking-widest content-center opacity-75"
9
+ >{{ label.toUpperCase() }}</span
10
+ >
6
11
  </button>
@@ -11,6 +11,7 @@ mat-icon {
11
11
  font-size: 1.5em;
12
12
  margin-top: -0.1em;
13
13
  font-variation-settings: 'opsz' 40;
14
+ stroke: var(--color-primary-darker);
14
15
  }
15
16
 
16
17
  .star-filled {
@@ -41,6 +41,7 @@ import { MatFormFieldModule } from '@angular/material/form-field'
41
41
  import { MatInputModule } from '@angular/material/input'
42
42
  import { MatDatepickerModule } from '@angular/material/datepicker'
43
43
  import { MatNativeDateModule } from '@angular/material/core'
44
+ import { EditableLabelDirective } from './editable-label/editable-label.directive'
44
45
 
45
46
  @NgModule({
46
47
  declarations: [
@@ -87,6 +88,7 @@ import { MatNativeDateModule } from '@angular/material/core'
87
88
  MatInputModule,
88
89
  MatDatepickerModule,
89
90
  MatNativeDateModule,
91
+ EditableLabelDirective,
90
92
  ],
91
93
  exports: [
92
94
  DropdownSelectorComponent,
@@ -106,6 +108,7 @@ import { MatNativeDateModule } from '@angular/material/core'
106
108
  CheckboxComponent,
107
109
  SearchInputComponent,
108
110
  DateRangePickerComponent,
111
+ EditableLabelDirective,
109
112
  ],
110
113
  })
111
114
  export class UiInputsModule {}
@@ -1,4 +1,4 @@
1
- :host .carousel-container /deep/ > * {
1
+ :host .carousel-container ::ng-deep > * {
2
2
  flex-shrink: 0;
3
3
  }
4
4
  :host {
@@ -38,7 +38,7 @@
38
38
  </div>
39
39
  <div
40
40
  class="contents hover:text-gray-900 text-gray-800 cursor-pointer"
41
- (click)="recordSelect.emit(record)"
41
+ (click)="recordsSelect.emit([record])"
42
42
  *ngFor="let record of records"
43
43
  >
44
44
  <div class="record-table-col text-16">
@@ -157,7 +157,7 @@
157
157
  </div>
158
158
  <div
159
159
  class="contents hover:text-gray-900 text-gray-800 cursor-pointer"
160
- (click)="recordSelect.emit(record)"
160
+ (click)="recordsSelect.emit([record])"
161
161
  *ngFor="let record of records"
162
162
  >
163
163
  <div class="record-table-col">
@@ -5,3 +5,4 @@ export * from './lib/lang.service'
5
5
  export * from './lib/file.translate.loader'
6
6
  export * from './lib/testing/test.translate.module'
7
7
  export * from './lib/embedded.translate.loader'
8
+ export * from './lib/translate.loader.utils'
@@ -43,9 +43,15 @@ export const FORMATS = {
43
43
  color: '#328556',
44
44
  mimeTypes: ['x-gis/x-shapefile'],
45
45
  },
46
+ gml: {
47
+ extensions: ['gml'],
48
+ priority: 5,
49
+ color: '#c92bce',
50
+ mimeTypes: ['application/gml+xml', 'text/xml; subtype=gml'],
51
+ },
46
52
  kml: {
47
53
  extensions: ['kml', 'kmz'],
48
- priority: 5,
54
+ priority: 6,
49
55
  color: '#348009',
50
56
  mimeTypes: [
51
57
  'application/vnd.google-earth.kml+xml',
@@ -54,34 +60,40 @@ export const FORMATS = {
54
60
  },
55
61
  gpkg: {
56
62
  extensions: ['gpkg', 'geopackage'],
57
- priority: 6,
63
+ priority: 7,
58
64
  color: '#ea79ba',
59
65
  mimeTypes: ['application/geopackage+sqlite3'],
60
66
  },
61
67
  zip: {
62
68
  extensions: ['zip', 'tar.gz'],
63
- priority: 7,
69
+ priority: 8,
64
70
  color: '#f2bb3a',
65
71
  mimeTypes: ['application/zip', 'application/x-zip'],
66
72
  },
67
73
  pdf: {
68
74
  extensions: ['pdf'],
69
- priority: 8,
75
+ priority: 9,
70
76
  color: '#db544a',
71
77
  mimeTypes: ['application/pdf'],
72
78
  },
73
79
  jpg: {
74
80
  extensions: ['jpg', 'jpeg', 'jfif', 'pjpeg', 'pjp'],
75
- priority: 8,
81
+ priority: 9,
76
82
  color: '#673ab7',
77
83
  mimeTypes: ['image/jpg'],
78
84
  },
79
85
  svg: {
80
86
  extensions: ['svg'],
81
- priority: 9,
87
+ priority: 10,
82
88
  color: '#d98294',
83
89
  mimeTypes: ['image/svg+xml'],
84
90
  },
91
+ dxf: {
92
+ extensions: ['dxf'],
93
+ priority: 11,
94
+ color: '#de630b',
95
+ mimeTypes: ['application/x-dxf', 'image/x-dxf'],
96
+ },
85
97
  } as const
86
98
 
87
99
  export type FileFormat = keyof typeof FORMATS
@@ -102,13 +114,24 @@ export function getLinkPriority(link: DatasetDistribution): number {
102
114
  return getFormatPriority(getFileFormat(link))
103
115
  }
104
116
 
105
- export function extensionToFormat(extension: string): FileFormat {
106
- for (const format in FORMATS) {
107
- for (const alias of FORMATS[format].extensions) {
108
- if (alias === extension.toLowerCase()) return format as FileFormat
117
+ export function getFileFormatFromServiceOutput(
118
+ serviceOutput: string
119
+ ): FileFormat | null {
120
+ function formatMatcher(format: typeof FORMATS[FileFormat]): boolean {
121
+ const output = serviceOutput.toLowerCase()
122
+ return (
123
+ format.extensions.some((extension: string) =>
124
+ output.includes(extension)
125
+ ) ||
126
+ format.mimeTypes.some((mimeType: string) => output.includes(mimeType))
127
+ )
128
+ }
129
+ for (const formatName in FORMATS) {
130
+ if (formatMatcher(FORMATS[formatName])) {
131
+ return formatName as FileFormat
109
132
  }
110
133
  }
111
- return undefined
134
+ return null
112
135
  }
113
136
 
114
137
  export function getFileFormat(link: DatasetDistribution): FileFormat {
@@ -0,0 +1,32 @@
1
+ type FuzzyFilter = (input: string) => boolean
2
+
3
+ function normalize(input: string) {
4
+ return input
5
+ .toLowerCase()
6
+ .normalize('NFD') // explode composite chars (e.g. é) into multiple chars
7
+ .replace(/[\u0300-\u036f]/g, '') // remove accents
8
+ .replace(/œ/g, 'oe') // remove accents
9
+ .replace(/[^a-z0-9\s]/g, ' ') // replace special characters with space
10
+ }
11
+
12
+ function asNormalizedParts(input: string): string[] {
13
+ return normalize(input)
14
+ .split(/\s+/)
15
+ .map((part) => part.trim())
16
+ .filter((part) => part.length > 0)
17
+ }
18
+
19
+ /**
20
+ * This creates a filter function based on a pattern (typically a user-input
21
+ * search text).
22
+ * @param pattern
23
+ */
24
+ export function createFuzzyFilter(pattern: string): FuzzyFilter {
25
+ const patternParts = asNormalizedParts(pattern)
26
+ return (input: string) => {
27
+ const inputParts = asNormalizedParts(input)
28
+ return patternParts.every((patternPart) =>
29
+ inputParts.some((part) => part.includes(patternPart))
30
+ )
31
+ }
32
+ }
@@ -5,3 +5,4 @@ export * from './geojson'
5
5
  export * from './sort-by'
6
6
  export * from './url'
7
7
  export * from './event'
8
+ export * from './fuzzy-filter'