admin-dashboard.vue 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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='/svg/icon-browse-page.svg', alt='Dashboard', style='width: 80px;')
  7. .admin-header-title
  8. .headline.primary--text.animated.fadeInLeft {{ $t('admin:dashboard.title') }}
  9. .subtitle-1.grey--text.animated.fadeInLeft.wait-p2s {{ $t('admin:dashboard.subtitle') }}
  10. v-flex(xs12 md6 lg4 xl3 d-flex)
  11. v-card.primary.dashboard-card.animated.fadeInUp(dark)
  12. v-card-text
  13. v-icon.dashboard-icon mdi-file-document-outline
  14. .overline {{$t('admin:dashboard.pages')}}
  15. animated-number.display-1(
  16. :value='info.pagesTotal'
  17. :duration='2000'
  18. :formatValue='round'
  19. easing='easeOutQuint'
  20. )
  21. v-flex(xs12 md6 lg4 xl3 d-flex)
  22. v-card.indigo.lighten-1.dashboard-card.animated.fadeInUp.wait-p2s(dark)
  23. v-card-text
  24. v-icon.dashboard-icon mdi-account
  25. .overline {{$t('admin:dashboard.users')}}
  26. animated-number.display-1(
  27. :value='info.usersTotal'
  28. :duration='2000'
  29. :formatValue='round'
  30. easing='easeOutQuint'
  31. )
  32. v-flex(xs12 md6 lg4 xl3 d-flex)
  33. v-card.indigo.lighten-2.dashboard-card.animated.fadeInUp.wait-p4s(dark)
  34. v-card-text
  35. v-icon.dashboard-icon mdi-account-group
  36. .overline {{$t('admin:dashboard.groups')}}
  37. animated-number.display-1(
  38. :value='info.groupsTotal'
  39. :duration='2000'
  40. :formatValue='round'
  41. easing='easeOutQuint'
  42. )
  43. v-flex(xs12 md6 lg12 xl3 d-flex)
  44. v-card.dashboard-card.animated.fadeInUp.wait-p6s(
  45. :class='isLatestVersion ? "teal lighten-2" : "red lighten-2"'
  46. dark
  47. )
  48. v-btn.btn-animate-wrench(fab, absolute, right, top, small, light, to='system', v-if='hasPermission(`manage:system`)')
  49. v-icon(:color='isLatestVersion ? `teal` : `red darken-4`', small) mdi-wrench
  50. v-card-text
  51. v-icon.dashboard-icon mdi-blur
  52. .subtitle-1 Wiki.js {{info.currentVersion}}
  53. .body-2(v-if='isLatestVersion') {{$t('admin:dashboard.versionLatest')}}
  54. .body-2(v-else) {{$t('admin:dashboard.versionNew', { version: info.latestVersion })}}
  55. v-flex(xs12, xl6)
  56. v-card.radius-7.animated.fadeInUp.wait-p2s
  57. v-card-title.subtitle-1(:class='$vuetify.dark ? `grey darken-2` : `grey lighten-5`') Recent Pages
  58. v-data-table.pb-2(
  59. :items='recentPages'
  60. hide-default-footer
  61. hide-default-header
  62. )
  63. template(slot='items' slot-scope='props')
  64. td(width='20', style='padding-right: 0;'): v-icon insert_drive_file
  65. td
  66. .body-2.primary--text {{ props.item.title }}
  67. .caption.grey--text.text--darken-2 {{ props.item.description }}
  68. td.caption /{{ props.item.path }}
  69. td.grey--text.text--darken-2(width='250')
  70. .caption: strong Updated {{ props.item.updatedAt | moment('from') }}
  71. .caption Created {{ props.item.createdAt | moment('calendar') }}
  72. v-flex(xs12, xl6)
  73. v-card.radius-7.animated.fadeInUp.wait-p4s
  74. v-card-title.subtitle-1(:class='$vuetify.dark ? `grey darken-2` : `grey lighten-5`') Most Popular Pages
  75. v-data-table.pb-2(
  76. :items='popularPages'
  77. hide-default-footer
  78. hide-default-header
  79. )
  80. template(slot='items' slot-scope='props')
  81. td(width='20', style='padding-right: 0;'): v-icon insert_drive_file
  82. td
  83. .body-2.primary--text {{ props.item.title }}
  84. .caption.grey--text.text--darken-2 {{ props.item.description }}
  85. td.caption /{{ props.item.path }}
  86. td.grey--text.text--darken-2(width='250')
  87. .caption: strong Updated {{ props.item.updatedAt | moment('from') }}
  88. .caption Created {{ props.item.createdAt | moment('calendar') }}
  89. v-flex(xs12)
  90. v-card.dashboard-contribute.animated.fadeInUp.wait-p4s
  91. v-card-text
  92. img(src='/svg/icon-heart-health.svg', alt='Contribute', style='height: 80px;')
  93. .pl-5
  94. .subtitle-1 {{$t('admin:contribute.title')}}
  95. .body-2.mt-3: strong {{$t('admin:dashboard.contributeSubtitle')}}
  96. .body-2 {{$t('admin:dashboard.contributeHelp')}}
  97. v-btn.mx-0.mt-4(:color='$vuetify.dark ? `indigo lighten-3` : `indigo`', outlined, small, to='/contribute')
  98. .caption: strong {{$t('admin:dashboard.contributeLearnMore')}}
  99. </template>
  100. <script>
  101. import _ from 'lodash'
  102. import AnimatedNumber from 'animated-number-vue'
  103. import { get } from 'vuex-pathify'
  104. export default {
  105. components: {
  106. AnimatedNumber
  107. },
  108. data() {
  109. return {
  110. recentPages: [],
  111. popularPages: []
  112. }
  113. },
  114. computed: {
  115. isLatestVersion() {
  116. return this.info.currentVersion === this.info.latestVersion
  117. },
  118. info: get('admin/info'),
  119. permissions: get('user/permissions')
  120. },
  121. methods: {
  122. round(val) { return Math.round(val) },
  123. hasPermission(prm) {
  124. if (_.isArray(prm)) {
  125. return _.some(prm, p => {
  126. return _.includes(this.permissions, p)
  127. })
  128. } else {
  129. return _.includes(this.permissions, prm)
  130. }
  131. }
  132. }
  133. }
  134. </script>
  135. <style lang='scss'>
  136. .dashboard-card {
  137. display: flex;
  138. width: 100%;
  139. border-radius: 7px;
  140. .v-card__text {
  141. overflow: hidden;
  142. position: relative;
  143. }
  144. }
  145. .dashboard-contribute {
  146. background-color: #FFF;
  147. background-image: linear-gradient(to bottom, #FFF 0%, lighten(mc('indigo', '50'), 3%) 100%);
  148. border-radius: 7px;
  149. @at-root .theme--dark & {
  150. background-color: mc('grey', '800');
  151. background-image: linear-gradient(to bottom, mc('grey', '800') 0%, darken(mc('grey', '800'), 6%) 100%);
  152. }
  153. .v-card__text {
  154. display: flex;
  155. align-items: center;
  156. color: mc('indigo', '500') !important;
  157. @at-root .theme--dark & {
  158. color: mc('grey', '300') !important;
  159. }
  160. }
  161. }
  162. .dashboard-icon {
  163. position: absolute;
  164. right: 0;
  165. top: 12px;
  166. font-size: 100px !important;
  167. opacity: .25;
  168. }
  169. </style>