PostComments.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. <style scoped>
  2. span {
  3. font-size: 14px;
  4. }
  5. .comment-text {
  6. }
  7. .comment-text p {
  8. display: inline;
  9. }
  10. </style>
  11. <template>
  12. <div>
  13. <div class="postCommentsLoader text-center">
  14. <div class="lds-ring"><div></div><div></div><div></div><div></div></div>
  15. </div>
  16. <div class="postCommentsContainer d-none">
  17. <p class="mb-1 text-center load-more-link d-none"><a href="#" class="text-muted" v-on:click="loadMore">Load more comments</a></p>
  18. <div class="comments" data-min-id="0" data-max-id="0">
  19. <p class="mb-1" v-for="(comment, index) in results" :data-id="comment.id" :key="comment.id">
  20. <span class="d-flex justify-content-between align-items-center">
  21. <span class="pr-3" style="overflow: hidden;">
  22. <div class="font-weight-bold pr-1"><bdi><a class="text-dark" :href="comment.account.url" :title="comment.account.username">{{l(comment.account.username)}}</a></bdi>
  23. </div>
  24. <div class="read-more" style="overflow: hidden;" :id="comment.id + '-reply-readmore'">
  25. <span class="comment-text" v-html="comment.content" style="overflow: hidden;"></span>
  26. </div>
  27. </span>
  28. <b-dropdown :id="comment.uri" variant="link" no-caret right class="float-right">
  29. <template slot="button-content">
  30. <i class="fas fa-ellipsis-v text-muted"></i><span class="sr-only">Options</span>
  31. </template>
  32. <b-dropdown-item class="font-weight-bold" v-on:click="reply(comment)">Reply</b-dropdown-item>
  33. <b-dropdown-item class="font-weight-bold" :href="comment.url">Permalink</b-dropdown-item>
  34. <!-- <b-dropdown-item class="font-weight-bold" v-on:click="embed(comment)">Embed</b-dropdown-item> -->
  35. <b-dropdown-item class="font-weight-bold" :href="comment.account.url">Profile</b-dropdown-item>
  36. <b-dropdown-divider></b-dropdown-divider>
  37. <b-dropdown-item class="font-weight-bold" :href="'/i/report?type=post&id='+comment.id">Report</b-dropdown-item>
  38. <b-dropdown-item class="font-weight-bold" v-on:click="deleteComment(comment.id, index)" v-if="comment.account.id == user.id">Delete</b-dropdown-item>
  39. </b-dropdown>
  40. </span>
  41. </p>
  42. </div>
  43. </div>
  44. </div>
  45. </template>
  46. <script>
  47. export default {
  48. props: ['post-id', 'post-username', 'user'],
  49. data() {
  50. return {
  51. results: null,
  52. pagination: {},
  53. min_id: 0,
  54. max_id: 0,
  55. reply_to_profile_id: 0,
  56. }
  57. },
  58. mounted() {
  59. this.fetchData();
  60. },
  61. updated() {
  62. pixelfed.readmore();
  63. },
  64. methods: {
  65. embed(e) {
  66. //pixelfed.embed.build(e);
  67. },
  68. deleteComment(id, i) {
  69. axios.post('/i/delete', {
  70. type: 'comment',
  71. item: id
  72. }).then(res => {
  73. this.results.splice(i, 1);
  74. }).catch(err => {
  75. swal('Something went wrong!', 'Please try again later', 'error');
  76. });
  77. },
  78. l(e) {
  79. let len = e.length;
  80. if(len < 10) { return e; }
  81. return e.substr(0, 10)+'...';
  82. },
  83. reply(e) {
  84. this.reply_to_profile_id = e.account.id;
  85. $('.comment-form input[name=comment]').val('@'+e.account.username+' ');
  86. $('.comment-form input[name=comment]').focus();
  87. },
  88. fetchData() {
  89. let url = '/api/v2/comments/'+this.postUsername+'/status/'+this.postId;
  90. axios.get(url)
  91. .then(response => {
  92. let self = this;
  93. this.results = _.reverse(response.data.data);
  94. this.pagination = response.data.meta.pagination;
  95. if(this.results.length > 0) {
  96. $('.load-more-link').removeClass('d-none');
  97. }
  98. $('.postCommentsLoader').addClass('d-none');
  99. $('.postCommentsContainer').removeClass('d-none');
  100. }).catch(error => {
  101. if(!error.response) {
  102. $('.postCommentsLoader .lds-ring')
  103. .attr('style','width:100%')
  104. .addClass('pt-4 font-weight-bold text-muted')
  105. .text('An error occurred, cannot fetch comments. Please try again later.');
  106. } else {
  107. switch(error.response.status) {
  108. case 401:
  109. $('.postCommentsLoader .lds-ring')
  110. .attr('style','width:100%')
  111. .addClass('pt-4 font-weight-bold text-muted')
  112. .text('Please login to view.');
  113. break;
  114. default:
  115. $('.postCommentsLoader .lds-ring')
  116. .attr('style','width:100%')
  117. .addClass('pt-4 font-weight-bold text-muted')
  118. .text('An error occurred, cannot fetch comments. Please try again later.');
  119. break;
  120. }
  121. }
  122. });
  123. },
  124. loadMore(e) {
  125. e.preventDefault();
  126. if(this.pagination.total_pages == 1 || this.pagination.current_page == this.pagination.total_pages) {
  127. $('.load-more-link').addClass('d-none');
  128. return;
  129. }
  130. $('.postCommentsLoader').removeClass('d-none');
  131. let next = this.pagination.links.next;
  132. axios.get(next)
  133. .then(response => {
  134. let self = this;
  135. let res = response.data.data;
  136. $('.postCommentsLoader').addClass('d-none');
  137. for(let i=0; i < res.length; i++) {
  138. this.results.unshift(res[i]);
  139. }
  140. this.pagination = response.data.meta.pagination;
  141. });
  142. }
  143. }
  144. }
  145. </script>