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.

149 lines
3.6 KiB

3 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="rolename"
  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.rolename, $t('members.roles')) }}
  37. </template>
  38. <template #selection="props">
  39. {{ $translateRole(props.item.rolename, $t('members.roles')) }}
  40. </template>
  41. </v-select>
  42. <v-alert
  43. v-show="errorMessage"
  44. prominent
  45. type="error"
  46. >
  47. <v-row align="center">
  48. <v-col class="grow">
  49. {{ errorMessage }}
  50. </v-col>
  51. </v-row>
  52. </v-alert>
  53. </v-form>
  54. </template>
  55. </base-card>
  56. </template>
  57. <script lang="ts">
  58. import Vue, { PropType } from 'vue'
  59. import { mdiAccount, mdiCreditCardOutline } from '@mdi/js'
  60. import BaseCard from '@/components/utils/BaseCard.vue'
  61. import { UserDTO } from '~/services/application/user/userData'
  62. import { RoleDTO } from '~/services/application/role/roleData'
  63. import { MemberDTO } from '~/services/application/member/memberData'
  64. export default Vue.extend({
  65. components: {
  66. BaseCard
  67. },
  68. props: {
  69. value: {
  70. type: Object as PropType<MemberDTO>,
  71. required: true
  72. },
  73. errorMessage: {
  74. type: String,
  75. default: ''
  76. }
  77. },
  78. data() {
  79. return {
  80. isLoading: false,
  81. valid: false,
  82. users: [] as UserDTO[],
  83. roles: [] as RoleDTO[],
  84. username: '',
  85. rules: {
  86. userRequired: (v: UserDTO) => !!v && !!v.username || 'Required',
  87. roleRequired: (v: RoleDTO) => !!v && !!v.rolename || 'Required'
  88. },
  89. mdiAccount,
  90. mdiCreditCardOutline
  91. }
  92. },
  93. async fetch() {
  94. this.isLoading = true
  95. this.users = await this.$services.user.list(this.username)
  96. this.isLoading = false
  97. },
  98. computed: {
  99. user: {
  100. get(): UserDTO {
  101. return {
  102. id: this.value.user,
  103. username: this.value.username,
  104. isStaff: false
  105. }
  106. },
  107. set(val: MemberDTO) {
  108. if (val === undefined) return
  109. const user = { user: val.id, username: val.username }
  110. this.$emit('input', { ...this.value, ...user })
  111. }
  112. },
  113. role: {
  114. get(): RoleDTO {
  115. return {
  116. id: this.value.role,
  117. rolename: this.value.rolename
  118. }
  119. },
  120. set(val: MemberDTO) {
  121. const role = { role: val.id, rolename: val.rolename }
  122. this.$emit('input', { ...this.value, ...role })
  123. }
  124. }
  125. },
  126. watch: {
  127. username() {
  128. // Items have already been loaded
  129. if (this.users.length > 0) return
  130. // Items have already been requested
  131. if (this.isLoading) return
  132. this.$fetch()
  133. }
  134. },
  135. async created() {
  136. this.roles = await this.$services.role.list()
  137. }
  138. })
  139. </script>