PostComments.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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 v-for="(reply, index) in results" class="mb-1 d-flex justify-content-between align-items-top read-more" style="overflow-y: hidden;">
  20. <span>
  21. <a class="text-dark font-weight-bold mr-1" :href="reply.account.url" v-bind:title="reply.account.username">{{truncate(reply.account.username,15)}}</a>
  22. <span class="text-break" v-html="reply.content"></span>
  23. </span>
  24. <span class="pl-2" style="min-width:38px">
  25. <span v-on:click="likeStatus(reply, $event)"><i v-bind:class="[reply.favourited ? 'fas fa-heart fa-sm text-danger':'far fa-heart fa-sm text-lighter']"></i></span>
  26. <post-menu :status="reply" :profile="user" :size="'sm'" :modal="'true'" class="d-inline-block pl-2" v-on:deletePost="deleteComment(reply.id, index)"></post-menu>
  27. </span>
  28. </p>
  29. </div>
  30. </div>
  31. </div>
  32. </template>
  33. <style type="text/css" scoped>
  34. .text-lighter {
  35. color:#B8C2CC !important;
  36. }
  37. .text-break {
  38. word-break: break-all !important;
  39. }
  40. .comments p {
  41. margin-bottom: 0;
  42. }
  43. </style>
  44. <script>
  45. export default {
  46. props: ['post-id', 'post-username', 'user'],
  47. data() {
  48. return {
  49. results: null,
  50. pagination: {},
  51. min_id: 0,
  52. max_id: 0,
  53. reply_to_profile_id: 0,
  54. }
  55. },
  56. mounted() {
  57. this.fetchData();
  58. },
  59. updated() {
  60. pixelfed.readmore();
  61. },
  62. methods: {
  63. embed(e) {
  64. //pixelfed.embed.build(e);
  65. },
  66. deleteComment(id, i) {
  67. axios.post('/i/delete', {
  68. type: 'comment',
  69. item: id
  70. }).then(res => {
  71. this.results.splice(i, 1);
  72. }).catch(err => {
  73. swal('Something went wrong!', 'Please try again later', 'error');
  74. });
  75. },
  76. l(e) {
  77. let len = e.length;
  78. if(len < 10) { return e; }
  79. return e.substr(0, 10)+'...';
  80. },
  81. reply(e) {
  82. this.reply_to_profile_id = e.account.id;
  83. $('.comment-form input[name=comment]').val('@'+e.account.username+' ');
  84. $('.comment-form input[name=comment]').focus();
  85. },
  86. fetchData() {
  87. let url = '/api/v2/comments/'+this.postUsername+'/status/'+this.postId;
  88. axios.get(url)
  89. .then(response => {
  90. let self = this;
  91. this.results = _.reverse(response.data.data);
  92. this.pagination = response.data.meta.pagination;
  93. if(this.results.length > 0) {
  94. $('.load-more-link').removeClass('d-none');
  95. }
  96. $('.postCommentsLoader').addClass('d-none');
  97. $('.postCommentsContainer').removeClass('d-none');
  98. }).catch(error => {
  99. if(!error.response) {
  100. $('.postCommentsLoader .lds-ring')
  101. .attr('style','width:100%')
  102. .addClass('pt-4 font-weight-bold text-muted')
  103. .text('An error occurred, cannot fetch comments. Please try again later.');
  104. } else {
  105. switch(error.response.status) {
  106. case 401:
  107. $('.postCommentsLoader .lds-ring')
  108. .attr('style','width:100%')
  109. .addClass('pt-4 font-weight-bold text-muted')
  110. .text('Please login to view.');
  111. break;
  112. default:
  113. $('.postCommentsLoader .lds-ring')
  114. .attr('style','width:100%')
  115. .addClass('pt-4 font-weight-bold text-muted')
  116. .text('An error occurred, cannot fetch comments. Please try again later.');
  117. break;
  118. }
  119. }
  120. });
  121. },
  122. loadMore(e) {
  123. e.preventDefault();
  124. if(this.pagination.total_pages == 1 || this.pagination.current_page == this.pagination.total_pages) {
  125. $('.load-more-link').addClass('d-none');
  126. return;
  127. }
  128. $('.postCommentsLoader').removeClass('d-none');
  129. let next = this.pagination.links.next;
  130. axios.get(next)
  131. .then(response => {
  132. let self = this;
  133. let res = response.data.data;
  134. $('.postCommentsLoader').addClass('d-none');
  135. for(let i=0; i < res.length; i++) {
  136. this.results.unshift(res[i]);
  137. }
  138. this.pagination = response.data.meta.pagination;
  139. });
  140. },
  141. likeStatus(status, $event) {
  142. if($('body').hasClass('loggedIn') == false) {
  143. return;
  144. }
  145. axios.post('/i/like', {
  146. item: status.id
  147. }).then(res => {
  148. status.favourites_count = res.data.count;
  149. if(status.favourited == true) {
  150. status.favourited = false;
  151. } else {
  152. status.favourited = true;
  153. }
  154. }).catch(err => {
  155. swal('Error', 'Something went wrong, please try again later.', 'error');
  156. });
  157. },
  158. truncate(str,lim) {
  159. return _.truncate(str,{
  160. length: lim
  161. });
  162. }
  163. },
  164. }
  165. </script>