@drax/identity-vue 0.0.14 → 0.0.16

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.0.14",
6
+ "version": "0.0.16",
7
7
  "type": "module",
8
8
  "main": "./src/index.ts",
9
9
  "module": "./src/index.ts",
@@ -24,7 +24,7 @@
24
24
  "format": "prettier --write src/"
25
25
  },
26
26
  "dependencies": {
27
- "@drax/common-front": "^0.0.14",
27
+ "@drax/common-front": "^0.0.16",
28
28
  "vue-i18n": "^9.13.1"
29
29
  },
30
30
  "peerDependencies": {
@@ -61,5 +61,5 @@
61
61
  "vue-tsc": "^2.0.11",
62
62
  "vuetify": "^3.6.4"
63
63
  },
64
- "gitHead": "ef0b07b3396f6eeb1f045ef430b4ec3856896f7e"
64
+ "gitHead": "edddb7a152dab85eb7bca07bd79c497bfd12c51f"
65
65
  }
@@ -5,6 +5,14 @@ import type { PropType } from 'vue'
5
5
  const props = defineProps({
6
6
  errorMessages: {
7
7
  type: String as PropType<string | string[] | undefined>,
8
+ },
9
+ multiple:{
10
+ type: Boolean,
11
+ default: false,
12
+ },
13
+ clearable:{
14
+ type: Boolean,
15
+ default: false,
8
16
  }
9
17
  })
10
18
 
@@ -29,6 +37,8 @@ onMounted(async () => {
29
37
  item-value="id"
30
38
  variant="outlined"
31
39
  :error-messages="errorMessages"
40
+ :multiple="multiple"
41
+ :clearable="clearable"
32
42
  ></v-select>
33
43
  </template>
34
44
 
@@ -0,0 +1,37 @@
1
+ <script setup lang="ts">
2
+
3
+ import {ref, onMounted, defineModel} from 'vue'
4
+ import type { PropType } from 'vue'
5
+ const props = defineProps({
6
+ errorMessages: {
7
+ type: String as PropType<string | string[] | undefined>,
8
+ }
9
+ })
10
+
11
+ const model = defineModel()
12
+ import {useTenant} from "../composables/useTenant";
13
+ const {fetchTenant} = useTenant()
14
+ let items = ref([])
15
+
16
+ onMounted(async () => {
17
+ items.value = await fetchTenant()
18
+ })
19
+
20
+
21
+ </script>
22
+
23
+ <template>
24
+ <v-select
25
+ v-model="model"
26
+ label="Tenant"
27
+ :items="items"
28
+ item-title="name"
29
+ item-value="id"
30
+ variant="outlined"
31
+ :error-messages="errorMessages"
32
+ ></v-select>
33
+ </template>
34
+
35
+ <style scoped>
36
+
37
+ </style>
@@ -69,12 +69,15 @@ const permissionGroups = computed(() => {
69
69
  v-slot="{ isSelected, toggle }"
70
70
  :value="permission"
71
71
  >
72
- <v-btn
72
+
73
+ <v-chip
73
74
  :color="isSelected? 'green' : 'grey-darken-3'" class=""
74
75
  @click="toggle" variant="flat" :rounded="false" border
75
76
  >
76
77
  {{ $t ? $t('permission.'+permission) : permission }}
77
- </v-btn>
78
+ </v-chip>
79
+
80
+
78
81
  </v-item>
79
82
  </v-card-text>
80
83
  </v-card>
@@ -0,0 +1,86 @@
1
+ import {inject, ref} from "vue";
2
+ import type {ITenant, TenantSystem} from "@drax/identity-front";
3
+ import {ClientError} from "@drax/common-front";
4
+ import type { IClientInputError} from "@drax/common-front";
5
+
6
+
7
+ export function useTenant() {
8
+
9
+ const tenantSystem = inject('TenantSystem') as TenantSystem
10
+
11
+ let tenantError = ref<string>('')
12
+ let inputErrors = ref<IClientInputError>()
13
+ let loading = ref(false);
14
+
15
+ async function fetchTenant(page = 1, perPage = 5) {
16
+ loading.value = true
17
+ let tenants = tenantSystem.fetchTenant()
18
+ loading.value = false
19
+ return tenants
20
+ }
21
+
22
+ async function paginateTenant(page = 1, perPage = 5, string = "") {
23
+ loading.value = true
24
+ let paginatedtenant = tenantSystem.paginateTenant(page, perPage,string)
25
+ loading.value = false
26
+ return paginatedtenant
27
+ }
28
+
29
+ async function createTenant(tenantData: ITenant) {
30
+ try {
31
+ loading.value = true
32
+ let tenant: ITenant = await tenantSystem.createTenant(tenantData)
33
+ return tenant
34
+ } catch (err) {
35
+ if (err instanceof ClientError) {
36
+ inputErrors.value = err.inputErrors
37
+ }if(err instanceof Error) {
38
+ tenantError.value = err.message
39
+ }
40
+ throw err
41
+ }finally {
42
+ loading.value = false
43
+ }
44
+
45
+ }
46
+
47
+ async function editTenant(id: string, tenantData: ITenant) {
48
+ try {
49
+ loading.value = true
50
+ let tenant: ITenant = await tenantSystem.editTenant(id, tenantData)
51
+ return tenant
52
+ } catch (err) {
53
+
54
+ if (err instanceof ClientError) {
55
+ inputErrors.value = err.inputErrors
56
+ }
57
+ if(err instanceof Error) {
58
+ tenantError.value = err.message
59
+ }
60
+ throw err
61
+ }finally {
62
+ loading.value = false
63
+ }
64
+ }
65
+
66
+ async function deleteTenant(id: string) {
67
+ try {
68
+ loading.value = true
69
+ await tenantSystem.deleteTenant(id)
70
+ } catch (err) {
71
+ console.log("composable deleteTenant error: ", err, )
72
+ if (err instanceof ClientError) {
73
+ inputErrors.value = err.inputErrors
74
+ }
75
+ if(err instanceof Error) {
76
+ tenantError.value = err.message
77
+ }
78
+ throw err
79
+ }finally {
80
+ loading.value = false
81
+ }
82
+ }
83
+
84
+ return {fetchTenant, paginateTenant, createTenant, editTenant, deleteTenant, loading, tenantError, inputErrors}
85
+
86
+ }
@@ -5,6 +5,7 @@ import {useRole} from "../../composables/useRole";
5
5
  import type {IRole} from "@drax/identity-front";
6
6
  import RoleForm from "../../forms/RoleForm.vue";
7
7
  import RoleView from "../../views/RoleView.vue";
8
+ import TenantForm from "@/forms/TenantForm.vue";
8
9
 
9
10
  const {createRole, editRole, deleteRole, loading, roleError, inputErrors} = useRole()
10
11
 
@@ -20,7 +21,7 @@ let dialog = ref(false);
20
21
  let dialogMode = ref<DialogMode>(null);
21
22
  let dialogTitle = ref('');
22
23
  const roleList = ref<RoleList | null>(null);
23
- let form = ref<IRole>({name: "", permissions: [], readonly: false})
24
+ let form = ref<IRole>({name: "", permissions: [], childRoles:[], readonly: false})
24
25
  let target = ref<IRole>();
25
26
  let targetId = ref<string>('');
26
27
  let filterEnable = ref(false);
@@ -75,7 +76,7 @@ let buttonText = computed(() => {
75
76
  function toCreate() {
76
77
  dialogMode.value = 'create';
77
78
  dialogTitle.value = 'role.creating';
78
- form.value = {name: "", permissions: [], readonly: false}
79
+ form.value = {name: "", permissions: [], childRoles:[], readonly: false}
79
80
  dialog.value = true;
80
81
  }
81
82
 
@@ -84,6 +85,7 @@ function toEdit(item: IRole) {
84
85
  dialogMode.value = 'edit';
85
86
  dialogTitle.value = 'role.updating';
86
87
  const {id, ...rest} = item;
88
+ rest.childRoles = rest.childRoles ? rest.childRoles.map(c => c.id) : []
87
89
  targetId.value = id;
88
90
  form.value = {...rest}
89
91
  dialog.value = true;
@@ -102,7 +104,7 @@ function toDelete(item: IRole) {
102
104
  </script>
103
105
 
104
106
  <template>
105
- <v-container>
107
+ <v-container fluid>
106
108
 
107
109
  <v-sheet border rounded>
108
110
  <v-toolbar>
@@ -138,6 +140,7 @@ function toDelete(item: IRole) {
138
140
  <RoleForm v-if="dialogMode === 'create' || dialogMode === 'edit'"
139
141
  v-model="form"
140
142
  :inputErrors="inputErrors"
143
+ @formSubmit="save"
141
144
  />
142
145
  <RoleView v-if="dialogMode === 'delete' && target" :role="target"></RoleView>
143
146
  </v-card-text>
@@ -21,6 +21,7 @@ const page = ref(1)
21
21
  const headers = ref([
22
22
  //{title: 'ID', align: 'start', sortable: false, key: 'id'},
23
23
  { title: t('role.name'), key: 'name', align: 'start' },
24
+ { title: t('role.childRoles'), key: 'childRoles', align: 'start' },
24
25
  { title: t('role.permissions'), key: 'permissions', align: 'start' },
25
26
  { title: t('role.readonly'), key: 'readonly', align: 'start' },
26
27
  { title: '', key: 'actions', align: 'start', minWidth: '150px' },
@@ -88,6 +89,15 @@ defineExpose({
88
89
  </v-chip>
89
90
  </template>
90
91
 
92
+ <template v-slot:item.childRoles="{ value }" >
93
+ <v-chip v-for="role in value"
94
+ :key="role" color="blue"
95
+ class="ma-1"
96
+ >
97
+ {{role.name}}
98
+ </v-chip>
99
+ </template>
100
+
91
101
  <template v-slot:item.readonly="{ value }" >
92
102
  <v-chip v-if="value" color="red" >
93
103
  <v-icon class="mdi mdi-pencil-off-outline"></v-icon>
@@ -98,8 +108,8 @@ defineExpose({
98
108
  </template>
99
109
 
100
110
  <template v-slot:item.actions="{item}" >
101
- <v-btn v-if="hasPermission('user:update')" :disabled="item.readonly" icon="mdi-pencil" variant="text" color="primary" @click="$emit('toEdit', item)"></v-btn>
102
- <v-btn v-if="hasPermission('user:delete')" :disabled="item.readonly" icon="mdi-delete" class="mr-1" variant="text" color="red" @click="$emit('toDelete', item)"></v-btn>
111
+ <v-btn v-if="hasPermission('role:update')" :disabled="item.readonly" icon="mdi-pencil" variant="text" color="primary" @click="$emit('toEdit', item)"></v-btn>
112
+ <v-btn v-if="hasPermission('role:delete')" :disabled="item.readonly" icon="mdi-delete" class="mr-1" variant="text" color="red" @click="$emit('toDelete', item)"></v-btn>
103
113
  </template>
104
114
 
105
115
  </v-data-table-server>
@@ -0,0 +1,166 @@
1
+ <script setup lang="ts">
2
+ import {computed, ref} from 'vue'
3
+ import TenantList from "./TenantList.vue";
4
+ import {useTenant} from "../../composables/useTenant";
5
+ import type {ITenant} from "@drax/identity-front";
6
+ import TenantForm from "../../forms/TenantForm.vue";
7
+ import TenantView from "../../views/TenantView.vue";
8
+
9
+ const {createTenant, editTenant, deleteTenant, loading, tenantError, inputErrors} = useTenant()
10
+
11
+ interface TenantList {
12
+ loadItems: () => void;
13
+ items: ITenant[];
14
+ }
15
+
16
+ type DialogMode = 'create' | 'edit' | 'delete' | null;
17
+
18
+
19
+ let dialog = ref(false);
20
+ let dialogMode = ref<DialogMode>(null);
21
+ let dialogTitle = ref('');
22
+ const tenantList = ref<TenantList | null>(null);
23
+ let form = ref<ITenant>({name: ""})
24
+ let target = ref<ITenant>();
25
+ let targetId = ref<string>('');
26
+ let filterEnable = ref(false);
27
+
28
+ function cancel() {
29
+ dialog.value = false
30
+ inputErrors.value = {}
31
+ tenantError.value = '';
32
+ dialogMode.value = null
33
+ dialogTitle.value = ''
34
+ targetId.value = ''
35
+ target.value = undefined
36
+ }
37
+
38
+ async function save() {
39
+
40
+ try {
41
+ if (dialogMode.value === 'create') {
42
+ await createTenant(form.value)
43
+ } else if (dialogMode.value === 'edit') {
44
+ await editTenant(targetId.value, form.value)
45
+ } else if (dialogMode.value === 'delete') {
46
+ await deleteTenant(targetId.value)
47
+ }
48
+ dialog.value = false
49
+ inputErrors.value = {}
50
+ tenantError.value = '';
51
+ if (tenantList.value !== null) {
52
+ tenantList.value.loadItems()
53
+ }
54
+ } catch (e) {
55
+ console.error(e)
56
+ if (e instanceof Error) {
57
+ tenantError.value = e.message
58
+ }
59
+ }
60
+ }
61
+
62
+ let buttonText = computed(() => {
63
+ switch (dialogMode.value) {
64
+ case 'create':
65
+ return 'action.create'
66
+ case 'edit':
67
+ return 'action.update'
68
+ case 'delete':
69
+ return 'action.delete'
70
+ default:
71
+ return 'action.sent'
72
+ }
73
+ })
74
+
75
+ function toCreate() {
76
+ dialogMode.value = 'create';
77
+ dialogTitle.value = 'tenant.creating';
78
+ form.value = {name: ""}
79
+ dialog.value = true;
80
+ }
81
+
82
+ function toEdit(item: ITenant) {
83
+ console.log('toEdit', item)
84
+ dialogMode.value = 'edit';
85
+ dialogTitle.value = 'tenant.updating';
86
+ const {id, ...rest} = item;
87
+ targetId.value = id;
88
+ form.value = {...rest}
89
+ dialog.value = true;
90
+ }
91
+
92
+ function toDelete(item: ITenant) {
93
+ console.log('toDelete', item)
94
+ dialogMode.value = 'delete';
95
+ dialogTitle.value = 'tenant.deleting';
96
+ target.value = item
97
+ const {id} = item;
98
+ targetId.value = id;
99
+ dialog.value = true;
100
+ }
101
+
102
+ </script>
103
+
104
+ <template>
105
+ <v-container fluid>
106
+
107
+ <v-sheet border rounded>
108
+ <v-toolbar>
109
+ <v-toolbar-title>{{ $t('tenant.managing') }}</v-toolbar-title>
110
+ <v-spacer></v-spacer>
111
+ <v-btn icon @click="filterEnable = !filterEnable">
112
+ <v-icon>{{ filterEnable ? 'mdi-filter' : 'mdi-filter-off' }}</v-icon>
113
+ </v-btn>
114
+ <v-btn color="primary" @click="toCreate">
115
+ {{ $t('action.create') }}
116
+ </v-btn>
117
+ </v-toolbar>
118
+ <v-theme-provider with-background class="pa-2 rounded-b">
119
+ <TenantList
120
+ ref="tenantList"
121
+ @toEdit="toEdit"
122
+ @toDelete="toDelete"
123
+ :filterEnable="filterEnable"
124
+ />
125
+ </v-theme-provider>
126
+ </v-sheet>
127
+
128
+ <v-dialog v-model="dialog" max-width="800">
129
+ <v-sheet border>
130
+ <v-toolbar>
131
+ <v-toolbar-title>{{ $t(dialogTitle) }}</v-toolbar-title>
132
+ </v-toolbar>
133
+ <v-card class="pa-10">
134
+ <v-card-text v-if="tenantError">
135
+ <v-alert type="error">{{ tenantError }}</v-alert>
136
+ </v-card-text>
137
+ <v-card-text>
138
+ <TenantForm v-if="dialogMode === 'create' || dialogMode === 'edit'"
139
+ v-model="form"
140
+ :inputErrors="inputErrors"
141
+ @formSubmit="save"
142
+ />
143
+ <TenantView v-if="dialogMode === 'delete' && target" :tenant="target"></TenantView>
144
+ </v-card-text>
145
+ <v-card-actions>
146
+ <v-spacer></v-spacer>
147
+ <v-btn variant="text" @click="cancel" :loading="loading">Cancelar</v-btn>
148
+ <v-btn variant="flat"
149
+ :color="dialogMode==='delete' ? 'red' : 'primary'"
150
+ @click="save"
151
+ :loading="loading"
152
+ >
153
+ {{ $t(buttonText) }}
154
+ </v-btn>
155
+ </v-card-actions>
156
+
157
+ </v-card>
158
+ </v-sheet>
159
+ </v-dialog>
160
+
161
+ </v-container>
162
+ </template>
163
+
164
+ <style scoped>
165
+
166
+ </style>
@@ -0,0 +1,92 @@
1
+ <script setup lang="ts">
2
+
3
+ import {defineProps, ref} from "vue";
4
+ import {useTenant} from "../../composables/useTenant";
5
+ import {useAuth} from "../../composables/useAuth";
6
+ import {useI18n} from "vue-i18n";
7
+
8
+ const {hasPermission} = useAuth()
9
+ const {paginateTenant} = useTenant()
10
+ const {t} = useI18n()
11
+
12
+ const props = defineProps({
13
+ filterEnable: {
14
+ type: Boolean,
15
+ default: false,
16
+ }
17
+ })
18
+
19
+ const itemsPerPage = ref(5)
20
+ const page = ref(1)
21
+ const headers = ref([
22
+ //{title: 'ID', align: 'start', sortable: false, key: 'id'},
23
+ { title: t('tenant.name'), key: 'name', align: 'start' },
24
+ { title: '', key: 'actions', align: 'start', minWidth: '150px' },
25
+ ])
26
+
27
+ const serverItems = ref([])
28
+ const totalItems = ref(0)
29
+ const loading = ref(false)
30
+ const search = ref('')
31
+
32
+ async function loadItems(){
33
+ try{
34
+ loading.value = true
35
+ const r = await paginateTenant(page.value,itemsPerPage.value, search.value)
36
+ serverItems.value = r.items
37
+ totalItems.value = r.total
38
+ }catch (e){
39
+ console.error(e)
40
+ }finally {
41
+ loading.value = false
42
+ }
43
+ }
44
+
45
+
46
+
47
+ defineExpose({
48
+ loadItems
49
+ });
50
+
51
+ </script>
52
+
53
+ <template>
54
+ <v-data-table-server
55
+ v-if="hasPermission('user:manage')"
56
+ v-model:items-per-page="itemsPerPage"
57
+ v-model:page="page"
58
+ :headers="headers"
59
+ :items="serverItems"
60
+ :items-length="totalItems"
61
+ :loading="loading"
62
+ :search="search"
63
+ item-value="name"
64
+ @update:options="loadItems"
65
+ >
66
+ <template v-slot:top>
67
+ <v-toolbar border density="compact" v-if="filterEnable" class="grey-lighten-1">
68
+ <v-toolbar-title>{{ $t('action.filter') }}</v-toolbar-title>
69
+ <v-spacer></v-spacer>
70
+ <v-text-field v-model="search" hide-details
71
+ density="compact" class="mr-2"
72
+ variant="outlined"
73
+ append-inner-icon="mdi-magnify"
74
+ :label="$t('action.search')"
75
+ single-line clearable @click:clear="() => search = ''"
76
+ />
77
+
78
+ </v-toolbar>
79
+ </template>
80
+
81
+
82
+ <template v-slot:item.actions="{item}" >
83
+ <v-btn v-if="hasPermission('tenant:update')" :disabled="item.readonly" icon="mdi-pencil" variant="text" color="primary" @click="$emit('toEdit', item)"></v-btn>
84
+ <v-btn v-if="hasPermission('tenant:delete')" :disabled="item.readonly" icon="mdi-delete" class="mr-1" variant="text" color="red" @click="$emit('toDelete', item)"></v-btn>
85
+ </template>
86
+
87
+ </v-data-table-server>
88
+ </template>
89
+
90
+ <style scoped>
91
+
92
+ </style>
@@ -8,6 +8,7 @@ import UserCreateForm from "../../forms/UserCreateForm.vue";
8
8
  import UserEditForm from "../../forms/UserEditForm.vue";
9
9
  import UserPasswordForm from "../../forms/UserPasswordForm.vue";
10
10
  import UserView from "../../views/UserView.vue";
11
+ import TenantForm from "@/forms/TenantForm.vue";
11
12
 
12
13
  const {createUser, editUser, changeUserPassword, deleteUser, loading, userError, inputErrors} = useUser()
13
14
 
@@ -23,8 +24,8 @@ let dialog = ref(false);
23
24
  let dialogMode = ref<DialogMode>(null);
24
25
  let dialogTitle = ref('');
25
26
  const userList = ref<UserList | null>(null);
26
- let createForm = ref<IUserCreate>({name: "", username: "", password: "", email: "", phone: "", role: "", active: true})
27
- let editForm = ref<IUserUpdate>({name: "", username: "", email: "", phone: "", role: "", active: true})
27
+ let createForm = ref<IUserCreate>({name: "", username: "", password: "", email: "", phone: "", role: "", tenant: "", active: true})
28
+ let editForm = ref<IUserUpdate>({name: "", username: "", email: "", phone: "", role: "", tenant: "", active: true})
28
29
  let passwordForm = ref<IUserPassword>({newPassword: "", confirmPassword: ""})
29
30
  let passwordChanged = ref(false);
30
31
  let target = ref<IUser>();
@@ -92,7 +93,7 @@ function toCreate() {
92
93
  actionButtonEnable.value = true
93
94
  dialogMode.value = 'create';
94
95
  dialogTitle.value = 'user.creating';
95
- createForm.value = {name: "", username: "", password: "", email: "", phone: "", role: "", active: true}
96
+ createForm.value = {name: "", username: "", password: "", email: "", phone: "", role: "", tenant: "", active: true}
96
97
  dialog.value = true;
97
98
  }
98
99
 
@@ -103,6 +104,7 @@ function toEdit(item: IUser) {
103
104
  const {id, ...rest} = item;
104
105
  targetId.value = id;
105
106
  rest.role = rest.role ? rest.role.id : null
107
+ rest.tenant = rest.tenant ? rest.tenant.id : null
106
108
  editForm.value = {...rest}
107
109
  dialog.value = true;
108
110
  }
@@ -131,7 +133,7 @@ function toChangePassword(item: IUser) {
131
133
  </script>
132
134
 
133
135
  <template>
134
- <v-container>
136
+ <v-container fluid>
135
137
 
136
138
  <v-sheet border rounded>
137
139
  <v-toolbar>
@@ -169,12 +171,14 @@ function toChangePassword(item: IUser) {
169
171
  v-if="dialogMode === 'create'"
170
172
  v-model="createForm"
171
173
  :inputErrors="inputErrors"
174
+ @formSubmit="save"
172
175
  />
173
176
 
174
177
  <UserEditForm
175
178
  v-if="dialogMode === 'edit'"
176
179
  v-model="editForm"
177
180
  :inputErrors="inputErrors"
181
+ @formSubmit="save"
178
182
  />
179
183
 
180
184
  <UserView v-if="dialogMode === 'delete'
@@ -187,6 +191,7 @@ function toChangePassword(item: IUser) {
187
191
  v-model="passwordForm"
188
192
  :inputErrors="inputErrors"
189
193
  :passwordChanged="passwordChanged"
194
+ @formSubmit="save"
190
195
  />
191
196
 
192
197
 
@@ -24,6 +24,7 @@ const headers = ref([
24
24
  { title: t('user.username'), key: 'username', align: 'start' },
25
25
  { title: t('user.email'), key: 'email', align: 'start' },
26
26
  { title: t('user.role'), key: 'role.name', align: 'start' },
27
+ { title: t('user.tenant'), key: 'tenant.name', align: 'start' },
27
28
  { title: t('user.active'), key: 'active', align: 'start' },
28
29
  { title: '', key: 'actions', align: 'start', fixed:true },
29
30
  ])
@@ -4,6 +4,7 @@ import type {IRole} from "@drax/identity-front";
4
4
  import {useI18nValidation} from "../composables/useI18nValidation";
5
5
  import type {IClientInputError} from "@drax/common-front";
6
6
  import PermissionSelector from "../components/PermissionSelector/PermissionSelector.vue";
7
+ import RoleCombobox from "../combobox/RoleCombobox.vue";
7
8
 
8
9
  const {$ta} = useI18nValidation()
9
10
 
@@ -19,10 +20,17 @@ const form = defineModel<IRole>({
19
20
  default: () => ({name: "", permissions: [], readonly: false})
20
21
  })
21
22
 
23
+ const emits = defineEmits(['formSubmit'])
24
+
25
+ // Function to call when form is attempted to be submitted
26
+ const onSubmit = () => {
27
+ emits('formSubmit', form); // Emitting an event with the form data
28
+ }
29
+
22
30
  </script>
23
31
 
24
32
  <template>
25
- <form>
33
+ <form @submit.prevent="onSubmit">
26
34
  <v-text-field
27
35
  variant="outlined"
28
36
  id="name-input"
@@ -33,6 +41,11 @@ const form = defineModel<IRole>({
33
41
  :error-messages="$ta(inputErrors.name)"
34
42
  ></v-text-field>
35
43
 
44
+ <RoleCombobox
45
+ v-model="form.childRoles"
46
+ :error-messages="$ta(inputErrors.role)"
47
+ multiple
48
+ ></RoleCombobox>
36
49
 
37
50
  <PermissionSelector v-model="form.permissions"></PermissionSelector>
38
51
 
@@ -0,0 +1,48 @@
1
+ <script setup lang="ts">
2
+ import {defineModel, type PropType} from "vue";
3
+ import type {ITenant} from "@drax/identity-front";
4
+ import {useI18nValidation} from "../composables/useI18nValidation";
5
+ import type {IClientInputError} from "@drax/common-front";
6
+
7
+ const {$ta} = useI18nValidation()
8
+
9
+ const props = defineProps({
10
+ inputErrors: {
11
+ type: Object as PropType<IClientInputError>,
12
+ default: () => ({name: ""})
13
+ }
14
+ })
15
+
16
+ const form = defineModel<ITenant>({
17
+ type: Object,
18
+ default: () => ({name: ""})
19
+ })
20
+
21
+ // Define emits
22
+ const emits = defineEmits(['formSubmit'])
23
+
24
+ // Function to call when form is attempted to be submitted
25
+ const onSubmit = () => {
26
+ emits('formSubmit', form); // Emitting an event with the form data
27
+ }
28
+
29
+ </script>
30
+
31
+ <template>
32
+ <form @submit.prevent="onSubmit">
33
+ <v-text-field
34
+ variant="outlined"
35
+ id="name-input"
36
+ label="Name"
37
+ v-model="form.name"
38
+ prepend-inner-icon="mdi-card-account-details"
39
+ required
40
+ :error-messages="$ta(inputErrors.name)"
41
+ ></v-text-field>
42
+
43
+ </form>
44
+ </template>
45
+
46
+ <style scoped>
47
+
48
+ </style>
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import {ref, defineModel, type PropType} from "vue";
3
3
  import RoleCombobox from "../combobox/RoleCombobox.vue";
4
+ import TenantCombobox from "../combobox/TenantCombobox.vue";
4
5
  import type {IClientInputError} from "@drax/common-front";
5
6
  import type {IUserCreate} from "@drax/identity-front/src/interfaces/IUser";
6
7
  import {useI18nValidation} from "../composables/useI18nValidation";
@@ -10,21 +11,28 @@ const {$ta} = useI18nValidation()
10
11
  const props = defineProps({
11
12
  inputErrors: {
12
13
  type: Object as PropType<IClientInputError>,
13
- default: () => ({name: "", username: "", password: "", email: "", phone: "", role: "", active: ""})
14
+ default: () => ({name: "", username: "", password: "", email: "", phone: "", role: "", tenant: "", active: ""})
14
15
  }
15
16
  })
16
17
 
17
18
  const form = defineModel<IUserCreate>({
18
19
  type: Object,
19
- default: () => ({name: "", username: "", password: "", email: "", phone: "", role: "", active: true})
20
+ default: () => ({name: "", username: "", password: "", email: "", phone: "", role: "", tenant: "", active: true})
20
21
  })
21
22
 
22
23
  let passwordVisibility = ref(false)
23
24
 
25
+ // Define emits
26
+ const emits = defineEmits(['formSubmit'])
27
+
28
+ // Function to call when form is attempted to be submitted
29
+ const onSubmit = () => {
30
+ emits('formSubmit', form); // Emitting an event with the form data
31
+ }
24
32
  </script>
25
33
 
26
34
  <template>
27
- <form>
35
+ <form @submit.prevent="onSubmit">
28
36
 
29
37
  <v-text-field
30
38
  variant="outlined"
@@ -65,6 +73,11 @@ let passwordVisibility = ref(false)
65
73
  :error-messages="$ta(inputErrors.role)"
66
74
  ></RoleCombobox>
67
75
 
76
+ <TenantCombobox
77
+ v-model="form.tenant"
78
+ :error-messages="$ta(inputErrors.tenant)"
79
+ ></TenantCombobox>
80
+
68
81
  <v-text-field
69
82
  v-model="form.email"
70
83
  variant="outlined"
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
- import {ref, defineModel, type PropType} from "vue";
2
+ import {defineModel, type PropType} from "vue";
3
3
  import RoleCombobox from "../combobox/RoleCombobox.vue";
4
+ import TenantCombobox from "../combobox/TenantCombobox.vue";
4
5
  import type {IClientInputError} from "@drax/common-front";
5
6
  import type {IUserUpdate} from "@drax/identity-front/src/interfaces/IUser";
6
7
  import {useI18nValidation} from "../composables/useI18nValidation";
@@ -9,20 +10,27 @@ const {$ta} = useI18nValidation()
9
10
  const props = defineProps({
10
11
  inputErrors: {
11
12
  type: Object as PropType<IClientInputError>,
12
- default: () => ({name: "", username: "", email: "", phone: "", role: "", active: ""})
13
+ default: () => ({name: "", username: "", email: "", phone: "", role: "", tenant: "", active: ""})
13
14
  }
14
15
  })
15
16
 
16
17
  const form = defineModel<IUserUpdate>({
17
18
  type: Object,
18
- default: () => ({name: "", username: "", email: "", phone: "", role: "", active: true})
19
+ default: () => ({name: "", username: "", email: "", phone: "", role: "", tenant: "", active: true})
19
20
  })
20
21
 
22
+ // Define emits
23
+ const emits = defineEmits(['formSubmit'])
24
+
25
+ // Function to call when form is attempted to be submitted
26
+ const onSubmit = () => {
27
+ emits('formSubmit', form); // Emitting an event with the form data
28
+ }
21
29
 
22
30
  </script>
23
31
 
24
32
  <template>
25
- <form>
33
+ <form @submit.prevent="onSubmit">
26
34
  <v-sheet>
27
35
  </v-sheet>
28
36
 
@@ -51,6 +59,11 @@ const form = defineModel<IUserUpdate>({
51
59
  :error-messages="$ta(inputErrors.role)"
52
60
  ></RoleCombobox>
53
61
 
62
+ <TenantCombobox
63
+ v-model="form.tenant"
64
+ :error-messages="$ta(inputErrors.tenant)"
65
+ ></TenantCombobox>
66
+
54
67
  <v-text-field
55
68
  v-model="form.email"
56
69
  variant="outlined"
@@ -31,7 +31,13 @@ function confirmPasswordRule(value: string) {
31
31
  return form.value.newPassword === form.value.confirmPassword || t('validation.password.confirmed')
32
32
  }
33
33
 
34
+ // Define emits
35
+ const emits = defineEmits(['formSubmit'])
34
36
 
37
+ // Function to call when form is attempted to be submitted
38
+ const onSubmit = () => {
39
+ emits('formSubmit', form); // Emitting an event with the form data
40
+ }
35
41
  </script>
36
42
 
37
43
  <template>
@@ -42,7 +48,7 @@ function confirmPasswordRule(value: string) {
42
48
  </v-alert>
43
49
  </v-sheet>
44
50
  <v-sheet v-else>
45
- <form ref="changeUserPassword">
51
+ <form ref="changeUserPassword" @submit.prevent="onSubmit">
46
52
 
47
53
  <div class="text-subtitle-1 text-medium-emphasis">{{ $t('user.newPassword') }}</div>
48
54
  <v-text-field
package/src/index.ts CHANGED
@@ -2,20 +2,31 @@ import IdentityLogin from "./components/IdentityLogin/IdentityLogin.vue";
2
2
  import IdentityProfileAvatar from "./components/IdentityProfileAvatar/IdentityProfileAvatar.vue";
3
3
  import IdentityProfileDrawer from "./components/IdentityProfileDrawer/IdentityProfileDrawer.vue";
4
4
  import IdentityProfileView from "./components/IdentityProfileView/IdentityProfileView.vue";
5
+
5
6
  import UserCrud from "./cruds/user-crud/UserCrud.vue";
6
7
  import UserList from "./cruds/user-crud/UserList.vue";
7
8
  import UserCrudPage from "./pages/UserCrudPage.vue";
8
9
  import UserCreateForm from "./forms/UserCreateForm.vue";
9
10
  import UserEditForm from "./forms/UserEditForm.vue";
10
- import RoleForm from "./forms/RoleForm.vue";
11
+ import UserView from "./views/UserView.vue";
11
12
 
13
+ import RoleForm from "./forms/RoleForm.vue";
14
+ import RoleView from "./views/RoleView.vue";
12
15
  import RoleCrud from "./cruds/role-crud/RoleCrud.vue";
13
16
  import RoleList from "./cruds/role-crud/RoleList.vue";
14
17
  import RoleCrudPage from "./pages/RoleCrudPage.vue";
15
18
 
19
+
20
+ import TenantForm from "./forms/TenantForm.vue";
21
+ import TenantView from "./views/TenantView.vue";
22
+ import TenantCrud from "./cruds/tenant-crud/TenantCrud.vue";
23
+ import TenantList from "./cruds/tenant-crud/TenantList.vue";
24
+ import TenantCrudPage from "./pages/TenantCrudPage.vue";
25
+
16
26
  import {useAuth} from "./composables/useAuth.js";
17
27
  import {useUser} from "./composables/useUser.js";
18
28
  import {useRole} from "./composables/useRole.js";
29
+ import {useTenant} from "./composables/useTenant.js";
19
30
  import {useAuthStore} from "./stores/auth/AuthStore.js";
20
31
 
21
32
  export {
@@ -25,26 +36,32 @@ export {
25
36
  IdentityProfileView,
26
37
  IdentityProfileDrawer,
27
38
 
28
- //Forms
39
+ //User
40
+ UserView,
29
41
  UserCreateForm,
30
42
  UserEditForm,
31
- RoleForm,
32
-
33
- //Vue Composables
34
- useAuth,
35
- useUser,
36
- useRole,
37
-
38
- //Cruds
39
43
  UserCrud,
40
44
  UserList,
45
+ UserCrudPage,
46
+ useAuth,
47
+ useUser,
41
48
 
49
+ //Role
50
+ RoleView,
51
+ RoleForm,
42
52
  RoleCrud,
43
53
  RoleList,
44
-
45
- //Pages
46
- UserCrudPage,
47
54
  RoleCrudPage,
55
+ useRole,
56
+
57
+ //Tenant
58
+ TenantView,
59
+ TenantForm,
60
+ TenantCrud,
61
+ TenantList,
62
+ TenantCrudPage,
63
+ useTenant,
64
+
48
65
 
49
66
  //Stores
50
67
  useAuthStore
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+
3
+ import TenantCrud from "../cruds/tenant-crud/TenantCrud.vue";
4
+ </script>
5
+
6
+ <template>
7
+ <TenantCrud></TenantCrud>
8
+ </template>
9
+
10
+ <style scoped>
11
+
12
+ </style>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import type {PropType} from "vue";
3
+ import type {ITenant} from "@drax/identity-front";
4
+
5
+ const props = defineProps({
6
+ tenant:{
7
+ type: Object as PropType<ITenant>,
8
+ required: true,
9
+ }
10
+ })
11
+ </script>
12
+
13
+ <template>
14
+ <v-sheet border class="position-relative d-flex justify-center align-center" height="150">
15
+ <v-sheet class="text-center">
16
+ <h6 class="text-h6">{{$t ? $t('tenant.name') : 'Name'}} : {{ tenant.name }}</h6>
17
+ </v-sheet>
18
+ </v-sheet>
19
+
20
+ </template>
21
+
22
+ <style scoped>
23
+
24
+ </style>