@collabdt/core 0.0.57 → 0.2.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.
- package/README.md +4 -26
- package/dist/core/components/support/BugReportDialog.d.ts.map +1 -1
- package/dist/core/components/support/BugReportDialog.js +32 -0
- package/dist/core/components/support/BugReportDialog.js.map +1 -1
- package/dist/core/components/support/FeatureRequestDialog.d.ts.map +1 -1
- package/dist/core/components/support/FeatureRequestDialog.js +32 -0
- package/dist/core/components/support/FeatureRequestDialog.js.map +1 -1
- package/dist/core/components/viewers/Data/DataMenu.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/DataMenu.js +9 -1
- package/dist/core/components/viewers/Data/DataMenu.js.map +1 -1
- package/dist/core/components/viewers/Data/HeaderButtons.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/HeaderButtons.js +5 -12
- package/dist/core/components/viewers/Data/HeaderButtons.js.map +1 -1
- package/dist/core/components/viewers/Data/MoreOptions.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/MoreOptions.js +14 -27
- package/dist/core/components/viewers/Data/MoreOptions.js.map +1 -1
- package/dist/core/components/viewers/Data/buildingDetails/FieldRenderer.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/buildingDetails/FieldRenderer.js +13 -18
- package/dist/core/components/viewers/Data/buildingDetails/FieldRenderer.js.map +1 -1
- package/dist/core/components/viewers/Data/details/FieldValue.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/details/FieldValue.js +13 -3
- package/dist/core/components/viewers/Data/details/FieldValue.js.map +1 -1
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.d.ts +2 -0
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.js +84 -3
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.js.map +1 -1
- package/dist/core/components/viewers/Data/siteDetails/SiteDetails.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/siteDetails/SiteDetails.js +23 -2
- package/dist/core/components/viewers/Data/siteDetails/SiteDetails.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.js +2 -0
- package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteContextMenu.d.ts +19 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteContextMenu.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteContextMenu.js +163 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteContextMenu.js.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteLayer.d.ts +3 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteLayer.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteLayer.js +310 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteLayer.js.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/siteGeometry.d.ts +30 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/siteGeometry.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/siteGeometry.js +122 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/siteGeometry.js.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/useShowSitesOnMap.d.ts +13 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/useShowSitesOnMap.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/useShowSitesOnMap.js +58 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/useShowSitesOnMap.js.map +1 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/AssociateBuildingsDialog.d.ts +18 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/AssociateBuildingsDialog.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/AssociateBuildingsDialog.js +102 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/AssociateBuildingsDialog.js.map +1 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/SiteAdder.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/SiteAdder.js +243 -176
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/SiteAdder.js.map +1 -1
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/persistSite.d.ts +24 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/persistSite.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/persistSite.js +46 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/persistSite.js.map +1 -0
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.d.ts +1 -0
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.d.ts.map +1 -1
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js +1 -0
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js.map +1 -1
- package/dist/core/hooks/sites/createSiteHooks.d.ts.map +1 -1
- package/dist/core/hooks/sites/createSiteHooks.js +0 -1
- package/dist/core/hooks/sites/createSiteHooks.js.map +1 -1
- package/dist/core/hooks/useCaptureScreenshot.d.ts.map +1 -1
- package/dist/core/hooks/useCaptureScreenshot.js +77 -30
- package/dist/core/hooks/useCaptureScreenshot.js.map +1 -1
- package/dist/core/store/CombineProviders.d.ts.map +1 -1
- package/dist/core/store/CombineProviders.js +2 -0
- package/dist/core/store/CombineProviders.js.map +1 -1
- package/dist/core/store/MapSites/context.d.ts +16 -0
- package/dist/core/store/MapSites/context.d.ts.map +1 -0
- package/dist/core/store/MapSites/context.js +29 -0
- package/dist/core/store/MapSites/context.js.map +1 -0
- package/dist/core/store/MapSites/reducer.d.ts +52 -0
- package/dist/core/store/MapSites/reducer.d.ts.map +1 -0
- package/dist/core/store/MapSites/reducer.js +70 -0
- package/dist/core/store/MapSites/reducer.js.map +1 -0
- package/dist/core/store/index.d.ts +1 -0
- package/dist/core/store/index.d.ts.map +1 -1
- package/dist/core/store/index.js +1 -0
- package/dist/core/store/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,18 +38,9 @@
|
|
|
38
38
|
|
|
39
39
|
Collab Digital Twins is the technology to power web-based, non-proprietary platforms designed for the visualization and interaction of multi-scale geospatial information systems (GIS), open data, open building information modelling (BIM), and a wide range of other digital media — including text, images, animated and static 3D models, IFCs, and point clouds.
|
|
40
40
|
|
|
41
|
-
The technology is built with full-stack web development frameworks, using **React.js** for the user interface, state management, and memory optimization, and **Next.js** for file organization, routing, and server-side rendering (SSR). It integrates multiple open-source packages to support maps and 3D models
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|---|---|
|
|
45
|
-
| Web map renderer | MapLibre |
|
|
46
|
-
| Vector tile server | Martin (PostGIS) |
|
|
47
|
-
| 3D graphics | Three.js |
|
|
48
|
-
| IFC parsing | Web-IFC (That Open Company) — with IDS & BCF |
|
|
49
|
-
| Point cloud streaming | COPC / Potree |
|
|
50
|
-
| Object storage | MinIO |
|
|
51
|
-
| Database | PostgreSQL |
|
|
52
|
-
| Infrastructure | Fullhost (Canada) |
|
|
41
|
+
The technology is built with full-stack web development frameworks, using **React.js** for the user interface, state management, and memory optimization, and **Next.js** for file organization, routing, and server-side rendering (SSR). It integrates multiple open-source packages to support maps and 3D models.
|
|
42
|
+
|
|
43
|
+
For more information about the tech-stack, visit: https://docs.collabdt.org/docs/architecture/overview
|
|
53
44
|
|
|
54
45
|
CDT efficiently incorporates multi-scale open data (federal, provincial, municipal), fetched directly from organizational APIs without requiring local data storage. Rather than functioning as a system of record, it serves as a **framework and infrastructure for referencing and linking distributed data sources**.
|
|
55
46
|
|
|
@@ -78,8 +69,6 @@ Because CDT is dual-licensed (see [Licensing](#licensing) below), every contribu
|
|
|
78
69
|
|
|
79
70
|
## Licensing
|
|
80
71
|
|
|
81
|
-
Collab Digital Twins is **dual-licensed**.
|
|
82
|
-
|
|
83
72
|
### Open source — AGPL-3.0
|
|
84
73
|
|
|
85
74
|
The project is free and open source under the **GNU Affero General Public License, version 3.0** ([full text](LICENSE) · [plain-language summary](https://www.gnu.org/licenses/agpl-3.0.en.html)). You may use, study, modify, and redistribute it under those terms, at no cost.
|
|
@@ -91,18 +80,7 @@ The AGPL is a strong copyleft license with one obligation that is easy to miss
|
|
|
91
80
|
|
|
92
81
|
If those terms work for you, you are free to self-host with no further obligation to us.
|
|
93
82
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
If you cannot or prefer not to comply with the AGPL — for example, you want to embed CDT in a closed-source product, offer it as a hosted service without releasing your modifications, or need warranty, indemnity, and support terms — a separate **Commercial License Agreement** is available from Collab Digital Twins. Commercial licensing also helps fund the not-for-profit's public-benefit mission.
|
|
97
|
-
|
|
98
|
-
| | AGPL-3.0 (open source) | Commercial license |
|
|
99
|
-
|---|---|---|
|
|
100
|
-
| Cost | Free | Paid |
|
|
101
|
-
| Must release source of your modifications, including when hosted (§13) | Yes | No |
|
|
102
|
-
| Use in closed-source / proprietary products | No | Yes |
|
|
103
|
-
| Warranty, indemnity & guaranteed support | No (as-is, community) | Yes (per agreement) |
|
|
104
|
-
|
|
105
|
-
To discuss commercial licensing or a support agreement, contact **[support@collabdt.org](mailto:support@collabdt.org)**.
|
|
83
|
+
To discuss commercial licensing or a support agreement, contact **[info@collabdt.org](mailto:info@collabdt.org)**.
|
|
106
84
|
|
|
107
85
|
> Copyright © 2025 Collab Digital Twins. Distributed under AGPL-3.0; see [LICENSE](LICENSE) and third-party attributions in [NOTICE](NOTICE).
|
|
108
86
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BugReportDialog.d.ts","sourceRoot":"","sources":["../../../../src/core/components/support/BugReportDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"BugReportDialog.d.ts","sourceRoot":"","sources":["../../../../src/core/components/support/BugReportDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAoD/B,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,MAAM,GACP,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,qBAmJA"}
|
|
@@ -14,6 +14,36 @@ import { Input } from "../ui/Input";
|
|
|
14
14
|
import { useCaptureScreenshot } from "../../hooks/useCaptureScreenshot";
|
|
15
15
|
import * as LR from "lucide-react";
|
|
16
16
|
import { toast } from "sonner";
|
|
17
|
+
function getBrowserInfo() {
|
|
18
|
+
var _a, _b, _c, _d;
|
|
19
|
+
const ua = navigator.userAgent;
|
|
20
|
+
if ("userAgentData" in navigator) {
|
|
21
|
+
const uaData = navigator.userAgentData;
|
|
22
|
+
const brands = (_a = uaData.brands) != null ? _a : [];
|
|
23
|
+
const brand = (_b = brands.find((b) => !b.brand.includes("Not") && b.brand !== "Chromium")) != null ? _b : brands[0];
|
|
24
|
+
const name = (_c = brand == null ? void 0 : brand.brand) != null ? _c : "Unknown";
|
|
25
|
+
const version = (_d = brand == null ? void 0 : brand.version) != null ? _d : "";
|
|
26
|
+
return version ? `${name} ${version}` : name;
|
|
27
|
+
}
|
|
28
|
+
const checks = [
|
|
29
|
+
["Firefox", /Firefox\/(\d+)/],
|
|
30
|
+
["Edge", /Edg\/(\d+)/],
|
|
31
|
+
["Chrome", /Chrome\/(\d+)/],
|
|
32
|
+
["Safari", /Version\/(\d+).*Safari/]
|
|
33
|
+
];
|
|
34
|
+
for (const [name, re] of checks) {
|
|
35
|
+
const m = re.exec(ua);
|
|
36
|
+
if (m) return `${name} ${m[1]}`;
|
|
37
|
+
}
|
|
38
|
+
return "Unknown";
|
|
39
|
+
}
|
|
40
|
+
function getDeviceInfo() {
|
|
41
|
+
var _a;
|
|
42
|
+
if ("userAgentData" in navigator) {
|
|
43
|
+
return ((_a = navigator.userAgentData) == null ? void 0 : _a.mobile) ? "Mobile" : "Desktop";
|
|
44
|
+
}
|
|
45
|
+
return /Mobile|Android|iPhone|iPad|iPod/.test(navigator.userAgent) ? "Mobile" : "Desktop";
|
|
46
|
+
}
|
|
17
47
|
function BugReportDialog({
|
|
18
48
|
open,
|
|
19
49
|
onOpenChange,
|
|
@@ -57,6 +87,8 @@ function BugReportDialog({
|
|
|
57
87
|
meta: {
|
|
58
88
|
url: window.location.href,
|
|
59
89
|
userAgent: navigator.userAgent,
|
|
90
|
+
browser: getBrowserInfo(),
|
|
91
|
+
device: getDeviceInfo(),
|
|
60
92
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
61
93
|
viewer,
|
|
62
94
|
userEmail
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/components/support/BugReportDialog.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { useTranslations } from \"next-intl\";\r\n\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n} from \"../ui/Dialog\";\r\n\r\nimport { Button } from \"../ui/Button\";\r\nimport { Textarea } from \"../ui/Textarea\";\r\nimport { Input } from \"../ui/Input\";\r\nimport { useCaptureScreenshot } from \"../../hooks/useCaptureScreenshot\";\r\n\r\nimport * as LR from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\n\r\nexport function BugReportDialog({\r\n open,\r\n onOpenChange,\r\n userEmail,\r\n viewer,\r\n}: {\r\n open: boolean;\r\n onOpenChange: (v: boolean) => void;\r\n userEmail?: string;\r\n viewer?: string;\r\n}) {\r\n const t = useTranslations(\"supportDialog\");\r\n const captureScreenshot = useCaptureScreenshot();\r\n\r\n const [title, setTitle] = React.useState(\"\");\r\n const [description, setDescription] = React.useState(\"\");\r\n const [repro, setRepro] = React.useState(\"\");\r\n const [screenshot, setScreenshot] = React.useState<string | null>(null);\r\n const [loading, setLoading] = React.useState(false);\r\n const [error, setError] = React.useState<string | null>(null);\r\n\r\n const reset = () => {\r\n setTitle(\"\");\r\n setDescription(\"\");\r\n setRepro(\"\");\r\n setScreenshot(null);\r\n setError(null);\r\n };\r\n\r\n const capture = async () => {\r\n const img = await captureScreenshot();\r\n setScreenshot(img);\r\n };\r\n\r\n const submit = async () => {\r\n if (!title.trim()) return;\r\n try {\r\n setLoading(true);\r\n setError(null);\r\n\r\n const res = await fetch(\"/api/github-issue\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n title,\r\n description,\r\n repro,\r\n screenshot,\r\n type: \"bug\",\r\n labels: [\"users\"],\r\n meta: {\r\n url: window.location.href,\r\n userAgent: navigator.userAgent,\r\n timestamp: new Date().toISOString(),\r\n viewer,\r\n userEmail,\r\n },\r\n }),\r\n });\r\n\r\n if (!res.ok) {\r\n const data = await res.json().catch(() => ({}));\r\n throw new Error(data.error || \"Submission failed\");\r\n }\r\n\r\n reset();\r\n onOpenChange(false);\r\n toast.success(t(\"submitSuccess\"));\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : \"Something went wrong\");\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <Dialog\r\n open={open}\r\n onOpenChange={(v) => {\r\n onOpenChange(v);\r\n if (!v) reset();\r\n }}\r\n >\r\n <DialogContent className=\"sm:max-w-[520px]\">\r\n <DialogHeader>\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <LR.Bug className=\"h-5 w-5\" />\r\n {t(\"bugTitle\")}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n <div className=\"space-y-3\">\r\n <Input\r\n placeholder={t(\"bugTitlePlaceholder\")}\r\n value={title}\r\n onChange={(e) => setTitle(e.target.value)}\r\n />\r\n\r\n <Textarea\r\n placeholder={t(\"descriptionPlaceholder\")}\r\n value={description}\r\n onChange={(e) => setDescription(e.target.value)}\r\n />\r\n\r\n <Textarea\r\n placeholder={t(\"reproPlaceholder\")}\r\n value={repro}\r\n onChange={(e) => setRepro(e.target.value)}\r\n />\r\n\r\n <div className=\"flex gap-2 items-center\">\r\n <Button onClick={capture} variant=\"secondary\" disabled={loading}>\r\n <LR.Camera className=\"h-4 w-4 mr-1\" />\r\n {t(\"captureScreenshot\")}\r\n </Button>\r\n {screenshot && (\r\n <span className=\"text-sm text-muted-foreground flex items-center gap-1\">\r\n <LR.CheckCircle className=\"h-3 w-3 text-green-500\" />\r\n {t(\"screenshotAttached\")}\r\n </span>\r\n )}\r\n </div>\r\n\r\n {screenshot && (\r\n <img\r\n src={screenshot}\r\n alt=\"screenshot preview\"\r\n className=\"w-full h-auto rounded border max-h-40 object-contain\"\r\n />\r\n )}\r\n\r\n {error && (\r\n <p className=\"text-sm text-destructive\">{error}</p>\r\n )}\r\n\r\n <div className=\"flex justify-end gap-2\">\r\n <Button\r\n variant=\"secondary\"\r\n onClick={() => onOpenChange(false)}\r\n disabled={loading}\r\n >\r\n {t(\"cancel\")}\r\n </Button>\r\n\r\n <Button\r\n onClick={submit}\r\n disabled={!title.trim() || loading}\r\n >\r\n {loading ? \"...\" : t(\"submit\")}\r\n </Button>\r\n </div>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/components/support/BugReportDialog.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { useTranslations } from \"next-intl\";\r\n\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n} from \"../ui/Dialog\";\r\n\r\nimport { Button } from \"../ui/Button\";\r\nimport { Textarea } from \"../ui/Textarea\";\r\nimport { Input } from \"../ui/Input\";\r\nimport { useCaptureScreenshot } from \"../../hooks/useCaptureScreenshot\";\r\n\r\nimport * as LR from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\n\r\nfunction getBrowserInfo(): string {\r\n const ua = navigator.userAgent;\r\n if (\"userAgentData\" in navigator) {\r\n const uaData = (navigator as any).userAgentData;\r\n const brands: Array<{ brand: string; version: string }> = uaData.brands ?? [];\r\n const brand =\r\n brands.find((b) => !b.brand.includes(\"Not\") && b.brand !== \"Chromium\") ??\r\n brands[0];\r\n const name = brand?.brand ?? \"Unknown\";\r\n const version = brand?.version ?? \"\";\r\n return version ? `${name} ${version}` : name;\r\n }\r\n const checks: Array<[string, RegExp]> = [\r\n [\"Firefox\", /Firefox\\/(\\d+)/],\r\n [\"Edge\", /Edg\\/(\\d+)/],\r\n [\"Chrome\", /Chrome\\/(\\d+)/],\r\n [\"Safari\", /Version\\/(\\d+).*Safari/],\r\n ];\r\n for (const [name, re] of checks) {\r\n const m = re.exec(ua);\r\n if (m) return `${name} ${m[1]}`;\r\n }\r\n return \"Unknown\";\r\n}\r\n\r\nfunction getDeviceInfo(): string {\r\n if (\"userAgentData\" in navigator) {\r\n return (navigator as any).userAgentData?.mobile ? \"Mobile\" : \"Desktop\";\r\n }\r\n return /Mobile|Android|iPhone|iPad|iPod/.test(navigator.userAgent)\r\n ? \"Mobile\"\r\n : \"Desktop\";\r\n}\r\n\r\nexport function BugReportDialog({\r\n open,\r\n onOpenChange,\r\n userEmail,\r\n viewer,\r\n}: {\r\n open: boolean;\r\n onOpenChange: (v: boolean) => void;\r\n userEmail?: string;\r\n viewer?: string;\r\n}) {\r\n const t = useTranslations(\"supportDialog\");\r\n const captureScreenshot = useCaptureScreenshot();\r\n\r\n const [title, setTitle] = React.useState(\"\");\r\n const [description, setDescription] = React.useState(\"\");\r\n const [repro, setRepro] = React.useState(\"\");\r\n const [screenshot, setScreenshot] = React.useState<string | null>(null);\r\n const [loading, setLoading] = React.useState(false);\r\n const [error, setError] = React.useState<string | null>(null);\r\n\r\n const reset = () => {\r\n setTitle(\"\");\r\n setDescription(\"\");\r\n setRepro(\"\");\r\n setScreenshot(null);\r\n setError(null);\r\n };\r\n\r\n const capture = async () => {\r\n const img = await captureScreenshot();\r\n setScreenshot(img);\r\n };\r\n\r\n const submit = async () => {\r\n if (!title.trim()) return;\r\n try {\r\n setLoading(true);\r\n setError(null);\r\n\r\n const res = await fetch(\"/api/github-issue\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n title,\r\n description,\r\n repro,\r\n screenshot,\r\n type: \"bug\",\r\n labels: [\"users\"],\r\n meta: {\r\n url: window.location.href,\r\n userAgent: navigator.userAgent,\r\n browser: getBrowserInfo(),\r\n device: getDeviceInfo(),\r\n timestamp: new Date().toISOString(),\r\n viewer,\r\n userEmail,\r\n },\r\n }),\r\n });\r\n\r\n if (!res.ok) {\r\n const data = await res.json().catch(() => ({}));\r\n throw new Error(data.error || \"Submission failed\");\r\n }\r\n\r\n reset();\r\n onOpenChange(false);\r\n toast.success(t(\"submitSuccess\"));\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : \"Something went wrong\");\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <Dialog\r\n open={open}\r\n onOpenChange={(v) => {\r\n onOpenChange(v);\r\n if (!v) reset();\r\n }}\r\n >\r\n <DialogContent className=\"sm:max-w-[520px]\">\r\n <DialogHeader>\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <LR.Bug className=\"h-5 w-5\" />\r\n {t(\"bugTitle\")}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n <div className=\"space-y-3\">\r\n <Input\r\n placeholder={t(\"bugTitlePlaceholder\")}\r\n value={title}\r\n onChange={(e) => setTitle(e.target.value)}\r\n />\r\n\r\n <Textarea\r\n placeholder={t(\"descriptionPlaceholder\")}\r\n value={description}\r\n onChange={(e) => setDescription(e.target.value)}\r\n />\r\n\r\n <Textarea\r\n placeholder={t(\"reproPlaceholder\")}\r\n value={repro}\r\n onChange={(e) => setRepro(e.target.value)}\r\n />\r\n\r\n <div className=\"flex gap-2 items-center\">\r\n <Button onClick={capture} variant=\"secondary\" disabled={loading}>\r\n <LR.Camera className=\"h-4 w-4 mr-1\" />\r\n {t(\"captureScreenshot\")}\r\n </Button>\r\n {screenshot && (\r\n <span className=\"text-sm text-muted-foreground flex items-center gap-1\">\r\n <LR.CheckCircle className=\"h-3 w-3 text-green-500\" />\r\n {t(\"screenshotAttached\")}\r\n </span>\r\n )}\r\n </div>\r\n\r\n {screenshot && (\r\n <img\r\n src={screenshot}\r\n alt=\"screenshot preview\"\r\n className=\"w-full h-auto rounded border max-h-40 object-contain\"\r\n />\r\n )}\r\n\r\n {error && (\r\n <p className=\"text-sm text-destructive\">{error}</p>\r\n )}\r\n\r\n <div className=\"flex justify-end gap-2\">\r\n <Button\r\n variant=\"secondary\"\r\n onClick={() => onOpenChange(false)}\r\n disabled={loading}\r\n >\r\n {t(\"cancel\")}\r\n </Button>\r\n\r\n <Button\r\n onClick={submit}\r\n disabled={!title.trim() || loading}\r\n >\r\n {loading ? \"...\" : t(\"submit\")}\r\n </Button>\r\n </div>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FeatureRequestDialog.d.ts","sourceRoot":"","sources":["../../../../src/core/components/support/FeatureRequestDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"FeatureRequestDialog.d.ts","sourceRoot":"","sources":["../../../../src/core/components/support/FeatureRequestDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAmD/B,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,KAAK,qBAwGpF"}
|
|
@@ -13,6 +13,36 @@ import { Input } from "../ui/Input";
|
|
|
13
13
|
import { Textarea } from "../ui/Textarea";
|
|
14
14
|
import * as LR from "lucide-react";
|
|
15
15
|
import { toast } from "sonner";
|
|
16
|
+
function getBrowserInfo() {
|
|
17
|
+
var _a, _b, _c, _d;
|
|
18
|
+
const ua = navigator.userAgent;
|
|
19
|
+
if ("userAgentData" in navigator) {
|
|
20
|
+
const uaData = navigator.userAgentData;
|
|
21
|
+
const brands = (_a = uaData.brands) != null ? _a : [];
|
|
22
|
+
const brand = (_b = brands.find((b) => !b.brand.includes("Not") && b.brand !== "Chromium")) != null ? _b : brands[0];
|
|
23
|
+
const name = (_c = brand == null ? void 0 : brand.brand) != null ? _c : "Unknown";
|
|
24
|
+
const version = (_d = brand == null ? void 0 : brand.version) != null ? _d : "";
|
|
25
|
+
return version ? `${name} ${version}` : name;
|
|
26
|
+
}
|
|
27
|
+
const checks = [
|
|
28
|
+
["Firefox", /Firefox\/(\d+)/],
|
|
29
|
+
["Edge", /Edg\/(\d+)/],
|
|
30
|
+
["Chrome", /Chrome\/(\d+)/],
|
|
31
|
+
["Safari", /Version\/(\d+).*Safari/]
|
|
32
|
+
];
|
|
33
|
+
for (const [name, re] of checks) {
|
|
34
|
+
const m = re.exec(ua);
|
|
35
|
+
if (m) return `${name} ${m[1]}`;
|
|
36
|
+
}
|
|
37
|
+
return "Unknown";
|
|
38
|
+
}
|
|
39
|
+
function getDeviceInfo() {
|
|
40
|
+
var _a;
|
|
41
|
+
if ("userAgentData" in navigator) {
|
|
42
|
+
return ((_a = navigator.userAgentData) == null ? void 0 : _a.mobile) ? "Mobile" : "Desktop";
|
|
43
|
+
}
|
|
44
|
+
return /Mobile|Android|iPhone|iPad|iPod/.test(navigator.userAgent) ? "Mobile" : "Desktop";
|
|
45
|
+
}
|
|
16
46
|
function FeatureRequestDialog({ open, onOpenChange, userEmail, viewer }) {
|
|
17
47
|
const t = useTranslations("supportDialog");
|
|
18
48
|
const [title, setTitle] = React.useState("");
|
|
@@ -37,6 +67,8 @@ function FeatureRequestDialog({ open, onOpenChange, userEmail, viewer }) {
|
|
|
37
67
|
meta: {
|
|
38
68
|
url: window.location.href,
|
|
39
69
|
userAgent: navigator.userAgent,
|
|
70
|
+
browser: getBrowserInfo(),
|
|
71
|
+
device: getDeviceInfo(),
|
|
40
72
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41
73
|
viewer,
|
|
42
74
|
userEmail
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/components/support/FeatureRequestDialog.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { useTranslations } from \"next-intl\";\r\n\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n} from \"../ui/Dialog\";\r\n\r\nimport { Button } from \"../ui/Button\";\r\nimport { Input } from \"../ui/Input\";\r\nimport { Textarea } from \"../ui/Textarea\";\r\n\r\nimport * as LR from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\n\r\ntype Props = {\r\n open: boolean;\r\n onOpenChange: (open: boolean) => void;\r\n userEmail?: string;\r\n viewer?: string;\r\n};\r\n\r\nexport function FeatureRequestDialog({ open, onOpenChange, userEmail, viewer }: Props) {\r\n const t = useTranslations(\"supportDialog\");\r\n\r\n const [title, setTitle] = React.useState(\"\");\r\n const [description, setDescription] = React.useState(\"\");\r\n const [loading, setLoading] = React.useState(false);\r\n\r\n const reset = () => {\r\n setTitle(\"\");\r\n setDescription(\"\");\r\n };\r\n\r\n const submit = async () => {\r\n if (!title.trim() || !description.trim()) return;\r\n\r\n try {\r\n setLoading(true);\r\n\r\n await fetch(\"/api/github-issue\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n title,\r\n description,\r\n type: \"feature-request\",\r\n labels: [\"users\"],\r\n meta: {\r\n url: window.location.href,\r\n userAgent: navigator.userAgent,\r\n timestamp: new Date().toISOString(),\r\n viewer,\r\n userEmail,\r\n },\r\n }),\r\n });\r\n\r\n reset();\r\n onOpenChange(false);\r\n toast.success(t(\"featureSubmitSuccess\"));\r\n } catch (err) {\r\n console.error(\"Feature request failed:\", err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <Dialog\r\n open={open}\r\n onOpenChange={(v) => {\r\n onOpenChange(v);\r\n if (!v) reset();\r\n }}\r\n >\r\n <DialogContent className=\"sm:max-w-[520px]\">\r\n <DialogHeader>\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <LR.SquarePlus className=\"h-5 w-5\" />\r\n {t(\"featureTitle\")}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n <div className=\"space-y-4 mt-2\">\r\n <Input\r\n placeholder={t(\"featureTitle\")}\r\n value={title}\r\n onChange={(e) => setTitle(e.target.value)}\r\n />\r\n\r\n <Textarea\r\n placeholder={t(\"descriptionPlaceholder\")}\r\n value={description}\r\n onChange={(e) => setDescription(e.target.value)}\r\n rows={5}\r\n />\r\n\r\n <div className=\"text-sm text-muted-foreground\"> {t(\"wantToBuild\")}{\" \"} \r\n <a href=\"https://docs.collabdt.org/docs/plugins/overview\" target=\"_blank\" rel=\"noreferrer\" className=\"underline hover:text-foreground\" > \r\n {t(\"pluginDocumentation\")}\r\n </a> \r\n </div>\r\n\r\n <div className=\"flex justify-end gap-2\">\r\n <Button\r\n variant=\"secondary\"\r\n onClick={() => onOpenChange(false)}\r\n disabled={loading}\r\n >\r\n {t(\"cancel\")}\r\n </Button>\r\n\r\n <Button\r\n onClick={submit}\r\n disabled={!title.trim() || !description.trim() || loading}\r\n >\r\n {loading ? \"...\" : t(\"submit\")}\r\n </Button>\r\n </div>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}"],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/components/support/FeatureRequestDialog.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { useTranslations } from \"next-intl\";\r\n\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n} from \"../ui/Dialog\";\r\n\r\nimport { Button } from \"../ui/Button\";\r\nimport { Input } from \"../ui/Input\";\r\nimport { Textarea } from \"../ui/Textarea\";\r\n\r\nimport * as LR from \"lucide-react\";\r\nimport { toast } from \"sonner\";\r\n\r\nfunction getBrowserInfo(): string {\r\n const ua = navigator.userAgent;\r\n if (\"userAgentData\" in navigator) {\r\n const uaData = (navigator as any).userAgentData;\r\n const brands: Array<{ brand: string; version: string }> = uaData.brands ?? [];\r\n const brand =\r\n brands.find((b) => !b.brand.includes(\"Not\") && b.brand !== \"Chromium\") ??\r\n brands[0];\r\n const name = brand?.brand ?? \"Unknown\";\r\n const version = brand?.version ?? \"\";\r\n return version ? `${name} ${version}` : name;\r\n }\r\n const checks: Array<[string, RegExp]> = [\r\n [\"Firefox\", /Firefox\\/(\\d+)/],\r\n [\"Edge\", /Edg\\/(\\d+)/],\r\n [\"Chrome\", /Chrome\\/(\\d+)/],\r\n [\"Safari\", /Version\\/(\\d+).*Safari/],\r\n ];\r\n for (const [name, re] of checks) {\r\n const m = re.exec(ua);\r\n if (m) return `${name} ${m[1]}`;\r\n }\r\n return \"Unknown\";\r\n}\r\n\r\nfunction getDeviceInfo(): string {\r\n if (\"userAgentData\" in navigator) {\r\n return (navigator as any).userAgentData?.mobile ? \"Mobile\" : \"Desktop\";\r\n }\r\n return /Mobile|Android|iPhone|iPad|iPod/.test(navigator.userAgent)\r\n ? \"Mobile\"\r\n : \"Desktop\";\r\n}\r\n\r\ntype Props = {\r\n open: boolean;\r\n onOpenChange: (open: boolean) => void;\r\n userEmail?: string;\r\n viewer?: string;\r\n};\r\n\r\nexport function FeatureRequestDialog({ open, onOpenChange, userEmail, viewer }: Props) {\r\n const t = useTranslations(\"supportDialog\");\r\n\r\n const [title, setTitle] = React.useState(\"\");\r\n const [description, setDescription] = React.useState(\"\");\r\n const [loading, setLoading] = React.useState(false);\r\n\r\n const reset = () => {\r\n setTitle(\"\");\r\n setDescription(\"\");\r\n };\r\n\r\n const submit = async () => {\r\n if (!title.trim() || !description.trim()) return;\r\n\r\n try {\r\n setLoading(true);\r\n\r\n await fetch(\"/api/github-issue\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n title,\r\n description,\r\n type: \"feature-request\",\r\n labels: [\"users\"],\r\n meta: {\r\n url: window.location.href,\r\n userAgent: navigator.userAgent,\r\n browser: getBrowserInfo(),\r\n device: getDeviceInfo(),\r\n timestamp: new Date().toISOString(),\r\n viewer,\r\n userEmail,\r\n },\r\n }),\r\n });\r\n\r\n reset();\r\n onOpenChange(false);\r\n toast.success(t(\"featureSubmitSuccess\"));\r\n } catch (err) {\r\n console.error(\"Feature request failed:\", err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <Dialog\r\n open={open}\r\n onOpenChange={(v) => {\r\n onOpenChange(v);\r\n if (!v) reset();\r\n }}\r\n >\r\n <DialogContent className=\"sm:max-w-[520px]\">\r\n <DialogHeader>\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <LR.SquarePlus className=\"h-5 w-5\" />\r\n {t(\"featureTitle\")}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n <div className=\"space-y-4 mt-2\">\r\n <Input\r\n placeholder={t(\"featureTitle\")}\r\n value={title}\r\n onChange={(e) => setTitle(e.target.value)}\r\n />\r\n\r\n <Textarea\r\n placeholder={t(\"descriptionPlaceholder\")}\r\n value={description}\r\n onChange={(e) => setDescription(e.target.value)}\r\n rows={5}\r\n />\r\n\r\n <div className=\"text-sm text-muted-foreground\"> {t(\"wantToBuild\")}{\" \"} \r\n <a href=\"https://docs.collabdt.org/docs/plugins/overview\" target=\"_blank\" rel=\"noreferrer\" className=\"underline hover:text-foreground\" > \r\n {t(\"pluginDocumentation\")}\r\n </a> \r\n </div>\r\n\r\n <div className=\"flex justify-end gap-2\">\r\n <Button\r\n variant=\"secondary\"\r\n onClick={() => onOpenChange(false)}\r\n disabled={loading}\r\n >\r\n {t(\"cancel\")}\r\n </Button>\r\n\r\n <Button\r\n onClick={submit}\r\n disabled={!title.trim() || !description.trim() || loading}\r\n >\r\n {loading ? \"...\" : t(\"submit\")}\r\n </Button>\r\n </div>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataMenu.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/Data/DataMenu.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAS9B,OAAO,KAAK,EAAwC,YAAY,EAAE,MAAM,wBAAwB,CAAA;AA6ChG,OAAO,EAA6B,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAKvE,KAAK,aAAa,GAAG;IACnB,aAAa,EAAE,WAAW,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAgB,QAAQ,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"DataMenu.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/Data/DataMenu.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAS9B,OAAO,KAAK,EAAwC,YAAY,EAAE,MAAM,wBAAwB,CAAA;AA6ChG,OAAO,EAA6B,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAKvE,KAAK,aAAa,GAAG;IACnB,aAAa,EAAE,WAAW,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAgB,QAAQ,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,EAAE,aAAa,qBA6jBlJ"}
|
|
@@ -116,7 +116,15 @@ function DataMenu({ currentViewer, height, hideTitle, hideActions, hideFrame, or
|
|
|
116
116
|
removeItemFromCompare
|
|
117
117
|
} = useBuildingsContext();
|
|
118
118
|
React.useEffect(() => {
|
|
119
|
-
|
|
119
|
+
var _a2;
|
|
120
|
+
const viewerToDataType = {
|
|
121
|
+
[ViewerNames.buildings]: DataTypesNames.building,
|
|
122
|
+
[ViewerNames.sites]: DataTypesNames.site,
|
|
123
|
+
[ViewerNames.infrastructure]: DataTypesNames.infrastructure,
|
|
124
|
+
[ViewerNames.files]: DataTypesNames.file,
|
|
125
|
+
[ViewerNames.users]: DataTypesNames.user
|
|
126
|
+
};
|
|
127
|
+
setDataType((_a2 = viewerToDataType[currentViewer]) != null ? _a2 : DataTypesNames.building);
|
|
120
128
|
}, [currentViewer]);
|
|
121
129
|
React.useEffect(() => {
|
|
122
130
|
setComparing(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/core/components/viewers/Data/DataMenu.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { toast } from 'sonner'\r\nimport { useTranslations } from 'next-intl'\r\nimport { handleApiError } from '../../../utils/errorHandler'\r\n\r\n// Utils\r\nimport { useViewerData } from './utils/useViewerData'\r\nimport { VIEWER_CONFIG } from './utils/viewerConfig'\r\n\r\nimport type { Building, Site, User, Infrastructure, Organization } from '../../../types/dbTypes'\r\nimport type { FilterState } from '../../../types/global'\r\n\r\n// Custom hooks\r\nimport { useBuildings, useCreateBuilding } from '../../../hooks/buildings/buildings'\r\nimport { useCreateSite, useSites } from '../../../hooks/sites/sites'\r\nimport { useFiles } from '../../../hooks/files/files'\r\nimport { useUsers } from '../../../hooks/users/users'\r\n\r\n// Context\r\nimport { useMenusContext } from '../../../store'\r\nimport { useBuildingsContext } from '../../../store'\r\nimport { useFilesContext } from '../../../store'\r\n\r\n// Types\r\nimport type { FileRow } from '../../../types/files'\r\nimport {\r\n Breadcrumb,\r\n BreadcrumbItem,\r\n BreadcrumbLink,\r\n BreadcrumbList,\r\n BreadcrumbPage,\r\n BreadcrumbSeparator,\r\n} from '../../ui/Breadcrumb'\r\nimport { Button, Checkbox, DataTable, Input, Separator } from '../../ui/'\r\n\r\nimport type { BuildingDetailsRef } from './buildingDetails/BuildingDetails'\r\nimport type { SiteDetailsRef } from './siteDetails/SiteDetails'\r\nimport type { InfrastructureDetailsRef } from './infrastructureDetails/InfrastructureDetails'\r\n\r\nimport BuildingDetails from './buildingDetails/BuildingDetails'\r\nimport { FileDetails } from './files/FileDetails'\r\n\r\n// Custom Components\r\nimport DetailActions from './details/DetailActions'\r\nimport DetailHeader from './details/DetailHeader'\r\nimport FilterButtons from './FilterButtons'\r\nimport HeaderButtons from './HeaderButtons'\r\nimport MoreOptions from './MoreOptions'\r\nimport SiteDetails from './siteDetails/SiteDetails'\r\nimport UserDetails from './userDetails/UserDetails'\r\n\r\n// Data\r\nimport { useColumns, useUserColumns } from './utils/Columns'\r\nimport { useBuildingHeaders, useInfrastructureHeaders, useSiteHeaders } from './utils/Headers'\r\nimport { DataTypes, DataTypesNames, ViewerNames } from '../../../types'\r\nimport { useSession } from 'next-auth/react'\r\nimport InfrastructureDetails from './infrastructureDetails/InfrastructureDetails'\r\nimport { useCreateInfrastructure, useInfrastructures } from '../../../hooks/infrastructures/infrastructures'\r\n\r\ntype DataMenuProps = {\r\n currentViewer: ViewerNames\r\n height?: string\r\n hideFrame?: boolean\r\n hideTitle?: boolean\r\n hideActions?: boolean\r\n organization?: Organization\r\n geocodeEarthApiKey?: string\r\n geocoderUrl?: string\r\n}\r\n\r\nexport function DataMenu({ currentViewer, height, hideTitle, hideActions, hideFrame, organization, geocodeEarthApiKey, geocoderUrl }: DataMenuProps) {\r\n // Translations\r\n const t = useTranslations('DataMenu')\r\n\r\n // View state\r\n const { view, setView } = useMenusContext()\r\n const { selectedItem, setSelectedItem } = useMenusContext()\r\n const { selectedSite, setSelectedSite } = useMenusContext()\r\n const { selectedInfrastructure, setSelectedInfrastructure } = useMenusContext()\r\n const { selectedFile, setSelectedFile } = useMenusContext()\r\n const { selectedUser, setSelectedUser } = useMenusContext()\r\n const { state: fileState } = useFilesContext()\r\n const { currentFile } = fileState.files\r\n\r\n // Search / filter state\r\n const [searchTerm, setSearchTerm] = React.useState('')\r\n const [activeFilters, setActiveFilters] = React.useState<FilterState[]>([])\r\n const [filters, setFilters] = React.useState([\r\n { id: 1, field: '', fieldType: null, operator: null, value: null, secondValue: null },\r\n ])\r\n\r\n const [dataType, setDataType] = React.useState<DataTypes>(DataTypesNames.building)\r\n const [editing, setEditing] = React.useState(false)\r\n const [activeChanges, setActiveChanges] = React.useState(false)\r\n\r\n // Tab headers\r\n const buildingHeaders = useBuildingHeaders()\r\n const siteHeaders = useSiteHeaders()\r\n const infrastructureHeaders = useInfrastructureHeaders()\r\n\r\n const buildingTabOptions = buildingHeaders.map(section => ({\r\n key: section.title.toLowerCase().replaceAll(/\\s/g, '-'),\r\n label: section.title,\r\n }))\r\n const siteTabOptions = siteHeaders.map(section => ({\r\n key: section.title.toLowerCase().replaceAll(/\\s/g, '-'),\r\n label: section.title,\r\n }))\r\n const infrastructureTabOptions = infrastructureHeaders.map(section => ({\r\n key: section.title.toLowerCase().replaceAll(/\\s/g, '-'),\r\n label: section.title,\r\n }))\r\n\r\n const [activeBuildingTab, setActiveBuildingTab] = React.useState(buildingTabOptions[0]?.key || '')\r\n const [activeSiteTab, setActiveSiteTab] = React.useState(siteTabOptions[0]?.key || '')\r\n const [activeInfrastructureTab, setActiveInfrastructureTab] = React.useState(infrastructureTabOptions[0]?.key || '')\r\n\r\n // Reset active tab only when selected item ID changes\r\n const prevBuildingId = React.useRef<number | undefined>(undefined)\r\n const prevInfrastructureId = React.useRef<number | undefined>(undefined)\r\n\r\n React.useEffect(() => {\r\n if (currentViewer === ViewerNames.buildings && selectedItem?.id !== prevBuildingId.current) {\r\n setActiveBuildingTab(buildingTabOptions[0]?.key || '')\r\n prevBuildingId.current = selectedItem?.id\r\n }\r\n if (currentViewer === ViewerNames.infrastructure && selectedInfrastructure?.id !== prevInfrastructureId.current) {\r\n setActiveInfrastructureTab(infrastructureTabOptions[0]?.key || '')\r\n prevInfrastructureId.current = selectedInfrastructure?.id\r\n }\r\n }, [selectedItem?.id, selectedInfrastructure?.id, currentViewer])\r\n\r\n const [newItemName, setNewItemName] = React.useState('')\r\n\r\n // Compare state\r\n const {\r\n compareItems,\r\n setCompareItems,\r\n comparing,\r\n setComparing,\r\n addItemToCompare,\r\n removeItemFromCompare,\r\n } = useBuildingsContext()\r\n\r\n // Sync dataType with current viewer\r\n React.useEffect(() => {\r\n setDataType(DataTypesNames[currentViewer])\r\n }, [currentViewer])\r\n\r\n // Reset compare state when viewer changes\r\n React.useEffect(() => {\r\n setComparing(false)\r\n setCompareItems([])\r\n }, [currentViewer, setComparing, setCompareItems])\r\n\r\n // Data fetching\r\n const { buildings, isLoading: buildingsLoading, isError: buildingsError } = useBuildings()\r\n const { sites, isLoading: sitesLoading, isError: sitesError } = useSites()\r\n const { infrastructures, isLoading: infrastructuresLoading, isError: infrastructuresError } = useInfrastructures()\r\n const { files, isLoading: filesLoading, isError: filesError } = useFiles()\r\n const { users, isLoading: usersLoading, isError: usersError } = useUsers()\r\n\r\n const { createError: createSiteError } = useCreateSite()\r\n const { createError: createBuildingError } = useCreateBuilding()\r\n const { createError: createInfrastructureError } = useCreateInfrastructure()\r\n\r\n React.useEffect(() => {\r\n handleApiError(buildingsError)\r\n handleApiError(sitesError)\r\n handleApiError(filesError)\r\n handleApiError(infrastructuresError)\r\n handleApiError(usersError)\r\n handleApiError(createSiteError)\r\n handleApiError(createBuildingError)\r\n handleApiError(createInfrastructureError)\r\n }, [buildingsError, sitesError, infrastructuresError, filesError, usersError, createSiteError, createBuildingError, createInfrastructureError])\r\n\r\n const tableColumns = useColumns(buildings || [])\r\n const userColumns = useUserColumns()\r\n\r\n const { user } = useSession().data\r\n\r\n // Viewer config — resolves icon and i18n title key\r\n const viewerConfig = VIEWER_CONFIG[currentViewer]\r\n const headerTitle = t(viewerConfig.titleKey)\r\n const MenuIcon = viewerConfig.icon\r\n\r\n // Derived data, filtered data, and filter options — all per-viewer logic lives in this hook\r\n const { data, filteredData, filtersOptions, isLoading } = useViewerData({\r\n currentViewer,\r\n buildings,\r\n sites,\r\n infrastructures,\r\n files,\r\n users,\r\n loadingFlags: {\r\n buildings: buildingsLoading,\r\n sites: sitesLoading,\r\n infrastructures: infrastructuresLoading,\r\n files: filesLoading,\r\n users: usersLoading,\r\n },\r\n searchTerm,\r\n activeFilters,\r\n filters,\r\n userEmail: user?.email || '',\r\n })\r\n\r\n const openedCurrentFileIdRef = React.useRef<number | null>(null)\r\n\r\n React.useEffect(() => {\r\n if (currentViewer !== ViewerNames.files || !currentFile) return\r\n if (openedCurrentFileIdRef.current === currentFile.id) return\r\n\r\n const fileRow = data.find((item): item is FileRow => String(item.id) === String(currentFile.id))\r\n if (!fileRow) return\r\n\r\n openedCurrentFileIdRef.current = currentFile.id\r\n setSelectedFile(fileRow)\r\n setView('detail')\r\n }, [currentViewer, currentFile, data, setSelectedFile, setView])\r\n\r\n // Breadcrumb title — derives the detail page label from whichever item is selected\r\n const breadcrumbTitle = React.useMemo(() => {\r\n if (selectedItem) return selectedItem.buildingName || selectedItem.buildingAddress\r\n if (selectedSite) return selectedSite.siteName || selectedSite.siteAddress\r\n if (selectedInfrastructure) return selectedInfrastructure.infrastructureName || selectedInfrastructure.infrastructureType\r\n if (selectedFile) return selectedFile.name\r\n if (selectedUser) return selectedUser.name\r\n if (currentViewer === ViewerNames.extensions) return 'Extension Details'\r\n return undefined\r\n }, [selectedItem, selectedSite, selectedInfrastructure, selectedFile, selectedUser, currentViewer])\r\n\r\n // Row click handlers — consolidated into one function\r\n\r\n const handleRowClick = (item: Building | Site | Infrastructure | FileRow | User) => {\r\n // Files and users don't participate in compare mode\r\n if (comparing && 'id' in item) {\r\n const id = String(item.id)\r\n const isChecked = compareItems.some(i => i.id === id)\r\n if (isChecked) {\r\n removeItemFromCompare(id)\r\n } else {\r\n addItemToCompare({ ...item, id })\r\n }\r\n return\r\n }\r\n\r\n // Navigate to detail view, setting the correct selected item per viewer\r\n switch (currentViewer) {\r\n case ViewerNames.buildings:\r\n setSelectedItem(item as Building)\r\n break\r\n case ViewerNames.sites:\r\n setSelectedSite(item as Site)\r\n break\r\n case ViewerNames.infrastructure:\r\n setSelectedInfrastructure(item as Infrastructure)\r\n break\r\n case ViewerNames.files:\r\n setSelectedFile(item as FileRow)\r\n break\r\n case ViewerNames.users:\r\n setSelectedUser(item as User)\r\n break\r\n }\r\n setView('detail')\r\n }\r\n\r\nconst handleBackToTable = () => {\r\n setView('table')\r\n setSelectedItem(null)\r\n setSelectedSite(null)\r\n setSelectedInfrastructure(null)\r\n setSelectedFile(null)\r\n setSelectedUser(null)\r\n setEditing(false)\r\n setActiveChanges(false)\r\n }\r\n\r\n // Refs for imperative save on child detail components\r\n\r\n const buildingDetailsRef = React.useRef<BuildingDetailsRef>(null)\r\n const siteDetailsRef = React.useRef<SiteDetailsRef>(null)\r\n const infrastructureDetailsRef = React.useRef<InfrastructureDetailsRef>(null)\r\n const fileDetailsRef = React.useRef(null)\r\n const userDetailsRef = React.useRef(null)\r\n\r\n // Save / create handlers — consolidated into one function\r\n\r\n const handleSaveChanges = async () => {\r\n switch (currentViewer) {\r\n case ViewerNames.buildings:\r\n await buildingDetailsRef.current?.saveChanges()\r\n break\r\n case ViewerNames.sites:\r\n await siteDetailsRef.current?.saveChanges()\r\n break\r\n case ViewerNames.infrastructure:\r\n await infrastructureDetailsRef.current?.saveChanges()\r\n break\r\n case ViewerNames.files:\r\n await fileDetailsRef.current?.saveChanges()\r\n break\r\n case ViewerNames.users:\r\n await userDetailsRef.current?.saveChanges()\r\n break\r\n }\r\n }\r\n\r\n /**\r\n * Handles creation of a new entity (id < 0).\r\n * Calls saveChanges on the appropriate ref, then shows a toast.\r\n * Pass successKey as undefined for viewers that show their own success toast (e.g. buildings).\r\n */\r\n const handleCreate = async (\r\n ref: React.RefObject<{ saveChanges: () => Promise<void> }>,\r\n toastKeys: { successKey?: string; errorKey: string },\r\n ) => {\r\n try {\r\n await ref.current?.saveChanges()\r\n setActiveChanges(false)\r\n if (toastKeys.successKey) toast.success(t(toastKeys.successKey))\r\n } catch (error) {\r\n if (error?.status !== 401) toast.error(t(toastKeys.errorKey))\r\n }\r\n }\r\n\r\n // Dispatches to the right ref + toast keys based on which new item is selected\r\n const handleCreateNewItem = async () => {\r\n if (selectedSite && selectedSite.id < 0) {\r\n await handleCreate(siteDetailsRef, {\r\n successKey: 'toastSuccessCreateSite',\r\n errorKey: 'toastFailCreateSite',\r\n })\r\n } else if (selectedItem && selectedItem.id < 0) {\r\n await handleCreate(buildingDetailsRef, {\r\n // Building details shows its own success toast\r\n errorKey: 'toastFailCreateBuilding',\r\n })\r\n } else if (selectedInfrastructure && selectedInfrastructure.id < 0) {\r\n await handleCreate(infrastructureDetailsRef, {\r\n successKey: 'toastSuccessCreateInfrastructure',\r\n errorKey: 'toastFailCreateInfrastructure',\r\n })\r\n } else {\r\n // Users and existing items — standard save\r\n await handleSaveChanges()\r\n }\r\n }\r\n\r\n // Derived UI helpers\r\n\r\n const isNewItem = !!(\r\n (selectedSite && selectedSite.id < 0)\r\n || (selectedItem && selectedItem.id < 0)\r\n || (selectedInfrastructure && selectedInfrastructure.id < 0)\r\n )\r\n\r\n // Render\r\n\r\n return (\r\n <div className={`${hideFrame ? '' : 'sm:p-2'} overflow-hidden ${hideFrame ? '' : 'bg-[#fafafa]'} ${height ? height : 'h-full'}`}>\r\n <div className={`${hideFrame ? '' : 'bg-background rounded-xl shadow'} h-full min-h-0`}>\r\n <div className=\"flex flex-col h-full min-h-0\">\r\n\r\n {/* Breadcrumb Navigation */}\r\n <div className=\"\">\r\n <div className=\"flex flex-row gap-2 justify-start items-center px-3 py-4 relative\">\r\n <Breadcrumb className=\"px-3\">\r\n <BreadcrumbList>\r\n <BreadcrumbItem>\r\n {view === 'table'\r\n ? <BreadcrumbPage>{headerTitle}</BreadcrumbPage>\r\n : (\r\n <BreadcrumbLink onClick={handleBackToTable} className=\"cursor-pointer\">\r\n {headerTitle}\r\n </BreadcrumbLink>\r\n )}\r\n </BreadcrumbItem>\r\n\r\n {view === 'detail' && (\r\n <>\r\n <BreadcrumbSeparator />\r\n <BreadcrumbItem>\r\n <BreadcrumbPage>{breadcrumbTitle}</BreadcrumbPage>\r\n </BreadcrumbItem>\r\n </>\r\n )}\r\n </BreadcrumbList>\r\n </Breadcrumb>\r\n </div>\r\n\r\n {/* Header content based on view */}\r\n {view === 'table' ? (\r\n <>\r\n {/* Title Row */}\r\n {!hideTitle && (\r\n <div className=\"flex flex-row justify-between items-center px-6 py-6\">\r\n <div className=\"flex flex-col gap-1.5\">\r\n <div className=\"flex items-center gap-2\">\r\n <MenuIcon className=\"h-8 w-8\" />\r\n <h1 className=\"text-2xl text-foreground\">{headerTitle}</h1>\r\n </div>\r\n {comparing && (\r\n <h2 className=\"text-sm text-muted-foreground font-normal\">\r\n Choose up to 3 {headerTitle.toLowerCase()} to compare.\r\n </h2>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Search & Filter & Actions Row */}\r\n <div className={`flex ${hideTitle ? 'justify-between' : 'justify-end'} items-center px-6 py-4 gap-4`}>\r\n <div className={hideTitle ? 'w-64' : 'w-96'}>\r\n <Input\r\n placeholder={`${t('searchPlaceholder')} ${headerTitle}...`}\r\n value={searchTerm}\r\n onChange={e => setSearchTerm(e.target.value)}\r\n />\r\n </div>\r\n\r\n <div className=\"flex gap-2\">\r\n <FilterButtons\r\n currentViewer={currentViewer}\r\n filters={filters}\r\n activeFilters={activeFilters}\r\n filterFields={filtersOptions}\r\n data={data}\r\n setFilters={setFilters}\r\n setActiveFilters={setActiveFilters}\r\n />\r\n <HeaderButtons\r\n headerTitle={headerTitle}\r\n currentViewer={currentViewer}\r\n compareItems={compareItems}\r\n setCompareItems={setCompareItems}\r\n comparing={comparing}\r\n setComparing={setComparing}\r\n newItemName={newItemName}\r\n setNewItemName={setNewItemName}\r\n filteredData={\r\n currentViewer === ViewerNames.buildings\r\n || currentViewer === ViewerNames.sites\r\n || currentViewer === ViewerNames.infrastructure\r\n ? filteredData\r\n : undefined\r\n }\r\n users={currentViewer === ViewerNames.users ? users : undefined}\r\n geocodeEarthApiKey={geocodeEarthApiKey}\r\n geocoderUrl={geocoderUrl}\r\n />\r\n </div>\r\n </div>\r\n\r\n <Separator />\r\n </>\r\n ) : (\r\n // Detail View Header\r\n <div className=\"flex justify-between items-center px-6 py-6\">\r\n <DetailHeader\r\n selectedItem={selectedItem}\r\n selectedSite={selectedSite}\r\n selectedInfrastructure={selectedInfrastructure}\r\n selectedFile={selectedFile}\r\n selectedUser={selectedUser}\r\n countryCode={organization?.country}\r\n />\r\n\r\n <DetailActions\r\n editing={editing}\r\n activeChanges={activeChanges}\r\n currentViewer={currentViewer}\r\n selectedItem={selectedItem}\r\n selectedSite={selectedSite}\r\n selectedInfrastructure={selectedInfrastructure}\r\n selectedFile={selectedFile}\r\n selectedUser={selectedUser}\r\n activeBuildingTab={activeBuildingTab}\r\n activeSiteTab={activeSiteTab}\r\n onSave={async () => {\r\n await handleCreateNewItem()\r\n setEditing(false)\r\n }}\r\n onEdit={() => {\r\n setEditing(true)\r\n if (isNewItem) setActiveChanges(true)\r\n }}\r\n onCancel={() => {\r\n setEditing(false)\r\n if (isNewItem) handleBackToTable()\r\n }}\r\n onDeleteUser={() => {\r\n setSelectedUser(null)\r\n setView('table')\r\n }}\r\n setView={setView}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* Detail view separator */}\r\n {view === 'detail' && <Separator />}\r\n </div>\r\n\r\n {/* Scrollable Content Area */}\r\n <div className=\"flex-1 overflow-hidden\">\r\n {view === 'table' ? (\r\n <div className=\"h-full flex flex-col md:p-6 overflow-auto\">\r\n <DataTable\r\n columns={currentViewer === ViewerNames.users ? userColumns : tableColumns}\r\n data={filteredData}\r\n onRowClick={handleRowClick}\r\n currentViewer={currentViewer}\r\n isLoading={isLoading}\r\n leadingCell={comparing\r\n ? ({ dataset }) => {\r\n const item = dataset\r\n const isChecked = compareItems.some(i => i?.id === String(item?.id))\r\n const maxReached = compareItems.length >= 3 && !isChecked\r\n\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"transition-opacity duration-200 hover:bg-transparent\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n if (isChecked) {\r\n removeItemFromCompare?.(String(item.id))\r\n } else {\r\n addItemToCompare?.({ ...item, id: String(item.id) })\r\n }\r\n }}\r\n >\r\n <Checkbox\r\n checked={isChecked}\r\n disabled={maxReached}\r\n className={`opacity-70 hover:opacity-100 data-[state=checked]:opacity-100 ${maxReached && '!cursor-default'}`}\r\n />\r\n </Button>\r\n )\r\n }\r\n : undefined}\r\n trailingCell={({ row }) => (\r\n <div onClick={e => e.stopPropagation()}>\r\n <MoreOptions\r\n row={row.original}\r\n dataType={dataType}\r\n hideViewOnMap={currentViewer === ViewerNames.users}\r\n setView={setView}\r\n onDeleteUser={() => setSelectedUser(null)}\r\n />\r\n </div>\r\n )}\r\n />\r\n </div>\r\n ) : (\r\n <div className=\"h-full overflow-auto\">\r\n {selectedFile\r\n ? (\r\n <FileDetails\r\n selectedFile={selectedFile}\r\n buildings={buildings || []}\r\n editing={editing}\r\n setEditing={setEditing}\r\n setActiveChanges={setActiveChanges}\r\n ref={fileDetailsRef}\r\n />\r\n )\r\n : currentViewer === ViewerNames.buildings\r\n ? (\r\n <BuildingDetails\r\n selectedItem={selectedItem}\r\n setSelectedItem={setSelectedItem}\r\n editing={editing}\r\n setEditing={setEditing}\r\n setActiveChanges={setActiveChanges}\r\n buildings={buildings || []}\r\n ref={buildingDetailsRef}\r\n activeTab={activeBuildingTab}\r\n setActiveTab={setActiveBuildingTab}\r\n />\r\n )\r\n : currentViewer === ViewerNames.sites\r\n ? (\r\n <SiteDetails\r\n selectedSite={selectedSite}\r\n setSelectedSite={setSelectedSite}\r\n editing={editing}\r\n setEditing={setEditing}\r\n setActiveChanges={setActiveChanges}\r\n sites={sites || []}\r\n ref={siteDetailsRef}\r\n activeTab={activeSiteTab}\r\n setActiveTab={setActiveSiteTab}\r\n />\r\n )\r\n : currentViewer === ViewerNames.infrastructure\r\n ? (\r\n <InfrastructureDetails\r\n selectedInfrastructure={selectedInfrastructure}\r\n setSelectedInfrastructure={setSelectedInfrastructure}\r\n editing={editing}\r\n setEditing={setEditing}\r\n setActiveChanges={setActiveChanges}\r\n infrastructures={infrastructures || []}\r\n ref={infrastructureDetailsRef}\r\n activeTab={activeInfrastructureTab}\r\n setActiveTab={setActiveInfrastructureTab}\r\n />\r\n )\r\n : currentViewer === ViewerNames.users\r\n ? (\r\n <UserDetails\r\n selectedUser={selectedUser}\r\n setSelectedUser={setSelectedUser}\r\n editing={editing}\r\n setEditing={setEditing}\r\n setActiveChanges={setActiveChanges}\r\n users={users || []}\r\n ref={userDetailsRef}\r\n hideTitle={hideTitle}\r\n />\r\n )\r\n : null}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}"],"mappings":"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","names":["_a","_b","_c"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/core/components/viewers/Data/DataMenu.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { toast } from 'sonner'\r\nimport { useTranslations } from 'next-intl'\r\nimport { handleApiError } from '../../../utils/errorHandler'\r\n\r\n// Utils\r\nimport { useViewerData } from './utils/useViewerData'\r\nimport { VIEWER_CONFIG } from './utils/viewerConfig'\r\n\r\nimport type { Building, Site, User, Infrastructure, Organization } from '../../../types/dbTypes'\r\nimport type { FilterState } from '../../../types/global'\r\n\r\n// Custom hooks\r\nimport { useBuildings, useCreateBuilding } from '../../../hooks/buildings/buildings'\r\nimport { useCreateSite, useSites } from '../../../hooks/sites/sites'\r\nimport { useFiles } from '../../../hooks/files/files'\r\nimport { useUsers } from '../../../hooks/users/users'\r\n\r\n// Context\r\nimport { useMenusContext } from '../../../store'\r\nimport { useBuildingsContext } from '../../../store'\r\nimport { useFilesContext } from '../../../store'\r\n\r\n// Types\r\nimport type { FileRow } from '../../../types/files'\r\nimport {\r\n Breadcrumb,\r\n BreadcrumbItem,\r\n BreadcrumbLink,\r\n BreadcrumbList,\r\n BreadcrumbPage,\r\n BreadcrumbSeparator,\r\n} from '../../ui/Breadcrumb'\r\nimport { Button, Checkbox, DataTable, Input, Separator } from '../../ui/'\r\n\r\nimport type { BuildingDetailsRef } from './buildingDetails/BuildingDetails'\r\nimport type { SiteDetailsRef } from './siteDetails/SiteDetails'\r\nimport type { InfrastructureDetailsRef } from './infrastructureDetails/InfrastructureDetails'\r\n\r\nimport BuildingDetails from './buildingDetails/BuildingDetails'\r\nimport { FileDetails } from './files/FileDetails'\r\n\r\n// Custom Components\r\nimport DetailActions from './details/DetailActions'\r\nimport DetailHeader from './details/DetailHeader'\r\nimport FilterButtons from './FilterButtons'\r\nimport HeaderButtons from './HeaderButtons'\r\nimport MoreOptions from './MoreOptions'\r\nimport SiteDetails from './siteDetails/SiteDetails'\r\nimport UserDetails from './userDetails/UserDetails'\r\n\r\n// Data\r\nimport { useColumns, useUserColumns } from './utils/Columns'\r\nimport { useBuildingHeaders, useInfrastructureHeaders, useSiteHeaders } from './utils/Headers'\r\nimport { DataTypes, DataTypesNames, ViewerNames } from '../../../types'\r\nimport { useSession } from 'next-auth/react'\r\nimport InfrastructureDetails from './infrastructureDetails/InfrastructureDetails'\r\nimport { useCreateInfrastructure, useInfrastructures } from '../../../hooks/infrastructures/infrastructures'\r\n\r\ntype DataMenuProps = {\r\n currentViewer: ViewerNames\r\n height?: string\r\n hideFrame?: boolean\r\n hideTitle?: boolean\r\n hideActions?: boolean\r\n organization?: Organization\r\n geocodeEarthApiKey?: string\r\n geocoderUrl?: string\r\n}\r\n\r\nexport function DataMenu({ currentViewer, height, hideTitle, hideActions, hideFrame, organization, geocodeEarthApiKey, geocoderUrl }: DataMenuProps) {\r\n // Translations\r\n const t = useTranslations('DataMenu')\r\n\r\n // View state\r\n const { view, setView } = useMenusContext()\r\n const { selectedItem, setSelectedItem } = useMenusContext()\r\n const { selectedSite, setSelectedSite } = useMenusContext()\r\n const { selectedInfrastructure, setSelectedInfrastructure } = useMenusContext()\r\n const { selectedFile, setSelectedFile } = useMenusContext()\r\n const { selectedUser, setSelectedUser } = useMenusContext()\r\n const { state: fileState } = useFilesContext()\r\n const { currentFile } = fileState.files\r\n\r\n // Search / filter state\r\n const [searchTerm, setSearchTerm] = React.useState('')\r\n const [activeFilters, setActiveFilters] = React.useState<FilterState[]>([])\r\n const [filters, setFilters] = React.useState([\r\n { id: 1, field: '', fieldType: null, operator: null, value: null, secondValue: null },\r\n ])\r\n\r\n const [dataType, setDataType] = React.useState<DataTypes>(DataTypesNames.building)\r\n const [editing, setEditing] = React.useState(false)\r\n const [activeChanges, setActiveChanges] = React.useState(false)\r\n\r\n // Tab headers\r\n const buildingHeaders = useBuildingHeaders()\r\n const siteHeaders = useSiteHeaders()\r\n const infrastructureHeaders = useInfrastructureHeaders()\r\n\r\n const buildingTabOptions = buildingHeaders.map(section => ({\r\n key: section.title.toLowerCase().replaceAll(/\\s/g, '-'),\r\n label: section.title,\r\n }))\r\n const siteTabOptions = siteHeaders.map(section => ({\r\n key: section.title.toLowerCase().replaceAll(/\\s/g, '-'),\r\n label: section.title,\r\n }))\r\n const infrastructureTabOptions = infrastructureHeaders.map(section => ({\r\n key: section.title.toLowerCase().replaceAll(/\\s/g, '-'),\r\n label: section.title,\r\n }))\r\n\r\n const [activeBuildingTab, setActiveBuildingTab] = React.useState(buildingTabOptions[0]?.key || '')\r\n const [activeSiteTab, setActiveSiteTab] = React.useState(siteTabOptions[0]?.key || '')\r\n const [activeInfrastructureTab, setActiveInfrastructureTab] = React.useState(infrastructureTabOptions[0]?.key || '')\r\n\r\n // Reset active tab only when selected item ID changes\r\n const prevBuildingId = React.useRef<number | undefined>(undefined)\r\n const prevInfrastructureId = React.useRef<number | undefined>(undefined)\r\n\r\n React.useEffect(() => {\r\n if (currentViewer === ViewerNames.buildings && selectedItem?.id !== prevBuildingId.current) {\r\n setActiveBuildingTab(buildingTabOptions[0]?.key || '')\r\n prevBuildingId.current = selectedItem?.id\r\n }\r\n if (currentViewer === ViewerNames.infrastructure && selectedInfrastructure?.id !== prevInfrastructureId.current) {\r\n setActiveInfrastructureTab(infrastructureTabOptions[0]?.key || '')\r\n prevInfrastructureId.current = selectedInfrastructure?.id\r\n }\r\n }, [selectedItem?.id, selectedInfrastructure?.id, currentViewer])\r\n\r\n const [newItemName, setNewItemName] = React.useState('')\r\n\r\n // Compare state\r\n const {\r\n compareItems,\r\n setCompareItems,\r\n comparing,\r\n setComparing,\r\n addItemToCompare,\r\n removeItemFromCompare,\r\n } = useBuildingsContext()\r\n\r\n // Sync dataType with current viewer. ViewerNames are plural ('sites',\r\n // 'buildings', …) while DataTypes are singular ('site', 'building', …), so a\r\n // direct index returns undefined for most viewers — map explicitly.\r\n React.useEffect(() => {\r\n const viewerToDataType: Partial<Record<string, DataTypes>> = {\r\n [ViewerNames.buildings]: DataTypesNames.building,\r\n [ViewerNames.sites]: DataTypesNames.site,\r\n [ViewerNames.infrastructure]: DataTypesNames.infrastructure,\r\n [ViewerNames.files]: DataTypesNames.file,\r\n [ViewerNames.users]: DataTypesNames.user,\r\n }\r\n setDataType(viewerToDataType[currentViewer] ?? DataTypesNames.building)\r\n }, [currentViewer])\r\n\r\n // Reset compare state when viewer changes\r\n React.useEffect(() => {\r\n setComparing(false)\r\n setCompareItems([])\r\n }, [currentViewer, setComparing, setCompareItems])\r\n\r\n // Data fetching\r\n const { buildings, isLoading: buildingsLoading, isError: buildingsError } = useBuildings()\r\n const { sites, isLoading: sitesLoading, isError: sitesError } = useSites()\r\n const { infrastructures, isLoading: infrastructuresLoading, isError: infrastructuresError } = useInfrastructures()\r\n const { files, isLoading: filesLoading, isError: filesError } = useFiles()\r\n const { users, isLoading: usersLoading, isError: usersError } = useUsers()\r\n\r\n const { createError: createSiteError } = useCreateSite()\r\n const { createError: createBuildingError } = useCreateBuilding()\r\n const { createError: createInfrastructureError } = useCreateInfrastructure()\r\n\r\n React.useEffect(() => {\r\n handleApiError(buildingsError)\r\n handleApiError(sitesError)\r\n handleApiError(filesError)\r\n handleApiError(infrastructuresError)\r\n handleApiError(usersError)\r\n handleApiError(createSiteError)\r\n handleApiError(createBuildingError)\r\n handleApiError(createInfrastructureError)\r\n }, [buildingsError, sitesError, infrastructuresError, filesError, usersError, createSiteError, createBuildingError, createInfrastructureError])\r\n\r\n const tableColumns = useColumns(buildings || [])\r\n const userColumns = useUserColumns()\r\n\r\n const { user } = useSession().data\r\n\r\n // Viewer config — resolves icon and i18n title key\r\n const viewerConfig = VIEWER_CONFIG[currentViewer]\r\n const headerTitle = t(viewerConfig.titleKey)\r\n const MenuIcon = viewerConfig.icon\r\n\r\n // Derived data, filtered data, and filter options — all per-viewer logic lives in this hook\r\n const { data, filteredData, filtersOptions, isLoading } = useViewerData({\r\n currentViewer,\r\n buildings,\r\n sites,\r\n infrastructures,\r\n files,\r\n users,\r\n loadingFlags: {\r\n buildings: buildingsLoading,\r\n sites: sitesLoading,\r\n infrastructures: infrastructuresLoading,\r\n files: filesLoading,\r\n users: usersLoading,\r\n },\r\n searchTerm,\r\n activeFilters,\r\n filters,\r\n userEmail: user?.email || '',\r\n })\r\n\r\n const openedCurrentFileIdRef = React.useRef<number | null>(null)\r\n\r\n React.useEffect(() => {\r\n if (currentViewer !== ViewerNames.files || !currentFile) return\r\n if (openedCurrentFileIdRef.current === currentFile.id) return\r\n\r\n const fileRow = data.find((item): item is FileRow => String(item.id) === String(currentFile.id))\r\n if (!fileRow) return\r\n\r\n openedCurrentFileIdRef.current = currentFile.id\r\n setSelectedFile(fileRow)\r\n setView('detail')\r\n }, [currentViewer, currentFile, data, setSelectedFile, setView])\r\n\r\n // Breadcrumb title — derives the detail page label from whichever item is selected\r\n const breadcrumbTitle = React.useMemo(() => {\r\n if (selectedItem) return selectedItem.buildingName || selectedItem.buildingAddress\r\n if (selectedSite) return selectedSite.siteName || selectedSite.siteAddress\r\n if (selectedInfrastructure) return selectedInfrastructure.infrastructureName || selectedInfrastructure.infrastructureType\r\n if (selectedFile) return selectedFile.name\r\n if (selectedUser) return selectedUser.name\r\n if (currentViewer === ViewerNames.extensions) return 'Extension Details'\r\n return undefined\r\n }, [selectedItem, selectedSite, selectedInfrastructure, selectedFile, selectedUser, currentViewer])\r\n\r\n // Row click handlers — consolidated into one function\r\n\r\n const handleRowClick = (item: Building | Site | Infrastructure | FileRow | User) => {\r\n // Files and users don't participate in compare mode\r\n if (comparing && 'id' in item) {\r\n const id = String(item.id)\r\n const isChecked = compareItems.some(i => i.id === id)\r\n if (isChecked) {\r\n removeItemFromCompare(id)\r\n } else {\r\n addItemToCompare({ ...item, id })\r\n }\r\n return\r\n }\r\n\r\n // Navigate to detail view, setting the correct selected item per viewer\r\n switch (currentViewer) {\r\n case ViewerNames.buildings:\r\n setSelectedItem(item as Building)\r\n break\r\n case ViewerNames.sites:\r\n setSelectedSite(item as Site)\r\n break\r\n case ViewerNames.infrastructure:\r\n setSelectedInfrastructure(item as Infrastructure)\r\n break\r\n case ViewerNames.files:\r\n setSelectedFile(item as FileRow)\r\n break\r\n case ViewerNames.users:\r\n setSelectedUser(item as User)\r\n break\r\n }\r\n setView('detail')\r\n }\r\n\r\nconst handleBackToTable = () => {\r\n setView('table')\r\n setSelectedItem(null)\r\n setSelectedSite(null)\r\n setSelectedInfrastructure(null)\r\n setSelectedFile(null)\r\n setSelectedUser(null)\r\n setEditing(false)\r\n setActiveChanges(false)\r\n }\r\n\r\n // Refs for imperative save on child detail components\r\n\r\n const buildingDetailsRef = React.useRef<BuildingDetailsRef>(null)\r\n const siteDetailsRef = React.useRef<SiteDetailsRef>(null)\r\n const infrastructureDetailsRef = React.useRef<InfrastructureDetailsRef>(null)\r\n const fileDetailsRef = React.useRef(null)\r\n const userDetailsRef = React.useRef(null)\r\n\r\n // Save / create handlers — consolidated into one function\r\n\r\n const handleSaveChanges = async () => {\r\n switch (currentViewer) {\r\n case ViewerNames.buildings:\r\n await buildingDetailsRef.current?.saveChanges()\r\n break\r\n case ViewerNames.sites:\r\n await siteDetailsRef.current?.saveChanges()\r\n break\r\n case ViewerNames.infrastructure:\r\n await infrastructureDetailsRef.current?.saveChanges()\r\n break\r\n case ViewerNames.files:\r\n await fileDetailsRef.current?.saveChanges()\r\n break\r\n case ViewerNames.users:\r\n await userDetailsRef.current?.saveChanges()\r\n break\r\n }\r\n }\r\n\r\n /**\r\n * Handles creation of a new entity (id < 0).\r\n * Calls saveChanges on the appropriate ref, then shows a toast.\r\n * Pass successKey as undefined for viewers that show their own success toast (e.g. buildings).\r\n */\r\n const handleCreate = async (\r\n ref: React.RefObject<{ saveChanges: () => Promise<void> }>,\r\n toastKeys: { successKey?: string; errorKey: string },\r\n ) => {\r\n try {\r\n await ref.current?.saveChanges()\r\n setActiveChanges(false)\r\n if (toastKeys.successKey) toast.success(t(toastKeys.successKey))\r\n } catch (error) {\r\n if (error?.status !== 401) toast.error(t(toastKeys.errorKey))\r\n }\r\n }\r\n\r\n // Dispatches to the right ref + toast keys based on which new item is selected\r\n const handleCreateNewItem = async () => {\r\n if (selectedSite && selectedSite.id < 0) {\r\n await handleCreate(siteDetailsRef, {\r\n successKey: 'toastSuccessCreateSite',\r\n errorKey: 'toastFailCreateSite',\r\n })\r\n } else if (selectedItem && selectedItem.id < 0) {\r\n await handleCreate(buildingDetailsRef, {\r\n // Building details shows its own success toast\r\n errorKey: 'toastFailCreateBuilding',\r\n })\r\n } else if (selectedInfrastructure && selectedInfrastructure.id < 0) {\r\n await handleCreate(infrastructureDetailsRef, {\r\n successKey: 'toastSuccessCreateInfrastructure',\r\n errorKey: 'toastFailCreateInfrastructure',\r\n })\r\n } else {\r\n // Users and existing items — standard save\r\n await handleSaveChanges()\r\n }\r\n }\r\n\r\n // Derived UI helpers\r\n\r\n const isNewItem = !!(\r\n (selectedSite && selectedSite.id < 0)\r\n || (selectedItem && selectedItem.id < 0)\r\n || (selectedInfrastructure && selectedInfrastructure.id < 0)\r\n )\r\n\r\n // Render\r\n\r\n return (\r\n <div className={`${hideFrame ? '' : 'sm:p-2'} overflow-hidden ${hideFrame ? '' : 'bg-[#fafafa]'} ${height ? height : 'h-full'}`}>\r\n <div className={`${hideFrame ? '' : 'bg-background rounded-xl shadow'} h-full min-h-0`}>\r\n <div className=\"flex flex-col h-full min-h-0\">\r\n\r\n {/* Breadcrumb Navigation */}\r\n <div className=\"\">\r\n <div className=\"flex flex-row gap-2 justify-start items-center px-3 py-4 relative\">\r\n <Breadcrumb className=\"px-3\">\r\n <BreadcrumbList>\r\n <BreadcrumbItem>\r\n {view === 'table'\r\n ? <BreadcrumbPage>{headerTitle}</BreadcrumbPage>\r\n : (\r\n <BreadcrumbLink onClick={handleBackToTable} className=\"cursor-pointer\">\r\n {headerTitle}\r\n </BreadcrumbLink>\r\n )}\r\n </BreadcrumbItem>\r\n\r\n {view === 'detail' && (\r\n <>\r\n <BreadcrumbSeparator />\r\n <BreadcrumbItem>\r\n <BreadcrumbPage>{breadcrumbTitle}</BreadcrumbPage>\r\n </BreadcrumbItem>\r\n </>\r\n )}\r\n </BreadcrumbList>\r\n </Breadcrumb>\r\n </div>\r\n\r\n {/* Header content based on view */}\r\n {view === 'table' ? (\r\n <>\r\n {/* Title Row */}\r\n {!hideTitle && (\r\n <div className=\"flex flex-row justify-between items-center px-6 py-6\">\r\n <div className=\"flex flex-col gap-1.5\">\r\n <div className=\"flex items-center gap-2\">\r\n <MenuIcon className=\"h-8 w-8\" />\r\n <h1 className=\"text-2xl text-foreground\">{headerTitle}</h1>\r\n </div>\r\n {comparing && (\r\n <h2 className=\"text-sm text-muted-foreground font-normal\">\r\n Choose up to 3 {headerTitle.toLowerCase()} to compare.\r\n </h2>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Search & Filter & Actions Row */}\r\n <div className={`flex ${hideTitle ? 'justify-between' : 'justify-end'} items-center px-6 py-4 gap-4`}>\r\n <div className={hideTitle ? 'w-64' : 'w-96'}>\r\n <Input\r\n placeholder={`${t('searchPlaceholder')} ${headerTitle}...`}\r\n value={searchTerm}\r\n onChange={e => setSearchTerm(e.target.value)}\r\n />\r\n </div>\r\n\r\n <div className=\"flex gap-2\">\r\n <FilterButtons\r\n currentViewer={currentViewer}\r\n filters={filters}\r\n activeFilters={activeFilters}\r\n filterFields={filtersOptions}\r\n data={data}\r\n setFilters={setFilters}\r\n setActiveFilters={setActiveFilters}\r\n />\r\n <HeaderButtons\r\n headerTitle={headerTitle}\r\n currentViewer={currentViewer}\r\n compareItems={compareItems}\r\n setCompareItems={setCompareItems}\r\n comparing={comparing}\r\n setComparing={setComparing}\r\n newItemName={newItemName}\r\n setNewItemName={setNewItemName}\r\n filteredData={\r\n currentViewer === ViewerNames.buildings\r\n || currentViewer === ViewerNames.sites\r\n || currentViewer === ViewerNames.infrastructure\r\n ? filteredData\r\n : undefined\r\n }\r\n users={currentViewer === ViewerNames.users ? users : undefined}\r\n geocodeEarthApiKey={geocodeEarthApiKey}\r\n geocoderUrl={geocoderUrl}\r\n />\r\n </div>\r\n </div>\r\n\r\n <Separator />\r\n </>\r\n ) : (\r\n // Detail View Header\r\n <div className=\"flex justify-between items-center px-6 py-6\">\r\n <DetailHeader\r\n selectedItem={selectedItem}\r\n selectedSite={selectedSite}\r\n selectedInfrastructure={selectedInfrastructure}\r\n selectedFile={selectedFile}\r\n selectedUser={selectedUser}\r\n countryCode={organization?.country}\r\n />\r\n\r\n <DetailActions\r\n editing={editing}\r\n activeChanges={activeChanges}\r\n currentViewer={currentViewer}\r\n selectedItem={selectedItem}\r\n selectedSite={selectedSite}\r\n selectedInfrastructure={selectedInfrastructure}\r\n selectedFile={selectedFile}\r\n selectedUser={selectedUser}\r\n activeBuildingTab={activeBuildingTab}\r\n activeSiteTab={activeSiteTab}\r\n onSave={async () => {\r\n await handleCreateNewItem()\r\n setEditing(false)\r\n }}\r\n onEdit={() => {\r\n setEditing(true)\r\n if (isNewItem) setActiveChanges(true)\r\n }}\r\n onCancel={() => {\r\n setEditing(false)\r\n if (isNewItem) handleBackToTable()\r\n }}\r\n onDeleteUser={() => {\r\n setSelectedUser(null)\r\n setView('table')\r\n }}\r\n setView={setView}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* Detail view separator */}\r\n {view === 'detail' && <Separator />}\r\n </div>\r\n\r\n {/* Scrollable Content Area */}\r\n <div className=\"flex-1 overflow-hidden\">\r\n {view === 'table' ? (\r\n <div className=\"h-full flex flex-col md:p-6 overflow-auto\">\r\n <DataTable\r\n columns={currentViewer === ViewerNames.users ? userColumns : tableColumns}\r\n data={filteredData}\r\n onRowClick={handleRowClick}\r\n currentViewer={currentViewer}\r\n isLoading={isLoading}\r\n leadingCell={comparing\r\n ? ({ dataset }) => {\r\n const item = dataset\r\n const isChecked = compareItems.some(i => i?.id === String(item?.id))\r\n const maxReached = compareItems.length >= 3 && !isChecked\r\n\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"transition-opacity duration-200 hover:bg-transparent\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n if (isChecked) {\r\n removeItemFromCompare?.(String(item.id))\r\n } else {\r\n addItemToCompare?.({ ...item, id: String(item.id) })\r\n }\r\n }}\r\n >\r\n <Checkbox\r\n checked={isChecked}\r\n disabled={maxReached}\r\n className={`opacity-70 hover:opacity-100 data-[state=checked]:opacity-100 ${maxReached && '!cursor-default'}`}\r\n />\r\n </Button>\r\n )\r\n }\r\n : undefined}\r\n trailingCell={({ row }) => (\r\n <div onClick={e => e.stopPropagation()}>\r\n <MoreOptions\r\n row={row.original}\r\n dataType={dataType}\r\n hideViewOnMap={currentViewer === ViewerNames.users}\r\n setView={setView}\r\n onDeleteUser={() => setSelectedUser(null)}\r\n />\r\n </div>\r\n )}\r\n />\r\n </div>\r\n ) : (\r\n <div className=\"h-full overflow-auto\">\r\n {selectedFile\r\n ? (\r\n <FileDetails\r\n selectedFile={selectedFile}\r\n buildings={buildings || []}\r\n editing={editing}\r\n setEditing={setEditing}\r\n setActiveChanges={setActiveChanges}\r\n ref={fileDetailsRef}\r\n />\r\n )\r\n : currentViewer === ViewerNames.buildings\r\n ? (\r\n <BuildingDetails\r\n selectedItem={selectedItem}\r\n setSelectedItem={setSelectedItem}\r\n editing={editing}\r\n setEditing={setEditing}\r\n setActiveChanges={setActiveChanges}\r\n buildings={buildings || []}\r\n ref={buildingDetailsRef}\r\n activeTab={activeBuildingTab}\r\n setActiveTab={setActiveBuildingTab}\r\n />\r\n )\r\n : currentViewer === ViewerNames.sites\r\n ? (\r\n <SiteDetails\r\n selectedSite={selectedSite}\r\n setSelectedSite={setSelectedSite}\r\n editing={editing}\r\n setEditing={setEditing}\r\n setActiveChanges={setActiveChanges}\r\n sites={sites || []}\r\n ref={siteDetailsRef}\r\n activeTab={activeSiteTab}\r\n setActiveTab={setActiveSiteTab}\r\n />\r\n )\r\n : currentViewer === ViewerNames.infrastructure\r\n ? (\r\n <InfrastructureDetails\r\n selectedInfrastructure={selectedInfrastructure}\r\n setSelectedInfrastructure={setSelectedInfrastructure}\r\n editing={editing}\r\n setEditing={setEditing}\r\n setActiveChanges={setActiveChanges}\r\n infrastructures={infrastructures || []}\r\n ref={infrastructureDetailsRef}\r\n activeTab={activeInfrastructureTab}\r\n setActiveTab={setActiveInfrastructureTab}\r\n />\r\n )\r\n : currentViewer === ViewerNames.users\r\n ? (\r\n <UserDetails\r\n selectedUser={selectedUser}\r\n setSelectedUser={setSelectedUser}\r\n editing={editing}\r\n setEditing={setEditing}\r\n setActiveChanges={setActiveChanges}\r\n users={users || []}\r\n ref={userDetailsRef}\r\n hideTitle={hideTitle}\r\n />\r\n )\r\n : null}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}"],"mappings":"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","names":["_a","_b","_c"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeaderButtons.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/Data/HeaderButtons.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAA;AAGlE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAmBjD,KAAK,kBAAkB,GAAG;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,eAAe,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;IACrE,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;IAC3D,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAA;IAC5D,YAAY,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAA;IACrC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EACpC,WAAW,EACX,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EACT,YAAY,EACZ,WAAW,EACX,cAAc,EACd,YAAY,EACZ,KAAK,EACL,kBAAkB,EAClB,WAAW,GACZ,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"HeaderButtons.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/Data/HeaderButtons.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAA;AAGlE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAmBjD,KAAK,kBAAkB,GAAG;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,eAAe,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;IACrE,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;IAC3D,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAA;IAC5D,YAAY,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAA;IACrC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EACpC,WAAW,EACX,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EACT,YAAY,EACZ,WAAW,EACX,cAAc,EACd,YAAY,EACZ,KAAK,EACL,kBAAkB,EAClB,WAAW,GACZ,EAAE,kBAAkB,qBAuOpB"}
|
|
@@ -25,8 +25,8 @@ import { useTranslations } from "next-intl";
|
|
|
25
25
|
import { usePermissions } from "../../../store";
|
|
26
26
|
import { DatasetsContext, MapContext, MenusContext } from "../../../store";
|
|
27
27
|
import { Button } from "../../../components/ui/Button";
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
28
|
+
import { fitBuildingsBounds } from "../map/utils/fitBuildingsBounds";
|
|
29
|
+
import { useShowSitesOnMap } from "../map/src/MapLayers/src/SiteLayer/useShowSitesOnMap";
|
|
30
30
|
import AddBuilding from "./buildingDetails/AddBuilding";
|
|
31
31
|
import DatatableFileAdder from "./files/DatatableFileAdder";
|
|
32
32
|
import AddSite from "./siteDetails/AddSite";
|
|
@@ -62,6 +62,7 @@ function HeaderButtons({
|
|
|
62
62
|
const [addBuildingOpen, setAddBuildingOpen] = React.useState(false);
|
|
63
63
|
const [addUserOpen, setAddUserOpen] = React.useState(false);
|
|
64
64
|
const { map } = mapState.map;
|
|
65
|
+
const showSitesOnMap = useShowSitesOnMap();
|
|
65
66
|
const firstBuilding = compareItems[0];
|
|
66
67
|
const coordinates = firstBuilding ? "buildingLongitude" in firstBuilding && "buildingLatitude" in firstBuilding ? [firstBuilding.buildingLongitude, firstBuilding.buildingLatitude] : "coordinates" in firstBuilding : void 0;
|
|
67
68
|
const handleViewOnMap = () => {
|
|
@@ -101,18 +102,10 @@ function HeaderButtons({
|
|
|
101
102
|
});
|
|
102
103
|
fitBuildingsBounds(validBuildings, map);
|
|
103
104
|
} else if (currentViewer === "sites") {
|
|
104
|
-
const validSites = filteredData.filter(
|
|
105
|
-
(item) => item.siteLongitude != null && item.siteLatitude != null
|
|
106
|
-
);
|
|
105
|
+
const validSites = (filteredData != null ? filteredData : []).filter((item) => !!(item == null ? void 0 : item.id));
|
|
107
106
|
if (validSites.length === 0)
|
|
108
107
|
return;
|
|
109
|
-
|
|
110
|
-
const dataset = createSitesDataset(validSites, name);
|
|
111
|
-
datasetDispatch({
|
|
112
|
-
type: "ADD_DATASET_TO_MAP",
|
|
113
|
-
payload: { dataset }
|
|
114
|
-
});
|
|
115
|
-
fitSitesBounds(validSites, map);
|
|
108
|
+
await showSitesOnMap(validSites, { switchViewer: false });
|
|
116
109
|
} else if (currentViewer === "infrastructure") {
|
|
117
110
|
}
|
|
118
111
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/core/components/viewers/Data/HeaderButtons.tsx"],"sourcesContent":["\"use client\"\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { usePermissions } from '../../../store'\r\n\r\n// Utils\r\nimport type { Dataset } from '../../../types/datasetTypes'\r\nimport type { Building, Site, User } from '../../../types/dbTypes'\r\n\r\nimport { DatasetsContext, MapContext, MenusContext } from '../../../store'\r\nimport type { CompareItem } from '../../../store'\r\n\r\n// Shadcn Components\r\nimport { Button } from '../../../components/ui/Button'\r\nimport { createSitesDataset } from '../map/src/MapLayers/src/SiteLayer'\r\nimport { fitBuildingsBounds, fitSitesBounds } from '../map/utils/fitBuildingsBounds'\r\nimport AddBuilding from './buildingDetails/AddBuilding'\r\n// File Adder\r\nimport DatatableFileAdder from './files/DatatableFileAdder'\r\n// Custom Components\r\nimport AddSite from './siteDetails/AddSite'\r\nimport CompareDialog from '../map/src/compare/CompareDialog'\r\nimport UserMoreOptions from './userDetails/UserMoreOptions'\r\nimport AddUser from './userDetails/AddUser'\r\nimport BuildingMoreOptions from './buildingDetails/BuildingsMoreOptions'\r\nimport { ViewerNames } from '../../../types/'\r\nimport AddInfrastructure from './infrastructureDetails/AddInfrastructure'\r\nimport { createBuildingsDataset } from '../map/src/MapLayers/src/BuildingLayers/src/databaseBuildings'\r\n\r\ntype HeaderButtonsProps = {\r\n headerTitle: string\r\n currentViewer: string\r\n compareItems: CompareItem[]\r\n setCompareItems?: React.Dispatch<React.SetStateAction<CompareItem[]>>\r\n comparing: boolean\r\n setComparing: React.Dispatch<React.SetStateAction<boolean>>\r\n newItemName: string\r\n setNewItemName: React.Dispatch<React.SetStateAction<string>>\r\n filteredData?: Array<Building | Site>\r\n users?: User[]\r\n geocodeEarthApiKey?: string\r\n geocoderUrl?: string\r\n}\r\n\r\nexport default function HeaderButtons({\r\n headerTitle,\r\n currentViewer,\r\n compareItems,\r\n setCompareItems,\r\n comparing,\r\n setComparing,\r\n newItemName,\r\n setNewItemName,\r\n filteredData,\r\n users,\r\n geocodeEarthApiKey,\r\n geocoderUrl,\r\n}: HeaderButtonsProps) {\r\n // Translations\r\n const t = useTranslations('HeaderButtons')\r\n\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const { state: mapState } = React.useContext(MapContext)\r\n const { dispatch: datasetDispatch } = React.useContext(DatasetsContext)\r\n const { dispatch: menusDispatch } = React.useContext(MenusContext)\r\n const [newBuildingFields, setNewBuildingFields] = React.useState({})\r\n const [newInfrastructureFields, setNewInfrastructureFields] = React.useState({})\r\n const [addInfrastructureOpen, setAddInfrastructureOpen] = React.useState(false)\r\n const [addBuildingOpen, setAddBuildingOpen] = React.useState(false)\r\n const [addUserOpen, setAddUserOpen] = React.useState(false)\r\n\r\n const { map } = mapState.map\r\n const firstBuilding = compareItems[0]\r\n\r\n const coordinates = firstBuilding\r\n ? (('buildingLongitude' in firstBuilding && 'buildingLatitude' in firstBuilding)\r\n ? [firstBuilding.buildingLongitude, firstBuilding.buildingLatitude]\r\n : ('coordinates' in firstBuilding))\r\n : undefined\r\n\r\n const handleViewOnMap = () => {\r\n // set the current viewer to map\r\n menusDispatch({\r\n type: 'SET_VIEWER',\r\n payload: { currentViewer: ViewerNames.map },\r\n })\r\n }\r\n\r\n const handleViewAllOnMap = async () => {\r\n if (filteredData.length === 0)\r\n return\r\n\r\n // Switch to map view\r\n menusDispatch({\r\n type: 'SET_VIEWER',\r\n payload: { currentViewer: ViewerNames.map },\r\n })\r\n\r\n if (currentViewer === 'buildings') {\r\n // Filter buildings with valid coordinates\r\n const validBuildings = filteredData.filter(\r\n (item): item is Building => {\r\n const b = item as Building\r\n const lon = b.buildingLongitude\r\n const lat = b.buildingLatitude\r\n if (lon == null || lat == null) return false\r\n\r\n // Rough North America bounding box\r\n const minLat = 5\r\n const maxLat = 85\r\n const minLon = -170\r\n const maxLon = -10\r\n\r\n return Number.isFinite(lat)\r\n && Number.isFinite(lon)\r\n && lat >= minLat\r\n && lat <= maxLat\r\n && lon >= minLon\r\n && lon <= maxLon\r\n }\r\n )\r\n\r\n if (validBuildings.length === 0)\r\n return\r\n\r\n const name = 'Database Buildings'\r\n\r\n const dataset: Dataset = createBuildingsDataset(validBuildings, name)\r\n\r\n // Add buildings as a dataset to the map state\r\n datasetDispatch({\r\n type: 'ADD_DATASET_TO_MAP',\r\n payload: { dataset },\r\n })\r\n\r\n fitBuildingsBounds(validBuildings, map)\r\n }\r\n\r\n else if (currentViewer === 'sites') {\r\n // Filter sites with valid coordinates\r\n const validSites = filteredData.filter(\r\n (item): item is Site =>\r\n (item as Site).siteLongitude != null && (item as Site).siteLatitude != null\r\n )\r\n\r\n if (validSites.length === 0)\r\n return\r\n\r\n const name = 'Database Sites'\r\n\r\n const dataset: Dataset = createSitesDataset(validSites, name)\r\n\r\n // Add buildings as a dataset to the map state\r\n datasetDispatch({\r\n type: 'ADD_DATASET_TO_MAP',\r\n payload: { dataset },\r\n })\r\n\r\n fitSitesBounds(validSites, map)\r\n }\r\n\r\n else if (currentViewer === 'infrastructure') {\r\n // Filter infrastructure with valid coordinates\r\n }\r\n\r\n\r\n }\r\n\r\n const handleAddBuilding = (building: Building) => {\r\n if (setCompareItems) {\r\n const compareItem: CompareItem = {\r\n ...building,\r\n id: String(building.id),\r\n }\r\n setCompareItems([...compareItems, compareItem])\r\n }\r\n }\r\n\r\n const toggleOpen = () => {\r\n setComparing(false)\r\n // Clear compareItems when exiting compare mode for proper cleanup\r\n if (setCompareItems) {\r\n setCompareItems([])\r\n }\r\n }\r\n\r\n return (\r\n <div className=\"flex flex-row gap-2.5\">\r\n {comparing\r\n ? (\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => {\r\n setComparing(false)\r\n // Clear compareItems for proper cleanup when canceling\r\n if (setCompareItems) {\r\n setCompareItems([])\r\n }\r\n }}\r\n disabled={currentViewer === 'buildings' && !ability.can('read', 'Building') || currentViewer === 'sites' && !ability.can('read', 'Site')}\r\n >\r\n {t('cancelButton')}\r\n </Button>\r\n )\r\n : currentViewer === 'files'\r\n ? (\r\n <DatatableFileAdder />\r\n )\r\n : currentViewer === 'buildings'\r\n ? (\r\n <>\r\n <Button\r\n variant=\"default\"\r\n onClick={() => setAddBuildingOpen(true)}\r\n disabled={!ability.can('create', 'Building')}\r\n >\r\n <LR.CirclePlus />\r\n {t('addBuilding')}\r\n </Button>\r\n <AddBuilding\r\n newBuildingFields={newBuildingFields}\r\n setNewBuildingFields={setNewBuildingFields}\r\n open={addBuildingOpen}\r\n onOpenChange={setAddBuildingOpen}\r\n geocodeEarthApiKey={geocodeEarthApiKey}\r\n geocoderUrl={geocoderUrl}\r\n />\r\n <BuildingMoreOptions buildings={filteredData as Building[]} variant=\"outline\" />\r\n </>\r\n )\r\n : currentViewer === 'sites'\r\n ? (\r\n <AddSite\r\n newItemName={newItemName}\r\n setNewItemName={setNewItemName}\r\n />\r\n )\r\n : currentViewer === 'infrastructure'\r\n ? (\r\n <AddInfrastructure\r\n newInfrastructureFields={newInfrastructureFields}\r\n setNewInfrastructureFields={setNewInfrastructureFields}\r\n open={addInfrastructureOpen}\r\n onOpenChange={setAddInfrastructureOpen}\r\n />\r\n )\r\n : currentViewer === 'users'\r\n ? (\r\n <>\r\n <Button\r\n variant=\"default\"\r\n onClick={() => setAddUserOpen(true)}\r\n disabled={!ability.can('create', 'User')}\r\n >\r\n <LR.CirclePlus />\r\n {t('addUser')}\r\n </Button>\r\n <AddUser open={addUserOpen} onOpenChange={setAddUserOpen} />\r\n <UserMoreOptions users={users} variant=\"outline\" />\r\n </>\r\n )\r\n : null}\r\n\r\n {/* Compare Button/Dialog */}\r\n {comparing\r\n ? (\r\n <CompareDialog\r\n toggleOpen={toggleOpen}\r\n compareItems={compareItems}\r\n setCompareItems={setCompareItems || (() => {})}\r\n handleAddBuilding={handleAddBuilding}\r\n />\r\n )\r\n : (\r\n <Button\r\n variant=\"secondary\"\r\n className={`max-sm:hidden ${(currentViewer === ViewerNames.files || currentViewer === ViewerNames.extensions || currentViewer === ViewerNames.users) ? 'hidden' : ''}`}\r\n onClick={() => setComparing(true)}\r\n >\r\n <LR.GitCompare />\r\n {t('compare')}\r\n {' '}\r\n {headerTitle}\r\n </Button>\r\n )}\r\n {(currentViewer === 'buildings' || currentViewer === 'sites') && filteredData && (\r\n <Button\r\n variant=\"outline\"\r\n onClick={handleViewAllOnMap}\r\n disabled={filteredData.length === 0 || currentViewer === 'buildings' &&!ability.can('read', 'Building') || currentViewer === 'sites' && !ability.can('read', 'Site')}\r\n >\r\n <LR.Map className=\"\" />\r\n {t('viewButton')}\r\n </Button>\r\n )}\r\n </div>\r\n )\r\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/core/components/viewers/Data/HeaderButtons.tsx"],"sourcesContent":["\"use client\"\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { usePermissions } from '../../../store'\r\n\r\n// Utils\r\nimport type { Dataset } from '../../../types/datasetTypes'\r\nimport type { Building, Site, User } from '../../../types/dbTypes'\r\n\r\nimport { DatasetsContext, MapContext, MenusContext } from '../../../store'\r\nimport type { CompareItem } from '../../../store'\r\n\r\n// Shadcn Components\r\nimport { Button } from '../../../components/ui/Button'\r\nimport { fitBuildingsBounds } from '../map/utils/fitBuildingsBounds'\r\nimport { useShowSitesOnMap } from '../map/src/MapLayers/src/SiteLayer/useShowSitesOnMap'\r\nimport AddBuilding from './buildingDetails/AddBuilding'\r\n// File Adder\r\nimport DatatableFileAdder from './files/DatatableFileAdder'\r\n// Custom Components\r\nimport AddSite from './siteDetails/AddSite'\r\nimport CompareDialog from '../map/src/compare/CompareDialog'\r\nimport UserMoreOptions from './userDetails/UserMoreOptions'\r\nimport AddUser from './userDetails/AddUser'\r\nimport BuildingMoreOptions from './buildingDetails/BuildingsMoreOptions'\r\nimport { ViewerNames } from '../../../types/'\r\nimport AddInfrastructure from './infrastructureDetails/AddInfrastructure'\r\nimport { createBuildingsDataset } from '../map/src/MapLayers/src/BuildingLayers/src/databaseBuildings'\r\n\r\ntype HeaderButtonsProps = {\r\n headerTitle: string\r\n currentViewer: string\r\n compareItems: CompareItem[]\r\n setCompareItems?: React.Dispatch<React.SetStateAction<CompareItem[]>>\r\n comparing: boolean\r\n setComparing: React.Dispatch<React.SetStateAction<boolean>>\r\n newItemName: string\r\n setNewItemName: React.Dispatch<React.SetStateAction<string>>\r\n filteredData?: Array<Building | Site>\r\n users?: User[]\r\n geocodeEarthApiKey?: string\r\n geocoderUrl?: string\r\n}\r\n\r\nexport default function HeaderButtons({\r\n headerTitle,\r\n currentViewer,\r\n compareItems,\r\n setCompareItems,\r\n comparing,\r\n setComparing,\r\n newItemName,\r\n setNewItemName,\r\n filteredData,\r\n users,\r\n geocodeEarthApiKey,\r\n geocoderUrl,\r\n}: HeaderButtonsProps) {\r\n // Translations\r\n const t = useTranslations('HeaderButtons')\r\n\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const { state: mapState } = React.useContext(MapContext)\r\n const { dispatch: datasetDispatch } = React.useContext(DatasetsContext)\r\n const { dispatch: menusDispatch } = React.useContext(MenusContext)\r\n const [newBuildingFields, setNewBuildingFields] = React.useState({})\r\n const [newInfrastructureFields, setNewInfrastructureFields] = React.useState({})\r\n const [addInfrastructureOpen, setAddInfrastructureOpen] = React.useState(false)\r\n const [addBuildingOpen, setAddBuildingOpen] = React.useState(false)\r\n const [addUserOpen, setAddUserOpen] = React.useState(false)\r\n\r\n const { map } = mapState.map\r\n const showSitesOnMap = useShowSitesOnMap()\r\n const firstBuilding = compareItems[0]\r\n\r\n const coordinates = firstBuilding\r\n ? (('buildingLongitude' in firstBuilding && 'buildingLatitude' in firstBuilding)\r\n ? [firstBuilding.buildingLongitude, firstBuilding.buildingLatitude]\r\n : ('coordinates' in firstBuilding))\r\n : undefined\r\n\r\n const handleViewOnMap = () => {\r\n // set the current viewer to map\r\n menusDispatch({\r\n type: 'SET_VIEWER',\r\n payload: { currentViewer: ViewerNames.map },\r\n })\r\n }\r\n\r\n const handleViewAllOnMap = async () => {\r\n if (filteredData.length === 0)\r\n return\r\n\r\n // Switch to map view\r\n menusDispatch({\r\n type: 'SET_VIEWER',\r\n payload: { currentViewer: ViewerNames.map },\r\n })\r\n\r\n if (currentViewer === 'buildings') {\r\n // Filter buildings with valid coordinates\r\n const validBuildings = filteredData.filter(\r\n (item): item is Building => {\r\n const b = item as Building\r\n const lon = b.buildingLongitude\r\n const lat = b.buildingLatitude\r\n if (lon == null || lat == null) return false\r\n\r\n // Rough North America bounding box\r\n const minLat = 5\r\n const maxLat = 85\r\n const minLon = -170\r\n const maxLon = -10\r\n\r\n return Number.isFinite(lat)\r\n && Number.isFinite(lon)\r\n && lat >= minLat\r\n && lat <= maxLat\r\n && lon >= minLon\r\n && lon <= maxLon\r\n }\r\n )\r\n\r\n if (validBuildings.length === 0)\r\n return\r\n\r\n const name = 'Database Buildings'\r\n\r\n const dataset: Dataset = createBuildingsDataset(validBuildings, name)\r\n\r\n // Add buildings as a dataset to the map state\r\n datasetDispatch({\r\n type: 'ADD_DATASET_TO_MAP',\r\n payload: { dataset },\r\n })\r\n\r\n fitBuildingsBounds(validBuildings, map)\r\n }\r\n\r\n else if (currentViewer === 'sites') {\r\n const validSites = (filteredData ?? []).filter((item): item is Site => !!(item as Site)?.id)\r\n\r\n if (validSites.length === 0)\r\n return\r\n\r\n // Render each site's saved GeoJSON boundary (not just a point marker).\r\n // Viewer was already switched to the map above.\r\n await showSitesOnMap(validSites, { switchViewer: false })\r\n }\r\n\r\n else if (currentViewer === 'infrastructure') {\r\n // Filter infrastructure with valid coordinates\r\n }\r\n\r\n\r\n }\r\n\r\n const handleAddBuilding = (building: Building) => {\r\n if (setCompareItems) {\r\n const compareItem: CompareItem = {\r\n ...building,\r\n id: String(building.id),\r\n }\r\n setCompareItems([...compareItems, compareItem])\r\n }\r\n }\r\n\r\n const toggleOpen = () => {\r\n setComparing(false)\r\n // Clear compareItems when exiting compare mode for proper cleanup\r\n if (setCompareItems) {\r\n setCompareItems([])\r\n }\r\n }\r\n\r\n return (\r\n <div className=\"flex flex-row gap-2.5\">\r\n {comparing\r\n ? (\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => {\r\n setComparing(false)\r\n // Clear compareItems for proper cleanup when canceling\r\n if (setCompareItems) {\r\n setCompareItems([])\r\n }\r\n }}\r\n disabled={currentViewer === 'buildings' && !ability.can('read', 'Building') || currentViewer === 'sites' && !ability.can('read', 'Site')}\r\n >\r\n {t('cancelButton')}\r\n </Button>\r\n )\r\n : currentViewer === 'files'\r\n ? (\r\n <DatatableFileAdder />\r\n )\r\n : currentViewer === 'buildings'\r\n ? (\r\n <>\r\n <Button\r\n variant=\"default\"\r\n onClick={() => setAddBuildingOpen(true)}\r\n disabled={!ability.can('create', 'Building')}\r\n >\r\n <LR.CirclePlus />\r\n {t('addBuilding')}\r\n </Button>\r\n <AddBuilding\r\n newBuildingFields={newBuildingFields}\r\n setNewBuildingFields={setNewBuildingFields}\r\n open={addBuildingOpen}\r\n onOpenChange={setAddBuildingOpen}\r\n geocodeEarthApiKey={geocodeEarthApiKey}\r\n geocoderUrl={geocoderUrl}\r\n />\r\n <BuildingMoreOptions buildings={filteredData as Building[]} variant=\"outline\" />\r\n </>\r\n )\r\n : currentViewer === 'sites'\r\n ? (\r\n <AddSite\r\n newItemName={newItemName}\r\n setNewItemName={setNewItemName}\r\n />\r\n )\r\n : currentViewer === 'infrastructure'\r\n ? (\r\n <AddInfrastructure\r\n newInfrastructureFields={newInfrastructureFields}\r\n setNewInfrastructureFields={setNewInfrastructureFields}\r\n open={addInfrastructureOpen}\r\n onOpenChange={setAddInfrastructureOpen}\r\n />\r\n )\r\n : currentViewer === 'users'\r\n ? (\r\n <>\r\n <Button\r\n variant=\"default\"\r\n onClick={() => setAddUserOpen(true)}\r\n disabled={!ability.can('create', 'User')}\r\n >\r\n <LR.CirclePlus />\r\n {t('addUser')}\r\n </Button>\r\n <AddUser open={addUserOpen} onOpenChange={setAddUserOpen} />\r\n <UserMoreOptions users={users} variant=\"outline\" />\r\n </>\r\n )\r\n : null}\r\n\r\n {/* Compare Button/Dialog */}\r\n {comparing\r\n ? (\r\n <CompareDialog\r\n toggleOpen={toggleOpen}\r\n compareItems={compareItems}\r\n setCompareItems={setCompareItems || (() => {})}\r\n handleAddBuilding={handleAddBuilding}\r\n />\r\n )\r\n : (\r\n <Button\r\n variant=\"secondary\"\r\n className={`max-sm:hidden ${(currentViewer === ViewerNames.files || currentViewer === ViewerNames.extensions || currentViewer === ViewerNames.users) ? 'hidden' : ''}`}\r\n onClick={() => setComparing(true)}\r\n >\r\n <LR.GitCompare />\r\n {t('compare')}\r\n {' '}\r\n {headerTitle}\r\n </Button>\r\n )}\r\n {(currentViewer === 'buildings' || currentViewer === 'sites') && filteredData && (\r\n <Button\r\n variant=\"outline\"\r\n onClick={handleViewAllOnMap}\r\n disabled={filteredData.length === 0 || currentViewer === 'buildings' &&!ability.can('read', 'Building') || currentViewer === 'sites' && !ability.can('read', 'Site')}\r\n >\r\n <LR.Map className=\"\" />\r\n {t('viewButton')}\r\n </Button>\r\n )}\r\n </div>\r\n )\r\n}"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MoreOptions.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/Data/MoreOptions.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"MoreOptions.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/Data/MoreOptions.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAA;AAyBlE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAInD,OAAO,EAAE,SAAS,EAAe,MAAM,iBAAiB,CAAA;AAKxD,UAAU,gBAAgB;IACxB,GAAG,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,QAAQ,EAAE,SAAS,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAA;IACzC,OAAO,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAA;IAClE,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;CAC1B;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,aAAqB,EAAE,YAAY,EAAE,EAAE,gBAAgB,qBAiL7H"}
|