@iservice365/layer-common 1.0.5 → 1.0.6

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @iservice365/layer-common
2
2
 
3
+ ## 1.0.6
4
+
5
+ ### Patch Changes
6
+
7
+ - adf0043: Revision - add invitation form as component
8
+
3
9
  ## 1.0.5
4
10
 
5
11
  ### Patch Changes
@@ -0,0 +1,237 @@
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">
6
+ {{ props.title }}
7
+ </span>
8
+ </v-row>
9
+ </v-toolbar>
10
+ <v-card-text style="max-height: 100vh; overflow-y: auto">
11
+ <v-form v-model="validForm" :disabled="disable">
12
+ <v-row no-gutters>
13
+ <v-col cols="12" class="mt-2">
14
+ <v-row no-gutters>
15
+ <InputLabel class="text-capitalize" title="Email" required />
16
+ <v-col cols="12">
17
+ <v-text-field
18
+ v-model="invite.email"
19
+ density="comfortable"
20
+ :rules="[requiredRule]"
21
+ ></v-text-field>
22
+ </v-col>
23
+ </v-row>
24
+ </v-col>
25
+
26
+ <v-col v-if="APP === 'organization'" cols="12" class="mt-2">
27
+ <v-row no-gutters>
28
+ <InputLabel class="text-capitalize" title="App" required />
29
+ <v-col cols="12">
30
+ <v-autocomplete
31
+ v-model="invite.app"
32
+ density="comfortable"
33
+ :rules="[requiredRule]"
34
+ :items="apps"
35
+ ></v-autocomplete>
36
+ </v-col>
37
+ </v-row>
38
+ </v-col>
39
+
40
+ <v-col cols="12">
41
+ <v-row no-gutters>
42
+ <InputLabel class="text-capitalize" title="Role" />
43
+ <v-col cols="12">
44
+ <v-autocomplete
45
+ v-model="invite.role"
46
+ :items="roles"
47
+ item-title="name"
48
+ item-value="_id"
49
+ density="comfortable"
50
+ ></v-autocomplete>
51
+ </v-col>
52
+ </v-row>
53
+ </v-col>
54
+
55
+ <v-col cols="12" class="mt-2">
56
+ <v-checkbox v-model="createMore" density="comfortable" hide-details>
57
+ <template #label>
58
+ <span class="text-subtitle-2 font-weight-bold">
59
+ Create more
60
+ </span>
61
+ </template>
62
+ </v-checkbox>
63
+ </v-col>
64
+
65
+ <v-col cols="12" class="my-2">
66
+ <v-row no-gutters>
67
+ <v-col cols="12" class="text-center">
68
+ <span
69
+ class="text-none text-subtitle-2 font-weight-medium text-error"
70
+ >
71
+ {{ message }}
72
+ </span>
73
+ </v-col>
74
+ </v-row>
75
+ </v-col>
76
+ </v-row>
77
+ </v-form>
78
+ </v-card-text>
79
+
80
+ <v-toolbar density="compact">
81
+ <v-row no-gutters>
82
+ <v-col cols="6">
83
+ <v-btn
84
+ tile
85
+ block
86
+ variant="text"
87
+ class="text-none"
88
+ size="48"
89
+ @click="cancel"
90
+ >
91
+ Cancel
92
+ </v-btn>
93
+ </v-col>
94
+
95
+ <v-col cols="6">
96
+ <v-btn
97
+ tile
98
+ block
99
+ variant="flat"
100
+ color="black"
101
+ class="text-none"
102
+ size="48"
103
+ :disabled="!validForm"
104
+ @click="submit"
105
+ >
106
+ Submit
107
+ </v-btn>
108
+ </v-col>
109
+ </v-row>
110
+ </v-toolbar>
111
+ </v-card>
112
+ </template>
113
+
114
+ <script setup lang="ts">
115
+ const APP = useRuntimeConfig().public.APP;
116
+ const props = defineProps({
117
+ title: {
118
+ type: String,
119
+ default: "Invite Form",
120
+ },
121
+ mode: {
122
+ type: String,
123
+ default: "create",
124
+ },
125
+ permissions: {
126
+ type: Object,
127
+ default: () => ({}),
128
+ },
129
+ type: {
130
+ type: String,
131
+ default: "app",
132
+ },
133
+ org: {
134
+ type: String,
135
+ default: "",
136
+ },
137
+ site: {
138
+ type: Object as PropType<TCustomerSite>,
139
+ default: () => ({
140
+ name: "",
141
+ site: "",
142
+ siteOrg: "",
143
+ siteOrgName: "",
144
+ org: "",
145
+ }),
146
+ },
147
+ invite: {
148
+ type: Object as PropType<TVerification>,
149
+ default: () => ({
150
+ email: "",
151
+ metadata: { app: "organization", role: "" },
152
+ }),
153
+ },
154
+ });
155
+
156
+ const emit = defineEmits(["cancel", "success", "success:create-more"]);
157
+
158
+ const validForm = ref(false);
159
+
160
+ const invite = ref<Record<string, any>>({
161
+ email: "",
162
+ app: "organization",
163
+ role: "",
164
+ });
165
+
166
+ if (props.mode === "edit") {
167
+ invite.value.email = props.invite.email;
168
+ invite.value.app = props.invite.metadata?.app;
169
+ invite.value.role = props.invite.metadata?.role;
170
+ }
171
+
172
+ const { natureOfBusiness } = useLocal();
173
+
174
+ const apps = computed(() => {
175
+ const items = natureOfBusiness.slice(1);
176
+ items.unshift({ title: "Organization", value: "organization" });
177
+ return items;
178
+ });
179
+
180
+ const roles = ref<Array<Record<string, any>>>([]);
181
+
182
+ const { getRoles } = useRole();
183
+
184
+ const app = computed(() => invite.value.metadata?.app ?? "");
185
+
186
+ const { data: RolesData } = await useLazyAsyncData(
187
+ "get-roles-by-type",
188
+ () => getRoles({ org: props.org, type: app.value, limit: 50 }),
189
+ { watch: [app] }
190
+ );
191
+
192
+ watchEffect(() => {
193
+ if (RolesData.value) {
194
+ roles.value = RolesData.value.items;
195
+ }
196
+ });
197
+
198
+ watchEffect(() => {
199
+ if (invite.value.app) {
200
+ roles.value = [];
201
+ invite.value.role = "";
202
+ }
203
+ });
204
+
205
+ const createMore = ref(false);
206
+ const disable = ref(false);
207
+
208
+ const { requiredRule } = useUtils();
209
+
210
+ const message = ref("");
211
+
212
+ function resetInvite() {
213
+ invite.value.email = "";
214
+ invite.value.app = "organization";
215
+ invite.value.role = "";
216
+ message.value = "";
217
+ }
218
+
219
+ const { inviteUser } = useUser();
220
+
221
+ async function submit() {
222
+ try {
223
+ await inviteUser(invite.value);
224
+ emit("success");
225
+
226
+ if (createMore.value) {
227
+ resetInvite();
228
+ }
229
+ } catch (error: any) {
230
+ message.value = error.response._data.message;
231
+ }
232
+ }
233
+
234
+ function cancel() {
235
+ emit("cancel");
236
+ }
237
+ </script>
@@ -6,10 +6,8 @@
6
6
  class="text-none mr-2"
7
7
  rounded="pill"
8
8
  variant="tonal"
9
- :to="{
10
- name: 'org-customer-site-invitations-invite',
11
- }"
12
9
  size="large"
10
+ @click="inviteMember()"
13
11
  v-if="props.inviteMember"
14
12
  >
15
13
  Invite member
@@ -47,7 +45,7 @@
47
45
  <v-tabs>
48
46
  <v-tab
49
47
  :to="{
50
- name: 'org-customer-site-invitations-status-status',
48
+ name: props.route,
51
49
  params: { status: 'pending' },
52
50
  }"
53
51
  >
@@ -55,7 +53,7 @@
55
53
  </v-tab>
56
54
  <v-tab
57
55
  :to="{
58
- name: 'org-customer-site-invitations-status-status',
56
+ name: props.route,
59
57
  params: { status: 'expired' },
60
58
  }"
61
59
  >
@@ -82,7 +80,7 @@
82
80
  <v-chip>{{ value.length }}</v-chip>
83
81
  </template>
84
82
  <template #item.createdAt="{ item }">
85
- {{ formatDate(item.createdAt) }}
83
+ {{ item.createdAt ? formatDate(item.createdAt) : "" }}
86
84
  </template>
87
85
  <template #item.action-table="{ item }">
88
86
  <v-menu
@@ -95,7 +93,7 @@
95
93
  <v-icon v-bind="props">mdi-dots-horizontal</v-icon>
96
94
  </template>
97
95
  <v-list>
98
- <v-list-item @click="openConfirmDialog(item._id)">
96
+ <v-list-item @click="openConfirmDialog(item._id ?? '')">
99
97
  Cancel Invite
100
98
  </v-list-item>
101
99
  </v-list>
@@ -104,40 +102,50 @@
104
102
  </v-data-table>
105
103
  </v-card>
106
104
  </v-col>
105
+
106
+ <ConfirmDialog
107
+ v-model="confirmDialog"
108
+ :loading="cancelLoading"
109
+ @submit="onConfirmCancel"
110
+ >
111
+ <template #title>
112
+ <span class="font-weight-medium text-h5">Cancel Invitation</span>
113
+ </template>
114
+ <template #description>
115
+ <p class="text-subtitle-2">
116
+ Are you sure you want to cancel this invitation? This action cannot be
117
+ undone.
118
+ </p>
119
+ </template>
120
+ <template #footer>
121
+ <v-btn
122
+ variant="text"
123
+ @click="confirmDialog = false"
124
+ :disabled="cancelLoading"
125
+ >
126
+ Close
127
+ </v-btn>
128
+ <v-btn
129
+ color="primary"
130
+ variant="flat"
131
+ @click="onConfirmCancel"
132
+ :loading="cancelLoading"
133
+ >
134
+ Cancel Invite
135
+ </v-btn>
136
+ </template>
137
+ </ConfirmDialog>
138
+ <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
139
+
140
+ <v-dialog v-model="dialogMember" max-width="450">
141
+ <InvitationForm
142
+ title="Invite member"
143
+ :org="org"
144
+ @cancel="dialogMember = false"
145
+ @invited="getVerifications()"
146
+ />
147
+ </v-dialog>
107
148
  </v-row>
108
- <ConfirmDialog
109
- v-model="confirmDialog"
110
- :loading="cancelLoading"
111
- @submit="onConfirmCancel"
112
- >
113
- <template #title>
114
- <span class="font-weight-medium text-h5">Cancel Invitation</span>
115
- </template>
116
- <template #description>
117
- <p class="text-subtitle-2">
118
- Are you sure you want to cancel this invitation? This action cannot be
119
- undone.
120
- </p>
121
- </template>
122
- <template #footer>
123
- <v-btn
124
- variant="text"
125
- @click="confirmDialog = false"
126
- :disabled="cancelLoading"
127
- >
128
- Close
129
- </v-btn>
130
- <v-btn
131
- color="primary"
132
- variant="flat"
133
- @click="onConfirmCancel"
134
- :loading="cancelLoading"
135
- >
136
- Cancel Invite
137
- </v-btn>
138
- </template>
139
- </ConfirmDialog>
140
- <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
141
149
  </template>
142
150
 
143
151
  <script setup lang="ts">
@@ -146,7 +154,7 @@ const props = defineProps({
146
154
  type: String,
147
155
  default: "index",
148
156
  },
149
- orgId: {
157
+ org: {
150
158
  type: String,
151
159
  default: "",
152
160
  },
@@ -179,8 +187,6 @@ const props = defineProps({
179
187
  const { authenticate } = useLocalAuth();
180
188
  authenticate();
181
189
 
182
- const organization = (useRoute().params.org as string) ?? "";
183
-
184
190
  const headers = [
185
191
  {
186
192
  title: "Date",
@@ -281,4 +287,10 @@ watchEffect(() => {
281
287
  useRouter().back();
282
288
  }
283
289
  });
290
+
291
+ const dialogMember = ref(false);
292
+
293
+ function inviteMember() {
294
+ dialogMember.value = true;
295
+ }
284
296
  </script>
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@iservice365/layer-common",
3
3
  "license": "MIT",
4
4
  "type": "module",
5
- "version": "1.0.5",
5
+ "version": "1.0.6",
6
6
  "main": "./nuxt.config.ts",
7
7
  "scripts": {
8
8
  "dev": "nuxi dev .playground",
@@ -9,14 +9,7 @@ export default defineNuxtPlugin(() => {
9
9
  router.afterEach((to) => {
10
10
  const isMember = to.meta?.memberOnly;
11
11
 
12
- if (typeof isMember === "boolean" && !isMember) {
13
- navigateTo(
14
- {
15
- name: "index",
16
- },
17
- { replace: true }
18
- );
19
- }
12
+ if (!isMember) return;
20
13
 
21
14
  const APP = useRuntimeConfig().public.APP;
22
15
  const org = computed(
@@ -9,12 +9,12 @@ declare type TMiniVerification = Pick<
9
9
  >;
10
10
 
11
11
  declare type TVerification = {
12
- _id: string;
12
+ _id?: string;
13
13
  type: string;
14
14
  email: string;
15
15
  metadata?: TVerificationMetadata;
16
16
  status?: string;
17
- createdAt: string;
17
+ createdAt?: string;
18
18
  updatedAt?: string | null;
19
- expireAt: string;
19
+ expireAt?: string;
20
20
  };