@drax/identity-vue 0.5.4 → 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.
Files changed (35) hide show
  1. package/package.json +5 -5
  2. package/src/combobox/RoleCombobox.vue +9 -1
  3. package/src/combobox/TenantCombobox.vue +11 -9
  4. package/src/components/IdentityChangeOwnPassword/IdentityChangeOwnPassword.vue +4 -4
  5. package/src/components/IdentityProfileDrawer/IdentityProfileDrawer.vue +2 -2
  6. package/src/cruds/role-crud/RoleCrud.ts +9 -1
  7. package/src/cruds/role-crud/RoleForm.vue +116 -0
  8. package/src/cruds/tenant-crud/TenantCrud.ts +8 -0
  9. package/src/cruds/user-crud/PasswordUpdateButton.vue +25 -0
  10. package/src/cruds/user-crud/UserCrud.ts +11 -0
  11. package/src/cruds/user-crud/UserCrud.vue +4 -17
  12. package/src/cruds/user-crud/UserForm.vue +177 -0
  13. package/src/cruds/user-crud/UserPasswordDialog.vue +94 -0
  14. package/src/{forms → cruds/user-crud}/UserPasswordForm.vue +4 -2
  15. package/src/index.ts +7 -21
  16. package/src/pages/ProfilePage.vue +1 -1
  17. package/src/pages/{RoleCrudPage.vue → crud/RoleCrudPage.vue} +11 -10
  18. package/src/pages/{TenantCrudPage.vue → crud/TenantCrudPage.vue} +1 -1
  19. package/src/pages/{UserApiKeyCrudPage.vue → crud/UserApiKeyCrudPage.vue} +1 -1
  20. package/src/pages/crud/UserCrudPage.vue +61 -0
  21. package/src/routes/IdentityRoutes.ts +5 -35
  22. package/src/cruds/role-crud/RoleCrud.vue +0 -171
  23. package/src/cruds/role-crud/RoleList.vue +0 -129
  24. package/src/cruds/tenant-crud/TenantCrud.vue +0 -168
  25. package/src/cruds/tenant-crud/TenantList.vue +0 -108
  26. package/src/cruds/user-crud/UserList.vue +0 -110
  27. package/src/forms/RoleForm.vue +0 -89
  28. package/src/forms/RoleFormOld.vue +0 -57
  29. package/src/forms/TenantForm.vue +0 -48
  30. package/src/forms/UserCreateForm.vue +0 -115
  31. package/src/forms/UserEditForm.vue +0 -101
  32. package/src/pages/RoleCrudCustomPage.vue +0 -12
  33. package/src/pages/TenantCrudCustomPage.vue +0 -12
  34. package/src/pages/UserCrudCustomPage.vue +0 -12
  35. package/src/pages/UserCrudPage.vue +0 -18
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.5.4",
6
+ "version": "0.5.5",
7
7
  "type": "module",
8
8
  "main": "./src/index.ts",
9
9
  "module": "./src/index.ts",
@@ -24,10 +24,10 @@
24
24
  "format": "prettier --write src/"
25
25
  },
26
26
  "dependencies": {
27
- "@drax/common-front": "^0.5.4",
28
- "@drax/common-vue": "^0.5.4",
27
+ "@drax/common-front": "^0.5.5",
28
+ "@drax/common-vue": "^0.5.5",
29
29
  "@drax/crud-front": "^0.5.3",
30
- "@drax/crud-share": "^0.5.4",
30
+ "@drax/crud-share": "^0.5.5",
31
31
  "@drax/identity-share": "^0.5.1"
32
32
  },
33
33
  "peerDependencies": {
@@ -65,5 +65,5 @@
65
65
  "vue-tsc": "^2.1.6",
66
66
  "vuetify": "^3.7.1"
67
67
  },
68
- "gitHead": "6db0bebb2df9edecd2c3caa7288fb5c7001c4243"
68
+ "gitHead": "c89751dd8eb2ede7d565b596f698c2b83e0c2fed"
69
69
  }
@@ -3,12 +3,19 @@ import {ref, onMounted, defineModel} from 'vue'
3
3
  import type {PropType} from 'vue'
4
4
  import type {IRole} from "@drax/identity-share";
5
5
  import {useRole} from "../composables/useRole";
6
+ import {useI18n} from "vue-i18n";
7
+
8
+
9
+ const {t,te} = useI18n()
10
+
6
11
 
7
12
  defineProps({
8
13
  errorMessages: {type: String as PropType<string | string[] | undefined>},
14
+ rules: {type: Array as PropType<any[]>, default: () => []},
9
15
  multiple: {type: Boolean, default: false},
10
16
  clearable: {type: Boolean, default: false},
11
17
  readonly: {type: Boolean, default: false},
18
+ label: {type: String, default: 'role.entity'},
12
19
  density: {type: String as PropType<'comfortable' | 'compact' | 'default'>, default: 'default'},
13
20
  variant: {type: String as PropType<'underlined' | 'outlined' | 'filled' | 'solo' | 'solo-inverted' | 'solo-filled' | 'plain'>, default: 'filled'},
14
21
  })
@@ -26,7 +33,7 @@ onMounted(async () => {
26
33
  <template>
27
34
  <v-select
28
35
  v-model="model"
29
- label="Rol"
36
+ :label="te(label) ? t(label) : label"
30
37
  :items="items"
31
38
  item-title="name"
32
39
  item-value="id"
@@ -36,6 +43,7 @@ onMounted(async () => {
36
43
  :clearable="clearable"
37
44
  :readonly="readonly"
38
45
  :density="density"
46
+ :rules="rules"
39
47
  ></v-select>
40
48
  </template>
41
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
- type: String as PropType<string | string[] | undefined>,
10
- },
11
- clearable: {
12
- type: Boolean,
13
- default: false,
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="t ? t('tenant.entity') : 'Tenant'"
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>
@@ -73,7 +73,15 @@ class RoleCrud extends EntityCrud implements IEntityCrud {
73
73
  }
74
74
 
75
75
  get exportHeaders(){
76
- return ['_id', 'name']
76
+ return ['_id', 'name','permissions','childRoles','readonly']
77
+ }
78
+
79
+ get isExportable(){
80
+ return true
81
+ }
82
+
83
+ get isImportable(){
84
+ return false
77
85
  }
78
86
 
79
87
  }
@@ -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>
@@ -73,6 +73,14 @@ class TenantCrud extends EntityCrud implements IEntityCrud {
73
73
  return ['_id', 'name']
74
74
  }
75
75
 
76
+ get isExportable(){
77
+ return true
78
+ }
79
+
80
+ get isImportable(){
81
+ return false
82
+ }
83
+
76
84
  }
77
85
 
78
86
  export default 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>
@@ -95,6 +95,17 @@ class UserCrud extends EntityCrud implements IEntityCrud {
95
95
  return ['_id', 'name','username','email','phone','role.name','tenant.name','active']
96
96
  }
97
97
 
98
+ get exportFormats(){
99
+ return ['CSV']
100
+ }
101
+
102
+ get isExportable(){
103
+ return true
104
+ }
105
+
106
+ get isImportable(){
107
+ return false
108
+ }
98
109
  }
99
110
 
100
111
  export default UserCrud
@@ -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 "../../forms/UserCreateForm.vue";
8
- import UserEditForm from "../../forms/UserEditForm.vue";
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
- <UserList
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
- <UserEditForm
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"
@@ -0,0 +1,177 @@
1
+ <script setup lang="ts">
2
+ import {useFormUtils, useCrudStore} from "@drax/crud-vue";
3
+ import {defineEmits, defineModel, defineProps, ref} from "vue";
4
+ import {useI18nValidation} from "@drax/common-vue";
5
+ import RoleCombobox from "../../combobox/RoleCombobox.vue";
6
+ import TenantCombobox from "../../combobox/TenantCombobox.vue";
7
+ import {useI18n} from "vue-i18n";
8
+
9
+ const {$ta} = useI18nValidation()
10
+ const {t, te} = useI18n()
11
+
12
+ defineProps({
13
+ enablePassword: {type: Boolean, default: false}
14
+ })
15
+
16
+ const valueModel = defineModel({type: [Object]})
17
+
18
+ const emit = defineEmits(['submit', 'cancel'])
19
+
20
+ const store = useCrudStore()
21
+
22
+ const valid = ref()
23
+ const formRef = ref()
24
+
25
+
26
+ async function submit() {
27
+ store.resetErrors()
28
+ await formRef.value.validate()
29
+ if (valid.value) {
30
+ emit('submit', valueModel.value)
31
+ } else {
32
+ console.log('Invalid form')
33
+ }
34
+ }
35
+
36
+ function cancel() {
37
+ emit('cancel')
38
+ }
39
+
40
+ const {
41
+ variant, submitColor, readonly
42
+ } = useFormUtils(store.operation)
43
+
44
+
45
+ let passwordVisibility = ref(false)
46
+
47
+ </script>
48
+
49
+ <template>
50
+ <v-form v-model="valid" ref="formRef" @submit.prevent="submit">
51
+ <v-card flat>
52
+
53
+ <v-alert v-if="valueModel.readonly && store.operation != 'view'" type="warning">
54
+ {{ t('role.readonly') }}
55
+ </v-alert>
56
+
57
+ <v-card-text v-if="store.error">
58
+ <v-alert color="error">{{ te(store.error) ? t(store.error) : store.error }}</v-alert>
59
+ </v-card-text>
60
+
61
+ <v-card-text>
62
+
63
+ <v-text-field
64
+ id="name-input"
65
+ :label="$t('user.field.name')"
66
+ v-model="valueModel.name"
67
+ prepend-inner-icon="mdi-card-account-details"
68
+ :variant="variant"
69
+ :rules="[v => !!v || t('validation.required')]"
70
+ :error-messages="$ta(store.inputErrors?.name)"
71
+ :readonly="readonly"
72
+ ></v-text-field>
73
+
74
+ <v-text-field
75
+ id="username-input"
76
+ :label="$t('user.field.username')"
77
+ v-model="valueModel.username"
78
+ prepend-inner-icon="mdi-account-question"
79
+ :variant="variant"
80
+ :rules="[v => !!v || t('validation.required')]"
81
+ autocomplete="new-username"
82
+ :error-messages="$ta(store.inputErrors?.username)"
83
+ :readonly="readonly"
84
+ ></v-text-field>
85
+
86
+ <v-text-field
87
+ v-if="enablePassword"
88
+ id="password-input"
89
+ :label="$t('user.field.password')"
90
+ v-model="valueModel.password"
91
+ :type="passwordVisibility ? 'text': 'password'"
92
+ :variant="variant"
93
+ :rules="[v => !!v || t('validation.required')]"
94
+ prepend-inner-icon="mdi-lock-outline"
95
+ :append-inner-icon="passwordVisibility ? 'mdi-eye-off': 'mdi-eye'"
96
+ @click:append-inner="passwordVisibility = !passwordVisibility"
97
+ autocomplete="new-password"
98
+ :error-messages="$ta(store.inputErrors?.password)"
99
+ :readonly="readonly"
100
+ ></v-text-field>
101
+
102
+ <RoleCombobox
103
+ v-model="valueModel.role"
104
+ :label="$t('user.field.role')"
105
+ :variant="variant"
106
+ :rules="[(v:any) => !!v || t('validation.required')]"
107
+ :error-messages="$ta(store.inputErrors?.role)"
108
+ :readonly="readonly"
109
+ ></RoleCombobox>
110
+
111
+ <TenantCombobox
112
+ v-model="valueModel.tenant"
113
+ :label="$t('user.field.tenant')"
114
+ :variant="variant"
115
+ :error-messages="$ta(store.inputErrors?.tenant)"
116
+ clearable
117
+ :readonly="readonly"
118
+ ></TenantCombobox>
119
+
120
+ <v-text-field
121
+ v-model="valueModel.email"
122
+ :variant="variant"
123
+ id="email-input"
124
+ :label="$t('user.field.email')"
125
+ prepend-inner-icon="mdi-email"
126
+ :rules="[(v:any) => !!v || t('validation.required')]"
127
+ :error-messages="$ta(store.inputErrors?.email)"
128
+ :readonly="readonly"
129
+ ></v-text-field>
130
+
131
+ <v-text-field
132
+ v-model="valueModel.phone"
133
+ :variant="variant"
134
+ id="phone-input"
135
+ :label="$t('user.field.phone')"
136
+ prepend-inner-icon="mdi-phone"
137
+ :rules="[(v:any) => !!v || t('validation.required')]"
138
+ :error-messages="$ta(store.inputErrors?.phone)"
139
+ :readonly="readonly"
140
+ ></v-text-field>
141
+
142
+ <v-switch
143
+ id="active-input"
144
+ v-model="valueModel.active"
145
+ color="primary"
146
+ label="Active"
147
+ :true-value="true"
148
+ :false-value="false"
149
+ :readonly="readonly"
150
+ ></v-switch>
151
+
152
+ </v-card-text>
153
+
154
+ <v-card-actions>
155
+ <v-spacer></v-spacer>
156
+ <v-btn
157
+ variant="text"
158
+ color="grey"
159
+ @click="cancel">
160
+ {{ t('action.cancel') }}
161
+ </v-btn>
162
+ <v-btn
163
+ v-if="!valueModel.readonly && store.operation != 'view'"
164
+ variant="flat"
165
+ :color="submitColor"
166
+ @click="submit"
167
+ >
168
+ {{ store.operation ? t('action.' + store.operation) : t('action.sent') }}
169
+ </v-btn>
170
+ </v-card-actions>
171
+ </v-card>
172
+ </v-form>
173
+ </template>
174
+
175
+ <style scoped>
176
+
177
+ </style>
@@ -0,0 +1,94 @@
1
+ <script setup lang="ts">
2
+ import UserPasswordForm from "./UserPasswordForm.vue";
3
+ import {defineModel, defineProps, type PropType, ref} from "vue";
4
+ import type {IUserPassword} from "@drax/identity-front";
5
+ import type {IUser} from "@drax/identity-share";
6
+ import {UserSystemFactory} from "@drax/identity-front";
7
+ import {ClientError, type IClientInputError} from "@drax/common-front";
8
+ import {useI18n} from "vue-i18n";
9
+
10
+ const {t} = useI18n()
11
+
12
+ const valueModel = defineModel({type: Boolean, default: false})
13
+
14
+ const {user} = defineProps({
15
+ user: {type: Object as PropType<IUser>, required: true},
16
+ })
17
+
18
+ const userSystem = UserSystemFactory.getInstance()
19
+
20
+ let passwordForm = ref<IUserPassword>({newPassword: "", confirmPassword: ""})
21
+ let passwordChanged = ref(false);
22
+ let inputErrors = ref<IClientInputError>()
23
+ let loading = ref(false);
24
+ let userError = ref<string>('')
25
+
26
+ async function savePassword() {
27
+ if (passwordForm.value.newPassword === passwordForm.value.confirmPassword) {
28
+ passwordChanged.value = await changeUserPassword(user.id, passwordForm.value.newPassword)
29
+ return
30
+ } else {
31
+ return
32
+ }
33
+ }
34
+
35
+ async function changeUserPassword(id: string, newPassword: string) {
36
+ try {
37
+ loading.value = true
38
+ return await userSystem.changeUserPassword(id, newPassword)
39
+ } catch (err) {
40
+ if (err instanceof ClientError) {
41
+ inputErrors.value = err.inputErrors
42
+ }
43
+ if (err instanceof Error) {
44
+ userError.value = err.message
45
+ }
46
+ throw err
47
+ } finally {
48
+ loading.value = false
49
+ }
50
+ }
51
+
52
+ </script>
53
+
54
+ <template>
55
+ <v-dialog v-model="valueModel" max-width="800">
56
+ <v-card>
57
+ <v-card-title>{{t('user.operation.changePassword')}}</v-card-title>
58
+ <v-card-subtitle>{{t('user.field.username')}}: {{user.username}}</v-card-subtitle>
59
+ <v-card-text>
60
+ <user-password-form
61
+ v-model="passwordForm"
62
+ :inputErrors="inputErrors"
63
+ :passwordChanged="passwordChanged"
64
+ @formSubmit="savePassword"
65
+ />
66
+ </v-card-text>
67
+
68
+ <v-card-actions>
69
+ <v-spacer></v-spacer>
70
+ <v-btn
71
+ variant="text"
72
+ color="grey"
73
+ @click="valueModel = false">
74
+ {{ passwordChanged ? t('action.close') : t('action.cancel') }}
75
+ </v-btn>
76
+ <v-btn
77
+ v-if="!passwordChanged"
78
+ variant="flat"
79
+ color="primary"
80
+ @click="savePassword"
81
+ :loading="loading"
82
+ >
83
+ {{ t('action.change') }}
84
+ </v-btn>
85
+ </v-card-actions>
86
+
87
+ </v-card>
88
+
89
+ </v-dialog>
90
+ </template>
91
+
92
+ <style scoped>
93
+
94
+ </style>