@7365admin1/layer-common 4.97.0 → 4.97.1-staging.501
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/CHANGELOG.md +4 -4
- package/assets/css/primitives.css +57 -0
- package/assets/css/screens.css +8 -4
- package/components/AccessCardDetailsDialog.vue +59 -6
- package/components/AccessCardPreviewDialog.vue +371 -53
- package/components/AppSelect.vue +143 -4
- package/components/BuildingUnitFormEdit.vue +6 -0
- package/components/BuildingUnitManagement.vue +298 -0
- package/components/Dialog/UpdateMoreAction.vue +11 -1
- package/components/DocumentForm.vue +407 -112
- package/components/DocumentManagement.vue +213 -12
- package/components/Facility/BookingSetup.vue +63 -0
- package/components/HidAccessLogDashboard.vue +74 -17
- package/components/HidAccessPermissions.vue +532 -0
- package/components/HidIntercomManagement.vue +183 -14
- package/components/HidProfileQrCode.vue +332 -0
- package/components/HidQrCodeConfiguration.vue +17 -195
- package/components/HidReaderManagement.vue +398 -0
- package/components/HidReaderUserRoster.vue +44 -3
- package/components/HidUserEnrollment.vue +2242 -279
- package/components/InvitationClientForm.vue +19 -1
- package/components/Nfc/NFCPatrolRouteForm.vue +109 -58
- package/components/Nfc/NFCPatrolRouteMain.vue +3 -18
- package/components/Nfc/PatrolReport/PatrolActivityTable.vue +0 -8
- package/components/Nfc/PatrolReport/PatrolRouteSummary.vue +1 -1
- package/components/ServiceProviderMain.vue +48 -0
- package/components/SiteProviderChange.vue +371 -0
- package/components/TableMain.vue +22 -7
- package/components/VisitorForm.vue +12 -0
- package/components/VisitorManagement.vue +267 -5
- package/composables/useAccessManagement.ts +17 -1
- package/composables/useCustomerSite.ts +29 -0
- package/composables/useDocument.ts +7 -0
- package/composables/useFacility.ts +11 -0
- package/composables/useHidAmico.ts +165 -0
- package/composables/useHidNavigation.ts +25 -1
- package/composables/useHidReaderSelection.ts +50 -0
- package/composables/useMember.ts +12 -0
- package/composables/useNFCPatrolReport.ts +36 -32
- package/composables/useNFCPatrolReportFilters.ts +21 -3
- package/composables/useNFCPatrolRoute.ts +10 -3
- package/composables/usePeople.ts +19 -0
- package/composables/useServiceProvider.ts +45 -2
- package/composables/useSiteCategory.ts +45 -0
- package/package.json +1 -1
- package/pages/[org]/[site]/access-mgmt/administrator/index.vue +1 -1
- package/pages/[org]/[site]/access-mgmt/hid-cards/index.vue +1 -1
- package/pages/[org]/[site]/access-mgmt/hid-qr-code/index.vue +23 -0
- package/pages/[org]/[site]/access-mgmt/hid-readers/index.vue +1 -1
- package/types/document.d.ts +14 -0
- package/types/facility.d.ts +4 -0
- package/types/member.d.ts +4 -0
- package/types/nfc-patrol-report.ts +0 -2
- package/types/people.d.ts +28 -1
- package/types/service-provider.d.ts +5 -0
- package/types/site.d.ts +7 -1
- package/utils/hid-enrolment-subject.ts +366 -0
- package/utils/hid-permission-assignments.ts +259 -0
- package/utils/hid-reader-selection.ts +52 -0
- package/utils/nfc-patrol-time.ts +99 -0
- package/utils/occupancy-role.ts +109 -0
- package/utils/service-type.ts +30 -0
package/CHANGELOG.md
CHANGED
|
@@ -2082,11 +2082,11 @@
|
|
|
2082
2082
|
`utils/console-tier.ts` + `composables/useConsoleTier.ts` mirror the server's
|
|
2083
2083
|
own rule from two endpoints the console already calls, unprojected:
|
|
2084
2084
|
|
|
2085
|
-
|
|
2086
|
-
|
|
2085
|
+
GET /api/members/user/:user/app/admin the Seven365 staff membership
|
|
2086
|
+
GET /api/roles/id/:role that membership's role document
|
|
2087
2087
|
|
|
2088
|
-
|
|
2089
|
-
|
|
2088
|
+
owner = member.type === "admin" && role.type === "admin" && role.default === true
|
|
2089
|
+
staff = member.type === "admin" && role.type === "admin"
|
|
2090
2090
|
|
|
2091
2091
|
`role.default` is the marker because it is the only property of a platform
|
|
2092
2092
|
staff role no API caller can set - `role.controller.ts` validates create and
|
|
@@ -775,6 +775,63 @@ select option {
|
|
|
775
775
|
box-shadow: var(--shadow-menu);
|
|
776
776
|
}
|
|
777
777
|
|
|
778
|
+
/* The filter box of a `searchable` AppSelect. Sticky rather than scrolled
|
|
779
|
+
away with the options: the list it filters is long enough to need scrolling,
|
|
780
|
+
which is the only reason the box is there. */
|
|
781
|
+
.app-select__search {
|
|
782
|
+
position: sticky;
|
|
783
|
+
top: -6px;
|
|
784
|
+
z-index: 1;
|
|
785
|
+
display: flex;
|
|
786
|
+
align-items: center;
|
|
787
|
+
gap: 6px;
|
|
788
|
+
margin: -6px -6px 4px;
|
|
789
|
+
padding: 8px 10px;
|
|
790
|
+
border-bottom: 1px solid var(--border);
|
|
791
|
+
background: var(--card);
|
|
792
|
+
color: var(--muted);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
.app-select__search-input {
|
|
796
|
+
flex: 1;
|
|
797
|
+
min-width: 0;
|
|
798
|
+
border: none;
|
|
799
|
+
outline: none;
|
|
800
|
+
background: none;
|
|
801
|
+
font-family: var(--font-sans);
|
|
802
|
+
font-size: var(--fs-cell);
|
|
803
|
+
font-weight: 500;
|
|
804
|
+
color: var(--text);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
.app-select__search-input::placeholder {
|
|
808
|
+
color: var(--muted);
|
|
809
|
+
font-weight: 500;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
.app-select__empty {
|
|
813
|
+
margin: 0;
|
|
814
|
+
padding: 10px 8px;
|
|
815
|
+
font-family: var(--font-sans);
|
|
816
|
+
font-size: var(--fs-cell);
|
|
817
|
+
color: var(--muted);
|
|
818
|
+
text-align: center;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/* The footer of a paging AppSelect. Same voice as the empty state - it is the
|
|
822
|
+
same kind of message about the list rather than an option in it - with a rule
|
|
823
|
+
above so it does not read as one more row to click. */
|
|
824
|
+
.app-select__loading {
|
|
825
|
+
margin: 6px 0 0;
|
|
826
|
+
padding: 9px 8px;
|
|
827
|
+
border-top: 1px solid var(--border);
|
|
828
|
+
font-family: var(--font-sans);
|
|
829
|
+
font-size: var(--fs-cell);
|
|
830
|
+
font-weight: 600;
|
|
831
|
+
color: var(--muted);
|
|
832
|
+
text-align: center;
|
|
833
|
+
}
|
|
834
|
+
|
|
778
835
|
.app-select__option {
|
|
779
836
|
display: flex;
|
|
780
837
|
align-items: center;
|
package/assets/css/screens.css
CHANGED
|
@@ -809,10 +809,14 @@
|
|
|
809
809
|
color: var(--muted);
|
|
810
810
|
}
|
|
811
811
|
|
|
812
|
-
/* The
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
812
|
+
/* The title-row search beside the primary button. `--search` alone is
|
|
813
|
+
`flex: 1`, written for a filter row; in the actions group that collapses it,
|
|
814
|
+
so it gets a fixed width here and never more than the row on a phone. */
|
|
815
|
+
.table-card__search.app-field--search {
|
|
816
|
+
flex: 0 0 auto;
|
|
817
|
+
width: 260px;
|
|
818
|
+
max-width: 100%;
|
|
819
|
+
min-width: 0;
|
|
816
820
|
}
|
|
817
821
|
|
|
818
822
|
.table-card__primary {
|
|
@@ -47,22 +47,30 @@
|
|
|
47
47
|
<div>
|
|
48
48
|
<div class="card-details__label">User</div>
|
|
49
49
|
<div class="card-details__value">
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
<template v-if="holderState === 'named'">
|
|
51
|
+
{{ holderName }}
|
|
52
|
+
<template v-if="details.user?.email">({{ details.user.email }})</template>
|
|
53
|
+
</template>
|
|
54
|
+
<!-- Assigned, but the server did not send the name back. Saying
|
|
55
|
+
so beats "N/A", which reads as "nobody holds this card". -->
|
|
56
|
+
<template v-else-if="holderState === 'assigned'">
|
|
57
|
+
<span class="text-medium-emphasis">Assigned — name unavailable</span>
|
|
58
|
+
</template>
|
|
59
|
+
<template v-else>Unassigned</template>
|
|
52
60
|
</div>
|
|
53
61
|
</div>
|
|
54
62
|
|
|
55
|
-
<div v-if="
|
|
63
|
+
<div v-if="holderType">
|
|
56
64
|
<div class="card-details__label">User Type</div>
|
|
57
|
-
<div class="card-details__value">{{
|
|
65
|
+
<div class="card-details__value">{{ holderType }}</div>
|
|
58
66
|
</div>
|
|
59
67
|
|
|
60
68
|
<!-- Visitor / Resident Credentials -->
|
|
61
69
|
<template v-if="details.userCred">
|
|
62
70
|
<v-divider />
|
|
63
|
-
<div class="card-details__section">
|
|
71
|
+
<!-- <div class="card-details__section">
|
|
64
72
|
{{ details.userType ?? "Visitor Information" }}
|
|
65
|
-
</div>
|
|
73
|
+
</div> -->
|
|
66
74
|
|
|
67
75
|
<div v-if="details.userCred.email">
|
|
68
76
|
<div class="card-details__label">Email</div>
|
|
@@ -216,6 +224,51 @@ const sortedHistory = computed(() =>
|
|
|
216
224
|
)
|
|
217
225
|
);
|
|
218
226
|
|
|
227
|
+
/**
|
|
228
|
+
* WHO HOLDS THIS CARD.
|
|
229
|
+
*
|
|
230
|
+
* `userCred` is written by the visitor-pass flow and carries the person's
|
|
231
|
+
* details on the card itself. `user` is the resolved account - the card only
|
|
232
|
+
* stores `userId`, so the server has to join it.
|
|
233
|
+
*
|
|
234
|
+
* `card-details` does not do that join today (the lookup is commented out in
|
|
235
|
+
* core's `getCardDetailsRepo`), so this is empty for every card assigned
|
|
236
|
+
* through Assign to Person and the field falls through to `holderState`.
|
|
237
|
+
* Nothing here needs to change when the join is restored.
|
|
238
|
+
*/
|
|
239
|
+
const holderName = computed(
|
|
240
|
+
() => details.value?.userCred?.name ?? details.value?.user?.name ?? "",
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* A card with a `userId` IS assigned, whether or not the name came back.
|
|
245
|
+
*
|
|
246
|
+
* Printing "N/A" for both cases is the actual defect here: it reads as "nobody
|
|
247
|
+
* holds this card", which is the opposite of the truth for an assigned one and
|
|
248
|
+
* could have someone hand out a card that is already in use.
|
|
249
|
+
*/
|
|
250
|
+
const holderState = computed<"named" | "assigned" | "unassigned">(() => {
|
|
251
|
+
if (holderName.value) return "named";
|
|
252
|
+
return details.value?.userId ? "assigned" : "unassigned";
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* WHICH KIND OF PERSON HOLDS THIS CARD — Visitor/Resident, Management or
|
|
257
|
+
* Service Provider, matching the groups Assign to Person offers.
|
|
258
|
+
*
|
|
259
|
+
* `holderType` is what the server should send once it records the category the
|
|
260
|
+
* card was assigned under. `userType` is NOT that: it is the card's own pool,
|
|
261
|
+
* and `getCardDetailsRepo` filters on `EAccessCardUserTypes.DEFAULT`, so every
|
|
262
|
+
* card this dialog can load has the literal value "Visitor/Resident" whoever
|
|
263
|
+
* actually holds it. Preferring `holderType` means a card given to Management
|
|
264
|
+
* stops describing itself as a resident's the day the field arrives.
|
|
265
|
+
*
|
|
266
|
+
* Falls back to `userType` so nothing disappears in the meantime.
|
|
267
|
+
*/
|
|
268
|
+
const holderType = computed(
|
|
269
|
+
() => details.value?.holderType ?? details.value?.userType ?? "",
|
|
270
|
+
);
|
|
271
|
+
|
|
219
272
|
watch(
|
|
220
273
|
() => props.modelValue,
|
|
221
274
|
async (val) => {
|