@iservice365/layer-common 1.1.0 → 1.3.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 +21 -0
- package/components/CameraForm.vue +264 -0
- package/components/CameraMain.vue +352 -0
- package/components/Card/DeleteConfirmation.vue +51 -0
- package/components/Card/MemberInfoSummary.vue +44 -0
- package/components/Chat/Information.vue +28 -11
- package/components/Dialog/DeleteConfirmation.vue +51 -0
- package/components/Dialog/UpdateMoreAction.vue +99 -0
- package/components/Feedback/Form.vue +17 -3
- package/components/FeedbackDetail.vue +0 -11
- package/components/FeedbackMain.vue +21 -11
- package/components/Input/DateTimePicker.vue +10 -5
- package/components/Input/File.vue +1 -1
- package/components/Input/FileV2.vue +106 -63
- package/components/Input/InputPhoneNumberV2.vue +114 -0
- package/components/Input/NRICNumber.vue +41 -0
- package/components/Input/PhoneNumber.vue +1 -0
- package/components/Input/VehicleNumber.vue +49 -0
- package/components/NumberSettingField.vue +107 -0
- package/components/PeopleForm.vue +452 -0
- package/components/TableMain.vue +2 -1
- package/components/VehicleUpdateMoreAction.vue +84 -0
- package/components/VisitorForm.vue +712 -0
- package/components/VisitorFormSelection.vue +53 -0
- package/components/VisitorManagement.vue +569 -0
- package/components/WorkOrder/Create.vue +87 -49
- package/components/WorkOrder/Main.vue +17 -12
- package/composables/useBuilding.ts +250 -0
- package/composables/useBuildingUnit.ts +116 -0
- package/composables/useFeedback.ts +3 -3
- package/composables/useFile.ts +7 -9
- package/composables/useLocal.ts +67 -0
- package/composables/usePeople.ts +48 -0
- package/composables/useSecurityUtils.ts +18 -0
- package/composables/useSiteSettings.ts +111 -0
- package/composables/useUtils.ts +30 -1
- package/composables/useVisitor.ts +80 -0
- package/composables/useWorkOrder.ts +3 -3
- package/package.json +1 -1
- package/plugins/vuetify.ts +6 -1
- package/types/building.d.ts +19 -0
- package/types/camera.d.ts +31 -0
- package/types/people.d.ts +22 -0
- package/types/select.d.ts +4 -0
- package/types/site.d.ts +10 -7
- package/types/visitor.d.ts +42 -0
- package/utils/phoneMasks.ts +1703 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @iservice365/layer-common
|
|
2
2
|
|
|
3
|
+
## 1.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 88b8014: ## What's Changed
|
|
8
|
+
|
|
9
|
+
- 20089 add edit guest feature by @aguirremac17 in https://github.com/Seven365-Pte-Ltd/iservice365-layer-common/pull/156
|
|
10
|
+
- chore: remove deltefile integration in frontend by @aguirremac17 in https://github.com/Seven365-Pte-Ltd/iservice365-layer-common/pull/157
|
|
11
|
+
- Work Order subject form update by @Jerome7365 in https://github.com/Seven365-Pte-Ltd/iservice365-layer-common/pull/158
|
|
12
|
+
- chore: update query key to status by @aguirremac17 in https://github.com/Seven365-Pte-Ltd/iservice365-layer-common/pull/159
|
|
13
|
+
- 20114 update key type to status in visitor management by @aguirremac17 in https://github.com/Seven365-Pte-Ltd/iservice365-layer-common/pull/160
|
|
14
|
+
- Update Work Order Component And Composable by @Jerome7365 in https://github.com/Seven365-Pte-Ltd/iservice365-layer-common/pull/161
|
|
15
|
+
|
|
16
|
+
**Full Changelog**: https://github.com/Seven365-Pte-Ltd/iservice365-layer-common/compare/v1.2.0...1.3.0
|
|
17
|
+
|
|
18
|
+
## 1.2.0
|
|
19
|
+
|
|
20
|
+
### Minor Changes
|
|
21
|
+
|
|
22
|
+
- 770867c: People mgmt - initial release
|
|
23
|
+
|
|
3
24
|
## 1.1.0
|
|
4
25
|
|
|
5
26
|
### Minor Changes
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-card width="100%">
|
|
3
|
+
<v-toolbar>
|
|
4
|
+
<v-row no-gutters class="fill-height px-6" align="center">
|
|
5
|
+
<span class="font-weight-bold text-h5 text-capitalize">
|
|
6
|
+
{{ title }}
|
|
7
|
+
</span>
|
|
8
|
+
</v-row>
|
|
9
|
+
</v-toolbar>
|
|
10
|
+
|
|
11
|
+
<v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-5 my-5">
|
|
12
|
+
<v-form ref="formRef" v-model="validForm" :disabled="disable">
|
|
13
|
+
<v-row no-gutters class="pt-4">
|
|
14
|
+
<v-col cols="12">
|
|
15
|
+
<InputLabel class="text-capitalize" title="URL" required />
|
|
16
|
+
<v-text-field
|
|
17
|
+
v-model.trim="camera.host"
|
|
18
|
+
density="comfortable"
|
|
19
|
+
:rules="[requiredRule, isValidBaseURL]"
|
|
20
|
+
placeholder="Enter camera URL"
|
|
21
|
+
/>
|
|
22
|
+
</v-col>
|
|
23
|
+
|
|
24
|
+
<v-col v-if="isANPR" cols="12">
|
|
25
|
+
<InputLabel class="text-capitalize" title="Category" required />
|
|
26
|
+
<v-select
|
|
27
|
+
v-model="camera.category"
|
|
28
|
+
:items="anprCategoryOptions"
|
|
29
|
+
density="comfortable"
|
|
30
|
+
:rules="[requiredRule]"
|
|
31
|
+
/>
|
|
32
|
+
</v-col>
|
|
33
|
+
|
|
34
|
+
<v-col v-if="isANPR" cols="12">
|
|
35
|
+
<InputLabel class="text-capitalize" title="Direction" required />
|
|
36
|
+
<v-select
|
|
37
|
+
v-model="camera.direction"
|
|
38
|
+
:items="anprDirectionOptions"
|
|
39
|
+
density="comfortable"
|
|
40
|
+
:rules="[requiredRule]"
|
|
41
|
+
/>
|
|
42
|
+
</v-col>
|
|
43
|
+
|
|
44
|
+
<v-col v-if="isANPR" cols="12">
|
|
45
|
+
<InputLabel class="text-capitalize" title="Guard House" />
|
|
46
|
+
<v-select
|
|
47
|
+
v-model="camera.guardPost"
|
|
48
|
+
:items="guardPostOptions"
|
|
49
|
+
density="comfortable"
|
|
50
|
+
/>
|
|
51
|
+
</v-col>
|
|
52
|
+
|
|
53
|
+
<v-col cols="12">
|
|
54
|
+
<InputLabel class="text-capitalize" title="User" required />
|
|
55
|
+
<v-text-field
|
|
56
|
+
v-model.trim="camera.username"
|
|
57
|
+
density="comfortable"
|
|
58
|
+
:rules="[requiredRule]"
|
|
59
|
+
placeholder="Enter username"
|
|
60
|
+
/>
|
|
61
|
+
</v-col>
|
|
62
|
+
|
|
63
|
+
<v-col cols="12">
|
|
64
|
+
<InputLabel class="text-capitalize" title="Password" required />
|
|
65
|
+
<v-text-field
|
|
66
|
+
v-model.trim="camera.password"
|
|
67
|
+
type="password"
|
|
68
|
+
density="comfortable"
|
|
69
|
+
:rules="[requiredRule]"
|
|
70
|
+
placeholder="Enter password"
|
|
71
|
+
/>
|
|
72
|
+
</v-col>
|
|
73
|
+
</v-row>
|
|
74
|
+
</v-form>
|
|
75
|
+
</v-card-text>
|
|
76
|
+
|
|
77
|
+
<v-toolbar density="compact">
|
|
78
|
+
<v-row no-gutters>
|
|
79
|
+
<v-col cols="6">
|
|
80
|
+
<v-btn
|
|
81
|
+
tile
|
|
82
|
+
block
|
|
83
|
+
variant="text"
|
|
84
|
+
class="text-none"
|
|
85
|
+
size="48"
|
|
86
|
+
@click="back"
|
|
87
|
+
text="Cancel"
|
|
88
|
+
/>
|
|
89
|
+
</v-col>
|
|
90
|
+
<v-col cols="6">
|
|
91
|
+
<v-btn
|
|
92
|
+
tile
|
|
93
|
+
block
|
|
94
|
+
variant="flat"
|
|
95
|
+
color="black"
|
|
96
|
+
class="text-none"
|
|
97
|
+
size="48"
|
|
98
|
+
:disabled="!validForm || disable || !hasChanges"
|
|
99
|
+
@click="submit"
|
|
100
|
+
:loading="disable"
|
|
101
|
+
text="Submit"
|
|
102
|
+
/>
|
|
103
|
+
</v-col>
|
|
104
|
+
</v-row>
|
|
105
|
+
</v-toolbar>
|
|
106
|
+
</v-card>
|
|
107
|
+
</template>
|
|
108
|
+
|
|
109
|
+
<script setup lang="ts">
|
|
110
|
+
import useSiteSettings from '../composables/useSiteSettings';
|
|
111
|
+
|
|
112
|
+
const prop = defineProps({
|
|
113
|
+
title: {
|
|
114
|
+
type: String,
|
|
115
|
+
default: "Site Camera Form",
|
|
116
|
+
},
|
|
117
|
+
site: {
|
|
118
|
+
type: String,
|
|
119
|
+
required: true,
|
|
120
|
+
},
|
|
121
|
+
guardPosts: {
|
|
122
|
+
type: Number,
|
|
123
|
+
default: 0,
|
|
124
|
+
},
|
|
125
|
+
type: {
|
|
126
|
+
type: String as PropType<TSiteCamera["type"]>,
|
|
127
|
+
default: "anpr",
|
|
128
|
+
},
|
|
129
|
+
mode: {
|
|
130
|
+
type: String,
|
|
131
|
+
default: "add",
|
|
132
|
+
},
|
|
133
|
+
camera: {
|
|
134
|
+
type: Object as PropType<TSiteCamera>,
|
|
135
|
+
default: () => ({
|
|
136
|
+
site: "",
|
|
137
|
+
host: "",
|
|
138
|
+
username: "",
|
|
139
|
+
password: "",
|
|
140
|
+
type: "ip",
|
|
141
|
+
category: "standard",
|
|
142
|
+
direction: "none",
|
|
143
|
+
guardPost: null,
|
|
144
|
+
status: "active",
|
|
145
|
+
}),
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const { requiredRule, isValidBaseURL } = useUtils();
|
|
150
|
+
const emit = defineEmits(["cancel", "select", "success", "error"]);
|
|
151
|
+
|
|
152
|
+
const camera = ref<TSiteCamera>({
|
|
153
|
+
site: "",
|
|
154
|
+
host: "",
|
|
155
|
+
username: "",
|
|
156
|
+
password: "",
|
|
157
|
+
type: "ip",
|
|
158
|
+
category: "standard",
|
|
159
|
+
direction: "none",
|
|
160
|
+
guardPost: null,
|
|
161
|
+
status: "active",
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
camera.value.site = prop.site;
|
|
165
|
+
|
|
166
|
+
if (prop.mode === "edit") {
|
|
167
|
+
camera.value = JSON.parse(JSON.stringify(prop.camera));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
camera.value.site = prop.site;
|
|
171
|
+
camera.value.type = prop.type;
|
|
172
|
+
camera.value.category = prop.type === "anpr" ? "resident" : "standard";
|
|
173
|
+
camera.value.direction = prop.type === "anpr" ? "both" : "none";
|
|
174
|
+
|
|
175
|
+
const validForm = ref(false);
|
|
176
|
+
const formRef = ref<HTMLFormElement | null>(null);
|
|
177
|
+
const disable = ref(false);
|
|
178
|
+
const message = ref("");
|
|
179
|
+
|
|
180
|
+
const isANPR = computed(() => prop.type === "anpr");
|
|
181
|
+
|
|
182
|
+
const anprCategoryOptions = computed(() => [
|
|
183
|
+
{ title: "Resident", value: "resident" },
|
|
184
|
+
{ title: "Visitor", value: "visitor" },
|
|
185
|
+
]);
|
|
186
|
+
|
|
187
|
+
const anprDirectionOptions = computed(() => [
|
|
188
|
+
{ title: "Entry", value: "entry" },
|
|
189
|
+
{ title: "Exit", value: "exit" },
|
|
190
|
+
{ title: "Both", value: "both" },
|
|
191
|
+
{ title: "None", value: "none" },
|
|
192
|
+
]);
|
|
193
|
+
|
|
194
|
+
function back() {
|
|
195
|
+
message.value = "";
|
|
196
|
+
|
|
197
|
+
if (formRef.value) {
|
|
198
|
+
formRef.value.reset();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
emit("cancel");
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const hasChanges = computed(() => {
|
|
205
|
+
// Only check for changes in edit mode
|
|
206
|
+
if (prop.mode === "edit") {
|
|
207
|
+
return (
|
|
208
|
+
camera.value.host !== prop.camera.host ||
|
|
209
|
+
camera.value.username !== prop.camera.username ||
|
|
210
|
+
camera.value.password !== prop.camera.password ||
|
|
211
|
+
camera.value.category !== prop.camera.category ||
|
|
212
|
+
camera.value.guardPost !== prop.camera.guardPost ||
|
|
213
|
+
camera.value.direction !== prop.camera.direction
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// For add mode, always return true (allow submission)
|
|
218
|
+
return true;
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const { addCamera, updateSiteCamera } = useSiteSettings();
|
|
222
|
+
|
|
223
|
+
async function submit() {
|
|
224
|
+
disable.value = true;
|
|
225
|
+
camera.value.guardPost = camera.value.guardPost ?? 0;
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
if (prop.mode === "add") {
|
|
229
|
+
await addCamera(camera.value);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (prop.mode === "edit") {
|
|
233
|
+
await updateSiteCamera(camera.value._id ?? "", {
|
|
234
|
+
host: camera.value.host,
|
|
235
|
+
username: camera.value.username,
|
|
236
|
+
password: camera.value.password,
|
|
237
|
+
category: camera.value.category,
|
|
238
|
+
guardPost: camera.value.guardPost,
|
|
239
|
+
direction: camera.value.direction,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
emit("success", `${prop.title} added successfully!`);
|
|
244
|
+
} catch (error: any) {
|
|
245
|
+
emit("error", error.response?._data?.message || "Failed to add camera");
|
|
246
|
+
} finally {
|
|
247
|
+
disable.value = false;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const guardPostOptions = computed(() => {
|
|
252
|
+
const items = [];
|
|
253
|
+
|
|
254
|
+
for (let index = 0; index < prop.guardPosts; index++) {
|
|
255
|
+
items.push({
|
|
256
|
+
title: `Guard House ${index + 1}`,
|
|
257
|
+
value: index + 1,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return items;
|
|
262
|
+
});
|
|
263
|
+
</script>
|
|
264
|
+
<style scoped></style>
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-row no-gutters>
|
|
3
|
+
<v-col cols="12">
|
|
4
|
+
<v-card width="100%" variant="outlined" border="thin" rounded="lg">
|
|
5
|
+
<v-toolbar density="compact" color="grey-lighten-4 pl-2 pr-4">
|
|
6
|
+
<template #prepend>
|
|
7
|
+
<v-btn fab icon density="comfortable" @click="getCameraRefresh()">
|
|
8
|
+
<v-icon>mdi-refresh</v-icon>
|
|
9
|
+
</v-btn>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<template #append>
|
|
13
|
+
<v-btn
|
|
14
|
+
variant="flat"
|
|
15
|
+
color="primary"
|
|
16
|
+
class="text-none"
|
|
17
|
+
@click="dialogAdd = true"
|
|
18
|
+
>
|
|
19
|
+
Add
|
|
20
|
+
</v-btn>
|
|
21
|
+
</template>
|
|
22
|
+
</v-toolbar>
|
|
23
|
+
|
|
24
|
+
<v-card-text class="pa-0 bg-red">
|
|
25
|
+
<v-data-table
|
|
26
|
+
:headers="prop.headers"
|
|
27
|
+
:items="items"
|
|
28
|
+
fixed-header
|
|
29
|
+
hide-default-footer
|
|
30
|
+
hide-default-header
|
|
31
|
+
@click:row="handleRowClick"
|
|
32
|
+
style="max-height: 300px"
|
|
33
|
+
>
|
|
34
|
+
</v-data-table>
|
|
35
|
+
</v-card-text>
|
|
36
|
+
|
|
37
|
+
<v-toolbar density="compact" color="grey-lighten-4">
|
|
38
|
+
<template #append>
|
|
39
|
+
<v-row no-gutters justify="end" align="center">
|
|
40
|
+
<span class="mr-2 text-caption text-font gray">
|
|
41
|
+
{{ pageRange }}
|
|
42
|
+
</span>
|
|
43
|
+
<local-pagination
|
|
44
|
+
v-model="page"
|
|
45
|
+
:length="pages"
|
|
46
|
+
@update:value="$emit('update:value', $event)"
|
|
47
|
+
/>
|
|
48
|
+
</v-row>
|
|
49
|
+
</template>
|
|
50
|
+
</v-toolbar>
|
|
51
|
+
</v-card>
|
|
52
|
+
</v-col>
|
|
53
|
+
|
|
54
|
+
<!-- dialog -->
|
|
55
|
+
<v-dialog v-model="dialogAdd" persistent width="450">
|
|
56
|
+
<CameraForm
|
|
57
|
+
title="Add Camera"
|
|
58
|
+
:site="prop.site"
|
|
59
|
+
:guard-posts="prop.guardPosts"
|
|
60
|
+
:type="prop.type"
|
|
61
|
+
@cancel="dialogAdd = false"
|
|
62
|
+
@success="handleSuccess"
|
|
63
|
+
/>
|
|
64
|
+
</v-dialog>
|
|
65
|
+
|
|
66
|
+
<v-dialog v-model="dialogEdit" persistent width="450">
|
|
67
|
+
<CameraForm
|
|
68
|
+
title="Edit Camera"
|
|
69
|
+
:site="prop.site"
|
|
70
|
+
:guard-posts="prop.guardPosts"
|
|
71
|
+
:type="prop.type"
|
|
72
|
+
@cancel="dialogEdit = false"
|
|
73
|
+
@success="handleSuccess"
|
|
74
|
+
mode="edit"
|
|
75
|
+
:camera="camera"
|
|
76
|
+
/>
|
|
77
|
+
</v-dialog>
|
|
78
|
+
|
|
79
|
+
<v-dialog v-model="dialogPreview" persistent width="540">
|
|
80
|
+
<v-card width="100%">
|
|
81
|
+
<v-toolbar>
|
|
82
|
+
<v-row no-gutters class="fill-height px-6" align="center">
|
|
83
|
+
<span class="font-weight-bold text-h5 text-capitalize">
|
|
84
|
+
Preview
|
|
85
|
+
</span>
|
|
86
|
+
</v-row>
|
|
87
|
+
</v-toolbar>
|
|
88
|
+
|
|
89
|
+
<v-card-text
|
|
90
|
+
style="max-height: 100vh; overflow-y: auto"
|
|
91
|
+
class="pa-5 my-5 px-7"
|
|
92
|
+
>
|
|
93
|
+
<v-row no-gutters>
|
|
94
|
+
<v-col cols="12" class="mb-2">
|
|
95
|
+
Host:
|
|
96
|
+
<span class="font-weight-bold">
|
|
97
|
+
{{ camera.host }}
|
|
98
|
+
</span>
|
|
99
|
+
</v-col>
|
|
100
|
+
|
|
101
|
+
<v-col cols="12" class="mb-2">
|
|
102
|
+
Username:
|
|
103
|
+
<span class="font-weight-bold">
|
|
104
|
+
{{ camera.username }}
|
|
105
|
+
</span>
|
|
106
|
+
</v-col>
|
|
107
|
+
|
|
108
|
+
<v-col cols="12" class="mb-2">
|
|
109
|
+
Password:
|
|
110
|
+
<span class="font-weight-bold">
|
|
111
|
+
{{ camera.password }}
|
|
112
|
+
</span>
|
|
113
|
+
</v-col>
|
|
114
|
+
|
|
115
|
+
<v-col cols="12" class="mb-2">
|
|
116
|
+
Type:
|
|
117
|
+
<span class="font-weight-bold">
|
|
118
|
+
{{ camera.type }}
|
|
119
|
+
</span>
|
|
120
|
+
</v-col>
|
|
121
|
+
|
|
122
|
+
<v-col cols="12" class="mb-2">
|
|
123
|
+
Category:
|
|
124
|
+
<span class="font-weight-bold">
|
|
125
|
+
{{ camera.category }}
|
|
126
|
+
</span>
|
|
127
|
+
</v-col>
|
|
128
|
+
|
|
129
|
+
<v-col v-if="camera.type === 'anpr'" cols="12" class="mb-2">
|
|
130
|
+
Direction:
|
|
131
|
+
<span class="font-weight-bold">
|
|
132
|
+
{{ camera.direction }}
|
|
133
|
+
</span>
|
|
134
|
+
</v-col>
|
|
135
|
+
|
|
136
|
+
<v-col v-if="camera.type === 'anpr'" cols="12">
|
|
137
|
+
Guard House:
|
|
138
|
+
<span class="font-weight-bold">
|
|
139
|
+
{{ camera.guardPost }}
|
|
140
|
+
</span>
|
|
141
|
+
</v-col>
|
|
142
|
+
</v-row>
|
|
143
|
+
</v-card-text>
|
|
144
|
+
|
|
145
|
+
<v-toolbar class="pa-0" density="compact">
|
|
146
|
+
<v-row no-gutters>
|
|
147
|
+
<v-col cols="6" class="pa-0">
|
|
148
|
+
<v-btn
|
|
149
|
+
block
|
|
150
|
+
variant="text"
|
|
151
|
+
class="text-none"
|
|
152
|
+
size="large"
|
|
153
|
+
@click="dialogPreview = false"
|
|
154
|
+
height="48"
|
|
155
|
+
>
|
|
156
|
+
Close
|
|
157
|
+
</v-btn>
|
|
158
|
+
</v-col>
|
|
159
|
+
|
|
160
|
+
<v-col cols="6" class="pa-0">
|
|
161
|
+
<v-menu>
|
|
162
|
+
<template #activator="{ props }">
|
|
163
|
+
<v-btn
|
|
164
|
+
block
|
|
165
|
+
variant="flat"
|
|
166
|
+
color="black"
|
|
167
|
+
class="text-none"
|
|
168
|
+
height="48"
|
|
169
|
+
v-bind="props"
|
|
170
|
+
tile
|
|
171
|
+
>
|
|
172
|
+
More actions
|
|
173
|
+
</v-btn>
|
|
174
|
+
</template>
|
|
175
|
+
|
|
176
|
+
<v-list class="pa-0">
|
|
177
|
+
<v-list-item @click="openDialogEdit()">
|
|
178
|
+
<v-list-item-title class="text-subtitle-2">
|
|
179
|
+
Edit Building
|
|
180
|
+
</v-list-item-title>
|
|
181
|
+
</v-list-item>
|
|
182
|
+
|
|
183
|
+
<v-list-item @click="openDialogDelete()" class="text-red">
|
|
184
|
+
<v-list-item-title class="text-subtitle-2">
|
|
185
|
+
Delete Building
|
|
186
|
+
</v-list-item-title>
|
|
187
|
+
</v-list-item>
|
|
188
|
+
</v-list>
|
|
189
|
+
</v-menu>
|
|
190
|
+
</v-col>
|
|
191
|
+
</v-row>
|
|
192
|
+
</v-toolbar>
|
|
193
|
+
</v-card>
|
|
194
|
+
</v-dialog>
|
|
195
|
+
|
|
196
|
+
<v-dialog v-model="dialogDelete" persistent width="540">
|
|
197
|
+
<v-card width="100%">
|
|
198
|
+
<v-card-text
|
|
199
|
+
style="max-height: 100vh; overflow-y: auto"
|
|
200
|
+
class="pa-5 my-5 px-7 text-center"
|
|
201
|
+
>
|
|
202
|
+
Are you sure want to delete this {{ camera.type }} camera?
|
|
203
|
+
</v-card-text>
|
|
204
|
+
|
|
205
|
+
<v-toolbar class="pa-0" density="compact">
|
|
206
|
+
<v-row no-gutters>
|
|
207
|
+
<v-col cols="6" class="pa-0">
|
|
208
|
+
<v-btn
|
|
209
|
+
block
|
|
210
|
+
variant="text"
|
|
211
|
+
class="text-none"
|
|
212
|
+
size="large"
|
|
213
|
+
tile
|
|
214
|
+
@click="dialogDelete = false"
|
|
215
|
+
height="48"
|
|
216
|
+
>
|
|
217
|
+
Cancel
|
|
218
|
+
</v-btn>
|
|
219
|
+
</v-col>
|
|
220
|
+
|
|
221
|
+
<v-col cols="6" class="pa-0">
|
|
222
|
+
<v-btn
|
|
223
|
+
block
|
|
224
|
+
tile
|
|
225
|
+
variant="flat"
|
|
226
|
+
class="text-none"
|
|
227
|
+
size="large"
|
|
228
|
+
height="48"
|
|
229
|
+
color="black"
|
|
230
|
+
@click="submitDelete()"
|
|
231
|
+
>
|
|
232
|
+
Delete
|
|
233
|
+
</v-btn>
|
|
234
|
+
</v-col>
|
|
235
|
+
</v-row>
|
|
236
|
+
</v-toolbar>
|
|
237
|
+
</v-card>
|
|
238
|
+
</v-dialog>
|
|
239
|
+
</v-row>
|
|
240
|
+
</template>
|
|
241
|
+
|
|
242
|
+
<script setup lang="ts">
|
|
243
|
+
import type { PropType } from "vue";
|
|
244
|
+
import useSiteSettings from "../composables/useSiteSettings";
|
|
245
|
+
|
|
246
|
+
const events = defineEmits(["update:value", "row-click"]);
|
|
247
|
+
|
|
248
|
+
const prop = defineProps({
|
|
249
|
+
site: {
|
|
250
|
+
type: String,
|
|
251
|
+
required: true,
|
|
252
|
+
default: "site",
|
|
253
|
+
},
|
|
254
|
+
type: {
|
|
255
|
+
type: String as PropType<TSiteCamera["type"]>,
|
|
256
|
+
default: "anpr",
|
|
257
|
+
},
|
|
258
|
+
guardPosts: {
|
|
259
|
+
type: Number,
|
|
260
|
+
default: 0,
|
|
261
|
+
},
|
|
262
|
+
headers: {
|
|
263
|
+
type: Array as PropType<Array<any>>,
|
|
264
|
+
default: () => [
|
|
265
|
+
{ text: "Host", value: "host" },
|
|
266
|
+
{ text: "Category", value: "category" },
|
|
267
|
+
{ text: "Guard House", value: "guardPost" },
|
|
268
|
+
{ text: "Actions", value: "action", sortable: false },
|
|
269
|
+
],
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
const items = ref<Array<TCamera>>([]);
|
|
274
|
+
const page = ref(1);
|
|
275
|
+
const pages = ref(0);
|
|
276
|
+
const pageRange = ref("-- - -- of --");
|
|
277
|
+
|
|
278
|
+
const { getAllSiteCameras, deleteSiteCameraById } = useSiteSettings();
|
|
279
|
+
const { data: getCameraReq, refresh: getCameraRefresh } =
|
|
280
|
+
await useLazyAsyncData(
|
|
281
|
+
`get-site-${prop.site}-${prop.type}-cameras`,
|
|
282
|
+
() =>
|
|
283
|
+
getAllSiteCameras({ site: prop.site, type: prop.type, page: page.value }),
|
|
284
|
+
{
|
|
285
|
+
watch: [page],
|
|
286
|
+
}
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
watchEffect(() => {
|
|
290
|
+
if (getCameraReq.value) {
|
|
291
|
+
items.value = getCameraReq.value.items;
|
|
292
|
+
pageRange.value = getCameraReq.value.pageRange;
|
|
293
|
+
pages.value = getCameraReq.value.pages;
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const dialogAdd = ref(false);
|
|
298
|
+
const dialogEdit = ref(false);
|
|
299
|
+
const dialogPreview = ref(false);
|
|
300
|
+
const dialogDelete = ref(false);
|
|
301
|
+
|
|
302
|
+
function openDialogEdit() {
|
|
303
|
+
dialogEdit.value = true;
|
|
304
|
+
|
|
305
|
+
if (dialogPreview.value) dialogPreview.value = false;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function openDialogDelete() {
|
|
309
|
+
dialogDelete.value = true;
|
|
310
|
+
|
|
311
|
+
if (dialogPreview.value) dialogPreview.value = false;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function handleSuccess() {
|
|
315
|
+
if (dialogAdd.value) dialogAdd.value = false;
|
|
316
|
+
|
|
317
|
+
if (dialogEdit.value) dialogEdit.value = false;
|
|
318
|
+
|
|
319
|
+
if (dialogPreview.value) dialogPreview.value = false;
|
|
320
|
+
|
|
321
|
+
if (dialogDelete.value) dialogDelete.value = false;
|
|
322
|
+
|
|
323
|
+
getCameraRefresh();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const camera = ref<TSiteCamera>({
|
|
327
|
+
site: "",
|
|
328
|
+
host: "",
|
|
329
|
+
username: "",
|
|
330
|
+
password: "",
|
|
331
|
+
type: "ip",
|
|
332
|
+
category: "standard",
|
|
333
|
+
direction: "none",
|
|
334
|
+
guardPost: null,
|
|
335
|
+
status: "active",
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
function handleRowClick(_: any, data: any) {
|
|
339
|
+
dialogPreview.value = true;
|
|
340
|
+
camera.value = JSON.parse(JSON.stringify(data.item));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
async function submitDelete() {
|
|
344
|
+
try {
|
|
345
|
+
await deleteSiteCameraById(camera.value._id ?? "");
|
|
346
|
+
await getCameraRefresh();
|
|
347
|
+
dialogDelete.value = false;
|
|
348
|
+
} catch (error) {
|
|
349
|
+
console.error("Error deleting camera:", error);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
</script>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-card width="100%" :disabled="loading" :loading="loading">
|
|
3
|
+
<v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-5 my-5 px-7 text-center">
|
|
4
|
+
<span> {{ promptTitle }}</span>
|
|
5
|
+
|
|
6
|
+
<span v-if="message" class="text-error mt-2">
|
|
7
|
+
{{ message }} Do you want to delete anyway?
|
|
8
|
+
</span>
|
|
9
|
+
</v-card-text>
|
|
10
|
+
|
|
11
|
+
<v-toolbar class="pa-0" density="compact">
|
|
12
|
+
<v-row no-gutters>
|
|
13
|
+
<v-col cols="6" class="pa-0">
|
|
14
|
+
<v-btn block variant="text" class="text-none" size="large" tile @click="emit('close')"
|
|
15
|
+
height="48">
|
|
16
|
+
Cancel
|
|
17
|
+
</v-btn>
|
|
18
|
+
</v-col>
|
|
19
|
+
|
|
20
|
+
<v-col cols="6" class="pa-0">
|
|
21
|
+
<v-btn block tile variant="flat" class="text-none" size="large" height="48" color="black"
|
|
22
|
+
@click="emit('delete')">
|
|
23
|
+
Delete
|
|
24
|
+
</v-btn>
|
|
25
|
+
</v-col>
|
|
26
|
+
</v-row>
|
|
27
|
+
</v-toolbar>
|
|
28
|
+
</v-card>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script setup lang="ts">
|
|
32
|
+
const props = defineProps({
|
|
33
|
+
message: {
|
|
34
|
+
type: String,
|
|
35
|
+
default: ""
|
|
36
|
+
},
|
|
37
|
+
promptTitle: {
|
|
38
|
+
type: String,
|
|
39
|
+
default: "Are you sure want to delete this? "
|
|
40
|
+
},
|
|
41
|
+
loading: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
default: false
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const emit = defineEmits(["close", "delete"])
|
|
48
|
+
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<style scoped></style>
|