@camstack/addon-admin-ui 1.2.96 → 1.2.98
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/assets/{AddLocationWizard-7HXgNBWJ.js → AddLocationWizard-BH8qzKUS.js} +1 -1
- package/dist/assets/{AddonCollectionPage-Tz6pUPgq.js → AddonCollectionPage-DBot-bgj.js} +1 -1
- package/dist/assets/{Addons-eviwvm1Q.js → Addons-D9EFNHE1.js} +1 -1
- package/dist/assets/{AdminTabs-BacD8YLL.js → AdminTabs-Dk1eLBgE.js} +1 -1
- package/dist/assets/{AiProfiles-C66qnr0a.js → AiProfiles-BQ_3LDPD.js} +1 -1
- package/dist/assets/{BrokerForm-D2uKDvTb.js → BrokerForm-GsfCv1ks.js} +1 -1
- package/dist/assets/{Build-OJqDm99i.js → Build-D3dp29Pc.js} +1 -1
- package/dist/assets/{Capabilities-pY76s-il.js → Capabilities-CoYla6oL.js} +1 -1
- package/dist/assets/{CapabilityBadges-BJnRgUWh.js → CapabilityBadges-DGA5_XiI.js} +1 -1
- package/dist/assets/{Cluster-DDDFrbT4.js → Cluster-DV1zGnLF.js} +1 -1
- package/dist/assets/{Data-BUC8oitr.js → Data-zSfgUsc7.js} +1 -1
- package/dist/assets/{DetectionIntelligence-BrpoaCw-.js → DetectionIntelligence-aHCL16Cy.js} +1 -1
- package/dist/assets/{DeviceAggregateSection-CzBiUH7Q.js → DeviceAggregateSection-BSMvAqDX.js} +1 -1
- package/dist/assets/{DeviceDetail-BJaUoh8P.js → DeviceDetail-DH0vN28R.js} +1 -1
- package/dist/assets/{Devices-CWvBcb7g.js → Devices-BYXPSPMY.js} +1 -1
- package/dist/assets/{EmbedPlayerPage-GCdMVPns.js → EmbedPlayerPage-Chq0wty0.js} +1 -1
- package/dist/assets/{Events-vE-EGnK8.js → Events-EROtLWJf.js} +1 -1
- package/dist/assets/{FormBuilder-D3fxAgRR.js → FormBuilder-C7GWtsAC.js} +1 -1
- package/dist/assets/{Identity-1PvF_DWd.js → Identity-CQZ5NPpO.js} +1 -1
- package/dist/assets/{IntegrationDetail-XUrYk1pF.js → IntegrationDetail-CWL7rGIm.js} +1 -1
- package/dist/assets/{Integrations-D4-8-Obx.js → Integrations-DAIDYD8x.js} +1 -1
- package/dist/assets/{Integrations-DpBQxr0I.js → Integrations-Defjpzw9.js} +1 -1
- package/dist/assets/{Logs-DN6_NKF5.js → Logs-DvLobSoL.js} +1 -1
- package/dist/assets/{MotionZonesSettings-XMPsARUd.js → MotionZonesSettings-B_MAiEkW.js} +1 -1
- package/dist/assets/{MyAccess-CKvI-Z0_.js → MyAccess-Ci2ZSSm5.js} +1 -1
- package/dist/assets/{Network-B95UTPbG.js → Network-BovHq3wO.js} +1 -1
- package/dist/assets/{NodeAddonsSettingsPanel-Bc7bSbqj.js → NodeAddonsSettingsPanel-kZjm-up8.js} +1 -1
- package/dist/assets/{NodeInferenceDevices-BByQ_HIP.js → NodeInferenceDevices-CW1MDnBG.js} +1 -1
- package/dist/assets/{Notifications-Bjfo5qwM.js → Notifications-C8I3Vz31.js} +1 -1
- package/dist/assets/{Pipeline-1-iGl6tS.js → Pipeline-BBVvpBCd.js} +1 -1
- package/dist/assets/Plates-qD8BtBqF.js +1 -0
- package/dist/assets/{PrivacyMaskSettings-CHvicgXi.js → PrivacyMaskSettings-axbq_wSU.js} +1 -1
- package/dist/assets/{ProviderIcon-BoVzH148.js → ProviderIcon-DllNEady.js} +1 -1
- package/dist/assets/{Recordings-D6LJy8Rc.js → Recordings-CzEDQqtj.js} +1 -1
- package/dist/assets/{ScanNetworkModal-MOAZa-jX.js → ScanNetworkModal-CW0yYE5R.js} +1 -1
- package/dist/assets/{SceneMonitorEditor-x5UklOIZ.js → SceneMonitorEditor-Cq2t8wbg.js} +1 -1
- package/dist/assets/{Scenes-DJFUGhWI.js → Scenes-Xn6O5H7e.js} +1 -1
- package/dist/assets/{Settings-CtH4Cg4r.js → Settings-D9Vlv2hw.js} +1 -1
- package/dist/assets/{Showroom-tGL0F9f_.js → Showroom-Bp6aCuMd.js} +1 -1
- package/dist/assets/{Terminal-BJpVPocr.js → Terminal-7vWKE2zb.js} +1 -1
- package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-DBMO3fsc.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-DrOgR36u.js} +1 -1
- package/dist/assets/{bell-ring-CzOT6NMB.js → bell-ring-D4Iz5fKj.js} +1 -1
- package/dist/assets/{boxes-DswpMqB1.js → boxes-BFsuQuon.js} +1 -1
- package/dist/assets/{build-cluster-graph-BrByHTLD.js → build-cluster-graph-Cl_uvOCR.js} +1 -1
- package/dist/assets/circle-check-big-HrHc_ipL.js +1 -0
- package/dist/assets/{circle-x-DyNv4OyW.js → circle-x-y_k7wCKw.js} +1 -1
- package/dist/assets/clock-D2qlcgwd.js +1 -0
- package/dist/assets/{copy-FYfDQ47B.js → copy-BrVxemF7.js} +1 -1
- package/dist/assets/{debounced-invalidate-BH1sC5jE.js → debounced-invalidate-CNZ2w-7t.js} +1 -1
- package/dist/assets/{dist-Co7g7F9h.js → dist-C7L1HtAB.js} +1 -1
- package/dist/assets/dist-JjXjac1y.js +349 -0
- package/dist/assets/{download-BC5TewX7.js → download-DPw0c0lm.js} +1 -1
- package/dist/assets/{face-bbox-Dn6UYckX.js → face-bbox-d1aWGz2s.js} +1 -1
- package/dist/assets/{hostInit-BBnsXvqc.js → hostInit-D5R1Qfsh.js} +1 -1
- package/dist/assets/{index-CEBJ8eMc.js → index-iNi1Y7nh.js} +3 -3
- package/dist/assets/{key-round-WwYx_tWB.js → key-round-fO7JDI-O.js} +1 -1
- package/dist/assets/{mf-entry-bootstrap-0-7adc4db4.js → mf-entry-bootstrap-0-f566460e.js} +2 -2
- package/dist/assets/{pencil-tOoSQgOe.js → pencil-B4i0ErRE.js} +1 -1
- package/dist/assets/play-BxkaaFOu.js +1 -0
- package/dist/assets/{player-overlays-DDdfjf3a.js → player-overlays-DLbOIwJR.js} +1 -1
- package/dist/assets/plus-DE5rskj6.js +1 -0
- package/dist/assets/power-CzV5Z-a_.js +1 -0
- package/dist/assets/{radio-DOXhded3.js → radio-CxioeWPp.js} +1 -1
- package/dist/assets/{refresh-cw-BUIUPFCx.js → refresh-cw-B8ABC_pB.js} +1 -1
- package/dist/assets/remoteEntry-DXwp0vbz.js +1 -0
- package/dist/assets/rotate-ccw-CD3wu9ON.js +1 -0
- package/dist/assets/rotate-cw-8vMRQVny.js +1 -0
- package/dist/assets/search-Dia6mspm.js +1 -0
- package/dist/assets/{send-XtWs9fvd.js → send-BqmuTM7o.js} +1 -1
- package/dist/assets/{server-mkNfNOY7.js → server-D9l8GGnn.js} +1 -1
- package/dist/assets/{shield-CBzh6N_L.js → shield-B_7hlY3B.js} +1 -1
- package/dist/assets/square-Cj45Ro71.js +1 -0
- package/dist/assets/{square-check-big-Dj6GBQ2z.js → square-check-big-B8iw67nQ.js} +1 -1
- package/dist/assets/src-CQrwlltP.js +349 -0
- package/dist/assets/{src-BZYWQYID.js → src-UiaZA05p.js} +17 -17
- package/dist/assets/{star-DHlHcHTP.js → star-BTw7N-6p.js} +1 -1
- package/dist/assets/{undo-2-Cjrq9n-U.js → undo-2-DG5MLTW-.js} +1 -1
- package/dist/assets/{upload-BTd5OdKC.js → upload-DAJfnCVB.js} +1 -1
- package/dist/assets/{use-scenes-feed-BfWfqf9H.js → use-scenes-feed-B6yeT27i.js} +1 -1
- package/dist/assets/useEventInvalidation-D7ElHW62.js +1 -0
- package/dist/assets/{video-FO1i6n6W.js → video-D4j_U5zK.js} +1 -1
- package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-CQJelRoY.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-Di4hPkeF.js} +2 -2
- package/dist/assets/{wifi-CTIqltCN.js → wifi-BW00qcYq.js} +1 -1
- package/dist/assets/{zap-LGSGshyr.js → zap-BSOiEhX4.js} +1 -1
- package/dist/index.html +5 -5
- package/dist/server/addon.js +103 -27
- package/package.json +1 -1
- package/dist/assets/Plates-DQWBAsO7.js +0 -1
- package/dist/assets/circle-check-big-1XtyEULB.js +0 -1
- package/dist/assets/clock-Bj5qhvvB.js +0 -1
- package/dist/assets/dist-DNOH5tQa.js +0 -349
- package/dist/assets/play-CCCY3IiJ.js +0 -1
- package/dist/assets/plus-B3wRoz6c.js +0 -1
- package/dist/assets/power-BVqfHLBQ.js +0 -1
- package/dist/assets/remoteEntry-Bp_xGqaI.js +0 -1
- package/dist/assets/rotate-ccw-DZrozpxW.js +0 -1
- package/dist/assets/rotate-cw-CoHNvA24.js +0 -1
- package/dist/assets/search-Do5uPwT2.js +0 -1
- package/dist/assets/square-BI_w3nhL.js +0 -1
- package/dist/assets/src-Ddt6JS34.js +0 -349
- package/dist/assets/useEventInvalidation-BSkjRuXC.js +0 -1
package/dist/server/addon.js
CHANGED
|
@@ -5802,6 +5802,13 @@ var BaseAddon = class {
|
|
|
5802
5802
|
_readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
|
|
5803
5803
|
/** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
|
|
5804
5804
|
_registeredCapNames = [];
|
|
5805
|
+
/**
|
|
5806
|
+
* True only after `readAddonStore` actually answered. Constructor
|
|
5807
|
+
* defaults look like stored config when the store is down — a forked
|
|
5808
|
+
* addon that auto-starts from those defaults (cloudflare-tunnel quick
|
|
5809
|
+
* mode, 2026-08-25) is not "the operator chose this".
|
|
5810
|
+
*/
|
|
5811
|
+
settingsStoreReady = false;
|
|
5805
5812
|
/** Default config values. Provided via constructor. */
|
|
5806
5813
|
defaults;
|
|
5807
5814
|
constructor(defaults) {
|
|
@@ -6202,7 +6209,9 @@ var BaseAddon = class {
|
|
|
6202
6209
|
];
|
|
6203
6210
|
let lastErr;
|
|
6204
6211
|
for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
|
|
6205
|
-
|
|
6212
|
+
const stored = await settings.readAddonStore() ?? {};
|
|
6213
|
+
this.settingsStoreReady = true;
|
|
6214
|
+
return stored;
|
|
6206
6215
|
} catch (err) {
|
|
6207
6216
|
lastErr = err;
|
|
6208
6217
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -6210,6 +6219,7 @@ var BaseAddon = class {
|
|
|
6210
6219
|
if (attempt === delaysMs.length) break;
|
|
6211
6220
|
await new Promise((r) => setTimeout(r, delaysMs[attempt]));
|
|
6212
6221
|
}
|
|
6222
|
+
this.settingsStoreReady = false;
|
|
6213
6223
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
6214
6224
|
return {};
|
|
6215
6225
|
}
|
|
@@ -11742,6 +11752,27 @@ var LinkedDeviceSchema = object({
|
|
|
11742
11752
|
features: array(string()),
|
|
11743
11753
|
producesTrackedEvents: boolean().optional()
|
|
11744
11754
|
});
|
|
11755
|
+
/** One camera's resolved linked set, tagged with the camera it belongs to.
|
|
11756
|
+
* The batch answer needs the tag; the single-device answer already has it
|
|
11757
|
+
* from the input, which is why `getLinkedDevices` keeps the untagged shape. */
|
|
11758
|
+
var LinkedDevicesForDeviceSchema = object({
|
|
11759
|
+
deviceId: number(),
|
|
11760
|
+
mode: LinkedDevicesModeSchema,
|
|
11761
|
+
devices: array(LinkedDeviceSchema)
|
|
11762
|
+
});
|
|
11763
|
+
/** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
|
|
11764
|
+
* `getAllBindings` all answer in. Declared once: three copies of the same
|
|
11765
|
+
* object literal is exactly how the three drift apart. */
|
|
11766
|
+
var DeviceBindingsForDeviceSchema = object({
|
|
11767
|
+
deviceId: number(),
|
|
11768
|
+
entries: array(object({
|
|
11769
|
+
capName: string(),
|
|
11770
|
+
kind: _enum(["native", "wrapped"]),
|
|
11771
|
+
providerAddonId: string(),
|
|
11772
|
+
providerNodeId: string(),
|
|
11773
|
+
nativeAddonId: string()
|
|
11774
|
+
}))
|
|
11775
|
+
});
|
|
11745
11776
|
var SavedDeviceRowSchema = object({
|
|
11746
11777
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
11747
11778
|
id: number(),
|
|
@@ -11967,11 +11998,25 @@ method(object({
|
|
|
11967
11998
|
projection: _enum(["full", "slim"]).optional(),
|
|
11968
11999
|
/** Return only camera devices. Filtering server-side instead of
|
|
11969
12000
|
* shipping 293 rows to find 12. */
|
|
11970
|
-
isCamera: boolean().optional()
|
|
12001
|
+
isCamera: boolean().optional(),
|
|
12002
|
+
/**
|
|
12003
|
+
* Return only these device ids. For the caller that already KNOWS the
|
|
12004
|
+
* handful it wants and needs a field the id-bearing answer does not
|
|
12005
|
+
* carry — the viewer's linked-devices panel joins `type` and `online`
|
|
12006
|
+
* onto ~8 linked ids and, unfiltered, dragged the fleet across to do
|
|
12007
|
+
* it: 433 KB slim / 958 KB full for 967 devices, on a query that
|
|
12008
|
+
* refetches on the reconcile interval, on a phone.
|
|
12009
|
+
*
|
|
12010
|
+
* Safe to send at a hub that predates it: Zod STRIPS unknown input
|
|
12011
|
+
* keys rather than rejecting them (verified against the live hub
|
|
12012
|
+
* 2026-08-25 — 967 rows came back), so an old hub answers exactly what
|
|
12013
|
+
* it answers today and the caller filters as it already does.
|
|
12014
|
+
*/
|
|
12015
|
+
deviceIds: array(number()).optional()
|
|
11971
12016
|
}), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
11972
12017
|
mode: LinkedDevicesModeSchema,
|
|
11973
12018
|
devices: array(LinkedDeviceSchema)
|
|
11974
|
-
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
12019
|
+
})), method(object({ deviceIds: array(number()) }), array(LinkedDevicesForDeviceSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
11975
12020
|
deviceId: number(),
|
|
11976
12021
|
values: record(string(), unknown())
|
|
11977
12022
|
}), object({ success: literal(true) }), {
|
|
@@ -11998,25 +12043,7 @@ method(object({
|
|
|
11998
12043
|
}), method(object({ deviceId: number() }), array(StreamProbeResultSchema), {
|
|
11999
12044
|
kind: "mutation",
|
|
12000
12045
|
auth: "admin"
|
|
12001
|
-
}), method(object({ deviceId: number() }), object({
|
|
12002
|
-
deviceId: number(),
|
|
12003
|
-
entries: array(object({
|
|
12004
|
-
capName: string(),
|
|
12005
|
-
kind: _enum(["native", "wrapped"]),
|
|
12006
|
-
providerAddonId: string(),
|
|
12007
|
-
providerNodeId: string(),
|
|
12008
|
-
nativeAddonId: string()
|
|
12009
|
-
}))
|
|
12010
|
-
})), method(object({}), array(object({
|
|
12011
|
-
deviceId: number(),
|
|
12012
|
-
entries: array(object({
|
|
12013
|
-
capName: string(),
|
|
12014
|
-
kind: _enum(["native", "wrapped"]),
|
|
12015
|
-
providerAddonId: string(),
|
|
12016
|
-
providerNodeId: string(),
|
|
12017
|
-
nativeAddonId: string()
|
|
12018
|
-
}))
|
|
12019
|
-
}))), method(object({
|
|
12046
|
+
}), method(object({ deviceId: number() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
|
|
12020
12047
|
deviceId: number(),
|
|
12021
12048
|
capName: string(),
|
|
12022
12049
|
wrapperAddonId: string(),
|
|
@@ -23975,8 +24002,10 @@ var PlateInfoSchema = object({
|
|
|
23975
24002
|
keyFrameMediaKey: string().optional(),
|
|
23976
24003
|
base64: string().optional(),
|
|
23977
24004
|
/**
|
|
23978
|
-
* Same crop as a data-plane URL
|
|
23979
|
-
* never inlines JPEG; `listPlates`
|
|
24005
|
+
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
24006
|
+
* crop. `getPlateByTrack` returns this and never inlines JPEG; `listPlates`
|
|
24007
|
+
* and `searchPlates` inline the crop only when their `includeCrops` input is
|
|
24008
|
+
* left at its `true` default.
|
|
23980
24009
|
*/
|
|
23981
24010
|
cropUrl: string().optional()
|
|
23982
24011
|
});
|
|
@@ -23996,14 +24025,34 @@ var PlateClusterSchema = object({
|
|
|
23996
24025
|
});
|
|
23997
24026
|
method(object({
|
|
23998
24027
|
deviceId: number().int().optional(),
|
|
23999
|
-
limit: number().int().positive().optional()
|
|
24028
|
+
limit: number().int().positive().optional(),
|
|
24029
|
+
/**
|
|
24030
|
+
* Inline the base64 crop on every row. Default `true` — the existing
|
|
24031
|
+
* behaviour, kept so no caller breaks.
|
|
24032
|
+
*
|
|
24033
|
+
* Set `false` once the caller renders {@link PlateInfo.cropUrl}.
|
|
24034
|
+
* Measured on the live hub at the 500 rows the Plates view asks for:
|
|
24035
|
+
* 879,403 B and 27.7 s with the crops inline, against a few KiB of
|
|
24036
|
+
* metadata without them — and the browser then caches the images.
|
|
24037
|
+
*
|
|
24038
|
+
* This is the plate twin of `faceGallery.listRecentFaces`'s option;
|
|
24039
|
+
* plates were the one gallery list left without it.
|
|
24040
|
+
*
|
|
24041
|
+
* **This is an INPUT field, so it does not reach the addon until the
|
|
24042
|
+
* next train.** The hub router validates cap inputs against its own
|
|
24043
|
+
* compiled Zod and strips a key it does not know. Until the train
|
|
24044
|
+
* ships, sending `false` is harmless and keeps the crops inline.
|
|
24045
|
+
*/
|
|
24046
|
+
includeCrops: boolean().optional()
|
|
24000
24047
|
}).optional(), array(PlateInfoSchema).readonly()), method(object({
|
|
24001
24048
|
deviceId: number().int(),
|
|
24002
24049
|
trackId: string()
|
|
24003
24050
|
}), PlateInfoSchema.nullable()), method(object({ plateId: string() }), array(MediaFileLiteSchema).readonly()), method(object({
|
|
24004
24051
|
text: string().min(1),
|
|
24005
24052
|
maxDistance: number().int().min(0).optional(),
|
|
24006
|
-
limit: number().int().positive().optional()
|
|
24053
|
+
limit: number().int().positive().optional(),
|
|
24054
|
+
/** See `listPlates.includeCrops`. Default `true`. */
|
|
24055
|
+
includeCrops: boolean().optional()
|
|
24007
24056
|
}), array(PlateInfoSchema).readonly()), method(object({
|
|
24008
24057
|
maxDistance: number().int().min(0).optional(),
|
|
24009
24058
|
minClusterSize: number().int().min(2).optional(),
|
|
@@ -27618,6 +27667,12 @@ Object.freeze({
|
|
|
27618
27667
|
addonId: null,
|
|
27619
27668
|
access: "view"
|
|
27620
27669
|
},
|
|
27670
|
+
"deviceManager.getBindingsBatch": {
|
|
27671
|
+
capName: "device-manager",
|
|
27672
|
+
capScope: "system",
|
|
27673
|
+
addonId: null,
|
|
27674
|
+
access: "view"
|
|
27675
|
+
},
|
|
27621
27676
|
"deviceManager.getChildren": {
|
|
27622
27677
|
capName: "device-manager",
|
|
27623
27678
|
capScope: "system",
|
|
@@ -27678,6 +27733,12 @@ Object.freeze({
|
|
|
27678
27733
|
addonId: null,
|
|
27679
27734
|
access: "view"
|
|
27680
27735
|
},
|
|
27736
|
+
"deviceManager.getLinkedDevicesBatch": {
|
|
27737
|
+
capName: "device-manager",
|
|
27738
|
+
capScope: "system",
|
|
27739
|
+
addonId: null,
|
|
27740
|
+
access: "view"
|
|
27741
|
+
},
|
|
27681
27742
|
"deviceManager.getRoleDisplayDefaults": {
|
|
27682
27743
|
capName: "device-manager",
|
|
27683
27744
|
capScope: "system",
|
|
@@ -32325,6 +32386,11 @@ Object.freeze({
|
|
|
32325
32386
|
form: "single",
|
|
32326
32387
|
optional: false
|
|
32327
32388
|
}],
|
|
32389
|
+
"deviceManager.getBindingsBatch": [{
|
|
32390
|
+
name: "deviceIds",
|
|
32391
|
+
form: "array",
|
|
32392
|
+
optional: false
|
|
32393
|
+
}],
|
|
32328
32394
|
"deviceManager.getChildren": [{
|
|
32329
32395
|
name: "parentDeviceId",
|
|
32330
32396
|
form: "single",
|
|
@@ -32370,6 +32436,11 @@ Object.freeze({
|
|
|
32370
32436
|
form: "single",
|
|
32371
32437
|
optional: false
|
|
32372
32438
|
}],
|
|
32439
|
+
"deviceManager.getLinkedDevicesBatch": [{
|
|
32440
|
+
name: "deviceIds",
|
|
32441
|
+
form: "array",
|
|
32442
|
+
optional: false
|
|
32443
|
+
}],
|
|
32373
32444
|
"deviceManager.getSettingsSchema": [{
|
|
32374
32445
|
name: "deviceId",
|
|
32375
32446
|
form: "single",
|
|
@@ -32390,6 +32461,11 @@ Object.freeze({
|
|
|
32390
32461
|
form: "single",
|
|
32391
32462
|
optional: false
|
|
32392
32463
|
}],
|
|
32464
|
+
"deviceManager.listAll": [{
|
|
32465
|
+
name: "deviceIds",
|
|
32466
|
+
form: "array",
|
|
32467
|
+
optional: true
|
|
32468
|
+
}],
|
|
32393
32469
|
"deviceManager.loadConfig": [{
|
|
32394
32470
|
name: "deviceId",
|
|
32395
32471
|
form: "single",
|
|
@@ -34242,7 +34318,7 @@ var AdminUIAddon = class extends BaseAddon {
|
|
|
34242
34318
|
capability: adminUiCapability,
|
|
34243
34319
|
provider: {
|
|
34244
34320
|
getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
|
|
34245
|
-
getVersion: async () => ({ version: "1.2.
|
|
34321
|
+
getVersion: async () => ({ version: "1.2.98" })
|
|
34246
34322
|
}
|
|
34247
34323
|
}];
|
|
34248
34324
|
}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{K as e,Q as t,S as n,W as r,b as i,o as a,q as o,x as s,z as c}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DhP-Lgiq.js";import{At as l,Br as u,Co as d,Dt as f,Et as p,Fs as m,It as h,Lt as g,Ot as _,Pt as v,So as y,_o as b,bo as x,fo as S,go as C,ho as w,kt as T,mo as E,po as D,vo as O,wo as k,wt as A,xo as j,yo as M}from"./src-BZYWQYID.js";import{Rt as N}from"./src-Ddt6JS34.js";import{a as P,i as ee,n as F,r as I,t as L}from"./face-bbox-Dn6UYckX.js";import{a as R,c as z,f as B,i as te,l as ne,m as V,n as H,o as re,p as ie,r as U,s as ae,t as W,u as oe}from"./debounced-invalidate-BH1sC5jE.js";import{t as G}from"./pencil-tOoSQgOe.js";import{t as K}from"./plus-B3wRoz6c.js";import{t as se}from"./square-check-big-Dj6GBQ2z.js";import{t as q}from"./square-BI_w3nhL.js";import{B as J,C as Y,I as ce,K as le,R as ue,i as X,s as Z,z as de}from"./index-CEBJ8eMc.js";import{t as fe}from"./AdminPage-CCD07UMs.js";import{r as pe,t as me}from"./authed-media-BPd_L9jr.js";var he=le(`badge-check`,[[`path`,{d:`M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z`,key:`3c2336`}],[`path`,{d:`m9 12 2 2 4-4`,key:`dzmm74`}]]);t();var Q=[[`plateGallery`]];function ge({vehicleId:e}){let t=a(),{data:r,isLoading:i}=M({vehicleId:e}),o=j();function c(n){o.mutate({vehicleId:e,sampleId:n.id},{onSettled:()=>{t.invalidateQueries({queryKey:Q})}})}return i?n(`div`,{className:`flex items-center gap-2 py-3 text-xs text-foreground-subtle`,children:[s(Y,{className:`h-3.5 w-3.5 animate-spin`}),`Loading plates…`]}):!r||r.length===0?s(`p`,{className:`py-2 text-xs text-foreground-subtle`,children:`No plates yet.`}):s(`div`,{className:`mt-2 grid grid-cols-3 gap-2 sm:grid-cols-4 md:grid-cols-6`,children:r.map(e=>n(`div`,{className:`group relative overflow-hidden rounded-md border border-border bg-surface`,children:[n(`div`,{className:`relative aspect-[2/1] overflow-hidden bg-surface-hover`,children:[e.base64?s(`img`,{src:`data:image/jpeg;base64,${e.base64}`,alt:e.text,className:`h-full w-full object-cover`}):s(`div`,{className:`flex h-full w-full items-center justify-center text-foreground-subtle`,children:s(J,{className:`h-6 w-6`})}),s(`button`,{type:`button`,onClick:()=>c(e),disabled:o.isPending,className:`absolute inset-0 flex items-center justify-center bg-black/50 opacity-0 transition-opacity group-hover:opacity-100 disabled:cursor-not-allowed`,"aria-label":`Remove plate sample`,children:s(X,{className:`h-4 w-4 text-white`})})]}),s(`p`,{className:`truncate px-1.5 py-1 text-center font-mono text-[11px] font-semibold tracking-wide text-foreground`,title:e.text,children:e.text})]},e.id))})}function _e({vehicle:e,expanded:t,onToggle:r}){let c=a(),[u,d]=o(``),[m,b]=o(!1),[x,S]=o(!1),w=y(),E=C();function D(){d(e.name),b(!0)}function O(){b(!1),d(``)}function k(){let t=u.trim();if(!t||t===e.name){O();return}w.mutate({id:e.id,name:t},{onSettled:()=>{c.invalidateQueries({queryKey:Q}),O()}})}function j(){E.mutate({id:e.id},{onSettled:()=>{c.invalidateQueries({queryKey:Q}),S(!1)}})}return n(`div`,{className:`rounded-md border border-border bg-surface`,children:[n(`div`,{className:`flex items-center gap-2 px-3 py-2`,children:[s(`div`,{className:`h-8 w-12 shrink-0 overflow-hidden rounded border border-border bg-surface-hover`,children:e.coverBase64?s(`img`,{src:`data:image/jpeg;base64,${e.coverBase64}`,alt:e.name,className:`h-full w-full object-cover`}):s(`div`,{className:`flex h-full w-full items-center justify-center`,children:s(J,{className:`h-4 w-4 text-foreground-subtle`})})}),s(`div`,{className:`flex flex-1 min-w-0 items-center gap-2`,children:m?n(i,{children:[s(v,{value:u,onChange:e=>d(e.target.value),onKeyDown:e=>{e.key===`Enter`&&k(),e.key===`Escape`&&O()},className:`h-6 text-xs`,autoFocus:!0}),s(`button`,{type:`button`,onClick:k,disabled:w.isPending,className:`text-success hover:text-success/80 disabled:opacity-50`,"aria-label":`Confirm rename`,children:s(de,{className:`h-3.5 w-3.5`})}),s(`button`,{type:`button`,onClick:O,className:`text-foreground-subtle hover:text-foreground`,"aria-label":`Cancel rename`,children:s(X,{className:`h-3.5 w-3.5`})})]}):s(`span`,{className:`truncate text-sm font-medium text-foreground`,children:e.name})}),s(h,{variant:`default`,className:`text-[10px]`,children:e.sampleCount}),!m&&n(`div`,{className:`flex items-center gap-1`,children:[s(`button`,{type:`button`,onClick:D,className:`p-1 rounded hover:bg-surface-hover text-foreground-subtle hover:text-foreground`,"aria-label":`Rename`,children:s(G,{className:`h-3.5 w-3.5`})}),s(`button`,{type:`button`,onClick:()=>S(!0),className:`p-1 rounded hover:bg-danger/10 text-foreground-subtle hover:text-danger`,"aria-label":`Delete`,children:s(Z,{className:`h-3.5 w-3.5`})})]}),s(`button`,{type:`button`,onClick:r,className:`p-1 rounded hover:bg-surface-hover text-foreground-subtle`,"aria-label":t?`Collapse`:`Expand`,children:s(t?ue:ce,{className:`h-3.5 w-3.5`})})]}),t&&s(`div`,{className:`border-t border-border px-3 pb-3 pt-2`,children:s(ge,{vehicleId:e.id})}),s(A,{open:x,onOpenChange:e=>!e&&S(!1),children:n(p,{children:[n(T,{children:[s(l,{children:`Delete vehicle`}),n(f,{children:[`Delete `,s(`strong`,{children:e.name}),` and all its plate samples? This cannot be undone.`]})]}),n(_,{children:[s(g,{variant:`secondary`,onClick:()=>S(!1),children:`Cancel`}),n(g,{variant:`danger`,onClick:j,disabled:E.isPending,children:[E.isPending?s(Y,{className:`h-3.5 w-3.5 animate-spin`}):null,`Delete`]})]})]})})]})}function ve(){let e=a(),[t,r]=o(``),i=E();function c(){let n=t.trim();n&&i.mutate({name:n},{onSettled:()=>{e.invalidateQueries({queryKey:Q}),r(``)}})}return n(`div`,{className:`flex items-center gap-2 pt-2`,children:[s(v,{placeholder:`New vehicle name…`,value:t,onChange:e=>r(e.target.value),onKeyDown:e=>{e.key===`Enter`&&c()},className:`h-7 text-xs flex-1`}),n(g,{variant:`primary`,size:`sm`,onClick:c,disabled:i.isPending||!t.trim(),children:[i.isPending?s(Y,{className:`h-3.5 w-3.5 animate-spin`}):s(K,{className:`h-3.5 w-3.5`}),`Add`]})]})}function ye(){let{data:e,isLoading:t}=x(),[r,i]=o(null);function a(e){i(t=>t===e?null:e)}return t?n(`div`,{className:`flex items-center gap-2 py-4 text-xs text-foreground-subtle`,children:[s(Y,{className:`h-4 w-4 animate-spin`}),`Loading vehicles…`]}):n(`div`,{className:`space-y-2`,children:[(!e||e.length===0)&&s(`p`,{className:`py-2 text-xs text-foreground-subtle`,children:`No vehicles enrolled yet. Add one below.`}),e?.map(e=>s(_e,{vehicle:e,expanded:r===e.id,onToggle:()=>a(e.id)},e.id)),s(ve,{})]})}t();var be=[[`plateGallery`]];function xe(e){let[t,n]=o(null),[r,i]=o(null),[a,s]=o(!1);return c(()=>{if(n(null),i(null),s(!1),!e)return;let t=!1,r=null;return(async()=>{try{let i=await pe(`${me}/${encodeURIComponent(e)}`);if(t)return;r=URL.createObjectURL(i),n(r)}catch{t||s(!0)}})(),()=>{t=!0,r&&URL.revokeObjectURL(r)}},[e]),c(()=>{if(!t)return;let e=new Image;return e.onload=()=>i({width:e.naturalWidth,height:e.naturalHeight}),e.onerror=()=>s(!0),e.src=t,()=>{e.onload=null,e.onerror=null}},[t]),{frameSrc:t,naturalWidth:r?.width??null,naturalHeight:r?.height??null,failed:a}}function Se(e){let t=e.filter(e=>e.base64.length>0);return t.length===0?null:t.find(e=>/crop|plate/i.test(e.kind))??t[0]}function $({label:e,value:t,mono:r}){return n(`div`,{className:`flex items-baseline justify-between gap-3 py-1.5 border-b border-border/60 last:border-0`,children:[s(`span`,{className:`shrink-0 text-[11px] uppercase tracking-wide text-foreground-subtle`,children:e}),s(`span`,{className:`min-w-0 truncate text-right text-xs font-medium text-foreground ${r?`font-mono`:``}`,title:t,children:t})]})}function Ce({box:e}){return s(`div`,{className:`pointer-events-none absolute rounded-[3px] border-2 border-primary shadow-[0_0_0_9999px_rgba(0,0,0,0.28)]`,style:{left:`${String(e.x*100)}%`,top:`${String(e.y*100)}%`,width:`${String(e.width*100)}%`,height:`${String(e.height*100)}%`},children:s(`span`,{className:`absolute -top-4 left-0 rounded bg-primary px-1 text-[9px] font-semibold uppercase tracking-wide text-white`,children:`Plate`})})}function we({plate:e,cameraName:t,onClose:i,onAssign:l,onUnassign:u,onDelete:d,actionsPending:f}){let m=a(),{data:h,isFetching:_}=b({plateId:e?.plateId??``},{enabled:e!==null}),y=D(),[x,S]=o(`frame`),[C,w]=o(!1),[T,E]=o(``),{frameSrc:O,naturalWidth:k,naturalHeight:j,failed:M}=xe(e?.keyFrameMediaKey);c(()=>{w(!1),E(``),S(`frame`)},[e?.plateId]);let N=r(()=>{let t=Se(h??[]);return t?`data:image/jpeg;base64,${t.base64}`:e?.base64?`data:image/jpeg;base64,${e.base64}`:null},[h,e]),R=r(()=>!e?.plateBbox||k===null||j===null?null:L(e.plateBbox,k,j),[e?.plateBbox,k,j]);if(e===null)return null;let z=typeof e.keyFrameMediaKey==`string`&&e.keyFrameMediaKey.length>0&&!M,B=z&&x===`frame`,te=e.assigned?e.vehicleName??`Assigned`:e.recognizedVehicleId?`${e.vehicleName??`Recognized`} (suggested)`:`Unassigned`,ne=`${String(Math.round(e.score*100))}%${e.corrected?` · corrected`:``}`;function re(){e&&(E(e.text),w(!0))}function U(){if(!e)return;let t=T.trim().toUpperCase();if(!t||t===e.text){w(!1);return}y.mutate({plateId:e.plateId,text:t},{onSettled:()=>{m.invalidateQueries({queryKey:be}),w(!1)}})}return s(A,{open:!0,onOpenChange:e=>!e&&i(),children:n(p,{width:`lg`,placement:`sheet-on-mobile`,"aria-label":`Plate detail`,className:`flex h-[92dvh] flex-col gap-0 overflow-hidden p-0 bottom-0 left-0 right-0 top-auto w-full max-w-full translate-x-0 translate-y-0 rounded-b-none md:bottom-auto md:left-1/2 md:right-auto md:top-1/2 md:h-auto md:w-[calc(100vw-2rem)] md:max-w-xl md:-translate-x-1/2 md:-translate-y-1/2 md:rounded-lg md:max-h-[calc(100dvh-2rem)]`,children:[n(`header`,{className:`flex shrink-0 items-start justify-between gap-2 border-b border-border px-4 py-3`,children:[n(`div`,{className:`min-w-0`,children:[s(`div`,{className:`truncate font-mono text-sm font-semibold tracking-wide text-foreground`,children:e.text||`Plate detail`}),s(`div`,{className:`mt-0.5 truncate text-[11px] text-foreground-subtle`,children:t})]}),s(`button`,{type:`button`,onClick:i,className:`rounded p-1 text-foreground-subtle hover:bg-surface-hover hover:text-foreground`,"aria-label":`Close`,children:s(X,{className:`h-4 w-4`})})]}),n(`div`,{className:`min-h-0 flex-1 space-y-3 overflow-y-auto overscroll-contain px-4 py-3`,children:[z&&n(`div`,{className:`flex items-center gap-1 rounded-md border border-border p-0.5 text-xs`,children:[n(`button`,{type:`button`,onClick:()=>S(`frame`),className:`flex flex-1 items-center justify-center gap-1 rounded px-2 py-1 transition-colors ${x===`frame`?`bg-primary/12 font-medium text-primary`:`text-foreground-subtle hover:bg-surface-hover hover:text-foreground`}`,children:[s(ee,{className:`h-3.5 w-3.5`}),` Full frame`]}),n(`button`,{type:`button`,onClick:()=>S(`crop`),className:`flex flex-1 items-center justify-center gap-1 rounded px-2 py-1 transition-colors ${x===`crop`?`bg-primary/12 font-medium text-primary`:`text-foreground-subtle hover:bg-surface-hover hover:text-foreground`}`,children:[s(P,{className:`h-3.5 w-3.5`}),` Crop`]})]}),B&&O?s(`div`,{className:`overflow-hidden rounded-lg border border-border bg-background`,children:s(H,{src:O,alt:`Full frame with detected plate`,fit:`natural`,className:`w-full`,overlay:R?s(Ce,{box:R}):void 0})}):N?n(`div`,{className:`relative aspect-[2/1] w-full overflow-hidden rounded-lg border border-border bg-background`,children:[s(H,{src:N,alt:`Detected plate`,className:`h-full w-full`}),_&&s(`div`,{className:`absolute right-2 top-2 rounded-full bg-black/50 p-1 text-white`,children:s(Y,{className:`h-3.5 w-3.5 animate-spin`})})]}):n(`div`,{className:`flex aspect-[2/1] w-full flex-col items-center justify-center gap-1.5 rounded-lg border border-border bg-warning/5 text-foreground-subtle`,children:[s(V,{className:`h-8 w-8 text-warning/70`}),s(`span`,{className:`text-[11px] font-medium uppercase tracking-wide text-warning/80`,children:`No image`}),s(`span`,{className:`px-6 text-center text-[10px] text-foreground-subtle`,children:`The crop media for this plate could not be resolved. Safe to delete.`})]}),s(`div`,{className:`rounded-lg border border-border bg-surface px-3 py-2`,children:n(`div`,{className:`flex items-center justify-between gap-3`,children:[s(`span`,{className:`shrink-0 text-[11px] uppercase tracking-wide text-foreground-subtle`,children:`Plate text`}),C?n(`div`,{className:`flex min-w-0 flex-1 items-center justify-end gap-1.5`,children:[s(v,{value:T,onChange:e=>E(e.target.value),onKeyDown:e=>{e.key===`Enter`&&U(),e.key===`Escape`&&w(!1)},className:`h-7 max-w-[10rem] text-right font-mono text-xs uppercase`,autoFocus:!0}),s(`button`,{type:`button`,onClick:U,disabled:y.isPending,className:`text-success hover:text-success/80 disabled:opacity-50`,"aria-label":`Save corrected text`,children:y.isPending?s(Y,{className:`h-3.5 w-3.5 animate-spin`}):s(de,{className:`h-3.5 w-3.5`})}),s(`button`,{type:`button`,onClick:()=>w(!1),className:`text-foreground-subtle hover:text-foreground`,"aria-label":`Cancel`,children:s(X,{className:`h-3.5 w-3.5`})})]}):n(`button`,{type:`button`,onClick:re,className:`group flex min-w-0 items-center gap-1.5`,title:`Correct the OCR reading`,children:[s(`span`,{className:`truncate font-mono text-sm font-semibold tracking-wide text-foreground`,children:e.text||`—`}),s(G,{className:`h-3 w-3 shrink-0 text-foreground-subtle group-hover:text-foreground`})]})]})}),n(`div`,{className:`rounded-lg border border-border bg-surface px-3 py-1`,children:[s($,{label:`Camera`,value:t}),s($,{label:`Captured`,value:ie(e.timestamp)}),s($,{label:`Confidence`,value:ne}),s($,{label:`Vehicle`,value:te}),s($,{label:`Track`,value:e.trackId,mono:!0})]})]}),n(`footer`,{className:`flex shrink-0 items-center justify-end gap-2 border-t border-border px-4 py-3 pb-[max(0.75rem,env(safe-area-inset-bottom))]`,children:[e.assigned?n(g,{variant:`secondary`,onClick:()=>u(e.plateId),disabled:f,children:[s(F,{className:`h-3.5 w-3.5`}),` Detach`]}):n(g,{variant:`primary`,onClick:()=>l(e.plateId),disabled:f,children:[s(I,{className:`h-3.5 w-3.5`}),` Assign`]}),n(g,{variant:`secondary`,onClick:()=>d(e.plateId),disabled:f,children:[s(Z,{className:`h-3.5 w-3.5`}),` Delete`]})]})]})})}t();var Te=[[`plateGallery`]];function Ee({plateIds:e,vehicles:t,onDone:r}){let i=a(),c=S(),u=E(),[d,m]=o(``),[h,y]=o(!1),[b,x]=o(null),C=e!==null&&e.length>0,w=e?.length??0;function D(){y(!1),m(``),x(null)}function O(){D(),r()}function k(t){!e||e.length===0||c.mutate({plateIds:[...e],vehicleId:t},{onSettled:()=>{i.invalidateQueries({queryKey:Te}),O()}})}function j(){!e||!d.trim()||u.mutate({name:d.trim()},{onSuccess:e=>{e?.id&&k(e.id)},onError:()=>{i.invalidateQueries({queryKey:Te}),O()}})}let M=c.isPending||u.isPending;return s(A,{open:C,onOpenChange:e=>!e&&O(),children:n(p,{children:[n(T,{children:[s(l,{children:w>1?`Assign ${String(w)} plates to vehicle`:`Assign plate to vehicle`}),s(f,{children:`Select an existing vehicle or create a new one.`})]}),s(`div`,{className:`space-y-1 max-h-56 overflow-y-auto`,children:t.map(e=>n(`button`,{type:`button`,onClick:()=>x(e.id),className:`w-full rounded-md px-3 py-2 text-left text-xs transition-colors ${b===e.id?`bg-primary/12 text-primary`:`hover:bg-surface-hover text-foreground`}`,children:[s(`span`,{className:`font-medium`,children:e.name}),n(`span`,{className:`ml-2 text-foreground-subtle`,children:[e.sampleCount,` plates`]})]},e.id))}),h?s(`div`,{className:`flex items-center gap-2 pt-2 border-t border-border`,children:s(v,{placeholder:`New vehicle name…`,value:d,onChange:e=>m(e.target.value),onKeyDown:e=>{e.key===`Enter`&&j()},autoFocus:!0,className:`flex-1`})}):s(`button`,{type:`button`,onClick:()=>{x(null),y(!0)},className:`mt-2 w-full rounded-md border border-dashed border-border px-3 py-2 text-left text-xs text-foreground-subtle hover:border-primary hover:text-primary transition-colors`,children:`+ New vehicle…`}),n(_,{children:[s(g,{variant:`secondary`,onClick:O,disabled:M,children:`Cancel`}),h?n(g,{variant:`primary`,onClick:j,disabled:M||!d.trim(),children:[M&&s(Y,{className:`h-3.5 w-3.5 animate-spin`}),`Create & assign`]}):n(g,{variant:`primary`,onClick:()=>b&&k(b),disabled:M||!b,children:[M&&s(Y,{className:`h-3.5 w-3.5 animate-spin`}),`Assign`,w>1?` ${String(w)}`:``]})]})]})})}t();var De=[[`plateGallery`]],Oe=500,ke=120;function Ae({plate:e,cameraName:t,nowMs:r,selected:i,onToggleSelect:o,onAssign:c,onOpenDetail:l}){let u=a(),f=d(),p=w(),m=()=>{u.invalidateQueries({queryKey:De})},h=()=>l(e.plateId);return n(`div`,{className:`relative flex flex-col overflow-hidden rounded-md border bg-surface ${i?`border-primary ring-1 ring-primary`:`border-border`}`,children:[n(`div`,{className:`relative aspect-[2/1] overflow-hidden bg-surface-hover`,children:[e.base64?s(`img`,{src:`data:image/jpeg;base64,${e.base64}`,alt:`Plate ${e.text} from ${t}`,onClick:h,className:`h-full w-full cursor-zoom-in object-cover`}):n(`button`,{type:`button`,onClick:h,className:`flex h-full w-full flex-col items-center justify-center gap-1 bg-warning/5 text-foreground-subtle`,title:`No crop image — the plate's crop media is missing. Safe to delete.`,children:[s(V,{className:`h-7 w-7 text-warning/70`}),s(`span`,{className:`text-[9px] font-medium uppercase tracking-wide text-warning/80`,children:`No crop`})]}),s(`button`,{type:`button`,onClick:t=>{t.stopPropagation(),o(e.plateId)},className:`absolute left-0 top-0 z-10 rounded-br-md bg-black/50 p-1.5 text-white hover:bg-black/70`,"aria-label":i?`Deselect`:`Select`,children:i?s(se,{className:`h-4 w-4 text-primary`}):s(q,{className:`h-4 w-4`})}),e.corrected&&n(`span`,{className:`absolute right-0 top-0 z-10 flex items-center gap-0.5 rounded-bl-md bg-primary/80 px-1 py-0.5 text-[8px] font-semibold uppercase tracking-wide text-white`,title:`Manually corrected`,children:[s(he,{className:`h-3 w-3`}),` Fixed`]})]}),n(`div`,{className:`min-w-0 px-2 pt-1.5 space-y-0.5`,children:[s(`p`,{className:`truncate font-mono text-xs font-bold tracking-wide text-foreground`,title:e.text,children:e.text||`—`}),s(`p`,{className:`truncate text-[10px] text-foreground-subtle`,title:t,children:t}),s(`p`,{className:`truncate text-[10px] text-foreground-subtle`,children:B(e.timestamp,r)}),e.vehicleName&&s(`p`,{className:`truncate text-[10px] font-medium text-primary`,title:e.vehicleName,children:e.vehicleName})]}),n(`div`,{className:`mt-1 flex items-center gap-0.5 border-t border-border/60 px-1 py-0.5`,children:[e.assigned?s(`button`,{type:`button`,onClick:t=>{t.stopPropagation(),f.mutate({plateId:e.plateId},{onSettled:m})},disabled:f.isPending,className:`rounded p-1.5 text-foreground-subtle transition-colors hover:bg-warning/10 hover:text-warning disabled:opacity-40`,"aria-label":`Detach plate`,title:`Detach`,children:f.isPending?s(Y,{className:`h-4 w-4 animate-spin`}):s(F,{className:`h-4 w-4`})}):s(`button`,{type:`button`,onClick:t=>{t.stopPropagation(),c(e.plateId)},className:`rounded p-1.5 text-foreground-subtle transition-colors hover:bg-primary/10 hover:text-primary`,"aria-label":`Assign plate to vehicle`,title:`Assign to vehicle`,children:s(I,{className:`h-4 w-4`})}),s(`button`,{type:`button`,onClick:t=>{t.stopPropagation(),p.mutate({plateId:e.plateId},{onSettled:m})},disabled:p.isPending,className:`ml-auto rounded p-1.5 text-foreground-subtle transition-colors hover:bg-danger/10 hover:text-danger disabled:opacity-40`,"aria-label":`Delete plate`,title:`Delete plate`,children:p.isPending?s(Y,{className:`h-4 w-4 animate-spin`}):s(Z,{className:`h-4 w-4`})})]})]})}var je=[{label:`All`,value:`all`},{label:`Unassigned`,value:`unassigned`},{label:`Assigned`,value:`assigned`}];function Me(e,t){return t===`unassigned`?e.filter(e=>!e.assigned):t===`assigned`?e.filter(e=>e.assigned):e}function Ne(){let e=a(),[t,c]=o(`all`),[l,f]=o(ae),[p,m]=o(new Set),[h,_]=o(new Set),[v,y]=o(null),[b,S]=o(null),{data:C,isLoading:T}=O({limit:Oe},{refetchInterval:3e4}),{data:E=[]}=x(),{data:D}=u({}),A=d(),j=k(),M=w(),N=Date.now(),P=C??[],ee=r(()=>{let e=new Map;for(let t of D??[])e.set(t.id,t.name);return e},[D]),L=e=>ee.get(e)??`Camera #${String(e)}`,B=r(()=>z(P).map(e=>({id:e,name:L(e)})).sort((e,t)=>e.name.localeCompare(t.name)),[P,ee]),V=r(()=>ne(oe(Me(P,t),l),p),[P,t,l,p]),H=re(V,ke,r(()=>JSON.stringify([t,l.fromMs,l.toMs,[...p].sort((e,t)=>e-t)]),[t,l.fromMs,l.toMs,p])),ie=r(()=>new Map(P.map(e=>[e.plateId,e])),[P]),W=b===null?null:ie.get(b)??null,G=()=>{e.invalidateQueries({queryKey:De})},K=()=>_(new Set);function se(e){_(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})}let q=[...h],J=j.isPending||M.isPending,ce=A.isPending||M.isPending;function le(){q.length!==0&&j.mutate({plateIds:q},{onSettled:()=>{G(),K()}})}function ue(){q.length!==0&&Promise.allSettled(q.map(e=>M.mutateAsync({plateId:e}))).then(()=>{G(),K()})}function de(e){S(null),y([e])}function fe(e){A.mutate({plateId:e},{onSettled:G}),S(null)}function pe(e){M.mutate({plateId:e},{onSettled:G}),S(null)}let me=V.length!==P.length;return n(`div`,{className:`relative space-y-3`,children:[n(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[s(`div`,{className:`flex items-center gap-1`,children:je.map(e=>s(`button`,{type:`button`,onClick:()=>c(e.value),className:`rounded-md px-2.5 py-1 text-xs transition-colors ${t===e.value?`bg-primary/12 text-primary font-medium`:`text-foreground-subtle hover:bg-surface-hover hover:text-foreground`}`,children:e.label},e.value))}),s(U,{onChange:f}),s(te,{cameras:B,selected:p,onChange:m}),!T&&s(`span`,{className:`ml-auto text-[10px] text-foreground-subtle`,children:me?`${String(V.length)} of ${String(P.length)} plates`:`${String(V.length)} plate${V.length===1?``:`s`}`})]}),h.size>0&&n(`div`,{className:`flex flex-wrap items-center gap-2 rounded-md border border-primary/40 bg-primary/8 px-3 py-2`,children:[n(`span`,{className:`text-xs font-medium text-foreground`,children:[h.size,` selected`]}),n(`div`,{className:`ml-auto flex flex-wrap items-center gap-1.5`,children:[n(g,{variant:`primary`,onClick:()=>y(q),disabled:J,children:[s(I,{className:`h-3.5 w-3.5`}),` Assign`]}),n(g,{variant:`secondary`,onClick:le,disabled:J,children:[j.isPending?s(Y,{className:`h-3.5 w-3.5 animate-spin`}):s(F,{className:`h-3.5 w-3.5`}),` `,`Detach`]}),n(g,{variant:`secondary`,onClick:ue,disabled:J,children:[s(Z,{className:`h-3.5 w-3.5`}),` Delete`]}),s(g,{variant:`ghost`,onClick:K,disabled:J,children:s(X,{className:`h-3.5 w-3.5`})})]})]}),T&&n(`div`,{className:`flex items-center gap-2 py-4 text-xs text-foreground-subtle`,children:[s(Y,{className:`h-4 w-4 animate-spin`}),` Loading plates…`]}),!T&&V.length===0&&s(`p`,{className:`py-4 text-xs text-foreground-subtle`,children:P.length>0?`No plates match the current filters.`:`No plates recognized yet.`}),!T&&V.length>0&&n(i,{children:[s(`div`,{className:`grid grid-cols-[repeat(auto-fill,minmax(9rem,1fr))] gap-2`,children:H.pageItems.map(e=>s(Ae,{plate:e,cameraName:L(e.deviceId),nowMs:N,selected:h.has(e.plateId),onToggleSelect:se,onAssign:e=>y([e]),onOpenDetail:S},e.plateId))}),s(R,{currentPage:H.page,totalItems:H.totalItems,pageSize:H.pageSize,onPageChange:H.setPage,itemNoun:`plates`})]}),s(we,{plate:W,cameraName:W?L(W.deviceId):``,onClose:()=>S(null),onAssign:de,onUnassign:fe,onDelete:pe,actionsPending:ce}),s(Ee,{plateIds:v,vehicles:E,onDone:()=>{y(null),K()}})]})}t();var Pe=[[`plateGallery`]],Fe=2e3;function Ie(){let t=a(),n=e(t);n.current=t;let r=e(void 0);r.current||=W({delayMs:Fe,invalidate:()=>{n.current.invalidateQueries({queryKey:Pe})}}),c(()=>()=>r.current?.cancel(),[]),m(N.PipelineAnalyticsPlateGalleryChanged,()=>{r.current?.trigger()})}function Le(){return Ie(),s(fe,{icon:J,title:`Plates`,subtitle:`Manage enrolled vehicles and assign recognized license plates to them.`,children:n(`section`,{className:`space-y-3`,children:[n(`div`,{children:[s(`h2`,{className:`text-sm font-semibold text-foreground mb-1`,children:`Vehicles`}),s(`p`,{className:`text-xs text-foreground-subtle mb-3`,children:`Enrolled vehicle identities used for plate recognition. Expand a row to view or remove plate samples.`}),s(ye,{})]}),n(`div`,{className:`pt-4 border-t border-border`,children:[s(`h2`,{className:`text-sm font-semibold text-foreground mb-1`,children:`Recent recognized plates`}),s(`p`,{className:`text-xs text-foreground-subtle mb-3`,children:`License plates read by the detection pipeline. Assign them to a vehicle, correct the OCR text, or delete.`}),s(Ne,{})]})]})})}export{Le as PlatesPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{K as e}from"./index-CEBJ8eMc.js";var t=e(`circle-check-big`,[[`path`,{d:`M21.801 10A10 10 0 1 1 17 3.335`,key:`yps3ct`}],[`path`,{d:`m9 11 3 3L22 4`,key:`1pflzl`}]]);export{t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{K as e}from"./index-CEBJ8eMc.js";var t=e(`clock`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`polyline`,{points:`12 6 12 12 16 14`,key:`68esgv`}]]);export{t};
|