@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.
- package/CHANGELOG.md +12 -0
- package/components/InvitationMain.vue +83 -53
- package/components/Layout/Header.vue +1 -1
- package/components/ListGroupSelection.vue +8 -6
- package/components/MemberForm.vue +227 -0
- package/components/MemberInvite.vue +206 -0
- package/components/MemberMain.vue +216 -262
- package/components/RoleForm.vue +1 -1
- package/components/RolePermissionMain.vue +11 -16
- package/composables/useLocalAuth.ts +3 -33
- package/composables/useMember.ts +44 -37
- package/composables/useRole.ts +6 -4
- package/composables/useVerification.ts +28 -0
- package/nuxt.config.ts +30 -0
- package/package.json +1 -1
- package/pages/forgot-password.vue +76 -0
- package/pages/login.vue +156 -0
- package/pages/logout.vue +18 -0
- package/pages/member-suspended.vue +44 -0
- package/pages/sign-up/[id].vue +214 -0
- package/pages/sign-up/index.vue +135 -0
- package/plugins/member.client.ts +13 -9
- package/types/member.d.ts +9 -0
- package/types/role.d.ts +1 -1
- package/types/verification.d.ts +9 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,20 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-row no-gutters>
|
|
3
|
-
<v-col cols="12" class="mb-2">
|
|
4
|
-
<v-row no-gutters>
|
|
5
|
-
<v-btn
|
|
6
|
-
class="text-none mr-2"
|
|
7
|
-
rounded="pill"
|
|
8
|
-
variant="tonal"
|
|
9
|
-
:to="props.inviteRoute"
|
|
10
|
-
size="large"
|
|
11
|
-
v-if="props.inviteMember"
|
|
12
|
-
>
|
|
13
|
-
Invite member
|
|
14
|
-
</v-btn>
|
|
15
|
-
</v-row>
|
|
16
|
-
</v-col>
|
|
17
|
-
|
|
18
3
|
<v-col cols="12">
|
|
19
4
|
<v-card
|
|
20
5
|
width="100%"
|
|
@@ -46,24 +31,11 @@
|
|
|
46
31
|
<template #extension>
|
|
47
32
|
<v-tabs>
|
|
48
33
|
<v-tab
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
? { status: 'pending', org: props.org }
|
|
53
|
-
: { status: 'active' },
|
|
54
|
-
}"
|
|
55
|
-
>
|
|
56
|
-
Pending
|
|
57
|
-
</v-tab>
|
|
58
|
-
<v-tab
|
|
59
|
-
:to="{
|
|
60
|
-
name: props.route,
|
|
61
|
-
params: props.org
|
|
62
|
-
? { status: 'expired', org: props.org }
|
|
63
|
-
: { status: 'pending' },
|
|
64
|
-
}"
|
|
34
|
+
v-for="(routeStatus, routeStatusIndex) in props.routeStatus"
|
|
35
|
+
:key="routeStatusIndex"
|
|
36
|
+
:to="routeStatus"
|
|
65
37
|
>
|
|
66
|
-
|
|
38
|
+
{{ routeStatus.title }}
|
|
67
39
|
</v-tab>
|
|
68
40
|
</v-tabs>
|
|
69
41
|
</template>
|
|
@@ -90,6 +62,29 @@
|
|
|
90
62
|
</v-data-table>
|
|
91
63
|
</v-card>
|
|
92
64
|
</v-col>
|
|
65
|
+
|
|
66
|
+
<v-dialog v-model="dialogView" width="450" persistent>
|
|
67
|
+
<MemberInvite
|
|
68
|
+
title="Invite Details"
|
|
69
|
+
:app="props.app"
|
|
70
|
+
v-model="invitation"
|
|
71
|
+
@close="setInvite({ dialog: false })"
|
|
72
|
+
@cancel:invite="handleOpenCancelInvite()"
|
|
73
|
+
mode="view"
|
|
74
|
+
/>
|
|
75
|
+
</v-dialog>
|
|
76
|
+
|
|
77
|
+
<v-dialog v-model="dialogCancelInvite" width="450" persistent>
|
|
78
|
+
<ConfirmationPrompt
|
|
79
|
+
title="Cancel Invite"
|
|
80
|
+
action="Cancel Invite"
|
|
81
|
+
:content="`Are you sure you want to cancel invitation to ${invitation.email}?`"
|
|
82
|
+
@cancel="dialogCancelInvite = false"
|
|
83
|
+
@confirm="submitCancelInvite()"
|
|
84
|
+
v-model:message="message"
|
|
85
|
+
:disabled="disabledDelete"
|
|
86
|
+
/>
|
|
87
|
+
</v-dialog>
|
|
93
88
|
</v-row>
|
|
94
89
|
</template>
|
|
95
90
|
|
|
@@ -105,27 +100,20 @@ const props = defineProps({
|
|
|
105
100
|
},
|
|
106
101
|
app: {
|
|
107
102
|
type: String,
|
|
108
|
-
default: "
|
|
109
|
-
},
|
|
110
|
-
inviteMember: {
|
|
111
|
-
type: Boolean,
|
|
112
|
-
default: false,
|
|
113
|
-
},
|
|
114
|
-
inviteRoute: {
|
|
115
|
-
type: Object as PropType<Record<string, any>>,
|
|
116
|
-
default: () => ({
|
|
117
|
-
name: "index",
|
|
118
|
-
params: {},
|
|
119
|
-
}),
|
|
103
|
+
default: "org",
|
|
120
104
|
},
|
|
121
105
|
route: {
|
|
122
106
|
type: String,
|
|
123
107
|
default: "index",
|
|
124
108
|
},
|
|
109
|
+
routeStatus: {
|
|
110
|
+
type: Array as PropType<
|
|
111
|
+
{ title: string; name: string; params?: Record<string, any> }[]
|
|
112
|
+
>,
|
|
113
|
+
default: () => [],
|
|
114
|
+
},
|
|
125
115
|
});
|
|
126
116
|
|
|
127
|
-
const organization = (useRoute().params.organization as string) ?? "";
|
|
128
|
-
|
|
129
117
|
const headers = [
|
|
130
118
|
{
|
|
131
119
|
title: "Date",
|
|
@@ -137,11 +125,14 @@ const headers = [
|
|
|
137
125
|
},
|
|
138
126
|
{
|
|
139
127
|
title: "App",
|
|
140
|
-
value: "metadata.
|
|
128
|
+
value: "metadata.roleName",
|
|
141
129
|
},
|
|
142
130
|
];
|
|
143
131
|
|
|
144
|
-
const { getVerifications } = useVerification();
|
|
132
|
+
const { getVerifications, cancelInvite } = useVerification();
|
|
133
|
+
const { invitation } = useMember();
|
|
134
|
+
|
|
135
|
+
const dialogView = ref(false);
|
|
145
136
|
|
|
146
137
|
const page = ref(1);
|
|
147
138
|
const pages = ref(0);
|
|
@@ -180,11 +171,27 @@ watchEffect(() => {
|
|
|
180
171
|
}
|
|
181
172
|
});
|
|
182
173
|
|
|
183
|
-
function
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
174
|
+
function setInvite({
|
|
175
|
+
dialog = true,
|
|
176
|
+
data = useMember().invitation.value,
|
|
177
|
+
} = {}) {
|
|
178
|
+
Object.assign(invitation.value, JSON.parse(JSON.stringify(data)));
|
|
179
|
+
|
|
180
|
+
if (dialog) {
|
|
181
|
+
dialogView.value = dialog;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function tableRowClickHandler(_: any, data: any) {
|
|
186
|
+
setInvite({
|
|
187
|
+
data: {
|
|
188
|
+
_id: data.item._id,
|
|
189
|
+
email: data.item.email,
|
|
190
|
+
role: data.item.metadata.role,
|
|
191
|
+
org: data.item.metadata.org,
|
|
192
|
+
app: data.item.metadata.app,
|
|
193
|
+
},
|
|
194
|
+
dialog: true,
|
|
188
195
|
});
|
|
189
196
|
}
|
|
190
197
|
|
|
@@ -198,6 +205,29 @@ watch(selectAll, (curr) => {
|
|
|
198
205
|
selected.value.push(...ids);
|
|
199
206
|
}
|
|
200
207
|
});
|
|
208
|
+
|
|
209
|
+
const dialogCancelInvite = ref(false);
|
|
210
|
+
const disabledDelete = ref(false);
|
|
211
|
+
const message = ref("");
|
|
212
|
+
|
|
213
|
+
function handleOpenCancelInvite() {
|
|
214
|
+
dialogCancelInvite.value = true;
|
|
215
|
+
dialogView.value = false;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async function submitCancelInvite() {
|
|
219
|
+
disabledDelete.value = true;
|
|
220
|
+
try {
|
|
221
|
+
await cancelInvite(invitation.value._id ?? "");
|
|
222
|
+
await getInvitations();
|
|
223
|
+
|
|
224
|
+
dialogCancelInvite.value = false;
|
|
225
|
+
} catch (error: any) {
|
|
226
|
+
message.value = error.response._data.message || "An error occurred.";
|
|
227
|
+
} finally {
|
|
228
|
+
disabledDelete.value = false;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
201
231
|
</script>
|
|
202
232
|
|
|
203
233
|
<style scoped>
|
|
@@ -37,25 +37,27 @@
|
|
|
37
37
|
>
|
|
38
38
|
<v-divider></v-divider>
|
|
39
39
|
<v-list-item v-if="attrs.readonly" density="compact">
|
|
40
|
-
<template #title
|
|
41
|
-
<span class="text-subtitle-2 text-capitalize">
|
|
40
|
+
<template #title>
|
|
41
|
+
<span class="text-subtitle-2 text-capitalize pl-11">
|
|
42
42
|
{{ item.title }}
|
|
43
43
|
</span>
|
|
44
44
|
</template>
|
|
45
45
|
|
|
46
|
-
<template #subtitle
|
|
47
|
-
<span class="text-subtitle-2">{{
|
|
46
|
+
<template #subtitle>
|
|
47
|
+
<span class="text-subtitle-2 pl-11">{{
|
|
48
|
+
item.description
|
|
49
|
+
}}</span>
|
|
48
50
|
</template>
|
|
49
51
|
</v-list-item>
|
|
50
52
|
|
|
51
53
|
<v-list-item v-else :value="item.key" density="compact">
|
|
52
|
-
<template #title
|
|
54
|
+
<template #title>
|
|
53
55
|
<span class="text-subtitle-2 text-capitalize">
|
|
54
56
|
{{ item.title }}
|
|
55
57
|
</span>
|
|
56
58
|
</template>
|
|
57
59
|
|
|
58
|
-
<template #subtitle
|
|
60
|
+
<template #subtitle>
|
|
59
61
|
<span class="text-subtitle-2 text-capitalize">
|
|
60
62
|
{{ item.description }}
|
|
61
63
|
</span>
|
|
@@ -0,0 +1,227 @@
|
|
|
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
|
+
{{ localProps.title }}
|
|
7
|
+
</span>
|
|
8
|
+
</v-row>
|
|
9
|
+
</v-toolbar>
|
|
10
|
+
|
|
11
|
+
<v-card-text style="max-height: 100vh; overflow-y: auto">
|
|
12
|
+
<v-form v-model="valid" :disabled="localProps.disabled">
|
|
13
|
+
<v-row no-gutters>
|
|
14
|
+
<v-col cols="12" class="mb-2">
|
|
15
|
+
<v-row no-gutters>
|
|
16
|
+
<InputLabel class="text-capitalize" title="Name" />
|
|
17
|
+
<v-col cols="12">
|
|
18
|
+
<v-text-field v-model="member.name" readonly></v-text-field>
|
|
19
|
+
</v-col>
|
|
20
|
+
</v-row>
|
|
21
|
+
</v-col>
|
|
22
|
+
|
|
23
|
+
<v-col cols="12" class="mb-2">
|
|
24
|
+
<v-row no-gutters>
|
|
25
|
+
<InputLabel class="text-capitalize" title="Role" />
|
|
26
|
+
<v-col cols="12">
|
|
27
|
+
<v-select
|
|
28
|
+
v-model="member.role"
|
|
29
|
+
:items="roles"
|
|
30
|
+
item-title="name"
|
|
31
|
+
item-value="_id"
|
|
32
|
+
:rules="isMutable ? [requiredRule] : []"
|
|
33
|
+
:readonly="!isMutable"
|
|
34
|
+
:loading="loadingRoles"
|
|
35
|
+
></v-select>
|
|
36
|
+
</v-col>
|
|
37
|
+
</v-row>
|
|
38
|
+
</v-col>
|
|
39
|
+
</v-row>
|
|
40
|
+
</v-form>
|
|
41
|
+
|
|
42
|
+
<v-alert
|
|
43
|
+
v-if="message"
|
|
44
|
+
type="error"
|
|
45
|
+
variant="flat"
|
|
46
|
+
closable
|
|
47
|
+
position="absolute"
|
|
48
|
+
location="bottom"
|
|
49
|
+
style="bottom: 48px"
|
|
50
|
+
@click:close="message = ''"
|
|
51
|
+
width="100%"
|
|
52
|
+
tile
|
|
53
|
+
class="text-caption"
|
|
54
|
+
>
|
|
55
|
+
{{ message }}
|
|
56
|
+
</v-alert>
|
|
57
|
+
</v-card-text>
|
|
58
|
+
|
|
59
|
+
<v-toolbar density="compact">
|
|
60
|
+
<v-row no-gutters>
|
|
61
|
+
<v-col v-if="localProps.mode === 'view'" cols="6">
|
|
62
|
+
<v-btn
|
|
63
|
+
tile
|
|
64
|
+
block
|
|
65
|
+
variant="text"
|
|
66
|
+
class="text-none"
|
|
67
|
+
size="48"
|
|
68
|
+
@click="emits('close')"
|
|
69
|
+
>
|
|
70
|
+
Close
|
|
71
|
+
</v-btn>
|
|
72
|
+
</v-col>
|
|
73
|
+
|
|
74
|
+
<v-col v-if="isMutable" cols="6">
|
|
75
|
+
<v-btn
|
|
76
|
+
tile
|
|
77
|
+
block
|
|
78
|
+
variant="text"
|
|
79
|
+
class="text-none"
|
|
80
|
+
size="48"
|
|
81
|
+
@click="emits('cancel')"
|
|
82
|
+
>
|
|
83
|
+
Cancel
|
|
84
|
+
</v-btn>
|
|
85
|
+
</v-col>
|
|
86
|
+
|
|
87
|
+
<v-col v-if="localProps.mode === 'view'" cols="6">
|
|
88
|
+
<v-menu>
|
|
89
|
+
<template #activator="{ props }">
|
|
90
|
+
<v-btn
|
|
91
|
+
block
|
|
92
|
+
variant="flat"
|
|
93
|
+
color="black"
|
|
94
|
+
class="text-none"
|
|
95
|
+
height="48"
|
|
96
|
+
v-bind="props"
|
|
97
|
+
tile
|
|
98
|
+
>
|
|
99
|
+
More actions
|
|
100
|
+
</v-btn>
|
|
101
|
+
</template>
|
|
102
|
+
|
|
103
|
+
<v-list class="pa-0">
|
|
104
|
+
<v-list-item @click="emits('assign')">
|
|
105
|
+
<v-list-item-title class="text-subtitle-2">
|
|
106
|
+
Assign Role
|
|
107
|
+
</v-list-item-title>
|
|
108
|
+
</v-list-item>
|
|
109
|
+
|
|
110
|
+
<v-list-item
|
|
111
|
+
v-if="member.status === 'active'"
|
|
112
|
+
@click="emits('suspend')"
|
|
113
|
+
class="text-red"
|
|
114
|
+
>
|
|
115
|
+
<v-list-item-title class="text-subtitle-2">
|
|
116
|
+
Suspend Member
|
|
117
|
+
</v-list-item-title>
|
|
118
|
+
</v-list-item>
|
|
119
|
+
|
|
120
|
+
<v-list-item
|
|
121
|
+
v-if="member.status === 'suspended'"
|
|
122
|
+
@click="emits('activate')"
|
|
123
|
+
>
|
|
124
|
+
<v-list-item-title class="text-subtitle-2">
|
|
125
|
+
Unsuspend Member
|
|
126
|
+
</v-list-item-title>
|
|
127
|
+
</v-list-item>
|
|
128
|
+
|
|
129
|
+
<v-list-item @click="emits('delete')">
|
|
130
|
+
<v-list-item-title class="text-subtitle-2">
|
|
131
|
+
Remove Member
|
|
132
|
+
</v-list-item-title>
|
|
133
|
+
</v-list-item>
|
|
134
|
+
</v-list>
|
|
135
|
+
</v-menu>
|
|
136
|
+
</v-col>
|
|
137
|
+
|
|
138
|
+
<v-col v-if="isMutable" cols="6">
|
|
139
|
+
<v-btn
|
|
140
|
+
tile
|
|
141
|
+
block
|
|
142
|
+
variant="flat"
|
|
143
|
+
color="black"
|
|
144
|
+
class="text-none"
|
|
145
|
+
size="48"
|
|
146
|
+
@click="emits('submit')"
|
|
147
|
+
:disabled="!valid || localProps.disabled"
|
|
148
|
+
>
|
|
149
|
+
{{
|
|
150
|
+
localProps.mode === "assign-role" ? "Assign Role" : "Save Changes"
|
|
151
|
+
}}
|
|
152
|
+
</v-btn>
|
|
153
|
+
</v-col>
|
|
154
|
+
</v-row>
|
|
155
|
+
</v-toolbar>
|
|
156
|
+
</v-card>
|
|
157
|
+
</template>
|
|
158
|
+
|
|
159
|
+
<script setup lang="ts">
|
|
160
|
+
const emits = defineEmits([
|
|
161
|
+
"submit",
|
|
162
|
+
"cancel",
|
|
163
|
+
"close",
|
|
164
|
+
"edit",
|
|
165
|
+
"delete",
|
|
166
|
+
"suspend",
|
|
167
|
+
"activate",
|
|
168
|
+
"assign",
|
|
169
|
+
"delete",
|
|
170
|
+
]);
|
|
171
|
+
|
|
172
|
+
const isMutable = computed(() => ["assign-role"].includes(localProps.mode));
|
|
173
|
+
|
|
174
|
+
const localProps = defineProps({
|
|
175
|
+
title: {
|
|
176
|
+
type: String,
|
|
177
|
+
default: "Member Form",
|
|
178
|
+
},
|
|
179
|
+
app: {
|
|
180
|
+
type: String,
|
|
181
|
+
default: "",
|
|
182
|
+
},
|
|
183
|
+
org: {
|
|
184
|
+
type: String,
|
|
185
|
+
default: "",
|
|
186
|
+
},
|
|
187
|
+
mode: {
|
|
188
|
+
type: String,
|
|
189
|
+
default: "add",
|
|
190
|
+
},
|
|
191
|
+
disabled: {
|
|
192
|
+
type: Boolean,
|
|
193
|
+
default: false,
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
const member = defineModel<TMember>({
|
|
198
|
+
default: () => useMember().member.value,
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
const perm = defineModel<TPerm>("perm", {
|
|
202
|
+
default: () => usePermission().perm.value,
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
const message = defineModel("message", { default: "" });
|
|
206
|
+
|
|
207
|
+
const valid = ref(false);
|
|
208
|
+
|
|
209
|
+
const { requiredRule } = useUtils();
|
|
210
|
+
|
|
211
|
+
const { getAll: getAllRoles } = useRole();
|
|
212
|
+
|
|
213
|
+
const roles = ref<Array<Record<string, any>>>([]);
|
|
214
|
+
|
|
215
|
+
const { data: roleData, status: roleReqStatus } = await useLazyAsyncData(
|
|
216
|
+
`get-all-role-app-${localProps.app}-${localProps.org ?? "org"}`,
|
|
217
|
+
() => getAllRoles({ org: localProps.org, app: localProps.app, limit: 50 })
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
const loadingRoles = computed(() => roleReqStatus.value === "pending");
|
|
221
|
+
|
|
222
|
+
watchEffect(() => {
|
|
223
|
+
if (roleData.value && roleData.value.items) {
|
|
224
|
+
roles.value = roleData.value.items;
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
</script>
|
|
@@ -0,0 +1,206 @@
|
|
|
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
|
+
{{ localProps.title }}
|
|
7
|
+
</span>
|
|
8
|
+
</v-row>
|
|
9
|
+
</v-toolbar>
|
|
10
|
+
|
|
11
|
+
<v-card-text style="max-height: 100vh; overflow-y: auto">
|
|
12
|
+
<v-form v-model="valid" :disabled="localProps.disabled">
|
|
13
|
+
<v-row no-gutters>
|
|
14
|
+
<v-col cols="12" class="mb-1">
|
|
15
|
+
<v-row no-gutters>
|
|
16
|
+
<InputLabel
|
|
17
|
+
class="text-capitalize"
|
|
18
|
+
title="Email"
|
|
19
|
+
:required="isMutable"
|
|
20
|
+
/>
|
|
21
|
+
<v-col cols="12">
|
|
22
|
+
<v-text-field
|
|
23
|
+
v-model="invite.email"
|
|
24
|
+
:rules="isMutable ? [requiredRule, emailRule] : []"
|
|
25
|
+
:readonly="!isMutable"
|
|
26
|
+
></v-text-field>
|
|
27
|
+
</v-col>
|
|
28
|
+
</v-row>
|
|
29
|
+
</v-col>
|
|
30
|
+
|
|
31
|
+
<v-col cols="12" class="mb-1">
|
|
32
|
+
<v-row no-gutters>
|
|
33
|
+
<InputLabel
|
|
34
|
+
class="text-capitalize"
|
|
35
|
+
title="Role"
|
|
36
|
+
:required="isMutable"
|
|
37
|
+
/>
|
|
38
|
+
<v-col cols="12">
|
|
39
|
+
<v-select
|
|
40
|
+
v-model="invite.role"
|
|
41
|
+
:items="roles"
|
|
42
|
+
item-title="name"
|
|
43
|
+
item-value="_id"
|
|
44
|
+
:loading="loadingRoles"
|
|
45
|
+
:rules="isMutable ? [requiredRule] : []"
|
|
46
|
+
:readonly="!isMutable"
|
|
47
|
+
></v-select>
|
|
48
|
+
</v-col>
|
|
49
|
+
</v-row>
|
|
50
|
+
</v-col>
|
|
51
|
+
|
|
52
|
+
<v-col v-if="!localProps.app" cols="12" class="mb-1">
|
|
53
|
+
<v-row no-gutters>
|
|
54
|
+
<InputLabel class="text-capitalize" title="App" required />
|
|
55
|
+
<v-col cols="12">
|
|
56
|
+
<v-select
|
|
57
|
+
v-model="invite.app"
|
|
58
|
+
:rules="[requiredRule]"
|
|
59
|
+
></v-select>
|
|
60
|
+
</v-col>
|
|
61
|
+
</v-row>
|
|
62
|
+
</v-col>
|
|
63
|
+
</v-row>
|
|
64
|
+
</v-form>
|
|
65
|
+
|
|
66
|
+
<v-alert
|
|
67
|
+
v-if="message"
|
|
68
|
+
type="error"
|
|
69
|
+
variant="flat"
|
|
70
|
+
closable
|
|
71
|
+
position="absolute"
|
|
72
|
+
location="bottom"
|
|
73
|
+
style="bottom: 48px"
|
|
74
|
+
@click:close="message = ''"
|
|
75
|
+
width="100%"
|
|
76
|
+
tile
|
|
77
|
+
class="text-caption"
|
|
78
|
+
>
|
|
79
|
+
{{ message }}
|
|
80
|
+
</v-alert>
|
|
81
|
+
</v-card-text>
|
|
82
|
+
|
|
83
|
+
<v-toolbar density="compact">
|
|
84
|
+
<v-row no-gutters>
|
|
85
|
+
<v-col v-if="localProps.mode === 'add'" cols="6">
|
|
86
|
+
<v-btn
|
|
87
|
+
tile
|
|
88
|
+
block
|
|
89
|
+
variant="text"
|
|
90
|
+
class="text-none"
|
|
91
|
+
size="48"
|
|
92
|
+
@click="emits('cancel')"
|
|
93
|
+
>
|
|
94
|
+
Cancel
|
|
95
|
+
</v-btn>
|
|
96
|
+
</v-col>
|
|
97
|
+
|
|
98
|
+
<v-col v-if="localProps.mode === 'view'" cols="6">
|
|
99
|
+
<v-btn
|
|
100
|
+
tile
|
|
101
|
+
block
|
|
102
|
+
variant="text"
|
|
103
|
+
class="text-none"
|
|
104
|
+
size="48"
|
|
105
|
+
@click="emits('close')"
|
|
106
|
+
>
|
|
107
|
+
Close
|
|
108
|
+
</v-btn>
|
|
109
|
+
</v-col>
|
|
110
|
+
|
|
111
|
+
<v-col v-if="localProps.mode === 'add'" cols="6">
|
|
112
|
+
<v-btn
|
|
113
|
+
tile
|
|
114
|
+
block
|
|
115
|
+
variant="flat"
|
|
116
|
+
color="black"
|
|
117
|
+
class="text-none"
|
|
118
|
+
size="48"
|
|
119
|
+
@click="emits('submit')"
|
|
120
|
+
:disabled="localProps.disabled || !valid"
|
|
121
|
+
>
|
|
122
|
+
Invite
|
|
123
|
+
</v-btn>
|
|
124
|
+
</v-col>
|
|
125
|
+
|
|
126
|
+
<v-col v-if="localProps.mode === 'view'" cols="6">
|
|
127
|
+
<v-btn
|
|
128
|
+
tile
|
|
129
|
+
block
|
|
130
|
+
variant="flat"
|
|
131
|
+
color="black"
|
|
132
|
+
class="text-none"
|
|
133
|
+
size="48"
|
|
134
|
+
@click="emits('cancel:invite')"
|
|
135
|
+
:disabled="localProps.disabled"
|
|
136
|
+
>
|
|
137
|
+
Cancel Invite
|
|
138
|
+
</v-btn>
|
|
139
|
+
</v-col>
|
|
140
|
+
</v-row>
|
|
141
|
+
</v-toolbar>
|
|
142
|
+
</v-card>
|
|
143
|
+
</template>
|
|
144
|
+
|
|
145
|
+
<script setup lang="ts">
|
|
146
|
+
const emits = defineEmits([
|
|
147
|
+
"submit",
|
|
148
|
+
"cancel",
|
|
149
|
+
"edit",
|
|
150
|
+
"delete",
|
|
151
|
+
"close",
|
|
152
|
+
"cancel:invite",
|
|
153
|
+
]);
|
|
154
|
+
|
|
155
|
+
const localProps = defineProps({
|
|
156
|
+
title: {
|
|
157
|
+
type: String,
|
|
158
|
+
default: "Invite Member",
|
|
159
|
+
},
|
|
160
|
+
app: {
|
|
161
|
+
type: String,
|
|
162
|
+
default: "",
|
|
163
|
+
},
|
|
164
|
+
org: {
|
|
165
|
+
type: String,
|
|
166
|
+
default: "",
|
|
167
|
+
},
|
|
168
|
+
disabled: {
|
|
169
|
+
type: Boolean,
|
|
170
|
+
default: false,
|
|
171
|
+
},
|
|
172
|
+
mode: {
|
|
173
|
+
type: String,
|
|
174
|
+
default: "add",
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const isMutable = computed(() => ["add"].includes(localProps.mode));
|
|
179
|
+
|
|
180
|
+
const invite = defineModel<TMemberInvitation>({
|
|
181
|
+
default: () => useMember().invitation.value,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const message = defineModel("message", { default: "" });
|
|
185
|
+
|
|
186
|
+
const valid = ref(false);
|
|
187
|
+
|
|
188
|
+
const { requiredRule, emailRule } = useUtils();
|
|
189
|
+
|
|
190
|
+
const { getAll: getAllRoles } = useRole();
|
|
191
|
+
|
|
192
|
+
const roles = ref<Array<Record<string, any>>>([]);
|
|
193
|
+
|
|
194
|
+
const { data: roleData, status: roleReqStatus } = await useLazyAsyncData(
|
|
195
|
+
`get-all-role-app-${localProps.app}-${localProps.org ?? "org"}`,
|
|
196
|
+
() => getAllRoles({ org: localProps.org, app: localProps.app, limit: 50 })
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const loadingRoles = computed(() => roleReqStatus.value === "pending");
|
|
200
|
+
|
|
201
|
+
watchEffect(() => {
|
|
202
|
+
if (roleData.value && roleData.value.items) {
|
|
203
|
+
roles.value = roleData.value.items;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
</script>
|