@goweekdays/layer-common 1.3.0 → 1.3.2

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.
@@ -1,18 +1,15 @@
1
1
  <template>
2
2
  <v-row no-gutters>
3
- <v-col v-if="props.seatManagement !== 'index'" cols="12" class="mb-2">
3
+ <v-col cols="12" class="mb-2">
4
4
  <v-row no-gutters>
5
5
  <v-btn
6
- class="text-none"
6
+ class="text-none mr-2"
7
7
  rounded="pill"
8
8
  variant="tonal"
9
- :to="{
10
- name: props.seatManagement,
11
- params: { organization: props.orgId },
12
- }"
13
9
  size="large"
10
+ @click="setInvite()"
14
11
  >
15
- Manage seats
12
+ Invite
16
13
  </v-btn>
17
14
  </v-row>
18
15
  </v-col>
@@ -31,11 +28,7 @@
31
28
  <span class="mr-2 text-caption text-font gray">
32
29
  {{ pageRange }}
33
30
  </span>
34
- <local-pagination
35
- v-model="page"
36
- :length="pages"
37
- @update:value="getAll()"
38
- />
31
+ <local-pagination v-model="page" :length="pages" />
39
32
  </v-row>
40
33
  </template>
41
34
 
@@ -51,7 +44,7 @@
51
44
  name: props.route,
52
45
  params: setRouteParams({
53
46
  status: tab.status,
54
- organization: props.orgId,
47
+ org: props.orgId,
55
48
  }),
56
49
  }"
57
50
  >
@@ -66,166 +59,86 @@
66
59
  :items="items"
67
60
  item-value="_id"
68
61
  items-per-page="20"
69
- fixed-header
62
+ hide-default-header
70
63
  hide-default-footer
71
64
  style="max-height: calc(100vh - (126px))"
72
65
  :loading="loading"
66
+ @click:row="handleRowClick"
73
67
  >
74
- <template #item.nature="{ item }">
75
- {{ replaceMatch(item.nature, "_", " ") }}
76
- </template>
77
- <template #item.action-table="{ item }">
78
- <v-menu
79
- v-if="
80
- (status === 'active' &&
81
- (canSuspendMembers || canDeleteMembers)) ||
82
- (status === 'suspended' &&
83
- (canActivateMembers || canDeleteMembers))
84
- "
85
- v-model="item.menuOpen"
86
- offset-y
87
- width="150"
88
- >
89
- <template v-slot:activator="{ props }">
90
- <v-icon v-bind="props">mdi-dots-horizontal</v-icon>
91
- </template>
92
- <v-list>
93
- <v-list-item
94
- v-if="props.assignRole"
95
- @click="
96
- setMember({
97
- dialog: true,
98
- mode: 'assign-role',
99
- role: item,
100
- })
101
- "
102
- >
103
- Assign Role
104
- </v-list-item>
105
-
106
- <v-list-item
107
- v-if="status === 'active' && canSuspendMembers"
108
- @click="openUpdateDialog(item.user, 'suspended')"
109
- >
110
- Suspend
111
- </v-list-item>
112
- <v-list-item
113
- v-if="status === 'suspended' && canActivateMembers"
114
- @click="openUpdateDialog(item.user, 'active')"
115
- >
116
- Activate
117
- </v-list-item>
118
- <v-list-item
119
- v-if="canDeleteMembers"
120
- @click="openUpdateDialog(item.user, 'deleted')"
121
- >
122
- Delete
123
- </v-list-item>
124
- </v-list>
125
- </v-menu>
126
- </template>
127
68
  </v-data-table>
128
69
  </v-card>
129
70
  </v-col>
130
- <ConfirmDialog
131
- v-model="confirmDialog"
132
- :loading="updateLoading"
133
- @submit="handleUpdateMemberStatus"
134
- >
135
- <template #title>
136
- <span class="font-weight-medium text-h5">
137
- {{ updateActionText }} Member</span
138
- >
139
- </template>
140
71
 
141
- <template #description>
142
- <p class="text-subtitle-2">
143
- Are you sure you want to {{ updateActionText }} this Member? This
144
- action cannot be undone.
145
- </p>
146
- </template>
72
+ <v-dialog v-model="dialogInvite" width="450" persistent>
73
+ <MemberInvite
74
+ v-model="invitation"
75
+ :app="type"
76
+ :org="orgId"
77
+ :disabled="disabledInvite"
78
+ @cancel="setInvite(false)"
79
+ @submit="submitInvite()"
80
+ v-model:message="message"
81
+ />
82
+ </v-dialog>
147
83
 
148
- <template #footer>
149
- <v-btn
150
- variant="text"
151
- @click="confirmDialog = false"
152
- :disabled="updateLoading"
153
- >
154
- Close
155
- </v-btn>
156
- <v-btn
157
- color="primary"
158
- variant="flat"
159
- @click="handleUpdateMemberStatus"
160
- :loading="updateLoading"
161
- >
162
- {{ updateActionText }} Member
163
- </v-btn>
164
- </template>
165
- </ConfirmDialog>
166
-
167
- <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
168
-
169
- <v-dialog v-model="assignRoleDialog" max-width="400px">
170
- <v-card>
171
- <v-card-title class="text-h5">Assign Role</v-card-title>
172
- <v-card-text>
173
- <v-form v-model="memberRoleForm" @submit.prevent="updateMemberRole()">
174
- <v-row no-gutters>
175
- <v-col cols="12" class="mb-2">
176
- <v-row no-gutters>
177
- <InputLabel class="text-capitalize" title="Name" required />
178
- <v-col cols="12">
179
- <v-select
180
- v-model="selectedRole"
181
- :items="roles"
182
- item-value="_id"
183
- item-title="name"
184
- density="comfortable"
185
- :rules="[requiredRule]"
186
- :error-messages="
187
- selectedRole === selectedMemberRole
188
- ? 'Role already assigned'
189
- : ''
190
- "
191
- persistent-hint
192
- ></v-select>
193
- </v-col>
194
-
195
- <v-col cols="12" class="text-error text-center">
196
- {{ message }}
197
- </v-col>
198
- </v-row>
199
- </v-col>
200
-
201
- <v-col cols="12">
202
- <v-row>
203
- <v-col cols="6">
204
- <v-btn
205
- block
206
- variant="text"
207
- @click="setMember({ mode: 'assign-role' })"
208
- >
209
- Cancel
210
- </v-btn>
211
- </v-col>
212
- <v-col cols="6">
213
- <v-btn
214
- block
215
- variant="flat"
216
- color="black"
217
- :disabled="!memberRoleForm"
218
- type="submit"
219
- >
220
- Submit
221
- </v-btn>
222
- </v-col>
223
- </v-row>
224
- </v-col>
225
- </v-row>
226
- </v-form>
227
- </v-card-text>
228
- </v-card>
84
+ <v-dialog v-model="dialogView" width="450" persistent>
85
+ <MemberForm
86
+ title="View member details"
87
+ v-model="member"
88
+ mode="view"
89
+ @close="dialogView = false"
90
+ @assign="handleOpenAssignRole()"
91
+ @suspend="handleOpenSuspension()"
92
+ @activate="handleOpenActivation()"
93
+ @delete="handleOpenDelete()"
94
+ />
95
+ </v-dialog>
96
+
97
+ <v-dialog v-model="dialogAssignRole" width="450" persistent>
98
+ <MemberForm
99
+ title="Assign Role"
100
+ v-model="member"
101
+ mode="assign-role"
102
+ @cancel="dialogAssignRole = false"
103
+ @submit="submitAssignRole()"
104
+ :disabled="disabledAssignRole"
105
+ />
106
+ </v-dialog>
107
+
108
+ <v-dialog v-model="dialogSuspend" width="450" persistent>
109
+ <ConfirmationPrompt
110
+ title="Suspend Member"
111
+ action="Suspend Member"
112
+ content="Are you sure you want to suspend this member?"
113
+ @cancel="handleCancelSuspension()"
114
+ @confirm="submitStatus('suspended')"
115
+ v-model:message="message"
116
+ :disabled="disabledStatusChange"
117
+ />
118
+ </v-dialog>
119
+
120
+ <v-dialog v-model="dialogActive" width="450" persistent>
121
+ <ConfirmationPrompt
122
+ title="Unsuspend Member"
123
+ action="Unsuspend Member"
124
+ content="Are you sure you want to unsuspend this member?"
125
+ @cancel="handleCancelSuspension()"
126
+ @confirm="submitStatus('active')"
127
+ v-model:message="message"
128
+ :disabled="disabledStatusChange"
129
+ />
130
+ </v-dialog>
131
+
132
+ <v-dialog v-model="dialogDelete" width="450" persistent>
133
+ <ConfirmationPrompt
134
+ title="Remove Member"
135
+ action="Remove Member"
136
+ content="Are you sure you want to remove this member?"
137
+ @cancel="handleCancelDelete()"
138
+ @confirm="submitDelete()"
139
+ v-model:message="message"
140
+ :disabled="disabledDelete"
141
+ />
229
142
  </v-dialog>
230
143
  </v-row>
231
144
  </template>
@@ -250,7 +163,7 @@ const props = defineProps({
250
163
  },
251
164
  type: {
252
165
  type: String,
253
- default: "organization",
166
+ default: "org",
254
167
  },
255
168
  seatManagement: {
256
169
  type: String,
@@ -293,15 +206,6 @@ const props = defineProps({
293
206
 
294
207
  value: "roleName",
295
208
  },
296
- {
297
- title: "Organization",
298
-
299
- value: "orgName",
300
- },
301
- {
302
- title: "Action",
303
- value: "action-table",
304
- },
305
209
  ],
306
210
  },
307
211
  });
@@ -311,31 +215,35 @@ const page = ref(1);
311
215
  const pages = ref(10);
312
216
  const pageRange = ref("-- - -- of --");
313
217
 
314
- const message = ref("");
315
- const messageSnackbar = ref(false);
316
- const messageColor = ref("");
317
-
318
218
  const {
219
+ invitation,
220
+ member,
319
221
  getAll: _getAll,
320
- updateMemberStatus: _updateMemberStatus,
321
- updateMemberRole: _updateMemberRole,
222
+ updateStatusById: _updateStatusById,
223
+ updateRoleById: _updateRoleById,
224
+ deleteById: _deleteById,
322
225
  } = useMember();
323
226
 
324
227
  const { headerSearch } = useLocal();
325
- const { replaceMatch, setRouteParams, requiredRule } = useUtils();
228
+ const { setRouteParams } = useUtils();
326
229
 
327
230
  const {
328
231
  data: getAllReq,
329
232
  refresh: getAll,
330
233
  status: getAllReqStatus,
331
- } = useLazyAsyncData("get-all-members-by-status" + props.status, () =>
332
- _getAll({
333
- status: props.status,
334
- org: props.orgId,
335
- search: headerSearch.value,
336
- page: page.value,
337
- type: props.type,
338
- })
234
+ } = await useLazyAsyncData(
235
+ "get-all-members-by-status" + props.status,
236
+ () =>
237
+ _getAll({
238
+ status: props.status,
239
+ org: props.orgId,
240
+ search: headerSearch.value,
241
+ page: page.value,
242
+ app: props.type,
243
+ }),
244
+ {
245
+ watch: [headerSearch, page],
246
+ }
339
247
  );
340
248
 
341
249
  const loading = computed(() => getAllReqStatus.value === "pending");
@@ -348,105 +256,151 @@ watchEffect(() => {
348
256
  }
349
257
  });
350
258
 
351
- watch(headerSearch, () => {
352
- getAll();
353
- });
354
-
355
- const confirmDialog = ref(false);
356
- const selectedMemberId = ref<string | null>(null);
357
- const updateLoading = ref(false);
358
- const updateAction = ref("");
359
-
360
- const memberRoleForm = ref(false);
361
- const assignRoleDialog = ref(false);
362
- const selectedRole = ref<string | null>(null);
363
- const selectedMemberRole = ref("");
259
+ const dialogInvite = ref(false);
260
+ const dialogView = ref(false);
261
+ const modeMember = ref("");
262
+ const message = ref("");
364
263
 
365
264
  function setMember({
366
- dialog = false,
265
+ data = useMember().member.value,
367
266
  mode = "",
368
- role = {} as Record<string, any>,
267
+ dialog = true,
369
268
  } = {}) {
370
- if (mode === "assign-role") {
371
- assignRoleDialog.value = dialog;
269
+ dialogView.value = dialog;
270
+ Object.assign(member.value, JSON.parse(JSON.stringify(data)));
271
+ modeMember.value = mode;
272
+
273
+ if (mode === "view") {
274
+ dialogView.value = true;
372
275
  }
276
+ }
373
277
 
374
- selectedMemberId.value = role._id;
375
- selectedRole.value = role.role;
376
- selectedMemberRole.value = role.role;
278
+ function setInvite(dialog = true) {
279
+ dialogInvite.value = dialog;
280
+ Object.assign(
281
+ invitation.value,
282
+ JSON.parse(JSON.stringify(useMember().invitation.value))
283
+ );
377
284
  }
378
285
 
379
- const roles = ref<Array<Record<string, any>>>([]);
380
- const { getRoles } = useRole();
381
- const { data: getAllRoleReq } = useLazyAsyncData("get-roles", () =>
382
- getRoles({ org: props.orgId, type: props.type, limit: 20 })
383
- );
286
+ const disabledInvite = ref(false);
384
287
 
385
- watchEffect(() => {
386
- if (getAllRoleReq.value) {
387
- roles.value = getAllRoleReq.value.items;
288
+ const { inviteMember } = useVerification();
289
+
290
+ async function submitInvite() {
291
+ disabledInvite.value = true;
292
+ try {
293
+ await inviteMember({
294
+ app: props.type,
295
+ org: props.orgId,
296
+ email: invitation.value.email,
297
+ role: invitation.value.role,
298
+ });
299
+ await setInvite(false);
300
+ } catch (error: any) {
301
+ message.value = error.response._data.message || "An error occurred.";
302
+ } finally {
303
+ disabledInvite.value = false;
388
304
  }
389
- });
305
+ }
390
306
 
391
- watchEffect(() => {
392
- if (selectedRole.value) {
393
- message.value = "";
307
+ function handleRowClick(_: any, data: any) {
308
+ setMember({ data: data.item, mode: "view" });
309
+ }
310
+
311
+ const dialogAssignRole = ref(false);
312
+
313
+ const disabledAssignRole = ref(false);
314
+
315
+ function handleOpenAssignRole() {
316
+ dialogView.value = false;
317
+ dialogAssignRole.value = true;
318
+ }
319
+
320
+ async function submitAssignRole() {
321
+ disabledAssignRole.value = true;
322
+ try {
323
+ await _updateRoleById(member.value._id ?? "", member.value.role);
324
+ await getAll();
325
+ dialogAssignRole.value = false;
326
+ setMember({ dialog: false });
327
+ } catch (error: any) {
328
+ message.value = error.response._data.message || "An error occurred.";
329
+ } finally {
330
+ disabledAssignRole.value = false;
394
331
  }
395
- });
332
+ }
333
+
334
+ const dialogSuspend = ref(false);
335
+
336
+ function handleOpenSuspension() {
337
+ dialogView.value = false;
338
+ dialogSuspend.value = true;
339
+ }
340
+
341
+ function handleCancelSuspension() {
342
+ dialogSuspend.value = false;
343
+ setMember({ dialog: false });
344
+ }
345
+
346
+ const dialogActive = ref(false);
347
+
348
+ function handleOpenActivation() {
349
+ dialogView.value = false;
350
+ dialogActive.value = true;
351
+ }
396
352
 
397
- async function updateMemberRole() {
353
+ function handleCancelActivation() {
354
+ dialogActive.value = false;
355
+ setMember({ dialog: false });
356
+ }
357
+
358
+ const disabledStatusChange = ref(false);
359
+
360
+ async function submitStatus(status = "") {
361
+ disabledStatusChange.value = true;
398
362
  try {
399
- await _updateMemberRole(
400
- selectedMemberId.value ?? "",
401
- selectedRole.value ?? "",
402
- props.type,
403
- props.orgId
404
- );
405
- await setMember({ mode: "assign-role" });
363
+ await _updateStatusById(member.value._id ?? "", status);
406
364
  await getAll();
365
+ if (status === "suspended") {
366
+ dialogSuspend.value = false;
367
+ }
368
+ if (status === "active") {
369
+ dialogActive.value = false;
370
+ }
371
+ setMember({ dialog: false });
407
372
  } catch (error: any) {
408
- message.value = error?.response?._data?.message || "Failed to update role";
373
+ message.value = error.response._data.message || "An error occurred.";
374
+ } finally {
375
+ disabledStatusChange.value = false;
409
376
  }
410
377
  }
411
378
 
412
- function openUpdateDialog(id: string, action: string) {
413
- updateAction.value = action;
414
- selectedMemberId.value = id;
415
- confirmDialog.value = true;
379
+ const dialogDelete = ref(false);
380
+
381
+ function handleOpenDelete() {
382
+ dialogView.value = false;
383
+ dialogDelete.value = true;
416
384
  }
417
385
 
418
- function showMessage(msg: string, color: string) {
419
- message.value = msg;
420
- messageColor.value = color;
421
- messageSnackbar.value = true;
386
+ function handleCancelDelete() {
387
+ dialogDelete.value = false;
388
+ setMember({ dialog: false });
422
389
  }
423
390
 
424
- async function handleUpdateMemberStatus() {
425
- if (!selectedMemberId.value) return;
426
- updateLoading.value = true;
391
+ const disabledDelete = ref(false);
392
+
393
+ async function submitDelete() {
394
+ disabledDelete.value = true;
427
395
  try {
428
- const res = await _updateMemberStatus(
429
- selectedMemberId.value,
430
- updateAction.value
431
- );
432
-
433
- confirmDialog.value = false;
434
- showMessage(res.message, "success");
435
- getAll();
396
+ await _deleteById(member.value._id ?? "");
397
+ await getAll();
398
+ dialogDelete.value = false;
399
+ setMember({ dialog: false });
436
400
  } catch (error: any) {
437
- const errorMessage = error?.response?._data?.message;
438
- showMessage(errorMessage, "error");
401
+ message.value = error.response._data.message || "An error occurred.";
439
402
  } finally {
440
- updateLoading.value = false;
441
- selectedMemberId.value = null;
403
+ disabledDelete.value = false;
442
404
  }
443
405
  }
444
- const updateActionText = computed(() => {
445
- const map: Record<string, string> = {
446
- active: "Activate",
447
- suspended: "Suspend",
448
- deleted: "Delete",
449
- };
450
- return map[updateAction.value] || updateAction.value;
451
- });
452
406
  </script>
@@ -75,7 +75,7 @@
75
75
  />
76
76
  <v-col cols="12">
77
77
  <v-select
78
- v-model="role.type"
78
+ v-model="role.app"
79
79
  :items="apps"
80
80
  item-title="name"
81
81
  item-value="code"
@@ -68,6 +68,7 @@
68
68
  <v-dialog v-model="dialogAdd" width="500" persistent>
69
69
  <RoleForm
70
70
  v-model="role"
71
+ v-model:message="message"
71
72
  :app="props.app"
72
73
  @cancel="setRole({ mode: 'add' })"
73
74
  @submit="submitAdd()"
@@ -77,6 +78,7 @@
77
78
  <v-dialog v-model="dialogPreview" width="500" persistent>
78
79
  <RoleForm
79
80
  title="Role Details"
81
+ :app="props.app"
80
82
  v-model="role"
81
83
  @close="setRole({ mode: 'view' })"
82
84
  @edit="handOpenEdit()"
@@ -115,15 +117,10 @@ const props = defineProps({
115
117
  type: String,
116
118
  default: "",
117
119
  },
118
- orgId: {
120
+ org: {
119
121
  type: String,
120
122
  default: "",
121
123
  },
122
- permissions: {
123
- type: Object,
124
- required: true,
125
- default: () => ({}),
126
- },
127
124
  types: {
128
125
  type: Array as PropType<Array<{ title: string; value: string }>>,
129
126
  default: () => [],
@@ -165,11 +162,6 @@ const props = defineProps({
165
162
  },
166
163
  });
167
164
 
168
- const type = defineModel<string>("type", {
169
- type: String,
170
- default: "",
171
- });
172
-
173
165
  const { headerSearch } = useLocal();
174
166
 
175
167
  const {
@@ -197,7 +189,7 @@ function setRole({
197
189
  JSON.parse(
198
190
  JSON.stringify({
199
191
  ...data,
200
- type: props.app,
192
+ app: props.app,
201
193
  })
202
194
  )
203
195
  );
@@ -233,8 +225,8 @@ const {
233
225
  _getRoles({
234
226
  page: page.value,
235
227
  search: headerSearch.value,
236
- type: type.value,
237
- org: props.orgId,
228
+ app: props.app,
229
+ org: props.org,
238
230
  }),
239
231
  {
240
232
  watch: [page, headerSearch],
@@ -259,13 +251,16 @@ const dialogAdd = ref(false);
259
251
 
260
252
  const dialogPreview = ref(false);
261
253
 
254
+ const { loggedInUser } = useLocalAuth();
255
+
262
256
  async function submitAdd() {
263
257
  try {
264
258
  await addRole({
265
259
  name: role.value.name,
266
260
  permissions: role.value.permissions,
267
- type: role.value.type,
268
- org: props.orgId,
261
+ app: role.value.app,
262
+ org: props.org,
263
+ createdBy: loggedInUser(),
269
264
  });
270
265
  setRole({ mode: "add" });
271
266
  getRoles();