1import { a as __toESM } from "./rolldown-runtime-Cql5ZV07.js"; 2import { p as require_react } from "./vendor-charts-D81iZKCV.js"; 3import { g as require_compiler_runtime, t as require_jsx_runtime } from "./vendor-react-HZz3WA9p.js"; 4import "./vendor-dnd-D_JGdZnv.js"; 5import "./vendor-mixpanel-Dh8wsiZW.js"; 6import "./device-CBwMusKw.js"; 7import "./vendor-redux-CLEI5hTp.js"; 8import "./vendor-utils-DiM3BD4o.js"; 9import "./vendor-ui-G6aSO5L-.js"; 10import { $t as Download, G as Plus, Ot as Info, Xt as EyeOff, Yt as Eye, in as Copy, l as UserRound, v as TriangleAlert, y as Trash } from "./vendor-lucide-EY3Z5fcy.js"; 11import { t as Button } from "./button-BWyXpawe.js"; 12import "./vendor-twilio-BWAG7uEQ.js"; 13import "./app-storage-slice-mFVFfzPf.js"; 14import { E as addDays, S as startOfDay, b as addYears, p as format } from "./vendor-date-d6_4rWHy.js"; 15import "./dates-B2P7D4-n.js"; 16import { t as Label } from "./label-BU8XDazs.js"; 17import { a as AlertDialogDescription, c as AlertDialogTitle, i as AlertDialogContent, n as AlertDialogAction, o as AlertDialogFooter, r as AlertDialogCancel, s as AlertDialogHeader, t as AlertDialog } from "./alert-dialog-DqgZ-9QP.js"; 18import { B as TableCell, Fn as baseApi, H as TableHead, In as overrideExisting, R as Table, U as TableHeader, W as TableRow, Yn as trackMethodCall, cn as DialogFooter, dn as DialogTitle, hn as Badge, in as Dialog, ln as DialogHeader, mr as Input, on as DialogContent, sn as DialogDescription, yt as DatePicker, z as TableBody } from "./main-DDHJZG-i.js"; 19var import_compiler_runtime$2 = /* @__PURE__ */ __toESM(require_compiler_runtime()); 20var import_react = /* @__PURE__ */ __toESM(require_react()); 21const { useGetTokenListQuery, useGenerateTokenMutation, useDeleteTokenMutation } = baseApi.injectEndpoints({ 22 overrideExisting: true, 23 endpoints: (builder) => ({ 24 getTokenList: builder.query({ 25 query: (params) => ({ 26 url: "/fleet/jwt/token/list", 27 method: "GET", 28 params 29 }), 30 providesTags: ["apiTokens"] 31 }), 32 generateToken: builder.mutation({ 33 query: (body) => ({ 34 url: "/fleet/jwt/token/generate", 35 method: "POST", 36 body 37 }), 38 invalidatesTags: ["apiTokens"] 39 }), 40 deleteToken: builder.mutation({ 41 query: (issuerId) => ({ 42 url: `/fleet/jwt/token/${issuerId}`, 43 method: "DELETE" 44 }), 45 invalidatesTags: ["apiTokens"] 46 }) 47 }) 48}); 49var import_jsx_runtime = /* @__PURE__ */ __toESM(require_jsx_runtime()); 50var generateRsaKeys = async () => { 51 const keyPair = await window.crypto.subtle.generateKey({ 52 name: "RSASSA-PKCS1-v1_5", 53 modulusLength: 2048, 54 publicExponent: new Uint8Array([ 55 1, 56 0, 57 1 58 ]), 59 hash: "SHA-256" 60 }, true, ["sign", "verify"]); 61 const [publicKeyBuffer, privateKeyBuffer] = await Promise.all([window.crypto.subtle.exportKey("spki", keyPair.publicKey), window.crypto.subtle.exportKey("pkcs8", keyPair.privateKey)]); 62 const toBase64 = (buffer) => { 63 return btoa(String.fromCharCode(...new Uint8Array(buffer))); 64 }; 65 return { 66 publicKey: toBase64(publicKeyBuffer), 67 privateKey: toBase64(privateKeyBuffer) 68 }; 69}; 70var GenerateTokenDialog = (t0) => { 71 const $ = (0, import_compiler_runtime$2.c)(54); 72 const { open, onOpenChange, onSuccess } = t0; 73 const [tokenName, setTokenName] = (0, import_react.useState)(""); 74 const [expiryDate, setExpiryDate] = (0, import_react.useState)(void 0); 75 const [generateToken, t1] = useGenerateTokenMutation(); 76 const { isLoading } = t1; 77 let t2; 78 if ($[0] === Symbol.for("react.memo_cache_sentinel")) { 79 t2 = startOfDay(addDays(/* @__PURE__ */ new Date(), 1)); 80 $[0] = t2; 81 } else t2 = $[0]; 82 const tomorrow = t2; 83 let t3; 84 if ($[1] !== expiryDate || $[2] !== generateToken || $[3] !== isLoading || $[4] !== onSuccess || $[5] !== tokenName) { 85 t3 = async () => { 86 trackMethodCall("handleGenerate", []); 87 if (!tokenName.trim() || isLoading) return; 88 const { publicKey, privateKey } = await generateRsaKeys(); 89 let expiredTime; 90 if (expiryDate) { 91 const endOfDay = new Date(expiryDate); 92 endOfDay.setHours(23, 59, 59, 999); 93 expiredTime = endOfDay.toISOString(); 94 } 95 const result = await generateToken({ 96 name: tokenName.trim(), 97 publicKey, 98 privateKey, 99 ...expiredTime ? { expiredTime } : {} 100 }); 101 if ("data" in result && result.data?.data) { 102 onSuccess({ 103 ...result.data.data, 104 tokenName: tokenName.trim(), 105 publicKey, 106 privateKey 107 }); 108 setTokenName(""); 109 setExpiryDate(void 0); 110 } 111 }; 112 $[1] = expiryDate; 113 $[2] = generateToken; 114 $[3] = isLoading; 115 $[4] = onSuccess; 116 $[5] = tokenName; 117 $[6] = t3; 118 } else t3 = $[6]; 119 const handleGenerate = t3; 120 let t4; 121 if ($[7] !== onOpenChange) { 122 t4 = () => { 123 trackMethodCall("handleBackToTokenList", []); 124 setTokenName(""); 125 setExpiryDate(void 0); 126 onOpenChange(false); 127 }; 128 $[7] = onOpenChange; 129 $[8] = t4; 130 } else t4 = $[8]; 131 const handleBackToTokenList = t4; 132 let t5; 133 if ($[9] !== handleBackToTokenList) { 134 t5 = (open_0) => !open_0 && handleBackToTokenList(); 135 $[9] = handleBackToTokenList; 136 $[10] = t5; 137 } else t5 = $[10]; 138 let t6; 139 if ($[11] === Symbol.for("react.memo_cache_sentinel")) { 140 t6 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { 141 className: "gap-4", 142 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 143 className: "flex h-10 w-10 items-center justify-center rounded-xl bg-primary-muted", 144 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserRound, { className: "size-5 text-primary" }) 145 }
145), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { 146 className: "text-lg font-semibold text-foreground", 147 children: "Generate an API token" 148 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { 149 className: "mt-1 text-sm text-muted-foreground", 150 children: "Give your token a name so you can identify it later. We'll handle the rest automatically." 151 })] })] 152 }); 153 $[11] = t6; 154 } else t6 = $[11]; 155 let t7; 156 if ($[12] === Symbol.for("react.memo_cache_sentinel")) { 157 t7 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Label, { 158 className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", 159 children: ["Token Name ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 160 className: "text-destructive", 161 children: "*" 162 })] 163 }); 164 $[12] = t7; 165 } else t7 = $[12]; 166 let t8; 167 if ($[13] === Symbol.for("react.memo_cache_sentinel")) { 168 t8 = (e) => setTokenName(e.target.value); 169 $[13] = t8; 170 } else t8 = $[13]; 171 let t9; 172 if ($[14] !== handleGenerate) { 173 t9 = (e_0) => e_0.key === "Enter" && handleGenerate(); 174 $[14] = handleGenerate; 175 $[15] = t9; 176 } else t9 = $[15]; 177 let t10; 178 if ($[16] !== t9 || $[17] !== tokenName) { 179 t10 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 180 className: "flex flex-col gap-1.5", 181 children: [t7, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Input, { 182 placeholder: "Token name", 183 value: tokenName, 184 maxLength: 100, 185 onChange: t8, 186 onKeyDown: t9 187 })] 188 }); 189 $[16] = t9; 190 $[17] = tokenName; 191 $[18] = t10; 192 } else t10 = $[18]; 193 let t11; 194 if ($[19] === Symbol.for("react.memo_cache_sentinel")) { 195 t11 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Label, { 196 className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", 197 children: "Expiry Date" 198 }); 199 $[19] = t11; 200 } else t11 = $[19]; 201 let t12; 202 let t13; 203 if ($[20] === Symbol.for("react.memo_cache_sentinel")) { 204 t12 = (date) => setExpiryDate(date); 205 t13 = { before: tomorrow }; 206 $[20] = t12; 207 $[21] = t13; 208 } else { 209 t12 = $[20]; 210 t13 = $[21]; 211 } 212 let t14; 213 if ($[22] !== expiryDate) { 214 t14 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DatePicker, { 215 mode: "single", 216 selected: expiryDate, 217 onSelect: t12, 218 disabled: t13 219 }); 220 $[22] = expiryDate; 221 $[23] = t14; 222 } else t14 = $[23]; 223 let t15; 224 if ($[24] !== expiryDate) { 225 t15 = expiryDate ?? addYears(/* @__PURE__ */ new Date(), 1); 226 $[24] = expiryDate; 227 $[25] = t15; 228 } else t15 = $[25]; 229 let t16; 230 if ($[26] !== t15) { 231 t16 = format(t15, "MMMM d, yyyy"); 232 $[26] = t15; 233 $[27] = t16; 234 } else t16 = $[27]; 235 let t17; 236 if ($[28] !== t16) { 237 t17 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { 238 className: "text-xs text-muted-foreground", 239 children: [ 240 "Token will expire on ", 241 t16, 242 "." 243 ] 244 }); 245 $[28] = t16; 246 $[29] = t17; 247 } else t17 = $[29]; 248 let t18; 249 if ($[30] !== t14 || $[31] !== t17) { 250 t18 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 251 className: "flex flex-col gap-1.5", 252 children: [ 253 t11, 254 t14, 255 t17 256 ] 257 }); 258 $[30] = t14; 259 $[31] = t17; 260 $[32] = t18; 261 } else t18 = $[32]; 262 let t19; 263 if ($[33] !== t10 || $[34] !== t18) { 264 t19 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 265 className: "flex flex-col gap-4 px-5 pb-2", 266 children: [t10, t18] 267 }); 268 $[33] = t10; 269 $[34] = t18; 270 $[35] = t19; 271 } else t19 = $[35]; 272 let t20; 273 if ($[36] !== tokenName) { 274 t20 = tokenName.trim(); 275 $[36] = tokenName; 276 $[37] = t20; 277 } else t20 = $[37]; 278 const t21 = !t20; 279 let t22; 280 if ($[38] !== handleGenerate || $[39] !== isLoading || $[40] !== t21) { 281 t22 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { 282 className: "w-full", 283 onClick: handleGenerate, 284 loading: isLoading, 285 disabled: t21, 286 children: "Generate Token" 287 }); 288 $[38] = handleGenerate; 289 $[39] = isLoading; 290 $[40] = t21; 291 $[41] = t22; 292 } else t22 = $[41]; 293 let t23; 294 if ($[42] !== handleBackToTokenList) { 295 t23 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { 296 variant: "link", 297 onClick: handleBackToTokenList, 298 className: "w-full", 299 children: "â Back to token list" 300 }); 301 $[42] = handleBackToTokenList; 302 $[43] = t23; 303 } else t23 = $[43]; 304 let t24; 305 if ($[44] !== t22 || $[45] !== t23) { 306 t24 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 307 className: "flex flex-col gap-3 px-5 pt-2 pb-5", 308 children: [t22, t23] 309 }); 310 $[44] = t22; 311 $[45] = t23; 312 $[46] = t24; 313 } else t24 = $[46]; 314 let t25; 315 if ($[47] !== t19 || $[48] !== t24) { 316 t25 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogContent, {
317 showCloseButton: false, 318 className: "max-w-[460px]", 319 children: [ 320 t6, 321 t19, 322 t24 323 ] 324 }); 325 $[47] = t19; 326 $[48] = t24; 327 $[49] = t25; 328 } else t25 = $[49]; 329 let t26; 330 if ($[50] !== open || $[51] !== t25 || $[52] !== t5) { 331 t26 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Dialog, { 332 open, 333 onOpenChange: t5, 334 children: t25 335 }); 336 $[50] = open; 337 $[51] = t25; 338 $[52] = t5; 339 $[53] = t26; 340 } else t26 = $[53]; 341 return t26; 342}; 343var import_compiler_runtime$1 = /* @__PURE__ */ __toESM(require_compiler_runtime()); 344var copyToClipboard = (text) => { 345 return navigator.clipboard.writeText(text); 346}; 347var downloadCredentials = (data) => { 348 const json = JSON.stringify({ 349 name: data.tokenName, 350 client_id: data.issuerId, 351 jwt_token: data.jwtToken, 352 public_key: data.publicKey, 353 private_key: data.privateKey 354 }, null, 2); 355 const blob = new Blob([json], { type: "application/json" }); 356 const url = URL.createObjectURL(blob); 357 const a = document.createElement("a"); 358 a.href = url; 359 a.download = `${data.tokenName.replace(/\s+/g, "_")}_credentials.json`; 360 a.click(); 361 URL.revokeObjectURL(url); 362}; 363var SaveCredentialsDialog = (t0) => { 364 const $ = (0, import_compiler_runtime$1.c)(65); 365 const { open, data, onDone } = t0; 366 const [showJwt, setShowJwt] = (0, import_react.useState)(false); 367 if (!data) return null; 368 let t1; 369 if ($[0] !== data.expireTime) { 370 t1 = data.expireTime ? format(new Date(data.expireTime), "MMM d, yyyy") : "â"; 371 $[0] = data.expireTime; 372 $[1] = t1; 373 } else t1 = $[1]; 374 const expiryText = t1; 375 let t2; 376 if ($[2] !== onDone) { 377 t2 = (isOpen) => { 378 if (!isOpen) onDone(); 379 }; 380 $[2] = onDone; 381 $[3] = t2; 382 } else t2 = $[3]; 383 let t3; 384 if ($[4] === Symbol.for("react.memo_cache_sentinel")) { 385 t3 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, { children: "Save your credentials" }); 386 $[4] = t3; 387 } else t3 = $[4]; 388 let t4; 389 if ($[5] !== data.tokenName) { 390 t4 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [t3, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription, { children: data.tokenName })] }); 391 $[5] = data.tokenName; 392 $[6] = t4; 393 } else t4 = $[6]; 394 let t5; 395 if ($[7] === Symbol.for("react.memo_cache_sentinel")) { 396 t5 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 397 className: "flex items-start gap-2 rounded-md bg-amber-50 px-3 py-2.5 text-sm text-amber-700", 398 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, { className: "mt-0.5 size-4 shrink-0" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Copy or download your credentials now. The JWT token will not be shown again after closing this dialog." })] 399 }); 400 $[7] = t5; 401 } else t5 = $[7]; 402 let t6; 403 if ($[8] === Symbol.for("react.memo_cache_sentinel")) { 404 t6 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 405 className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", 406 children: "JWT Token" 407 }); 408 $[8] = t6; 409 } else t6 = $[8]; 410 let t7; 411 if ($[9] === Symbol.for("react.memo_cache_sentinel")) { 412 t7 = () => setShowJwt(_temp); 413 $[9] = t7; 414 } else t7 = $[9]; 415 let t8; 416 if ($[10] !== showJwt) { 417 t8 = showJwt ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EyeOff, { className: "size-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Eye, { className: "size-3.5" }); 418 $[10] = showJwt; 419 $[11] = t8; 420 } else t8 = $[11]; 421 const t9 = showJwt ? "Hide" : "Show"; 422 let t10; 423 if ($[12] !== t8 || $[13] !== t9) { 424 t10 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, { 425 variant: "outline", 426 size: "sm", 427 onClick: t7, 428 children: [t8, t9] 429 }); 430 $[12] = t8; 431 $[13] = t9; 432 $[14] = t10; 433 } else t10 = $[14]; 434 let t11; 435 if ($[15] !== data.jwtToken) { 436 t11 = () => copyToClipboard(data.jwtToken); 437 $[15] = data.jwtToken; 438 $[16] = t11; 439 } else t11 = $[16]; 440 let t12; 441 if ($[17] === Symbol.for("react.memo_cache_sentinel")) { 442 t12 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "size-3.5" }); 443 $[17] = t12; 444 } else t12 = $[17]; 445 let t13; 446 if ($[18] !== t11) { 447 t13 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, { 448 variant: "outline", 449 size: "sm", 450 onClick: t11, 451 children: [t12, "Copy"] 452 }); 453 $[18] = t11; 454 $[19] = t13; 455 } else t13 = $[19]; 456 let t14; 457 if ($[20] !== t10 || $[21] !== t13) { 458 t14 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 459 className: "flex items-center justify-between",
460 children: [t6, /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 461 className: "flex gap-2", 462 children: [t10, t13] 463 })] 464 }); 465 $[20] = t10; 466 $[21] = t13; 467 $[22] = t14; 468 } else t14 = $[22]; 469 let t15; 470 if ($[23] !== data.jwtToken || $[24] !== showJwt) { 471 t15 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 472 className: "mt-3 min-h-8 overflow-hidden text-sm break-all", 473 children: showJwt ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 474 className: "font-mono text-foreground", 475 children: data.jwtToken 476 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 477 className: "tracking-[0.25em] text-muted-foreground", 478 children: "⢠⢠⢠⢠⢠⢠⢠⢠⢠⢠⢠⢠⢠⢠⢠⢠⢠⢠⢠â¢" 479 }) 480 }); 481 $[23] = data.jwtToken; 482 $[24] = showJwt; 483 $[25] = t15; 484 } else t15 = $[25]; 485 let t16; 486 if ($[26] === Symbol.for("react.memo_cache_sentinel")) { 487 t16 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 488 className: "mt-3", 489 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { 490 className: "rounded bg-muted px-2 py-1 text-xs text-muted-foreground", 491 children: "Authorization: Bearer <token>" 492 }) 493 }); 494 $[26] = t16; 495 } else t16 = $[26]; 496 let t17; 497 if ($[27] !== t14 || $[28] !== t15) { 498 t17 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 499 className: "rounded-lg border border-border p-4", 500 children: [ 501 t14, 502 t15, 503 t16 504 ] 505 }); 506 $[27] = t14; 507 $[28] = t15; 508 $[29] = t17; 509 } else t17 = $[29]; 510 let t18; 511 if ($[30] === Symbol.for("react.memo_cache_sentinel")) { 512 t18 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 513 className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", 514 children: "Client ID" 515 }); 516 $[30] = t18; 517 } else t18 = $[30]; 518 let t19; 519 if ($[31] !== data.issuerId) { 520 t19 = () => copyToClipboard(data.issuerId); 521 $[31] = data.issuerId; 522 $[32] = t19; 523 } else t19 = $[32]; 524 let t20; 525 if ($[33] === Symbol.for("react.memo_cache_sentinel")) { 526 t20 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "size-3.5" }); 527 $[33] = t20; 528 } else t20 = $[33]; 529 let t21; 530 if ($[34] !== t19) { 531 t21 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 532 className: "flex items-center justify-between", 533 children: [t18, /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, { 534 variant: "outline", 535 size: "sm", 536 onClick: t19, 537 children: [t20, "Copy"] 538 })] 539 }); 540 $[34] = t19; 541 $[35] = t21; 542 } else t21 = $[35]; 543 let t22; 544 if ($[36] !== data.issuerId) { 545 t22 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { 546 className: "mt-2 font-mono text-sm text-foreground", 547 children: data.issuerId 548 }); 549 $[36] = data.issuerId; 550 $[37] = t22; 551 } else t22 = $[37]; 552 let t23; 553 if ($[38] !== expiryText) { 554 t23 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { 555 className: "mt-1 text-xs text-muted-foreground", 556 children: [ 557 "Expires ", 558 expiryText, 559 " · Unique identifier for this token" 560 ] 561 }); 562 $[38] = expiryText; 563 $[39] = t23; 564 } else t23 = $[39]; 565 let t24; 566 if ($[40] !== t21 || $[41] !== t22 || $[42] !== t23) { 567 t24 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 568 className: "rounded-lg border border-border p-4", 569 children: [ 570 t21, 571 t22, 572 t23 573 ] 574 }); 575 $[40] = t21; 576 $[41] = t22; 577 $[42] = t23; 578 $[43] = t24; 579 } else t24 = $[43]; 580 let t25; 581 if ($[44] !== t17 || $[45] !== t24) { 582 t25 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 583 className: "flex flex-col gap-3 px-5", 584 children: [ 585 t5, 586 t17, 587 t24 588 ] 589 }); 590 $[44] = t17; 591 $[45] = t24; 592 $[46] = t25; 593 } else t25 = $[46]; 594 let t26; 595 if ($[47] !== data) { 596 t26 = () => downloadCredentials(data); 597 $[47] = data; 598 $[48] = t26; 599 } else t26 = $[48]; 600 let t27; 601 if ($[49] === Symbol.for("react.memo_cache_sentinel")) { 602 t27 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { className: "size-4" }); 603 $[49] = t27; 604 } else t27 = $[49]; 605 let t28; 606 if ($[50] !== t26) { 607 t28 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, { 608 variant: "outline", 609 onClick: t26, 610 children: [t27, "Download"] 611 }); 612 $[50] = t26; 613 $[51] = t28; 614 } else t28 = $[51]; 615 let t29; 616 if ($[52] !== onDone) { 617 t29 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { 618 onClick: onDone, 619 children: "Done" 620 }); 621 $[52] = onDone; 622 $[53] = t29; 623 } else t29 = $[53]; 624 let t30; 625 if ($[54] !== t28 || $[55] !== t29) { 626 t30 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogFooter, { children: [t28, t29] }); 627 $[54] = t28; 628 $[55] = t29; 629 $[56] = t30; 630 } else t30 = $[56]; 631 let t31; 632 if ($[57] !== t25 || $[58] !== t30 || $[59] !== t4) { 633 t31 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogContent, {
634 showCloseButton: false, 635 className: "max-w-[520px]", 636 children: [ 637 t4, 638 t25, 639 t30 640 ] 641 }); 642 $[57] = t25; 643 $[58] = t30; 644 $[59] = t4; 645 $[60] = t31; 646 } else t31 = $[60]; 647 let t32; 648 if ($[61] !== open || $[62] !== t2 || $[63] !== t31) { 649 t32 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Dialog, { 650 open, 651 onOpenChange: t2, 652 children: t31 653 }); 654 $[61] = open; 655 $[62] = t2; 656 $[63] = t31; 657 $[64] = t32; 658 } else t32 = $[64]; 659 return t32; 660}; 661function _temp(v) { 662 return !v; 663} 664var import_compiler_runtime = /* @__PURE__ */ __toESM(require_compiler_runtime()); 665var MAX_API_TOKENS = 10; 666var API_DOCS_URL = "https://docs.truckerpath.com/navpro.html"; 667var EXPIRING_SOON_MS = 720 * 60 * 60 * 1e3; 668var formatExpiry = (expireTime) => { 669 return format(new Date(expireTime), "MMM d, yyyy"); 670}; 671var getTokenStatus = (expireTime) => { 672 const expireMs = new Date(expireTime).getTime(); 673 const now = Date.now(); 674 if (expireMs < now) return "expired"; 675 if (expireMs - now < EXPIRING_SOON_MS) return "expiring_soon"; 676 return "active"; 677}; 678var StatusBadge = (t0) => { 679 const $ = (0, import_compiler_runtime.c)(3); 680 const { status } = t0; 681 if (status === "active") { 682 let t1$1; 683 if ($[0] === Symbol.for("react.memo_cache_sentinel")) { 684 t1$1 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { 685 className: "border-transparent bg-green-100 tracking-wide text-green-700 uppercase hover:bg-green-100", 686 children: "Active" 687 }); 688 $[0] = t1$1; 689 } else t1$1 = $[0]; 690 return t1$1; 691 } 692 if (status === "expiring_soon") { 693 let t1$1; 694 if ($[1] === Symbol.for("react.memo_cache_sentinel")) { 695 t1$1 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { 696 className: "border-transparent bg-amber-100 tracking-wide text-amber-700 uppercase hover:bg-amber-100", 697 children: "Expiring Soon" 698 }); 699 $[1] = t1$1; 700 } else t1$1 = $[1]; 701 return t1$1; 702 } 703 let t1; 704 if ($[2] === Symbol.for("react.memo_cache_sentinel")) { 705 t1 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { 706 className: "border-transparent bg-slate-100 tracking-wide text-slate-500 uppercase hover:bg-slate-100", 707 children: "Expired" 708 }); 709 $[2] = t1; 710 } else t1 = $[2]; 711 return t1; 712}; 713var Integrations = () => { 714 const $ = (0, import_compiler_runtime.c)(61); 715 const [isGenerateOpen, setIsGenerateOpen] = (0, import_react.useState)(false); 716 const [credentialData, setCredentialData] = (0, import_react.useState)(null); 717 const [isSaveOpen, setIsSaveOpen] = (0, import_react.useState)(false); 718 const [deleteTarget, setDeleteTarget] = (0, import_react.useState)(null); 719 const [newIssuerId, setNewIssuerId] = (0, import_react.useState)(null); 720 let t0; 721 if ($[0] === Symbol.for("react.memo_cache_sentinel")) { 722 t0 = { 723 page: 1, 724 size: MAX_API_TOKENS 725 }; 726 $[0] = t0; 727 } else t0 = $[0]; 728 const { data, isLoading } = useGetTokenListQuery(t0); 729 const [deleteToken, t1] = useDeleteTokenMutation(); 730 const { isLoading: isDeleting } = t1; 731 const tokenData = data?.data; 732 let t2; 733 if ($[1] !== tokenData?.data || $[2] !== tokenData?.list || $[3] !== tokenData?.records) { 734 t2 = tokenData?.data ?? tokenData?.list ?? tokenData?.records ?? []; 735 $[1] = tokenData?.data; 736 $[2] = tokenData?.list; 737 $[3] = tokenData?.records; 738 $[4] = t2; 739 } else t2 = $[4]; 740 const tokens = t2; 741 const total = tokenData?.total ?? 0; 742 let t3; 743 if ($[5] === Symbol.for("react.memo_cache_sentinel")) { 744 t3 = (cred) => { 745 trackMethodCall("handleGenerateSuccess", [cred]); 746 setCredentialData(cred); 747 setNewIssuerId(cred.issuerId); 748 setIsGenerateOpen(false); 749 setIsSaveOpen(true); 750 }; 751 $[5] = t3; 752 } else t3 = $[5]; 753 const handleGenerateSuccess = t3; 754 let t4; 755 if ($[6] === Symbol.for("react.memo_cache_sentinel")) { 756 t4 = () => { 757 trackMethodCall("handleDone", []); 758 setIsSaveOpen(false); 759 setCredentialData(null); 760 }; 761 $[6] = t4; 762 } else t4 = $[6]; 763 const handleDone = t4; 764 let t5; 765 if ($[7] !== deleteTarget || $[8] !== deleteToken || $[9] !== newIssuerId) { 766 t5 = async () => { 767 trackMethodCall("handleDeleteConfirm", []); 768 if (!deleteTarget) return; 769 await deleteToken(deleteTarget.issuerId); 770 if (newIssuerId === deleteTarget.issuerId) setNewIssuerId(null); 771 setDeleteTarget(null); 772 }; 773 $[7] = deleteTarget; 774 $[8] = deleteToken; 775 $[9] = newIssuerId; 776 $[10] = t5; 777 } else t5 = $[10]; 778 const handleDeleteConfirm = t5; 779 let t6; 780 if ($[11] === Symbol.for("react.memo_cache_sentinel")) { 781 t6 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { 782 className: "text-xl font-semibold text-foreground", 783 children: "Integrations" 784 }
784), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { 785 className: "mt-1 text-[13px] leading-[19.5px] font-normal tracking-[-0.076px] text-slate-500", 786 children: "Manage your TruckerPath API credentials." 787 })] }); 788 $[11] = t6; 789 } else t6 = $[11]; 790 let t7; 791 if ($[12] !== total) { 792 t7 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { 793 className: "rounded-full bg-muted px-3 py-1 text-[12px] leading-[18px] font-medium text-[#1D4ED8]", 794 children: [ 795 total, 796 " / ", 797 MAX_API_TOKENS, 798 " tokens" 799 ] 800 }); 801 $[12] = total; 802 $[13] = t7; 803 } else t7 = $[13]; 804 let t8; 805 if ($[14] === Symbol.for("react.memo_cache_sentinel")) { 806 t8 = () => setIsGenerateOpen(true); 807 $[14] = t8; 808 } else t8 = $[14]; 809 const t9 = total >= MAX_API_TOKENS; 810 let t10; 811 if ($[15] === Symbol.for("react.memo_cache_sentinel")) { 812 t10 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Plus, { className: "size-4" }); 813 $[15] = t10; 814 } else t10 = $[15]; 815 let t11; 816 if ($[16] !== t9) { 817 t11 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, { 818 onClick: t8, 819 disabled: t9, 820 className: "h-auto gap-[6px] rounded-[8px] border-[1.176px] border-[#1D4ED8] bg-[#1D4ED8] px-[14px] py-[8px]", 821 children: [t10, "Generate New Token"] 822 }); 823 $[16] = t9; 824 $[17] = t11; 825 } else t11 = $[17]; 826 let t12; 827 if ($[18] !== t11 || $[19] !== t7) { 828 t12 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 829 className: "flex items-start justify-between gap-4", 830 children: [t6, /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 831 className: "flex items-center gap-3", 832 children: [t7, t11] 833 })] 834 }); 835 $[18] = t11; 836 $[19] = t7; 837 $[20] = t12; 838 } else t12 = $[20]; 839 let t13; 840 if ($[21] === Symbol.for("react.memo_cache_sentinel")) { 841 t13 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 842 className: "mt-5 flex items-center justify-between gap-4 rounded-lg bg-blue-50 px-4 py-3", 843 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 844 className: "flex items-center gap-2", 845 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Info, { className: "size-4 shrink-0 text-[#1E40AF]" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 846 className: "text-[13px] leading-[19.5px] font-normal tracking-[-0.076px] text-[#1E40AF]", 847 children: "Use API tokens to integrate your systems with TruckerPath. Each token is associated with a unique Client ID." 848 })] 849 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { 850 href: API_DOCS_URL, 851 target: "_blank", 852 rel: "noopener noreferrer", 853 className: "shrink-0 text-[13px] leading-[19.5px] font-medium tracking-[-0.076px] text-[#1D4ED8] hover:underline", 854 children: "View API documentation â" 855 })] 856 }); 857 $[21] = t13; 858 } else t13 = $[21]; 859 let t14; 860 if ($[22] === Symbol.for("react.memo_cache_sentinel")) { 861 t14 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableRow, { children: [ 862 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { 863 className: "w-[45%] text-xs font-semibold tracking-wider text-slate-400 uppercase", 864 children: "Name / Client ID" 865 }), 866 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { 867 className: "w-[25%] text-xs font-semibold tracking-wider text-slate-400 uppercase", 868 children: "Status" 869 }), 870 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { 871 className: "w-[20%] text-xs font-semibold tracking-wider text-slate-400 uppercase", 872 children: "Expires" 873 }), 874 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { className: "w-[10%]" }) 875 ] }) }); 876 $[22] = t14; 877 } else t14 = $[22]; 878 let t15; 879 if ($[23] !== isLoading || $[24] !== tokens.length) { 880 t15 = !isLoading && tokens.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableCell, {
881 colSpan: 4, 882 className: "py-16 text-center", 883 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { 884 className: "font-medium text-foreground", 885 children: "No API tokens yet" 886 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { 887 className: "mt-1 text-sm text-muted-foreground", 888 children: "Generate a token to start connecting your systems with NavPro." 889 })] 890 }) }); 891 $[23] = isLoading; 892 $[24] = tokens.length; 893 $[25] = t15; 894 } else t15 = $[25]; 895 let t16; 896 if ($[26] !== newIssuerId || $[27] !== tokens) { 897 let t17$1; 898 if ($[29] !== newIssuerId) { 899 t17$1 = (token) => { 900 const status = getTokenStatus(token.expireTime); 901 const isExpiring = status === "expiring_soon"; 902 const isExpired = status === "expired"; 903 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableRow, { children: [ 904 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 905 className: "flex flex-col gap-0.5", 906 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 907 className: "flex items-center gap-2", 908 children: [token.name && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 909 className: `text-[13px] leading-[19.5px] tracking-[-0.076px] ${isExpired ? "font-medium text-muted-foreground" : "font-semibold text-slate-900"}`, 910 children: token.name 911 }), token.issuerId === newIssuerId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { 912 variant: "default-subtle", 913 children: "New" 914 })] 915 }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 916 className: "flex items-center gap-1", 917 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 918 className: "font-mono text-[11px] leading-[16.5px] text-slate-400", 919 children: token.issuerId 920 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { 921 variant: "ghost", 922 size: "icon-sm", 923 "aria-label": "Copy Client ID", 924 onClick: () => navigator.clipboard.writeText(token.issuerId), 925 className: "text-slate-400/60 hover:text-slate-400", 926 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "size-[11.985px]" }) 927 })] 928 })] 929 }) }), 930 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { 931 className: "w-[25%] whitespace-nowrap", 932 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBadge, { status }) 933 }), 934 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { 935 className: "w-[20%] whitespace-nowrap", 936 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 937 className: isExpiring ? "font-medium text-amber-700" : isExpired ? "text-slate-400" : "text-slate-500", 938 children: formatExpiry(token.expireTime) 939 }) 940 }), 941 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { 942 className: "w-[10%]", 943 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { 944 variant: "ghost", 945 size: "icon-sm", 946 "aria-label": "Delete token", 947 onClick: () => setDeleteTarget(token), 948 className: "text-muted-foreground hover:text-destructive", 949 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Trash, { className: "size-4" }) 950 }) 951 }) 952 ] }, token.issuerId); 953 }; 954 $[29] = newIssuerId; 955 $[30] = t17$1; 956 } else t17$1 = $[30]; 957 t16 = tokens.map(t17$1); 958 $[26] = newIssuerId; 959 $[27] = tokens; 960 $[28] = t16; 961 } else t16 = $[28]; 962 let t17; 963 if ($[31] !== t15 || $[32] !== t16) { 964 t17 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 965 className: "mt-4", 966 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table, { children: [t14, /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableBody, { children: [t15, t16] })] }) 967 }); 968 $[31] = t15; 969 $[32] = t16; 970 $[33] = t17; 971 } else t17 = $[33]; 972 let t18; 973 if ($[34] !== t12 || $[35] !== t17) { 974 t18 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 975 className: "flex-1 overflow-auto py-6", 976 children: [ 977 t12, 978 t13, 979 t17 980 ] 981 }); 982 $[34] = t12; 983 $[35] = t17; 984 $[36] = t18; 985 } else t18 = $[36]; 986 let t19; 987 if ($[37] !== isGenerateOpen) { 988 t19 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GenerateTokenDialog, { 989 open: isGenerateOpen, 990 onOpenChange: setIsGenerateOpen, 991 onSuccess: handleGenerateSuccess 992 }); 993 $[37] = isGenerateOpen; 994 $[38] = t19; 995 } else t19 = $[38]; 996 let t20; 997 if ($[39] !== credentialData || $[40] !== isSaveOpen) { 998 t20 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SaveCredentialsDialog, { 999 open: isSaveOpen, 1000 data: credentialData, 1001 onDone: handleDone 1002 }); 1003 $[39] = credentialData; 1004 $[40] = isSaveOpen; 1005 $[41] = t20; 1006 } else t20 = $[41]; 1007 const t21 = !!deleteTarget; 1008 let t22; 1009 if ($[42] === Symbol.for("react.memo_cache_sentinel")) { 1010 t22 = (open) => !open && setDeleteTarget(null); 1011 $[42] = t22; 1012 } else t22 = $[42]; 1013 let t23; 1014 if ($[43] === Symbol.for("react.memo_cache_sentinel")) { 1015 t23 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogTitle, { children: "Delete API token?" }); 1016 $[43] = t23; 1017 } else t23 = $[43]; 1018 const t24 = deleteTarget?.name; 1019 let t25; 1020 if ($[44] !== t24) { 1021 t25 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogHeader, { children: [t23, /* @__P
1021URE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogDescription, { children: [ 1022 "â", 1023 t24, 1024 "â will be permanently deleted. Any integrations using this token will stop working immediately." 1025 ] })] }); 1026 $[44] = t24; 1027 $[45] = t25; 1028 } else t25 = $[45]; 1029 let t26; 1030 if ($[46] === Symbol.for("react.memo_cache_sentinel")) { 1031 t26 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogCancel, { children: "Cancel" }); 1032 $[46] = t26; 1033 } else t26 = $[46]; 1034 let t27; 1035 if ($[47] !== handleDeleteConfirm || $[48] !== isDeleting) { 1036 t27 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogFooter, { children: [t26, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogAction, { 1037 variant: "destructive", 1038 onClick: handleDeleteConfirm, 1039 disabled: isDeleting, 1040 children: "Delete" 1041 })] }); 1042 $[47] = handleDeleteConfirm; 1043 $[48] = isDeleting; 1044 $[49] = t27; 1045 } else t27 = $[49]; 1046 let t28; 1047 if ($[50] !== t25 || $[51] !== t27) { 1048 t28 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogContent, { children: [t25, t27] }); 1049 $[50] = t25; 1050 $[51] = t27; 1051 $[52] = t28; 1052 } else t28 = $[52]; 1053 let t29; 1054 if ($[53] !== t21 || $[54] !== t28) { 1055 t29 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialog, { 1056 open: t21, 1057 onOpenChange: t22, 1058 children: t28 1059 }); 1060 $[53] = t21; 1061 $[54] = t28; 1062 $[55] = t29; 1063 } else t29 = $[55]; 1064 let t30; 1065 if ($[56] !== t18 || $[57] !== t19 || $[58] !== t20 || $[59] !== t29) { 1066 t30 = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 1067 className: "flex h-full flex-col px-5", 1068 children: [ 1069 t18, 1070 t19, 1071 t20, 1072 t29 1073 ] 1074 }); 1075 $[56] = t18; 1076 $[57] = t19; 1077 $[58] = t20; 1078 $[59] = t29; 1079 $[60] = t30; 1080 } else t30 = $[60]; 1081 return t30; 1082}; 1083export { Integrations };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.