TopPosts.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <template>
  2. <div class='widgets__top_posts'>
  3. <template v-if='data_.length'>
  4. <div
  5. class='widgets__top_posts__item'
  6. :class='"widgets__top_posts__item--" + $index'
  7. v-for='(thread, $index) in data'
  8. @click='goToThread(thread)'
  9. >
  10. <div class='widgets__top_posts__item__number' v-if='thread.Thread'>{{$index + 1}}</div>
  11. <div class='widgets__top_posts__item__info'>
  12. <div class='widgets__top_posts__item__title'>
  13. <template v-if='thread.Thread'>{{thread.Thread.name}}</template>
  14. </div>
  15. <div class='widgets__top_posts__item__views' v-if='thread.Thread'>
  16. {{thread.pageViews}} {{thread.pageViews | pluralize('page view')}}
  17. </div>
  18. </div>
  19. </div>
  20. </template>
  21. <div class='widgets__top_posts__overlay widgets__top_posts__overlay--show' v-else>
  22. <div class='widgets__top_posts__overlay__message'>No threads today</div>
  23. </div>
  24. <div class='widgets__top_posts__overlay' :class='{ "widgets__top_posts__overlay--show" : loading }'>
  25. <loading-icon></loading-icon>
  26. </div>
  27. </div>
  28. </template>
  29. <script>
  30. import LoadingIcon from '../LoadingIcon'
  31. import AjaxErrorHandler from '../../assets/js/errorHandler'
  32. export default {
  33. name: 'TopPosts',
  34. components: { LoadingIcon },
  35. data () {
  36. return {
  37. loading: true,
  38. data_: []
  39. }
  40. },
  41. computed: {
  42. data () {
  43. let ret = []
  44. for(let i = 0; i < 4; i++) {
  45. if(this.data_[i]) {
  46. ret.push(this.data_[i])
  47. } else {
  48. ret.push({})
  49. }
  50. }
  51. return ret
  52. }
  53. },
  54. methods: {
  55. goToThread (thread) {
  56. if(thread.Thread) {
  57. this.$router.push(
  58. '/thread/' +
  59. thread.Thread.slug + '/' +
  60. thread.Thread.id
  61. )
  62. }
  63. }
  64. },
  65. created () {
  66. this.axios
  67. .get('/api/v1/log/top-threads')
  68. .then(res => {
  69. this.data_ = res.data
  70. this.loading = false
  71. })
  72. .catch(AjaxErrorHandler(this.$store))
  73. }
  74. }
  75. </script>
  76. <style lang='scss' scoped>
  77. @import '../../assets/scss/variables.scss';
  78. .widgets__top_posts {
  79. background-color: #fff;
  80. width: 100%;
  81. height: 100%;
  82. overflow: auto;
  83. border-radius: 0.25rem 0.25rem 0 0;
  84. position: relative;
  85. @at-root #{&}__overlay {
  86. @include loading-overlay($color__gray--darkest, 0.25rem 0.25rem 0 0);
  87. }
  88. @at-root #{&}__item {
  89. display: flex;
  90. flex-direction: row;
  91. padding: 0.25rem 1rem;
  92. cursor: default;
  93. height: 25%;
  94. overflow: hidden;
  95. padding-top: 0.125rem;
  96. transition: filter 0.2s;
  97. &:hover {
  98. filter: brightness(0.9);
  99. }
  100. @for $i from 0 through 3 {
  101. @at-root #{&}--#{$i} {
  102. $alpha: null;
  103. @if $i == 3 {
  104. $alpha: 0.075;
  105. } @else {
  106. $alpha: 0.8 - ($i + 1) / 5
  107. }
  108. background-color: rgba(160, 160, 160, $alpha);
  109. }
  110. }
  111. @at-root #{&}__number {
  112. font-size: 1.75rem;
  113. font-family: $font--role-emphasis;
  114. margin-right: 1rem;
  115. width: 1rem;
  116. @include user-select(none);
  117. }
  118. @at-root #{&}__title {
  119. font-size: 1.125rem;
  120. text-overflow: ellipsis;
  121. width: 13rem;
  122. cursor: pointer;
  123. white-space: nowrap;
  124. overflow: hidden;
  125. }
  126. @at-root #{&}__views {
  127. color: $color__text--secondary;
  128. font-size: 0.9rem;
  129. margin-top: -0.125rem;
  130. }
  131. }
  132. }
  133. </style>