@7365admin1/layer-common 3.1.2 → 3.1.3-staging.40
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/.github/workflows/publish-staging.yml +11 -0
- package/components/AddEqupmentForm.vue +52 -1
- package/components/CameraMain.vue +17 -9
- package/components/DashboardMain.vue +231 -87
- package/components/EquipmentManagementMain.vue +56 -0
- package/components/InvitationMain.vue +4 -3
- package/components/ManageChecklistMain.vue +44 -38
- package/components/Nfc/NFCPatrolReportMain.vue +146 -38
- package/components/Nfc/PatrolReport/DailyReportTab.vue +10 -6
- package/components/Nfc/PatrolReport/MonthlyReportTab.vue +19 -9
- package/components/Nfc/PatrolReport/MonthlyReportTable.vue +69 -0
- package/components/Nfc/PatrolReport/PatrolActivityTable.vue +20 -0
- package/components/Nfc/PatrolReport/PatrolReportTab.vue +5 -3
- package/components/Nfc/PatrolReport/ReportDatePicker.vue +61 -0
- package/components/Nfc/PatrolReport/ReportFilters.vue +52 -20
- package/components/Nfc/PatrolReport/SummaryReportTable.vue +22 -0
- package/components/PhotoUpload.vue +19 -4
- package/components/ServiceProviderMain.vue +59 -25
- package/components/VisitorForm.vue +78 -18
- package/components/VisitorManagement.vue +12 -16
- package/composables/useCleaningSchedulePermission.ts +16 -51
- package/composables/useEquipment.ts +2 -0
- package/composables/useLocalAuth.ts +1 -1
- package/composables/useNFCPatrolDailyReport.ts +3 -4
- package/composables/useNFCPatrolMonthlyReport.ts +62 -30
- package/composables/useNFCPatrolReport.ts +2 -0
- package/composables/useServiceProvider.ts +21 -0
- package/package.json +1 -1
- package/types/customer.d.ts +2 -1
- package/types/equipment.d.ts +5 -1
- package/types/nfc-patrol-report.ts +19 -1
|
@@ -34,3 +34,14 @@ jobs:
|
|
|
34
34
|
|
|
35
35
|
- name: Publish to npm with staging tag
|
|
36
36
|
run: npm publish --tag staging --registry https://registry.npmjs.org
|
|
37
|
+
|
|
38
|
+
- name: Notify Discord on failure
|
|
39
|
+
if: failure()
|
|
40
|
+
env:
|
|
41
|
+
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
|
42
|
+
run: |
|
|
43
|
+
MESSAGE="@everyone :rotating_light: **Publish Staging** failed in \`${{ github.repository }}\` (\`${{ github.workflow }}\`)
|
|
44
|
+
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
45
|
+
curl -s -X POST -H "Content-Type: application/json" \
|
|
46
|
+
-d "$(jq -n --arg content "$MESSAGE" '{content: $content}')" \
|
|
47
|
+
"$DISCORD_WEBHOOK_URL"
|
|
@@ -12,6 +12,24 @@
|
|
|
12
12
|
<v-card-text class="pa-4">
|
|
13
13
|
<v-form ref="formRef" v-model="valid">
|
|
14
14
|
<v-row no-gutters class="pa-0">
|
|
15
|
+
<v-col cols="12" class="pa-0 mb-2">
|
|
16
|
+
<PhotoUpload
|
|
17
|
+
v-model="attachmentPhotos"
|
|
18
|
+
v-model:photo-ids="attachmentIds"
|
|
19
|
+
title="Photo"
|
|
20
|
+
@error="photoUploadError = $event"
|
|
21
|
+
/>
|
|
22
|
+
|
|
23
|
+
<v-alert
|
|
24
|
+
v-if="photoUploadError"
|
|
25
|
+
type="error"
|
|
26
|
+
density="compact"
|
|
27
|
+
variant="tonal"
|
|
28
|
+
class="mt-2"
|
|
29
|
+
>
|
|
30
|
+
{{ photoUploadError }}
|
|
31
|
+
</v-alert>
|
|
32
|
+
</v-col>
|
|
15
33
|
<v-col cols="12" class="pa-0 mb-2">
|
|
16
34
|
<InputLabel for="name" title="Name" required class="mb-1" />
|
|
17
35
|
<v-text-field
|
|
@@ -87,6 +105,10 @@ const unitOfMeasurementModel = defineModel("unitOfMeasurement", {
|
|
|
87
105
|
type: String,
|
|
88
106
|
default: "",
|
|
89
107
|
});
|
|
108
|
+
const attachmentModel = defineModel("attachment", {
|
|
109
|
+
type: String,
|
|
110
|
+
default: "",
|
|
111
|
+
});
|
|
90
112
|
const showDialog = defineModel({ type: Boolean, default: false });
|
|
91
113
|
|
|
92
114
|
const prop = defineProps({
|
|
@@ -105,6 +127,9 @@ const emit = defineEmits(["saved", "close"]);
|
|
|
105
127
|
const formRef = ref<any>(null);
|
|
106
128
|
const valid = ref(false);
|
|
107
129
|
const submitting = ref(false);
|
|
130
|
+
const attachmentPhotos = ref<string[]>([]);
|
|
131
|
+
const attachmentIds = ref<string[]>([]);
|
|
132
|
+
const photoUploadError = ref("");
|
|
108
133
|
|
|
109
134
|
const { requiredRule } = useUtils();
|
|
110
135
|
|
|
@@ -124,6 +149,29 @@ const unitOfMeasurementOptions = [
|
|
|
124
149
|
watchEffect(() => {
|
|
125
150
|
nameModel.value = prop.equipmentData?.name || "";
|
|
126
151
|
unitOfMeasurementModel.value = prop.equipmentData?.unitOfMeasurement || "";
|
|
152
|
+
attachmentModel.value = prop.equipmentData?.attachment || "";
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
watch(
|
|
156
|
+
attachmentIds,
|
|
157
|
+
(photoIds) => {
|
|
158
|
+
const [attachmentId] = photoIds;
|
|
159
|
+
attachmentModel.value = attachmentId || "";
|
|
160
|
+
|
|
161
|
+
if (photoIds.length > 1) {
|
|
162
|
+
attachmentIds.value = attachmentId ? [attachmentId] : [];
|
|
163
|
+
attachmentPhotos.value = attachmentPhotos.value.slice(0, 1);
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
{ deep: true }
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
watch(showDialog, (isOpen) => {
|
|
170
|
+
if (!isOpen) {
|
|
171
|
+
attachmentPhotos.value = [];
|
|
172
|
+
attachmentIds.value = [];
|
|
173
|
+
photoUploadError.value = "";
|
|
174
|
+
}
|
|
127
175
|
});
|
|
128
176
|
|
|
129
177
|
function close() {
|
|
@@ -147,12 +195,15 @@ async function submit() {
|
|
|
147
195
|
|
|
148
196
|
emit("saved", {
|
|
149
197
|
name: nameModel.value,
|
|
150
|
-
|
|
151
198
|
unitOfMeasurement: unitOfMeasurementModel.value,
|
|
199
|
+
attachment: attachmentModel.value,
|
|
152
200
|
});
|
|
153
201
|
|
|
154
202
|
nameModel.value = "";
|
|
155
203
|
unitOfMeasurementModel.value = "";
|
|
204
|
+
attachmentModel.value = "";
|
|
205
|
+
attachmentPhotos.value = [];
|
|
206
|
+
attachmentIds.value = [];
|
|
156
207
|
|
|
157
208
|
showDialog.value = false;
|
|
158
209
|
emit("close");
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
:items="items"
|
|
29
29
|
fixed-header
|
|
30
30
|
hide-default-footer
|
|
31
|
-
hide-default-header
|
|
32
31
|
@click:row="handleRowClick"
|
|
33
32
|
style="max-height: 300px"
|
|
34
33
|
>
|
|
@@ -281,10 +280,10 @@ const prop = defineProps({
|
|
|
281
280
|
headers: {
|
|
282
281
|
type: Array as PropType<Array<any>>,
|
|
283
282
|
default: () => [
|
|
284
|
-
{
|
|
285
|
-
{
|
|
286
|
-
{
|
|
287
|
-
{
|
|
283
|
+
// { title: "Host", key: "host" },
|
|
284
|
+
// { title: "Category", key: "category" },
|
|
285
|
+
// { title: "Guard House", key: "guardPost" },
|
|
286
|
+
// { title: "Actions", key: "action", sortable: false },
|
|
288
287
|
],
|
|
289
288
|
},
|
|
290
289
|
readOnly: {
|
|
@@ -295,11 +294,20 @@ const prop = defineProps({
|
|
|
295
294
|
|
|
296
295
|
const computedHeaders = computed(() => {
|
|
297
296
|
if (prop.type === "ip") {
|
|
298
|
-
const base = [...prop.headers];
|
|
299
|
-
base.splice(0, 0, {
|
|
300
|
-
return base;
|
|
297
|
+
// const base = [...prop.headers];
|
|
298
|
+
// base.splice(0, 0, { title: "Name", key: "name" });
|
|
299
|
+
// return base;
|
|
300
|
+
return [
|
|
301
|
+
{ title: "Camera Name", key: "name" },
|
|
302
|
+
{ title: "URL", key: "host" },
|
|
303
|
+
]
|
|
304
|
+
}else if(prop.type === "anpr"){
|
|
305
|
+
return [
|
|
306
|
+
{ title: "URL", key: "host" },
|
|
307
|
+
{ title: "Type", key: "direction" },
|
|
308
|
+
]
|
|
301
309
|
}
|
|
302
|
-
return prop.headers;
|
|
310
|
+
// return prop.headers;
|
|
303
311
|
});
|
|
304
312
|
|
|
305
313
|
const items = ref<Array<TCamera>>([]);
|
|
@@ -984,60 +984,44 @@
|
|
|
984
984
|
<div
|
|
985
985
|
v-for="item in formattedActivePatrolItems"
|
|
986
986
|
:key="item.id || item._id"
|
|
987
|
-
class="
|
|
988
|
-
style="
|
|
989
|
-
padding: 16px 20px;
|
|
990
|
-
border: 1px solid #e2e8f0;
|
|
991
|
-
border-radius: 12px;
|
|
992
|
-
margin-bottom: 12px;
|
|
993
|
-
background-color: #ffffff;
|
|
994
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
|
|
995
|
-
"
|
|
987
|
+
class="active-patrol-row"
|
|
996
988
|
>
|
|
997
|
-
<div
|
|
998
|
-
<strong
|
|
999
|
-
|
|
1000
|
-
display: block;
|
|
1001
|
-
font-size: 15px;
|
|
1002
|
-
font-weight: 700;
|
|
1003
|
-
color: #0b2f47;
|
|
1004
|
-
margin-bottom: 4px;
|
|
1005
|
-
"
|
|
1006
|
-
>{{ item.title || item.name }}</strong
|
|
1007
|
-
>
|
|
1008
|
-
<span style="font-size: 13px; color: #94a3b8">{{
|
|
1009
|
-
item.subtitle || item.location || ""
|
|
1010
|
-
}}</span>
|
|
989
|
+
<div class="active-patrol-main">
|
|
990
|
+
<strong>{{ item.title || item.name }}</strong>
|
|
991
|
+
<span>{{ item.subtitle || item.location || "" }}</span>
|
|
1011
992
|
</div>
|
|
1012
993
|
|
|
1013
|
-
<div
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
item.
|
|
1022
|
-
|
|
994
|
+
<div class="active-patrol-assignees">
|
|
995
|
+
<div class="active-patrol-assignee">
|
|
996
|
+
<AvatarMain :name="item.primaryAssignee" :size="24" />
|
|
997
|
+
<span>{{ item.primaryAssignee }}</span>
|
|
998
|
+
</div>
|
|
999
|
+
<span
|
|
1000
|
+
v-if="item.extraAssigneeCount > 0"
|
|
1001
|
+
class="active-patrol-more-pill active-patrol-tooltip"
|
|
1002
|
+
:data-tooltip="item.extraAssignees.join(', ')"
|
|
1003
|
+
>
|
|
1004
|
+
+{{ item.extraAssigneeCount }}
|
|
1005
|
+
</span>
|
|
1023
1006
|
</div>
|
|
1024
1007
|
|
|
1025
|
-
<div
|
|
1008
|
+
<div class="active-patrol-statuses">
|
|
1026
1009
|
<div
|
|
1027
|
-
|
|
1028
|
-
style="
|
|
1029
|
-
padding: 6px 16px;
|
|
1030
|
-
border-radius: 20px;
|
|
1031
|
-
font-size: 13px;
|
|
1032
|
-
font-weight: 500;
|
|
1033
|
-
text-transform: capitalize;
|
|
1034
|
-
"
|
|
1010
|
+
class="active-patrol-status-pill"
|
|
1011
|
+
:style="getPatrolStatusStyle(item.primaryStatus)"
|
|
1035
1012
|
>
|
|
1036
|
-
{{ item.
|
|
1013
|
+
{{ item.primaryStatus }}
|
|
1037
1014
|
</div>
|
|
1015
|
+
<span
|
|
1016
|
+
v-if="item.extraStatusCount > 0"
|
|
1017
|
+
class="active-patrol-more-pill active-patrol-tooltip"
|
|
1018
|
+
:data-tooltip="item.extraStatuses.join(', ')"
|
|
1019
|
+
>
|
|
1020
|
+
+{{ item.extraStatusCount }}
|
|
1021
|
+
</span>
|
|
1038
1022
|
</div>
|
|
1039
1023
|
|
|
1040
|
-
<div
|
|
1024
|
+
<div class="active-patrol-action">
|
|
1041
1025
|
<v-btn
|
|
1042
1026
|
variant="outlined"
|
|
1043
1027
|
class="text-none font-weight-medium"
|
|
@@ -1545,30 +1529,16 @@ const { userAppRole } = useLocalSetup();
|
|
|
1545
1529
|
const { downloadPDF } = usePDFDownload();
|
|
1546
1530
|
const route = useRoute();
|
|
1547
1531
|
|
|
1548
|
-
const dashboardWidgetPermissions: Record<string, string> = {
|
|
1549
|
-
activity: "dashboard:view-activity",
|
|
1550
|
-
recentActivity: "dashboard:view-activity",
|
|
1551
|
-
taskSchedule: "dashboard:view-task-schedule",
|
|
1552
|
-
staffStatus: "dashboard:view-attendance-widget",
|
|
1553
|
-
attendance: "dashboard:view-attendance-widget",
|
|
1554
|
-
feedbacks: "dashboard:view-feedbacks-widget",
|
|
1555
|
-
workOrderStatus: "dashboard:view-work-order-status",
|
|
1556
|
-
activePatrol: "dashboard:view-active-patrol",
|
|
1557
|
-
upcomingEvents: "dashboard:view-upcoming-events",
|
|
1558
|
-
todayReminders: "dashboard:view-today-reminders",
|
|
1559
|
-
todayAttentions: "dashboard:view-today-attentions",
|
|
1560
|
-
};
|
|
1561
|
-
|
|
1562
1532
|
const propertyWidgetPermissions: Record<string, string[]> = {
|
|
1563
1533
|
workOrders: [
|
|
1564
|
-
"
|
|
1534
|
+
"work_orders:see-all-work-orders",
|
|
1565
1535
|
"work-order:see-all-work-orders",
|
|
1566
1536
|
],
|
|
1567
1537
|
incidents: ["incident-reports:see-incident-reports"],
|
|
1568
1538
|
visitors: ["visitorManagement:see-all-visitor"],
|
|
1569
1539
|
facilityBookings: ["facility-booking-mgmt:see-all-facility-booking"],
|
|
1570
1540
|
activity: [
|
|
1571
|
-
"
|
|
1541
|
+
"work_orders:see-all-work-orders",
|
|
1572
1542
|
"work-order:see-all-work-orders",
|
|
1573
1543
|
],
|
|
1574
1544
|
upcomingEvents: ["event-mgmt:see-all-event"],
|
|
@@ -1578,7 +1548,7 @@ const propertyWidgetPermissions: Record<string, string[]> = {
|
|
|
1578
1548
|
"facility-booking-mgmt:see-all-facility-booking",
|
|
1579
1549
|
],
|
|
1580
1550
|
workOrderStatus: [
|
|
1581
|
-
"
|
|
1551
|
+
"work_orders:see-all-work-orders",
|
|
1582
1552
|
"work-order:see-all-work-orders",
|
|
1583
1553
|
],
|
|
1584
1554
|
feedbacks: ["feedbacks:see-all-feedback"],
|
|
@@ -1587,27 +1557,30 @@ const propertyWidgetPermissions: Record<string, string[]> = {
|
|
|
1587
1557
|
|
|
1588
1558
|
const moduleWidgetPermissions: Record<string, string[]> = {
|
|
1589
1559
|
openWorkOrder: [
|
|
1560
|
+
"work_orders:see-all-work-orders",
|
|
1590
1561
|
"work_order:see-all-work-orders",
|
|
1591
1562
|
"work-order:see-all-work-orders",
|
|
1592
1563
|
"work-orders:see-all-work-orders",
|
|
1593
1564
|
],
|
|
1594
1565
|
workOrders: [
|
|
1566
|
+
"work_orders:see-all-work-orders",
|
|
1595
1567
|
"work_order:see-all-work-orders",
|
|
1596
1568
|
"work-order:see-all-work-orders",
|
|
1597
1569
|
"work-orders:see-all-work-orders",
|
|
1598
1570
|
],
|
|
1599
1571
|
activity: [
|
|
1572
|
+
"work_orders:see-all-work-orders",
|
|
1600
1573
|
"work_order:see-all-work-orders",
|
|
1601
1574
|
"work-order:see-all-work-orders",
|
|
1602
1575
|
"work-orders:see-all-work-orders",
|
|
1576
|
+
"work_orders:see-all-work-orders",
|
|
1603
1577
|
],
|
|
1604
|
-
|
|
1605
|
-
"
|
|
1606
|
-
"
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
"
|
|
1610
|
-
"schedule-task-mgmt:see-all-schedule-tasks",
|
|
1578
|
+
recentActivity: [
|
|
1579
|
+
"work_orders:see-all-work-orders",
|
|
1580
|
+
"work_order:see-all-work-orders",
|
|
1581
|
+
"work-order:see-all-work-orders",
|
|
1582
|
+
"work-orders:see-all-work-orders",
|
|
1583
|
+
"work_orders:see-all-work-orders",
|
|
1611
1584
|
],
|
|
1612
1585
|
staffStatus: ["attendance-mgmt:see-all-attendance"],
|
|
1613
1586
|
attendance: ["attendance-mgmt:see-all-attendance"],
|
|
@@ -1630,9 +1603,14 @@ const moduleWidgetPermissions: Record<string, string[]> = {
|
|
|
1630
1603
|
activePatrol: ["virtual-patrol:see-all-virtual-patrol-logs"],
|
|
1631
1604
|
};
|
|
1632
1605
|
|
|
1606
|
+
function hasSchedulePermission(permissions: string[], action: string) {
|
|
1607
|
+
return permissions.some((permission) =>
|
|
1608
|
+
permission.endsWith(`-schedule-mgmt:${action}`)
|
|
1609
|
+
);
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1633
1612
|
function canViewWidget(key: string) {
|
|
1634
1613
|
const permissions = userAppRole.value?.permissions;
|
|
1635
|
-
const dashboardPermission = dashboardWidgetPermissions[key];
|
|
1636
1614
|
const modulePermissions = isPropertyMode.value
|
|
1637
1615
|
? propertyWidgetPermissions[key]
|
|
1638
1616
|
: moduleWidgetPermissions[key];
|
|
@@ -1640,20 +1618,22 @@ function canViewWidget(key: string) {
|
|
|
1640
1618
|
if (!permissions) return true;
|
|
1641
1619
|
if (permissions.includes("*")) return true;
|
|
1642
1620
|
|
|
1621
|
+
if (
|
|
1622
|
+
!isPropertyMode.value &&
|
|
1623
|
+
["taskSchedule", "taskCompleted"].includes(key)
|
|
1624
|
+
) {
|
|
1625
|
+
return hasSchedulePermission(permissions, "see-all-schedules");
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1643
1628
|
if (isPropertyMode.value && modulePermissions) {
|
|
1644
1629
|
return modulePermissions.some((permission) =>
|
|
1645
1630
|
permissions.includes(permission)
|
|
1646
1631
|
);
|
|
1647
1632
|
}
|
|
1648
1633
|
|
|
1649
|
-
if (
|
|
1650
|
-
return (
|
|
1651
|
-
|
|
1652
|
-
Boolean(
|
|
1653
|
-
modulePermissions?.some((permission) =>
|
|
1654
|
-
permissions.includes(permission)
|
|
1655
|
-
)
|
|
1656
|
-
)
|
|
1634
|
+
if (modulePermissions) {
|
|
1635
|
+
return modulePermissions.some((permission) =>
|
|
1636
|
+
permissions.includes(permission)
|
|
1657
1637
|
);
|
|
1658
1638
|
}
|
|
1659
1639
|
|
|
@@ -2771,18 +2751,23 @@ const activePatrolItems = computed<any[]>(
|
|
|
2771
2751
|
|
|
2772
2752
|
const formattedActivePatrolItems = computed<any[]>(() => {
|
|
2773
2753
|
return activePatrolItems.value.map((item) => {
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
if (Array.isArray(person)) {
|
|
2780
|
-
person = person.join(", ");
|
|
2781
|
-
}
|
|
2754
|
+
const statuses = normalizeListValue(item.status || "Pending");
|
|
2755
|
+
const assignees = normalizeListValue(
|
|
2756
|
+
item.person || item.assignedTo || "Unassigned"
|
|
2757
|
+
);
|
|
2758
|
+
|
|
2782
2759
|
return {
|
|
2783
2760
|
...item,
|
|
2784
|
-
status,
|
|
2785
|
-
|
|
2761
|
+
status: statuses.join(", "),
|
|
2762
|
+
statuses,
|
|
2763
|
+
primaryStatus: statuses[0] || "Pending",
|
|
2764
|
+
extraStatuses: statuses.slice(1),
|
|
2765
|
+
extraStatusCount: Math.max(0, statuses.length - 1),
|
|
2766
|
+
person: assignees.join(", "),
|
|
2767
|
+
assignees,
|
|
2768
|
+
primaryAssignee: assignees[0] || "Unassigned",
|
|
2769
|
+
extraAssignees: assignees.slice(1),
|
|
2770
|
+
extraAssigneeCount: Math.max(0, assignees.length - 1),
|
|
2786
2771
|
};
|
|
2787
2772
|
});
|
|
2788
2773
|
});
|
|
@@ -3952,6 +3937,20 @@ function normalizeStatus(value: any) {
|
|
|
3952
3937
|
return text.replace(/[_-]+/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
3953
3938
|
}
|
|
3954
3939
|
|
|
3940
|
+
function normalizeListValue(value: any) {
|
|
3941
|
+
if (Array.isArray(value)) {
|
|
3942
|
+
return value
|
|
3943
|
+
.flatMap((entry) => normalizeListValue(entry))
|
|
3944
|
+
.map((entry) => String(entry).trim())
|
|
3945
|
+
.filter(Boolean);
|
|
3946
|
+
}
|
|
3947
|
+
|
|
3948
|
+
return String(value || "")
|
|
3949
|
+
.split(",")
|
|
3950
|
+
.map((entry) => entry.trim())
|
|
3951
|
+
.filter(Boolean);
|
|
3952
|
+
}
|
|
3953
|
+
|
|
3955
3954
|
function getStatusTone(status: any) {
|
|
3956
3955
|
const s = String(status || "").toLowerCase();
|
|
3957
3956
|
if (
|
|
@@ -4419,6 +4418,151 @@ function formatDashboardTime(value?: string) {
|
|
|
4419
4418
|
border: 2px solid #f9c97c;
|
|
4420
4419
|
}
|
|
4421
4420
|
|
|
4421
|
+
.active-patrol-row {
|
|
4422
|
+
align-items: center;
|
|
4423
|
+
background-color: #ffffff;
|
|
4424
|
+
border: 1px solid #e2e8f0;
|
|
4425
|
+
border-radius: 8px;
|
|
4426
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
|
|
4427
|
+
display: grid;
|
|
4428
|
+
gap: 10px;
|
|
4429
|
+
grid-template-columns: 150px minmax(0, 1fr) max-content max-content;
|
|
4430
|
+
margin-bottom: 12px;
|
|
4431
|
+
min-height: 64px;
|
|
4432
|
+
overflow: visible;
|
|
4433
|
+
padding: 12px 14px;
|
|
4434
|
+
}
|
|
4435
|
+
|
|
4436
|
+
.active-patrol-main {
|
|
4437
|
+
min-width: 0;
|
|
4438
|
+
}
|
|
4439
|
+
|
|
4440
|
+
.active-patrol-main strong {
|
|
4441
|
+
color: #0b2f47;
|
|
4442
|
+
display: block;
|
|
4443
|
+
font-size: 13px;
|
|
4444
|
+
font-weight: 700;
|
|
4445
|
+
line-height: 1.25;
|
|
4446
|
+
margin-bottom: 3px;
|
|
4447
|
+
overflow-wrap: anywhere;
|
|
4448
|
+
}
|
|
4449
|
+
|
|
4450
|
+
.active-patrol-main span {
|
|
4451
|
+
color: #94a3b8;
|
|
4452
|
+
display: block;
|
|
4453
|
+
font-size: 11px;
|
|
4454
|
+
line-height: 1.25;
|
|
4455
|
+
overflow-wrap: anywhere;
|
|
4456
|
+
}
|
|
4457
|
+
|
|
4458
|
+
.active-patrol-assignees {
|
|
4459
|
+
align-items: center;
|
|
4460
|
+
display: flex;
|
|
4461
|
+
gap: 6px;
|
|
4462
|
+
min-width: 0;
|
|
4463
|
+
}
|
|
4464
|
+
|
|
4465
|
+
.active-patrol-assignee {
|
|
4466
|
+
align-items: center;
|
|
4467
|
+
background: #f8fafc;
|
|
4468
|
+
border: 1px solid #e7edf3;
|
|
4469
|
+
border-radius: 999px;
|
|
4470
|
+
display: inline-flex;
|
|
4471
|
+
flex: 1 1 auto;
|
|
4472
|
+
gap: 6px;
|
|
4473
|
+
max-width: 100%;
|
|
4474
|
+
min-width: 0;
|
|
4475
|
+
padding: 2px 8px 2px 3px;
|
|
4476
|
+
}
|
|
4477
|
+
|
|
4478
|
+
.active-patrol-assignee span {
|
|
4479
|
+
color: #475569;
|
|
4480
|
+
font-size: 11px;
|
|
4481
|
+
font-weight: 600;
|
|
4482
|
+
line-height: 1.2;
|
|
4483
|
+
min-width: 0;
|
|
4484
|
+
overflow: hidden;
|
|
4485
|
+
text-overflow: ellipsis;
|
|
4486
|
+
white-space: nowrap;
|
|
4487
|
+
}
|
|
4488
|
+
|
|
4489
|
+
.active-patrol-statuses {
|
|
4490
|
+
align-items: center;
|
|
4491
|
+
display: flex;
|
|
4492
|
+
gap: 6px;
|
|
4493
|
+
justify-content: flex-start;
|
|
4494
|
+
min-width: 0;
|
|
4495
|
+
}
|
|
4496
|
+
|
|
4497
|
+
.active-patrol-status-pill {
|
|
4498
|
+
border-radius: 20px;
|
|
4499
|
+
font-size: 11px;
|
|
4500
|
+
font-weight: 600;
|
|
4501
|
+
line-height: 1.2;
|
|
4502
|
+
padding: 5px 10px;
|
|
4503
|
+
text-transform: capitalize;
|
|
4504
|
+
white-space: nowrap;
|
|
4505
|
+
}
|
|
4506
|
+
|
|
4507
|
+
.active-patrol-more-pill {
|
|
4508
|
+
align-items: center;
|
|
4509
|
+
background: #eef3f8;
|
|
4510
|
+
border: 1px solid #dbe4ed;
|
|
4511
|
+
border-radius: 999px;
|
|
4512
|
+
color: #607386;
|
|
4513
|
+
display: inline-flex;
|
|
4514
|
+
flex: 0 0 auto;
|
|
4515
|
+
font-size: 11px;
|
|
4516
|
+
font-weight: 800;
|
|
4517
|
+
height: 24px;
|
|
4518
|
+
justify-content: center;
|
|
4519
|
+
line-height: 1;
|
|
4520
|
+
min-width: 30px;
|
|
4521
|
+
padding: 0 8px;
|
|
4522
|
+
position: relative;
|
|
4523
|
+
white-space: nowrap;
|
|
4524
|
+
}
|
|
4525
|
+
|
|
4526
|
+
.active-patrol-action {
|
|
4527
|
+
justify-self: end;
|
|
4528
|
+
text-align: right;
|
|
4529
|
+
}
|
|
4530
|
+
|
|
4531
|
+
.active-patrol-tooltip::after {
|
|
4532
|
+
background: #0f2638;
|
|
4533
|
+
border-radius: 6px;
|
|
4534
|
+
bottom: calc(100% + 8px);
|
|
4535
|
+
box-shadow: 0 8px 24px rgba(15, 38, 56, 0.18);
|
|
4536
|
+
color: #ffffff;
|
|
4537
|
+
content: attr(data-tooltip);
|
|
4538
|
+
font-size: 11px;
|
|
4539
|
+
font-weight: 600;
|
|
4540
|
+
left: 50%;
|
|
4541
|
+
line-height: 1.35;
|
|
4542
|
+
max-width: 260px;
|
|
4543
|
+
opacity: 0;
|
|
4544
|
+
padding: 7px 9px;
|
|
4545
|
+
pointer-events: none;
|
|
4546
|
+
position: absolute;
|
|
4547
|
+
text-align: left;
|
|
4548
|
+
transform: translate(-50%, 4px);
|
|
4549
|
+
transition: opacity 0.14s ease, transform 0.14s ease;
|
|
4550
|
+
white-space: normal;
|
|
4551
|
+
width: max-content;
|
|
4552
|
+
z-index: 5;
|
|
4553
|
+
}
|
|
4554
|
+
|
|
4555
|
+
.active-patrol-tooltip:hover::after {
|
|
4556
|
+
opacity: 1;
|
|
4557
|
+
transform: translate(-50%, 0);
|
|
4558
|
+
}
|
|
4559
|
+
|
|
4560
|
+
@media (max-width: 960px) {
|
|
4561
|
+
.active-patrol-row {
|
|
4562
|
+
grid-template-columns: 120px minmax(0, 1fr) max-content max-content;
|
|
4563
|
+
}
|
|
4564
|
+
}
|
|
4565
|
+
|
|
4422
4566
|
.figma-icon-badge {
|
|
4423
4567
|
align-items: center;
|
|
4424
4568
|
border-radius: 50%;
|