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.

145 lines
3.6 KiB

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