@7365admin1/layer-common 3.2.8-staging.205 → 3.2.8-staging.206

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.
@@ -31,7 +31,7 @@
31
31
  item-value="key"
32
32
  show-header
33
33
  @refresh="loadDashboard"
34
- @update:page="page = $event"
34
+ @update:page="goToPage"
35
35
  >
36
36
  <template #actions>
37
37
  <AppButton icon="mdi-download" @click="openExportDialog">Export</AppButton>
@@ -62,20 +62,27 @@
62
62
  v-model="selectedReaderId"
63
63
  class="reader-select"
64
64
  :items="readerOptions"
65
- @update:model-value="loadDashboard"
65
+ @update:model-value="reloadDashboardFromFirstPage"
66
+ />
67
+ <AppField
68
+ v-model="search"
69
+ search
70
+ placeholder="Search"
71
+ @keyup.enter="reloadDashboardFromFirstPage"
66
72
  />
67
- <AppField v-model="search" search placeholder="Search" />
68
73
  <AppSelect
69
74
  v-model="status"
70
75
  :items="statusOptions"
71
76
  placeholder="Status"
72
77
  clearable
78
+ @update:model-value="reloadDashboardFromFirstPage"
73
79
  />
74
80
  <AppSelect
75
81
  v-model="accessMethod"
76
82
  :items="accessMethodFilterOptions"
77
83
  placeholder="Access Method"
78
84
  clearable
85
+ @update:model-value="reloadDashboardFromFirstPage"
79
86
  />
80
87
  </div>
81
88
  </template>
@@ -320,16 +327,57 @@ type PdfAccessRow = {
320
327
  accessDateTime: string;
321
328
  };
322
329
 
323
- const { getReaders, getIdentities, getLogs, getUserImage, runObjectOperation, getReaderConfiguration } = useHidAmico();
330
+ type HidAccessRecord = {
331
+ [key: string]: unknown;
332
+ _id?: string | number;
333
+ id?: string | number;
334
+ name?: string;
335
+ location?: string;
336
+ metadata?: HidAccessRecord;
337
+ payload?: HidAccessRecord;
338
+ identity?: HidAccessRecord;
339
+ identityLookup?: HidAccessRecord;
340
+ rawAccessLog?: HidAccessRecord;
341
+ reader?: HidAccessRecord;
342
+ authorization?: HidAccessRecord;
343
+ data?: HidAccessRecord;
344
+ result?: HidAccessRecord;
345
+ values?: HidAccessRecord;
346
+ access_logs?: HidAccessRecord[];
347
+ accessLogs?: HidAccessRecord[];
348
+ object_changes?: unknown[];
349
+ };
350
+
351
+ type JsPdf = {
352
+ internal: { pageSize: { getWidth(): number; getHeight(): number } };
353
+ setFillColor(red: number, green: number, blue: number): void;
354
+ setDrawColor(red: number, green: number, blue: number): void;
355
+ setTextColor(red: number, green: number, blue: number): void;
356
+ setFont(name: string, style: string): void;
357
+ setFontSize(size: number): void;
358
+ rect(x: number, y: number, width: number, height: number, style?: string): void;
359
+ text(value: string | string[], x: number, y: number): void;
360
+ addPage(): void;
361
+ splitTextToSize(value: string, width: number): string[];
362
+ save(filename: string): void;
363
+ };
364
+
365
+ const {
366
+ getReaders,
367
+ getIdentities,
368
+ getLogs,
369
+ getUserImage,
370
+ getReaderUsers,
371
+ getReaderAccessLogs,
372
+ } = useHidAmico();
324
373
  const { getVisitors } = useVisitor();
325
374
 
326
- const readers = ref<Record<string, any>[]>([]);
327
- const identities = ref<Record<string, any>[]>([]);
328
- const allIdentities = ref<Record<string, any>[]>([]);
329
- const visitorRecords = ref<Record<string, any>>({});
330
- const logs = ref<Record<string, any>[]>([]);
331
- const liveAccessLogs = ref<Record<string, any>[]>([]);
332
- const readerConfiguration = ref<Record<string, any>>({});
375
+ const readers = ref<HidAccessRecord[]>([]);
376
+ const identities = ref<HidAccessRecord[]>([]);
377
+ const allIdentities = ref<HidAccessRecord[]>([]);
378
+ const visitorRecords = ref<Record<string, HidAccessRecord>>({});
379
+ const logs = ref<HidAccessRecord[]>([]);
380
+ const liveAccessLogs = ref<HidAccessRecord[]>([]);
333
381
  const administratorUserIds = ref<Set<number>>(new Set());
334
382
  const userImages = ref<Record<string, string>>({});
335
383
  const selectedReaderId = ref("");
@@ -339,6 +387,8 @@ const status = ref("");
339
387
  const accessMethod = ref("");
340
388
  const page = ref(1);
341
389
  const limit = 10;
390
+ const serverPages = ref(1);
391
+ const serverPageRange = ref("");
342
392
  const loading = ref(false);
343
393
  const loadSequence = ref(0);
344
394
  const exportDialog = ref(false);
@@ -490,22 +540,26 @@ const logHeaders = [
490
540
  { title: "", value: "action-table", sortable: false },
491
541
  ];
492
542
 
493
- const pages = computed(() => Math.max(1, Math.ceil(filteredRows.value.length / limit)));
543
+ const pages = computed(() => Math.max(1, serverPages.value));
494
544
 
495
545
  const paginatedRows = computed(() => {
496
- const currentPage = Math.min(page.value, pages.value);
497
- const start = (currentPage - 1) * limit;
498
- return filteredRows.value.slice(start, start + limit);
546
+ return filteredRows.value;
499
547
  });
500
548
 
501
549
  const pageRange = computed(() => {
502
- if (!filteredRows.value.length) return "0-0 of 0";
503
- const currentPage = Math.min(page.value, pages.value);
504
- const start = (currentPage - 1) * limit + 1;
505
- const end = Math.min(currentPage * limit, filteredRows.value.length);
506
- return `${start}-${end} of ${filteredRows.value.length}`;
550
+ return serverPageRange.value || (filteredRows.value.length ? `1-${filteredRows.value.length}` : "0-0 of 0");
507
551
  });
508
552
 
553
+ function goToPage(nextPage: number) {
554
+ page.value = nextPage;
555
+ loadDashboard();
556
+ }
557
+
558
+ function reloadDashboardFromFirstPage() {
559
+ page.value = 1;
560
+ loadDashboard();
561
+ }
562
+
509
563
  const exportRowsData = computed(() =>
510
564
  getExportSourceRows().filter((row) => {
511
565
  const selectedUsers = exportForm.users.filter((user) => user !== "all");
@@ -525,10 +579,6 @@ watch(
525
579
  { immediate: true },
526
580
  );
527
581
 
528
- watch([search, status, accessMethod, activeTab], () => {
529
- page.value = 1;
530
- });
531
-
532
582
  watch(pages, () => {
533
583
  if (page.value > pages.value) page.value = pages.value;
534
584
  });
@@ -559,26 +609,47 @@ async function loadDashboard() {
559
609
  resetDashboardData();
560
610
  try {
561
611
  const isVisitorTab = activeTab.value === "visitor";
562
- const [identityResponse, logResponse, hidAccessLogs, configurationResponse, roleResponse, visitorResponse, readerUserResponse] = await Promise.all([
612
+ const [identityResponse, logResponse, hidAccessLogResponse, visitorResponse, readerUserResponse] = await Promise.all([
563
613
  loadDashboardSource(
564
614
  getIdentities(selectedReaderId.value, {
565
- page: 1,
566
- limit: 500,
615
+ page: page.value,
616
+ limit: 100,
567
617
  }),
568
618
  null,
569
619
  "identities",
570
620
  ),
571
621
  loadDashboardSource(
572
622
  getLogs(selectedReaderId.value, {
573
- page: 1,
574
- limit: 500,
623
+ page: page.value,
624
+ limit,
575
625
  }),
576
626
  null,
577
627
  "persisted access logs",
578
628
  ),
579
- loadDashboardSource(loadLiveAccessLogs(selectedReaderId.value), [], "live access logs"),
580
- loadDashboardSource(loadReaderConfiguration(selectedReaderId.value), {}, "reader configuration"),
581
- loadDashboardSource(loadAdministratorRoles(selectedReaderId.value), null, "administrator roles"),
629
+ loadDashboardSource(
630
+ getReaderAccessLogs(selectedReaderId.value, {
631
+ page: page.value,
632
+ limit,
633
+ search: search.value.trim(),
634
+ status: status.value === "Authorized"
635
+ ? "authorized"
636
+ : status.value === "Not Authorized"
637
+ ? "not_authorized"
638
+ : status.value === "Unknown" ? "unknown" : "",
639
+ method: accessMethod.value === "Facial"
640
+ ? "facial"
641
+ : accessMethod.value === "QR Code"
642
+ ? "qr_code"
643
+ : accessMethod.value === "ID and Password"
644
+ ? "id_password"
645
+ : accessMethod.value === "PIN"
646
+ ? "pin"
647
+ : accessMethod.value === "Card" ? "card" : "",
648
+ tab: activeTab.value,
649
+ }),
650
+ { items: [], pages: 1, pageRange: "0-0 of 0" },
651
+ "live access logs",
652
+ ),
582
653
  isVisitorTab && props.org
583
654
  ? loadDashboardSource(
584
655
  getVisitors({
@@ -592,25 +663,47 @@ async function loadDashboard() {
592
663
  "visitor records",
593
664
  )
594
665
  : Promise.resolve(null),
595
- loadDashboardSource(loadReaderUsers(selectedReaderId.value), [], "reader users"),
666
+ loadDashboardSource(
667
+ getReaderUsers(selectedReaderId.value, { page: page.value, limit: 100 }),
668
+ { items: [] },
669
+ "reader users",
670
+ ),
596
671
  ]);
597
672
 
598
673
  if (sequence !== loadSequence.value) return;
599
674
 
600
675
  const loadedIdentities = identityResponse?.items ?? identityResponse?.data?.items ?? identityResponse?.data?.identities ?? [];
601
- const mergedIdentities = mergeReaderUsersWithIdentities(readerUserResponse, loadedIdentities);
676
+ const liveItems = hidAccessLogResponse?.items ?? hidAccessLogResponse?.data?.items ?? [];
677
+ const readerUsers = readerUserResponse?.items ?? readerUserResponse?.data?.items ?? [];
678
+ const embeddedIdentities = liveItems
679
+ .map((item: Record<string, unknown>) => item.identity)
680
+ .filter(isUnknownRecord);
681
+ const mergedIdentities = mergeReaderUsersWithIdentities(
682
+ readerUsers,
683
+ [...loadedIdentities, ...embeddedIdentities],
684
+ );
602
685
  const loadedVisitors = visitorResponse?.items ?? visitorResponse?.data?.items ?? visitorResponse?.data?.visitors ?? [];
603
686
  visitorRecords.value = Object.fromEntries(
604
- loadedVisitors.map((visitor: Record<string, any>) => [String(visitor._id), visitor]),
687
+ loadedVisitors.map((visitor: HidAccessRecord) => [String(visitor._id), visitor]),
688
+ );
689
+ administratorUserIds.value = new Set(
690
+ [...readerUsers, ...liveItems]
691
+ .filter((item: Record<string, unknown>) => item.isAdministrator === true)
692
+ .map((item: Record<string, unknown>) => toHidNumericId(item.hidUserId ?? item.user_id))
693
+ .filter((userId: number | undefined): userId is number => Boolean(userId)),
605
694
  );
606
- administratorUserIds.value = getAdministratorRoleUserIds(roleResponse);
607
695
  allIdentities.value = mergedIdentities;
608
696
  identities.value = mergedIdentities.filter(
609
697
  (identity: Record<string, unknown>) => classifyIdentity(identity) === activeTab.value,
610
698
  );
611
- logs.value = logResponse?.items ?? logResponse?.data?.items ?? logResponse?.data?.logs ?? [];
612
- liveAccessLogs.value = hidAccessLogs;
613
- readerConfiguration.value = normalizeReaderConfiguration(configurationResponse);
699
+ logs.value = liveItems.length
700
+ ? []
701
+ : logResponse?.items ?? logResponse?.data?.items ?? logResponse?.data?.logs ?? [];
702
+ liveAccessLogs.value = liveItems;
703
+ serverPages.value = Number(hidAccessLogResponse?.pages ?? hidAccessLogResponse?.data?.pages ?? 1);
704
+ serverPageRange.value = String(
705
+ hidAccessLogResponse?.pageRange ?? hidAccessLogResponse?.data?.pageRange ?? "",
706
+ );
614
707
  await loadUserImages(identities.value);
615
708
  } finally {
616
709
  if (sequence === loadSequence.value) {
@@ -628,7 +721,7 @@ async function loadDashboardSource<T>(request: Promise<T>, fallback: T, label: s
628
721
  }
629
722
  }
630
723
 
631
- async function loadUserImages(items: Record<string, any>[]) {
724
+ async function loadUserImages(items: HidAccessRecord[]) {
632
725
  if (!selectedReaderId.value) return;
633
726
 
634
727
  await Promise.all(items.map(async (identity) => {
@@ -648,7 +741,7 @@ async function loadUserImages(items: Record<string, any>[]) {
648
741
  }));
649
742
  }
650
743
 
651
- function hasHidImageHint(identity: Record<string, any>) {
744
+ function hasHidImageHint(identity: HidAccessRecord) {
652
745
  return Boolean(
653
746
  identity?.metadata?.imageTimestamp ||
654
747
  identity?.metadata?.facialData ||
@@ -660,56 +753,6 @@ function hasHidImageHint(identity: Record<string, any>) {
660
753
  );
661
754
  }
662
755
 
663
- async function loadLiveAccessLogs(readerId: string) {
664
- const allLogs: Record<string, any>[] = [];
665
- const limit = 500;
666
- const maxPages = 20;
667
-
668
- for (let pageIndex = 0; pageIndex < maxPages; pageIndex += 1) {
669
- try {
670
- const response = await runObjectOperation(readerId, {
671
- operation: "load",
672
- object: "access_logs",
673
- where: {
674
- access_logs: {},
675
- },
676
- limit,
677
- offset: pageIndex * limit,
678
- });
679
-
680
- const pageLogs = normalizeHidAccessLogs(response);
681
- allLogs.push(...pageLogs);
682
-
683
- if (pageLogs.length < limit) break;
684
- } catch (error) {
685
- console.warn("Unable to load HID live access logs", error);
686
- break;
687
- }
688
- }
689
-
690
- return dedupeAccessLogs(allLogs).sort((a, b) => {
691
- const aTime = parseDate(getAccessLogTime(a, {}))?.getTime() || 0;
692
- const bTime = parseDate(getAccessLogTime(b, {}))?.getTime() || 0;
693
- return bTime - aTime;
694
- });
695
- }
696
-
697
- async function loadReaderConfiguration(readerId: string) {
698
- try {
699
- return await getReaderConfiguration(readerId, {
700
- access_logs: [],
701
- event_types: [],
702
- log_types: [],
703
- identification_rules: [],
704
- portals: [],
705
- users: [],
706
- });
707
- } catch (error) {
708
- console.warn("Unable to load HID configuration", error);
709
- return {};
710
- }
711
- }
712
-
713
756
  async function onTabChange(tab: AccessTab) {
714
757
  if (tab) {
715
758
  activeTab.value = tab;
@@ -720,48 +763,8 @@ async function onTabChange(tab: AccessTab) {
720
763
  loadDashboard();
721
764
  }
722
765
 
723
- async function loadReaderUsers(readerId: string) {
724
- try {
725
- const response = await runObjectOperation(readerId, {
726
- operation: "load",
727
- object: "users",
728
- limit: 500,
729
- offset: 0,
730
- });
731
- return normalizeHidUsers(response);
732
- } catch (error) {
733
- console.warn("Unable to load HID users for access log images", error);
734
- return [];
735
- }
736
- }
737
-
738
- function normalizeHidUsers(response: Record<string, any>) {
739
- const items =
740
- response?.data?.users ||
741
- response?.data?.data?.users ||
742
- response?.users ||
743
- [];
744
-
745
- return Array.isArray(items)
746
- ? items.map((user) => ({
747
- hidUserId: String(user.id || ""),
748
- rawHidUserId: user.id,
749
- registration: user.registration,
750
- cardNo: user.card_value || user.cardNo || "",
751
- name: user.name,
752
- hidUserTypeId: user.user_type_id,
753
- metadata: {
754
- name: user.name,
755
- hidUserTypeId: user.user_type_id,
756
- imageTimestamp: user.image_timestamp ? String(user.image_timestamp) : "",
757
- hidReaderSource: true,
758
- },
759
- }))
760
- : [];
761
- }
762
-
763
- function mergeReaderUsersWithIdentities(readerUsers: Record<string, any>[], identities: Record<string, any>[]) {
764
- const identityById = new Map<string, Record<string, any>>();
766
+ function mergeReaderUsersWithIdentities(readerUsers: HidAccessRecord[], identities: HidAccessRecord[]) {
767
+ const identityById = new Map<string, HidAccessRecord>();
765
768
  identities.forEach((identity) => {
766
769
  const id = toHidNumericId(identity.hidUserId);
767
770
  if (id) identityById.set(String(id), identity);
@@ -799,8 +802,9 @@ function resetDashboardData() {
799
802
  visitorRecords.value = {};
800
803
  logs.value = [];
801
804
  liveAccessLogs.value = [];
802
- readerConfiguration.value = {};
803
805
  administratorUserIds.value = new Set();
806
+ serverPages.value = 1;
807
+ serverPageRange.value = "";
804
808
  }
805
809
 
806
810
  function isVisibleForActiveTab(row: AccessRow) {
@@ -823,35 +827,6 @@ function classifyIdentity(identity?: Record<string, unknown>, row?: AccessRow):
823
827
  return "resident";
824
828
  }
825
829
 
826
- function loadAdministratorRoles(readerId: string) {
827
- return runObjectOperation(readerId, {
828
- operation: "load",
829
- object: "user_roles",
830
- where: {
831
- user_roles: {
832
- role: 1,
833
- },
834
- },
835
- limit: 500,
836
- offset: 0,
837
- });
838
- }
839
-
840
- function getAdministratorRoleUserIds(response: Record<string, any> | null) {
841
- const data = response?.data || response || {};
842
- const roles =
843
- data?.user_roles ||
844
- data?.data?.user_roles ||
845
- data?.result?.user_roles ||
846
- [];
847
-
848
- return new Set(
849
- (Array.isArray(roles) ? roles : [])
850
- .map((role) => toHidNumericId(role.user_id))
851
- .filter((userId): userId is number => Boolean(userId)),
852
- );
853
- }
854
-
855
830
  function toHidNumericId(value: unknown) {
856
831
  const raw = String(value ?? "").trim();
857
832
  if (!raw) return undefined;
@@ -862,7 +837,7 @@ function toHidNumericId(value: unknown) {
862
837
  return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined;
863
838
  }
864
839
 
865
- function getIdentityKey(identity: Record<string, any>) {
840
+ function getIdentityKey(identity: HidAccessRecord) {
866
841
  return [
867
842
  identity.hidUserId,
868
843
  identity.registration,
@@ -875,7 +850,7 @@ function findIdentityByKey(identityKey: string) {
875
850
  return allIdentities.value.find((identity) => getIdentityKey(identity) === identityKey);
876
851
  }
877
852
 
878
- function getLogIdentityKey(log: Record<string, any>) {
853
+ function getLogIdentityKey(log: HidAccessRecord) {
879
854
  const identity = log.payload?.identity || {};
880
855
  const lookup = log.payload?.identityLookup || {};
881
856
  const rawLog = log.payload?.rawAccessLog || log;
@@ -886,20 +861,20 @@ function getLogIdentityKey(log: Record<string, any>) {
886
861
  ].filter(Boolean).join("|");
887
862
  }
888
863
 
889
- function getName(identity: Record<string, any>) {
864
+ function getName(identity: HidAccessRecord) {
890
865
  return getVisitorRecord(identity)?.name || identity.metadata?.name || identity.name || "N/A";
891
866
  }
892
867
 
893
- function getFacialData(identity: Record<string, any>) {
868
+ function getFacialData(identity: HidAccessRecord) {
894
869
  return identity.metadata?.facialData || identity.metadata?.imageTimestamp || (identity.metadata?.photo ? identity.hidUserId : "N/A");
895
870
  }
896
871
 
897
- function getUserImageSrc(identity: Record<string, any>) {
872
+ function getUserImageSrc(identity: HidAccessRecord) {
898
873
  const hidUserId = toHidNumericId(identity?.hidUserId);
899
874
  return identity?.metadata?.photo || (hidUserId ? userImages.value[String(hidUserId)] : "") || "";
900
875
  }
901
876
 
902
- function getUnit(identity: Record<string, any>) {
877
+ function getUnit(identity: HidAccessRecord) {
903
878
  const visitor = getVisitorRecord(identity);
904
879
  if (visitor) {
905
880
  return visitor.unitName || [visitor.block, visitor.level, visitor.unit].filter(Boolean).join("/") || "N/A";
@@ -908,17 +883,22 @@ function getUnit(identity: Record<string, any>) {
908
883
  return identity.metadata?.unitLabel || [identity.metadata?.block, identity.metadata?.level, identity.metadata?.unit].filter(Boolean).join("/") || "N/A";
909
884
  }
910
885
 
911
- function getVisitorRecord(identity: Record<string, any>) {
886
+ function getVisitorRecord(identity: HidAccessRecord) {
912
887
  const visitorId = identity?.visitor;
913
888
  return visitorId ? visitorRecords.value[String(visitorId)] : undefined;
914
889
  }
915
890
 
916
- function getAccessMethod(identity: Record<string, any>, log?: Record<string, any>) {
891
+ function getAccessMethod(identity: HidAccessRecord, log?: HidAccessRecord) {
917
892
  const payload = log?.payload?.rawAccessLog || log?.payload || log || {};
918
- const configuredLogType = getConfigurationLabel("log_types", payload.log_type_id || payload.logTypeId);
919
- if (configuredLogType) return configuredLogType;
920
- const configuredRule = getConfigurationLabel("identification_rules", payload.identification_rule_id || payload.identificationRuleId);
921
- if (configuredRule) return configuredRule;
893
+ const normalizedMethodLabels: Record<string, string> = {
894
+ facial: "Facial",
895
+ qr_code: "QR Code",
896
+ id_password: "ID and Password",
897
+ pin: "PIN",
898
+ card: "Card",
899
+ };
900
+ const normalizedMethod = String(payload.normalizedMethod || "");
901
+ if (normalizedMethodLabels[normalizedMethod]) return normalizedMethodLabels[normalizedMethod];
922
902
  const rawIdentification = String(payload.identification || payload.identification_type || payload.identificationType || "").toLowerCase();
923
903
  if (rawIdentification.includes("facial") || rawIdentification.includes("face")) return "Facial";
924
904
  if (payload.qrcode_value || payload.qrCode || payload.qrcode) return "QR Code";
@@ -1122,60 +1102,7 @@ function sortAccessRowsByDateDesc(a: AccessRow, b: AccessRow) {
1122
1102
  return bTime - aTime;
1123
1103
  }
1124
1104
 
1125
- function dedupeAccessLogs(items: Record<string, any>[]) {
1126
- const seen = new Set<string>();
1127
- return items.filter((item) => {
1128
- const key = [
1129
- item.id,
1130
- item.time,
1131
- item.user_id ?? item.userId ?? item.hidUserId,
1132
- item.card_value ?? item.cardNo,
1133
- ].join("|");
1134
-
1135
- if (seen.has(key)) return false;
1136
- seen.add(key);
1137
- return true;
1138
- });
1139
- }
1140
-
1141
- function normalizeHidAccessLogs(response: Record<string, any>) {
1142
- const data = response?.data || response || {};
1143
- const accessLogs =
1144
- data.access_logs ||
1145
- data.data?.access_logs ||
1146
- data.accessLogs ||
1147
- data.data?.accessLogs ||
1148
- data.result?.access_logs ||
1149
- data.result?.data?.access_logs;
1150
-
1151
- return Array.isArray(accessLogs) ? accessLogs : [];
1152
- }
1153
-
1154
- function normalizeReaderConfiguration(response: Record<string, any>) {
1155
- const data = response?.data || response || {};
1156
- return data?.data || data?.result || data;
1157
- }
1158
-
1159
- function getConfigurationLabel(section: string, id: unknown) {
1160
- if (id === undefined || id === null || id === "" || Number(id) === -1) return "";
1161
- const entries = readerConfiguration.value?.[section];
1162
- if (!entries) return "";
1163
-
1164
- const items = Array.isArray(entries)
1165
- ? entries
1166
- : typeof entries === "object"
1167
- ? Object.values(entries)
1168
- : [];
1169
-
1170
- const match = items.find((item: any) => {
1171
- if (!item || typeof item !== "object") return false;
1172
- return String(item.id ?? item.value ?? item.key ?? item.code) === String(id);
1173
- }) as Record<string, any> | undefined;
1174
-
1175
- return match?.name || match?.label || match?.description || match?.title || "";
1176
- }
1177
-
1178
- function getRawAccessLogs(event: Record<string, any>) {
1105
+ function getRawAccessLogs(event: HidAccessRecord): HidAccessRecord[] {
1179
1106
  const payload = event.payload || {};
1180
1107
  const result = payload.result || payload.data || {};
1181
1108
  const accessLogs =
@@ -1199,7 +1126,7 @@ function getRawAccessLogs(event: Record<string, any>) {
1199
1126
  : [];
1200
1127
  }
1201
1128
 
1202
- function mapAccessLogToRow(rawLog: Record<string, any>, event: Record<string, any>, index: string): AccessRow {
1129
+ function mapAccessLogToRow(rawLog: HidAccessRecord, event: HidAccessRecord, index: string): AccessRow {
1203
1130
  const identity = findIdentityForAccessLog(rawLog, event);
1204
1131
  const eventIdentity = event.payload?.identity || event.payload?.identityLookup || {};
1205
1132
  const rawAccessTime = getAccessLogTime(rawLog, event);
@@ -1225,8 +1152,8 @@ function mapAccessLogToRow(rawLog: Record<string, any>, event: Record<string, an
1225
1152
  }
1226
1153
 
1227
1154
  function getAuthorizationStatus(
1228
- rawLog: Record<string, any>,
1229
- event: Record<string, any>,
1155
+ rawLog: HidAccessRecord,
1156
+ event: HidAccessRecord,
1230
1157
  ): Pick<AccessRow, "status" | "authorizationReason"> {
1231
1158
  const authorization = event.payload?.authorization || rawLog.authorization;
1232
1159
  if (typeof authorization?.granted === "boolean") {
@@ -1248,9 +1175,7 @@ function getAuthorizationStatus(
1248
1175
  return { status: "Not Authorized", authorizationReason: "Access denied by HID authorization." };
1249
1176
  }
1250
1177
 
1251
- const eventLabel = String(
1252
- getConfigurationLabel("event_types", eventCode) || rawLog.event_name || rawLog.eventName || "",
1253
- ).toLowerCase();
1178
+ const eventLabel = String(rawLog.event_name || rawLog.eventName || "").toLowerCase();
1254
1179
  if (/not authorized|unauthori[sz]ed|access denied|denied|rejected/.test(eventLabel)) {
1255
1180
  return { status: "Not Authorized", authorizationReason: eventLabel };
1256
1181
  }
@@ -1264,7 +1189,10 @@ function getAuthorizationStatus(
1264
1189
  };
1265
1190
  }
1266
1191
 
1267
- function findIdentityForAccessLog(rawLog: Record<string, any>, event: Record<string, any>) {
1192
+ function findIdentityForAccessLog(rawLog: HidAccessRecord, event: HidAccessRecord) {
1193
+ if (rawLog.identity && typeof rawLog.identity === "object") {
1194
+ return rawLog.identity;
1195
+ }
1268
1196
  const eventIdentityId = event.payload?.identity?._id;
1269
1197
  if (eventIdentityId) {
1270
1198
  const byId = allIdentities.value.find((identity) => String(identity._id) === String(eventIdentityId));
@@ -1291,7 +1219,7 @@ function findIdentityForAccessLog(rawLog: Record<string, any>, event: Record<str
1291
1219
  });
1292
1220
  }
1293
1221
 
1294
- function getLatestAccessLogForIdentity(identity: Record<string, any>) {
1222
+ function getLatestAccessLogForIdentity(identity: HidAccessRecord) {
1295
1223
  const accessLogs = [
1296
1224
  ...liveAccessLogs.value,
1297
1225
  ...logs.value.flatMap((event) => getRawAccessLogs(event)),
@@ -1306,10 +1234,12 @@ function getLatestAccessLogForIdentity(identity: Record<string, any>) {
1306
1234
  })[0];
1307
1235
  }
1308
1236
 
1237
+ function isUnknownRecord(value: unknown): value is Record<string, unknown> {
1238
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1239
+ }
1240
+
1309
1241
  function toUnknownRecord(value: unknown): Record<string, unknown> {
1310
- return typeof value === "object" && value !== null && !Array.isArray(value)
1311
- ? value as Record<string, unknown>
1312
- : {};
1242
+ return isUnknownRecord(value) ? value : {};
1313
1243
  }
1314
1244
 
1315
1245
  function accessLogMatchesIdentity(log: unknown, identity: unknown) {
@@ -1341,7 +1271,7 @@ function accessLogMatchesIdentity(log: unknown, identity: unknown) {
1341
1271
  );
1342
1272
  }
1343
1273
 
1344
- function getAccessLogIdentityKey(rawLog: Record<string, any>) {
1274
+ function getAccessLogIdentityKey(rawLog: HidAccessRecord) {
1345
1275
  return [
1346
1276
  rawLog.user_id ?? rawLog.userId ?? rawLog.hidUserId,
1347
1277
  rawLog.registration,
@@ -1349,11 +1279,11 @@ function getAccessLogIdentityKey(rawLog: Record<string, any>) {
1349
1279
  ].filter(Boolean).join("|");
1350
1280
  }
1351
1281
 
1352
- function getAccessLogTime(rawLog: Record<string, any>, event: Record<string, any>) {
1282
+ function getAccessLogTime(rawLog: HidAccessRecord, event: HidAccessRecord) {
1353
1283
  return rawLog.time || rawLog.createdAt || rawLog.accessedAt || event.createdAt;
1354
1284
  }
1355
1285
 
1356
- function getRawLogName(rawLog: Record<string, any>, event: Record<string, any>) {
1286
+ function getRawLogName(rawLog: HidAccessRecord, event: HidAccessRecord) {
1357
1287
  return rawLog.name || event.payload?.identity?.name || event.payload?.name || "Unmapped";
1358
1288
  }
1359
1289
 
@@ -1366,12 +1296,12 @@ function getExportSourceRows() {
1366
1296
  return exportScope.value === "history" ? selectedHistoryRows.value : filteredRows.value;
1367
1297
  }
1368
1298
 
1369
- function getLogAccessDateValue(log: Record<string, any>) {
1299
+ function getLogAccessDateValue(log: HidAccessRecord) {
1370
1300
  const payload = log.payload || {};
1371
1301
  return log.createdAt || payload.createdAt || payload.accessedAt || payload.time || payload.eventTime;
1372
1302
  }
1373
1303
 
1374
- function getLogReaderLocation(log: Record<string, any>) {
1304
+ function getLogReaderLocation(log: HidAccessRecord) {
1375
1305
  return log.payload?.reader?.location || log.payload?.readerLocation || selectedReader.value?.location || "N/A";
1376
1306
  }
1377
1307
 
@@ -1392,7 +1322,7 @@ async function exportRowsAsPdf() {
1392
1322
  pdf.save(`hid-access-log-${activeTab.value}.pdf`);
1393
1323
  }
1394
1324
 
1395
- function drawAccessLogPdf(pdf: any, rows: PdfAccessRow[]) {
1325
+ function drawAccessLogPdf(pdf: JsPdf, rows: PdfAccessRow[]) {
1396
1326
  const margin = 12;
1397
1327
  const pageWidth = pdf.internal.pageSize.getWidth();
1398
1328
  const pageHeight = pdf.internal.pageSize.getHeight();