@7365admin1/layer-common 4.119.0 → 4.120.0
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 +19 -4
- package/components/AccessCardDetailsDialog.vue +3 -2
- package/components/AddPassKeyToVisitor.vue +5 -0
- package/components/BuildingUnitFormEdit.vue +3 -1
- package/components/DocumentManagement.vue +56 -3
- package/components/FeedbackHandlingSettings.vue +385 -0
- package/components/HandoverChecklistRecords.vue +223 -0
- package/components/HandoverChecklistSetup.vue +224 -0
- package/components/IncidentReportEmailsSettings.vue +88 -0
- package/components/KeyPressFilter.vue +43 -0
- package/components/KeyPressName.vue +14 -0
- package/components/KeyPressSelect.vue +31 -0
- package/components/KeySettingsPanel.vue +156 -0
- package/components/ListCsvExport.vue +71 -0
- package/components/MaStaffRegistrationSettings.vue +61 -0
- package/components/MemberInformation.vue +2 -2
- package/components/PassInformation.vue +5 -0
- package/components/RolePermissionFormCreate.vue +33 -0
- package/components/SearchVehicleNumberUser.vue +3 -0
- package/components/SiteDataRetention.vue +286 -0
- package/components/SiteSettings.vue +48 -0
- package/components/SiteSettingsVisitorRegistration.vue +118 -0
- package/components/VehicleForm.vue +2 -2
- package/components/VisitorForm.vue +41 -6
- package/components/VisitorManagement.vue +3 -1
- package/components/VisitorSearchResultSummary.vue +2 -1
- package/composables/useDataRetention.ts +43 -0
- package/composables/useDocument.ts +13 -0
- package/composables/useFeedback.ts +12 -0
- package/composables/useHandoverChecklist.ts +111 -0
- package/composables/useKeyPresses.ts +57 -0
- package/composables/usePassKey.ts +4 -0
- package/composables/useSiteFeatureSettings.ts +37 -0
- package/composables/useVisitor.ts +22 -0
- package/package.json +2 -2
- package/types/key-log.d.ts +2 -0
- package/types/passKey.d.ts +2 -0
- package/utils/feedback-handling-settings.ts +139 -0
- package/utils/inventory-presets.ts +64 -0
- package/utils/key-presses.ts +55 -0
- package/utils/list-export.ts +39 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key presses (cabinets) and the Passes & keys site switches (TLR B8 / D2).
|
|
3
|
+
* Stored on the site as `metadata.keySettings`; read with the same defaults
|
|
4
|
+
* as core's `getKeySettings`, so a site that never saved anything reads as
|
|
5
|
+
* today: no presses, no daily list, check-out never blocked by the server.
|
|
6
|
+
*/
|
|
7
|
+
export type TKeyPress = { id: string; name: string };
|
|
8
|
+
|
|
9
|
+
export type TKeySettings = {
|
|
10
|
+
cabinets: TKeyPress[];
|
|
11
|
+
dailyUnreturnedAlert: boolean;
|
|
12
|
+
alertTime: string;
|
|
13
|
+
blockCheckoutWithKeys: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function readKeySettings(site: any): TKeySettings {
|
|
17
|
+
const k = site?.metadata?.keySettings ?? {};
|
|
18
|
+
return {
|
|
19
|
+
cabinets: Array.isArray(k.cabinets)
|
|
20
|
+
? k.cabinets.filter((c: any) => c && typeof c.id === "string" && typeof c.name === "string")
|
|
21
|
+
: [],
|
|
22
|
+
dailyUnreturnedAlert: k.dailyUnreturnedAlert === true,
|
|
23
|
+
alertTime: typeof k.alertTime === "string" && /^([01]\d|2[0-3]):[0-5]\d$/.test(k.alertTime) ? k.alertTime : "18:00",
|
|
24
|
+
blockCheckoutWithKeys: k.blockCheckoutWithKeys === true,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The press's name, or "" when the key has none (or one since removed). */
|
|
29
|
+
export function keyPressName(cabinets: TKeyPress[], id?: string | null): string {
|
|
30
|
+
if (!id) return "";
|
|
31
|
+
return cabinets.find((c) => c.id === id)?.name ?? "";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The list as saved: names trimmed, empty rows dropped, and an id for each new
|
|
36
|
+
* row made from its name (lowercase letters, digits and dashes, unique). An
|
|
37
|
+
* existing row keeps its id, so renaming a press keeps every key in it.
|
|
38
|
+
*/
|
|
39
|
+
export function cleanKeyPresses(rows: Array<{ id?: string; name?: string }>): TKeyPress[] {
|
|
40
|
+
const out: TKeyPress[] = [];
|
|
41
|
+
const taken = new Set(rows.map((r) => r.id).filter(Boolean) as string[]);
|
|
42
|
+
for (const row of rows) {
|
|
43
|
+
const name = String(row.name ?? "").trim().slice(0, 60);
|
|
44
|
+
if (!name) continue;
|
|
45
|
+
let id = row.id;
|
|
46
|
+
if (!id) {
|
|
47
|
+
const base = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 34) || "press";
|
|
48
|
+
id = base;
|
|
49
|
+
for (let n = 2; taken.has(id); n++) id = `${base}-${n}`;
|
|
50
|
+
taken.add(id);
|
|
51
|
+
}
|
|
52
|
+
out.push({ id, name });
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSV download of a list screen (TLR B6): the rows the list itself can read,
|
|
3
|
+
* through the same list API and filters, paged through to the end. Browser-safe.
|
|
4
|
+
*/
|
|
5
|
+
import { toCsv } from "./attendance-proxy.ts";
|
|
6
|
+
|
|
7
|
+
export type TExportColumn = { title: string; value: (row: any) => unknown };
|
|
8
|
+
|
|
9
|
+
/** Largest page the list APIs accept (core feedback / work-order: max 100). */
|
|
10
|
+
export const EXPORT_PAGE_SIZE = 100;
|
|
11
|
+
/** ponytail: hard cap, so one click never pulls an estate's whole history; raise or add a server export if hit. */
|
|
12
|
+
export const EXPORT_MAX_ROWS = 5000;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Every row from `fetchPage(1..n)`, stopping at the last page, an empty page,
|
|
16
|
+
* or `maxRows`. `fetchPage` returns the list API's `{ items, pages }`.
|
|
17
|
+
*/
|
|
18
|
+
export async function collectAllPages(
|
|
19
|
+
fetchPage: (page: number, limit: number) => Promise<{ items?: any[]; pages?: number } | null | undefined>,
|
|
20
|
+
maxRows = EXPORT_MAX_ROWS,
|
|
21
|
+
limit = EXPORT_PAGE_SIZE,
|
|
22
|
+
): Promise<{ rows: any[]; truncated: boolean }> {
|
|
23
|
+
const rows: any[] = [];
|
|
24
|
+
for (let page = 1; rows.length < maxRows; page++) {
|
|
25
|
+
const res = await fetchPage(page, limit);
|
|
26
|
+
const items = Array.isArray(res?.items) ? res!.items : [];
|
|
27
|
+
rows.push(...items);
|
|
28
|
+
const last = Number(res?.pages) || 0;
|
|
29
|
+
if (!items.length || page >= last) return { rows: rows.slice(0, maxRows), truncated: rows.length > maxRows };
|
|
30
|
+
}
|
|
31
|
+
return { rows: rows.slice(0, maxRows), truncated: true };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function listCsv(columns: TExportColumn[], rows: any[]): string {
|
|
35
|
+
return toCsv(
|
|
36
|
+
columns.map((c) => c.title),
|
|
37
|
+
rows.map((row) => columns.map((c) => c.value(row))),
|
|
38
|
+
);
|
|
39
|
+
}
|