diff --git a/src/css/my-account.css b/src/css/my-account.css index a120a978..19c7dbe8 100644 --- a/src/css/my-account.css +++ b/src/css/my-account.css @@ -492,3 +492,82 @@ div[id^=route-summary-div_ID_] { background-repeat: no-repeat; background-image: url(assets/offline-map.svg); } + + +/* SELECTION MULTIPLE */ +.lblMultiSelect{ + height: 25px; + width: 25px; + padding: 0; + margin-left: 15px; +} + +#myaccount-landmarks-multiple-actions, +#myaccount-routes-multiple-actions { + flex-direction: row; +} + +#myaccount-landmarks-multiple-actions > .lblMultiSelect, +#myaccount-routes-multiple-actions > .lblMultiSelect { + width: fit-content; + padding-left: 42px; + font-size: 15px; +} + +#myAccountActionsBtnLandmarks, +#myAccountActionsBtnRoutes { + background-image: url("./assets/options-layer.svg"); + padding: 13px 20px 13px 30px; + background-repeat: no-repeat; + background-position: left; + border-radius: 100px; + background-color: var(--light-grey); + width: fit-content; + margin: auto; + margin-top: 20px; +} + +.tools-layer-panel.multiple-selected { + background-color: var(--light-green); +} + +.tools-layer-panel.multiple-selected { + background-color: var(--light-green); +} + +#myaccountLandmarksList > .tools-layer-panel > .lblMultiSelect, +#myaccountRouteList > .tools-layer-panel > .lblMultiSelect { + display: none; +} + +#myaccount-landmarks > #myaccount-landmarks-multiple-actions, +#myaccount-routes > #myaccount-routes-multiple-actions { + display: none; +} + +#myaccount-landmarks:has(.multiple-selected) > #myaccount-landmarks-multiple-actions, +#myaccount-routes:has(.multiple-selected) > #myaccount-routes-multiple-actions { + display: flex; +} + +#myaccount-landmarks:has(.multiple-selected) > #myAccountImportBtnLandmarks, +#myaccount-routes:has(.multiple-selected) > #myAccountImportBtnRoutes { + display: none; +} + +#myaccountLandmarksList:has(.multiple-selected) > .tools-layer-panel, +#myaccountRouteList:has(.multiple-selected) > .tools-layer-panel { + justify-content: left; +} + +#myaccountLandmarksList:has(.multiple-selected) > .tools-layer-panel > .handle-draggable-layer, +#myaccountLandmarksList:has(.multiple-selected) > .tools-layer-panel > .tools-layer-advanced, +#myaccountRouteList:has(.multiple-selected) > .tools-layer-panel > .handle-draggable-layer, +#myaccountRouteList:has(.multiple-selected) > .tools-layer-panel > .tools-layer-advanced { + display: none; +} + +#myaccountLandmarksList:has(.multiple-selected) > .tools-layer-panel > .lblMultiSelect, +#myaccountRouteList:has(.multiple-selected) > .tools-layer-panel > .lblMultiSelect { + display: unset; +} diff --git a/src/js/my-account/my-account-dom.js b/src/js/my-account/my-account-dom.js index acc7aac8..e748bfe9 100644 --- a/src/js/my-account/my-account-dom.js +++ b/src/js/my-account/my-account-dom.js @@ -128,9 +128,39 @@ let MyAccountDOM = {
-
Importer
+
+
Importer
+
+ +
Actions multiples
+
+
Télécharger une carte
Espace total des cartes enregistrées : 0 Mo
-
Importer
+
+
Importer
+
+ +
Actions multiples
+
+
`; @@ -155,6 +185,208 @@ let MyAccountDOM = { this.dom.offlineMapSizeSpan = container.querySelector("#myAccountOfflineTotalSizeSpan"); this.dom.tabsMenuBtn = container.querySelector(".tabs-menu-btn"); + + container.querySelector("#myaccount-routes-multiple-actions .lblMultiSelect").addEventListener("click", () => { + const checkbox = container.querySelector("#myaccount-routes-multiple-actions .lblMultiSelect .checkbox"); + const routeContainers = container.querySelectorAll("#myaccount-routes .tools-layer-panel"); + if (checkbox.checked) { + routeContainers.forEach((routeContainer) => { + routeContainer.classList.add("multiple-selected"); + routeContainer.querySelector(".lblMultiSelect .checkbox").checked = true; + }); + } else { + routeContainers.forEach((routeContainer) => { + routeContainer.classList.remove("multiple-selected"); + routeContainer.querySelector(".lblMultiSelect .checkbox").checked = false; + }); + } + }); + + container.querySelector("#myaccount-landmarks-multiple-actions .lblMultiSelect").addEventListener("click", () => { + const checkbox = container.querySelector("#myaccount-landmarks-multiple-actions .lblMultiSelect .checkbox"); + const landmarkContainers = container.querySelectorAll("#myaccount-landmarks .tools-layer-panel"); + if (checkbox.checked) { + landmarkContainers.forEach((landmarkContainer) => { + landmarkContainer.classList.add("multiple-selected"); + landmarkContainer.querySelector(".lblMultiSelect .checkbox").checked = true; + }); + } else { + landmarkContainers.forEach((landmarkContainer) => { + landmarkContainer.classList.remove("multiple-selected"); + landmarkContainer.querySelector(".lblMultiSelect .checkbox").checked = false; + }); + } + }); + + container.querySelector("#myAccountActionsBtnLandmarks").addEventListener("click", () => { + ActionSheet.show({ + options: [ + { + class: "tools-layer-visibility", + text: "Masquer les repères sélectionnés", + value: "hide", + }, + { + class: "tools-layer-visibility invisible", + text: "Afficher les repères sélectionnés", + value: "show", + }, + { + class: "tools-layer-export", + text: "Exporter les repères sélectionnés", + value: "export", + }, + { + class: "tools-layer-remove confirm-needed", + text: "Supprimer les repères sélectionnés", + value: "delete", + confirmCallback: () => { + Toast.show({ + text: "Confirmez la suppression des repères", + duration: "short", + position: "bottom" + }); + } + }, + ], + timeToHide: 50, + }).then( (value) => { + if (value === "hide") { + const landmarkContainers = container.querySelectorAll("#myaccount-landmarks .tools-layer-panel"); + landmarkContainers.forEach((landmarkContainer) => { + if (landmarkContainer.classList.contains("multiple-selected")) { + if (landmarkContainer.classList.contains("invisible")) { + return; + } + this.hideLandmarkFromID(parseInt(landmarkContainer.id.split("_")[2])); + landmarkContainer.classList.add("invisible"); + } + }); + } + if (value === "show") { + const landmarkContainers = container.querySelectorAll("#myaccount-landmarks .tools-layer-panel"); + landmarkContainers.forEach((landmarkContainer) => { + if (landmarkContainer.classList.contains("multiple-selected")) { + if (!landmarkContainer.classList.contains("invisible")) { + return; + } + this.showLandmarkFromID(parseInt(landmarkContainer.id.split("_")[2]), false); + landmarkContainer.classList.remove("invisible"); + } + }); + } + if (value === "export") { + const landmarkContainers = container.querySelectorAll("#myaccount-landmarks .tools-layer-panel"); + landmarkContainers.forEach((landmarkContainer) => { + if (landmarkContainer.classList.contains("multiple-selected")) { + this.exportLandmarkFromID(parseInt(landmarkContainer.id.split("_")[2])); + } + }); + } + if (value === "delete") { + const landmarkContainers = container.querySelectorAll("#myaccount-landmarks .tools-layer-panel"); + landmarkContainers.forEach((landmarkContainer) => { + if (landmarkContainer.classList.contains("multiple-selected")) { + this.deleteLandmark(parseInt(landmarkContainer.id.split("_")[2])); + } + }); + } + }); + }); + + container.querySelector("#myAccountActionsBtnRoutes").addEventListener("click", () => { + ActionSheet.show({ + options: [ + { + class: "tools-layer-visibility", + text: "Masquer les itinéraires sélectionnés", + value: "hide", + }, + { + class: "tools-layer-visibility invisible", + text: "Afficher les itinéraires sélectionnés", + value: "show", + }, + { + class: "tools-layer-export", + text: "Exporter les itinéraires sélectionnés", + value: "export", + }, + { + class: "tools-layer-remove confirm-needed", + text: "Supprimer les itinéraires sélectionnés", + value: "delete", + confirmCallback: () => { + Toast.show({ + text: "Confirmez la suppression des itinéraires", + duration: "short", + position: "bottom" + }); + } + }, + ], + timeToHide: 50, + }).then( (value) => { + if (value === "hide") { + const routeContainers = container.querySelectorAll("#myaccount-routes .tools-layer-panel"); + routeContainers.forEach((routeContainer) => { + if (routeContainer.classList.contains("multiple-selected")) { + if (routeContainer.classList.contains("invisible")) { + return; + } + this.hideRouteFromID(parseInt(routeContainer.id.split("_")[2])); + routeContainer.classList.add("invisible"); + } + }); + } + if (value === "show") { + const routeContainers = container.querySelectorAll("#myaccount-routes .tools-layer-panel"); + routeContainers.forEach((routeContainer) => { + if (routeContainer.classList.contains("multiple-selected")) { + if (!routeContainer.classList.contains("invisible")) { + return; + } + this.showRouteFromID(parseInt(routeContainer.id.split("_")[2]), false); + routeContainer.classList.remove("invisible"); + } + }); + } + if (value === "export") { + ActionSheet.show({ + style: "buttons", + title: "Choisissez votre format d'export", + options: [ + { + text: "JSON", + value: "json", + class: "" + }, + { + text: "GPX", + value: "gpx", + class: "" + } + ] + }).then((format) => { + const routeContainers = container.querySelectorAll("#myaccount-routes .tools-layer-panel"); + routeContainers.forEach((routeContainer) => { + if (routeContainer.classList.contains("multiple-selected")) { + this.exportRouteFromID(parseInt(routeContainer.id.split("_")[2]), format); + } + }); + }); + } + if (value === "delete") { + const routeContainers = container.querySelectorAll("#myaccount-routes .tools-layer-panel"); + routeContainers.forEach((routeContainer) => { + if (routeContainer.classList.contains("multiple-selected")) { + this.deleteRoute(parseInt(routeContainer.id.split("_")[2])); + } + }); + } + }); + }); + return container; }, @@ -295,6 +527,15 @@ let MyAccountDOM = { var tplContainer = `
+
@@ -386,11 +627,47 @@ let MyAccountDOM = { }); }); + let longPressTriggered = false; // Au clic sur l'itinéraire = l'afficher - container.querySelector(`#route-basic-tools_ID_${routeId}`).addEventListener("click", () => { + container.querySelector(`#route-basic-tools_ID_${routeId}`).addEventListener("click", (e) => { + if (longPressTriggered) { + // Cancel click if it was a long press + e.preventDefault(); + e.stopImmediatePropagation(); + return; + } this.showRouteDetails(route); }); + // event appui long + let contextMenuTimeout = null; + const clearContextMenuTimeout = () => { clearTimeout(contextMenuTimeout); }; + container.querySelector(`#route-basic-tools_ID_${routeId}`).addEventListener("pointerdown", () => { + longPressTriggered = false; + contextMenuTimeout = setTimeout(() => { + longPressTriggered = true; + container.classList.add("multiple-selected"); + container.querySelector(".lblMultiSelect .checkbox").checked = true; + }, 500); + container.addEventListener("pointerup", (e) => { + clearContextMenuTimeout(); + if (longPressTriggered) { + e.preventDefault(); + e.stopImmediatePropagation(); + } + }); + container.addEventListener("pointermove", clearContextMenuTimeout); + }); + + container.querySelector(".lblMultiSelect").addEventListener("click", () => { + const checkbox = container.querySelector(".lblMultiSelect .checkbox"); + if (checkbox.checked) { + container.classList.add("multiple-selected"); + } else { + container.classList.remove("multiple-selected"); + } + }); + if (!container) { console.warn(); return; @@ -413,6 +690,15 @@ let MyAccountDOM = { var tplContainer = `
+
@@ -491,8 +777,15 @@ let MyAccountDOM = { }); }); + let longPressTriggered = false; // Au clic sur le PR = l'afficher - container.querySelector(`#landmark-basic-tools_ID_${landmarkId}`).addEventListener("click", () => { + container.querySelector(`#landmark-basic-tools_ID_${landmarkId}`).addEventListener("click", (e) => { + if (longPressTriggered) { + // Cancel click if it was a long press + e.preventDefault(); + e.stopImmediatePropagation(); + return; + } if (landmark.properties.visible) { this.toggleShowLandmark(landmark); } @@ -500,6 +793,35 @@ let MyAccountDOM = { this.toggleShowLandmark(landmark); }); + // event appui long + let contextMenuTimeout = null; + const clearContextMenuTimeout = () => { clearTimeout(contextMenuTimeout); }; + container.querySelector(`#landmark-basic-tools_ID_${landmarkId}`).addEventListener("pointerdown", () => { + longPressTriggered = false; + contextMenuTimeout = setTimeout(() => { + longPressTriggered = true; + container.classList.add("multiple-selected"); + container.querySelector(".lblMultiSelect .checkbox").checked = true; + }, 500); + container.addEventListener("pointerup", (e) => { + clearContextMenuTimeout(); + if (longPressTriggered) { + e.preventDefault(); + e.stopImmediatePropagation(); + } + }); + container.addEventListener("pointermove", clearContextMenuTimeout); + }); + + container.querySelector(".lblMultiSelect").addEventListener("click", () => { + const checkbox = container.querySelector(".lblMultiSelect .checkbox"); + if (checkbox.checked) { + container.classList.add("multiple-selected"); + } else { + container.classList.remove("multiple-selected"); + } + }); + if (!container) { console.warn(); return; diff --git a/src/js/my-account/my-account.js b/src/js/my-account/my-account.js index 18a8ae12..d2a15578 100644 --- a/src/js/my-account/my-account.js +++ b/src/js/my-account/my-account.js @@ -1262,28 +1262,32 @@ ${props.text}`, * @param {String} dataName - Le nom de la donnée (utilisé pour le nom du fichier) * @param {String} errorMessage - Message d'erreur en cas d'échec * @param {Function} shareFunc - Fonction de partage en cas d'erreur + * @param {String} format - format d'export si paramétré (export multiple) */ - async #exportData(data, dataName, errorMessage, shareFunc) { + async #exportData(data, dataName, errorMessage, shareFunc, format = null) { let documentsName = "Documents"; if (Capacitor.getPlatform() === "ios") { documentsName = "Fichiers"; } - const value = await ActionSheet.show({ - style: "buttons", - title: "Choisissez votre format d'export", - options: [ - { - text: "JSON", - value: "json", - class: "" - }, - { - text: "GPX", - value: "gpx", - class: "" - } - ] - }); + let value = format; + if (!value) { + value = await ActionSheet.show({ + style: "buttons", + title: "Choisissez votre format d'export", + options: [ + { + text: "JSON", + value: "json", + class: "" + }, + { + text: "GPX", + value: "gpx", + class: "" + } + ] + }); + } try { let formatName; const existingFileNames = (await Filesystem.readdir({ @@ -1370,9 +1374,9 @@ ${props.text}`, * Exporte l'itinéraire sous forme d'un fichier à partir de son ID * @param {Number} routeId */ - exportRouteFromID(routeId) { + exportRouteFromID(routeId, format = null) { try { - this.exportRoute(this.#getRouteFromID(routeId)); + this.exportRoute(this.#getRouteFromID(routeId), format); } catch (e) { console.warn(e); Toast.show({ @@ -1421,25 +1425,27 @@ ${props.text}`, * Affiche l'itinéraire s'il est caché, ou le cache s'il est affiché * @param {*} route */ - toggleShowRoute(route) { + toggleShowRoute(route, fly = true) { if (route.visible) { route.visible = false; } else { route.visible = true; - this.hide(); - let coordinates = []; - route.data.steps.forEach((step) => { - coordinates = coordinates.concat(step.geometry.coordinates); - }); - const bounds = coordinates.reduce((bounds, coord) => { - return bounds.extend([coord[0], coord[1]]); - }, new maplibregl.LngLatBounds([coordinates[0][0], coordinates[0][1]], [coordinates[0][0], coordinates[0][1]])); - if (Location.isTrackingActive()) { - Location.disableTracking(); + if (fly) { + this.hide(); + let coordinates = []; + route.data.steps.forEach((step) => { + coordinates = coordinates.concat(step.geometry.coordinates); + }); + const bounds = coordinates.reduce((bounds, coord) => { + return bounds.extend(coord); + }, new maplibregl.LngLatBounds(coordinates[0], coordinates[0])); + if (Location.isTrackingActive()) { + Location.disableTracking(); + } + this.map.fitBounds(bounds, { + padding: 100, + }); } - this.map.fitBounds(bounds, { - padding: 100, - }); } this.#updateSources(); } @@ -1448,11 +1454,11 @@ ${props.text}`, * Affiche l'itinéraire s'il est caché à partir de son ID * @param {Number} routeId */ - showRouteFromID(routeId) { + showRouteFromID(routeId, fly = true) { try { const route = this.#getRouteFromID(routeId); if (!route.visible) { - this.toggleShowRoute(route); + this.toggleShowRoute(route, fly); } } catch (e) { console.warn(e); @@ -1489,20 +1495,52 @@ ${props.text}`, * Affiche le point de repère s'il est caché, ou le cache s'il est affiché * @param {*} landmark */ - toggleShowLandmark(landmark) { + toggleShowLandmark(landmark, fly = true) { if (landmark.properties.visible) { landmark.properties.visible = false; } else { landmark.properties.visible = true; - this.hide(); - if (Location.isTrackingActive()) { - Location.disableTracking(); + if (fly) { + this.hide(); + if (Location.isTrackingActive()) { + Location.disableTracking(); + } + this.map.flyTo({center: landmark.geometry.coordinates, zoom: 14}); } - this.map.flyTo({center: landmark.geometry.coordinates, zoom: 14}); } this.#updateSources(); } + /** + * Affiche le repère s'il est caché à partir de son ID + * @param {Number} landmarkId + */ + showLandmarkFromID(landmarkId, fly = true) { + try { + const landmark = this.#getLandmarkFromID(landmarkId); + if (!landmark.properties.visible) { + this.toggleShowLandmark(landmark, fly); + } + } catch (e) { + console.warn(e); + } + } + + /** + * Cache le repère s'il est visible à partir de son ID + * @param {Number} landmarkId + */ + hideLandmarkFromID(landmarkId) { + try { + const landmark = this.#getLandmarkFromID(landmarkId); + if (landmark.properties.visible) { + this.toggleShowLandmark(landmark); + } + } catch (e) { + console.warn(e); + } + } + /** * Récupère un itinéraire via son ID * @param {Number} routeId