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.

136 lines
3.1 KiB

  1. <template lang="pug">
  2. v-dialog(
  3. v-model='dialogOpen'
  4. max-width='650'
  5. )
  6. v-card
  7. .dialog-header
  8. span {{$t('common:user.search')}}
  9. v-spacer
  10. v-progress-circular(
  11. indeterminate
  12. color='white'
  13. :size='20'
  14. :width='2'
  15. v-show='searchLoading'
  16. )
  17. v-card-text.pt-5
  18. v-text-field(
  19. outlined
  20. :label='$t(`common:user.searchPlaceholder`)'
  21. v-model='search'
  22. prepend-inner-icon='mdi-account-search-outline'
  23. color='primary'
  24. ref='searchIpt'
  25. hide-details
  26. )
  27. v-list.grey.mt-3.py-0.radius-7(
  28. :class='$vuetify.theme.dark ? `darken-3-d5` : `lighten-3`'
  29. two-line
  30. dense
  31. )
  32. template(v-for='(usr, idx) in items')
  33. v-list-item(:key='usr.id', @click='setUser(usr)')
  34. v-list-item-avatar(size='40', color='primary')
  35. span.body-1.white--text {{usr.name | initials}}
  36. v-list-item-content
  37. v-list-item-title.body-2 {{usr.name}}
  38. v-list-item-subtitle {{usr.email}}
  39. v-list-item-action
  40. v-icon(color='primary') mdi-arrow-right
  41. v-divider.my-0(v-if='idx < items.length - 1')
  42. v-card-chin
  43. v-spacer
  44. v-btn(
  45. text
  46. @click='close'
  47. :disabled='loading'
  48. ) {{$t('common:actions.cancel')}}
  49. </template>
  50. <script>
  51. import _ from 'lodash'
  52. import gql from 'graphql-tag'
  53. export default {
  54. filters: {
  55. initials(val) {
  56. return val.split(' ').map(v => v.substring(0, 1)).join('')
  57. }
  58. },
  59. props: {
  60. multiple: {
  61. type: Boolean,
  62. default: false
  63. },
  64. value: {
  65. type: Boolean,
  66. default: false
  67. }
  68. },
  69. data() {
  70. return {
  71. loading: false,
  72. searchLoading: false,
  73. search: '',
  74. items: []
  75. }
  76. },
  77. computed: {
  78. dialogOpen: {
  79. get() { return this.value },
  80. set(value) { this.$emit('input', value) }
  81. }
  82. },
  83. watch: {
  84. value(newValue, oldValue) {
  85. if (newValue && !oldValue) {
  86. this.search = ''
  87. this.selectedItems = null
  88. _.delay(() => { this.$refs.searchIpt.focus() }, 100)
  89. }
  90. }
  91. },
  92. methods: {
  93. close() {
  94. this.$emit('input', false)
  95. },
  96. setUser(usr) {
  97. this.$emit('select', usr)
  98. this.close()
  99. },
  100. searchFilter(item, queryText, itemText) {
  101. return _.includes(_.toLower(item.email), _.toLower(queryText)) || _.includes(_.toLower(item.name), _.toLower(queryText))
  102. }
  103. },
  104. apollo: {
  105. items: {
  106. query: gql`
  107. query ($query: String!) {
  108. users {
  109. search(query:$query) {
  110. id
  111. name
  112. email
  113. providerKey
  114. }
  115. }
  116. }
  117. `,
  118. variables() {
  119. return {
  120. query: this.search
  121. }
  122. },
  123. fetchPolicy: 'cache-and-network',
  124. skip() {
  125. return !this.search || this.search.length < 2
  126. },
  127. update: (data) => data.users.search,
  128. watchLoading (isLoading) {
  129. this.searchLoading = isLoading
  130. }
  131. }
  132. }
  133. }
  134. </script>