From c5f26cb21ec66570472d7f837d605f15438da43e Mon Sep 17 00:00:00 2001 From: roei Date: Thu, 31 Jul 2025 11:10:03 +0300 Subject: [PATCH 1/5] ohad --- src/app/App.ts | 27 +++ .../ShareLocation/ShareLocation.tsx | 161 ++++++++++++++++++ .../ShareLocation/css/ShareLocation.scss | 151 ++++++++++++++++ 3 files changed, 339 insertions(+) create mode 100644 src/app/Components/ShareLocation/ShareLocation.tsx create mode 100644 src/app/Components/ShareLocation/css/ShareLocation.scss diff --git a/src/app/App.ts b/src/app/App.ts index 1579cd3..540cd95 100644 --- a/src/app/App.ts +++ b/src/app/App.ts @@ -13,6 +13,10 @@ import ApplicationBase from "templates-common-library/baseClasses/ApplicationBas import ConfigurationSettings from "./ConfigurationSettings/ConfigurationSettings"; +import ShareLocation from "./Components/ShareLocation/ShareLocation"; +import "./Components/ShareLocation/css/ShareLocation.scss"; + + const CSS = { loading: "configurable-application--loading" }; @@ -74,6 +78,7 @@ class AttachmentViewerApp { view: __esri.MapView; item: __esri.PortalItem | null = null; commonMessages: any = null; + private _shareLocation: ShareLocation | null = null; public async init(base: ApplicationBase): Promise { if (!base) { @@ -157,6 +162,11 @@ class AttachmentViewerApp { findQuery(find as string, view).then(async () => { this.view = view as __esri.MapView; + this._shareLocation = new ShareLocation({ + view: this.view + }); + this.view.ui.add(this._shareLocation, "manual"); // or "top-right" if you want it in the UI panel + const selectedLayerId = this._getURLParameter("selectedLayerId"); if (!this._configurationSettings.withinConfigurationExperience) { if (selectedLayerId) { @@ -273,6 +283,7 @@ class AttachmentViewerApp { await view.when(); this.initialExtent = view.extent.clone(); this._addWidgetsToUI(mapToolsExpanded, docDirection); + this.addShareLocationFAB(); this._initPropWatchers(widgetProps); goToMarker(marker as string, view); this._cleanUpHandles(); @@ -394,6 +405,22 @@ class AttachmentViewerApp { { initial: true, once: true } ); } + + private addShareLocationFAB(): void { + if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { + const fabButton = document.createElement("button"); + fabButton.className = "share-location-fab"; + fabButton.innerHTML = ` + + + + `; + fabButton.onclick = () => { + alert("Click on a location on the map to share it!"); + }; + document.body.appendChild(fabButton); + } + } } export default AttachmentViewerApp; diff --git a/src/app/Components/ShareLocation/ShareLocation.tsx b/src/app/Components/ShareLocation/ShareLocation.tsx new file mode 100644 index 0000000..c86e07c --- /dev/null +++ b/src/app/Components/ShareLocation/ShareLocation.tsx @@ -0,0 +1,161 @@ +import { subclass, property } from "@arcgis/core/core/accessorSupport/decorators"; +import Widget from "@arcgis/core/widgets/Widget"; +import { tsx } from "@arcgis/core/widgets/support/widget"; +import Point from "@arcgis/core/geometry/Point"; +import { whenTrue } from "@arcgis/core/core/watchUtils"; + +interface ShareLocationConfig { + view: __esri.MapView | __esri.SceneView; +} + +@subclass("ShareLocation") +class ShareLocation extends Widget { + @property() + view: __esri.MapView | __esri.SceneView | null = null; + + @property() + selectedLocation: Point| null = null; + + @property() + isSharing: boolean = false; + +// ...existing code... +constructor(params: ShareLocationConfig) { + super(); // Don't pass params to super + this.view = params.view; +} +// ...existing code... + + postInitialize() { + whenTrue(this, "view.ready", () => { + this.setupClickHandler(); + }); + } + +private setupClickHandler(): void { + if (!this.view) return; + + this.view.on("click", (event) => { + if (!this.view) return; // Add this check + this.view.hitTest(event).then((response) => { + if (response.results.length > 0) { + const result = response.results[0]; + if ( + result.graphic && + result.graphic.geometry && + result.graphic.geometry.type === "point" + ) { + this.selectedLocation = result.graphic.geometry as Point; + this.isSharing = true; + } + } + }); + }); +} + + private formatCoordinates(point: Point): string { + const lat = point.latitude.toFixed(6); + const lon = point.longitude.toFixed(6); + return `${lat},${lon}`; + } + + private shareViaWhatsApp(): void { + if (!this.selectedLocation) return; + + const coords = this.formatCoordinates(this.selectedLocation); + const message = encodeURIComponent( + `Check out this location: ${coords}\n` + + `https://www.google.com/maps?q=${coords}` + ); + + const whatsappUrl = `https://wa.me/?text=${message}`; + window.open(whatsappUrl, "_blank"); + this.isSharing = false; + } + + private shareViaWebShare(): void { + if (!this.selectedLocation || !navigator.share) { + this.shareViaWhatsApp(); + return; + } + + const coords = this.formatCoordinates(this.selectedLocation); + + navigator.share({ + title: "Location Share", + text: `Check out this location: ${coords}`, + url: `https://www.google.com/maps?q=${coords}` + }) + .then(() => { + this.isSharing = false; + }) + .catch((error) => { + console.log("Share failed:", error); + this.shareViaWhatsApp(); + }); + } + + private copyToClipboard(): void { + if (!this.selectedLocation) return; + + const coords = this.formatCoordinates(this.selectedLocation); + const text = `Location: ${coords}\nhttps://www.google.com/maps?q=${coords}`; + + navigator.clipboard.writeText(text).then(() => { + alert("Location copied to clipboard!"); + this.isSharing = false; + }).catch(() => { + alert("Failed to copy location"); + }); + } + + render() { + const { isSharing, selectedLocation } = this; + + return ( + + ); + } +} + +export default ShareLocation; \ No newline at end of file diff --git a/src/app/Components/ShareLocation/css/ShareLocation.scss b/src/app/Components/ShareLocation/css/ShareLocation.scss new file mode 100644 index 0000000..36bfdfa --- /dev/null +++ b/src/app/Components/ShareLocation/css/ShareLocation.scss @@ -0,0 +1,151 @@ +.share-location-widget { + .share-popup { + position: fixed; + bottom: 20px; + left: 50%; + transform: translateX(-50%); + background: white; + border-radius: 12px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + width: 90%; + max-width: 350px; + z-index: 1000; + animation: slideUp 0.3s ease-out; + + @media (min-width: 768px) { + bottom: 40px; + } + } + + .share-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px; + border-bottom: 1px solid #e0e0e0; + + h3 { + margin: 0; + font-size: 18px; + color: #333; + } + + .close-btn { + background: none; + border: none; + font-size: 24px; + color: #666; + cursor: pointer; + padding: 0; + width: 30px; + height: 30px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + transition: background 0.2s; + + &:hover { + background: #f0f0f0; + } + } + } + + .share-content { + padding: 16px; + } + + .coordinates { + background: #f5f5f5; + padding: 12px; + border-radius: 8px; + font-family: monospace; + font-size: 15px; + margin: 0 0 16px 0; + color: #333; + line-height: 1.5; + } + + .share-buttons { + display: flex; + flex-direction: column; + gap: 10px; + } + + .share-btn { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 12px 20px; + border: none; + border-radius: 8px; + font-size: 16px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s; + width: 100%; + + svg { + flex-shrink: 0; + } + + &.whatsapp { + background: #25d366; + color: white; + + &:hover { + background: #1da851; + } + } + + &.copy { + background: #f0f0f0; + color: #333; + + &:hover { + background: #e0e0e0; + } + } + } + + @keyframes slideUp { + from { + transform: translateX(-50%) translateY(100%); + } + to { + transform: translateX(-50%) translateY(0); + } + } +} + +// Add floating action button for mobile +@media (max-width: 767px) { + .share-location-fab { + position: fixed; + bottom: 80px; + right: 20px; + width: 56px; + height: 56px; + border-radius: 50%; + background: #007ac2; + color: white; + border: none; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + z-index: 100; + transition: background 0.2s; + + &:hover { + background: #005a92; + } + + svg { + width: 24px; + height: 24px; + } + } +} \ No newline at end of file From 93dc4bf8d6a7857a88983f6ad31013824e3f56d6 Mon Sep 17 00:00:00 2001 From: roei Date: Thu, 31 Jul 2025 11:25:16 +0300 Subject: [PATCH 2/5] . --- src/app/Components/ShareLocation/ShareLocation.tsx | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/app/Components/ShareLocation/ShareLocation.tsx b/src/app/Components/ShareLocation/ShareLocation.tsx index c86e07c..33e3fb2 100644 --- a/src/app/Components/ShareLocation/ShareLocation.tsx +++ b/src/app/Components/ShareLocation/ShareLocation.tsx @@ -126,10 +126,6 @@ private setupClickHandler(): void { From 7b6922c397b30d8bb63e9db9c545d2bc5a9aa36c Mon Sep 17 00:00:00 2001 From: roei Date: Thu, 31 Jul 2025 13:24:02 +0300 Subject: [PATCH 3/5] canceled the starting popup --- src/app/Components/PhotoCentric.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/Components/PhotoCentric.tsx b/src/app/Components/PhotoCentric.tsx index 43fc35b..674c776 100644 --- a/src/app/Components/PhotoCentric.tsx +++ b/src/app/Components/PhotoCentric.tsx @@ -534,7 +534,7 @@ class PhotoCentric extends Widget { } private _handleOnboardingPanel(): void { - this.onboardingPanelIsOpen = this.showOnboardingOnStart; + this.onboardingPanelIsOpen = false; this.scheduleRender(); } From 7380c7658e861dc190e065a4970a154913f6310e Mon Sep 17 00:00:00 2001 From: roei Date: Thu, 31 Jul 2025 14:54:14 +0300 Subject: [PATCH 4/5] added appIP --- src/config/application.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/application.json b/src/config/application.json index 9547e01..be21def 100644 --- a/src/config/application.json +++ b/src/config/application.json @@ -1,5 +1,5 @@ { - "appid": "", + "appid": "849dc0034ee14bc1a0b7e1fa70971703", "type": "webmap", "webmap": "default", "portalUrl": "https://arcgis.com", From a2bc996b2f23cab969a1551a81ac597b39518868 Mon Sep 17 00:00:00 2001 From: roei Date: Sat, 2 Aug 2025 16:40:13 +0300 Subject: [PATCH 5/5] opoup is not showing anymore when loading the app --- src/app/Components/MapCentric/css/MapCentric.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/Components/MapCentric/css/MapCentric.scss b/src/app/Components/MapCentric/css/MapCentric.scss index 1e82bfd..adf3f13 100644 --- a/src/app/Components/MapCentric/css/MapCentric.scss +++ b/src/app/Components/MapCentric/css/MapCentric.scss @@ -949,7 +949,7 @@ $calcite-blue: #0079c1; .esri-map-centric__onboarding-overlay { width: 100%; height: 100%; - display: flex; + display: none; justify-content: center; align-items: center; background-color: rgba(0, 0, 0, 0.44);