feat: admin dashboard last logins
This commit is contained in:
		| @@ -60,7 +60,7 @@ | ||||
|             v-spacer | ||||
|           v-data-table.pb-2( | ||||
|             :items='recentPages' | ||||
|             :headers='headers' | ||||
|             :headers='recentPagesHeaders' | ||||
|             :loading='recentPagesLoading' | ||||
|             hide-default-footer | ||||
|             hide-default-header | ||||
| @@ -77,23 +77,20 @@ | ||||
|         v-card.radius-7.animated.fadeInUp.wait-p4s | ||||
|           v-toolbar(:color='$vuetify.theme.dark ? `grey darken-2` : `grey lighten-5`', dense, flat) | ||||
|             v-spacer | ||||
|             .overline {{$t('admin:dashboard.mostPopularPages')}} | ||||
|             .overline {{$t('admin:dashboard.lastLogins')}} | ||||
|             v-spacer | ||||
|           v-data-table.pb-2( | ||||
|             :items='popularPages' | ||||
|             :headers='headers' | ||||
|             :loading='popularPagesLoading' | ||||
|             :items='lastLogins' | ||||
|             :headers='lastLoginsHeaders' | ||||
|             :loading='lastLoginsLoading' | ||||
|             hide-default-footer | ||||
|             hide-default-header | ||||
|             ) | ||||
|             template(slot='item', slot-scope='props') | ||||
|               tr.is-clickable(:active='props.selected', @click='$router.push(`/pages/` + props.item.id)') | ||||
|               tr.is-clickable(:active='props.selected', @click='$router.push(`/users/` + props.item.id)') | ||||
|                 td | ||||
|                   .body-2: strong {{ props.item.title }} | ||||
|                 td.admin-pages-path | ||||
|                   v-chip(label, small, :color='$vuetify.theme.dark ? `grey darken-4` : `grey lighten-4`') {{ props.item.locale }} | ||||
|                   span.ml-2.grey--text(:class='$vuetify.theme.dark ? `text--lighten-1` : `text--darken-2`') / {{ props.item.path }} | ||||
|                 td.text-right.caption(width='250') {{ props.item.updatedAt | moment('calendar') }} | ||||
|                   .body-2: strong {{ props.item.name }} | ||||
|                 td.text-right.caption(width='250') {{ props.item.lastLoginAt | moment('calendar') }} | ||||
|  | ||||
|       v-flex(xs12) | ||||
|         v-card.dashboard-contribute.animated.fadeInUp.wait-p4s | ||||
| @@ -112,8 +109,7 @@ | ||||
| import _ from 'lodash' | ||||
| import AnimatedNumber from 'animated-number-vue' | ||||
| import { get } from 'vuex-pathify' | ||||
|  | ||||
| import recentPagesQuery from 'gql/admin/dashboard/dashboard-query-recentpages.gql' | ||||
| import gql from 'graphql-tag' | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
| @@ -123,13 +119,16 @@ export default { | ||||
|     return { | ||||
|       recentPages: [], | ||||
|       recentPagesLoading: false, | ||||
|       popularPages: [], | ||||
|       popularPagesLoading: false, | ||||
|       headers: [ | ||||
|         { text: 'ID', value: 'id', width: 80 }, | ||||
|       recentPagesHeaders: [ | ||||
|         { text: 'Title', value: 'title' }, | ||||
|         { text: 'Path', value: 'path' }, | ||||
|         { text: 'Last Updated', value: 'updatedAt', width: 250 } | ||||
|       ], | ||||
|       lastLogins: [], | ||||
|       lastLoginsLoading: false, | ||||
|       lastLoginsHeaders: [ | ||||
|         { text: 'User', value: 'displayName' }, | ||||
|         { text: 'Last Login', value: 'lastLoginAt', width: 250 } | ||||
|       ] | ||||
|     } | ||||
|   }, | ||||
| @@ -154,12 +153,49 @@ export default { | ||||
|   }, | ||||
|   apollo: { | ||||
|     recentPages: { | ||||
|       query: recentPagesQuery, | ||||
|       query: gql` | ||||
|         query { | ||||
|           pages { | ||||
|             list(limit: 10, orderBy: UPDATED, orderByDirection: DESC) { | ||||
|               id | ||||
|               locale | ||||
|               path | ||||
|               title | ||||
|               description | ||||
|               contentType | ||||
|               isPublished | ||||
|               isPrivate | ||||
|               privateNS | ||||
|               createdAt | ||||
|               updatedAt | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       `, | ||||
|       update: (data) => data.pages.list, | ||||
|       watchLoading (isLoading) { | ||||
|         this.recentPagesLoading = isLoading | ||||
|         this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-dashboard-recentpages') | ||||
|       } | ||||
|     }, | ||||
|     lastLogins: { | ||||
|       query: gql` | ||||
|         query { | ||||
|           users { | ||||
|             lastLogins { | ||||
|               id | ||||
|               name | ||||
|               lastLoginAt | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       `, | ||||
|       fetchPolicy: 'network-only', | ||||
|       update: (data) => data.users.lastLogins, | ||||
|       watchLoading (isLoading) { | ||||
|         this.lastLoginsLoading = isLoading | ||||
|         this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-dashboard-lastlogins') | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,17 +0,0 @@ | ||||
| query { | ||||
|   pages { | ||||
|     list(limit: 10, orderBy: UPDATED, orderByDirection: DESC) { | ||||
|       id | ||||
|       locale | ||||
|       path | ||||
|       title | ||||
|       description | ||||
|       contentType | ||||
|       isPublished | ||||
|       isPrivate | ||||
|       privateNS | ||||
|       createdAt | ||||
|       updatedAt | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| <template lang="pug"> | ||||
|   div | ||||
|     .blue.darken-3.pa-3.d-flex | ||||
|     .blue.darken-3.pa-3.d-flex(v-if='navMode === `MIXED`') | ||||
|       v-btn(depressed, color='blue darken-2', style='min-width:0;', href='/') | ||||
|         v-icon(size='20') mdi-home | ||||
|       v-btn.ml-3(v-if='currentMode === `custom`', depressed, color='blue darken-2', style='flex: 1 1 100%;', @click='switchMode(`browse`)') | ||||
| @@ -61,10 +61,6 @@ export default { | ||||
|       type: Array, | ||||
|       default: () => [] | ||||
|     }, | ||||
|     mode: { | ||||
|       type: String, | ||||
|       default: 'browse' | ||||
|     }, | ||||
|     navMode: { | ||||
|       type: String, | ||||
|       default: 'MIXED' | ||||
| @@ -72,7 +68,7 @@ export default { | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       currentMode: 'browse', | ||||
|       currentMode: 'custom', | ||||
|       currentItems: [], | ||||
|       currentParent: { | ||||
|         id: 0, | ||||
| @@ -193,9 +189,11 @@ export default { | ||||
|     } | ||||
|   }, | ||||
|   mounted () { | ||||
|     this.currentMode = this.mode | ||||
|     if (this.mode === 'browse') { | ||||
|     if (this.navMode === 'TREE') { | ||||
|       this.currentMode = 'browse' | ||||
|       this.loadFromCurrentPath() | ||||
|     } else { | ||||
|       this.currentMode = 'custom' | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -46,6 +46,13 @@ module.exports = { | ||||
|       usr.tfaSecret = '' | ||||
|  | ||||
|       return usr | ||||
|     }, | ||||
|     async lastLogins (obj, args, context, info) { | ||||
|       return WIKI.models.users.query() | ||||
|         .select('id', 'name', 'lastLoginAt') | ||||
|         .whereNotNull('lastLoginAt') | ||||
|         .orderBy('lastLoginAt', 'desc') | ||||
|         .limit(10) | ||||
|     } | ||||
|   }, | ||||
|   UserMutation: { | ||||
|   | ||||
| @@ -29,6 +29,8 @@ type UserQuery { | ||||
|   ): User @auth(requires: ["manage:users", "manage:system"]) | ||||
|  | ||||
|   profile: UserProfile | ||||
|  | ||||
|   lastLogins: [UserLastLogin] @auth(requires: ["write:groups", "manage:groups", "write:users", "manage:users", "manage:system"]) | ||||
| } | ||||
|  | ||||
| # ----------------------------------------------- | ||||
| @@ -99,6 +101,12 @@ type UserResponse { | ||||
|   user: User | ||||
| } | ||||
|  | ||||
| type UserLastLogin { | ||||
|   id: Int! | ||||
|   name: String! | ||||
|   lastLoginAt: Date! | ||||
| } | ||||
|  | ||||
| type UserMinimal { | ||||
|   id: Int! | ||||
|   name: String! | ||||
|   | ||||
		Reference in New Issue
	
	Block a user