1
1
<script setup lang="ts">
2
+ import { cloneDeep , debounce } from ' lodash-es'
2
3
import { VForm } from ' vuetify/components/VForm'
3
4
import { usePermissionStore } from ' ~/stores/admin/permission'
5
+ import type { PivotRolePermission , Role } from ' ~/stores/admin/role'
4
6
5
7
interface Props {
6
8
isDialogVisible: boolean
7
- roleData? : Partial <Role >
9
+ roleData? : Partial <PivotRolePermission >
8
10
}
9
11
interface Emit {
10
12
(e : ' update:isDialogVisible' , value : boolean ): void
11
- (e : ' update:rolePermissions' , value : Partial <Role >): void
13
+ (e : ' update:rolePermissions' , value : Partial <PivotRolePermission >): void
12
14
}
13
15
14
16
const props = defineProps <Props >()
@@ -21,89 +23,61 @@ const { fetchPermissions } = permissionStore
21
23
const refPermissionForm = ref <VForm >()
22
24
const isFormValid = ref (false )
23
25
24
- const isSelectAll = ref (false )
25
- const localRoleData = ref <Partial <Role >>({
26
+ const localRoleData = ref <Partial <PivotRolePermission >>({
26
27
id: ' ' ,
27
28
name: ' ' ,
29
+ permissions: [],
28
30
})
29
31
30
- const permissions = [
31
- {
32
- action: ' Read' ,
33
- subject: ' All' ,
34
- value: {
35
- action: ' read' ,
36
- subject: ' all' ,
37
- },
38
- },
39
- {
40
- action: ' Read' ,
41
- subject: ' Category' ,
42
- value: {
43
- action: ' read' ,
44
- subject: ' category' ,
45
- },
46
- },
47
- {
48
- action: ' Create' ,
49
- subject: ' All' ,
50
- value: {
51
- action: ' create' ,
52
- subject: ' all' ,
53
- },
54
- },
55
- ]
56
-
57
- // // select all
58
- // watch(isSelectAll, (val) => {
59
- // permissions.value = permissions.value.map(permission => ({
60
- // ...permission,
61
- // read: val,
62
- // write: val,
63
- // create: val,
64
- // }))
65
- // })
66
-
67
- // // if Indeterminate is false, then set isSelectAll to false
68
- // watch(isIndeterminate, () => {
69
- // if (!isIndeterminate.value)
70
- // isSelectAll.value = false
71
- // })
72
-
73
- // // if all permissions are checked, then set isSelectAll to true
74
- // watch(permissions, () => {
75
- // if (checkedCount.value === (permissions.value.length * 3))
76
- // isSelectAll.value = true
77
- // }, { deep: true })
78
-
79
- // // if rolePermissions is not empty, then set permissions
80
- // watch(() => props, () => {
81
- // if (props.rolePermissions && props.rolePermissions.permissions.length) {
82
- // role.value = props.rolePermissions.name
83
- // permissions.value = permissions.value.map((permission) => {
84
- // const rolePermission = props.rolePermissions?.permissions.find(item => item.name === permission.name)
85
-
86
- // if (rolePermission) {
87
- // return {
88
- // ...permission,
89
- // ...rolePermission,
90
- // }
91
- // }
92
-
93
- // return permission
94
- // })
95
- // }
96
- // })
32
+ // 👉 Fetch Query
33
+ const queryKeyword = ref (' ' )
34
+ const queryOptions = ref <ParsedFilterQuery > ({
35
+ keyword: ' ' ,
36
+ keywordLower: ' ' ,
37
+ sortBy: ' action' ,
38
+ sortAsc: true ,
39
+ limit: 10 ,
40
+ page: 1 ,
41
+ withCount: true ,
42
+ })
43
+
44
+ const handleSearch = debounce ((keyword : string ) => {
45
+ queryOptions .value .keyword = keyword
46
+ }, 1000 )
97
47
48
+ watch (queryKeyword , (newValue ) => {
49
+ handleSearch (newValue )
50
+ })
51
+
52
+ watch (queryOptions .value , async () => {
53
+ await fetchPermissions (queryOptions .value )
54
+ })
55
+
56
+ // 👉 select all and none
57
+ const isSelectAll = computed (() => {
58
+ return (
59
+ localRoleData .value .permissions ?.length === permissionList .value .length
60
+ )
61
+ })
62
+
63
+ function handleCheckAllPermissions() {
64
+ localRoleData .value .permissions = [... permissionList .value ]
65
+ }
66
+
67
+ function handleCheckNonePermissions() {
68
+ localRoleData .value .permissions = []
69
+ }
70
+
71
+ // 👉 Submit
98
72
function onReset() {
99
73
emit (' update:isDialogVisible' , false )
100
74
101
- isSelectAll .value = false
102
75
refPermissionForm .value ?.reset ()
103
76
104
77
localRoleData .value = {
105
78
id: ' ' ,
106
79
name: ' ' ,
80
+ permissions: [],
107
81
}
108
82
}
109
83
@@ -114,6 +88,7 @@ function onSubmit() {
114
88
? localRoleData .value
115
89
: {
116
90
name: localRoleData .value .name ,
91
+ permissions: localRoleData .value .permissions ,
117
92
})
118
93
119
94
onReset ()
@@ -123,12 +98,26 @@ function onSubmit() {
123
98
124
99
watch (() => props .roleData , (newRoleData ) => {
125
100
if (newRoleData ) {
126
- localRoleData .value = { ... newRoleData }
101
+ localRoleData .value = {
102
+ id: newRoleData .id ,
103
+ name: newRoleData .name ,
104
+ permissions: permissionList .value .filter (permission =>
105
+ newRoleData .permissions ?.some (p => p .id === permission .id ),
106
+ ),
107
+ }
127
108
}
128
109
}, { immediate: true })
129
110
130
- onMounted (() => {
131
- fetchPermissions ()
111
+ onMounted (async () => {
112
+ await fetchPermissions ()
113
+
114
+ if (props .roleData ) {
115
+ localRoleData .value .permissions = permissionList .value .filter (permission =>
116
+ props .roleData ?.permissions ?.some (p =>
117
+ p .id === permission .id ,
118
+ ),
119
+ )
120
+ }
132
121
})
133
122
</script >
134
123
@@ -169,7 +158,7 @@ onMounted(() => {
169
158
<VRow >
170
159
<VCol cols =" 12" md =" 4" class =" d-flex align-center" >
171
160
<h5 class =" text-h5" >
172
- Role Permissions
161
+ Permissions
173
162
</h5 >
174
163
</VCol >
175
164
@@ -180,20 +169,22 @@ onMounted(() => {
180
169
</p >
181
170
182
171
<VBtn
183
- color =" secondary"
172
+ : color =" isSelectAll ? 'primary' : ' secondary' "
184
173
variant =" text"
185
174
text =" All"
175
+ @click =" handleCheckAllPermissions"
186
176
/>
187
177
188
178
<VBtn
189
- color =" secondary"
179
+ : color =" localRoleData?.permissions?.length === 0 ? 'primary' : ' secondary' "
190
180
variant =" text"
191
181
text =" None"
182
+ @click =" handleCheckNonePermissions"
192
183
/>
193
184
194
185
<div class =" flex-grow-1" >
195
186
<VTextField
196
- v-model =" search "
187
+ v-model =" queryKeyword "
197
188
placeholder =" Search"
198
189
density =" compact"
199
190
prepend-inner-icon =" ri-search-line"
@@ -204,12 +195,22 @@ onMounted(() => {
204
195
</VRow >
205
196
206
197
<!-- 👉 Role Permissions -->
207
- <div class =" mt-6 d-flex flex-wrap gap-3" >
208
- <div v-for =" permission in permissionList" :key =" permission.id" class =" d-flex align-center gap-2 flex-wrap border px-3 py-2 " >
198
+ <div class =" mt-6 d-flex flex-wrap gap-3 permission-container " >
199
+ <div v-for =" permission in permissionList" :key =" permission.id" class =" d-flex align-center gap-2 flex-wrap" >
209
200
<VLabel >
210
- <VCheckboxBtn />
211
-
212
- {{ permission.action }}:{{ permission.subject }}
201
+ <VCheckbox
202
+ v-model =" localRoleData.permissions"
203
+ :value =" permission"
204
+ class =" border pa-2"
205
+ :class =" { 'border border-primary text-primary': localRoleData?.permissions && localRoleData?.permissions.some(p => p.id === permission.id) }"
206
+ multiple
207
+ >
208
+ <template #label >
209
+ <span class =" pr-3" :class =" { 'text-primary': localRoleData?.permissions && localRoleData?.permissions.some(p => p.id === permission.id) }" >
210
+ {{ permission.action }} : {{ permission.subject }}
211
+ </span >
212
+ </template >
213
+ </VCheckbox >
213
214
</VLabel >
214
215
</div >
215
216
</div >
@@ -235,4 +236,7 @@ onMounted(() => {
235
236
</template >
236
237
237
238
<style lang="scss" scoped>
239
+ .permission-container {
240
+ min-block-size : 150px ;
241
+ }
238
242
</style >
0 commit comments