@drax/identity-vue 0.5.3 → 0.5.5
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/package.json +6 -5
- package/src/combobox/RoleCombobox.vue +24 -19
- package/src/combobox/TenantCombobox.vue +11 -9
- package/src/components/IdentityChangeOwnPassword/IdentityChangeOwnPassword.vue +4 -4
- package/src/components/IdentityProfileDrawer/IdentityProfileDrawer.vue +2 -2
- package/src/components/PermissionSelector/PermissionSelector.vue +4 -7
- package/src/cruds/role-crud/RoleCrud.ts +91 -0
- package/src/cruds/role-crud/RoleForm.vue +116 -0
- package/src/cruds/tenant-crud/TenantCrud.ts +17 -3
- package/src/cruds/user-crud/PasswordUpdateButton.vue +25 -0
- package/src/cruds/user-crud/UserCrud.ts +112 -0
- package/src/cruds/user-crud/UserCrud.vue +4 -17
- package/src/cruds/user-crud/UserForm.vue +177 -0
- package/src/cruds/user-crud/UserPasswordDialog.vue +94 -0
- package/src/{forms → cruds/user-crud}/UserPasswordForm.vue +4 -2
- package/src/index.ts +7 -21
- package/src/pages/ProfilePage.vue +1 -1
- package/src/pages/crud/RoleCrudPage.vue +62 -0
- package/src/pages/{TenantCrudPage.vue → crud/TenantCrudPage.vue} +1 -1
- package/src/pages/{UserApiKeyCrudPage.vue → crud/UserApiKeyCrudPage.vue} +1 -1
- package/src/pages/crud/UserCrudPage.vue +61 -0
- package/src/routes/IdentityRoutes.ts +70 -64
- package/src/cruds/role-crud/RoleCrud.vue +0 -171
- package/src/cruds/role-crud/RoleList.vue +0 -129
- package/src/cruds/tenant-crud/TenantCrud.vue +0 -168
- package/src/cruds/tenant-crud/TenantList.vue +0 -108
- package/src/cruds/user-crud/UserList.vue +0 -110
- package/src/forms/RoleForm.vue +0 -57
- package/src/forms/TenantForm.vue +0 -48
- package/src/forms/UserCreateForm.vue +0 -115
- package/src/forms/UserEditForm.vue +0 -101
- package/src/pages/RoleCrudPage.vue +0 -12
- package/src/pages/TenantCrudPageOld.vue +0 -12
- package/src/pages/UserCrudPage.vue +0 -12
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.5.
|
|
6
|
+
"version": "0.5.5",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./src/index.ts",
|
|
9
9
|
"module": "./src/index.ts",
|
|
@@ -24,9 +24,10 @@
|
|
|
24
24
|
"format": "prettier --write src/"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@drax/common-front": "^0.5.
|
|
28
|
-
"@drax/common-vue": "^0.5.
|
|
29
|
-
"@drax/crud-
|
|
27
|
+
"@drax/common-front": "^0.5.5",
|
|
28
|
+
"@drax/common-vue": "^0.5.5",
|
|
29
|
+
"@drax/crud-front": "^0.5.3",
|
|
30
|
+
"@drax/crud-share": "^0.5.5",
|
|
30
31
|
"@drax/identity-share": "^0.5.1"
|
|
31
32
|
},
|
|
32
33
|
"peerDependencies": {
|
|
@@ -64,5 +65,5 @@
|
|
|
64
65
|
"vue-tsc": "^2.1.6",
|
|
65
66
|
"vuetify": "^3.7.1"
|
|
66
67
|
},
|
|
67
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "c89751dd8eb2ede7d565b596f698c2b83e0c2fed"
|
|
68
69
|
}
|
|
@@ -1,44 +1,49 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
3
2
|
import {ref, onMounted, defineModel} from 'vue'
|
|
4
|
-
import type {
|
|
3
|
+
import type {PropType} from 'vue'
|
|
4
|
+
import type {IRole} from "@drax/identity-share";
|
|
5
|
+
import {useRole} from "../composables/useRole";
|
|
6
|
+
import {useI18n} from "vue-i18n";
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const {t,te} = useI18n()
|
|
10
|
+
|
|
11
|
+
|
|
5
12
|
defineProps({
|
|
6
|
-
errorMessages: {
|
|
7
|
-
|
|
8
|
-
},
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
},
|
|
13
|
-
|
|
14
|
-
type: Boolean,
|
|
15
|
-
default: false,
|
|
16
|
-
}
|
|
13
|
+
errorMessages: {type: String as PropType<string | string[] | undefined>},
|
|
14
|
+
rules: {type: Array as PropType<any[]>, default: () => []},
|
|
15
|
+
multiple: {type: Boolean, default: false},
|
|
16
|
+
clearable: {type: Boolean, default: false},
|
|
17
|
+
readonly: {type: Boolean, default: false},
|
|
18
|
+
label: {type: String, default: 'role.entity'},
|
|
19
|
+
density: {type: String as PropType<'comfortable' | 'compact' | 'default'>, default: 'default'},
|
|
20
|
+
variant: {type: String as PropType<'underlined' | 'outlined' | 'filled' | 'solo' | 'solo-inverted' | 'solo-filled' | 'plain'>, default: 'filled'},
|
|
17
21
|
})
|
|
18
22
|
|
|
19
23
|
const model = defineModel<any>()
|
|
20
|
-
|
|
24
|
+
|
|
21
25
|
const {fetchRole} = useRole()
|
|
22
|
-
let items = ref([])
|
|
26
|
+
let items = ref<IRole[]>([])
|
|
23
27
|
|
|
24
28
|
onMounted(async () => {
|
|
25
29
|
items.value = await fetchRole()
|
|
26
30
|
})
|
|
27
|
-
|
|
28
|
-
|
|
29
31
|
</script>
|
|
30
32
|
|
|
31
33
|
<template>
|
|
32
34
|
<v-select
|
|
33
35
|
v-model="model"
|
|
34
|
-
label="
|
|
36
|
+
:label="te(label) ? t(label) : label"
|
|
35
37
|
:items="items"
|
|
36
38
|
item-title="name"
|
|
37
39
|
item-value="id"
|
|
38
|
-
variant="
|
|
40
|
+
:variant="variant"
|
|
39
41
|
:error-messages="errorMessages"
|
|
40
42
|
:multiple="multiple"
|
|
41
43
|
:clearable="clearable"
|
|
44
|
+
:readonly="readonly"
|
|
45
|
+
:density="density"
|
|
46
|
+
:rules="rules"
|
|
42
47
|
></v-select>
|
|
43
48
|
</template>
|
|
44
49
|
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
import {ref, onMounted, defineModel} from 'vue'
|
|
4
4
|
import type { PropType } from 'vue'
|
|
5
5
|
import {useI18n} from "vue-i18n";
|
|
6
|
-
const {t} = useI18n()
|
|
6
|
+
const {t,te} = useI18n()
|
|
7
7
|
defineProps({
|
|
8
|
-
errorMessages: {
|
|
9
|
-
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
8
|
+
errorMessages: {type: String as PropType<string | string[] | undefined>,},
|
|
9
|
+
clearable: {type: Boolean, default: false},
|
|
10
|
+
readonly: {type: Boolean, default: false},
|
|
11
|
+
rules: {type: Array as PropType<any[]>, default: () => []},
|
|
12
|
+
label: {type: String, default: 'tenant.entity'},
|
|
13
|
+
density: {type: String as PropType<'comfortable' | 'compact' | 'default'>, default: 'default'},
|
|
14
|
+
variant: {type: String as PropType<'underlined' | 'outlined' | 'filled' | 'solo' | 'solo-inverted' | 'solo-filled' | 'plain'>, default: 'filled'},
|
|
15
15
|
})
|
|
16
16
|
|
|
17
17
|
const model = defineModel<any>()
|
|
@@ -29,13 +29,15 @@ onMounted(async () => {
|
|
|
29
29
|
<template>
|
|
30
30
|
<v-select
|
|
31
31
|
v-model="model"
|
|
32
|
-
:label="
|
|
32
|
+
:label="te(label) ? t(label) : label"
|
|
33
33
|
:items="items"
|
|
34
34
|
item-title="name"
|
|
35
35
|
item-value="id"
|
|
36
36
|
variant="outlined"
|
|
37
37
|
:error-messages="errorMessages"
|
|
38
38
|
:clearable="clearable"
|
|
39
|
+
:rules="rules"
|
|
40
|
+
:readonly="readonly"
|
|
39
41
|
></v-select>
|
|
40
42
|
</template>
|
|
41
43
|
|
|
@@ -65,14 +65,14 @@ async function submitChangePassowrd() {
|
|
|
65
65
|
|
|
66
66
|
<v-form @submit.prevent="submitChangePassowrd">
|
|
67
67
|
<v-card variant="elevated">
|
|
68
|
-
<v-card-title class="pa-4 text-center">{{ t('user.changeOwnPassword') }}</v-card-title>
|
|
68
|
+
<v-card-title class="pa-4 text-center">{{ t('user.action.changeOwnPassword') }}</v-card-title>
|
|
69
69
|
<v-card-text v-if="errorMsg">
|
|
70
70
|
<v-alert type="error">
|
|
71
71
|
{{ te(errorMsg) ?t(errorMsg) : errorMsg }}
|
|
72
72
|
</v-alert>
|
|
73
73
|
</v-card-text>
|
|
74
74
|
<v-card-text>
|
|
75
|
-
<div class="text-subtitle-1 text-medium-emphasis">{{ t('user.currentPassword') }}</div>
|
|
75
|
+
<div class="text-subtitle-1 text-medium-emphasis">{{ t('user.field.currentPassword') }}</div>
|
|
76
76
|
<v-text-field
|
|
77
77
|
variant="outlined"
|
|
78
78
|
id="current-password-input"
|
|
@@ -85,7 +85,7 @@ async function submitChangePassowrd() {
|
|
|
85
85
|
autocomplete="new-password"
|
|
86
86
|
:error-messages="$ta(inputErrors?.currentPassword)"
|
|
87
87
|
></v-text-field>
|
|
88
|
-
<div class="text-subtitle-1 text-medium-emphasis">{{ t('user.newPassword') }}</div>
|
|
88
|
+
<div class="text-subtitle-1 text-medium-emphasis">{{ t('user.field.newPassword') }}</div>
|
|
89
89
|
<v-text-field
|
|
90
90
|
variant="outlined"
|
|
91
91
|
id="new-password-input"
|
|
@@ -98,7 +98,7 @@ async function submitChangePassowrd() {
|
|
|
98
98
|
autocomplete="new-password"
|
|
99
99
|
:error-messages="$ta(inputErrors?.newPassword)"
|
|
100
100
|
></v-text-field>
|
|
101
|
-
<div class="text-subtitle-1 text-medium-emphasis">{{ t('user.confirmPassword') }}</div>
|
|
101
|
+
<div class="text-subtitle-1 text-medium-emphasis">{{ t('user.field.confirmPassword') }}</div>
|
|
102
102
|
<v-text-field
|
|
103
103
|
variant="outlined"
|
|
104
104
|
id="confirm-password-input"
|
|
@@ -37,7 +37,7 @@ const valueModel = defineModel<boolean>()
|
|
|
37
37
|
<v-list-item
|
|
38
38
|
@click="auth.logout()"
|
|
39
39
|
prepend-icon="mdi-logout"
|
|
40
|
-
:title="t('user.logout')"
|
|
40
|
+
:title="t('user.action.logout')"
|
|
41
41
|
>
|
|
42
42
|
</v-list-item>
|
|
43
43
|
</v-list>
|
|
@@ -48,7 +48,7 @@ const valueModel = defineModel<boolean>()
|
|
|
48
48
|
<v-list-item
|
|
49
49
|
href="/login"
|
|
50
50
|
prepend-icon="mdi-login"
|
|
51
|
-
:title="t('user.login')"
|
|
51
|
+
:title="t('user.action.login')"
|
|
52
52
|
>
|
|
53
53
|
</v-list-item>
|
|
54
54
|
</v-list>
|
|
@@ -6,9 +6,8 @@ import {useI18n} from "vue-i18n";
|
|
|
6
6
|
const {t,te} = useI18n()
|
|
7
7
|
|
|
8
8
|
defineProps({
|
|
9
|
-
errorMessages: {
|
|
10
|
-
|
|
11
|
-
}
|
|
9
|
+
errorMessages: {type: String as PropType<string | string[] | undefined>,},
|
|
10
|
+
readonly: {type: Boolean, default: false},
|
|
12
11
|
})
|
|
13
12
|
|
|
14
13
|
const model = defineModel()
|
|
@@ -68,17 +67,15 @@ const permissionGroups = computed(() => {
|
|
|
68
67
|
<v-item
|
|
69
68
|
v-for="permission in permissions"
|
|
70
69
|
v-slot="{ isSelected, toggle }"
|
|
71
|
-
:value="permission"
|
|
70
|
+
:value="permission" :disabled="readonly"
|
|
72
71
|
>
|
|
73
72
|
|
|
74
73
|
<v-chip
|
|
75
|
-
:color="isSelected? 'green' : 'grey-darken-3'"
|
|
74
|
+
:color="isSelected? 'green' : 'grey-darken-3'" :disabled="readonly"
|
|
76
75
|
@click="toggle" variant="flat" :rounded="false" border
|
|
77
76
|
>
|
|
78
77
|
{{ te('permission.'+permission) ? t('permission.'+permission) : permission }}
|
|
79
78
|
</v-chip>
|
|
80
|
-
|
|
81
|
-
|
|
82
79
|
</v-item>
|
|
83
80
|
</v-card-text>
|
|
84
81
|
</v-card>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
|
|
2
|
+
import {EntityCrud} from "@drax/crud-vue";
|
|
3
|
+
import {RoleSystemFactory} from "@drax/identity-front";
|
|
4
|
+
import type {IEntityCrud, IEntityCrudField, IEntityCrudFilter, IEntityCrudHeader} from "@drax/crud-share";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class RoleCrud extends EntityCrud implements IEntityCrud {
|
|
8
|
+
|
|
9
|
+
static singleton: RoleCrud
|
|
10
|
+
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
this.name = 'Role'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static get instance(): RoleCrud {
|
|
17
|
+
if(!RoleCrud.singleton){
|
|
18
|
+
RoleCrud.singleton = new RoleCrud()
|
|
19
|
+
}
|
|
20
|
+
return RoleCrud.singleton
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get permissions(){
|
|
24
|
+
return {
|
|
25
|
+
manage: 'tenant:manage',
|
|
26
|
+
view: 'tenant:view',
|
|
27
|
+
create: 'tenant:create',
|
|
28
|
+
update: 'tenant:update',
|
|
29
|
+
delete: 'tenant:delete'
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get headers():IEntityCrudHeader[] {
|
|
34
|
+
return [
|
|
35
|
+
//{title: 'id',key:'_id', align: 'start'},
|
|
36
|
+
{title: 'name',key:'name', align: 'start'},
|
|
37
|
+
{title: 'permissions',key:'permissions', align: 'start'},
|
|
38
|
+
{title: 'childRoles',key:'childRoles', align: 'start'},
|
|
39
|
+
{title: 'readonly',key:'readonly', align: 'start'},
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get provider(){
|
|
44
|
+
return RoleSystemFactory.getInstance()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get refs(){
|
|
48
|
+
return {
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get rules(){
|
|
54
|
+
return {
|
|
55
|
+
name: [(v: any) => !!v || 'Requerido']
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
get fields(): IEntityCrudField[]{
|
|
60
|
+
return [
|
|
61
|
+
{name: 'name', type: 'string', label: 'name', default:'', prependInnerIcon:'mdi-text-short' }
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get filters():IEntityCrudFilter[]{
|
|
66
|
+
return [
|
|
67
|
+
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get dialogFullscreen(){
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get exportHeaders(){
|
|
76
|
+
return ['_id', 'name','permissions','childRoles','readonly']
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get isExportable(){
|
|
80
|
+
return true
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get isImportable(){
|
|
84
|
+
return false
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export default RoleCrud
|
|
90
|
+
|
|
91
|
+
export {RoleCrud}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {useFormUtils, useCrudStore} from "@drax/crud-vue";
|
|
3
|
+
import {defineEmits, defineModel, ref} from "vue";
|
|
4
|
+
import {useI18nValidation} from "@drax/common-vue";
|
|
5
|
+
import PermissionSelector from "../../components/PermissionSelector/PermissionSelector.vue";
|
|
6
|
+
import RoleCombobox from "../../combobox/RoleCombobox.vue";
|
|
7
|
+
import {useI18n} from "vue-i18n";
|
|
8
|
+
|
|
9
|
+
const {$ta} = useI18nValidation()
|
|
10
|
+
const {t, te} = useI18n()
|
|
11
|
+
|
|
12
|
+
const valueModel = defineModel({type: [Object]})
|
|
13
|
+
|
|
14
|
+
const emit = defineEmits(['submit', 'cancel'])
|
|
15
|
+
|
|
16
|
+
const store = useCrudStore()
|
|
17
|
+
|
|
18
|
+
const valid = ref()
|
|
19
|
+
const formRef = ref()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
async function submit() {
|
|
23
|
+
store.resetErrors()
|
|
24
|
+
await formRef.value.validate()
|
|
25
|
+
if (valid.value) {
|
|
26
|
+
emit('submit', valueModel.value)
|
|
27
|
+
} else {
|
|
28
|
+
console.log('Invalid form')
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function cancel() {
|
|
33
|
+
emit('cancel')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const {
|
|
37
|
+
variant, submitColor, readonly
|
|
38
|
+
} = useFormUtils(store.operation)
|
|
39
|
+
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<template>
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
<v-form v-model="valid" ref="formRef" @submit.prevent="submit">
|
|
46
|
+
<v-card flat>
|
|
47
|
+
<v-alert v-if="valueModel.readonly && store.operation != 'view'" type="warning">
|
|
48
|
+
{{ t('role.readonly') }}
|
|
49
|
+
</v-alert>
|
|
50
|
+
|
|
51
|
+
<template v-if="!valueModel.readonly || store.operation == 'view'">
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
<v-card-subtitle v-if="valueModel._id">ID: {{ valueModel._id }}</v-card-subtitle>
|
|
55
|
+
|
|
56
|
+
<v-card-text v-if="store.error">
|
|
57
|
+
<v-alert color="error">{{ te(store.error) ? t(store.error) : store.error }}</v-alert>
|
|
58
|
+
</v-card-text>
|
|
59
|
+
|
|
60
|
+
<v-card-text>
|
|
61
|
+
|
|
62
|
+
<v-text-field
|
|
63
|
+
id="name-input"
|
|
64
|
+
name="name"
|
|
65
|
+
:label="$t('role.field.name')"
|
|
66
|
+
v-model="valueModel.name"
|
|
67
|
+
prepend-inner-icon="mdi-card-account-details"
|
|
68
|
+
:variant="variant"
|
|
69
|
+
:error-messages="$ta(store.inputErrors?.name)"
|
|
70
|
+
:rules="[v => !!v || 'validation.required']"
|
|
71
|
+
density="default"
|
|
72
|
+
:readonly="readonly"
|
|
73
|
+
:clearable="false"
|
|
74
|
+
></v-text-field>
|
|
75
|
+
|
|
76
|
+
<RoleCombobox
|
|
77
|
+
v-model="valueModel.childRoles"
|
|
78
|
+
label="role.field.childRoles"
|
|
79
|
+
:error-messages="$ta(store.inputErrors?.role)"
|
|
80
|
+
multiple
|
|
81
|
+
:readonly="readonly"
|
|
82
|
+
:variant="variant"
|
|
83
|
+
></RoleCombobox>
|
|
84
|
+
|
|
85
|
+
<PermissionSelector
|
|
86
|
+
v-model="valueModel.permissions"
|
|
87
|
+
:readonly="readonly"
|
|
88
|
+
></PermissionSelector>
|
|
89
|
+
|
|
90
|
+
</v-card-text>
|
|
91
|
+
</template>
|
|
92
|
+
|
|
93
|
+
<v-card-actions>
|
|
94
|
+
<v-spacer></v-spacer>
|
|
95
|
+
<v-btn
|
|
96
|
+
variant="text"
|
|
97
|
+
color="grey"
|
|
98
|
+
@click="cancel">
|
|
99
|
+
{{ t('action.cancel') }}
|
|
100
|
+
</v-btn>
|
|
101
|
+
<v-btn
|
|
102
|
+
v-if="!valueModel.readonly && store.operation != 'view'"
|
|
103
|
+
variant="flat"
|
|
104
|
+
:color="submitColor"
|
|
105
|
+
@click="submit"
|
|
106
|
+
>
|
|
107
|
+
{{ store.operation ? t('action.' + store.operation) : t('action.sent') }}
|
|
108
|
+
</v-btn>
|
|
109
|
+
</v-card-actions>
|
|
110
|
+
</v-card>
|
|
111
|
+
</v-form>
|
|
112
|
+
</template>
|
|
113
|
+
|
|
114
|
+
<style scoped>
|
|
115
|
+
|
|
116
|
+
</style>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import {EntityCrud} from "@drax/crud-vue";
|
|
3
3
|
import {TenantSystemFactory} from "@drax/identity-front";
|
|
4
|
-
import type {IEntityCrud, IEntityCrudField, IEntityCrudHeader} from "@drax/crud-share";
|
|
4
|
+
import type {IEntityCrud, IEntityCrudField, IEntityCrudFilter, IEntityCrudHeader} from "@drax/crud-share";
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class TenantCrud extends EntityCrud implements IEntityCrud {
|
|
@@ -55,7 +55,13 @@ class TenantCrud extends EntityCrud implements IEntityCrud {
|
|
|
55
55
|
|
|
56
56
|
get fields(): IEntityCrudField[]{
|
|
57
57
|
return [
|
|
58
|
-
{name: 'name', type: 'string', label: 'name', default:'' }
|
|
58
|
+
{name: 'name', type: 'string', label: 'name', default:'', prependInnerIcon:'mdi-text-short' }
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get filters():IEntityCrudFilter[]{
|
|
63
|
+
return [
|
|
64
|
+
|
|
59
65
|
]
|
|
60
66
|
}
|
|
61
67
|
|
|
@@ -67,7 +73,15 @@ class TenantCrud extends EntityCrud implements IEntityCrud {
|
|
|
67
73
|
return ['_id', 'name']
|
|
68
74
|
}
|
|
69
75
|
|
|
76
|
+
get isExportable(){
|
|
77
|
+
return true
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get isImportable(){
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
|
|
70
84
|
}
|
|
71
85
|
|
|
72
86
|
export default TenantCrud
|
|
73
|
-
|
|
87
|
+
export { TenantCrud }
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {useI18n} from "vue-i18n";
|
|
3
|
+
const {t} = useI18n()
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<template>
|
|
7
|
+
<v-tooltip location="top">
|
|
8
|
+
<template v-slot:activator="{ props}">
|
|
9
|
+
<v-btn
|
|
10
|
+
v-bind="{ ...$attrs, ...props }"
|
|
11
|
+
icon="mdi-form-textbox-password"
|
|
12
|
+
class="mr-1"
|
|
13
|
+
variant="text"
|
|
14
|
+
color="orange"
|
|
15
|
+
slim
|
|
16
|
+
>
|
|
17
|
+
</v-btn>
|
|
18
|
+
</template>
|
|
19
|
+
{{ t('user.action.changePassword')}}
|
|
20
|
+
</v-tooltip>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<style scoped>
|
|
24
|
+
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import {EntityCrud} from "@drax/crud-vue";
|
|
4
|
+
import {UserSystemFactory} from "@drax/identity-front";
|
|
5
|
+
import {RoleCrud} from '../role-crud/RoleCrud'
|
|
6
|
+
import {TenantCrud} from '../tenant-crud/TenantCrud'
|
|
7
|
+
import type {
|
|
8
|
+
IEntityCrud,
|
|
9
|
+
IEntityCrudField,
|
|
10
|
+
IEntityCrudFilter,
|
|
11
|
+
IEntityCrudHeader,
|
|
12
|
+
IEntityCrudRefs
|
|
13
|
+
} from "@drax/crud-share";
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class UserCrud extends EntityCrud implements IEntityCrud {
|
|
17
|
+
|
|
18
|
+
static singleton: UserCrud
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
super();
|
|
22
|
+
this.name = 'User'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static get instance(): UserCrud {
|
|
26
|
+
if(!UserCrud.singleton){
|
|
27
|
+
UserCrud.singleton = new UserCrud()
|
|
28
|
+
}
|
|
29
|
+
return UserCrud.singleton
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get permissions(){
|
|
33
|
+
return {
|
|
34
|
+
manage: 'tenant:manage',
|
|
35
|
+
view: 'tenant:view',
|
|
36
|
+
create: 'tenant:create',
|
|
37
|
+
update: 'tenant:update',
|
|
38
|
+
delete: 'tenant:delete'
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get headers():IEntityCrudHeader[] {
|
|
43
|
+
return [
|
|
44
|
+
//{title: 'id',key:'_id', align: 'start'},
|
|
45
|
+
{ title: 'name', key: 'name', align: 'start' },
|
|
46
|
+
{ title: 'username', key: 'username', align: 'start' },
|
|
47
|
+
{ title: 'email', key: 'email', align: 'start' },
|
|
48
|
+
{ title: 'role', key: 'role.name', align: 'start' },
|
|
49
|
+
{ title: 'tenant', key: 'tenant.name', align: 'start' },
|
|
50
|
+
{ title: 'active', key: 'active', align: 'start' },
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get provider(){
|
|
55
|
+
return UserSystemFactory.getInstance()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get refs():IEntityCrudRefs{
|
|
59
|
+
return {
|
|
60
|
+
role: RoleCrud.instance,
|
|
61
|
+
tenant: TenantCrud.instance,
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get rules(){
|
|
66
|
+
return {
|
|
67
|
+
name: [(v: any) => !!v || 'Requerido']
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get fields(): IEntityCrudField[]{
|
|
72
|
+
return [
|
|
73
|
+
{name: 'name', type: 'string', label: 'name', default:'' },
|
|
74
|
+
{name: 'username', type: 'string', label: 'username', default:'' },
|
|
75
|
+
{name: 'email', type: 'string', label: 'email', default:'' },
|
|
76
|
+
{name: 'phone', type: 'string', label: 'phone', default:'' },
|
|
77
|
+
{name: 'role', type: 'ref', ref: 'role', label: 'role', default:null },
|
|
78
|
+
{name: 'tenant', type: 'ref', ref: 'tenant', label: 'tenant', default:null },
|
|
79
|
+
{name: 'active', type: 'boolean', label: 'active', default:true },
|
|
80
|
+
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get filters():IEntityCrudFilter[]{
|
|
85
|
+
return [
|
|
86
|
+
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get dialogFullscreen(){
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
get exportHeaders(){
|
|
95
|
+
return ['_id', 'name','username','email','phone','role.name','tenant.name','active']
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get exportFormats(){
|
|
99
|
+
return ['CSV']
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
get isExportable(){
|
|
103
|
+
return true
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
get isImportable(){
|
|
107
|
+
return false
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export default UserCrud
|
|
112
|
+
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import {computed, ref} from 'vue'
|
|
3
|
-
import UserList from "./UserList.vue";
|
|
4
3
|
import {useUser} from "../../composables/useUser";
|
|
5
4
|
import type {IUser, IUserCreate, IUserUpdate} from "@drax/identity-share";
|
|
6
5
|
import type {IUserPassword} from "@drax/identity-front";
|
|
7
|
-
import UserCreateForm from "
|
|
8
|
-
import
|
|
9
|
-
import UserPasswordForm from "../../forms/UserPasswordForm.vue";
|
|
6
|
+
import UserCreateForm from "./UserForm.vue";
|
|
7
|
+
import UserPasswordForm from "./UserPasswordForm.vue";
|
|
10
8
|
import UserView from "../../views/UserView.vue";
|
|
11
9
|
import {useI18n} from "vue-i18n";
|
|
12
10
|
|
|
@@ -154,13 +152,7 @@ function toChangePassword(item: IUser) {
|
|
|
154
152
|
</v-btn>
|
|
155
153
|
</v-toolbar>
|
|
156
154
|
<v-theme-provider with-background class="pa-2 rounded-b">
|
|
157
|
-
|
|
158
|
-
ref="userList"
|
|
159
|
-
@toEdit="toEdit"
|
|
160
|
-
@toDelete="toDelete"
|
|
161
|
-
@toChangePassword="toChangePassword"
|
|
162
|
-
:filterEnable="filterEnable"
|
|
163
|
-
/>
|
|
155
|
+
|
|
164
156
|
</v-theme-provider>
|
|
165
157
|
</v-card>
|
|
166
158
|
|
|
@@ -181,12 +173,7 @@ function toChangePassword(item: IUser) {
|
|
|
181
173
|
@formSubmit="save"
|
|
182
174
|
/>
|
|
183
175
|
|
|
184
|
-
|
|
185
|
-
v-if="dialogMode === 'edit'"
|
|
186
|
-
v-model="editForm"
|
|
187
|
-
:inputErrors="inputErrors"
|
|
188
|
-
@formSubmit="save"
|
|
189
|
-
/>
|
|
176
|
+
|
|
190
177
|
|
|
191
178
|
<UserView v-if="dialogMode === 'delete'
|
|
192
179
|
&& target" :user="target"
|