@kalisio/kdk 2.3.2 → 2.4.1

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 (449) hide show
  1. package/.eslintignore +2 -1
  2. package/.github/workflows/main.yaml +3 -3
  3. package/README.md +1 -0
  4. package/core/api/db.js +6 -1
  5. package/core/api/hooks/hooks.model.js +1 -1
  6. package/core/api/hooks/hooks.schemas.js +0 -2
  7. package/core/api/models/messages.model.mongodb.js +13 -0
  8. package/core/api/services/authorisations/authorisations.service.js +13 -4
  9. package/core/api/services/index.js +19 -0
  10. package/core/api/services/messages/messages.hooks.js +38 -0
  11. package/core/client/api.js +7 -32
  12. package/core/client/capabilities.js +2 -2
  13. package/core/client/components/KActivity.vue +29 -6
  14. package/core/client/components/KContent.vue +2 -2
  15. package/core/client/components/KDialog.vue +4 -7
  16. package/core/client/components/KStamp.vue +3 -9
  17. package/core/client/components/KStore.vue +2 -4
  18. package/core/client/components/KTab.vue +95 -0
  19. package/core/client/components/action/KAction.vue +15 -2
  20. package/core/client/components/action/KBugReportAction.vue +4 -2
  21. package/core/client/components/action/KToggleFullscreenAction.vue +25 -0
  22. package/core/client/components/app/KSettings.vue +17 -13
  23. package/core/client/components/chart/KDataTable.vue +6 -9
  24. package/core/client/components/chart/KTimeSeriesChart.vue +62 -49
  25. package/core/client/components/collection/KBoard.vue +22 -33
  26. package/core/client/components/collection/KCard.vue +71 -56
  27. package/core/client/components/collection/KCardSection.vue +20 -10
  28. package/core/client/components/collection/KDescriptionCardSection.vue +47 -0
  29. package/core/client/components/collection/KGrid.vue +234 -54
  30. package/core/client/components/collection/KScrollDown.vue +97 -0
  31. package/core/client/components/collection/KScrollToTop.vue +93 -0
  32. package/core/client/components/collection/KTable.vue +87 -33
  33. package/core/client/components/collection/KTimeLine.vue +406 -0
  34. package/core/client/components/collection/index.js +1 -5
  35. package/core/client/components/document/KDocument.vue +20 -55
  36. package/core/client/components/document/KHtml.vue +17 -7
  37. package/core/client/components/document/KImage.vue +78 -0
  38. package/core/client/components/document/KMarkdown.vue +12 -16
  39. package/core/client/components/document/KPdf.vue +69 -0
  40. package/core/client/components/form/KFileField.vue +2 -2
  41. package/core/client/components/form/KSelectField.vue +2 -1
  42. package/core/client/components/form/KUnitField.vue +3 -1
  43. package/core/client/components/layout/KFab.vue +9 -10
  44. package/core/client/components/layout/KLayout.vue +104 -6
  45. package/core/client/components/layout/KOpener.vue +14 -19
  46. package/core/client/components/layout/KPage.vue +195 -105
  47. package/core/client/components/layout/KWindow.vue +54 -32
  48. package/core/client/components/layout/index.js +0 -2
  49. package/core/client/components/media/KRibbon.vue +95 -0
  50. package/core/client/components/menu/KMenu.vue +4 -4
  51. package/core/client/components/team/KGroupsActivity.vue +25 -27
  52. package/core/client/components/team/KMembersActivity.vue +21 -23
  53. package/core/client/components/team/KOrganisationsActivity.vue +20 -22
  54. package/core/client/components/team/KTagsActivity.vue +21 -23
  55. package/core/client/components/time/KAbsoluteTimeRange.vue +70 -170
  56. package/core/client/components/time/KDate.vue +4 -1
  57. package/core/client/components/time/KDateTimeRange.vue +2 -2
  58. package/core/client/components/time/KTime.vue +3 -1
  59. package/core/client/composables/activity.js +14 -12
  60. package/core/client/composables/collection.js +3 -1
  61. package/core/client/composables/counter.js +51 -0
  62. package/core/client/composables/index.js +3 -0
  63. package/core/client/composables/layout.js +13 -2
  64. package/core/client/composables/messages.js +15 -0
  65. package/core/client/composables/pwa.js +1 -1
  66. package/core/client/composables/schema.js +6 -6
  67. package/core/client/composables/screen.js +23 -0
  68. package/core/client/directives/index.js +1 -0
  69. package/core/client/directives/v-hover.js +23 -0
  70. package/core/client/document.js +61 -0
  71. package/core/client/exporter.js +1 -1
  72. package/core/client/filter.js +0 -1
  73. package/core/client/guards.js +1 -1
  74. package/core/client/i18n/core_en.json +14 -8
  75. package/core/client/i18n/core_fr.json +15 -9
  76. package/core/client/index.js +9 -3
  77. package/core/client/layout.js +129 -29
  78. package/core/client/local-storage.js +1 -1
  79. package/core/client/mixins/index.js +0 -1
  80. package/core/client/mixins/mixin.base-activity.js +23 -13
  81. package/core/client/mixins/mixin.base-item.js +6 -3
  82. package/core/client/services/index.js +4 -1
  83. package/core/client/services/local-settings.service.js +4 -0
  84. package/core/client/storage.js +1 -1
  85. package/core/client/store.js +1 -1
  86. package/core/client/template-context.js +17 -0
  87. package/core/client/time.js +1 -1
  88. package/core/client/units.js +49 -27
  89. package/core/client/utils/index.js +3 -2
  90. package/core/client/utils/utils.actions.js +4 -0
  91. package/core/client/utils/utils.colors.js +155 -2
  92. package/core/client/utils/utils.items.js +26 -0
  93. package/core/client/utils/utils.math.js +3 -0
  94. package/core/client/utils/utils.platform.js +3 -1
  95. package/core/client/utils/utils.screen.js +82 -0
  96. package/core/client/utils/utils.time.js +0 -1
  97. package/core/common/schemas/settings.update.json +12 -0
  98. package/coverage/base.css +224 -0
  99. package/coverage/block-navigation.js +87 -0
  100. package/coverage/core/api/application.js.html +1870 -0
  101. package/coverage/core/api/authentication.js.html +742 -0
  102. package/coverage/core/api/db.js.html +793 -0
  103. package/coverage/core/api/hooks/hooks.authentication.js.html +313 -0
  104. package/coverage/core/api/hooks/hooks.authorisations.js.html +1243 -0
  105. package/coverage/core/api/hooks/hooks.groups.js.html +229 -0
  106. package/coverage/core/api/hooks/hooks.logger.js.html +163 -0
  107. package/coverage/core/api/hooks/hooks.model.js.html +955 -0
  108. package/coverage/core/api/hooks/hooks.organisations.js.html +541 -0
  109. package/coverage/core/api/hooks/hooks.push.js.html +253 -0
  110. package/coverage/core/api/hooks/hooks.query.js.html +862 -0
  111. package/coverage/core/api/hooks/hooks.schemas.js.html +298 -0
  112. package/coverage/core/api/hooks/hooks.service.js.html +319 -0
  113. package/coverage/core/api/hooks/hooks.storage.js.html +193 -0
  114. package/coverage/core/api/hooks/hooks.users.js.html +868 -0
  115. package/coverage/core/api/hooks/index.html +296 -0
  116. package/coverage/core/api/hooks/index.js.html +121 -0
  117. package/coverage/core/api/index.html +191 -0
  118. package/coverage/core/api/index.js.html +148 -0
  119. package/coverage/core/api/marshall.js.html +448 -0
  120. package/coverage/core/api/models/groups.model.mongodb.js.html +109 -0
  121. package/coverage/core/api/models/index.html +176 -0
  122. package/coverage/core/api/models/messages.model.mongodb.js.html +121 -0
  123. package/coverage/core/api/models/organisations.model.mongodb.js.html +94 -0
  124. package/coverage/core/api/models/tags.model.mongodb.js.html +115 -0
  125. package/coverage/core/api/models/users.model.mongodb.js.html +115 -0
  126. package/coverage/core/api/services/account/account.hooks.js.html +208 -0
  127. package/coverage/core/api/services/account/account.service.js.html +436 -0
  128. package/coverage/core/api/services/account/index.html +131 -0
  129. package/coverage/core/api/services/authorisations/authorisations.hooks.js.html +184 -0
  130. package/coverage/core/api/services/authorisations/authorisations.service.js.html +529 -0
  131. package/coverage/core/api/services/authorisations/index.html +131 -0
  132. package/coverage/core/api/services/databases/databases.hooks.js.html +193 -0
  133. package/coverage/core/api/services/databases/databases.service.js.html +100 -0
  134. package/coverage/core/api/services/databases/index.html +131 -0
  135. package/coverage/core/api/services/groups/groups.hooks.js.html +178 -0
  136. package/coverage/core/api/services/groups/index.html +116 -0
  137. package/coverage/core/api/services/import-export/import-export.hooks.js.html +184 -0
  138. package/coverage/core/api/services/import-export/import-export.service.js.html +118 -0
  139. package/coverage/core/api/services/import-export/index.html +131 -0
  140. package/coverage/core/api/services/index.html +116 -0
  141. package/coverage/core/api/services/index.js.html +556 -0
  142. package/coverage/core/api/services/mailer/index.html +131 -0
  143. package/coverage/core/api/services/mailer/mailer.hooks.js.html +190 -0
  144. package/coverage/core/api/services/mailer/mailer.service.js.html +118 -0
  145. package/coverage/core/api/services/messages/index.html +116 -0
  146. package/coverage/core/api/services/messages/messages.hooks.js.html +199 -0
  147. package/coverage/core/api/services/organisations/index.html +131 -0
  148. package/coverage/core/api/services/organisations/organisations.hooks.js.html +178 -0
  149. package/coverage/core/api/services/organisations/organisations.service.js.html +343 -0
  150. package/coverage/core/api/services/push/index.html +131 -0
  151. package/coverage/core/api/services/push/push.hooks.js.html +190 -0
  152. package/coverage/core/api/services/push/push.service.js.html +121 -0
  153. package/coverage/core/api/services/storage/index.html +131 -0
  154. package/coverage/core/api/services/storage/storage.hooks.js.html +190 -0
  155. package/coverage/core/api/services/storage/storage.service.js.html +172 -0
  156. package/coverage/core/api/services/tags/index.html +116 -0
  157. package/coverage/core/api/services/tags/tags.hooks.js.html +178 -0
  158. package/coverage/core/api/services/users/index.html +116 -0
  159. package/coverage/core/api/services/users/users.hooks.js.html +307 -0
  160. package/coverage/core/api/utils.js.html +118 -0
  161. package/coverage/core/common/errors.js.html +88 -0
  162. package/coverage/core/common/index.html +176 -0
  163. package/coverage/core/common/index.js.html +115 -0
  164. package/coverage/core/common/permissions.js.html +1048 -0
  165. package/coverage/core/common/schema.js.html +190 -0
  166. package/coverage/core/common/utils.js.html +220 -0
  167. package/coverage/favicon.png +0 -0
  168. package/coverage/index.html +506 -0
  169. package/coverage/lcov-report/base.css +224 -0
  170. package/coverage/lcov-report/block-navigation.js +87 -0
  171. package/coverage/lcov-report/core/api/application.js.html +1870 -0
  172. package/coverage/lcov-report/core/api/authentication.js.html +742 -0
  173. package/coverage/lcov-report/core/api/db.js.html +793 -0
  174. package/coverage/lcov-report/core/api/hooks/hooks.authentication.js.html +313 -0
  175. package/coverage/lcov-report/core/api/hooks/hooks.authorisations.js.html +1243 -0
  176. package/coverage/lcov-report/core/api/hooks/hooks.groups.js.html +229 -0
  177. package/coverage/lcov-report/core/api/hooks/hooks.logger.js.html +163 -0
  178. package/coverage/lcov-report/core/api/hooks/hooks.model.js.html +955 -0
  179. package/coverage/lcov-report/core/api/hooks/hooks.organisations.js.html +541 -0
  180. package/coverage/lcov-report/core/api/hooks/hooks.push.js.html +253 -0
  181. package/coverage/lcov-report/core/api/hooks/hooks.query.js.html +862 -0
  182. package/coverage/lcov-report/core/api/hooks/hooks.schemas.js.html +298 -0
  183. package/coverage/lcov-report/core/api/hooks/hooks.service.js.html +319 -0
  184. package/coverage/lcov-report/core/api/hooks/hooks.storage.js.html +193 -0
  185. package/coverage/lcov-report/core/api/hooks/hooks.users.js.html +868 -0
  186. package/coverage/lcov-report/core/api/hooks/index.html +296 -0
  187. package/coverage/lcov-report/core/api/hooks/index.js.html +121 -0
  188. package/coverage/lcov-report/core/api/index.html +191 -0
  189. package/coverage/lcov-report/core/api/index.js.html +148 -0
  190. package/coverage/lcov-report/core/api/marshall.js.html +448 -0
  191. package/coverage/lcov-report/core/api/models/groups.model.mongodb.js.html +109 -0
  192. package/coverage/lcov-report/core/api/models/index.html +176 -0
  193. package/coverage/lcov-report/core/api/models/messages.model.mongodb.js.html +121 -0
  194. package/coverage/lcov-report/core/api/models/organisations.model.mongodb.js.html +94 -0
  195. package/coverage/lcov-report/core/api/models/tags.model.mongodb.js.html +115 -0
  196. package/coverage/lcov-report/core/api/models/users.model.mongodb.js.html +115 -0
  197. package/coverage/lcov-report/core/api/services/account/account.hooks.js.html +208 -0
  198. package/coverage/lcov-report/core/api/services/account/account.service.js.html +436 -0
  199. package/coverage/lcov-report/core/api/services/account/index.html +131 -0
  200. package/coverage/lcov-report/core/api/services/authorisations/authorisations.hooks.js.html +184 -0
  201. package/coverage/lcov-report/core/api/services/authorisations/authorisations.service.js.html +529 -0
  202. package/coverage/lcov-report/core/api/services/authorisations/index.html +131 -0
  203. package/coverage/lcov-report/core/api/services/databases/databases.hooks.js.html +193 -0
  204. package/coverage/lcov-report/core/api/services/databases/databases.service.js.html +100 -0
  205. package/coverage/lcov-report/core/api/services/databases/index.html +131 -0
  206. package/coverage/lcov-report/core/api/services/groups/groups.hooks.js.html +178 -0
  207. package/coverage/lcov-report/core/api/services/groups/index.html +116 -0
  208. package/coverage/lcov-report/core/api/services/import-export/import-export.hooks.js.html +184 -0
  209. package/coverage/lcov-report/core/api/services/import-export/import-export.service.js.html +118 -0
  210. package/coverage/lcov-report/core/api/services/import-export/index.html +131 -0
  211. package/coverage/lcov-report/core/api/services/index.html +116 -0
  212. package/coverage/lcov-report/core/api/services/index.js.html +556 -0
  213. package/coverage/lcov-report/core/api/services/mailer/index.html +131 -0
  214. package/coverage/lcov-report/core/api/services/mailer/mailer.hooks.js.html +190 -0
  215. package/coverage/lcov-report/core/api/services/mailer/mailer.service.js.html +118 -0
  216. package/coverage/lcov-report/core/api/services/messages/index.html +116 -0
  217. package/coverage/lcov-report/core/api/services/messages/messages.hooks.js.html +199 -0
  218. package/coverage/lcov-report/core/api/services/organisations/index.html +131 -0
  219. package/coverage/lcov-report/core/api/services/organisations/organisations.hooks.js.html +178 -0
  220. package/coverage/lcov-report/core/api/services/organisations/organisations.service.js.html +343 -0
  221. package/coverage/lcov-report/core/api/services/push/index.html +131 -0
  222. package/coverage/lcov-report/core/api/services/push/push.hooks.js.html +190 -0
  223. package/coverage/lcov-report/core/api/services/push/push.service.js.html +121 -0
  224. package/coverage/lcov-report/core/api/services/storage/index.html +131 -0
  225. package/coverage/lcov-report/core/api/services/storage/storage.hooks.js.html +190 -0
  226. package/coverage/lcov-report/core/api/services/storage/storage.service.js.html +172 -0
  227. package/coverage/lcov-report/core/api/services/tags/index.html +116 -0
  228. package/coverage/lcov-report/core/api/services/tags/tags.hooks.js.html +178 -0
  229. package/coverage/lcov-report/core/api/services/users/index.html +116 -0
  230. package/coverage/lcov-report/core/api/services/users/users.hooks.js.html +307 -0
  231. package/coverage/lcov-report/core/api/utils.js.html +118 -0
  232. package/coverage/lcov-report/core/common/errors.js.html +88 -0
  233. package/coverage/lcov-report/core/common/index.html +176 -0
  234. package/coverage/lcov-report/core/common/index.js.html +115 -0
  235. package/coverage/lcov-report/core/common/permissions.js.html +1048 -0
  236. package/coverage/lcov-report/core/common/schema.js.html +190 -0
  237. package/coverage/lcov-report/core/common/utils.js.html +220 -0
  238. package/coverage/lcov-report/favicon.png +0 -0
  239. package/coverage/lcov-report/index.html +506 -0
  240. package/coverage/lcov-report/map/api/hooks/hooks.catalog.js.html +457 -0
  241. package/coverage/lcov-report/map/api/hooks/hooks.features.js.html +397 -0
  242. package/coverage/lcov-report/map/api/hooks/hooks.query.js.html +1309 -0
  243. package/coverage/lcov-report/map/api/hooks/index.html +161 -0
  244. package/coverage/lcov-report/map/api/hooks/index.js.html +94 -0
  245. package/coverage/lcov-report/map/api/index.html +131 -0
  246. package/coverage/lcov-report/map/api/index.js.html +139 -0
  247. package/coverage/lcov-report/map/api/marshall.js.html +178 -0
  248. package/coverage/lcov-report/map/api/models/alerts.model.mongodb.js.html +106 -0
  249. package/coverage/lcov-report/map/api/models/catalog.model.mongodb.js.html +127 -0
  250. package/coverage/lcov-report/map/api/models/features.model.mongodb.js.html +196 -0
  251. package/coverage/lcov-report/map/api/models/index.html +161 -0
  252. package/coverage/lcov-report/map/api/models/projects.model.mongodb.js.html +109 -0
  253. package/coverage/lcov-report/map/api/services/alerts/alerts.hooks.js.html +274 -0
  254. package/coverage/lcov-report/map/api/services/alerts/alerts.service.js.html +610 -0
  255. package/coverage/lcov-report/map/api/services/alerts/index.html +131 -0
  256. package/coverage/lcov-report/map/api/services/catalog/catalog.hooks.js.html +310 -0
  257. package/coverage/lcov-report/map/api/services/catalog/index.html +116 -0
  258. package/coverage/lcov-report/map/api/services/daptiles/daptiles.service.js.html +1510 -0
  259. package/coverage/lcov-report/map/api/services/daptiles/index.html +116 -0
  260. package/coverage/lcov-report/map/api/services/features/features.hooks.js.html +241 -0
  261. package/coverage/lcov-report/map/api/services/features/features.service.js.html +241 -0
  262. package/coverage/lcov-report/map/api/services/features/index.html +131 -0
  263. package/coverage/lcov-report/map/api/services/index.html +116 -0
  264. package/coverage/lcov-report/map/api/services/index.js.html +817 -0
  265. package/coverage/lcov-report/map/api/services/projects/index.html +116 -0
  266. package/coverage/lcov-report/map/api/services/projects/projects.hooks.js.html +439 -0
  267. package/coverage/lcov-report/map/common/dynamic-grid-source.js.html +466 -0
  268. package/coverage/lcov-report/map/common/errors.js.html +94 -0
  269. package/coverage/lcov-report/map/common/geotiff-grid-source.js.html +541 -0
  270. package/coverage/lcov-report/map/common/grid.js.html +1612 -0
  271. package/coverage/lcov-report/map/common/index.html +371 -0
  272. package/coverage/lcov-report/map/common/index.js.html +172 -0
  273. package/coverage/lcov-report/map/common/meteo-model-grid-source.js.html +556 -0
  274. package/coverage/lcov-report/map/common/moment-utils.js.html +157 -0
  275. package/coverage/lcov-report/map/common/opendap-grid-source.js.html +868 -0
  276. package/coverage/lcov-report/map/common/opendap-utils.js.html +826 -0
  277. package/coverage/lcov-report/map/common/permissions.js.html +124 -0
  278. package/coverage/lcov-report/map/common/time-based-grid-source.js.html +418 -0
  279. package/coverage/lcov-report/map/common/tms-utils.js.html +274 -0
  280. package/coverage/lcov-report/map/common/wcs-grid-source.js.html +364 -0
  281. package/coverage/lcov-report/map/common/wcs-utils.js.html +586 -0
  282. package/coverage/lcov-report/map/common/weacast-grid-source.js.html +1033 -0
  283. package/coverage/lcov-report/map/common/wfs-utils.js.html +574 -0
  284. package/coverage/lcov-report/map/common/wms-utils.js.html +451 -0
  285. package/coverage/lcov-report/map/common/wmts-utils.js.html +547 -0
  286. package/coverage/lcov-report/prettify.css +1 -0
  287. package/coverage/lcov-report/prettify.js +2 -0
  288. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  289. package/coverage/lcov-report/sorter.js +196 -0
  290. package/coverage/lcov.info +11245 -0
  291. package/coverage/map/api/hooks/hooks.catalog.js.html +457 -0
  292. package/coverage/map/api/hooks/hooks.features.js.html +397 -0
  293. package/coverage/map/api/hooks/hooks.query.js.html +1309 -0
  294. package/coverage/map/api/hooks/index.html +161 -0
  295. package/coverage/map/api/hooks/index.js.html +94 -0
  296. package/coverage/map/api/index.html +131 -0
  297. package/coverage/map/api/index.js.html +139 -0
  298. package/coverage/map/api/marshall.js.html +178 -0
  299. package/coverage/map/api/models/alerts.model.mongodb.js.html +106 -0
  300. package/coverage/map/api/models/catalog.model.mongodb.js.html +127 -0
  301. package/coverage/map/api/models/features.model.mongodb.js.html +196 -0
  302. package/coverage/map/api/models/index.html +161 -0
  303. package/coverage/map/api/models/projects.model.mongodb.js.html +109 -0
  304. package/coverage/map/api/services/alerts/alerts.hooks.js.html +274 -0
  305. package/coverage/map/api/services/alerts/alerts.service.js.html +610 -0
  306. package/coverage/map/api/services/alerts/index.html +131 -0
  307. package/coverage/map/api/services/catalog/catalog.hooks.js.html +310 -0
  308. package/coverage/map/api/services/catalog/index.html +116 -0
  309. package/coverage/map/api/services/daptiles/daptiles.service.js.html +1510 -0
  310. package/coverage/map/api/services/daptiles/index.html +116 -0
  311. package/coverage/map/api/services/features/features.hooks.js.html +241 -0
  312. package/coverage/map/api/services/features/features.service.js.html +241 -0
  313. package/coverage/map/api/services/features/index.html +131 -0
  314. package/coverage/map/api/services/index.html +116 -0
  315. package/coverage/map/api/services/index.js.html +817 -0
  316. package/coverage/map/api/services/projects/index.html +116 -0
  317. package/coverage/map/api/services/projects/projects.hooks.js.html +439 -0
  318. package/coverage/map/common/dynamic-grid-source.js.html +466 -0
  319. package/coverage/map/common/errors.js.html +94 -0
  320. package/coverage/map/common/geotiff-grid-source.js.html +541 -0
  321. package/coverage/map/common/grid.js.html +1612 -0
  322. package/coverage/map/common/index.html +371 -0
  323. package/coverage/map/common/index.js.html +172 -0
  324. package/coverage/map/common/meteo-model-grid-source.js.html +556 -0
  325. package/coverage/map/common/moment-utils.js.html +157 -0
  326. package/coverage/map/common/opendap-grid-source.js.html +868 -0
  327. package/coverage/map/common/opendap-utils.js.html +826 -0
  328. package/coverage/map/common/permissions.js.html +124 -0
  329. package/coverage/map/common/time-based-grid-source.js.html +418 -0
  330. package/coverage/map/common/tms-utils.js.html +274 -0
  331. package/coverage/map/common/wcs-grid-source.js.html +364 -0
  332. package/coverage/map/common/wcs-utils.js.html +586 -0
  333. package/coverage/map/common/weacast-grid-source.js.html +1033 -0
  334. package/coverage/map/common/wfs-utils.js.html +574 -0
  335. package/coverage/map/common/wms-utils.js.html +451 -0
  336. package/coverage/map/common/wmts-utils.js.html +547 -0
  337. package/coverage/prettify.css +1 -0
  338. package/coverage/prettify.js +2 -0
  339. package/coverage/sort-arrow-sprite.png +0 -0
  340. package/coverage/sorter.js +196 -0
  341. package/coverage/tmp/coverage-280506-1731704745613-0.json +1 -0
  342. package/coverage/tmp/coverage-280518-1731704745599-0.json +1 -0
  343. package/coverage/tmp/coverage-280529-1731704745588-0.json +1 -0
  344. package/coverage/tmp/coverage-280541-1731704745574-0.json +1 -0
  345. package/coverage/tmp/coverage-280548-1731704745545-0.json +1 -0
  346. package/extras/css/core.variables.scss +32 -8
  347. package/extras/icons/attribution.png +0 -0
  348. package/map/api/services/catalog/catalog.hooks.js +5 -7
  349. package/map/api/services/features/features.hooks.js +1 -1
  350. package/map/client/cesium/utils/utils.style.js +11 -2
  351. package/map/client/components/KAttribution.vue +108 -0
  352. package/map/client/components/KPositionIndicator.vue +11 -18
  353. package/map/client/components/KProjectMenu.vue +4 -4
  354. package/map/client/components/catalog/KCategoryItem.vue +74 -0
  355. package/map/client/components/catalog/KLayerCategories.vue +24 -12
  356. package/map/client/components/catalog/KLayersPanel.vue +139 -116
  357. package/map/client/components/catalog/KProjectSelector.vue +29 -17
  358. package/map/client/components/catalog/KProjectsPanel.vue +19 -35
  359. package/map/client/components/catalog/KViewSelector.vue +37 -25
  360. package/map/client/components/catalog/KViewsPanel.vue +19 -35
  361. package/map/client/components/form/KLocationField.vue +1 -2
  362. package/map/client/components/legend/KLegend.vue +34 -34
  363. package/map/client/components/location/KLocationCardSection.vue +18 -22
  364. package/map/client/components/location/KLocationMap.vue +36 -38
  365. package/map/client/components/location/KLocationTimeLineCard.vue +147 -0
  366. package/map/client/components/location/KLocationTip.vue +12 -2
  367. package/map/client/components/widget/KInformationBox.vue +0 -4
  368. package/map/client/components/widget/KStackableTimeSeries.vue +8 -1
  369. package/map/client/components/widget/KTimeSeries.vue +1 -1
  370. package/map/client/composables/highlight.js +29 -31
  371. package/map/client/composables/probe.js +7 -3
  372. package/map/client/composables/weather.js +71 -31
  373. package/map/client/i18n/map_en.json +3 -0
  374. package/map/client/i18n/map_fr.json +3 -0
  375. package/map/client/init.js +4 -3
  376. package/map/client/leaflet/ShapeMarker.js +1 -1
  377. package/map/client/leaflet/TiledFeatureLayer.js +2 -3
  378. package/map/client/leaflet/utils/utils.events.js +1 -1
  379. package/map/client/leaflet/utils/utils.style.js +20 -8
  380. package/map/client/mixins/globe/mixin.base-globe.js +111 -13
  381. package/map/client/mixins/globe/mixin.file-layers.js +10 -10
  382. package/map/client/mixins/globe/mixin.geojson-layers.js +90 -15
  383. package/map/client/mixins/globe/mixin.style.js +2 -0
  384. package/map/client/mixins/index.js +0 -1
  385. package/map/client/mixins/map/index.js +1 -0
  386. package/map/client/mixins/map/mixin.base-map.js +21 -2
  387. package/map/client/mixins/map/mixin.canvas-layers.js +7 -2
  388. package/map/client/mixins/map/mixin.edit-layers.js +12 -4
  389. package/map/client/mixins/map/mixin.file-layers.js +3 -0
  390. package/map/client/mixins/map/mixin.geojson-layers.js +92 -6
  391. package/map/client/mixins/map/mixin.pmtiles-layers.js +106 -0
  392. package/map/client/mixins/mixin.activity.js +8 -3
  393. package/map/client/mixins/mixin.feature-service.js +73 -32
  394. package/map/client/mixins/mixin.levels.js +1 -0
  395. package/map/client/mixins/mixin.weacast.js +10 -87
  396. package/map/client/utils/index.js +1 -0
  397. package/map/client/utils/utils.capture.js +1 -1
  398. package/map/client/utils/utils.catalog.js +7 -7
  399. package/map/client/utils/utils.features.js +59 -1
  400. package/map/client/utils/utils.js +10 -0
  401. package/map/client/utils/utils.layers.js +8 -0
  402. package/map/client/utils/utils.time-series.js +195 -0
  403. package/map/client/utils/utils.weacast.js +102 -0
  404. package/package.json +6 -6
  405. package/scripts/init_runner.sh +2 -2
  406. package/scripts/kash/CHANGELOG.md +12 -0
  407. package/scripts/kash/README.md +2 -0
  408. package/scripts/kash/kash.sh +34 -32
  409. package/scripts/run_tests.sh +2 -2
  410. package/scripts/setup_workspace.sh +24 -6
  411. package/test/api/core/hooks.test.js +6 -3
  412. package/test/api/core/test-log-2023-12-19.log +7 -0
  413. package/test/api/core/test-log-2024-01-04.log +14 -0
  414. package/test/api/core/test-log-2024-05-14.log +6 -0
  415. package/test/api/core/{test-log-2024-04-23.log → test-log-2024-06-06.log} +3 -3
  416. package/test/api/core/test-log-2024-06-26.log +25 -0
  417. package/test/api/core/test-log-2024-06-28.log +2 -0
  418. package/test/api/core/test-log-2024-07-09.log +0 -0
  419. package/test/api/core/test-log-2024-08-13.log +69 -0
  420. package/test/api/core/test-log-2024-10-28.log +53 -0
  421. package/test/api/core/test-log-2024-11-05.log +30 -0
  422. package/test/api/core/test-log-2024-11-15.log +23 -0
  423. package/test/api/core/test-log-2024-11-18.log +0 -0
  424. package/test/api/core/test-log-2024-12-03.log +30 -0
  425. package/test/api/map/alerts.test.js +3 -1
  426. package/test/api/map/config/layers.json +3 -1
  427. package/test/api/map/index.test.js +18 -1
  428. package/test/api/map/test-log-2023-11-24.log +121 -0
  429. package/test/api/map/test-log-2023-12-12.log +29 -0
  430. package/test/api/map/test-log-2023-12-13.log +5 -0
  431. package/test/api/map/test-log-2024-01-04.log +2 -0
  432. package/test/api/map/test-log-2024-01-11.log +1 -0
  433. package/test/api/map/test-log-2024-01-25.log +19 -0
  434. package/test/api/map/test-log-2024-06-06.log +39 -0
  435. package/test/api/map/test-log-2024-08-13.log +13 -0
  436. package/test/api/map/test-log-2024-08-20.log +55 -0
  437. package/test/api/map/test-log-2024-09-09.log +92 -0
  438. package/test/api/map/test-log-2024-10-28.log +11 -0
  439. package/test/client/core/utils.js +13 -0
  440. package/test/client/map/api.js +34 -0
  441. package/test/client/map/catalog.js +6 -2
  442. package/test/client/map/index.js +1 -0
  443. package/test/client/map/utils.js +4 -2
  444. package/core/client/components/collection/KList.vue +0 -135
  445. package/core/client/components/layout/KPageSticky.vue +0 -53
  446. package/core/client/mixins/mixin.base-collection.js +0 -162
  447. package/core/client/utils/utils.data.js +0 -22
  448. package/map/client/mixins/mixin.catalog-panel.js +0 -26
  449. package/test/api/core/test-log-2024-04-22.log +0 -84
@@ -3,13 +3,16 @@ import _ from 'lodash'
3
3
  import logger from 'loglevel'
4
4
  import sift from 'sift'
5
5
  import { uid } from 'quasar'
6
- import { Time } from '../../../../core/client/time.js'
6
+ import { Time, Units } from '../../../../core.client.js'
7
7
  import { fetchGeoJson, getFeatureId, processFeatures, getFeatureStyleType, isInMemoryLayer } from '../../utils.js'
8
8
  import { convertSimpleStyleToPointStyle, convertSimpleStyleToLineStyle, convertSimpleStyleToPolygonStyle } from '../../utils/utils.style.js'
9
9
  import { convertToCesiumFromSimpleStyle, getPointSimpleStyle, getLineSimpleStyle, getPolygonSimpleStyle } from '../../cesium/utils/utils.style.js'
10
10
 
11
- function getWallEntityId (id) {
12
- return id + '-wall'
11
+ // Custom entity types that can be created from a base entity like eg a polyline
12
+ const CustomTypes = ['wall', 'corridor']
13
+ // Generate an id for a custom entity type, eg 'wall'
14
+ function getCustomEntityId (id, type) {
15
+ return `${id}-${type}`
13
16
  }
14
17
 
15
18
  function updateGeoJsonEntity(source, destination) {
@@ -44,10 +47,12 @@ export const geojsonLayers = {
44
47
  let features = (geoJson.type === 'FeatureCollection' ? geoJson.features : [geoJson])
45
48
  features.forEach(feature => {
46
49
  const id = getFeatureId(feature, options)
47
- const wallId = getWallEntityId(id)
48
- if (dataSource.entities.getById(id)) dataSource.entities.removeById(id)
49
- // Take care that in case of a wall entity we add it in addition to the original line
50
- if (dataSource.entities.getById(wallId)) dataSource.entities.removeById(wallId)
50
+ CustomTypes.forEach(type => {
51
+ const customId = getCustomEntityId(id, type)
52
+ if (dataSource.entities.getById(id)) dataSource.entities.removeById(id)
53
+ // Take care that in case of a custom entity we add it in addition to or instead the original line
54
+ if (dataSource.entities.getById(customId)) dataSource.entities.removeById(customId)
55
+ })
51
56
  })
52
57
  return
53
58
  }
@@ -66,10 +71,12 @@ export const geojsonLayers = {
66
71
  if (_.get(updateOptions, 'removeMissing', cesiumOptions.removeMissing)) {
67
72
  dataSource.entities.values.forEach(entity => {
68
73
  const id = entity.id
69
- const wallId = getWallEntityId(id)
70
- if (!loadingDataSource.entities.getById(id)) dataSource.entities.removeById(id)
71
- // Take care that in case of a wall entity we add it in addition to the original line
72
- if (dataSource.entities.getById(wallId)) dataSource.entities.removeById(wallId)
74
+ CustomTypes.forEach(type => {
75
+ const customId = getCustomEntityId(id, type)
76
+ if (!loadingDataSource.entities.getById(id)) dataSource.entities.removeById(id)
77
+ // Take care that in case of a custom entity we add it in addition to or instead the original line
78
+ if (dataSource.entities.getById(customId)) dataSource.entities.removeById(customId)
79
+ })
73
80
  })
74
81
  }
75
82
  // Process specific entities
@@ -108,7 +115,7 @@ export const geojsonLayers = {
108
115
  const { stroke, strokeWidth, fill } = this.convertFromSimpleStyleOrDefaults(properties)
109
116
  // Simply push the entity, other options like font will be set using styling options
110
117
  // This one will come in addition to the original line
111
- const wallId = getWallEntityId(entity.id)
118
+ const wallId = getCustomEntityId(entity.id, 'wall')
112
119
  entitiesToAdd.push({
113
120
  id: wallId,
114
121
  parent: entity,
@@ -124,6 +131,29 @@ export const geojsonLayers = {
124
131
  }
125
132
  })
126
133
  }
134
+ // Corridors
135
+ const corridor = _.get(properties, 'corridor')
136
+ if (corridor && entity.polyline) {
137
+ const { stroke, strokeWidth, fill } = this.convertFromSimpleStyleOrDefaults(properties)
138
+ // Simply push the entity, other options like width be set using styling options
139
+ // This one will come in replacement to the original line
140
+ const corridorId = getCustomEntityId(entity.id, 'corridor')
141
+ entitiesToAdd.push({
142
+ id: corridorId,
143
+ parent: entity,
144
+ name: entity.name ? entity.name : corridorId,
145
+ description: entity.description.getValue(0),
146
+ properties: entity.properties.getValue(0),
147
+ corridor: {
148
+ positions: entity.polyline.positions.getValue(0),
149
+ material: new ColorMaterialProperty(fill),
150
+ outlineColor: new ConstantProperty(stroke),
151
+ outlineWidth: strokeWidth,
152
+ outline: new ConstantProperty(true)
153
+ }
154
+ })
155
+ entitiesToRemove.push(entity)
156
+ }
127
157
  // Billboard with 'none' shape should be removed as Cesium creates it even if the maki icon id is unknown
128
158
  if (entity.billboard && (_.get(properties, 'marker-symbol') === 'none')) {
129
159
  entitiesToRemove.push(entity)
@@ -212,8 +242,11 @@ export const geojsonLayers = {
212
242
  // We cannot access data outside the properties object of a feature in Cesium
213
243
  // As a consequence we copy back any style information inside
214
244
  // We need to convert to simple-style spec as cesium manages this only
215
- // We also need to merge all styling properties as some entities requires eg both line/polygon style (wall polylines)
245
+ // We also need to merge all styling properties as some entities requires eg both line/polygon style (wall polylines or corridor polygons)
216
246
  const simpleStyle = Object.assign(getPointSimpleStyle(feature, options, engine), getLineSimpleStyle(feature, options, engine), getPolygonSimpleStyle(feature, options, engine))
247
+ // Manage our extended simple-style spec
248
+ const text = _.get(feature, 'style.text.label')
249
+ if (text) simpleStyle['icon-text'] = text
217
250
  if (!feature.properties) feature.properties = simpleStyle
218
251
  else Object.assign(feature.properties, simpleStyle)
219
252
  }
@@ -329,13 +362,18 @@ export const geojsonLayers = {
329
362
  this.$engineEvents.emit('layer-updated', layer, cesiumLayer, data)
330
363
  },
331
364
  onCurrentTimeChangedGeoJsonLayers (time) {
365
+ // Need to update layers that require an update at a given frequency
332
366
  const geoJsonlayers = _.values(this.layers).filter(sift({
367
+ // Possible for realtime layers only
333
368
  'cesium.type': 'geoJson',
334
369
  'cesium.realtime': true,
335
- $or: [ // Supported by template URL or time-based features
370
+ $or: [ // Supported by template URL or time-based features service
336
371
  { 'cesium.sourceTemplate': { $exists: true } },
337
372
  { service: { $exists: true } }
338
373
  ],
374
+ // Skip layers powered by realtime service events
375
+ serviceEvents: { $ne: true },
376
+ // Skip invisible layers
339
377
  isVisible: true
340
378
  }))
341
379
  geoJsonlayers.forEach(async geoJsonlayer => {
@@ -348,6 +386,41 @@ export const geojsonLayers = {
348
386
  }
349
387
  })
350
388
  },
389
+ onDefaultUnitChangedGeoJsonLayers (units) {
390
+ _.forOwn(units.default, (unit, quantity) => {
391
+ const units = _.map(Units.getUnits(quantity), 'name')
392
+ // Need to update layers with variables affected by the unit change,
393
+ // ie which style depends on it
394
+ let geoJsonlayers = _.values(this.layers).filter(sift({
395
+ 'cesium.type': 'geoJson',
396
+ 'cesium.realtime': true,
397
+ // Not sure why but this does not seem to work with sift
398
+ //'variables': { $elemMatch: { unit: { $in: units } } },
399
+ 'variables': { $exists: true },
400
+ isVisible: true,
401
+ 'cesium.style': { $exists: true },
402
+ 'cesium.template': { $exists: true }
403
+ }))
404
+ // Check for each layer if it uses the target unit and templated style uses the unit system or not
405
+ geoJsonlayers = geoJsonlayers.filter(layer => {
406
+ const unit = _.intersection(units, _.map(layer.variables, 'unit'))
407
+ if (_.isEmpty(unit)) return false
408
+ for (const template of layer.cesium.template) {
409
+ if (template.startsWith('style.')) {
410
+ const style = _.get(layer.cesium, template)
411
+ if ((typeof style === 'string') && style.includes('Units')) return true
412
+ }
413
+ }
414
+ return false
415
+ })
416
+ // Then retrieve the engine layers and update
417
+ geoJsonlayers.forEach(layer => {
418
+ // Retrieve the layer
419
+ const dataSource = this.getCesiumLayerByName(geoJsonlayer.name)
420
+ dataSource.updateGeoJson()
421
+ })
422
+ })
423
+ },
351
424
  onLayerShownGeoJsonLayers (layer, engineLayer) {
352
425
  // Check if we have cached geojson data for this layer
353
426
  const cachedGeojson = this.geojsonCache[layer.name]
@@ -371,6 +444,7 @@ export const geojsonLayers = {
371
444
  created () {
372
445
  this.registerCesiumConstructor(this.createCesiumGeoJsonLayer)
373
446
  this.$events.on('time-current-time-changed', this.onCurrentTimeChangedGeoJsonLayers)
447
+ this.$events.on('units-changed', this.onDefaultUnitChangedGeoJsonLayers)
374
448
  this.$engineEvents.on('layer-shown', this.onLayerShownGeoJsonLayers)
375
449
  this.$engineEvents.on('layer-removed', this.onLayerRemovedGeoJsonLayers)
376
450
  // Map of currently updated layers to avoid reentrance with real-time events as
@@ -380,7 +454,8 @@ export const geojsonLayers = {
380
454
  this.geojsonCache = {}
381
455
  },
382
456
  beforeUnmount () {
383
- this.$events.off('time-current-time-changed', this.onCurrentTimeChangedHeatmapLayers)
457
+ this.$events.off('time-current-time-changed', this.onCurrentTimeChangedGeoJsonLayers)
458
+ this.$events.off('units-changed', this.onDefaultUnitChangedGeoJsonLayers)
384
459
  this.$engineEvents.off('layer-shown', this.onLayerShownGeoJsonLayers)
385
460
  this.$engineEvents.off('layer-removed', this.onLayerRemovedGeoJsonLayers)
386
461
 
@@ -24,6 +24,8 @@ export const style = {
24
24
  }
25
25
  // Handle specific case of orientation
26
26
  if (style.orientation) entity.orientation = style.orientation
27
+ // Handle specific case of visibility
28
+ if (_.has(style, 'visibility')) entity.show = style.visibility
27
29
  }
28
30
  },
29
31
  applyClusterStyle (entities, cluster, options) {
@@ -1,5 +1,4 @@
1
1
  export * from './mixin.activity.js'
2
- export * from './mixin.catalog-panel.js'
3
2
  export * from './mixin.context.js'
4
3
  export * from './mixin.feature-selection.js'
5
4
  export * from './mixin.feature-service.js'
@@ -14,3 +14,4 @@ export * from './mixin.heatmap-layers.js'
14
14
  export * from './mixin.mapillary-layers.js'
15
15
  export * from './mixin.gsmap-layers.js'
16
16
  export * from './mixin.canvas-layers.js'
17
+ export * from './mixin.pmtiles-layers.js'
@@ -92,6 +92,9 @@ export const baseMap = {
92
92
  if (scale) this.setupScaleControl(scale)
93
93
  const geolocate = _.get(viewerOptions, 'geolocate', true)
94
94
  if (geolocate) this.setupGeolocateControl(geolocate)
95
+ // Add a special hidden pane, used to hide individual features
96
+ const hiddenPane = this.map.createPane('kdk-hidden-features')
97
+ hiddenPane.style.display = 'none'
95
98
  this.onMapReady()
96
99
  },
97
100
  onMapReady () {
@@ -560,11 +563,24 @@ export const baseMap = {
560
563
  },
561
564
  getBearing () {
562
565
  if (typeof this.map.getBearing !== 'function') {
563
- logger.warn(`[KDK] Map not configured to handle bearing, ignoring`)
564
566
  return 0
565
567
  }
566
568
  return this.map.getBearing()
567
569
  },
570
+ setCompassBearingTrackingEnabled (enabled) {
571
+ if (enabled) {
572
+ if (!this.map.compassBearing.enabled()) this.map.compassBearing.enable()
573
+ } else if (this.map.compassBearing.enabled()) {
574
+ this.map.compassBearing.disable()
575
+ }
576
+ },
577
+ setTouchRotateEnabled (enabled) {
578
+ if (enabled) {
579
+ if (!this.map.touchRotate.enabled()) this.map.touchRotate.enable()
580
+ } else if (this.map.touchRotate.enabled()) {
581
+ this.map.touchRotate.disable()
582
+ }
583
+ },
568
584
  getBounds () {
569
585
  this.viewBounds = this.map.getBounds()
570
586
  const south = this.viewBounds.getSouth()
@@ -650,6 +666,9 @@ export const baseMap = {
650
666
  this.$events.off('time-current-time-changed', this.onCurrentMapTimeChanged)
651
667
  },
652
668
  unmounted () {
653
- if (this.map) this.map.remove()
669
+ if (this.map) {
670
+ this.map.off()
671
+ this.map.remove()
672
+ }
654
673
  }
655
674
  }
@@ -207,8 +207,13 @@ L.KanvasLayer = (L.Layer ? L.Layer : L.Class).extend({
207
207
  }
208
208
 
209
209
  // Skip redraw when no feature hovered and we're not highlighting
210
- if (!hoveringFeatures && !this.highlighting) return
211
- this.needRedraw()
210
+ if (!hoveringFeatures && !this.highlighting) {
211
+ this._canvas.style.cursor = ''
212
+ return
213
+ } else {
214
+ this._canvas.style.cursor = 'pointer'
215
+ this.needRedraw()
216
+ }
212
217
  },
213
218
  // -------------------------------------------------------------
214
219
  getEvents: function () {
@@ -4,7 +4,8 @@ import { getType, getGeom } from '@turf/invariant'
4
4
  import { Dialog, uid } from 'quasar'
5
5
  import {
6
6
  bindLeafletEvents, unbindLeafletEvents,
7
- getDefaultPointStyle, getDefaultLineStyle, getDefaultPolygonStyle, createMarkerFromPointStyle
7
+ getDefaultPointStyle, getDefaultLineStyle, getDefaultPolygonStyle, createMarkerFromPointStyle,
8
+ convertSimpleStyleToPointStyle, convertSimpleStyleToLineStyle, convertSimpleStyleToPolygonStyle
8
9
  } from '../../utils.map.js'
9
10
 
10
11
  // Events we listen while layer is in edition mode
@@ -55,6 +56,13 @@ export const editLayers = {
55
56
  },
56
57
  getGeoJsonEditOptions (options) {
57
58
  let filteredOptions = options
59
+ // Convert and store style
60
+ const leafletOptions = options.leaflet || options
61
+ const layerStyle = {}
62
+ layerStyle.layerPointStyle = leafletOptions.style ? _.get(leafletOptions.style, 'point') : convertSimpleStyleToPointStyle(leafletOptions)
63
+ layerStyle.layerLineStyle = leafletOptions.style ? _.get(leafletOptions.style, 'line') : convertSimpleStyleToLineStyle(leafletOptions)
64
+ layerStyle.layerPolygonStyle = leafletOptions.style ? _.get(leafletOptions.style, 'polygon') : convertSimpleStyleToPolygonStyle(leafletOptions)
65
+
58
66
  if (_.has(filteredOptions, 'leaflet.tooltip') || _.has(filteredOptions, 'leaflet.popup')) {
59
67
  // Disable tooltip & popup features on edited layer
60
68
  filteredOptions = Object.assign({}, options)
@@ -72,16 +80,16 @@ export const editLayers = {
72
80
  // Use default styling when editing as dynamic styling can conflict
73
81
  style: (feature) => {
74
82
  if (['LineString', 'MultiLineString'].includes(feature.geometry.type)) {
75
- return getDefaultLineStyle(feature, null, _.get(this, 'activityOptions.engine'), 'style.edition.line')
83
+ return getDefaultLineStyle(feature, layerStyle, _.get(this, 'activityOptions.engine'), 'style.edition.line')
76
84
  }
77
85
  if (['Polygon', 'MultiPolygon'].includes(feature.geometry.type)) {
78
- return getDefaultPolygonStyle(feature, null, _.get(this, 'activityOptions.engine'), 'style.edition.polygon')
86
+ return getDefaultPolygonStyle(feature, layerStyle, _.get(this, 'activityOptions.engine'), 'style.edition.polygon')
79
87
  } else {
80
88
  logger.warn(`[KDK] the geometry of type of ${feature.geometry.type} is not supported`)
81
89
  }
82
90
  },
83
91
  pointToLayer: (feature, latlng) => {
84
- const style = getDefaultPointStyle(feature, null, _.get(this, 'activityOptions.engine'), 'style.edition.point')
92
+ const style = getDefaultPointStyle(feature, layerStyle, _.get(this, 'activityOptions.engine'), 'style.edition.point')
85
93
  style.options = { pmIgnore: false } // Allow geoman edition
86
94
  return createMarkerFromPointStyle(latlng, style)
87
95
  }
@@ -1,4 +1,5 @@
1
1
  import _ from 'lodash'
2
+ import logger from 'loglevel'
2
3
  import path from 'path-browserify'
3
4
  import { Reader } from '../../../../core/client/reader.js'
4
5
 
@@ -28,6 +29,7 @@ export const fileLayers = {
28
29
  dropFileInput.type = 'file'
29
30
  dropFileInput.style.display = 'none'
30
31
  dropFileInput.addEventListener('change', async (event) => {
32
+ logger.debug('[KDK] processing dropped files: ', event.target.files)
31
33
  await this.importFiles(event.target.files)
32
34
  })
33
35
  container.appendChild(dropFileInput)
@@ -39,6 +41,7 @@ export const fileLayers = {
39
41
  event.preventDefault()
40
42
  }, false)
41
43
  this.map._container.addEventListener('drop', async (event) => {
44
+ logger.debug('[KDK] processing dropped files: ', event.dataTransfer.files)
42
45
  event.stopPropagation()
43
46
  event.preventDefault()
44
47
  await this.importFiles(event.dataTransfer.files)
@@ -2,8 +2,9 @@ import L from 'leaflet'
2
2
  import _ from 'lodash'
3
3
  import sift from 'sift'
4
4
  import logger from 'loglevel'
5
+ import lineOffset from '@turf/line-offset'
5
6
  import 'leaflet-realtime'
6
- import { Time, utils as kdkCoreUtils } from '../../../../core.client.js'
7
+ import { Time, Units, utils as kdkCoreUtils } from '../../../../core.client.js'
7
8
  import { GradientPath } from '../../leaflet/GradientPath.js'
8
9
  import { MaskLayer } from '../../leaflet/MaskLayer.js'
9
10
  import { TiledFeatureLayer } from '../../leaflet/TiledFeatureLayer.js'
@@ -27,6 +28,31 @@ const Realtime = L.Realtime.extend({
27
28
  L.realtime = function (src, options) {
28
29
  return new Realtime(src, options)
29
30
  }
31
+ // Override default Polyline simplify function to manage offset
32
+ const simplifyPoints = L.Polyline.prototype._simplifyPoints
33
+ L.Polyline.include({
34
+ _simplifyPoints: function () {
35
+ simplifyPoints.call(this)
36
+ // Offset simplified version
37
+ if (this.options.offset) {
38
+ // We'd like to ensure a pixel constant offset when zooming
39
+ // Zoom 0 resolution is 156 543 m/pixel at equator in default map tiles,
40
+ // we take latitude into account to account for a convergence factor
41
+ const latitude = this.getBounds().getCenter().lat
42
+ const factor = 156543 / Math.pow(2, this._map.getZoom()) / Math.cos(latitude * Math.PI / 180)
43
+ const offset = Math.max(1, this.options.offset * factor)
44
+
45
+ for (let i = 0; i < this._parts.length; i++) {
46
+ let latLngs = this._parts[i].map(point => this._map.layerPointToLatLng(point))
47
+ // Ensure a large enough precision for computation (defaults to 6 in Leaflet)
48
+ const coords = L.GeoJSON.latLngsToCoords(latLngs, 0, false, 12)
49
+ const feature = lineOffset({ type: 'LineString', coordinates: coords }, offset, { units: 'meters' })
50
+ latLngs = L.GeoJSON.coordsToLatLngs(feature.geometry.coordinates, 0)
51
+ this._parts[i] = latLngs.map(latlng => this._map.latLngToLayerPoint(latlng))
52
+ }
53
+ }
54
+ }
55
+ })
30
56
 
31
57
  // Override default Leaflet GeoJson utility to manage some specific use cases
32
58
  const geometryToLayer = L.GeoJSON.geometryToLayer
@@ -55,10 +81,18 @@ L.GeoJSON.geometryToLayer = function (geojson, options) {
55
81
  if (geometry.type === 'Polygon' || geometry.type === 'MultiPolygon') {
56
82
  return new MaskLayer(geojson, options.style(geojson))
57
83
  }
84
+ }// Automate Leaflet.PolylineOffset plugin use
85
+ if (geometry && properties && properties.offset) {
86
+ if (geometry.type === 'LineString') {
87
+ options = Object.assign({ offset: properties.offset }, options)
88
+ }
58
89
  }
59
90
  // As we do so this breaks leaflet-arrowheads plugin
60
91
  const layer = geometryToLayer(geojson, options)
61
- if (options.arrowheads && (layer instanceof L.Polyline)) layer.arrowheads(options.arrowheads)
92
+ if (geometry && (options.arrowheads || (properties && properties.arrowheads))) {
93
+ if (layer instanceof L.Polyline) layer.arrowheads(options.arrowheads || properties.arrowheads)
94
+ }
95
+
62
96
  return layer
63
97
  }
64
98
 
@@ -164,7 +198,8 @@ export const geojsonLayers = {
164
198
  leafletOptions.removeMissing = false
165
199
  // Fetching is managed by tiles but even for manual update leaflet realtime require a src
166
200
  _.set(leafletOptions, 'source', async (successCallback, errorCallback) => {})
167
- // Generate fetch function for tiled feature layer
201
+ // Generate fetch functions for tiled feature layer
202
+ leafletOptions.probeSource = (baseQuery) => this.getProbeFeatures(_.merge({ baseQuery }, options))
168
203
  leafletOptions.featureSource = (baseQuery) => this.getFeatures(_.merge({ baseQuery }, options))
169
204
  } else {
170
205
  leafletOptions.removeMissing = !options.probeService
@@ -488,13 +523,18 @@ export const geojsonLayers = {
488
523
  this.$engineEvents.emit('layer-updated', layer, leafletLayer, data)
489
524
  },
490
525
  onCurrentTimeChangedGeoJsonLayers (time) {
526
+ // Need to update layers that require an update at a given frequency
491
527
  const geoJsonlayers = _.values(this.layers).filter(sift({
528
+ // Possible for realtime layers only
492
529
  'leaflet.type': 'geoJson',
493
530
  'leaflet.realtime': true,
494
- $or: [ // Supported by template URL or time-based features
531
+ $or: [ // Supported by template URL or time-based features service
495
532
  { 'leaflet.sourceTemplate': { $exists: true } },
496
533
  { service: { $exists: true } }
497
534
  ],
535
+ // Skip layers powered by realtime service events
536
+ serviceEvents: { $ne: true },
537
+ // Skip invisible layers
498
538
  isVisible: true
499
539
  }))
500
540
  geoJsonlayers.forEach(async geoJsonlayer => {
@@ -528,6 +568,44 @@ export const geojsonLayers = {
528
568
  }
529
569
  }
530
570
  },
571
+ onDefaultUnitChangedGeoJsonLayers (units) {
572
+ _.forOwn(units.default, (unit, quantity) => {
573
+ const units = _.map(Units.getUnits(quantity), 'name')
574
+ // Need to update layers with variables affected by the unit change,
575
+ // ie which style depends on it
576
+ let geoJsonlayers = _.values(this.layers).filter(sift({
577
+ 'leaflet.type': 'geoJson',
578
+ 'leaflet.realtime': true,
579
+ // Not sure why but this does not seem to work with sift
580
+ //'variables': { $elemMatch: { unit: { $in: units } } },
581
+ 'variables': { $exists: true },
582
+ isVisible: true,
583
+ 'leaflet.style': { $exists: true },
584
+ 'leaflet.template': { $exists: true }
585
+ }))
586
+ // Check for each layer if it uses the target unit and templated style uses the unit system or not
587
+ geoJsonlayers = geoJsonlayers.filter(layer => {
588
+ const unit = _.intersection(units, _.map(layer.variables, 'unit'))
589
+ if (_.isEmpty(unit)) return false
590
+ for (const template of layer.leaflet.template) {
591
+ if (template.startsWith('style.')) {
592
+ const style = _.get(layer.leaflet, template)
593
+ if ((typeof style === 'string') && style.includes('Units')) return true
594
+ }
595
+ }
596
+ return false
597
+ })
598
+ // Then retrieve the engine layers and update
599
+ geoJsonlayers.forEach(layer => {
600
+ layer = this.getLeafletLayerByName(layer.name)
601
+ if (layer.tiledLayer) {
602
+ layer.tiledLayer.redraw()
603
+ } else {
604
+ layer.update()
605
+ }
606
+ })
607
+ })
608
+ },
531
609
  onMapZoomChangedGeoJsonLayers () {
532
610
  // Need to update layers with tooltip defining a minZoom/maxZoom
533
611
  // as we cannot do that in template because tooltip needs to be recreated/destroyed dynamically
@@ -565,7 +643,13 @@ export const geojsonLayers = {
565
643
  if (cachedGeojson) {
566
644
  if (isInMemoryLayer(layer)) {
567
645
  // Restore geojson data for in-memory layers that was hidden
568
- this.updateLayer(layer.name, cachedGeojson)
646
+ // Directly deal with the leaflet layer instead of calling updateLayer, we are just restoring data
647
+ // Handle case where there's clustering on top (cf. updateLayer)
648
+ if (typeof engineLayer.getLayers === 'function') {
649
+ const container = engineLayer
650
+ engineLayer = container.getLayers().find(layer => layer._container === container)
651
+ }
652
+ engineLayer._onNewData(false, cachedGeojson)
569
653
  } else {
570
654
  // Clear cache since layer is not in memory anymore
571
655
  delete this.geojsonCache[layer.name]
@@ -583,6 +667,7 @@ export const geojsonLayers = {
583
667
  this.registerLeafletConstructor(this.createLeafletGeoJsonLayer)
584
668
  this.$events.on('time-current-time-changed', this.onCurrentTimeChangedGeoJsonLayers)
585
669
  this.$engineEvents.on('selected-level-changed', this.onCurrentLevelChangedGeoJsonLayers)
670
+ this.$events.on('units-changed', this.onDefaultUnitChangedGeoJsonLayers)
586
671
  this.$engineEvents.on('zoomend', this.onMapZoomChangedGeoJsonLayers)
587
672
  this.$engineEvents.on('layer-shown', this.onLayerShownGeoJsonLayers)
588
673
  this.$engineEvents.on('layer-removed', this.onLayerRemovedGeoJsonLayers)
@@ -591,8 +676,9 @@ export const geojsonLayers = {
591
676
  this.geojsonCache = {}
592
677
  },
593
678
  beforeUnmount () {
594
- this.$events.off('time-current-time-changed', this.onCurrentTimeChangedHeatmapLayers)
679
+ this.$events.off('time-current-time-changed', this.onCurrentTimeChangedGeoJsonLayers)
595
680
  this.$engineEvents.off('selected-level-changed', this.onCurrentLevelChangedGeoJsonLayers)
681
+ this.$events.off('units-changed', this.onDefaultUnitChangedGeoJsonLayers)
596
682
  this.$engineEvents.off('zoomend', this.onMapZoomChangedGeoJsonLayers)
597
683
  this.$engineEvents.off('layer-shown', this.onLayerShownGeoJsonLayers)
598
684
  this.$engineEvents.off('layer-removed', this.onLayerRemovedGeoJsonLayers)
@@ -0,0 +1,106 @@
1
+ import _ from 'lodash'
2
+ import chroma from 'chroma-js'
3
+ import moment from 'moment'
4
+ import sift from 'sift'
5
+ import L from 'leaflet'
6
+ import * as protomaps from 'protomaps-leaflet'
7
+ import { mapbox_style } from '@kalisio/leaflet-pmtiles'
8
+ import { Time, Units, TemplateContext } from '../../../../core/client/index.js'
9
+
10
+ export const pmtilesLayers = {
11
+ methods: {
12
+ async createLeafletPMTilesLayer (options) {
13
+ const leafletOptions = options.leaflet || options
14
+ // Check for valid types
15
+ if (leafletOptions.type !== 'pmtiles') return
16
+ // Optimize templating by creating compilers up-front
17
+ const layerStyleTemplate = _.get(leafletOptions, 'template')
18
+ if (layerStyleTemplate) {
19
+ // We allow to template style properties according to feature, because it can be slow you have to specify a subset of properties
20
+ leafletOptions.template = layerStyleTemplate.map(property => ({
21
+ property, compiler: _.template(_.get(leafletOptions, property))
22
+ }))
23
+ }
24
+
25
+ let rules = {}
26
+ // Check for style information given as object or URL
27
+ let style = _.get(leafletOptions, 'style')
28
+ if (typeof style === 'string') {
29
+ const response = await fetch(style)
30
+ if (response.status !== 200) {
31
+ throw new Error(`Impossible to fetch style ${style}: ` + response.status)
32
+ }
33
+ style = await response.json()
34
+ const backgroundLayer = style.layers.find(layer => layer.type === 'background')
35
+ if (backgroundLayer) leafletOptions.backgroundColor = backgroundLayer.paint['fill-color']
36
+ // Convert to PMTiles plugin paint rules
37
+ rules = mapbox_style(style, {})
38
+ } else {
39
+ // Manage templating
40
+ leafletOptions.template.forEach(entry => {
41
+ // protomaps allows property functions with zomm/feature as input
42
+ const f = (zoom, feature) => {
43
+ const context = Object.assign({ properties: feature.props, feature, chroma, moment, Units, Time, level: this.selectedLevel }, TemplateContext.get())
44
+ return entry.property.endsWith('filter') ? (entry.compiler(context) === 'true'): entry.compiler(context)
45
+ }
46
+ _.set(leafletOptions, entry.property, f)
47
+ })
48
+ const styleRules = _.map(style, rule => Object.assign(_.omit(rule, ['symbolizer']), {
49
+ symbolizer: new protomaps[rule.symbolizer.type](rule.symbolizer)
50
+ })
51
+ )
52
+ const isLabelSymbolizer = (rule) => typeof rule.symbolizer.place === 'function'
53
+ const isNotLabelSymbolizer = (rule) => !isLabelSymbolizer(rule)
54
+ // Support v1.x as well as v2.x
55
+ rules.paint_rules = rules.paintRules = _.filter(styleRules, isNotLabelSymbolizer)
56
+ rules.label_rules = rules.labelRules = _.filter(styleRules, isLabelSymbolizer)
57
+ }
58
+
59
+ return this.createLeafletLayer({
60
+ ...leafletOptions,
61
+ ...rules,
62
+ //debug: true,
63
+ //levelDiff: 2
64
+ })
65
+ },
66
+ onCurrentTimeChangedPMTilesLayers (time) {
67
+ const pmtileslayers = _.values(this.layers).filter(sift({
68
+ 'leaflet.type': 'pmtiles',
69
+ // Skip invisible layers
70
+ isVisible: true
71
+ }))
72
+ pmtileslayers.forEach(async pmtileslayer => {
73
+ // Retrieve the layer
74
+ const layer = this.getLeafletLayerByName(pmtileslayer.name)
75
+ layer.redraw()
76
+ })
77
+ },
78
+ onCurrentLevelChangedPMTilesLayers (level) {
79
+ // Retrieve the layer associated to current level sélection
80
+ let layer = this.selectableLevelsLayer
81
+ if (layer) {
82
+ const type = _.get(layer, `${this.engine}.type`)
83
+ // Check if of right type
84
+ if (type === 'pmtiles') {
85
+ // Retrieve the engine layer and update
86
+ layer = this.getLeafletLayerByName(layer.name)
87
+ layer.redraw()
88
+ }
89
+ }
90
+ }
91
+ },
92
+ created () {
93
+ this.registerLeafletConstructor(this.createLeafletPMTilesLayer)
94
+ this.$events.on('time-current-time-changed', this.onCurrentTimeChangedPMTilesLayers)
95
+ this.$engineEvents.on('selected-level-changed', this.onCurrentLevelChangedPMTilesLayers)
96
+ },
97
+ beforeUnmount () {
98
+ this.$events.off('time-current-time-changed', this.onCurrentTimeChangedPMTilesLayers)
99
+ this.$engineEvents.off('selected-level-changed', this.onCurrentLevelChangedPMTilesLayers)
100
+ }
101
+ }
102
+
103
+ // Not automatically declared by leaflet plugin
104
+ L.pmtiles = function (options) {
105
+ return protomaps.leafletLayer(options)
106
+ }
@@ -317,14 +317,19 @@ export const activity = {
317
317
  // (eg style edition, etc.)
318
318
  // Here we find layer by ID as renaming could have occured from another client
319
319
  const layer = this.getLayerById(object._id)
320
+ let planetApi
321
+ if (layer && (typeof layer.getPlanetApi === 'function')) {
322
+ planetApi = layer.getPlanetApi()
323
+ }
320
324
  if (layer) {
321
325
  // Stop any running edition
322
326
  if ((typeof this.isLayerEdited === 'function') && this.isLayerEdited(layer)) await this.stopEditLayer('reject')
323
327
  await this.removeCatalogLayer(layer)
324
328
  }
325
329
  if (event !== 'removed') {
326
- // Do we need to inject a token ?
327
- await setEngineJwt([object])
330
+ // Do we need to inject a token or restore planet API ?
331
+ if (planetApi) Object.assign(object, { getPlanetApi: () => planetApi })
332
+ await setEngineJwt([object], planetApi)
328
333
  await this.addCatalogLayer(object)
329
334
  }
330
335
  break
@@ -337,7 +342,7 @@ export const activity = {
337
342
  // Merge the engine options using defaults
338
343
  const defaultOptions = _.get(config, `engines.${this.engine}`)
339
344
  if (defaultOptions) {
340
- logger.debug(`[KDK] ${this.engine} engine use defaults: ${JSON.stringify(defaultOptions, null, 2)}`)
345
+ logger.debug(`[KDK] Configuring '${this.engine}' engine with options:`, defaultOptions)
341
346
  // Take care that if we only use the default options the specific options will be undefined
342
347
  this.activityOptions.engine = _.defaultsDeep(_.get(this.activityOptions, 'engine', {}), defaultOptions)
343
348
  }