@kalisio/kdk 2.6.4 → 2.7.0

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 (398) hide show
  1. package/core/api/application.js +2 -4
  2. package/core/api/authentication.js +2 -3
  3. package/core/api/db.js +10 -2
  4. package/core/api/hooks/hooks.authorisations.js +4 -2
  5. package/core/api/hooks/hooks.push.js +6 -2
  6. package/core/api/hooks/hooks.query.js +29 -12
  7. package/core/api/hooks/hooks.users.js +30 -17
  8. package/core/api/models/configurations.model.mongodb.js +4 -0
  9. package/core/api/services/authorisations/authorisations.service.js +1 -1
  10. package/core/api/services/configurations/configurations.hooks.js +33 -0
  11. package/core/api/services/index.js +41 -7
  12. package/core/api/services/messages/messages.hooks.js +9 -3
  13. package/core/client/api.js +14 -1
  14. package/core/client/capabilities.js +1 -6
  15. package/core/client/components/KAvatar.vue +24 -20
  16. package/core/client/components/account/KProfile.vue +10 -71
  17. package/core/client/components/account/index.js +0 -2
  18. package/core/client/components/app/KSettings.vue +1 -0
  19. package/core/client/components/collection/KBoard.vue +4 -3
  20. package/core/client/components/collection/KCardSection.vue +1 -0
  21. package/core/client/components/collection/KGrid.vue +2 -0
  22. package/core/client/components/collection/KTable.vue +5 -1
  23. package/core/client/components/collection/KTimeLine.vue +9 -1
  24. package/core/client/components/collection/index.js +0 -2
  25. package/core/client/components/form/KChipsField.vue +2 -1
  26. package/core/client/components/form/KEmailField.vue +1 -0
  27. package/core/client/components/form/KFileField.vue +22 -1
  28. package/core/client/components/form/KForm.vue +2 -0
  29. package/core/client/components/form/KItemField.vue +1 -0
  30. package/core/client/components/form/KNumberField.vue +1 -0
  31. package/core/client/components/form/KPasswordField.vue +1 -0
  32. package/core/client/components/form/KPhoneField.vue +1 -0
  33. package/core/client/components/form/KPropertyItemField.vue +1 -0
  34. package/core/client/components/form/KResolutionField.vue +1 -0
  35. package/core/client/components/form/KSelectField.vue +31 -0
  36. package/core/client/components/form/KTagField.vue +1 -0
  37. package/core/client/components/form/KTextField.vue +1 -0
  38. package/core/client/components/form/KTokenField.vue +1 -0
  39. package/core/client/components/form/KUnitField.vue +1 -0
  40. package/core/client/components/form/KUrlField.vue +1 -0
  41. package/core/client/components/graphics/KIcon.vue +3 -4
  42. package/core/client/components/layout/KPage.vue +1 -0
  43. package/core/client/components/layout/KWindow.vue +6 -3
  44. package/core/client/components/messages/KMessageComposer.vue +2 -1
  45. package/core/client/components/messages/KMessagesTimeLine.vue +1 -1
  46. package/core/client/components/time/KDate.vue +1 -2
  47. package/core/client/components/time/KDateTime.vue +11 -11
  48. package/core/client/components/time/KTime.vue +1 -1
  49. package/core/client/composables/collection.js +33 -8
  50. package/core/client/composables/errors.js +1 -1
  51. package/core/client/composables/layout.js +9 -9
  52. package/core/client/configurations.js +50 -0
  53. package/core/client/exporter.js +1 -1
  54. package/core/client/i18n/core_en.json +6 -39
  55. package/core/client/i18n/core_fr.json +6 -39
  56. package/core/client/index.js +2 -0
  57. package/core/client/layout.js +8 -8
  58. package/core/client/mixins/mixin.base-activity.js +5 -2
  59. package/core/client/mixins/mixin.base-field.js +3 -3
  60. package/core/client/search.js +2 -1
  61. package/core/client/utils/utils.collection.js +8 -8
  62. package/core/client/utils/utils.items.js +4 -0
  63. package/core/client/utils/utils.push.js +3 -3
  64. package/core/client/utils/utils.session.js +7 -5
  65. package/core/client/utils/utils.shapes.js +38 -7
  66. package/core/client/utils/utils.time.js +21 -22
  67. package/core/common/schemas/users.update-profile.json +3 -2
  68. package/coverage/core/api/application.js.html +392 -398
  69. package/coverage/core/api/authentication.js.html +352 -187
  70. package/coverage/core/api/db.js.html +165 -126
  71. package/coverage/core/api/hooks/hooks.authentication.js.html +22 -196
  72. package/coverage/core/api/hooks/hooks.authorisations.js.html +383 -662
  73. package/coverage/core/api/hooks/hooks.logger.js.html +41 -41
  74. package/coverage/core/api/hooks/hooks.model.js.html +113 -101
  75. package/coverage/core/api/hooks/hooks.push.js.html +124 -97
  76. package/coverage/core/api/hooks/hooks.query.js.html +292 -217
  77. package/coverage/core/api/hooks/hooks.schemas.js.html +123 -123
  78. package/coverage/core/api/hooks/hooks.service.js.html +1 -1
  79. package/coverage/core/api/hooks/hooks.storage.js.html +1 -1
  80. package/coverage/core/api/hooks/{hooks.groups.js.html → hooks.tags.js.html} +100 -76
  81. package/coverage/core/api/hooks/hooks.users.js.html +255 -447
  82. package/coverage/core/api/hooks/index.html +107 -122
  83. package/coverage/core/api/hooks/index.js.html +4 -10
  84. package/coverage/core/api/index.html +46 -61
  85. package/coverage/core/api/index.js.html +9 -9
  86. package/coverage/core/api/marshall.js.html +9 -9
  87. package/coverage/core/api/models/{organisations.model.mongodb.js.html → configurations.model.mongodb.js.html} +10 -7
  88. package/coverage/core/api/models/index.html +35 -50
  89. package/coverage/core/api/models/messages.model.mongodb.js.html +39 -27
  90. package/coverage/core/api/models/tags.model.mongodb.js.html +26 -32
  91. package/coverage/core/api/models/users.model.mongodb.js.html +10 -10
  92. package/coverage/core/api/services/account/account.hooks.js.html +5 -5
  93. package/coverage/core/api/services/account/account.service.js.html +127 -127
  94. package/coverage/core/api/services/account/index.html +22 -22
  95. package/coverage/core/api/services/authorisations/authorisations.hooks.js.html +1 -1
  96. package/coverage/core/api/services/authorisations/authorisations.service.js.html +213 -222
  97. package/coverage/core/api/services/authorisations/index.html +21 -21
  98. package/coverage/core/api/services/{organisations/organisations.hooks.js.html → configurations/configurations.hooks.js.html} +16 -10
  99. package/coverage/core/api/services/{groups → configurations}/index.html +8 -8
  100. package/coverage/core/api/services/databases/databases.hooks.js.html +1 -1
  101. package/coverage/core/api/services/databases/databases.service.js.html +1 -1
  102. package/coverage/core/api/services/databases/index.html +1 -1
  103. package/coverage/core/api/services/import-export/import-export.hooks.js.html +76 -76
  104. package/coverage/core/api/services/import-export/import-export.service.js.html +32 -32
  105. package/coverage/core/api/services/import-export/index.html +32 -32
  106. package/coverage/core/api/services/index.html +21 -21
  107. package/coverage/core/api/services/index.js.html +313 -142
  108. package/coverage/core/api/services/mailer/index.html +32 -32
  109. package/coverage/core/api/services/mailer/mailer.hooks.js.html +80 -80
  110. package/coverage/core/api/services/mailer/mailer.service.js.html +32 -32
  111. package/coverage/core/api/services/messages/index.html +21 -21
  112. package/coverage/core/api/services/messages/messages.hooks.js.html +112 -76
  113. package/coverage/core/api/services/push/index.html +32 -32
  114. package/coverage/core/api/services/push/push.hooks.js.html +80 -80
  115. package/coverage/core/api/services/push/push.service.js.html +34 -34
  116. package/coverage/core/api/services/storage/index.html +29 -29
  117. package/coverage/core/api/services/storage/storage.hooks.js.html +80 -80
  118. package/coverage/core/api/services/storage/storage.service.js.html +29 -29
  119. package/coverage/core/api/services/tags/index.html +21 -21
  120. package/coverage/core/api/services/tags/tags.hooks.js.html +119 -71
  121. package/coverage/core/api/services/users/index.html +27 -12
  122. package/coverage/core/api/services/users/users.hooks.js.html +14 -11
  123. package/coverage/core/api/services/users/users.service.js.html +100 -0
  124. package/coverage/core/common/errors.js.html +1 -1
  125. package/coverage/core/common/index.html +42 -27
  126. package/coverage/core/common/index.js.html +1 -1
  127. package/coverage/core/common/permissions.js.html +166 -472
  128. package/coverage/core/common/schema.js.html +4 -4
  129. package/coverage/core/common/utils.js.html +31 -25
  130. package/coverage/core/common/utils.offline.js.html +199 -0
  131. package/coverage/index.html +192 -192
  132. package/coverage/lcov-report/core/api/application.js.html +392 -398
  133. package/coverage/lcov-report/core/api/authentication.js.html +352 -187
  134. package/coverage/lcov-report/core/api/db.js.html +165 -126
  135. package/coverage/lcov-report/core/api/hooks/hooks.authentication.js.html +22 -196
  136. package/coverage/lcov-report/core/api/hooks/hooks.authorisations.js.html +383 -662
  137. package/coverage/lcov-report/core/api/hooks/hooks.logger.js.html +41 -41
  138. package/coverage/lcov-report/core/api/hooks/hooks.model.js.html +113 -101
  139. package/coverage/lcov-report/core/api/hooks/hooks.push.js.html +124 -97
  140. package/coverage/lcov-report/core/api/hooks/hooks.query.js.html +292 -217
  141. package/coverage/lcov-report/core/api/hooks/hooks.schemas.js.html +123 -123
  142. package/coverage/lcov-report/core/api/hooks/hooks.service.js.html +1 -1
  143. package/coverage/lcov-report/core/api/hooks/hooks.storage.js.html +1 -1
  144. package/coverage/lcov-report/core/api/hooks/{hooks.groups.js.html → hooks.tags.js.html} +100 -76
  145. package/coverage/lcov-report/core/api/hooks/hooks.users.js.html +255 -447
  146. package/coverage/lcov-report/core/api/hooks/index.html +107 -122
  147. package/coverage/lcov-report/core/api/hooks/index.js.html +4 -10
  148. package/coverage/lcov-report/core/api/index.html +46 -61
  149. package/coverage/lcov-report/core/api/index.js.html +9 -9
  150. package/coverage/lcov-report/core/api/marshall.js.html +9 -9
  151. package/coverage/lcov-report/core/api/models/{organisations.model.mongodb.js.html → configurations.model.mongodb.js.html} +10 -7
  152. package/coverage/lcov-report/core/api/models/index.html +35 -50
  153. package/coverage/lcov-report/core/api/models/messages.model.mongodb.js.html +39 -27
  154. package/coverage/lcov-report/core/api/models/tags.model.mongodb.js.html +26 -32
  155. package/coverage/lcov-report/core/api/models/users.model.mongodb.js.html +10 -10
  156. package/coverage/lcov-report/core/api/services/account/account.hooks.js.html +5 -5
  157. package/coverage/lcov-report/core/api/services/account/account.service.js.html +127 -127
  158. package/coverage/lcov-report/core/api/services/account/index.html +22 -22
  159. package/coverage/lcov-report/core/api/services/authorisations/authorisations.hooks.js.html +1 -1
  160. package/coverage/lcov-report/core/api/services/authorisations/authorisations.service.js.html +213 -222
  161. package/coverage/lcov-report/core/api/services/authorisations/index.html +21 -21
  162. package/coverage/lcov-report/core/api/services/{groups/groups.hooks.js.html → configurations/configurations.hooks.js.html} +16 -10
  163. package/coverage/lcov-report/core/api/services/{groups → configurations}/index.html +8 -8
  164. package/coverage/lcov-report/core/api/services/databases/databases.hooks.js.html +1 -1
  165. package/coverage/lcov-report/core/api/services/databases/databases.service.js.html +1 -1
  166. package/coverage/lcov-report/core/api/services/databases/index.html +1 -1
  167. package/coverage/lcov-report/core/api/services/import-export/import-export.hooks.js.html +76 -76
  168. package/coverage/lcov-report/core/api/services/import-export/import-export.service.js.html +32 -32
  169. package/coverage/lcov-report/core/api/services/import-export/index.html +32 -32
  170. package/coverage/lcov-report/core/api/services/index.html +21 -21
  171. package/coverage/lcov-report/core/api/services/index.js.html +313 -142
  172. package/coverage/lcov-report/core/api/services/mailer/index.html +32 -32
  173. package/coverage/lcov-report/core/api/services/mailer/mailer.hooks.js.html +80 -80
  174. package/coverage/lcov-report/core/api/services/mailer/mailer.service.js.html +32 -32
  175. package/coverage/lcov-report/core/api/services/messages/index.html +21 -21
  176. package/coverage/lcov-report/core/api/services/messages/messages.hooks.js.html +112 -76
  177. package/coverage/lcov-report/core/api/services/push/index.html +32 -32
  178. package/coverage/lcov-report/core/api/services/push/push.hooks.js.html +80 -80
  179. package/coverage/lcov-report/core/api/services/push/push.service.js.html +34 -34
  180. package/coverage/lcov-report/core/api/services/storage/index.html +29 -29
  181. package/coverage/lcov-report/core/api/services/storage/storage.hooks.js.html +80 -80
  182. package/coverage/lcov-report/core/api/services/storage/storage.service.js.html +29 -29
  183. package/coverage/lcov-report/core/api/services/tags/index.html +21 -21
  184. package/coverage/lcov-report/core/api/services/tags/tags.hooks.js.html +119 -71
  185. package/coverage/lcov-report/core/api/services/users/index.html +27 -12
  186. package/coverage/lcov-report/core/api/services/users/users.hooks.js.html +14 -11
  187. package/coverage/lcov-report/core/api/services/users/users.service.js.html +100 -0
  188. package/coverage/lcov-report/core/common/errors.js.html +1 -1
  189. package/coverage/lcov-report/core/common/index.html +42 -27
  190. package/coverage/lcov-report/core/common/index.js.html +1 -1
  191. package/coverage/lcov-report/core/common/permissions.js.html +166 -472
  192. package/coverage/lcov-report/core/common/schema.js.html +4 -4
  193. package/coverage/lcov-report/core/common/utils.js.html +31 -25
  194. package/coverage/lcov-report/core/common/utils.offline.js.html +199 -0
  195. package/coverage/lcov-report/index.html +192 -192
  196. package/coverage/lcov-report/map/api/hooks/hooks.catalog.js.html +169 -31
  197. package/coverage/lcov-report/map/api/hooks/hooks.features.js.html +1 -1
  198. package/coverage/lcov-report/map/api/hooks/hooks.query.js.html +215 -35
  199. package/coverage/lcov-report/map/api/hooks/index.html +7 -7
  200. package/coverage/lcov-report/map/api/hooks/index.js.html +1 -1
  201. package/coverage/lcov-report/map/api/index.html +1 -1
  202. package/coverage/lcov-report/map/api/index.js.html +1 -1
  203. package/coverage/lcov-report/map/api/marshall.js.html +1 -1
  204. package/coverage/lcov-report/map/api/models/alerts.model.mongodb.js.html +1 -1
  205. package/coverage/lcov-report/map/api/models/catalog.model.mongodb.js.html +82 -7
  206. package/coverage/lcov-report/map/api/models/features.model.mongodb.js.html +1 -1
  207. package/coverage/lcov-report/map/api/models/index.html +22 -7
  208. package/coverage/lcov-report/map/api/models/projects.model.mongodb.js.html +1 -1
  209. package/coverage/lcov-report/{core/api/models/groups.model.mongodb.js.html → map/api/models/styles.model.mongodb.js.html} +10 -7
  210. package/coverage/lcov-report/map/api/services/alerts/alerts.hooks.js.html +1 -1
  211. package/coverage/lcov-report/map/api/services/alerts/alerts.service.js.html +1 -1
  212. package/coverage/lcov-report/map/api/services/alerts/index.html +1 -1
  213. package/coverage/lcov-report/map/api/services/catalog/catalog.hooks.js.html +39 -12
  214. package/coverage/lcov-report/map/api/services/catalog/index.html +5 -5
  215. package/coverage/lcov-report/map/api/services/daptiles/daptiles.service.js.html +1 -1
  216. package/coverage/lcov-report/map/api/services/daptiles/index.html +1 -1
  217. package/coverage/lcov-report/map/api/services/features/features.hooks.js.html +86 -11
  218. package/coverage/lcov-report/map/api/services/features/features.service.js.html +307 -4
  219. package/coverage/lcov-report/map/api/services/features/index.html +7 -7
  220. package/coverage/lcov-report/map/api/services/index.html +5 -5
  221. package/coverage/lcov-report/map/api/services/index.js.html +326 -50
  222. package/coverage/lcov-report/map/api/services/projects/index.html +1 -1
  223. package/coverage/lcov-report/map/api/services/projects/projects.hooks.js.html +1 -1
  224. package/coverage/{core/api/services/organisations → lcov-report/map/api/services/styles}/index.html +10 -25
  225. package/coverage/lcov-report/{core/api/services/organisations/organisations.hooks.js.html → map/api/services/styles/styles.hooks.js.html} +45 -12
  226. package/coverage/lcov-report/map/common/dynamic-grid-source.js.html +1 -1
  227. package/coverage/lcov-report/map/common/errors.js.html +1 -1
  228. package/coverage/lcov-report/map/common/geotiff-grid-source.js.html +7 -10
  229. package/coverage/lcov-report/map/common/grid.js.html +1 -1
  230. package/coverage/lcov-report/map/common/index.html +19 -19
  231. package/coverage/lcov-report/map/common/index.js.html +1 -1
  232. package/coverage/lcov-report/map/common/meteo-model-grid-source.js.html +1 -1
  233. package/coverage/lcov-report/map/common/moment-utils.js.html +1 -1
  234. package/coverage/lcov-report/map/common/opendap-grid-source.js.html +1 -1
  235. package/coverage/lcov-report/map/common/opendap-utils.js.html +4 -7
  236. package/coverage/lcov-report/map/common/permissions.js.html +10 -4
  237. package/coverage/lcov-report/map/common/time-based-grid-source.js.html +1 -1
  238. package/coverage/lcov-report/map/common/tms-utils.js.html +9 -12
  239. package/coverage/lcov-report/map/common/wcs-grid-source.js.html +3 -3
  240. package/coverage/lcov-report/map/common/wcs-utils.js.html +12 -15
  241. package/coverage/lcov-report/map/common/weacast-grid-source.js.html +2 -2
  242. package/coverage/lcov-report/map/common/wfs-utils.js.html +14 -17
  243. package/coverage/lcov-report/map/common/wms-utils.js.html +30 -12
  244. package/coverage/lcov-report/map/common/wmts-utils.js.html +10 -13
  245. package/coverage/lcov.info +4157 -3816
  246. package/coverage/map/api/hooks/hooks.catalog.js.html +169 -31
  247. package/coverage/map/api/hooks/hooks.features.js.html +1 -1
  248. package/coverage/map/api/hooks/hooks.query.js.html +215 -35
  249. package/coverage/map/api/hooks/index.html +7 -7
  250. package/coverage/map/api/hooks/index.js.html +1 -1
  251. package/coverage/map/api/index.html +1 -1
  252. package/coverage/map/api/index.js.html +1 -1
  253. package/coverage/map/api/marshall.js.html +1 -1
  254. package/coverage/map/api/models/alerts.model.mongodb.js.html +1 -1
  255. package/coverage/map/api/models/catalog.model.mongodb.js.html +82 -7
  256. package/coverage/map/api/models/features.model.mongodb.js.html +1 -1
  257. package/coverage/map/api/models/index.html +22 -7
  258. package/coverage/map/api/models/projects.model.mongodb.js.html +1 -1
  259. package/coverage/{core/api/models/groups.model.mongodb.js.html → map/api/models/styles.model.mongodb.js.html} +10 -7
  260. package/coverage/map/api/services/alerts/alerts.hooks.js.html +1 -1
  261. package/coverage/map/api/services/alerts/alerts.service.js.html +1 -1
  262. package/coverage/map/api/services/alerts/index.html +1 -1
  263. package/coverage/map/api/services/catalog/catalog.hooks.js.html +39 -12
  264. package/coverage/map/api/services/catalog/index.html +5 -5
  265. package/coverage/map/api/services/daptiles/daptiles.service.js.html +1 -1
  266. package/coverage/map/api/services/daptiles/index.html +1 -1
  267. package/coverage/map/api/services/features/features.hooks.js.html +86 -11
  268. package/coverage/map/api/services/features/features.service.js.html +307 -4
  269. package/coverage/map/api/services/features/index.html +7 -7
  270. package/coverage/map/api/services/index.html +5 -5
  271. package/coverage/map/api/services/index.js.html +326 -50
  272. package/coverage/map/api/services/projects/index.html +1 -1
  273. package/coverage/map/api/services/projects/projects.hooks.js.html +1 -1
  274. package/coverage/{lcov-report/core/api/services/organisations → map/api/services/styles}/index.html +10 -25
  275. package/coverage/{core/api/services/groups/groups.hooks.js.html → map/api/services/styles/styles.hooks.js.html} +45 -12
  276. package/coverage/map/common/dynamic-grid-source.js.html +1 -1
  277. package/coverage/map/common/errors.js.html +1 -1
  278. package/coverage/map/common/geotiff-grid-source.js.html +7 -10
  279. package/coverage/map/common/grid.js.html +1 -1
  280. package/coverage/map/common/index.html +19 -19
  281. package/coverage/map/common/index.js.html +1 -1
  282. package/coverage/map/common/meteo-model-grid-source.js.html +1 -1
  283. package/coverage/map/common/moment-utils.js.html +1 -1
  284. package/coverage/map/common/opendap-grid-source.js.html +1 -1
  285. package/coverage/map/common/opendap-utils.js.html +4 -7
  286. package/coverage/map/common/permissions.js.html +10 -4
  287. package/coverage/map/common/time-based-grid-source.js.html +1 -1
  288. package/coverage/map/common/tms-utils.js.html +9 -12
  289. package/coverage/map/common/wcs-grid-source.js.html +3 -3
  290. package/coverage/map/common/wcs-utils.js.html +12 -15
  291. package/coverage/map/common/weacast-grid-source.js.html +2 -2
  292. package/coverage/map/common/wfs-utils.js.html +14 -17
  293. package/coverage/map/common/wms-utils.js.html +30 -12
  294. package/coverage/map/common/wmts-utils.js.html +10 -13
  295. package/coverage/tmp/coverage-1028514-1773134124472-0.json +1 -0
  296. package/coverage/tmp/coverage-1028526-1773134124448-0.json +1 -0
  297. package/coverage/tmp/coverage-1028537-1773134124431-0.json +1 -0
  298. package/coverage/tmp/coverage-1028549-1773134124401-0.json +1 -0
  299. package/coverage/tmp/coverage-1028556-1773134124353-0.json +1 -0
  300. package/extras/configs/widgets.top.js +3 -3
  301. package/extras/tests/core/collection.mjs +2 -9
  302. package/extras/tours/pane.top.js +0 -9
  303. package/map/api/hooks/hooks.catalog.js +18 -4
  304. package/map/api/services/catalog/catalog.hooks.js +3 -0
  305. package/map/api/services/features/features.hooks.js +3 -1
  306. package/map/api/services/index.js +2 -6
  307. package/map/api/services/styles/styles.hooks.js +6 -1
  308. package/map/client/components/KFeatureActionButton.vue +9 -3
  309. package/map/client/components/KFeaturesFilterManager.vue +5 -5
  310. package/map/client/components/KFilterCondition.vue +17 -10
  311. package/map/client/components/KLayerEditor.vue +49 -39
  312. package/map/client/components/KMeasureTool.vue +7 -1
  313. package/map/client/components/KTimezoneMap.vue +29 -9
  314. package/map/client/components/catalog/KLayersPanel.vue +26 -16
  315. package/map/client/components/catalog/KLayersSelector.vue +13 -2
  316. package/map/client/components/catalog/KViewsPanel.vue +5 -4
  317. package/map/client/components/form/KSelectLayersField.vue +28 -17
  318. package/map/client/components/form/KSelectViewsField.vue +18 -9
  319. package/map/client/components/form/KTimezoneField.vue +1 -2
  320. package/map/client/components/legend/KVariablesLegend.vue +10 -1
  321. package/map/client/components/location/KLocationCardSection.vue +7 -2
  322. package/map/client/components/location/KLocationMap.vue +31 -7
  323. package/map/client/components/selection/KSelectedLayerFeatures.vue +2 -2
  324. package/map/client/components/stickies/KZoomControl.vue +1 -1
  325. package/map/client/components/styles/KStyleManager.vue +4 -1
  326. package/map/client/components/widget/KTimeSeries.vue +174 -497
  327. package/map/client/components/widget/KTimeSeriesSelector.vue +72 -0
  328. package/map/client/components/widget/KTimeSeriesToolbar.vue +83 -0
  329. package/map/client/composables/catalog.js +6 -10
  330. package/map/client/composables/highlight.js +12 -9
  331. package/map/client/composables/project.js +1 -1
  332. package/map/client/composables/selection.js +8 -7
  333. package/map/client/composables/weather.js +9 -2
  334. package/map/client/geolocation.js +8 -5
  335. package/map/client/i18n/map_en.json +11 -10
  336. package/map/client/i18n/map_fr.json +10 -9
  337. package/map/client/leaflet/TiledFeatureLayer.js +85 -82
  338. package/map/client/leaflet/utils/utils.geojson.js +3 -3
  339. package/map/client/mixins/globe/mixin.base-globe.js +15 -6
  340. package/map/client/mixins/globe/mixin.geojson-layers.js +27 -18
  341. package/map/client/mixins/map/mixin.edit-layers.js +9 -1
  342. package/map/client/mixins/map/mixin.pmtiles-layers.js +118 -29
  343. package/map/client/mixins/map/mixin.tiled-mesh-layers.js +12 -5
  344. package/map/client/mixins/map/mixin.tiled-wind-layers.js +19 -10
  345. package/map/client/mixins/mixin.activity.js +23 -30
  346. package/map/client/mixins/mixin.feature-selection.js +41 -5
  347. package/map/client/planets.js +1 -1
  348. package/map/client/readers/reader.kml.js +2 -3
  349. package/map/client/utils/utils.catalog.js +36 -10
  350. package/map/client/utils/utils.layers.js +39 -8
  351. package/map/client/utils/utils.project.js +4 -0
  352. package/map/client/utils/utils.style.js +37 -7
  353. package/map/client/utils/utils.time-series.js +215 -6
  354. package/map/common/schemas/catalog.update.json +1 -1
  355. package/map/common/weacast-grid-source.js +1 -1
  356. package/package.json +3 -3
  357. package/scripts/kash/CHANGELOG.md +0 -4
  358. package/scripts/kash/README.md +0 -9
  359. package/scripts/kash/kash.sh +45 -40
  360. package/scripts/kash/scripts/run_tests.sh +1 -4
  361. package/test/api/core/authentication.test.js +9 -4
  362. package/test/api/core/config/default.cjs +1 -0
  363. package/test/api/core/hooks.test.js +6 -0
  364. package/test/api/core/index.test.js +43 -18
  365. package/test/api/core/push.test.js +8 -8
  366. package/test/api/core/test-log-2026-03-10.log +60 -0
  367. package/test/api/core/users.test.js +384 -0
  368. package/test/api/map/grid-sources.test.js +1 -1
  369. package/test/api/map/test-log-2026-03-10.log +56 -0
  370. package/vite/package.json +11 -2
  371. package/vite/test/core/composables.test.js +77 -0
  372. package/vite/vitest.config.js +13 -0
  373. package/vite/yarn.lock +1096 -18
  374. package/.vscode/settings.json +0 -5
  375. package/core/client/components/account/KAccount.vue +0 -68
  376. package/core/client/components/account/KDeleteAccountManager.vue +0 -62
  377. package/core/client/components/account/KEmailManager.vue +0 -128
  378. package/core/client/components/account/KPasswordManager.vue +0 -90
  379. package/core/client/components/account/KVerifyEmailManager.vue +0 -105
  380. package/core/client/components/collection/KColumn.vue +0 -227
  381. package/core/client/components/collection/KHistory.vue +0 -113
  382. package/core/client/components/collection/KHistoryEntry.vue +0 -109
  383. package/coverage/core/api/hooks/hooks.organisations.js.html +0 -541
  384. package/coverage/core/api/services/organisations/organisations.service.js.html +0 -343
  385. package/coverage/core/api/utils.js.html +0 -118
  386. package/coverage/lcov-report/core/api/hooks/hooks.organisations.js.html +0 -541
  387. package/coverage/lcov-report/core/api/services/organisations/organisations.service.js.html +0 -343
  388. package/coverage/lcov-report/core/api/utils.js.html +0 -118
  389. package/coverage/tmp/coverage-151166-1723543324307-0.json +0 -1
  390. package/coverage/tmp/coverage-151178-1723543324283-0.json +0 -1
  391. package/coverage/tmp/coverage-151189-1723543324271-0.json +0 -1
  392. package/coverage/tmp/coverage-151201-1723543324248-0.json +0 -1
  393. package/coverage/tmp/coverage-151208-1723543324227-0.json +0 -1
  394. package/scripts/kash/LICENSE +0 -21
  395. package/test/api/core/test-log-2024-04-22.log +0 -84
  396. package/test/api/core/test-log-2024-04-23.log +0 -23
  397. package/test/api/core/test-log-2024-08-13.log +0 -3
  398. package/test/api/map/test-log-2025-03-08.log +0 -0
@@ -27,10 +27,10 @@ module.exports = {
27
27
  },
28
28
  TIME_SERIES: {
29
29
  id: 'time-series',
30
- label: 'TimeSeries.LABEL',
30
+ label: 'KTimeSeries.LABEL',
31
31
  icon: 'las la-chart-line',
32
- content: { component: 'TimeSeries' },
33
- header: [{ component: 'TimeSeriesToolbar' }]
32
+ content: { component: 'widget/KTimeSeries' },
33
+ header: [{ component: 'widget/KTimeSeriesToolbar' }]
34
34
  },
35
35
  ELEVATION_PROFILE: {
36
36
  id: 'elevation-profile',
@@ -1,5 +1,5 @@
1
1
  import makeDebug from 'debug'
2
- import { countElements, waitForTimeout } from './utils.mjs'
2
+ import { countElements, waitForTimeout, clickXPath } from './utils.mjs'
3
3
 
4
4
  const debug = makeDebug('kdk:core:test:collection')
5
5
 
@@ -33,14 +33,7 @@ export async function clickItem (page, component, name, wait = 500) {
33
33
 
34
34
  export async function clickItemAction (page, component, name, action, wait = 500) {
35
35
  const xpath = `//div[contains(@component, "${component}") and contains(., "${name}")]//button[@id="${action}"]`
36
- const elements = await page.$$('xpath/.' + xpath)
37
- if (elements.length > 0) {
38
- elements[0].click()
39
- await waitForTimeout(wait)
40
- debug(`Clicked action ${action} on item ${name}`)
41
- } else {
42
- debug(`Action ${action} on item ${name} not found`)
43
- }
36
+ await clickXPath(page, xpath, wait)
44
37
  }
45
38
 
46
39
  export async function isCardExpanded (page, component, name) {
@@ -105,15 +105,6 @@ module.exports = {
105
105
  }
106
106
  }, options)
107
107
  },
108
- toggleZoomControl: (options) => {
109
- return Object.assign({
110
- target: '#toggle-zoom-control-sticky',
111
- title: 'tours.navigation-bar.ZOOM_CONTROL_LABEL',
112
- params: {
113
- placement: 'bottom'
114
- }
115
- }, options)
116
- },
117
108
  positionIndicator: (options) => {
118
109
  return Object.assign({
119
110
  target: '#position-indicator',
@@ -30,6 +30,7 @@ export function getDefaultCategories (hook) {
30
30
  const service = hook.service
31
31
  // Check for default categories config
32
32
  const defaultCategories = _.get(service, 'options.categories', [])
33
+ debug(`Retrieving ${defaultCategories.length} default categories for query`, query)
33
34
  replaceItems(hook, addDefaultItems(query, type, getItems(hook), defaultCategories))
34
35
  }
35
36
  }
@@ -42,6 +43,7 @@ export function getDefaultSublegends (hook) {
42
43
  const service = hook.service
43
44
  // Check for default sublegends config
44
45
  const defaultSublegends = _.get(service, 'options.sublegends', [])
46
+ debug(`Retrieving ${defaultSublegends.length} default sublegends for query`, query)
45
47
  replaceItems(hook, addDefaultItems(query, type, getItems(hook), defaultSublegends))
46
48
  }
47
49
  }
@@ -97,7 +99,9 @@ export async function updateProjects (hook) {
97
99
  if (!Array.isArray(removedItems)) removedItems = [removedItems]
98
100
  for (let i = 0; i < removedItems.length; i++) {
99
101
  const removedItem = removedItems[i]
100
- const isLayer = removedItem.type !== 'Context'
102
+ const isLayer = removedItem.type.endsWith('Layer')
103
+ const isView = (removedItem.type === 'Context')
104
+ if (!isLayer && !isView) continue
101
105
  const query = {}
102
106
  if (isLayer) {
103
107
  query.$or = [{ 'layers._id': removedItem._id }, { 'layers.name': removedItem.name }]
@@ -111,7 +115,7 @@ export async function updateProjects (hook) {
111
115
  // Stop when non found
112
116
  if (projects.length === 0) {
113
117
  debug(`No project to update after removing item ${removedItem.name} `)
114
- return hook
118
+ continue
115
119
  }
116
120
  // Update each project otherwise
117
121
  await Promise.all(projects.map(project => {
@@ -130,13 +134,18 @@ export function convertFilterQueriesToString (hook) {
130
134
  let items = getItems(hook)
131
135
  const isArray = Array.isArray(items)
132
136
  items = (isArray ? items : [items])
137
+ let nbUpdatedItems = 0
133
138
  items.forEach(item => {
134
139
  const filters = _.get(item, 'filters', [])
140
+ nbUpdatedItems += filters.length
135
141
  _.forEach(filters, filter => {
136
142
  toString(filter, ['active', 'inactive'])
137
143
  })
138
144
  })
139
- replaceItems(hook, isArray ? items : items[0])
145
+ if (nbUpdatedItems > 0) {
146
+ replaceItems(hook, isArray ? items : items[0])
147
+ debug(`Updated ${nbUpdatedItems} filters on items`)
148
+ }
140
149
 
141
150
  return hook
142
151
  }
@@ -145,13 +154,18 @@ export function convertFilterQueriesToObject (hook) {
145
154
  let items = getItems(hook)
146
155
  const isArray = Array.isArray(items)
147
156
  items = (isArray ? items : [items])
157
+ let nbUpdatedItems = 0
148
158
  items.forEach(item => {
149
159
  const filters = _.get(item, 'filters', [])
160
+ nbUpdatedItems += filters.length
150
161
  _.forEach(filters, filter => {
151
162
  toJson(filter, ['active', 'inactive'])
152
163
  })
153
164
  })
154
- replaceItems(hook, isArray ? items : items[0])
165
+ if (nbUpdatedItems > 0) {
166
+ replaceItems(hook, isArray ? items : items[0])
167
+ debug(`Updated ${nbUpdatedItems} filters on items`)
168
+ }
155
169
 
156
170
  return hook
157
171
  }
@@ -17,6 +17,9 @@ export default {
17
17
  get: [],
18
18
  create: [
19
19
  coreHooks.checkUnique({ field: 'name', query: (query, hook) => { query.type = _.get(hook, 'data.type') } }),
20
+ // Usually conversion of _id to ObjectID is performed by an app-evel hook, which is not yet setup when creating the service.
21
+ // As we can create features when initializing layer service/data we add it here as well to ensure it will work fine anyway.
22
+ coreHooks.convertObjectIDs(['_id']),
20
23
  coreHooks.convertToString(['baseQuery', 'schema.content']),
21
24
  convertFilterQueriesToString,
22
25
  setNow('createdAt', 'updatedAt'),
@@ -44,7 +44,9 @@ export default {
44
44
  find: [coreHooks.marshallComparisonQuery, coreHooks.marshallSortQuery, marshallSpatialQuery,
45
45
  coreHooks.distinct, aggregateFeaturesQuery, coreHooks.aggregationQuery, fuzzySearch, coreHooks.diacriticSearch()],
46
46
  get: [],
47
- create: [coreHooks.processTimes(['time']), fullResult, emitEvents],
47
+ // Usually conversion of _id to ObjectID is performed by an app-evel hook, which is not yet setup when creating the service.
48
+ // As we can create features when initializing layer service/data we add it here as well to ensure it will work fine anyway.
49
+ create: [coreHooks.processTimes(['time']), coreHooks.convertObjectIDs(['_id']), fullResult, emitEvents],
48
50
  update: [upsert, coreHooks.processTimes(['time']), fullResult, emitEvents],
49
51
  patch: [upsert, coreHooks.processTimes(['time']), fullResult, emitEvents],
50
52
  remove: [coreHooks.marshallComparisonQuery, marshallSpatialQuery, fullResult, emitEvents],
@@ -220,10 +220,6 @@ export async function createDefaultCatalogLayers (options = {}) {
220
220
  let geojson = fs.readJsonSync(extractedFileName)
221
221
  // We allow GeoJson collection or features array
222
222
  geojson = Array.isArray(geojson) ? geojson : geojson.features
223
- // We also allow for data exported from MongoDB, in this case remove any Mongo specific ID
224
- geojson.forEach(feature => {
225
- delete feature._id
226
- })
227
223
  try {
228
224
  await createFeaturesForLayer.call(app, geojson, defaultLayer, options)
229
225
  } catch (error) {
@@ -266,11 +262,11 @@ export function removeStylesService (options = {}) {
266
262
  return app.removeService(app.getService('styles', options.context))
267
263
  }
268
264
 
269
- export async function createDefaultStyles () {
265
+ export async function createDefaultStyles (context) {
270
266
  const app = this
271
267
  const defaultStyles = app.get('styles').defaultStyles
272
268
  if (!defaultStyles) return
273
- const stylesService = app.getService('styles')
269
+ const stylesService = app.getService('styles', context)
274
270
  // Create default styles if not already done
275
271
  const styles = await stylesService.find({ paginate: false })
276
272
  for (let i = 0; i < defaultStyles.length; i++) {
@@ -9,7 +9,12 @@ export default {
9
9
  kdkCoreHooks.diacriticSearch()
10
10
  ],
11
11
  get: [],
12
- create: [kdkCoreHooks.checkUnique({ field: 'name' })],
12
+ create: [
13
+ // Usually conversion of _id to ObjectID is performed by an app-evel hook, which is not yet setup when creating the service.
14
+ // As we can create features when initializing layer service/data we add it here as well to ensure it will work fine anyway.
15
+ kdkCoreHooks.convertObjectIDs(['_id']),
16
+ kdkCoreHooks.checkUnique({ field: 'name' })
17
+ ],
13
18
  update: [kdkCoreHooks.checkUnique({ field: 'name' })],
14
19
  patch: [kdkCoreHooks.checkUnique({ field: 'name' })],
15
20
  remove: []
@@ -7,13 +7,13 @@
7
7
  :actions="featureActions"
8
8
  @close="onCloseMenu">
9
9
  <!--template v-slot:closed-menu-container>
10
- <q-btn round color="accent" icon="las la-chevron-up" />
10
+ <q-btn round :color="color" icon="las la-chevron-up" />
11
11
  </template-->
12
12
  <template v-slot:open-menu-container>
13
- <q-btn round color="accent" icon="las la-times" />
13
+ <q-btn round :color="color" icon="las la-times" />
14
14
  </template>
15
15
  <template v-slot:menu-item="action">
16
- <q-btn round color="accent" :icon="action.icon" @click="onFeatureActionClicked(action)">
16
+ <q-btn round :color="color" :icon="action.icon" @click="onFeatureActionClicked(action)">
17
17
  <!-- tooltip -->
18
18
  <q-tooltip v-if="action.label">
19
19
  {{action.label}}
@@ -36,6 +36,12 @@ export default {
36
36
  components: {
37
37
  KRadialFab
38
38
  },
39
+ props: {
40
+ color: {
41
+ type: String,
42
+ default: 'accent'
43
+ }
44
+ },
39
45
  data () {
40
46
  return {
41
47
  featureActions: [],
@@ -25,8 +25,8 @@
25
25
  <q-list separator v-if="filters.length">
26
26
  <q-item v-for="item in filters" :key="item.id">
27
27
  <q-item-section>
28
- <q-item-label>{{ item.label }}</q-item-label>
29
- <q-item-label caption>{{ item.description }}</q-item-label>
28
+ <q-item-label>{{ $t(item.label) }}</q-item-label>
29
+ <q-item-label caption>{{ item.description ? $t(item.description) : '' }}</q-item-label>
30
30
  </q-item-section>
31
31
  <q-item-section class="col-auto">
32
32
  <KPanel
@@ -171,13 +171,13 @@ async function apply () {
171
171
  }
172
172
 
173
173
  const engineStyle = _.pick(_.get(CurrentActivity.value, 'activityOptions.engine.style', {}), ['point', 'line', 'polygon'])
174
- const layerDefaultStyle = getDefaultStyleFromTemplates(_.get(layer, 'leaflet.style', {}))
174
+ const layerDefaultStyle = getDefaultStyleFromTemplates(_.get(layer, 'leaflet.style', _.get(layer, 'cesium.style', {})))
175
175
  const templates = generateStyleTemplates(_.merge({}, DefaultStyle, engineStyle, layerDefaultStyle), styles)
176
176
  const result = Object.assign(
177
177
  {},
178
178
  (!_.isEmpty(validFilters) ? { filters: validFilters } : { $unset: { filters: true } }),
179
- _.mapKeys(templates, (value, key) => `leaflet.${key}`),
180
- _.mapKeys(templates, (value, key) => `cesium.${key}`)
179
+ _.has(layer, 'leaflet') ? _.mapKeys(templates, (value, key) => `leaflet.${key}`) : {},
180
+ _.has(layer, 'cesium') ? _.mapKeys(templates, (value, key) => `cesium.${key}`) : {}
181
181
  )
182
182
  const legendLayer = Object.assign({}, layer, result)
183
183
  if (_.isEmpty(validFilters)) delete legendLayer.filters
@@ -191,17 +191,24 @@ async function onPropertyChange (property) {
191
191
  return
192
192
  }
193
193
 
194
- const options = await api.getService(_.get(layer, 'service'))
195
- .find({ query: Object.assign({ $distinct: `properties.${property}` }, _.get(layer, 'baseQuery')) })
194
+ // If layer isn't backed by some feathers service, dont' bother querying the list
195
+ // of allowed values.
196
+ if (layer.service) {
197
+ const options = await api.getService(_.get(layer, 'service'))
198
+ .find({ query: Object.assign({ $distinct: `properties.${property}` }, _.get(layer, 'baseQuery')) })
196
199
 
197
- // Filter values that are not in the new options
198
- if (value.value && !_.isArray(value.value)) {
199
- value.value = options.includes(value.value) ? value.value : null
200
- } else if (value.value && _.isArray(value.value)) {
201
- value.value = _.filter(value.value, v => options.includes(v))
200
+ // Filter values that are not in the new options
201
+ if (value.value && !_.isArray(value.value)) {
202
+ value.value = options.includes(value.value) ? value.value : null
203
+ } else if (value.value && _.isArray(value.value)) {
204
+ value.value = _.filter(value.value, v => options.includes(v))
205
+ }
206
+
207
+ valueOptions.value = options.sort()
208
+ } else {
209
+ valueOptions.value = null
202
210
  }
203
211
 
204
- valueOptions.value = options.sort()
205
212
  valueIsNumber.value = false
206
213
 
207
214
  checkPropertyValidity(property)
@@ -246,9 +253,9 @@ function checkComparisonOperatorValidity (value) {
246
253
  function checkValueValidity (value) {
247
254
  const isDefined = !!value
248
255
  // For unique value, check if the value is in the options
249
- const valueInOptions = !useMultipleValuesSelect.value && valueOptions.value.includes(value)
256
+ const valueInOptions = !valueOptions.value || (!useMultipleValuesSelect.value && valueOptions.value.includes(value))
250
257
  // For multiple values, check if all values are in the options
251
- const valuesInOptions = useMultipleValuesSelect.value && !_.isEmpty(value) && !_.some(value, v => !valueOptions.value.includes(v))
258
+ const valuesInOptions = !valueOptions.value || (useMultipleValuesSelect.value && !_.isEmpty(value) && !_.some(value, v => !valueOptions.value.includes(v)))
252
259
  if (isDefined && (valueInOptions || valuesInOptions)) {
253
260
  hasValueErrors.value = false
254
261
  return true
@@ -391,44 +391,51 @@ function apply () {
391
391
  ? { pick: values.value.infobox.properties.map(property => property.value) }
392
392
  : false
393
393
 
394
- _.merge(updatedLayer, {
395
- isSelectable: display.isSelectable,
396
- leaflet: {
397
- isVisible: display.isVisible,
398
- cluster: display.clustering.leaflet.enabled
399
- ? { disableClusteringAtZoom: display.clustering.leaflet.value }
400
- : false,
401
- minZoom: display.zoom.leaflet.enabled
402
- ? display.zoom.leaflet.value.min
403
- : false,
404
- maxZoom: display.zoom.leaflet.enabled
405
- ? display.zoom.leaflet.value.max
406
- : false,
407
- opacity: display.opacity.enabled
408
- ? display.opacity.value
409
- : false,
410
- popup,
411
- tooltip,
412
- infobox
413
- },
414
- cesium: {
415
- isVisible: display.isVisible,
416
- cluster: display.clustering.cesium.enabled
417
- ? { pixelRange: display.clustering.cesium.value }
418
- : false,
419
- minZoom: display.zoom.cesium.enabled
420
- ? leafletToCesiumZoom(display.zoom.cesium.value.max)
421
- : false,
422
- maxZoom: display.zoom.cesium.enabled
423
- ? leafletToCesiumZoom(display.zoom.cesium.value.min)
424
- : false,
425
- popup,
426
- tooltip,
427
- infobox
428
- }
429
- })
430
-
431
394
  const layer = CurrentActivity.value.getLayerByName(props.layerName)
395
+ const is2DLayer = _.has(layer, 'leaflet')
396
+ const is3DLayer = _.has(layer, 'cesium')
397
+ const leaflet = {
398
+ isVisible: display.isVisible,
399
+ cluster: display.clustering.leaflet.enabled
400
+ ? { disableClusteringAtZoom: display.clustering.leaflet.value }
401
+ : false,
402
+ minZoom: display.zoom.leaflet.enabled
403
+ ? display.zoom.leaflet.value.min
404
+ : false,
405
+ maxZoom: display.zoom.leaflet.enabled
406
+ ? display.zoom.leaflet.value.max
407
+ : false,
408
+ opacity: display.opacity.enabled
409
+ ? display.opacity.value
410
+ : false,
411
+ popup,
412
+ tooltip,
413
+ infobox
414
+ }
415
+ const cesium = {
416
+ isVisible: display.isVisible,
417
+ cluster: display.clustering.cesium.enabled
418
+ ? { pixelRange: display.clustering.cesium.value }
419
+ : false,
420
+ minZoom: display.zoom.cesium.enabled
421
+ ? leafletToCesiumZoom(display.zoom.cesium.value.max)
422
+ : false,
423
+ maxZoom: display.zoom.cesium.enabled
424
+ ? leafletToCesiumZoom(display.zoom.cesium.value.min)
425
+ : false,
426
+ popup,
427
+ tooltip,
428
+ infobox
429
+ }
430
+ // Merge all updated values
431
+ // Ensure we don't create leaflet/cesium objects if the layer is not 2D/3D
432
+ _.merge(
433
+ updatedLayer,
434
+ { isSelectable: display.isSelectable },
435
+ is2DLayer ? { leaflet } : {},
436
+ is3DLayer ? { cesium } : {}
437
+ )
438
+
432
439
  if (isInMemoryLayer(layer)) {
433
440
  const previousName = _.get(layer, 'name', '')
434
441
  _.merge(layer, updatedLayer)
@@ -450,8 +457,11 @@ function apply () {
450
457
  })
451
458
  })
452
459
  // Add the objects that don't need to be dotified
453
- _.forEach(keys, (key) => {
454
- dotifiedLayer[key] = _.get(updatedLayer, key, false)
460
+ // Ensure not to add 2D properties to a 3D layer and vice versa
461
+ _.forEach(keys, (key, index) => {
462
+ if ((is2DLayer && index < 4) || (is3DLayer && index >= 4)) {
463
+ dotifiedLayer[key] = _.get(updatedLayer, key, false)
464
+ }
455
465
  })
456
466
 
457
467
  api.getService('catalog').patch(layer._id, dotifiedLayer)
@@ -34,6 +34,12 @@ export default {
34
34
  components: {
35
35
  KPanel
36
36
  },
37
+ props: {
38
+ wrapCircle: {
39
+ type: Boolean,
40
+ default: false
41
+ }
42
+ },
37
43
  data () {
38
44
  return {
39
45
  measureMode: 'measure-distance',
@@ -480,7 +486,7 @@ export default {
480
486
  state.distToCenter = distance(center, cursor, { units: 'kilometers' }) * 1000 // GeodesicCircle requires radius in m
481
487
  this.measureValue = this.formatDistance(state.distToCenter, 'm')
482
488
  if (!state.circleLayer) {
483
- state.circleLayer = L.geodesiccircle(this.measureCircle.center, { fill: true, steps: 360, radius: state.distToCenter })
489
+ state.circleLayer = L.geodesiccircle(this.measureCircle.center, { fill: true, wrap: this.wrapCircle, steps: 360, radius: state.distToCenter })
484
490
  state.lineLayer = L.polyline([state.center, event.latlng], { dashArray: [5, 5] })
485
491
  this.kActivity.map.addLayer(state.circleLayer)
486
492
  this.kActivity.map.addLayer(state.lineLayer)
@@ -7,7 +7,8 @@
7
7
  <script>
8
8
  import _ from 'lodash'
9
9
  import L from 'leaflet'
10
- import { api, utils as kCoreUtils } from '../../../core/client'
10
+ import sift from 'sift'
11
+ import { api, Context, utils as kCoreUtils } from '../../../core/client'
11
12
  import * as mapMixins from '../mixins/map'
12
13
  import * as mixins from '../mixins'
13
14
  import { useCatalog, useCurrentActivity } from '../composables'
@@ -66,10 +67,17 @@ export default {
66
67
  }
67
68
  },
68
69
  async refreshBaseLayer () {
69
- const layers = await this.getLayers()
70
- // Get first visible base layer
71
- if (layers.length > 0) {
72
- this.addLayer(layers[0])
70
+ // We get layers coming from global catalog first if any
71
+ let baseLayers = await this.getLayers()
72
+ // Then we get layers coming from contextual catalog if any
73
+ if (typeof this.getContextLayers === 'function') baseLayers = baseLayers.concat(await this.getContextLayers())
74
+ if (baseLayers.length > 0) {
75
+ const defaultLayer = _.find(baseLayers, sift({ 'leaflet.isVisible': true }))
76
+ // If no default layer defined use the first one
77
+ const baseLayer = (defaultLayer || baseLayers[0])
78
+ await this.addLayer(baseLayer)
79
+ // Ensure it is visible if not by default
80
+ await this.showLayer(baseLayer.name)
73
81
  }
74
82
  },
75
83
  getTimezoneMarker (feature, options) {
@@ -155,16 +163,28 @@ export default {
155
163
  const project = getActivityProject()
156
164
  // We expect the project object to expose the underlying API
157
165
  const planetApi = project && typeof project.getPlanetApi === 'function' ? project.getPlanetApi() : api
158
- // Use target catalog according to project and filtering options to get base layer
166
+ // Use target catalog(s) according to project and filtering options to get base layer
167
+ // Use global catalog
159
168
  const { getLayers } = useCatalog({
160
169
  project,
161
- layers: { type: 'BaseLayer', 'leaflet.isVisible': true },
162
- planetApi
170
+ layers: { type: 'BaseLayer' },
171
+ context: 'global'
163
172
  })
164
173
  // expose
165
- return {
174
+ const expose = {
166
175
  getLayers
167
176
  }
177
+ // Use local catalog if any
178
+ if (Context.get() && planetApi.hasService('catalog', Context.get())) {
179
+ const { getLayers: getContextLayers } = useCatalog({
180
+ project,
181
+ layers: { type: 'BaseLayer' },
182
+ context: Context.get()
183
+ })
184
+ Object.assign(expose, { getContextLayers })
185
+ }
186
+
187
+ return expose
168
188
  }
169
189
  }
170
190
  </script>
@@ -6,7 +6,7 @@
6
6
  <div>
7
7
  <slot name="header">
8
8
  <KPanel
9
- :content="header"
9
+ :content="panelHeader"
10
10
  :class="headerClass"
11
11
  />
12
12
  <q-separator inset v-if="header"/>
@@ -79,7 +79,7 @@
79
79
  <slot name="footer">
80
80
  <q-separator inset v-if="footer"/>
81
81
  <KPanel
82
- :content="footer"
82
+ :content="panelFooter"
83
83
  :class="footerClass"
84
84
  />
85
85
  </slot>
@@ -98,7 +98,7 @@ export default {
98
98
  <script setup>
99
99
  import _ from 'lodash'
100
100
  import sift from 'sift'
101
- import { ref, watchEffect } from 'vue'
101
+ import { ref, computed, watchEffect } from 'vue'
102
102
  import { utils as coreUtils, i18n } from '../../../../core/client'
103
103
  import { useCurrentActivity, useProject } from '../../composables'
104
104
  import { getLayersByCategory } from '../../utils'
@@ -176,6 +176,18 @@ const layersByCategory = ref({})
176
176
  const filteredOrphanLayers = ref([])
177
177
  const draggedIndex = ref(null)
178
178
 
179
+ // Computed
180
+ const panelHeader = computed(() => {
181
+ let header = _.cloneDeep(props.header)
182
+ header = coreUtils.bindContent(header, CurrentActivity.value)
183
+ return header
184
+ })
185
+ const panelFooter = computed(() => {
186
+ let footer = _.cloneDeep(props.footer)
187
+ footer = coreUtils.bindContent(footer, CurrentActivity.value)
188
+ return footer
189
+ })
190
+
179
191
  // Watch
180
192
  watchEffect(() => { refresh() })
181
193
 
@@ -187,14 +199,17 @@ function getCategoryIcon (category) {
187
199
  return _.get(category, 'icon.name', _.get(category, 'icon'), 'las la-bars')
188
200
  }
189
201
  function isCategoryVisible (category) {
190
- const options = category.options || category
191
202
  // Show a built-in category only if it has some layers.
192
203
  // Indeed, depending on the app configuration, none might be available for this category.
193
204
  // User-defined categories are visible by default, even if empty,
194
205
  // except if used inside a project as in this case having no layers means we don't want to use this category.
195
206
  // App might also force to hide it anyway with the hideIfEmpty option.
196
207
  const isEmpty = (layersByCategory.value[category.name].length === 0)
197
- return (isEmpty ? !_.get(options, 'hideIfEmpty', !category._id || hasProject()) : true)
208
+ let hideIfEmpty = !category._id || hasProject() || _.get(CurrentActivity.value, 'project')
209
+ if (category.options && _.has(category.options, 'hideIfEmpty')) hideIfEmpty = _.get(category.options, 'hideIfEmpty')
210
+ // Backward compatibility with KDK version <= 2.7 where it could be stored at root level and not in options subobject
211
+ else if (_.has(category, 'hideIfEmpty')) hideIfEmpty = _.get(category, 'hideIfEmpty')
212
+ return (isEmpty ? !hideIfEmpty : true)
198
213
  }
199
214
  function refresh () {
200
215
  const { layers, layerCategories, orphanLayers } = CurrentActivity.value
@@ -222,20 +237,15 @@ async function onOrphanLayerUpdated (targetIndex, draggedIndex) {
222
237
  const removedLayers = filteredOrphanLayers.value.splice(draggedIndex, 1)
223
238
  // As orphan layers are filtered we might have a mismatch between activity list index and panel index
224
239
  // so that we find the layer by name in the activity list to perform the same reordering
225
- let orphanLayer
226
- draggedIndex = _.findIndex(orphanLayers, orphanLayer => orphanLayer.name === layer.name)
227
- if (draggedIndex >= 0) {
228
- orphanLayer = orphanLayers[draggedIndex]
229
- orphanLayers.splice(draggedIndex, 1)
230
- }
240
+ const unfilteredDraggedIndex = _.findIndex(orphanLayers, orphanLayer => orphanLayer.name === layer.name)
241
+ const unfilteredTargetIndex = (targetLayer ? _.findIndex(orphanLayers, orphanLayer => orphanLayer.name === targetLayer.name) : -1)
242
+ orphanLayers.splice(unfilteredDraggedIndex, 1)
243
+
231
244
  // If not -1 it means the orphan layer has been moved within the orphan layers list.
232
245
  // Otherwise it has been moved to another category so that we only need to remove it from the list
233
246
  if ((removedLayers.length > 0) && targetLayer) {
234
247
  filteredOrphanLayers.value.splice(targetIndex, 0, removedLayers[0])
235
- // As orphan layers are filtered we might have a mismatch between activity list index and panel index
236
- // so that we find the layer by name in the activity list to perform the same reordering
237
- targetIndex = _.findIndex(orphanLayers, orphanLayer => orphanLayer.name === targetLayer.name)
238
- if (orphanLayer && (targetIndex >= 0)) orphanLayers.splice(targetIndex, 0, orphanLayer)
248
+ orphanLayers.splice(unfilteredTargetIndex, 0, removedLayers[0])
239
249
  }
240
250
  await updateOrphanLayersOrder(filteredOrphanLayers.value.map(layer => layer?._id || layer?.name), layer)
241
251
  }
@@ -251,7 +261,7 @@ async function onDrop (event, targetIndex) {
251
261
  const sourceCategoryId = event.dataTransfer.getData('categoryID')
252
262
  const layerName = event.dataTransfer.getData('layerName')
253
263
  const layers = _.flatten(_.values(layersByCategory.value)).concat(filteredOrphanLayers.value)
254
- const layer = layers.find(layer => layer.name === layerName)
264
+ const layer = layers.find(layer => layer?.name === layerName)
255
265
  const draggedLayerIndex = event.dataTransfer.getData('draggedIndex')
256
266
  if (layerName && layerName.length > 0) { // drag source is layer: change layer category
257
267
  const currentCategoryLayers = filteredCategories.value[targetIndex]?.layers
@@ -18,8 +18,8 @@
18
18
  multiple
19
19
  clearable
20
20
  @filter="filter"
21
- @add="toggleLayer"
22
- @remove="toggleLayer"
21
+ @add="addLayer"
22
+ @remove="removeLayer"
23
23
  @clear="clear"
24
24
  >
25
25
  <template v-slot:prepend>
@@ -94,6 +94,17 @@ const filteredLayers = computed(() =>
94
94
  )
95
95
 
96
96
  // Functions
97
+ function addLayer (layerId) {
98
+ const layer = props.layers.find((l) => l._id === layerId.value)
99
+ if (layer?.isVisible) return
100
+ toggleLayer(layerId)
101
+ }
102
+ function removeLayer (layerId) {
103
+ const layer = props.layers.find((l) => l._id === layerId.value)
104
+ if (layer?.isVisible) {
105
+ toggleLayer(layerId)
106
+ }
107
+ }
97
108
  function toggleLayer (layerId) {
98
109
  const layer = props.layers.find((l) => l._id === layerId.value)
99
110
  const toggleAction = _.find(layer.actions, { id: 'toggle' })
@@ -21,10 +21,11 @@
21
21
  import _ from 'lodash'
22
22
  import logger from 'loglevel'
23
23
  import { ref, computed } from 'vue'
24
- import { utils, i18n, api, LocalCache, Store } from '../../../../core/client'
24
+ import { utils, i18n, api, LocalCache, Context } from '../../../../core/client'
25
25
  import { KGrid } from '../../../../core/client/components'
26
26
  import { useCurrentActivity, useProject } from '../../composables'
27
27
  import { cacheView, uncacheView } from '../../utils/utils.offline.js'
28
+ import { getViewsProjectQuery } from '../../utils/utils.project.js'
28
29
  import { Dialog, Notify } from 'quasar'
29
30
 
30
31
  // Data
@@ -41,7 +42,7 @@ const baseQuery = computed(() => {
41
42
  })
42
43
  const filterQuery = computed(() => {
43
44
  const query = {}
44
- if (project.value) Object.assign(query, { _id: { $in: _.map(project.value.views, '_id') } })
45
+ if (project.value) Object.assign(query, getViewsProjectQuery(project.value))
45
46
  if (!_.isEmpty(searchString.value)) {
46
47
  Object.assign(query, { name: { $regex: searchString.value } })
47
48
  }
@@ -172,7 +173,7 @@ async function onViewSelected (view, action) {
172
173
  spinner: true
173
174
  })
174
175
  await cacheView(view, getProjectLayers(), {
175
- contextId: Store.get('context'),
176
+ contextId: Context.get(),
176
177
  ...values
177
178
  })
178
179
  view.isCached = true
@@ -190,7 +191,7 @@ async function onViewSelected (view, action) {
190
191
  spinner: true
191
192
  })
192
193
  await uncacheView(view, getProjectLayers(), {
193
- contextId: Store.get('context')
194
+ contextId: Context.get()
194
195
  })
195
196
  view.isCached = false
196
197
  dismiss()