@kalisio/kdk 2.5.3 → 2.6.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 (545) hide show
  1. package/.github/workflows/main.yaml +35 -6
  2. package/client.globe.js +8 -0
  3. package/client.js +8 -0
  4. package/client.map.js +8 -0
  5. package/core/api/hooks/hooks.push.js +3 -2
  6. package/core/api/hooks/hooks.tags.js +56 -0
  7. package/core/api/models/tags.model.mongodb.js +8 -0
  8. package/core/api/services/index.js +33 -2
  9. package/core/api/services/tags/tags.hooks.js +47 -0
  10. package/core/client/api.js +5 -5
  11. package/core/client/components/KActivity.vue +3 -2
  12. package/core/client/components/KChip.vue +2 -2
  13. package/core/client/components/KEditor.vue +3 -1
  14. package/core/client/components/KFollower.vue +4 -4
  15. package/core/client/components/KStore.vue +1 -1
  16. package/core/client/components/KTab.vue +20 -7
  17. package/core/client/components/account/KProfile.vue +9 -25
  18. package/core/client/components/action/KAction.vue +10 -10
  19. package/core/client/components/action/KToggleFullscreenAction.vue +2 -11
  20. package/core/client/components/app/KHome.vue +3 -2
  21. package/core/client/components/collection/KFilter.vue +5 -4
  22. package/core/client/components/collection/KGrid.vue +5 -1
  23. package/core/client/components/collection/KItemsFilter.vue +47 -0
  24. package/core/client/components/collection/KItemsSorter.vue +42 -0
  25. package/core/client/components/collection/KScrollDown.vue +2 -2
  26. package/core/client/components/collection/KSearchFilterControl.vue +3 -2
  27. package/core/client/components/collection/KSorter.vue +33 -37
  28. package/core/client/components/collection/KTagsFilterControl.vue +14 -40
  29. package/core/client/components/collection/KTagsFilterView.vue +10 -45
  30. package/core/client/components/collection/KTimeFilterControl.vue +6 -7
  31. package/core/client/components/collection/KTimeFilterView.vue +13 -22
  32. package/core/client/components/collection/KTimeLine.vue +18 -9
  33. package/core/client/components/form/KColorField.vue +13 -6
  34. package/core/client/components/form/KColorScaleField.vue +7 -12
  35. package/core/client/components/form/KFileField.vue +118 -89
  36. package/core/client/components/form/KForm.vue +30 -18
  37. package/core/client/components/form/KIconField.vue +4 -1
  38. package/core/client/components/form/KNumberField.vue +9 -2
  39. package/core/client/components/form/KSelectField.vue +1 -4
  40. package/core/client/components/form/KTagField.vue +229 -0
  41. package/core/client/components/form/KTextField.vue +4 -0
  42. package/core/client/components/form/KTextareaField.vue +3 -1
  43. package/core/client/components/input/KShapePicker.vue +3 -3
  44. package/core/client/components/layout/KFab.vue +32 -20
  45. package/core/client/components/layout/KPage.vue +11 -6
  46. package/core/client/components/layout/KWindow.vue +5 -0
  47. package/core/client/components/media/index.js +2 -6
  48. package/core/client/components/menu/KMenu.vue +12 -10
  49. package/core/client/components/menu/KSubMenu.vue +12 -12
  50. package/core/client/components/messages/KMessageCard.vue +13 -12
  51. package/core/client/components/messages/KMessageComposer.vue +13 -9
  52. package/core/client/components/messages/KMessagesTimeLine.vue +16 -8
  53. package/core/client/components/tags/KTagFilter.vue +99 -0
  54. package/core/client/components/tags/KTagItem.vue +65 -0
  55. package/core/client/components/tags/KTagManager.vue +198 -0
  56. package/core/client/components/tags/KTagSelection.vue +82 -0
  57. package/core/client/components/time/KDate.vue +3 -17
  58. package/core/client/components/time/KDateTime.vue +1 -1
  59. package/core/client/components/time/KTime.vue +0 -4
  60. package/core/client/composables/collection-filter.js +41 -2
  61. package/core/client/composables/collection.js +3 -3
  62. package/core/client/composables/index.js +1 -0
  63. package/core/client/composables/pwa.js +13 -0
  64. package/core/client/composables/session.js +7 -8
  65. package/core/client/composables/user.js +36 -0
  66. package/core/client/directives/index.js +1 -0
  67. package/core/client/directives/v-drop-file.js +174 -0
  68. package/core/client/document.js +2 -1
  69. package/core/client/exporter.js +17 -3
  70. package/core/client/i18n/core_en.json +34 -7
  71. package/core/client/i18n/core_fr.json +36 -9
  72. package/core/client/i18n.js +26 -11
  73. package/core/client/layout.js +5 -5
  74. package/core/client/mixins/mixin.base-activity.js +8 -5
  75. package/core/client/mixins/mixin.base-editor.js +2 -1
  76. package/core/client/mixins/mixin.base-field.js +3 -2
  77. package/core/client/mixins/mixin.base-item.js +12 -10
  78. package/core/client/mixins/mixin.service.js +3 -1
  79. package/core/client/platform.js +0 -3
  80. package/core/client/readers/reader.json.js +2 -2
  81. package/core/client/utils/index.js +2 -0
  82. package/core/client/utils/utils.collection.js +6 -6
  83. package/core/client/utils/utils.colors.js +46 -19
  84. package/core/client/utils/utils.files.js +19 -0
  85. package/core/client/utils/utils.locale.js +13 -17
  86. package/core/client/utils/utils.services.js +27 -0
  87. package/core/client/utils/utils.shapes.js +2 -2
  88. package/core/client/utils/utils.tags.js +17 -0
  89. package/core/client/utils/utils.tours.js +31 -0
  90. package/core/common/permissions.js +3 -0
  91. package/core/common/schemas/tags.update.json +35 -0
  92. package/core/common/schemas/users.update-profile.json +1 -1
  93. package/core/common/utils.js +5 -5
  94. package/extras/configs/panes.top.js +11 -0
  95. package/extras/configs/stickies.js +1 -1
  96. package/extras/configs/widgets.left.js +13 -1
  97. package/extras/libs/jsts.min.js +8 -0
  98. package/{test/client/core/account.js → extras/tests/core/account.mjs} +4 -4
  99. package/extras/tests/core/api.mjs +114 -0
  100. package/{test/client/core/collection.js → extras/tests/core/collection.mjs} +8 -8
  101. package/{test/client/core/dialogs.js → extras/tests/core/dialogs.mjs} +1 -1
  102. package/extras/tests/core/index.mjs +9 -0
  103. package/{test/client/core/layout.js → extras/tests/core/layout.mjs} +7 -3
  104. package/{test/client/core/runner.js → extras/tests/core/runner.mjs} +3 -3
  105. package/{test/client/core/screens.js → extras/tests/core/screens.mjs} +1 -1
  106. package/{test/client/core/utils.js → extras/tests/core/utils.mjs} +79 -26
  107. package/extras/tests/index.mjs +4 -0
  108. package/{test/client/map/api.js → extras/tests/map/api.mjs} +1 -1
  109. package/{test/client/map/catalog.js → extras/tests/map/catalog.mjs} +18 -18
  110. package/{test/client/map/controls.js → extras/tests/map/controls.mjs} +3 -3
  111. package/extras/tests/map/index.mjs +5 -0
  112. package/{test/client/map/time.js → extras/tests/map/time.mjs} +3 -3
  113. package/{test/client/map/utils.js → extras/tests/map/utils.mjs} +6 -5
  114. package/extras/tours/fab.js +36 -0
  115. package/extras/tours/layout.js +49 -0
  116. package/extras/tours/pane.left.js +78 -0
  117. package/extras/tours/pane.right.js +145 -0
  118. package/extras/tours/pane.top.js +239 -0
  119. package/map/api/config/layers.cjs +28 -13
  120. package/map/api/hooks/hooks.query.js +12 -7
  121. package/map/api/models/catalog.model.mongodb.js +17 -6
  122. package/map/api/services/catalog/catalog.hooks.js +1 -1
  123. package/map/api/services/index.js +18 -1
  124. package/map/client/cesium/utils/utils.cesium.js +25 -65
  125. package/map/client/cesium/utils/utils.features.js +1 -0
  126. package/map/client/cesium/utils/utils.geojson.js +1 -0
  127. package/map/client/cesium/utils/utils.style.js +7 -6
  128. package/map/client/components/KFeatureEditor.vue +3 -3
  129. package/map/client/components/KFeaturesChart.vue +4 -4
  130. package/map/client/components/KFeaturesFilterEditor.vue +19 -13
  131. package/map/client/components/KFeaturesFilterManager.vue +7 -4
  132. package/map/client/components/KFeaturesTable.vue +2 -2
  133. package/map/client/components/KLayerEditor.vue +6 -6
  134. package/map/client/components/KMeasureTool.vue +2 -1
  135. package/map/client/components/catalog/KBaseLayersSelector.vue +1 -1
  136. package/map/client/components/catalog/KCategoryItem.vue +15 -1
  137. package/map/client/components/catalog/KConnectLayer.vue +2 -2
  138. package/map/client/components/catalog/KCreateView.vue +3 -2
  139. package/map/client/components/catalog/KFilteredLayerItem.vue +26 -6
  140. package/map/client/components/catalog/KImportLayer.vue +6 -3
  141. package/map/client/components/catalog/KLayerCategories.vue +6 -6
  142. package/map/client/components/catalog/KLayerItem.vue +12 -2
  143. package/map/client/components/catalog/KLayersList.vue +180 -0
  144. package/map/client/components/catalog/KLayersPanel.vue +146 -36
  145. package/map/client/components/catalog/KLayersSelector.vue +96 -48
  146. package/map/client/components/catalog/KProjectEditor.vue +0 -9
  147. package/map/client/components/catalog/KProjectSelector.vue +3 -2
  148. package/map/client/components/catalog/KProjectsPanel.vue +23 -8
  149. package/map/client/components/catalog/KViewsPanel.vue +18 -8
  150. package/map/client/components/catalog/KWeatherLayersSelector.vue +3 -3
  151. package/map/client/components/form/KDirectionField.vue +3 -6
  152. package/map/client/components/form/KLayerCategoryField.vue +2 -2
  153. package/map/client/components/form/KOwsServiceField.vue +25 -24
  154. package/map/client/components/form/KSelectLayersField.vue +4 -4
  155. package/map/client/components/form/KSelectViewsField.vue +4 -4
  156. package/map/client/components/legend/KLayerLegend.vue +11 -2
  157. package/map/client/components/legend/KLegend.vue +44 -51
  158. package/map/client/components/location/KLocationCardSection.vue +6 -7
  159. package/map/client/components/location/KLocationMap.vue +23 -13
  160. package/map/client/components/stickies/KPosition.vue +5 -0
  161. package/map/client/components/styles/KLayerStyleAction.vue +59 -12
  162. package/map/client/components/styles/KStyleEditor.vue +71 -8
  163. package/map/client/components/styles/KStyleEditorSection.vue +82 -33
  164. package/map/client/components/styles/KStyleManager.vue +119 -59
  165. package/map/client/components/styles/KStylePreview.vue +9 -25
  166. package/map/client/components/styles/KStylePreviewItem.vue +22 -1
  167. package/map/client/components/tools/KSearchTool.vue +1 -1
  168. package/map/client/components/widget/KElevationProfile.vue +20 -17
  169. package/map/client/components/widget/KInformationBox.vue +5 -5
  170. package/map/client/components/widget/KMapillaryViewer.vue +2 -1
  171. package/map/client/components/widget/KTimeSeries.vue +11 -9
  172. package/map/client/globe.js +2 -0
  173. package/map/client/i18n/map_en.json +29 -7
  174. package/map/client/i18n/map_fr.json +29 -7
  175. package/map/client/leaflet/GradientPath.js +61 -24
  176. package/map/client/leaflet/ShapeMarker.js +12 -5
  177. package/map/client/leaflet/TiledMeshLayer.js +3 -3
  178. package/map/client/leaflet/utils/utils.geojson.js +66 -8
  179. package/map/client/leaflet/utils/utils.style.js +14 -15
  180. package/map/client/mixins/globe/mixin.base-globe.js +181 -34
  181. package/map/client/mixins/globe/mixin.file-layers.js +3 -0
  182. package/map/client/mixins/globe/mixin.geojson-layers.js +179 -31
  183. package/map/client/mixins/globe/mixin.opendap-layers.js +2 -1
  184. package/map/client/mixins/globe/mixin.style.js +23 -1
  185. package/map/client/mixins/globe/mixin.tooltip.js +14 -2
  186. package/map/client/mixins/map/mixin.base-map.js +146 -58
  187. package/map/client/mixins/map/mixin.edit-layers.js +18 -15
  188. package/map/client/mixins/map/mixin.geojson-layers.js +181 -106
  189. package/map/client/mixins/map/mixin.heatmap-layers.js +3 -2
  190. package/map/client/mixins/map/mixin.map-activity.js +6 -1
  191. package/map/client/mixins/map/mixin.mapillary-layers.js +2 -1
  192. package/map/client/mixins/map/mixin.pmtiles-layers.js +3 -3
  193. package/map/client/mixins/map/mixin.tiled-mesh-layers.js +3 -2
  194. package/map/client/mixins/map/mixin.tiled-wind-layers.js +3 -2
  195. package/map/client/mixins/mixin.activity.js +197 -51
  196. package/map/client/mixins/mixin.context.js +11 -11
  197. package/map/client/mixins/mixin.feature-service.js +11 -9
  198. package/map/client/mixins/mixin.weacast.js +5 -3
  199. package/map/client/readers/reader.geojson.js +3 -1
  200. package/map/client/utils/utils.capture.js +3 -3
  201. package/map/client/utils/utils.catalog.js +9 -5
  202. package/map/client/utils/utils.features.js +120 -54
  203. package/map/client/utils/utils.js +25 -10
  204. package/map/client/utils/utils.layers.js +148 -24
  205. package/map/client/utils/utils.location.js +26 -9
  206. package/map/client/utils/utils.schema.js +2 -1
  207. package/map/client/utils/utils.style.js +53 -9
  208. package/map/common/geotiff-grid-source.js +1 -3
  209. package/map/common/opendap-utils.js +0 -1
  210. package/map/common/tms-utils.js +0 -1
  211. package/map/common/wcs-utils.js +0 -1
  212. package/map/common/wfs-utils.js +0 -1
  213. package/map/common/wms-utils.js +7 -1
  214. package/map/common/wmts-utils.js +0 -1
  215. package/package.json +12 -12
  216. package/scripts/init_runner.sh +3 -3
  217. package/scripts/kash/CHANGELOG.md +27 -0
  218. package/scripts/kash/kash.sh +556 -237
  219. package/scripts/kash/scripts/run_tests.sh +44 -5
  220. package/scripts/setup_workspace.sh +23 -13
  221. package/test/api/core/config/default.cjs +2 -1
  222. package/test/api/core/tags.test.js +62 -0
  223. package/test/api/map/config/default.cjs +2 -1
  224. package/test/api/map/config/layers.json +9 -0
  225. package/test/api/map/data/openradiation.json +13811 -0
  226. package/test/api/map/grid-sources.test.js +1 -3
  227. package/test/api/map/index.test.js +60 -1
  228. package/test/api/map/style.test.js +30 -1
  229. package/test.api.js +1 -1
  230. package/vite/App.vue +18 -0
  231. package/vite/AppWithGlobe.vue +84 -0
  232. package/vite/GlobeActivity.vue +58 -0
  233. package/vite/MapActivity.vue +63 -0
  234. package/vite/MapActivityWithGlobe.vue +63 -0
  235. package/vite/README.md +169 -0
  236. package/vite/config.js +221 -0
  237. package/vite/index_with_globe.html +50 -0
  238. package/vite/index_with_map.html +50 -0
  239. package/vite/package.json +173 -0
  240. package/vite/quasar.variables.scss +17 -0
  241. package/vite/vite.config.js +166 -0
  242. package/vite/yarn.lock +11641 -0
  243. package/core/client/components/media/KImageViewer.vue +0 -68
  244. package/core/client/components/media/KMarkdownViewer.vue +0 -55
  245. package/core/client/components/media/KMediaBrowser.vue +0 -301
  246. package/coverage/base.css +0 -224
  247. package/coverage/block-navigation.js +0 -87
  248. package/coverage/core/api/application.js.html +0 -1870
  249. package/coverage/core/api/authentication.js.html +0 -874
  250. package/coverage/core/api/db.js.html +0 -793
  251. package/coverage/core/api/hooks/hooks.authentication.js.html +0 -139
  252. package/coverage/core/api/hooks/hooks.authorisations.js.html +0 -958
  253. package/coverage/core/api/hooks/hooks.groups.js.html +0 -229
  254. package/coverage/core/api/hooks/hooks.logger.js.html +0 -163
  255. package/coverage/core/api/hooks/hooks.model.js.html +0 -967
  256. package/coverage/core/api/hooks/hooks.organisations.js.html +0 -541
  257. package/coverage/core/api/hooks/hooks.push.js.html +0 -265
  258. package/coverage/core/api/hooks/hooks.query.js.html +0 -862
  259. package/coverage/core/api/hooks/hooks.schemas.js.html +0 -298
  260. package/coverage/core/api/hooks/hooks.service.js.html +0 -319
  261. package/coverage/core/api/hooks/hooks.storage.js.html +0 -193
  262. package/coverage/core/api/hooks/hooks.users.js.html +0 -595
  263. package/coverage/core/api/hooks/index.html +0 -266
  264. package/coverage/core/api/hooks/index.js.html +0 -115
  265. package/coverage/core/api/index.html +0 -176
  266. package/coverage/core/api/index.js.html +0 -148
  267. package/coverage/core/api/marshall.js.html +0 -448
  268. package/coverage/core/api/models/groups.model.mongodb.js.html +0 -109
  269. package/coverage/core/api/models/index.html +0 -131
  270. package/coverage/core/api/models/messages.model.mongodb.js.html +0 -121
  271. package/coverage/core/api/models/organisations.model.mongodb.js.html +0 -94
  272. package/coverage/core/api/models/tags.model.mongodb.js.html +0 -115
  273. package/coverage/core/api/models/users.model.mongodb.js.html +0 -115
  274. package/coverage/core/api/services/account/account.hooks.js.html +0 -208
  275. package/coverage/core/api/services/account/account.service.js.html +0 -436
  276. package/coverage/core/api/services/account/index.html +0 -131
  277. package/coverage/core/api/services/authorisations/authorisations.hooks.js.html +0 -184
  278. package/coverage/core/api/services/authorisations/authorisations.service.js.html +0 -520
  279. package/coverage/core/api/services/authorisations/index.html +0 -131
  280. package/coverage/core/api/services/databases/databases.hooks.js.html +0 -193
  281. package/coverage/core/api/services/databases/databases.service.js.html +0 -100
  282. package/coverage/core/api/services/databases/index.html +0 -131
  283. package/coverage/core/api/services/groups/groups.hooks.js.html +0 -178
  284. package/coverage/core/api/services/groups/index.html +0 -116
  285. package/coverage/core/api/services/import-export/import-export.hooks.js.html +0 -184
  286. package/coverage/core/api/services/import-export/import-export.service.js.html +0 -118
  287. package/coverage/core/api/services/import-export/index.html +0 -131
  288. package/coverage/core/api/services/index.html +0 -116
  289. package/coverage/core/api/services/index.js.html +0 -532
  290. package/coverage/core/api/services/mailer/index.html +0 -131
  291. package/coverage/core/api/services/mailer/mailer.hooks.js.html +0 -190
  292. package/coverage/core/api/services/mailer/mailer.service.js.html +0 -118
  293. package/coverage/core/api/services/messages/index.html +0 -116
  294. package/coverage/core/api/services/messages/messages.hooks.js.html +0 -202
  295. package/coverage/core/api/services/organisations/index.html +0 -131
  296. package/coverage/core/api/services/organisations/organisations.hooks.js.html +0 -178
  297. package/coverage/core/api/services/organisations/organisations.service.js.html +0 -343
  298. package/coverage/core/api/services/push/index.html +0 -131
  299. package/coverage/core/api/services/push/push.hooks.js.html +0 -190
  300. package/coverage/core/api/services/push/push.service.js.html +0 -121
  301. package/coverage/core/api/services/storage/index.html +0 -131
  302. package/coverage/core/api/services/storage/storage.hooks.js.html +0 -190
  303. package/coverage/core/api/services/storage/storage.service.js.html +0 -172
  304. package/coverage/core/api/services/tags/index.html +0 -116
  305. package/coverage/core/api/services/tags/tags.hooks.js.html +0 -178
  306. package/coverage/core/api/services/users/index.html +0 -131
  307. package/coverage/core/api/services/users/users.hooks.js.html +0 -310
  308. package/coverage/core/api/services/users/users.service.js.html +0 -100
  309. package/coverage/core/api/utils.js.html +0 -118
  310. package/coverage/core/common/errors.js.html +0 -88
  311. package/coverage/core/common/index.html +0 -191
  312. package/coverage/core/common/index.js.html +0 -115
  313. package/coverage/core/common/permissions.js.html +0 -733
  314. package/coverage/core/common/schema.js.html +0 -190
  315. package/coverage/core/common/utils.js.html +0 -226
  316. package/coverage/core/common/utils.offline.js.html +0 -199
  317. package/coverage/favicon.png +0 -0
  318. package/coverage/index.html +0 -476
  319. package/coverage/lcov-report/base.css +0 -224
  320. package/coverage/lcov-report/block-navigation.js +0 -87
  321. package/coverage/lcov-report/core/api/application.js.html +0 -1870
  322. package/coverage/lcov-report/core/api/authentication.js.html +0 -874
  323. package/coverage/lcov-report/core/api/db.js.html +0 -793
  324. package/coverage/lcov-report/core/api/hooks/hooks.authentication.js.html +0 -139
  325. package/coverage/lcov-report/core/api/hooks/hooks.authorisations.js.html +0 -958
  326. package/coverage/lcov-report/core/api/hooks/hooks.groups.js.html +0 -229
  327. package/coverage/lcov-report/core/api/hooks/hooks.logger.js.html +0 -163
  328. package/coverage/lcov-report/core/api/hooks/hooks.model.js.html +0 -967
  329. package/coverage/lcov-report/core/api/hooks/hooks.organisations.js.html +0 -541
  330. package/coverage/lcov-report/core/api/hooks/hooks.push.js.html +0 -265
  331. package/coverage/lcov-report/core/api/hooks/hooks.query.js.html +0 -862
  332. package/coverage/lcov-report/core/api/hooks/hooks.schemas.js.html +0 -298
  333. package/coverage/lcov-report/core/api/hooks/hooks.service.js.html +0 -319
  334. package/coverage/lcov-report/core/api/hooks/hooks.storage.js.html +0 -193
  335. package/coverage/lcov-report/core/api/hooks/hooks.users.js.html +0 -595
  336. package/coverage/lcov-report/core/api/hooks/index.html +0 -266
  337. package/coverage/lcov-report/core/api/hooks/index.js.html +0 -115
  338. package/coverage/lcov-report/core/api/index.html +0 -176
  339. package/coverage/lcov-report/core/api/index.js.html +0 -148
  340. package/coverage/lcov-report/core/api/marshall.js.html +0 -448
  341. package/coverage/lcov-report/core/api/models/groups.model.mongodb.js.html +0 -109
  342. package/coverage/lcov-report/core/api/models/index.html +0 -131
  343. package/coverage/lcov-report/core/api/models/messages.model.mongodb.js.html +0 -121
  344. package/coverage/lcov-report/core/api/models/organisations.model.mongodb.js.html +0 -94
  345. package/coverage/lcov-report/core/api/models/tags.model.mongodb.js.html +0 -115
  346. package/coverage/lcov-report/core/api/models/users.model.mongodb.js.html +0 -115
  347. package/coverage/lcov-report/core/api/services/account/account.hooks.js.html +0 -208
  348. package/coverage/lcov-report/core/api/services/account/account.service.js.html +0 -436
  349. package/coverage/lcov-report/core/api/services/account/index.html +0 -131
  350. package/coverage/lcov-report/core/api/services/authorisations/authorisations.hooks.js.html +0 -184
  351. package/coverage/lcov-report/core/api/services/authorisations/authorisations.service.js.html +0 -520
  352. package/coverage/lcov-report/core/api/services/authorisations/index.html +0 -131
  353. package/coverage/lcov-report/core/api/services/databases/databases.hooks.js.html +0 -193
  354. package/coverage/lcov-report/core/api/services/databases/databases.service.js.html +0 -100
  355. package/coverage/lcov-report/core/api/services/databases/index.html +0 -131
  356. package/coverage/lcov-report/core/api/services/groups/groups.hooks.js.html +0 -178
  357. package/coverage/lcov-report/core/api/services/groups/index.html +0 -116
  358. package/coverage/lcov-report/core/api/services/import-export/import-export.hooks.js.html +0 -184
  359. package/coverage/lcov-report/core/api/services/import-export/import-export.service.js.html +0 -118
  360. package/coverage/lcov-report/core/api/services/import-export/index.html +0 -131
  361. package/coverage/lcov-report/core/api/services/index.html +0 -116
  362. package/coverage/lcov-report/core/api/services/index.js.html +0 -532
  363. package/coverage/lcov-report/core/api/services/mailer/index.html +0 -131
  364. package/coverage/lcov-report/core/api/services/mailer/mailer.hooks.js.html +0 -190
  365. package/coverage/lcov-report/core/api/services/mailer/mailer.service.js.html +0 -118
  366. package/coverage/lcov-report/core/api/services/messages/index.html +0 -116
  367. package/coverage/lcov-report/core/api/services/messages/messages.hooks.js.html +0 -202
  368. package/coverage/lcov-report/core/api/services/organisations/index.html +0 -131
  369. package/coverage/lcov-report/core/api/services/organisations/organisations.hooks.js.html +0 -178
  370. package/coverage/lcov-report/core/api/services/organisations/organisations.service.js.html +0 -343
  371. package/coverage/lcov-report/core/api/services/push/index.html +0 -131
  372. package/coverage/lcov-report/core/api/services/push/push.hooks.js.html +0 -190
  373. package/coverage/lcov-report/core/api/services/push/push.service.js.html +0 -121
  374. package/coverage/lcov-report/core/api/services/storage/index.html +0 -131
  375. package/coverage/lcov-report/core/api/services/storage/storage.hooks.js.html +0 -190
  376. package/coverage/lcov-report/core/api/services/storage/storage.service.js.html +0 -172
  377. package/coverage/lcov-report/core/api/services/tags/index.html +0 -116
  378. package/coverage/lcov-report/core/api/services/tags/tags.hooks.js.html +0 -178
  379. package/coverage/lcov-report/core/api/services/users/index.html +0 -131
  380. package/coverage/lcov-report/core/api/services/users/users.hooks.js.html +0 -310
  381. package/coverage/lcov-report/core/api/services/users/users.service.js.html +0 -100
  382. package/coverage/lcov-report/core/api/utils.js.html +0 -118
  383. package/coverage/lcov-report/core/common/errors.js.html +0 -88
  384. package/coverage/lcov-report/core/common/index.html +0 -191
  385. package/coverage/lcov-report/core/common/index.js.html +0 -115
  386. package/coverage/lcov-report/core/common/permissions.js.html +0 -733
  387. package/coverage/lcov-report/core/common/schema.js.html +0 -190
  388. package/coverage/lcov-report/core/common/utils.js.html +0 -226
  389. package/coverage/lcov-report/core/common/utils.offline.js.html +0 -199
  390. package/coverage/lcov-report/favicon.png +0 -0
  391. package/coverage/lcov-report/index.html +0 -476
  392. package/coverage/lcov-report/map/api/hooks/hooks.catalog.js.html +0 -553
  393. package/coverage/lcov-report/map/api/hooks/hooks.features.js.html +0 -397
  394. package/coverage/lcov-report/map/api/hooks/hooks.query.js.html +0 -1294
  395. package/coverage/lcov-report/map/api/hooks/index.html +0 -161
  396. package/coverage/lcov-report/map/api/hooks/index.js.html +0 -94
  397. package/coverage/lcov-report/map/api/index.html +0 -131
  398. package/coverage/lcov-report/map/api/index.js.html +0 -139
  399. package/coverage/lcov-report/map/api/marshall.js.html +0 -178
  400. package/coverage/lcov-report/map/api/models/alerts.model.mongodb.js.html +0 -106
  401. package/coverage/lcov-report/map/api/models/catalog.model.mongodb.js.html +0 -169
  402. package/coverage/lcov-report/map/api/models/features.model.mongodb.js.html +0 -196
  403. package/coverage/lcov-report/map/api/models/index.html +0 -176
  404. package/coverage/lcov-report/map/api/models/projects.model.mongodb.js.html +0 -109
  405. package/coverage/lcov-report/map/api/models/styles.model.mongodb.js.html +0 -112
  406. package/coverage/lcov-report/map/api/services/alerts/alerts.hooks.js.html +0 -274
  407. package/coverage/lcov-report/map/api/services/alerts/alerts.service.js.html +0 -610
  408. package/coverage/lcov-report/map/api/services/alerts/index.html +0 -131
  409. package/coverage/lcov-report/map/api/services/catalog/catalog.hooks.js.html +0 -328
  410. package/coverage/lcov-report/map/api/services/catalog/index.html +0 -116
  411. package/coverage/lcov-report/map/api/services/daptiles/daptiles.service.js.html +0 -1510
  412. package/coverage/lcov-report/map/api/services/daptiles/index.html +0 -116
  413. package/coverage/lcov-report/map/api/services/features/features.hooks.js.html +0 -310
  414. package/coverage/lcov-report/map/api/services/features/features.service.js.html +0 -544
  415. package/coverage/lcov-report/map/api/services/features/index.html +0 -131
  416. package/coverage/lcov-report/map/api/services/index.html +0 -116
  417. package/coverage/lcov-report/map/api/services/index.js.html +0 -1054
  418. package/coverage/lcov-report/map/api/services/projects/index.html +0 -116
  419. package/coverage/lcov-report/map/api/services/projects/projects.hooks.js.html +0 -439
  420. package/coverage/lcov-report/map/api/services/styles/index.html +0 -116
  421. package/coverage/lcov-report/map/api/services/styles/styles.hooks.js.html +0 -196
  422. package/coverage/lcov-report/map/common/dynamic-grid-source.js.html +0 -466
  423. package/coverage/lcov-report/map/common/errors.js.html +0 -94
  424. package/coverage/lcov-report/map/common/geotiff-grid-source.js.html +0 -544
  425. package/coverage/lcov-report/map/common/grid.js.html +0 -1612
  426. package/coverage/lcov-report/map/common/index.html +0 -371
  427. package/coverage/lcov-report/map/common/index.js.html +0 -172
  428. package/coverage/lcov-report/map/common/meteo-model-grid-source.js.html +0 -556
  429. package/coverage/lcov-report/map/common/moment-utils.js.html +0 -157
  430. package/coverage/lcov-report/map/common/opendap-grid-source.js.html +0 -868
  431. package/coverage/lcov-report/map/common/opendap-utils.js.html +0 -826
  432. package/coverage/lcov-report/map/common/permissions.js.html +0 -130
  433. package/coverage/lcov-report/map/common/time-based-grid-source.js.html +0 -418
  434. package/coverage/lcov-report/map/common/tms-utils.js.html +0 -274
  435. package/coverage/lcov-report/map/common/wcs-grid-source.js.html +0 -364
  436. package/coverage/lcov-report/map/common/wcs-utils.js.html +0 -586
  437. package/coverage/lcov-report/map/common/weacast-grid-source.js.html +0 -1033
  438. package/coverage/lcov-report/map/common/wfs-utils.js.html +0 -574
  439. package/coverage/lcov-report/map/common/wms-utils.js.html +0 -451
  440. package/coverage/lcov-report/map/common/wmts-utils.js.html +0 -547
  441. package/coverage/lcov-report/prettify.css +0 -1
  442. package/coverage/lcov-report/prettify.js +0 -2
  443. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  444. package/coverage/lcov-report/sorter.js +0 -196
  445. package/coverage/lcov.info +0 -11520
  446. package/coverage/map/api/hooks/hooks.catalog.js.html +0 -553
  447. package/coverage/map/api/hooks/hooks.features.js.html +0 -397
  448. package/coverage/map/api/hooks/hooks.query.js.html +0 -1294
  449. package/coverage/map/api/hooks/index.html +0 -161
  450. package/coverage/map/api/hooks/index.js.html +0 -94
  451. package/coverage/map/api/index.html +0 -131
  452. package/coverage/map/api/index.js.html +0 -139
  453. package/coverage/map/api/marshall.js.html +0 -178
  454. package/coverage/map/api/models/alerts.model.mongodb.js.html +0 -106
  455. package/coverage/map/api/models/catalog.model.mongodb.js.html +0 -169
  456. package/coverage/map/api/models/features.model.mongodb.js.html +0 -196
  457. package/coverage/map/api/models/index.html +0 -176
  458. package/coverage/map/api/models/projects.model.mongodb.js.html +0 -109
  459. package/coverage/map/api/models/styles.model.mongodb.js.html +0 -112
  460. package/coverage/map/api/services/alerts/alerts.hooks.js.html +0 -274
  461. package/coverage/map/api/services/alerts/alerts.service.js.html +0 -610
  462. package/coverage/map/api/services/alerts/index.html +0 -131
  463. package/coverage/map/api/services/catalog/catalog.hooks.js.html +0 -328
  464. package/coverage/map/api/services/catalog/index.html +0 -116
  465. package/coverage/map/api/services/daptiles/daptiles.service.js.html +0 -1510
  466. package/coverage/map/api/services/daptiles/index.html +0 -116
  467. package/coverage/map/api/services/features/features.hooks.js.html +0 -310
  468. package/coverage/map/api/services/features/features.service.js.html +0 -544
  469. package/coverage/map/api/services/features/index.html +0 -131
  470. package/coverage/map/api/services/index.html +0 -116
  471. package/coverage/map/api/services/index.js.html +0 -1054
  472. package/coverage/map/api/services/projects/index.html +0 -116
  473. package/coverage/map/api/services/projects/projects.hooks.js.html +0 -439
  474. package/coverage/map/api/services/styles/index.html +0 -116
  475. package/coverage/map/api/services/styles/styles.hooks.js.html +0 -196
  476. package/coverage/map/common/dynamic-grid-source.js.html +0 -466
  477. package/coverage/map/common/errors.js.html +0 -94
  478. package/coverage/map/common/geotiff-grid-source.js.html +0 -544
  479. package/coverage/map/common/grid.js.html +0 -1612
  480. package/coverage/map/common/index.html +0 -371
  481. package/coverage/map/common/index.js.html +0 -172
  482. package/coverage/map/common/meteo-model-grid-source.js.html +0 -556
  483. package/coverage/map/common/moment-utils.js.html +0 -157
  484. package/coverage/map/common/opendap-grid-source.js.html +0 -868
  485. package/coverage/map/common/opendap-utils.js.html +0 -826
  486. package/coverage/map/common/permissions.js.html +0 -130
  487. package/coverage/map/common/time-based-grid-source.js.html +0 -418
  488. package/coverage/map/common/tms-utils.js.html +0 -274
  489. package/coverage/map/common/wcs-grid-source.js.html +0 -364
  490. package/coverage/map/common/wcs-utils.js.html +0 -586
  491. package/coverage/map/common/weacast-grid-source.js.html +0 -1033
  492. package/coverage/map/common/wfs-utils.js.html +0 -574
  493. package/coverage/map/common/wms-utils.js.html +0 -451
  494. package/coverage/map/common/wmts-utils.js.html +0 -547
  495. package/coverage/prettify.css +0 -1
  496. package/coverage/prettify.js +0 -2
  497. package/coverage/sort-arrow-sprite.png +0 -0
  498. package/coverage/sorter.js +0 -196
  499. package/coverage/tmp/coverage-151198-1753351220086-0.json +0 -1
  500. package/coverage/tmp/coverage-151210-1753351220070-0.json +0 -1
  501. package/coverage/tmp/coverage-151221-1753351129816-0.json +0 -1
  502. package/coverage/tmp/coverage-151233-1753351129803-0.json +0 -1
  503. package/coverage/tmp/coverage-151240-1753351129770-0.json +0 -1
  504. package/coverage/tmp/coverage-151307-1753351220058-0.json +0 -1
  505. package/coverage/tmp/coverage-151319-1753351220044-0.json +0 -1
  506. package/coverage/tmp/coverage-151326-1753351220010-0.json +0 -1
  507. package/extras/tours/core/account-profile.js +0 -32
  508. package/extras/tours/core/account.js +0 -143
  509. package/extras/tours/core/add-member.js +0 -75
  510. package/extras/tours/core/add-tag.js +0 -13
  511. package/extras/tours/core/create-group.js +0 -19
  512. package/extras/tours/core/create-organisation.js +0 -19
  513. package/extras/tours/core/create-tag.js +0 -26
  514. package/extras/tours/core/edit-member-role.js +0 -13
  515. package/extras/tours/core/groups.js +0 -65
  516. package/extras/tours/core/join-group.js +0 -13
  517. package/extras/tours/core/login.js +0 -41
  518. package/extras/tours/core/members.js +0 -108
  519. package/extras/tours/core/register.js +0 -61
  520. package/extras/tours/core/send-reset-password.js +0 -14
  521. package/extras/tours/core/tags.js +0 -65
  522. package/extras/tours/map/catalog-panel.js +0 -112
  523. package/extras/tours/map/fab.js +0 -26
  524. package/extras/tours/map/navigation-bar.js +0 -187
  525. package/extras/tours/map/side-nav.js +0 -36
  526. package/test/api/core/test-log-2025-02-05.log +0 -23
  527. package/test/api/core/test-log-2025-05-21.log +0 -15
  528. package/test/api/core/test-log-2025-06-25.log +0 -9
  529. package/test/api/core/test-log-2025-07-24.log +0 -44
  530. package/test/api/map/test-log-2025-05-27.log +0 -13
  531. package/test/api/map/test-log-2025-06-23.log +0 -7
  532. package/test/api/map/test-log-2025-07-24.log +0 -11
  533. package/test/client/core/api.js +0 -361
  534. package/test/client/core/index.js +0 -9
  535. package/test/client/index.js +0 -4
  536. package/test/client/map/index.js +0 -5
  537. package/test.client.js +0 -1
  538. /package/{test/client/core/time.js → extras/tests/core/time.mjs} +0 -0
  539. /package/extras/tours/{map/add-layer.js → add-layer.js} +0 -0
  540. /package/extras/tours/{map/catalog-categories.js → catalog-categories.js} +0 -0
  541. /package/extras/tours/{map/connect-layer.js → connect-layer.js} +0 -0
  542. /package/extras/tours/{map/create-layer.js → create-layer.js} +0 -0
  543. /package/extras/tours/{map/create-view.js → create-view.js} +0 -0
  544. /package/extras/tours/{map/import-layer.js → import-layer.js} +0 -0
  545. /package/extras/tours/{map/timeline.js → pane.bottom.js} +0 -0
@@ -18,6 +18,7 @@
18
18
  <script>
19
19
  import { KModal, KForm } from '../../../../core/client/components'
20
20
  import { baseModal } from '../../../../core/client/mixins'
21
+ import { api } from '../../../../core/client/api.js'
21
22
  import { useProject } from '../../composables'
22
23
 
23
24
  export default {
@@ -97,9 +98,9 @@ export default {
97
98
  this.creating = true
98
99
  const createdView = await this.kActivity.saveContext(view)
99
100
  // Add view to current project ? Check if not coming from another planet first
100
- if (this.project && (this.project.getPlanetApi() === this.$api)) {
101
+ if (this.project && (this.project.getPlanetApi() === api)) {
101
102
  this.project.views.push({ _id: createdView._id })
102
- await this.$api.getService('projects').patch(this.project._id, {
103
+ await api.getService('projects').patch(this.project._id, {
103
104
  views: this.project.views
104
105
  })
105
106
  }
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <KLayerItem v-if="!layer.filters"
2
+ <KLayerItem v-if="!layer?.filters && layer?.isVisible !== undefined"
3
3
  v-bind="$props"
4
4
  :layer="layer"
5
5
  @toggled="onToggled"
@@ -8,7 +8,7 @@
8
8
  <slot name="status" />
9
9
  </template>
10
10
  </KLayerItem>
11
- <q-tree v-else
11
+ <q-tree v-else-if="layer?.label"
12
12
  :nodes="[layer]"
13
13
  node-key="label"
14
14
  label-key="label"
@@ -17,7 +17,7 @@
17
17
  >
18
18
  <template v-slot:default-header="prop">
19
19
  <!-- Layer rendering -->
20
- <KLayerItem v-if="prop.node.name"
20
+ <KLayerItem v-if="prop.node.name && layer?.isVisible !== undefined"
21
21
  v-bind="$props"
22
22
  :layer="layer"
23
23
  @toggled="onToggled"
@@ -27,7 +27,7 @@
27
27
  </template>
28
28
  </KLayerItem>
29
29
  <!-- Filter rendering -->
30
- <div v-else class="row items-center q-pl-md q-pr-sm no-wrap">
30
+ <div v-else class="row col items-center q-pl-md q-pr-sm no-wrap">
31
31
  <!-- Filter toggle -->
32
32
  <q-toggle
33
33
  :ref="onToggleRefCreated(prop.node)"
@@ -39,7 +39,8 @@
39
39
  />
40
40
  <div :class="{
41
41
  'text-primary': layer.isVisible,
42
- 'text-grey-6': layer.isDisabled || !layer.isVisible || !prop.node.isActive
42
+ 'text-grey-6': layer.isDisabled || !layer.isVisible || !prop.node.isActive,
43
+ 'col': true
43
44
  }"
44
45
  >
45
46
  {{ $tie(prop.node.label) }}
@@ -51,6 +52,13 @@
51
52
  {{ prop.node.tooltip || prop.node.description }}
52
53
  </q-tooltip>
53
54
  </div>
55
+ <!-- Filter actions -->
56
+ <KPanel
57
+ :id="`${layer.name}-${prop.node.label}-filter-actions`"
58
+ :content="filterActions"
59
+ :context="{ layer, filter: prop.node }"
60
+ :filter="{ id: { $nin: ['toggle', 'toggle-filter'] } }"
61
+ />
54
62
  </div>
55
63
  </template>
56
64
  </q-tree>
@@ -58,8 +66,9 @@
58
66
 
59
67
  <script setup>
60
68
  import _ from 'lodash'
61
- import { ref } from 'vue'
69
+ import { ref, computed } from 'vue'
62
70
  import KLayerItem from './KLayerItem.vue'
71
+ import KPanel from '../../../../core/client/components/KPanel.vue'
63
72
 
64
73
  // Props
65
74
  const props = defineProps({
@@ -75,6 +84,17 @@ const emit = defineEmits(['toggled', 'filter-toggled'])
75
84
  // Datas
76
85
  const filters = ref([])
77
86
 
87
+ // Computed
88
+ const filterActions = computed(() => {
89
+ const filterActions = _.cloneDeep(props.layer.actions)
90
+ _.forEach(filterActions, (action) => {
91
+ action.content = _.filter(action.content, (item) => {
92
+ return _.get(item, 'isFilterAction')
93
+ })
94
+ })
95
+ return filterActions
96
+ })
97
+
78
98
  // Functions
79
99
  function onToggleRefCreated (node) {
80
100
  if (node) {
@@ -27,7 +27,7 @@ import _ from 'lodash'
27
27
  import path from 'path-browserify'
28
28
  import { ref, computed } from 'vue'
29
29
  import { generatePropertiesSchema } from '../../utils'
30
- import { i18n } from '../../../../core/client'
30
+ import { Events, i18n } from '../../../../core/client'
31
31
  import { KPanel } from '../../../../core/client/components'
32
32
  import { useCurrentActivity } from '../../composables'
33
33
  import KForm from '../../../../core/client/components/form/KForm.vue'
@@ -56,7 +56,7 @@ const fileFormSchema = computed(() => {
56
56
  component: 'form/KFileField',
57
57
  label: 'KImportLayer.FILE_FIELD_LABEL',
58
58
  mimeTypes: '.json,.geojson,.gpx,.kml',
59
- maxSize: 1024 * 1024 * 1024
59
+ maxFileSize: 1024 * 1024 * 1024
60
60
  }
61
61
  }
62
62
  },
@@ -147,7 +147,10 @@ async function onImport () {
147
147
  const fileResult = fileForm.value.validate()
148
148
  const propertiesResult = propertiesForm.value.validate()
149
149
  if (!fileResult.isValid || !propertiesResult.isValid) return
150
- this.importing = true
150
+ if (CurrentActivity.value.hasLayer(propertiesResult.values.name)) {
151
+ Events.emit('error', { message: i18n.t('KImportLayer.LAYER_ALREADY_EXISTS', { layer: propertiesResult.values.name }) })
152
+ }
153
+ importing.value = true
151
154
  await CurrentActivity.value.addGeoJsonLayer({
152
155
  name: propertiesResult.values.name,
153
156
  description: propertiesResult.values.description,
@@ -40,7 +40,7 @@
40
40
 
41
41
  <script>
42
42
  import _ from 'lodash'
43
- import { mixins as kCoreMixins } from '../../../../core/client'
43
+ import { api, Store, mixins as kCoreMixins } from '../../../../core/client'
44
44
  import { KModal, KGrid, KAction, KPanel, KForm } from '../../../../core/client/components'
45
45
 
46
46
  export default {
@@ -195,8 +195,8 @@ export default {
195
195
  },
196
196
  data () {
197
197
  return {
198
- filter: this.$store.get('filter'),
199
- sorter: this.$store.get('sorter'),
198
+ filter: Store.get('filter'),
199
+ sorter: Store.get('sorter'),
200
200
  mode: 'list',
201
201
  count: undefined,
202
202
  savingCategory: false,
@@ -226,7 +226,7 @@ export default {
226
226
  category.type = 'Category'
227
227
  this.savingCategory = true
228
228
  try {
229
- await this.$api.getService('catalog').create(category)
229
+ await api.getService('catalog').create(category)
230
230
  this.savingCategory = false
231
231
  } catch (error) {
232
232
  this.savingCategory = false
@@ -241,7 +241,7 @@ export default {
241
241
  if (result.isValid) {
242
242
  this.savingCategory = true
243
243
  try {
244
- await this.$api.getService('catalog').patch(this.editedCategory._id, result.values)
244
+ await api.getService('catalog').patch(this.editedCategory._id, result.values)
245
245
  this.savingCategory = false
246
246
  } catch (error) {
247
247
  this.savingCategory = false
@@ -281,7 +281,7 @@ export default {
281
281
  this.editedCategory = category
282
282
  },
283
283
  removeCategory (category) {
284
- this.$api.getService('catalog').remove(category._id)
284
+ api.getService('catalog').remove(category._id)
285
285
  }
286
286
  }
287
287
  }
@@ -30,13 +30,13 @@
30
30
  <q-space />
31
31
  <slot name="status">
32
32
  <q-icon name="las la-exclamation-circle" size="sm" color="warning" v-if="layer.isDisabled">
33
- <q-tooltip>{{ $t('KLayersSelector.LAYER_DISABLED') }}</q-tooltip>
33
+ <q-tooltip>{{ $t('KLayersList.LAYER_DISABLED') }}</q-tooltip>
34
34
  </q-icon>
35
35
  </slot>
36
36
  <!-- Layer actions -->
37
37
  <KPanel
38
38
  :id="`${layer.name}-actions`"
39
- :content="layer.actions"
39
+ :content="layerActions"
40
40
  :context="layer"
41
41
  :filter="{ id: { $nin: ['toggle', 'toggle-filter'] } }"
42
42
  />
@@ -74,6 +74,16 @@ const label = computed(() => {
74
74
  const label = _.get(props.layer, 'label')
75
75
  return Document.sanitizeHtml(label || _.get(props.layer, 'name'))
76
76
  })
77
+ const layerActions = computed(() => {
78
+ const layerActions = _.cloneDeep(_.get(props.layer, 'actions', []))
79
+ _.forEach(layerActions, (action) => {
80
+ if (!_.has(action, 'content')) return
81
+ action.content = _.filter(action.content, (item) => {
82
+ return !_.get(item, 'isFilterAction')
83
+ })
84
+ })
85
+ return layerActions
86
+ })
77
87
 
78
88
  // Functions
79
89
  function onToggled () {
@@ -0,0 +1,180 @@
1
+ <template>
2
+ <div>
3
+ <slot name="header" />
4
+
5
+ <div v-if="layers && layers.length > 0">
6
+ <template v-for="(layer, index) in layers">
7
+ <div
8
+ v-if="layer"
9
+ :key="index"
10
+ class="draggable-layer"
11
+ :draggable="isDraggable()"
12
+ @dragstart="onDragStart($event, index, layer)"
13
+ @drop="onDrop($event, index)"
14
+ @dragover.prevent
15
+ @dragenter.prevent
16
+ >
17
+ <q-icon v-if="isDraggable()" name="las la-grip-lines" color="primary" text-color="black" class="drag-handle" />
18
+ <component
19
+ :is="layerRenderer.component"
20
+ v-bind="layerRenderer.options"
21
+ :layer="layer"
22
+ @toggled="onLayerToggled"
23
+ @filter-toggled="onLayerFilterToggled"
24
+ style="flex-grow: 1;"
25
+ />
26
+ </div>
27
+ </template>
28
+ </div>
29
+
30
+ <div v-else-if="!options.hideIfEmpty" class="row justify-center q-pa-sm">
31
+ <KStamp
32
+ icon="las la-exclamation-circle"
33
+ icon-size="sm"
34
+ :text="$t('KLayersList.NO_LAYER_AVAILABLE')"
35
+ direction="horizontal"
36
+ />
37
+ </div>
38
+
39
+ <slot name="footer" />
40
+ </div>
41
+ </template>
42
+
43
+ <script setup>
44
+ import _ from 'lodash'
45
+ import { computed, ref } from 'vue'
46
+ import { utils } from '../../../../core/client'
47
+ import KStamp from '../../../../core/client/components/KStamp.vue'
48
+ import { useCurrentActivity } from '../../composables'
49
+ import { getCategories } from '../../utils.map'
50
+
51
+ // Props
52
+ const props = defineProps({
53
+ category: {
54
+ type: Object,
55
+ default: () => {}
56
+ },
57
+ layers: {
58
+ type: Array,
59
+ default: () => []
60
+ },
61
+ layersDraggable: {
62
+ type: [Boolean, Function],
63
+ default: () => false
64
+ },
65
+ options: {
66
+ type: Object,
67
+ default: () => {}
68
+ }
69
+ })
70
+
71
+ // Emits
72
+ const emit = defineEmits(['orphan-layer-updated'])
73
+
74
+ // Data
75
+ const draggedIndex = ref(null)
76
+ const { CurrentActivity } = useCurrentActivity()
77
+ const { updateCategoriesOrder, updateLayersOrder } = CurrentActivity.value
78
+
79
+ // Computed
80
+ const layerRenderer = computed(() => ({
81
+ component: utils.loadComponent(_.get(props.options, 'renderer', 'catalog/KFilteredLayerItem')),
82
+ options: _.get(props.options, 'renderer.options', {})
83
+ }))
84
+
85
+ // Drag & Drop handlers
86
+ function onDragStart (event, index, layer) {
87
+ draggedIndex.value = index
88
+ event.dataTransfer.dropEffect = 'move'
89
+ event.dataTransfer.effectAllowed = 'move'
90
+ event.dataTransfer.setData('draggedIndex', draggedIndex.value)
91
+ event.dataTransfer.setData('layerName', layer?.name)
92
+ event.dataTransfer.setData('categoryID', props.category?._id)
93
+ }
94
+
95
+ async function onDrop (event, targetIndex) {
96
+ const layerName = event.dataTransfer.getData('layerName')
97
+ const layer = props.layers.find(layer => layer.name === layerName)
98
+ const sourceCategoryId = event.dataTransfer.getData('categoryID')
99
+ if (!props.category?._id) { // source and target are orphan layers
100
+ // WARNING: Need to use a string here as dataTransfer serialize to strings
101
+ if (sourceCategoryId !== 'undefined') return
102
+ emit('orphan-layer-updated', targetIndex, draggedIndex.value)
103
+ return
104
+ }
105
+ if (layerName && layerName.length > 0) { // source is layer
106
+ const isLayerFromCurrentCategory = props.category._id === sourceCategoryId
107
+ // Avoid mutating read-only prop
108
+ const categoryLayers = _.clone(props.category.layers)
109
+ if (isLayerFromCurrentCategory) { // reorder layers in category
110
+ const removedLayers = categoryLayers.splice(draggedIndex.value, 1)
111
+ if (removedLayers.length > 0) categoryLayers.splice(targetIndex, 0, removedLayers[0])
112
+ await updateLayersOrder(props.category._id, { layers: categoryLayers }, layer)
113
+ } else { // layer isn't from current category: move layer to current category
114
+ // WARNING: Need to use a string here as dataTransfer serialize to strings
115
+ if (sourceCategoryId === 'undefined') { // source is orphan layer
116
+ emit('orphan-layer-updated', -1, draggedIndex.value)
117
+ categoryLayers.splice(targetIndex, 0, layerName)
118
+ await updateLayersOrder(props.category._id, { layers: categoryLayers }, layer)
119
+ } else { // source isn't orphan layer
120
+ const sourceCategory = await getCategories({ query: { _id: sourceCategoryId } })
121
+ const sourceCategoryLayers = sourceCategory[0].layers
122
+ const removedLayers = sourceCategoryLayers.splice(draggedIndex.value, 1)
123
+ if (removedLayers.length > 0) categoryLayers.splice(targetIndex, 0, removedLayers[0])
124
+ await updateLayersOrder(props.category._id, { layers: categoryLayers }, layer)
125
+ await updateLayersOrder(sourceCategoryId, { layers: sourceCategoryLayers }, layer)
126
+ }
127
+ }
128
+ } else { // drag source is category: reorder categories with target layer's category
129
+ const sourceCategoryId = event.dataTransfer.getData('categoryID')
130
+ const targetCategoryId = props.category._id
131
+ await updateCategoriesOrder(sourceCategoryId, targetCategoryId)
132
+ }
133
+ }
134
+
135
+ // Layer toggle handling
136
+ function toggleLayer (layer) {
137
+ const toggleAction = _.find(layer.actions, { id: 'toggle' })
138
+ if (toggleAction) toggleAction.handler()
139
+ }
140
+
141
+ async function onLayerToggled (layer) {
142
+ if (layer.isDisabled) return
143
+ if (props.options.exclusive) {
144
+ // Due to v-model the visible flag has already been changed on the layer
145
+ // Simply reset others layers before activating the new one to avoid any problem
146
+ const visibleLayers = _.filter(props.layers, { isVisible: true })
147
+ for (const visibleLayer of visibleLayers) {
148
+ if (visibleLayer !== layer) await toggleLayer(visibleLayer)
149
+ }
150
+ }
151
+ await toggleLayer(layer)
152
+ }
153
+
154
+ function toggleLayerFilter (layer, filter) {
155
+ const toggleFilterAction = _.find(layer.actions, { id: 'toggle-filter' })
156
+ if (toggleFilterAction) toggleFilterAction.handler(filter)
157
+ }
158
+
159
+ function onLayerFilterToggled (layer, filter) {
160
+ if (layer.isDisabled) return
161
+ toggleLayerFilter(layer, filter)
162
+ }
163
+
164
+ function isDraggable () {
165
+ return (typeof props.layersDraggable === 'function' ? props.layersDraggable(props.category) : props.layersDraggable)
166
+ }
167
+ </script>
168
+
169
+ <style scoped>
170
+ .draggable-layer {
171
+ display: flex;
172
+ align-items: center;
173
+ }
174
+ .drag-handle {
175
+ cursor: move;
176
+ margin-left: 16px;
177
+ font-size: 18px;
178
+ user-select: none;
179
+ }
180
+ </style>
@@ -24,20 +24,45 @@
24
24
  />
25
25
  </slot>
26
26
  <!-- Orphan layers -->
27
- <KLayersSelector
28
- :layers="orphanLayers"
27
+ <KLayersList
28
+ :layers="filteredOrphanLayers"
29
+ :layersDraggable="layersDraggable"
29
30
  :options="orphanLayersOptions"
31
+ @orphanLayerUpdated="onOrphanLayerUpdated"
30
32
  />
31
33
  <!-- Categorized layers -->
32
- <template v-for="category in filteredCategories">
34
+ <template v-for="(category, index) in filteredCategories">
33
35
  <KCategoryItem
34
36
  v-if="isCategoryVisible(category)"
35
37
  :key="getCategoryId(category)"
36
38
  :id="getCategoryId(category)"
37
39
  :category="category"
38
40
  :layers="layersByCategory[category.name]"
41
+ :layersDraggable="layersDraggable"
39
42
  :forecastModels="forecastModels"
40
- />
43
+ >
44
+ <template v-slot:header>
45
+ <div
46
+ :key="index"
47
+ class="draggable-category"
48
+ :draggable="isDraggable(category)"
49
+ @dragstart="onDragStart($event, index, category)"
50
+ @drop="onDrop($event, index)"
51
+ @dragover.prevent
52
+ @dragenter.prevent
53
+ >
54
+ <q-item-section v-if="isDraggable(category)" avatar class="drag-handle">
55
+ <q-icon name="las la-bars" color="primary" text-color="black" size="20px" />
56
+ </q-item-section>
57
+
58
+ <q-icon v-else :name="getCategoryIcon(category)" color="primary" text-color="black" size="20px" style="margin-right: 16px;" />
59
+
60
+ <q-item-section>
61
+ {{ i18n.tie(category.name) }}
62
+ </q-item-section>
63
+ </div>
64
+ </template>
65
+ </KCategoryItem>
41
66
  </template>
42
67
  <!-- Custom content -->
43
68
  <slot name="after-content">
@@ -73,31 +98,36 @@ export default {
73
98
  <script setup>
74
99
  import _ from 'lodash'
75
100
  import sift from 'sift'
76
- import { ref, watchEffect, onMounted } from 'vue'
77
- import { utils as coreUtils } from '../../../../core/client'
78
- import { getLayersByCategory, getOrphanLayers } from '../../utils'
79
- import { useProject } from '../../composables'
80
- import KLayersSelector from './KLayersSelector.vue'
101
+ import { ref, watchEffect } from 'vue'
102
+ import { utils as coreUtils, i18n } from '../../../../core/client'
103
+ import { useCurrentActivity, useProject } from '../../composables'
104
+ import { getLayersByCategory } from '../../utils'
81
105
  import KCategoryItem from './KCategoryItem.vue'
106
+ import KLayersList from './KLayersList.vue'
82
107
 
83
108
  // Props
84
109
  const props = defineProps({
85
- layers: {
86
- type: [Object, Array],
87
- default: () => []
88
- },
89
110
  layersFilter: {
90
111
  type: [Object, Function],
91
112
  default: () => {}
92
113
  },
93
- layerCategories: {
94
- type: Array,
95
- default: () => []
114
+ orphanLayersFilter: {
115
+ type: [Object, Function],
116
+ // By default orphan layers are user/activity layers
117
+ default: () => ({ scope: { $in: ['user', 'activity'] } })
96
118
  },
97
119
  layerCategoriesFilter: {
98
120
  type: [Object, Function],
99
121
  default: () => {}
100
122
  },
123
+ layersDraggable: {
124
+ type: [Boolean, Function],
125
+ default: false
126
+ },
127
+ categoriesDraggable: {
128
+ type: [Boolean, Function],
129
+ default: () => false
130
+ },
101
131
  forecastModels: {
102
132
  type: Array,
103
133
  default: () => []
@@ -138,10 +168,13 @@ const props = defineProps({
138
168
 
139
169
  // Data
140
170
  const { hasProject } = useProject()
171
+ const { CurrentActivity } = useCurrentActivity()
172
+ const { forecastModels, updateCategoriesOrder, updateLayersOrder, updateOrphanLayersOrder } = CurrentActivity.value
141
173
  const orphanLayersOptions = { hideIfEmpty: true }
142
174
  const filteredCategories = ref([])
143
175
  const layersByCategory = ref({})
144
- const orphanLayers = ref([])
176
+ const filteredOrphanLayers = ref([])
177
+ const draggedIndex = ref(null)
145
178
 
146
179
  // Watch
147
180
  watchEffect(() => { refresh() })
@@ -150,36 +183,113 @@ watchEffect(() => { refresh() })
150
183
  function getCategoryId (category) {
151
184
  return _.kebabCase(category.name)
152
185
  }
186
+ function getCategoryIcon (category) {
187
+ return _.get(category, 'icon.name', _.get(category, 'icon'), 'las la-bars')
188
+ }
153
189
  function isCategoryVisible (category) {
154
- // Show a built-in category only if it has some layers.
155
- // Indeed, depending on the app configuration, none might be available for this category.
156
- // User-defined categories are visible by default, even if empty,
157
- // except if used inside a project as in this case having no layers means we don't want to use this category
190
+ const options = category.options || category
191
+ // Show a built-in category only if it has some layers.
192
+ // Indeed, depending on the app configuration, none might be available for this category.
193
+ // User-defined categories are visible by default, even if empty,
194
+ // except if used inside a project as in this case having no layers means we don't want to use this category.
195
+ // App might also force to hide it anyway with the hideIfEmpty option.
158
196
  const isEmpty = (layersByCategory.value[category.name].length === 0)
159
- if (isEmpty) {
160
- if (hasProject()) return false
161
- else return !_.get(category, 'hideIfEmpty', !category._id)
162
- }
163
- return true
197
+ return (isEmpty ? !_.get(options, 'hideIfEmpty', !category._id || hasProject()) : true)
164
198
  }
165
199
  function refresh () {
200
+ const { layers, layerCategories, orphanLayers } = CurrentActivity.value
166
201
  // filter layers
167
202
  const layersFilter = (typeof props.layersFilter === 'object' ? sift(props.layersFilter) : props.layersFilter)
168
- const filteredLayers = _.filter(props.layers, layersFilter)
203
+ const filteredLayers = _.filter(layers, layersFilter)
169
204
  // filter categories
170
205
  const categoriesFilter = (typeof props.layerCategoriesFilter === 'object' ? sift(props.layerCategoriesFilter) : props.layerCategoriesFilter)
171
- filteredCategories.value = _.filter(props.layerCategories, categoriesFilter)
206
+ filteredCategories.value = _.filter(layerCategories, categoriesFilter)
172
207
  _.forEach(filteredCategories.value, category => {
173
- const component = _.get(category, 'component', 'catalog/KLayersSelector')
208
+ const component = _.get(category, 'component', 'catalog/KLayersList')
174
209
  if (!category.componentInstance) category.componentInstance = coreUtils.loadComponent(component)
175
210
  })
176
- // compute layers by categories and orphans layers
211
+ // compute layers by categories
177
212
  layersByCategory.value = getLayersByCategory(filteredLayers, filteredCategories.value)
178
- orphanLayers.value = getOrphanLayers(filteredLayers, layersByCategory.value)
179
- }//, 100)
213
+ // filter orphan layers
214
+ const orphanLayersFilter = (typeof props.orphanLayersFilter === 'object' ? sift(props.orphanLayersFilter) : props.orphanLayersFilter)
215
+ filteredOrphanLayers.value = _.filter(_.filter(orphanLayers, layersFilter), orphanLayersFilter)
216
+ }
180
217
 
181
- // Hooks
182
- onMounted(() => {
183
- refresh()
184
- })
218
+ async function onOrphanLayerUpdated (targetIndex, draggedIndex) {
219
+ const { orphanLayers } = CurrentActivity.value
220
+ const layer = filteredOrphanLayers.value[draggedIndex]
221
+ const targetLayer = (targetIndex >= 0 ? filteredOrphanLayers.value[targetIndex] : null)
222
+ const removedLayers = filteredOrphanLayers.value.splice(draggedIndex, 1)
223
+ // As orphan layers are filtered we might have a mismatch between activity list index and panel index
224
+ // 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
+ }
231
+ // If not -1 it means the orphan layer has been moved within the orphan layers list.
232
+ // Otherwise it has been moved to another category so that we only need to remove it from the list
233
+ if ((removedLayers.length > 0) && targetLayer) {
234
+ 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)
239
+ }
240
+ await updateOrphanLayersOrder(filteredOrphanLayers.value.map(layer => layer?._id || layer?.name), layer)
241
+ }
242
+
243
+ function onDragStart (event, index, category) {
244
+ draggedIndex.value = index
245
+ event.dataTransfer.dropEffect = 'move'
246
+ event.dataTransfer.effectAllowed = 'move'
247
+ event.dataTransfer.setData('categoryID', category._id)
248
+ }
249
+
250
+ async function onDrop (event, targetIndex) {
251
+ const sourceCategoryId = event.dataTransfer.getData('categoryID')
252
+ const layerName = event.dataTransfer.getData('layerName')
253
+ const layers = _.flatten(_.values(layersByCategory.value)).concat(filteredOrphanLayers.value)
254
+ const layer = layers.find(layer => layer.name === layerName)
255
+ const draggedLayerIndex = event.dataTransfer.getData('draggedIndex')
256
+ if (layerName && layerName.length > 0) { // drag source is layer: change layer category
257
+ const currentCategoryLayers = filteredCategories.value[targetIndex]?.layers
258
+ // WARNING: Need to use a string here as dataTransfer serialize to strings
259
+ if (sourceCategoryId === 'undefined') { // source is orphan layer
260
+ onOrphanLayerUpdated(-1, draggedLayerIndex)
261
+ currentCategoryLayers.unshift(layerName)
262
+ await updateLayersOrder(filteredCategories.value[targetIndex]._id, { layers: currentCategoryLayers }, layer)
263
+ } else {
264
+ const sourceCategoryLayers = filteredCategories.value.find(category => category?._id === sourceCategoryId)?.layers
265
+ const removedLayers = sourceCategoryLayers.splice(draggedLayerIndex, 1)
266
+ if (removedLayers.length > 0) currentCategoryLayers.unshift(removedLayers[0])
267
+ await updateLayersOrder(filteredCategories.value[targetIndex]._id, { layers: currentCategoryLayers }, layer)
268
+ await updateLayersOrder(sourceCategoryId, { layers: sourceCategoryLayers }, layer)
269
+ }
270
+ } else { // drag source is category: reorder category
271
+ await updateCategoriesOrder(sourceCategoryId, filteredCategories.value[targetIndex]._id)
272
+ }
273
+ }
274
+
275
+ function isDraggable (category) {
276
+ return !!category._id && (typeof props.categoriesDraggable === 'function' ? props.categoriesDraggable(category) : props.categoriesDraggable)
277
+ }
185
278
  </script>
279
+
280
+ <style scoped>
281
+ .draggable-category {
282
+ display: flex;
283
+ align-items: center;
284
+ flex-grow: 1;
285
+ }
286
+ .drag-handle {
287
+ min-width: 0;
288
+ width: 1px;
289
+ cursor: move;
290
+ margin-left: 0px;
291
+ margin-right: 32px;
292
+ padding: 0px;
293
+ user-select: none;
294
+ }
295
+ </style>