@mosierdata/emdash-plugin-analytics 1.0.1 → 1.0.3
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/dist/admin.d.mts +3 -11
- package/dist/admin.d.mts.map +1 -1
- package/dist/admin.mjs +497 -152
- package/dist/admin.mjs.map +1 -1
- package/dist/descriptor.mjs +5 -17
- package/dist/descriptor.mjs.map +1 -1
- package/dist/index.mjs +33 -141
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -6
- package/scripts/postinstall.mjs +0 -43
package/dist/admin.mjs
CHANGED
|
@@ -1,10 +1,36 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
-
import {
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { API_BASE, apiFetch, parseApiResponse } from "@emdash-cms/admin";
|
|
3
3
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
|
|
5
|
+
//#region src/lib/usePluginAPI.ts
|
|
6
|
+
const PLUGIN_ID = "roi-insights";
|
|
7
|
+
/**
|
|
8
|
+
* Shim for usePluginAPI — @emdash-cms/admin 0.1.0 does not export this hook.
|
|
9
|
+
* Builds a stable { get, post } helper that routes through the plugin API
|
|
10
|
+
* at /_emdash/api/plugins/roi-insights/<path> using the admin apiFetch
|
|
11
|
+
* wrapper (adds CSRF header) and parseApiResponse (handles error shapes).
|
|
12
|
+
*
|
|
13
|
+
* Remove this file once @emdash-cms/admin exports usePluginAPI natively.
|
|
14
|
+
*/
|
|
15
|
+
function usePluginAPI() {
|
|
16
|
+
return useMemo(() => ({
|
|
17
|
+
get(path) {
|
|
18
|
+
return apiFetch(`${API_BASE}/plugins/${PLUGIN_ID}/${path}`).then((r) => parseApiResponse(r));
|
|
19
|
+
},
|
|
20
|
+
post(path, body) {
|
|
21
|
+
return apiFetch(`${API_BASE}/plugins/${PLUGIN_ID}/${path}`, {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: { "Content-Type": "application/json" },
|
|
24
|
+
body: JSON.stringify(body)
|
|
25
|
+
}).then((r) => parseApiResponse(r));
|
|
26
|
+
}
|
|
27
|
+
}), []);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
5
31
|
//#region src/admin/Dashboard.tsx
|
|
6
32
|
const DASHBOARD_BASE_URL = "https://my.roiknowledge.com/embed";
|
|
7
|
-
function AdminDashboard() {
|
|
33
|
+
function AdminDashboard({ onNavigateToSettings }) {
|
|
8
34
|
const api = usePluginAPI();
|
|
9
35
|
const [dashboardUrl, setDashboardUrl] = useState(null);
|
|
10
36
|
const [error, setError] = useState(null);
|
|
@@ -41,9 +67,17 @@ function AdminDashboard() {
|
|
|
41
67
|
children: [
|
|
42
68
|
/* @__PURE__ */ jsx("h3", { children: "ROI Insights Dashboard" }),
|
|
43
69
|
/* @__PURE__ */ jsx("p", { children: error }),
|
|
44
|
-
/* @__PURE__ */ jsx("
|
|
45
|
-
|
|
46
|
-
|
|
70
|
+
onNavigateToSettings && /* @__PURE__ */ jsx("button", {
|
|
71
|
+
onClick: onNavigateToSettings,
|
|
72
|
+
style: {
|
|
73
|
+
background: "none",
|
|
74
|
+
border: "none",
|
|
75
|
+
color: "#2563eb",
|
|
76
|
+
cursor: "pointer",
|
|
77
|
+
padding: 0,
|
|
78
|
+
fontSize: "inherit"
|
|
79
|
+
},
|
|
80
|
+
children: "Go to License & Google →"
|
|
47
81
|
})
|
|
48
82
|
]
|
|
49
83
|
});
|
|
@@ -74,146 +108,6 @@ function AdminDashboard() {
|
|
|
74
108
|
});
|
|
75
109
|
}
|
|
76
110
|
|
|
77
|
-
//#endregion
|
|
78
|
-
//#region src/admin/Settings.tsx
|
|
79
|
-
function SettingsPage() {
|
|
80
|
-
const api = usePluginAPI();
|
|
81
|
-
const [license, setLicense] = useState(null);
|
|
82
|
-
const [googleConnected, setGoogleConnected] = useState(false);
|
|
83
|
-
const [activating, setActivating] = useState(false);
|
|
84
|
-
const [message, setMessage] = useState("");
|
|
85
|
-
useEffect(() => {
|
|
86
|
-
Promise.all([api.get("license/status").then(setLicense), api.get("google-oauth/status").then((r) => setGoogleConnected(r.connected))]);
|
|
87
|
-
}, [api]);
|
|
88
|
-
useEffect(() => {
|
|
89
|
-
const params = new URLSearchParams(window.location.search);
|
|
90
|
-
if (params.get("oauth_callback") !== "1" || params.get("google_connected") !== "true") return;
|
|
91
|
-
api.post("google-oauth/connected", {}).then(() => {
|
|
92
|
-
setGoogleConnected(true);
|
|
93
|
-
setMessage("Google Services connected successfully.");
|
|
94
|
-
});
|
|
95
|
-
}, [api]);
|
|
96
|
-
const handleActivateLicense = useCallback(async () => {
|
|
97
|
-
setActivating(true);
|
|
98
|
-
setMessage("");
|
|
99
|
-
try {
|
|
100
|
-
const fresh = await api.get("license/validate");
|
|
101
|
-
setLicense(fresh);
|
|
102
|
-
setMessage(fresh.isValid ? "License activated." : `License invalid: ${fresh.reason ?? "unknown"}`);
|
|
103
|
-
} catch {
|
|
104
|
-
setMessage("Error validating license.");
|
|
105
|
-
} finally {
|
|
106
|
-
setActivating(false);
|
|
107
|
-
}
|
|
108
|
-
}, [api]);
|
|
109
|
-
const handleGoogleOAuth = useCallback(async () => {
|
|
110
|
-
try {
|
|
111
|
-
const result = await api.post("google-oauth/initiate", {});
|
|
112
|
-
if (result.error) {
|
|
113
|
-
setMessage(result.error);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
if (result.authUrl) window.location.href = result.authUrl;
|
|
117
|
-
} catch {
|
|
118
|
-
setMessage("Error initiating Google connection.");
|
|
119
|
-
}
|
|
120
|
-
}, [api]);
|
|
121
|
-
const licenseStatusLabel = () => {
|
|
122
|
-
if (!license) return "Not checked";
|
|
123
|
-
if (license.isFallback) return "Active (offline)";
|
|
124
|
-
if (!license.isValid) return `Invalid — ${license.reason ?? "unknown"}`;
|
|
125
|
-
return `Active — ${license.tier ?? "free"} tier`;
|
|
126
|
-
};
|
|
127
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
128
|
-
style: {
|
|
129
|
-
maxWidth: 640,
|
|
130
|
-
padding: "1.5rem"
|
|
131
|
-
},
|
|
132
|
-
children: [
|
|
133
|
-
/* @__PURE__ */ jsx("h2", { children: "License & Google" }),
|
|
134
|
-
/* @__PURE__ */ jsxs("p", {
|
|
135
|
-
style: {
|
|
136
|
-
fontSize: "0.9rem",
|
|
137
|
-
color: "#555",
|
|
138
|
-
marginBottom: "1.5rem"
|
|
139
|
-
},
|
|
140
|
-
children: [
|
|
141
|
-
"Enter your license key in the ",
|
|
142
|
-
/* @__PURE__ */ jsx("strong", { children: "Settings" }),
|
|
143
|
-
" tab above, then click Activate below."
|
|
144
|
-
]
|
|
145
|
-
}),
|
|
146
|
-
/* @__PURE__ */ jsxs("section", {
|
|
147
|
-
style: { marginBottom: "1.5rem" },
|
|
148
|
-
children: [
|
|
149
|
-
/* @__PURE__ */ jsx("h3", { children: "License" }),
|
|
150
|
-
license && /* @__PURE__ */ jsxs("p", {
|
|
151
|
-
style: {
|
|
152
|
-
fontSize: "0.9rem",
|
|
153
|
-
marginBottom: "0.75rem"
|
|
154
|
-
},
|
|
155
|
-
children: ["Status: ", /* @__PURE__ */ jsx("strong", { children: licenseStatusLabel() })]
|
|
156
|
-
}),
|
|
157
|
-
/* @__PURE__ */ jsx("button", {
|
|
158
|
-
onClick: () => void handleActivateLicense(),
|
|
159
|
-
disabled: activating,
|
|
160
|
-
children: activating ? "Activating…" : "Activate License"
|
|
161
|
-
})
|
|
162
|
-
]
|
|
163
|
-
}),
|
|
164
|
-
/* @__PURE__ */ jsxs("section", {
|
|
165
|
-
style: { marginBottom: "1.5rem" },
|
|
166
|
-
children: [/* @__PURE__ */ jsx("h3", { children: "Google Services (Free Tier)" }), googleConnected ? /* @__PURE__ */ jsx("p", { children: "Connected to Google Analytics & Search Console ✅" }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
|
|
167
|
-
style: {
|
|
168
|
-
fontSize: "0.9rem",
|
|
169
|
-
color: "#555"
|
|
170
|
-
},
|
|
171
|
-
children: "Grant read access to GA4 and Search Console. Tokens are stored securely on the MosierData backend."
|
|
172
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
173
|
-
onClick: () => void handleGoogleOAuth(),
|
|
174
|
-
children: "Connect Google Services"
|
|
175
|
-
})] })]
|
|
176
|
-
}),
|
|
177
|
-
message && /* @__PURE__ */ jsx("p", {
|
|
178
|
-
style: {
|
|
179
|
-
fontSize: "0.9rem",
|
|
180
|
-
color: "#444",
|
|
181
|
-
marginTop: "1rem"
|
|
182
|
-
},
|
|
183
|
-
children: message
|
|
184
|
-
}),
|
|
185
|
-
license?.isValid && license.tier === "free" && /* @__PURE__ */ jsxs("div", {
|
|
186
|
-
style: {
|
|
187
|
-
marginTop: "2rem",
|
|
188
|
-
padding: "1rem",
|
|
189
|
-
background: "#f0f7ff",
|
|
190
|
-
border: "1px solid #c0d8f5",
|
|
191
|
-
borderRadius: 6
|
|
192
|
-
},
|
|
193
|
-
children: [
|
|
194
|
-
/* @__PURE__ */ jsx("h4", {
|
|
195
|
-
style: { margin: "0 0 0.5rem" },
|
|
196
|
-
children: "Upgrade to Professional"
|
|
197
|
-
}),
|
|
198
|
-
/* @__PURE__ */ jsx("p", {
|
|
199
|
-
style: {
|
|
200
|
-
margin: "0 0 0.75rem",
|
|
201
|
-
fontSize: "0.9rem"
|
|
202
|
-
},
|
|
203
|
-
children: "Unlock AI Call Transcription, Lead Scoring, and Call Recording."
|
|
204
|
-
}),
|
|
205
|
-
/* @__PURE__ */ jsx("a", {
|
|
206
|
-
href: "https://quotedash.io/upgrade",
|
|
207
|
-
target: "_blank",
|
|
208
|
-
rel: "noreferrer",
|
|
209
|
-
children: "Upgrade Now →"
|
|
210
|
-
})
|
|
211
|
-
]
|
|
212
|
-
})
|
|
213
|
-
]
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
|
|
217
111
|
//#endregion
|
|
218
112
|
//#region src/admin/TrackingSettings.tsx
|
|
219
113
|
const HELP_CONTENT = {
|
|
@@ -1526,18 +1420,469 @@ function TrackingSettingsAdmin() {
|
|
|
1526
1420
|
})] });
|
|
1527
1421
|
}
|
|
1528
1422
|
|
|
1423
|
+
//#endregion
|
|
1424
|
+
//#region src/admin/Settings.tsx
|
|
1425
|
+
function SettingsPage() {
|
|
1426
|
+
const api = usePluginAPI();
|
|
1427
|
+
const [license, setLicense] = useState(null);
|
|
1428
|
+
const [googleConnected, setGoogleConnected] = useState(false);
|
|
1429
|
+
const [activating, setActivating] = useState(false);
|
|
1430
|
+
const [message, setMessage] = useState("");
|
|
1431
|
+
const [licenseKeyInput, setLicenseKeyInput] = useState("");
|
|
1432
|
+
const [savingKey, setSavingKey] = useState(false);
|
|
1433
|
+
const [advanced, setAdvanced] = useState({
|
|
1434
|
+
dniSwapNumber: "",
|
|
1435
|
+
dniScriptUrl: "",
|
|
1436
|
+
customHeadCode: "",
|
|
1437
|
+
customFooterCode: "",
|
|
1438
|
+
debug: false
|
|
1439
|
+
});
|
|
1440
|
+
const [savingAdvanced, setSavingAdvanced] = useState(false);
|
|
1441
|
+
useEffect(() => {
|
|
1442
|
+
Promise.all([
|
|
1443
|
+
api.get("license/status").then(setLicense),
|
|
1444
|
+
api.get("google-oauth/status").then((r) => setGoogleConnected(r.connected)),
|
|
1445
|
+
api.get("settings/load").then(setAdvanced)
|
|
1446
|
+
]);
|
|
1447
|
+
}, [api]);
|
|
1448
|
+
useEffect(() => {
|
|
1449
|
+
const params = new URLSearchParams(window.location.search);
|
|
1450
|
+
if (params.get("oauth_callback") !== "1" || params.get("google_connected") !== "true") return;
|
|
1451
|
+
api.post("google-oauth/connected", {}).then(() => {
|
|
1452
|
+
setGoogleConnected(true);
|
|
1453
|
+
setMessage("Google Services connected successfully.");
|
|
1454
|
+
});
|
|
1455
|
+
}, [api]);
|
|
1456
|
+
const handleActivateLicense = useCallback(async () => {
|
|
1457
|
+
setActivating(true);
|
|
1458
|
+
setMessage("");
|
|
1459
|
+
try {
|
|
1460
|
+
const fresh = await api.get("license/validate");
|
|
1461
|
+
setLicense(fresh);
|
|
1462
|
+
setMessage(fresh.isValid ? "License activated." : `License invalid: ${fresh.reason ?? "unknown"}`);
|
|
1463
|
+
} catch {
|
|
1464
|
+
setMessage("Error validating license.");
|
|
1465
|
+
} finally {
|
|
1466
|
+
setActivating(false);
|
|
1467
|
+
}
|
|
1468
|
+
}, [api]);
|
|
1469
|
+
const handleSaveLicenseKey = useCallback(async () => {
|
|
1470
|
+
if (!licenseKeyInput.trim()) return;
|
|
1471
|
+
setSavingKey(true);
|
|
1472
|
+
setMessage("");
|
|
1473
|
+
try {
|
|
1474
|
+
await api.post("settings/save", { licenseKey: licenseKeyInput.trim() });
|
|
1475
|
+
setMessage("License key saved. Click Activate to validate.");
|
|
1476
|
+
setLicenseKeyInput("");
|
|
1477
|
+
} catch {
|
|
1478
|
+
setMessage("Error saving license key.");
|
|
1479
|
+
} finally {
|
|
1480
|
+
setSavingKey(false);
|
|
1481
|
+
}
|
|
1482
|
+
}, [api, licenseKeyInput]);
|
|
1483
|
+
const handleSaveAdvanced = useCallback(async () => {
|
|
1484
|
+
setSavingAdvanced(true);
|
|
1485
|
+
setMessage("");
|
|
1486
|
+
try {
|
|
1487
|
+
await api.post("settings/save", advanced);
|
|
1488
|
+
setMessage("Settings saved.");
|
|
1489
|
+
} catch {
|
|
1490
|
+
setMessage("Error saving settings.");
|
|
1491
|
+
} finally {
|
|
1492
|
+
setSavingAdvanced(false);
|
|
1493
|
+
}
|
|
1494
|
+
}, [api, advanced]);
|
|
1495
|
+
const handleGoogleOAuth = useCallback(async () => {
|
|
1496
|
+
try {
|
|
1497
|
+
const result = await api.post("google-oauth/initiate", {});
|
|
1498
|
+
if (result.error) {
|
|
1499
|
+
setMessage(result.error);
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
if (result.authUrl) window.location.href = result.authUrl;
|
|
1503
|
+
} catch {
|
|
1504
|
+
setMessage("Error initiating Google connection.");
|
|
1505
|
+
}
|
|
1506
|
+
}, [api]);
|
|
1507
|
+
const licenseStatusLabel = () => {
|
|
1508
|
+
if (!license) return "Not checked";
|
|
1509
|
+
if (license.isFallback) return "Active (offline)";
|
|
1510
|
+
if (!license.isValid) return `Invalid — ${license.reason ?? "unknown"}`;
|
|
1511
|
+
return `Active — ${license.tier ?? "free"} tier`;
|
|
1512
|
+
};
|
|
1513
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1514
|
+
style: {
|
|
1515
|
+
maxWidth: 640,
|
|
1516
|
+
padding: "1.5rem"
|
|
1517
|
+
},
|
|
1518
|
+
children: [
|
|
1519
|
+
/* @__PURE__ */ jsx("h2", { children: "License & Google" }),
|
|
1520
|
+
/* @__PURE__ */ jsxs("section", {
|
|
1521
|
+
style: { marginBottom: "1.5rem" },
|
|
1522
|
+
children: [
|
|
1523
|
+
/* @__PURE__ */ jsx("h3", { children: "License Key" }),
|
|
1524
|
+
/* @__PURE__ */ jsxs("p", {
|
|
1525
|
+
style: {
|
|
1526
|
+
fontSize: "0.9rem",
|
|
1527
|
+
color: "#555",
|
|
1528
|
+
marginBottom: "0.75rem"
|
|
1529
|
+
},
|
|
1530
|
+
children: ["Paste your license key from the MosierData portal. Prefix: ", /* @__PURE__ */ jsx("code", { children: "qdsh_" })]
|
|
1531
|
+
}),
|
|
1532
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1533
|
+
style: {
|
|
1534
|
+
display: "flex",
|
|
1535
|
+
gap: "0.5rem",
|
|
1536
|
+
alignItems: "center"
|
|
1537
|
+
},
|
|
1538
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
1539
|
+
type: "password",
|
|
1540
|
+
value: licenseKeyInput,
|
|
1541
|
+
onChange: (e) => setLicenseKeyInput(e.target.value),
|
|
1542
|
+
placeholder: "qdsh_…",
|
|
1543
|
+
style: {
|
|
1544
|
+
flex: 1,
|
|
1545
|
+
padding: "0.5rem 0.75rem",
|
|
1546
|
+
border: "1px solid #d1d5db",
|
|
1547
|
+
borderRadius: 4,
|
|
1548
|
+
fontSize: "0.9rem"
|
|
1549
|
+
}
|
|
1550
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
1551
|
+
onClick: () => void handleSaveLicenseKey(),
|
|
1552
|
+
disabled: savingKey || !licenseKeyInput.trim(),
|
|
1553
|
+
children: savingKey ? "Saving…" : "Save Key"
|
|
1554
|
+
})]
|
|
1555
|
+
})
|
|
1556
|
+
]
|
|
1557
|
+
}),
|
|
1558
|
+
/* @__PURE__ */ jsxs("section", {
|
|
1559
|
+
style: { marginBottom: "1.5rem" },
|
|
1560
|
+
children: [
|
|
1561
|
+
/* @__PURE__ */ jsx("h3", { children: "License" }),
|
|
1562
|
+
license && /* @__PURE__ */ jsxs("p", {
|
|
1563
|
+
style: {
|
|
1564
|
+
fontSize: "0.9rem",
|
|
1565
|
+
marginBottom: "0.75rem"
|
|
1566
|
+
},
|
|
1567
|
+
children: ["Status: ", /* @__PURE__ */ jsx("strong", { children: licenseStatusLabel() })]
|
|
1568
|
+
}),
|
|
1569
|
+
/* @__PURE__ */ jsx("button", {
|
|
1570
|
+
onClick: () => void handleActivateLicense(),
|
|
1571
|
+
disabled: activating,
|
|
1572
|
+
children: activating ? "Activating…" : "Activate License"
|
|
1573
|
+
})
|
|
1574
|
+
]
|
|
1575
|
+
}),
|
|
1576
|
+
/* @__PURE__ */ jsxs("section", {
|
|
1577
|
+
style: { marginBottom: "1.5rem" },
|
|
1578
|
+
children: [/* @__PURE__ */ jsx("h3", { children: "Google Services (Free Tier)" }), googleConnected ? /* @__PURE__ */ jsx("p", { children: "Connected to Google Analytics & Search Console ✅" }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
|
|
1579
|
+
style: {
|
|
1580
|
+
fontSize: "0.9rem",
|
|
1581
|
+
color: "#555"
|
|
1582
|
+
},
|
|
1583
|
+
children: "Grant read access to GA4 and Search Console. Tokens are stored securely on the MosierData backend."
|
|
1584
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
1585
|
+
onClick: () => void handleGoogleOAuth(),
|
|
1586
|
+
children: "Connect Google Services"
|
|
1587
|
+
})] })]
|
|
1588
|
+
}),
|
|
1589
|
+
/* @__PURE__ */ jsxs("section", {
|
|
1590
|
+
style: { marginBottom: "1.5rem" },
|
|
1591
|
+
children: [
|
|
1592
|
+
/* @__PURE__ */ jsx("h3", { children: "Call Tracking (AvidTrak DNI)" }),
|
|
1593
|
+
/* @__PURE__ */ jsx("p", {
|
|
1594
|
+
style: {
|
|
1595
|
+
fontSize: "0.9rem",
|
|
1596
|
+
color: "#555",
|
|
1597
|
+
marginBottom: "0.75rem"
|
|
1598
|
+
},
|
|
1599
|
+
children: "Dynamic Number Insertion replaces a phone number on your site with a tracked number."
|
|
1600
|
+
}),
|
|
1601
|
+
/* @__PURE__ */ jsx("label", {
|
|
1602
|
+
style: {
|
|
1603
|
+
display: "block",
|
|
1604
|
+
fontSize: "0.875rem",
|
|
1605
|
+
marginBottom: "0.25rem"
|
|
1606
|
+
},
|
|
1607
|
+
children: "Phone Number to Swap"
|
|
1608
|
+
}),
|
|
1609
|
+
/* @__PURE__ */ jsx("input", {
|
|
1610
|
+
type: "text",
|
|
1611
|
+
value: advanced.dniSwapNumber,
|
|
1612
|
+
onChange: (e) => setAdvanced((a) => ({
|
|
1613
|
+
...a,
|
|
1614
|
+
dniSwapNumber: e.target.value
|
|
1615
|
+
})),
|
|
1616
|
+
placeholder: "e.g. (555) 867-5309",
|
|
1617
|
+
style: {
|
|
1618
|
+
width: "100%",
|
|
1619
|
+
padding: "0.5rem 0.75rem",
|
|
1620
|
+
border: "1px solid #d1d5db",
|
|
1621
|
+
borderRadius: 4,
|
|
1622
|
+
fontSize: "0.9rem",
|
|
1623
|
+
marginBottom: "0.75rem",
|
|
1624
|
+
boxSizing: "border-box"
|
|
1625
|
+
}
|
|
1626
|
+
}),
|
|
1627
|
+
/* @__PURE__ */ jsx("label", {
|
|
1628
|
+
style: {
|
|
1629
|
+
display: "block",
|
|
1630
|
+
fontSize: "0.875rem",
|
|
1631
|
+
marginBottom: "0.25rem"
|
|
1632
|
+
},
|
|
1633
|
+
children: "AvidTrak Script URL"
|
|
1634
|
+
}),
|
|
1635
|
+
/* @__PURE__ */ jsx("input", {
|
|
1636
|
+
type: "text",
|
|
1637
|
+
value: advanced.dniScriptUrl,
|
|
1638
|
+
onChange: (e) => setAdvanced((a) => ({
|
|
1639
|
+
...a,
|
|
1640
|
+
dniScriptUrl: e.target.value
|
|
1641
|
+
})),
|
|
1642
|
+
placeholder: "https://…",
|
|
1643
|
+
style: {
|
|
1644
|
+
width: "100%",
|
|
1645
|
+
padding: "0.5rem 0.75rem",
|
|
1646
|
+
border: "1px solid #d1d5db",
|
|
1647
|
+
borderRadius: 4,
|
|
1648
|
+
fontSize: "0.9rem",
|
|
1649
|
+
boxSizing: "border-box"
|
|
1650
|
+
}
|
|
1651
|
+
})
|
|
1652
|
+
]
|
|
1653
|
+
}),
|
|
1654
|
+
/* @__PURE__ */ jsxs("section", {
|
|
1655
|
+
style: { marginBottom: "1.5rem" },
|
|
1656
|
+
children: [
|
|
1657
|
+
/* @__PURE__ */ jsx("h3", { children: "Custom Code" }),
|
|
1658
|
+
/* @__PURE__ */ jsx("label", {
|
|
1659
|
+
style: {
|
|
1660
|
+
display: "block",
|
|
1661
|
+
fontSize: "0.875rem",
|
|
1662
|
+
marginBottom: "0.25rem"
|
|
1663
|
+
},
|
|
1664
|
+
children: "Custom <head> Code"
|
|
1665
|
+
}),
|
|
1666
|
+
/* @__PURE__ */ jsx("textarea", {
|
|
1667
|
+
value: advanced.customHeadCode,
|
|
1668
|
+
onChange: (e) => setAdvanced((a) => ({
|
|
1669
|
+
...a,
|
|
1670
|
+
customHeadCode: e.target.value
|
|
1671
|
+
})),
|
|
1672
|
+
rows: 4,
|
|
1673
|
+
style: {
|
|
1674
|
+
width: "100%",
|
|
1675
|
+
padding: "0.5rem 0.75rem",
|
|
1676
|
+
border: "1px solid #d1d5db",
|
|
1677
|
+
borderRadius: 4,
|
|
1678
|
+
fontSize: "0.85rem",
|
|
1679
|
+
fontFamily: "monospace",
|
|
1680
|
+
marginBottom: "0.75rem",
|
|
1681
|
+
boxSizing: "border-box"
|
|
1682
|
+
}
|
|
1683
|
+
}),
|
|
1684
|
+
/* @__PURE__ */ jsx("label", {
|
|
1685
|
+
style: {
|
|
1686
|
+
display: "block",
|
|
1687
|
+
fontSize: "0.875rem",
|
|
1688
|
+
marginBottom: "0.25rem"
|
|
1689
|
+
},
|
|
1690
|
+
children: "Custom Footer Code"
|
|
1691
|
+
}),
|
|
1692
|
+
/* @__PURE__ */ jsx("textarea", {
|
|
1693
|
+
value: advanced.customFooterCode,
|
|
1694
|
+
onChange: (e) => setAdvanced((a) => ({
|
|
1695
|
+
...a,
|
|
1696
|
+
customFooterCode: e.target.value
|
|
1697
|
+
})),
|
|
1698
|
+
rows: 4,
|
|
1699
|
+
style: {
|
|
1700
|
+
width: "100%",
|
|
1701
|
+
padding: "0.5rem 0.75rem",
|
|
1702
|
+
border: "1px solid #d1d5db",
|
|
1703
|
+
borderRadius: 4,
|
|
1704
|
+
fontSize: "0.85rem",
|
|
1705
|
+
fontFamily: "monospace",
|
|
1706
|
+
boxSizing: "border-box"
|
|
1707
|
+
}
|
|
1708
|
+
})
|
|
1709
|
+
]
|
|
1710
|
+
}),
|
|
1711
|
+
/* @__PURE__ */ jsxs("section", {
|
|
1712
|
+
style: { marginBottom: "1.5rem" },
|
|
1713
|
+
children: [
|
|
1714
|
+
/* @__PURE__ */ jsx("h3", { children: "Developer" }),
|
|
1715
|
+
/* @__PURE__ */ jsxs("label", {
|
|
1716
|
+
style: {
|
|
1717
|
+
display: "flex",
|
|
1718
|
+
alignItems: "center",
|
|
1719
|
+
gap: "0.5rem",
|
|
1720
|
+
fontSize: "0.9rem",
|
|
1721
|
+
cursor: "pointer"
|
|
1722
|
+
},
|
|
1723
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
1724
|
+
type: "checkbox",
|
|
1725
|
+
checked: advanced.debug,
|
|
1726
|
+
onChange: (e) => setAdvanced((a) => ({
|
|
1727
|
+
...a,
|
|
1728
|
+
debug: e.target.checked
|
|
1729
|
+
}))
|
|
1730
|
+
}), "Debug Mode"]
|
|
1731
|
+
}),
|
|
1732
|
+
/* @__PURE__ */ jsx("p", {
|
|
1733
|
+
style: {
|
|
1734
|
+
fontSize: "0.8rem",
|
|
1735
|
+
color: "#888",
|
|
1736
|
+
marginTop: "0.25rem"
|
|
1737
|
+
},
|
|
1738
|
+
children: "Logs injected script activity to the browser console on every page load."
|
|
1739
|
+
})
|
|
1740
|
+
]
|
|
1741
|
+
}),
|
|
1742
|
+
/* @__PURE__ */ jsx("button", {
|
|
1743
|
+
onClick: () => void handleSaveAdvanced(),
|
|
1744
|
+
disabled: savingAdvanced,
|
|
1745
|
+
children: savingAdvanced ? "Saving…" : "Save Settings"
|
|
1746
|
+
}),
|
|
1747
|
+
message && /* @__PURE__ */ jsx("p", {
|
|
1748
|
+
style: {
|
|
1749
|
+
fontSize: "0.9rem",
|
|
1750
|
+
color: "#444",
|
|
1751
|
+
marginTop: "1rem"
|
|
1752
|
+
},
|
|
1753
|
+
children: message
|
|
1754
|
+
}),
|
|
1755
|
+
license?.isValid && license.tier === "free" && /* @__PURE__ */ jsxs("div", {
|
|
1756
|
+
style: {
|
|
1757
|
+
marginTop: "2rem",
|
|
1758
|
+
padding: "1rem",
|
|
1759
|
+
background: "#f0f7ff",
|
|
1760
|
+
border: "1px solid #c0d8f5",
|
|
1761
|
+
borderRadius: 6
|
|
1762
|
+
},
|
|
1763
|
+
children: [
|
|
1764
|
+
/* @__PURE__ */ jsx("h4", {
|
|
1765
|
+
style: { margin: "0 0 0.5rem" },
|
|
1766
|
+
children: "Upgrade to Professional"
|
|
1767
|
+
}),
|
|
1768
|
+
/* @__PURE__ */ jsx("p", {
|
|
1769
|
+
style: {
|
|
1770
|
+
margin: "0 0 0.75rem",
|
|
1771
|
+
fontSize: "0.9rem"
|
|
1772
|
+
},
|
|
1773
|
+
children: "Unlock AI Call Transcription, Lead Scoring, and Call Recording."
|
|
1774
|
+
}),
|
|
1775
|
+
/* @__PURE__ */ jsx("a", {
|
|
1776
|
+
href: "https://quotedash.io/upgrade",
|
|
1777
|
+
target: "_blank",
|
|
1778
|
+
rel: "noreferrer",
|
|
1779
|
+
children: "Upgrade Now →"
|
|
1780
|
+
})
|
|
1781
|
+
]
|
|
1782
|
+
})
|
|
1783
|
+
]
|
|
1784
|
+
});
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
//#endregion
|
|
1788
|
+
//#region src/admin/PluginLayout.tsx
|
|
1789
|
+
const TABS = [
|
|
1790
|
+
{
|
|
1791
|
+
id: "dashboard",
|
|
1792
|
+
label: "Marketing ROI"
|
|
1793
|
+
},
|
|
1794
|
+
{
|
|
1795
|
+
id: "tracking",
|
|
1796
|
+
label: "Tracking Pixels"
|
|
1797
|
+
},
|
|
1798
|
+
{
|
|
1799
|
+
id: "settings",
|
|
1800
|
+
label: "License & Google"
|
|
1801
|
+
}
|
|
1802
|
+
];
|
|
1803
|
+
function getTabFromHash() {
|
|
1804
|
+
const hash = window.location.hash.slice(1);
|
|
1805
|
+
return hash === "tracking" || hash === "settings" ? hash : "dashboard";
|
|
1806
|
+
}
|
|
1807
|
+
function PluginLayout() {
|
|
1808
|
+
const [activeTab, setActiveTab] = useState(getTabFromHash);
|
|
1809
|
+
const handleTabChange = (tab) => {
|
|
1810
|
+
setActiveTab(tab);
|
|
1811
|
+
window.location.hash = tab === "dashboard" ? "" : tab;
|
|
1812
|
+
};
|
|
1813
|
+
useEffect(() => {
|
|
1814
|
+
const onHashChange = () => setActiveTab(getTabFromHash());
|
|
1815
|
+
window.addEventListener("hashchange", onHashChange);
|
|
1816
|
+
return () => window.removeEventListener("hashchange", onHashChange);
|
|
1817
|
+
}, []);
|
|
1818
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1819
|
+
style: {
|
|
1820
|
+
display: "flex",
|
|
1821
|
+
flexDirection: "column",
|
|
1822
|
+
height: "100%"
|
|
1823
|
+
},
|
|
1824
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1825
|
+
role: "tablist",
|
|
1826
|
+
style: {
|
|
1827
|
+
display: "flex",
|
|
1828
|
+
borderBottom: "1px solid #e2e8f0",
|
|
1829
|
+
background: "#fff",
|
|
1830
|
+
padding: "0 1.25rem",
|
|
1831
|
+
gap: "0.25rem",
|
|
1832
|
+
flexShrink: 0
|
|
1833
|
+
},
|
|
1834
|
+
children: TABS.map((tab) => /* @__PURE__ */ jsx("button", {
|
|
1835
|
+
role: "tab",
|
|
1836
|
+
"aria-selected": activeTab === tab.id,
|
|
1837
|
+
onClick: () => handleTabChange(tab.id),
|
|
1838
|
+
style: {
|
|
1839
|
+
padding: "0.75rem 1rem",
|
|
1840
|
+
border: "none",
|
|
1841
|
+
borderBottom: activeTab === tab.id ? "2px solid #2563eb" : "2px solid transparent",
|
|
1842
|
+
background: "none",
|
|
1843
|
+
cursor: "pointer",
|
|
1844
|
+
fontSize: "0.875rem",
|
|
1845
|
+
fontWeight: activeTab === tab.id ? 600 : 400,
|
|
1846
|
+
color: activeTab === tab.id ? "#2563eb" : "#64748b",
|
|
1847
|
+
marginBottom: "-1px"
|
|
1848
|
+
},
|
|
1849
|
+
children: tab.label
|
|
1850
|
+
}, tab.id))
|
|
1851
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1852
|
+
style: {
|
|
1853
|
+
flex: 1,
|
|
1854
|
+
overflow: "auto"
|
|
1855
|
+
},
|
|
1856
|
+
children: [
|
|
1857
|
+
/* @__PURE__ */ jsx("div", {
|
|
1858
|
+
style: {
|
|
1859
|
+
display: activeTab === "dashboard" ? "block" : "none",
|
|
1860
|
+
height: "100%"
|
|
1861
|
+
},
|
|
1862
|
+
children: /* @__PURE__ */ jsx(AdminDashboard, { onNavigateToSettings: () => handleTabChange("settings") })
|
|
1863
|
+
}),
|
|
1864
|
+
/* @__PURE__ */ jsx("div", {
|
|
1865
|
+
style: { display: activeTab === "tracking" ? "block" : "none" },
|
|
1866
|
+
children: /* @__PURE__ */ jsx(TrackingSettingsAdmin, {})
|
|
1867
|
+
}),
|
|
1868
|
+
/* @__PURE__ */ jsx("div", {
|
|
1869
|
+
style: { display: activeTab === "settings" ? "block" : "none" },
|
|
1870
|
+
children: /* @__PURE__ */ jsx(SettingsPage, {})
|
|
1871
|
+
})
|
|
1872
|
+
]
|
|
1873
|
+
})]
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1529
1877
|
//#endregion
|
|
1530
1878
|
//#region src/admin.tsx
|
|
1531
1879
|
/**
|
|
1532
1880
|
* Admin UI entry point — loaded in the browser by EmDash's admin panel.
|
|
1533
1881
|
* Exports `pages` (keyed by path) and `widgets` (keyed by ID).
|
|
1534
|
-
*
|
|
1882
|
+
* All plugin tabs (Dashboard, Tracking Pixels, License & Google) are rendered
|
|
1883
|
+
* inside PluginLayout so only one sidebar entry appears.
|
|
1535
1884
|
*/
|
|
1536
|
-
const pages = {
|
|
1537
|
-
"/dashboard": AdminDashboard,
|
|
1538
|
-
"/settings": SettingsPage,
|
|
1539
|
-
"/tracking": TrackingSettingsAdmin
|
|
1540
|
-
};
|
|
1885
|
+
const pages = { "/dashboard": PluginLayout };
|
|
1541
1886
|
const widgets = {};
|
|
1542
1887
|
|
|
1543
1888
|
//#endregion
|