You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
3.6 KiB

3 years ago
3 years ago
2 years ago
2 years ago
3 years ago
3 years ago
  1. <template>
  2. <base-card
  3. :disabled="!valid"
  4. :title="$t('members.addMember')"
  5. :agree-text="$t('generic.save')"
  6. :cancel-text="$t('generic.cancel')"
  7. @agree="$emit('save')"
  8. @cancel="$emit('cancel')"
  9. >
  10. <template #content>
  11. <v-form v-model="valid">
  12. <v-autocomplete
  13. v-model="user"
  14. :items="users"
  15. :loading="isLoading"
  16. :search-input.sync="username"
  17. hide-no-data
  18. item-text="username"
  19. :label="$t('members.userSearchAPIs')"
  20. :placeholder="$t('members.userSearchPrompt')"
  21. :prepend-icon="mdiAccount"
  22. :rules="[rules.userRequired]"
  23. return-object
  24. />
  25. <v-select
  26. v-model="role"
  27. :items="roles"
  28. item-text="name"
  29. item-value="id"
  30. :label="$t('members.role')"
  31. :rules="[rules.roleRequired]"
  32. return-object
  33. :prepend-icon="mdiCreditCardOutline"
  34. >
  35. <template #item="props">
  36. {{ $translateRole(props.item.name, $t('members.roles')) }}
  37. </template>
  38. <template #selection="props">
  39. {{ $translateRole(props.item.name, $t('members.roles')) }}
  40. </template>
  41. </v-select>
  42. <v-alert v-show="errorMessage" prominent type="error">
  43. <v-row align="center">
  44. <v-col class="grow">
  45. {{ errorMessage }}
  46. </v-col>
  47. </v-row>
  48. </v-alert>
  49. </v-form>
  50. </template>
  51. </base-card>
  52. </template>
  53. <script lang="ts">
  54. import { mdiAccount, mdiCreditCardOutline } from '@mdi/js'
  55. import type { PropType } from 'vue'
  56. import Vue from 'vue'
  57. import BaseCard from '@/components/utils/BaseCard.vue'
  58. import { MemberItem } from '~/domain/models/member/member'
  59. import { RoleItem } from '~/domain/models/role/role'
  60. import { UserItem } from '~/domain/models/user/user'
  61. export default Vue.extend({
  62. components: {
  63. BaseCard
  64. },
  65. props: {
  66. value: {
  67. type: Object as PropType<MemberItem>,
  68. required: true
  69. },
  70. errorMessage: {
  71. type: String,
  72. default: ''
  73. }
  74. },
  75. data() {
  76. return {
  77. isLoading: false,
  78. valid: false,
  79. users: [] as UserItem[],
  80. roles: [] as RoleItem[],
  81. username: '',
  82. rules: {
  83. userRequired: (v: UserItem) => (!!v && !!v.username) || 'Required',
  84. roleRequired: (v: RoleItem) => (!!v && !!v.name) || 'Required'
  85. },
  86. mdiAccount,
  87. mdiCreditCardOutline
  88. }
  89. },
  90. async fetch() {
  91. this.isLoading = true
  92. this.users = await this.$repositories.user.list(this.username)
  93. this.isLoading = false
  94. },
  95. computed: {
  96. user: {
  97. get(): UserItem {
  98. return {
  99. id: this.value.user,
  100. username: this.value.username,
  101. isStaff: false,
  102. isSuperuser: false
  103. }
  104. },
  105. set(val: MemberItem) {
  106. if (val === undefined) return
  107. const user = { user: val.id, username: val.username }
  108. this.$emit('input', { ...this.value, ...user })
  109. }
  110. },
  111. role: {
  112. get(): RoleItem {
  113. return {
  114. id: this.value.role,
  115. name: this.value.rolename
  116. }
  117. },
  118. set(val: RoleItem) {
  119. const role = { role: val.id, rolename: val.name }
  120. this.$emit('input', { ...this.value, ...role })
  121. }
  122. }
  123. },
  124. watch: {
  125. username() {
  126. // Items have already been loaded
  127. if (this.users.length > 0) return
  128. // Items have already been requested
  129. if (this.isLoading) return
  130. this.$fetch()
  131. }
  132. },
  133. async created() {
  134. this.roles = await this.$repositories.role.list()
  135. }
  136. })
  137. </script>