@iservice365/layer-common 1.5.7 → 1.7.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.
@@ -24,7 +24,7 @@
24
24
  >
25
25
  <v-toolbar density="compact" color="grey-lighten-4">
26
26
  <template #prepend>
27
- <v-btn fab icon density="comfortable" @click="">
27
+ <v-btn fab icon density="comfortable" @click="getDocuments">
28
28
  <v-icon>mdi-refresh</v-icon>
29
29
  </v-btn>
30
30
  </template>
@@ -37,7 +37,7 @@
37
37
  <local-pagination
38
38
  v-model="page"
39
39
  :length="pages"
40
- @update:value=""
40
+ @update:value="getDocuments"
41
41
  />
42
42
  </v-row>
43
43
  </template>
@@ -60,6 +60,154 @@
60
60
  <v-dialog v-model="createDialog" width="450" persistent>
61
61
  <DocumentForm @cancel="createDialog = false" @success="successCreate()" />
62
62
  </v-dialog>
63
+
64
+ <!-- Edit Dialog -->
65
+ <v-dialog v-model="editDialog" width="450" persistent>
66
+ <DocumentForm
67
+ mode="edit"
68
+ @cancel="editDialog = false"
69
+ @success="successUpdate()"
70
+ :document="selectedDocument"
71
+ />
72
+ </v-dialog>
73
+
74
+ <!-- Preview Dialog -->
75
+ <v-dialog v-model="previewDialog" width="450" persistent>
76
+ <v-card width="100%">
77
+ <v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0">
78
+ <v-row no-gutters class="mb-4">
79
+ <v-col cols="12">
80
+ <strong>Name:</strong> {{ selectedDocument?.name ?? "N/A" }}
81
+ </v-col>
82
+
83
+ <v-col cols="12">
84
+ <strong>Document: </strong>
85
+ <NuxtLink
86
+ :to="getFileUrl(selectedDocument.attachment)"
87
+ external
88
+ target="_blank"
89
+ >
90
+ View Document
91
+ </NuxtLink>
92
+ </v-col>
93
+ </v-row>
94
+ </v-card-text>
95
+ <v-toolbar class="pa-0" density="compact">
96
+ <v-row no-gutters>
97
+ <v-col cols="6" class="pa-0">
98
+ <v-btn
99
+ block
100
+ variant="text"
101
+ class="text-none"
102
+ size="large"
103
+ @click="previewDialog = false"
104
+ height="48"
105
+ >
106
+ Close
107
+ </v-btn>
108
+ </v-col>
109
+ <v-col cols="6" class="pa-0" v-if="canUpdate">
110
+ <v-menu>
111
+ <template #activator="{ props }">
112
+ <v-btn
113
+ block
114
+ variant="flat"
115
+ color="black"
116
+ class="text-none"
117
+ height="48"
118
+ v-bind="props"
119
+ tile
120
+ :disabled="!canUpdateDocument && !canDeleteDocument"
121
+ >
122
+ More actions
123
+ </v-btn>
124
+ </template>
125
+ <v-list class="pa-0">
126
+ <v-list-item
127
+ v-if="canUpdateDocument"
128
+ @click="openEditDialog()"
129
+ >
130
+ <v-list-item-title class="text-subtitle-2">
131
+ Edit Document
132
+ </v-list-item-title>
133
+ </v-list-item>
134
+
135
+ <v-list-item
136
+ v-if="canDeleteDocument"
137
+ @click="openDeleteDialog()"
138
+ class="text-red"
139
+ >
140
+ <v-list-item-title class="text-subtitle-2">
141
+ Delete Document
142
+ </v-list-item-title>
143
+ </v-list-item>
144
+ </v-list>
145
+ </v-menu>
146
+ </v-col>
147
+ </v-row>
148
+ </v-toolbar>
149
+ </v-card>
150
+ </v-dialog>
151
+
152
+ <!-- Delete Dialog -->
153
+ <v-dialog
154
+ v-model="confirmDialog"
155
+ :loading="deleteLoading"
156
+ width="450"
157
+ persistent
158
+ >
159
+ <v-card width="100%">
160
+ <v-toolbar density="compact" class="pl-4">
161
+ <span class="font-weight-medium text-h5">Delete Document</span>
162
+ </v-toolbar>
163
+ <v-card-text>
164
+ <p class="text-subtitle-2 text-center">
165
+ Are you sure you want to delete this document? This action cannot be
166
+ undone.
167
+ </p>
168
+
169
+ <v-row v-if="message" no-gutters justify="center" class="mt-4">
170
+ <span class="text-caption text-error text-center">
171
+ {{ message }}
172
+ </span>
173
+ </v-row>
174
+ </v-card-text>
175
+
176
+ <v-toolbar density="compact">
177
+ <v-row no-gutters>
178
+ <v-col cols="6">
179
+ <v-btn
180
+ tile
181
+ block
182
+ size="48"
183
+ variant="text"
184
+ class="text-none"
185
+ @click="confirmDialog = false"
186
+ :disabled="deleteLoading"
187
+ >
188
+ Close
189
+ </v-btn>
190
+ </v-col>
191
+ <v-col cols="6">
192
+ <v-btn
193
+ tile
194
+ block
195
+ size="48"
196
+ color="black"
197
+ variant="flat"
198
+ class="text-none"
199
+ @click="handleDeleteDocument"
200
+ :loading="deleteLoading"
201
+ >
202
+ Delete Document
203
+ </v-btn>
204
+ </v-col>
205
+ </v-row>
206
+ </v-toolbar>
207
+ </v-card>
208
+ </v-dialog>
209
+
210
+ <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
63
211
  </v-row>
64
212
  </template>
65
213
  <script setup lang="ts">
@@ -105,7 +253,8 @@ const props = defineProps({
105
253
  });
106
254
 
107
255
  const { headerSearch } = useLocal();
108
- const { getAll: _getAllDocuments } = useDocument();
256
+ const { getAll: _getAllDocuments, deleteById } = useDocument();
257
+ const { getFileUrl } = useFile();
109
258
 
110
259
  const page = ref(1);
111
260
  const pages = ref(0);
@@ -149,8 +298,11 @@ const previewDialog = ref(false);
149
298
  const selectedDocument = ref<TDocument>({
150
299
  _id: "",
151
300
  name: "",
152
- attachment: [],
301
+ attachment: "",
153
302
  });
303
+ const deleteLoading = ref(false);
304
+ const confirmDialog = ref(false);
305
+ const selectedDocumentId = ref<string | null>(null);
154
306
 
155
307
  function tableRowClickHandler(_: any, data: any) {
156
308
  selectedDocument.value = data.item as TDocument;
@@ -184,4 +336,36 @@ function successCreate() {
184
336
  getDocuments();
185
337
  showMessage("Document created successfully!", "success");
186
338
  }
339
+
340
+ function openDeleteDialog() {
341
+ confirmDialog.value = true;
342
+ message.value = "";
343
+ }
344
+
345
+ function openEditDialog() {
346
+ editDialog.value = true;
347
+ }
348
+
349
+ async function handleDeleteDocument() {
350
+ deleteLoading.value = true;
351
+ try {
352
+ await deleteById(selectedDocument.value._id ?? "");
353
+ await getDocuments();
354
+ selectedDocumentId.value = null;
355
+ confirmDialog.value = false;
356
+ previewDialog.value = false;
357
+ } catch (error: any) {
358
+ message.value =
359
+ error?.response?._data?.message || "Failed to delete document";
360
+ } finally {
361
+ deleteLoading.value = false;
362
+ }
363
+ }
364
+
365
+ function successUpdate() {
366
+ editDialog.value = false;
367
+ previewDialog.value = false;
368
+ getDocuments();
369
+ showMessage("Document updated successfully!", "success");
370
+ };
187
371
  </script>
@@ -1,23 +1,30 @@
1
1
  <template>
2
- <ClientOnly>
3
- <v-row no-gutters class="ckeditor-container w-100">
4
- <ckeditor v-model="data" :editor="ClassicEditor" :config="config" />
5
- </v-row>
6
- </ClientOnly>
2
+ <ClientOnly>
3
+ <v-row no-gutters class="ckeditor-container w-100">
4
+ <ckeditor v-model="data" :editor="ClassicEditor" :config="config" @ready="onReady" :key="prop.readOnly" />
5
+ </v-row>
6
+ </ClientOnly>
7
7
  </template>
8
8
 
9
9
  <script setup>
10
+
11
+ const prop = defineProps({
12
+ readOnly: {
13
+ type: Boolean,
14
+ required: false
15
+ }
16
+ })
10
17
  import {
11
- ClassicEditor,
12
- Essentials,
13
- Paragraph,
14
- Bold,
15
- Italic,
16
- Heading,
17
- List,
18
- Link,
19
- Alignment,
20
- Font
18
+ ClassicEditor,
19
+ Essentials,
20
+ Paragraph,
21
+ Bold,
22
+ Italic,
23
+ Heading,
24
+ List,
25
+ Link,
26
+ Alignment,
27
+ Font,
21
28
  } from 'ckeditor5'
22
29
  import { Ckeditor } from '@ckeditor/ckeditor5-vue'
23
30
  import 'ckeditor5/ckeditor5.css';
@@ -26,17 +33,45 @@ import 'ckeditor5/ckeditor5.css'
26
33
 
27
34
  const data = defineModel({ required: true, default: "" })
28
35
 
36
+ const editorInstance = ref(null);
37
+
29
38
  const config = computed(() => ({
30
- licenseKey: 'GPL',
31
- plugins: [Essentials, Paragraph, Bold, Italic, Heading, List, Alignment, Font],
32
- toolbar: [
33
- 'undo', 'redo',
34
- '|', 'bold', 'italic',
35
- '|', 'fontSize', 'fontColor', 'fontBackgroundColor',
36
- '|', 'bulletedList', 'numberedList',
37
- '|', 'heading', '|', 'alignment:left', 'alignment:center', 'alignment:right', 'alignment:justify',
38
- ]
39
+ licenseKey: 'GPL',
40
+ plugins: [Essentials, Paragraph, Bold, Italic, Heading, List, Alignment, Font],
41
+ toolbar: [
42
+ 'undo', 'redo',
43
+ '|', 'bold', 'italic',
44
+ '|', 'fontSize', 'fontColor', 'fontBackgroundColor',
45
+ '|', 'bulletedList', 'numberedList',
46
+ '|', 'heading', '|', 'alignment:left', 'alignment:center', 'alignment:right', 'alignment:justify',
47
+ ],
39
48
  }))
49
+
50
+
51
+ function onReady(editor) {
52
+ editorInstance.value = editor;
53
+ toggleReadOnly(prop.readOnly);
54
+ }
55
+
56
+ function toggleReadOnly(isReadOnly) {
57
+ if (!editorInstance.value) return;
58
+
59
+
60
+ if (isReadOnly) {
61
+ editorInstance.value.enableReadOnlyMode("view-mode-lock");
62
+ } else {
63
+ editorInstance.value.disableReadOnlyMode("view-mode-lock");
64
+ }
65
+ }
66
+
67
+ watch(
68
+ () => prop.readOnly,
69
+ (newVal) => {
70
+ toggleReadOnly(newVal);
71
+ }
72
+ );
73
+
74
+
40
75
  </script>
41
76
 
42
77
  <style scoped>
@@ -58,4 +93,3 @@ const config = computed(() => ({
58
93
  box-sizing: border-box;
59
94
  }
60
95
  </style>
61
-
@@ -0,0 +1,231 @@
1
+ <template>
2
+ <v-row no-gutters class="">
3
+ <v-col cols="12" elevation="3" class="border">
4
+ <v-row no-gutters class="px-6 pt-4">
5
+ <div class="d-flex mt-7 pb-5">
6
+ <p class="mr-6 font-weight-medium flex-grow-1">
7
+ Physical / Key Pass
8
+ <span class="d-block text-caption text-grey-darken-1 mt-1">
9
+ A Physical Pass Card is a tangible identification or access card
10
+ used for entry and verification purposes at a specific site or
11
+ property. Its primary functions include granting authorized
12
+ access, enhancing security, and tracking attendance or movement.
13
+ </span>
14
+ </p>
15
+ <v-switch color="success" hide-details></v-switch>
16
+ </div>
17
+ <v-divider thickness="1"></v-divider>
18
+ <div class="d-flex mt-7 pb-5">
19
+ <p class="mr-6 font-weight-medium flex-grow-1">
20
+ NFC / QR Code Pass
21
+ <span class="d-block text-caption text-grey-darken-1 mt-1">
22
+ NFC Card Pass is a type of access card that uses Near Field
23
+ Communication (NFC) technology to enable secure and convenient
24
+ entry to a site or property. This technology facilitates wireless
25
+ communication between the card and an NFC reader when they are
26
+ placed in close proximity (typically within 4 cm).
27
+ </span>
28
+ </p>
29
+ <v-switch color="success" hide-details></v-switch>
30
+ </div>
31
+ <v-divider thickness="1"></v-divider>
32
+ <div class="d-flex w-100 mt-7 pb-10">
33
+ <p class="mr-6 font-weight-medium flex-grow-1">
34
+ Upload Access Cards Template
35
+ <span class="d-block text-caption text-grey-darken-1 mt-1">
36
+ <a
37
+ target="_blank"
38
+ class="text-truncate d-flex items-center text-decoration-none"
39
+ href=""
40
+ >
41
+ <v-icon class="mr-2" size="24px"> mdi-paperclip </v-icon>
42
+ template
43
+ </a>
44
+ </span>
45
+ </p>
46
+ <v-btn
47
+ variant="flat"
48
+ color="error"
49
+ size="small"
50
+ style="height: 40px; margin-left: auto"
51
+ prepend-icon="mdi-file-document-remove-outline"
52
+ >
53
+ Remove
54
+ </v-btn>
55
+ </div>
56
+ <v-divider thickness="1"></v-divider>
57
+ <div class="d-flex w-100 mt-7 pb-10">
58
+ <p class="mr-6 font-weight-medium flex-grow-1">
59
+ Printer Setup
60
+ <v-col cols="12">
61
+ <v-row>
62
+ <v-col cols="3">
63
+ <v-text-field
64
+ label="Vendor ID"
65
+ hide-details
66
+ clearable
67
+ ></v-text-field>
68
+ </v-col>
69
+ <v-col cols="3">
70
+ <v-text-field
71
+ label="Product ID"
72
+ hide-details
73
+ clearable
74
+ ></v-text-field>
75
+ </v-col>
76
+ <v-col cols="3">
77
+ <v-btn
78
+ color="primary"
79
+ variant="outlined"
80
+ prepend-icon="mdi-magnify"
81
+ block
82
+ >
83
+ Scan Printer
84
+ </v-btn>
85
+ </v-col>
86
+ <v-col cols="3">
87
+ <v-btn
88
+ color="success"
89
+ variant="outlined"
90
+ prepend-icon="mdi-printer-check"
91
+ block
92
+ >
93
+ Test & Print
94
+ </v-btn>
95
+ </v-col>
96
+ </v-row>
97
+ <v-row class="mt-4">
98
+ <v-col cols="12" sm="6" md="4">
99
+ <v-btn
100
+ color="primary"
101
+ variant="flat"
102
+ prepend-icon="mdi-content-save"
103
+ block
104
+ >
105
+ Save Printer Settings
106
+ </v-btn>
107
+ </v-col>
108
+ </v-row>
109
+ </v-col>
110
+ </p>
111
+ </div>
112
+
113
+ <v-divider thickness="1"></v-divider>
114
+
115
+ <div class="d-flex w-100 mt-7 pb-10">
116
+ <p class="mr-6 font-weight-medium flex-grow-1">
117
+ QR Code Template
118
+ <span class="d-block text-caption text-grey-darken-1 mt-1">
119
+ <v-col cols="12">
120
+ <v-row>
121
+ <v-col cols="12">
122
+ <v-text-field
123
+ label="Header"
124
+ placeholder="Enter qr code header eg. Welcome to Company Name"
125
+ hide-details
126
+ density="comfortable"
127
+ clearable
128
+ ></v-text-field>
129
+ </v-col>
130
+ <v-col cols="12">
131
+ <v-text-field
132
+ label="Subtext"
133
+ placeholder="Enter qr code sub header"
134
+ hide-details
135
+ density="comfortable"
136
+ clearable
137
+ class="mb-2"
138
+ ></v-text-field>
139
+ </v-col>
140
+ <v-row class="mt-3">
141
+ <v-col cols="12" md="2">
142
+ <v-btn color="primary" variant="flat" block>
143
+ Preview
144
+ </v-btn>
145
+ </v-col>
146
+ <v-col cols="12" md="2">
147
+ <v-btn color="primary" variant="flat" block> Save </v-btn>
148
+ </v-col>
149
+ </v-row>
150
+ </v-row>
151
+ </v-col>
152
+ </span>
153
+ </p>
154
+ </div>
155
+
156
+ <v-divider thickness="1"></v-divider>
157
+
158
+ <div class="d-flex w-100 mt-7 pb-10">
159
+ <p class="mr-6 font-weight-medium flex-grow-1">
160
+ Resident-app Disclaimer Message
161
+ <span class="d-block text-caption text-grey-darken-1 mt-1">
162
+ <v-col cols="12">
163
+ <v-row no-gutters>
164
+ <v-col cols="12" class="mb-5">
165
+ <v-textarea
166
+ label="Disclaimer Message"
167
+ placeholder="Enter disclaimer message for resident app"
168
+ hide-details
169
+ density="comfortable"
170
+ clearable
171
+ rows="5"
172
+ auto-grow
173
+ ></v-textarea>
174
+ </v-col>
175
+ <v-row class="mt-3">
176
+ <v-col cols="12" md="2">
177
+ <v-btn color="primary" variant="flat" block> Save </v-btn>
178
+ </v-col>
179
+ </v-row>
180
+ </v-row>
181
+ </v-col>
182
+ </span>
183
+ </p>
184
+ </div>
185
+
186
+ <v-divider thickness="1"></v-divider>
187
+
188
+ <div class="d-flex w-100 mt-7 pb-10">
189
+ <p class="mr-6 font-weight-medium flex-grow-1">
190
+ Entrypass URL
191
+ <span class="d-block text-caption text-grey-darken-1 mt-1">
192
+ <v-col>
193
+ <v-text-field
194
+ label="Enter entrypass URL"
195
+ placeholder="https://example.com"
196
+ outlined
197
+ clearable
198
+ hide-details
199
+ />
200
+ </v-col>
201
+ <v-col>
202
+ <v-btn color="primary">Save</v-btn>
203
+ </v-col>
204
+ </span>
205
+ </p>
206
+ </div>
207
+ </v-row>
208
+ </v-col></v-row
209
+ >
210
+ </template>
211
+ <script lang="ts" setup>
212
+ definePageMeta({
213
+ middleware: ["01-auth", "02-org"],
214
+ memberOnly: true,
215
+ });
216
+ const prop = defineProps({
217
+ site: {
218
+ type: String,
219
+ required: true,
220
+ },
221
+ siteName: {
222
+ type: String,
223
+ required: true,
224
+ },
225
+
226
+ orgId: {
227
+ type: String,
228
+ required: true,
229
+ },
230
+ });
231
+ </script>