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.

146 lines
3.5 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="mdi-account"
  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="mdi-credit-card-outline"
  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 BaseCard from '@/components/utils/BaseCard.vue'
  60. import { UserDTO } from '~/services/application/user/userData'
  61. import { RoleDTO } from '~/services/application/role/roleData'
  62. import { MemberDTO } from '~/services/application/member/memberData'
  63. export default Vue.extend({
  64. components: {
  65. BaseCard
  66. },
  67. props: {
  68. value: {
  69. type: Object as PropType<MemberDTO>,
  70. required: true
  71. },
  72. errorMessage: {
  73. type: String,
  74. default: ''
  75. }
  76. },
  77. data() {
  78. return {
  79. isLoading: false,
  80. valid: false,
  81. users: [] as UserDTO[],
  82. roles: [] as RoleDTO[],
  83. username: '',
  84. rules: {
  85. userRequired: (v: UserDTO) => !!v && !!v.username || 'Required',
  86. roleRequired: (v: RoleDTO) => !!v && !!v.rolename || 'Required'
  87. }
  88. }
  89. },
  90. async fetch() {
  91. this.isLoading = true
  92. this.users = await this.$services.user.list(this.username)
  93. this.isLoading = false
  94. },
  95. computed: {
  96. user: {
  97. get(): UserDTO {
  98. return {
  99. id: this.value.user,
  100. username: this.value.username,
  101. isStaff: false
  102. }
  103. },
  104. set(val: MemberDTO) {
  105. if (val === undefined) return
  106. const user = { user: val.id, username: val.username }
  107. this.$emit('input', { ...this.value, ...user })
  108. }
  109. },
  110. role: {
  111. get(): RoleDTO {
  112. return {
  113. id: this.value.role,
  114. rolename: this.value.rolename
  115. }
  116. },
  117. set(val: MemberDTO) {
  118. const role = { role: val.id, rolename: val.rolename }
  119. this.$emit('input', { ...this.value, ...role })
  120. }
  121. }
  122. },
  123. watch: {
  124. username() {
  125. // Items have already been loaded
  126. if (this.users.length > 0) return
  127. // Items have already been requested
  128. if (this.isLoading) return
  129. this.$fetch()
  130. }
  131. },
  132. async created() {
  133. this.roles = await this.$services.role.list()
  134. }
  135. })
  136. </script>