Insights.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <template>
  2. <div class="discover-insights-component">
  3. <div v-if="isLoaded" class="container-fluid mt-3">
  4. <div class="row">
  5. <div class="col-md-4 col-lg-3">
  6. <sidebar :user="profile" />
  7. </div>
  8. <div class="col-md-6 col-lg-6">
  9. <b-breadcrumb class="font-default" :items="breadcrumbItems"></b-breadcrumb>
  10. <h1 class="font-default">Account Insights</h1>
  11. <p class="font-default lead">A brief overview of your account</p>
  12. <hr>
  13. <div class="row">
  14. <div class="col-12 col-md-6 mb-3">
  15. <div class="card bg-midnight">
  16. <div class="card-body font-default text-white">
  17. <h1 class="display-4 mb-n2">{{ formatCount(profile.statuses_count) }}</h1>
  18. <p class="primary lead mb-0 font-weight-bold">Posts</p>
  19. </div>
  20. </div>
  21. </div>
  22. <div class="col-12 col-md-6 mb-3">
  23. <div class="card bg-midnight">
  24. <div class="card-body font-default text-white">
  25. <h1 class="display-4 mb-n2">{{ formatCount(profile.followers_count) }}</h1>
  26. <p class="primary lead mb-0 font-weight-bold">Followers</p>
  27. </div>
  28. </div>
  29. </div>
  30. </div>
  31. <div v-if="profile.statuses_count" class="card my-3 bg-midnight">
  32. <div class="card-header bg-dark border-bottom border-primary text-white font-default lead">Popular Posts</div>
  33. <div v-if="!popularLoaded" class="card-body text-white">
  34. <b-spinner/>
  35. </div>
  36. <ul v-else class="list-group list-group-flush font-default text-white">
  37. <li v-for="post in popular" class="list-group-item bg-midnight">
  38. <div class="media align-items-center">
  39. <img
  40. v-if="post.media_attachments.length"
  41. :src="post.media_attachments[0].url"
  42. onerror="this.onerror=null;this.src='/storage/no-preview.png?v=0'"
  43. class="media-photo shadow">
  44. <div class="media-body">
  45. <p class="media-caption mb-0">{{ post.content_text.slice(0, 40) }}</p>
  46. <p class="mb-0">
  47. <span class="font-weight-bold">{{ post.favourites_count }} Likes</span>
  48. <span class="mx-2">·</span>
  49. <span class="text-muted">Posted {{ timeago(post.created_at) }} ago</span>
  50. </p>
  51. </div>
  52. <button class="btn btn-primary primary font-weight-bold rounded-pill" @click="gotoPost(post)">View</button>
  53. </div>
  54. </li>
  55. </ul>
  56. </div>
  57. </div>
  58. </div>
  59. </div>
  60. </div>
  61. </template>
  62. <script type="text/javascript">
  63. import Drawer from './../partials/drawer.vue';
  64. import Sidebar from './../partials/sidebar.vue';
  65. import StatusCard from './../partials/TimelineStatus.vue';
  66. export default {
  67. components: {
  68. "drawer": Drawer,
  69. "sidebar": Sidebar,
  70. "status-card": StatusCard
  71. },
  72. data() {
  73. return {
  74. isLoaded: true,
  75. isLoading: true,
  76. profile: window._sharedData.user,
  77. feed: [],
  78. popular: [],
  79. popularLoaded: false,
  80. breadcrumbItems: [
  81. {
  82. text: 'Discover',
  83. href: '/i/web/discover'
  84. },
  85. {
  86. text: 'Account Insights',
  87. active: true
  88. }
  89. ]
  90. }
  91. },
  92. mounted() {
  93. this.fetchConfig();
  94. },
  95. methods: {
  96. fetchConfig() {
  97. axios.get('/api/pixelfed/v2/discover/meta')
  98. .then(res => {
  99. if(res.data.insights.enabled == false) {
  100. this.$router.push('/i/web/discover');
  101. }
  102. this.fetchPopular();
  103. })
  104. },
  105. fetchPopular() {
  106. axios.get('/api/pixelfed/v2/discover/account-insights')
  107. .then(res => {
  108. this.popular = res.data.filter(p => {
  109. return p.favourites_count;
  110. });
  111. this.popularLoaded = true;
  112. })
  113. },
  114. formatCount(val) {
  115. return App.util.format.count(val);
  116. },
  117. timeago(ts) {
  118. return App.util.format.timeAgo(ts);
  119. },
  120. gotoPost(status) {
  121. this.$router.push({
  122. name: 'post',
  123. path: `/i/web/post/${status.id}`,
  124. params: {
  125. id: status.id,
  126. cachedStatus: status,
  127. cachedProfile: this.profile
  128. }
  129. })
  130. }
  131. }
  132. }
  133. </script>
  134. <style lang="scss" scoped>
  135. .discover-insights-component {
  136. .bg-stellar {
  137. background: #7474BF;
  138. background: -webkit-linear-gradient(to right, #348AC7, #7474BF);
  139. background: linear-gradient(to right, #348AC7, #7474BF);
  140. }
  141. .bg-midnight {
  142. background: #232526;
  143. background: -webkit-linear-gradient(to right, #414345, #232526);
  144. background: linear-gradient(to right, #414345, #232526);
  145. }
  146. .font-default {
  147. font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  148. letter-spacing: -0.7px;
  149. }
  150. .active {
  151. font-weight: 700;
  152. }
  153. .media-photo {
  154. width: 70px;
  155. height: 70px;
  156. border-radius: 8px;
  157. margin-right: 2rem;
  158. object-fit: cover;
  159. }
  160. .media-caption {
  161. letter-spacing: -0.3px;
  162. font-size: 17px;
  163. opacity: 0.7;
  164. }
  165. }
  166. </style>