admin-users.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <template lang='pug'>
  2. v-container(fluid, grid-list-lg)
  3. v-layout(row, wrap)
  4. v-flex(xs12)
  5. .admin-header
  6. img.animated.fadeInUp(src='/_assets/svg/icon-customer.svg', alt='Users', style='width: 80px;')
  7. .admin-header-title
  8. .headline.blue--text.text--darken-2.animated.fadeInLeft Users
  9. .subtitle-1.grey--text.animated.fadeInLeft.wait-p2s Manage users
  10. v-spacer
  11. v-btn.animated.fadeInDown.wait-p2s.mr-3(outlined, color='grey', large, @click='refresh')
  12. v-icon mdi-refresh
  13. v-btn.animated.fadeInDown(color='primary', large, depressed, @click='createUser')
  14. v-icon(left) mdi-plus
  15. span New User
  16. v-card.wiki-form.mt-3.animated.fadeInUp
  17. v-toolbar(flat, :color='$vuetify.theme.dark ? `grey darken-3-d5` : `grey lighten-5`', height='80')
  18. v-spacer
  19. v-text-field(
  20. outlined
  21. v-model='search'
  22. prepend-inner-icon='mdi-account-search-outline'
  23. label='Search Users...'
  24. hide-details
  25. )
  26. v-select.ml-2(
  27. outlined
  28. hide-details
  29. label='Identity Provider'
  30. :items='strategies'
  31. v-model='filterStrategy'
  32. item-text='title'
  33. item-value='key'
  34. )
  35. v-spacer
  36. v-divider
  37. v-data-table(
  38. v-model='selected'
  39. :items='usersFiltered',
  40. :headers='headers',
  41. :search='search',
  42. :page.sync='pagination'
  43. :items-per-page='15'
  44. :loading='loading'
  45. @page-count='pageCount = $event'
  46. hide-default-footer
  47. )
  48. template(slot='item', slot-scope='props')
  49. tr.is-clickable(:active='props.selected', @click='$router.push("/users/" + props.item.id)')
  50. //- td
  51. v-checkbox(hide-details, :input-value='props.selected', color='blue darken-2', @click='props.selected = !props.selected')
  52. td {{ props.item.id }}
  53. td: strong {{ props.item.name }}
  54. td {{ props.item.email }}
  55. td {{ props.item.providerKey }}
  56. td {{ props.item.createdAt | moment('from') }}
  57. td
  58. span(v-if='props.item.lastLoginAt') {{ props.item.lastLoginAt | moment('from') }}
  59. em.grey--text(v-else) Never
  60. td.text-right
  61. v-icon.mr-3(v-if='props.item.isSystem') mdi-lock-outline
  62. status-indicator(positive, pulse, v-if='props.item.isActive')
  63. status-indicator(negative, pulse, v-else)
  64. template(slot='no-data')
  65. .pa-3
  66. v-alert.text-left(icon='mdi-alert', outlined, color='grey')
  67. em.body-2 No users to display!
  68. v-card-chin(v-if='pageCount > 1')
  69. v-spacer
  70. v-pagination(v-model='pagination', :length='pageCount')
  71. v-spacer
  72. user-create(v-model='isCreateDialogShown', @refresh='refresh(false)')
  73. </template>
  74. <script>
  75. import _ from 'lodash'
  76. import gql from 'graphql-tag'
  77. import { StatusIndicator } from 'vue-status-indicator'
  78. import UserCreate from './admin-users-create.vue'
  79. export default {
  80. components: {
  81. StatusIndicator,
  82. UserCreate
  83. },
  84. data() {
  85. return {
  86. selected: [],
  87. pagination: 1,
  88. pageCount: 0,
  89. users: [],
  90. headers: [
  91. { text: 'ID', value: 'id', width: 80, sortable: true },
  92. { text: 'Name', value: 'name', sortable: true },
  93. { text: 'Email', value: 'email', sortable: true },
  94. { text: 'Provider', value: 'provider', sortable: true },
  95. { text: 'Created', value: 'createdAt', sortable: true },
  96. { text: 'Last Login', value: 'lastLoginAt', sortable: true },
  97. { text: '', value: 'actions', sortable: false, width: 80 }
  98. ],
  99. strategies: [],
  100. filterStrategy: 'all',
  101. search: '',
  102. loading: false,
  103. isCreateDialogShown: false
  104. }
  105. },
  106. computed: {
  107. usersFiltered () {
  108. const all = this.filterStrategy === 'all' || this.filterStrategy === ''
  109. return _.filter(this.users, u => all || u.providerKey === this.filterStrategy)
  110. }
  111. },
  112. methods: {
  113. createUser() {
  114. this.isCreateDialogShown = true
  115. },
  116. async refresh(notify = true) {
  117. await this.$apollo.queries.users.refetch()
  118. if (notify) {
  119. this.$store.commit('showNotification', {
  120. message: 'Users list has been refreshed.',
  121. style: 'success',
  122. icon: 'cached'
  123. })
  124. }
  125. }
  126. },
  127. apollo: {
  128. users: {
  129. query: gql`
  130. query {
  131. users {
  132. list {
  133. id
  134. name
  135. email
  136. providerKey
  137. isSystem
  138. isActive
  139. createdAt
  140. lastLoginAt
  141. }
  142. }
  143. }
  144. `,
  145. fetchPolicy: 'network-only',
  146. update: (data) => data.users.list,
  147. watchLoading (isLoading) {
  148. this.loading = isLoading
  149. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-users-refresh')
  150. }
  151. },
  152. strategies: {
  153. query: gql`
  154. query {
  155. authentication {
  156. strategies(
  157. isEnabled: true
  158. ) {
  159. key
  160. title
  161. icon
  162. color
  163. }
  164. }
  165. }
  166. `,
  167. fetchPolicy: 'network-only',
  168. update: (data) => {
  169. return _.concat({
  170. key: 'all',
  171. title: 'All'
  172. }, data.authentication.strategies)
  173. },
  174. watchLoading (isLoading) {
  175. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-users-strategies-refresh')
  176. }
  177. }
  178. }
  179. }
  180. </script>
  181. <style lang='scss'>
  182. </style>