AnnouncementsCard.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <template>
  2. <div>
  3. <transition name="fade">
  4. <div v-if="announcements.length" class="card border shadow-none mb-3" style="max-width: 18rem;">
  5. <div class="card-body">
  6. <div class="card-title mb-0">
  7. <span class="font-weight-bold">{{announcement.title}}</span>
  8. <span class="float-right cursor-pointer" title="Close" @click="close"><i class="fas fa-times text-lighter"></i></span>
  9. </div>
  10. <p class="card-text">
  11. <span style="font-size:13px;">{{announcement.summary}}</span>
  12. </p>
  13. <p class="d-flex align-items-center justify-content-between mb-0">
  14. <a v-if="announcement.url" :href="announcement.url" class="small font-weight-bold mb-0">Read more</a>
  15. <span v-else></span>
  16. <span>
  17. <span :class="[showPrev ? 'btn btn-outline-secondary btn-sm py-0':'btn btn-outline-secondary btn-sm py-0 disabled']" :disabled="showPrev == false" @click="loadPrev()">
  18. <i class="fas fa-chevron-left fa-sm"></i>
  19. </span>
  20. <span class="btn btn-outline-success btn-sm py-0 mx-1" title="Mark as Read" data-toggle="tooltip" data-placement="bottom" @click="markAsRead()">
  21. <i class="fas fa-check fa-sm"></i>
  22. </span>
  23. <span :class="[showNext ? 'btn btn-outline-secondary btn-sm py-0':'btn btn-outline-secondary btn-sm py-0 disabled']" :disabled="showNext == false" @click="loadNext()">
  24. <i class="fas fa-chevron-right fa-sm"></i>
  25. </span>
  26. </span>
  27. </p>
  28. </div>
  29. </div>
  30. </transition>
  31. </div>
  32. </template>
  33. <style type="text/css" scoped>
  34. .fade-enter-active, .fade-leave-active {
  35. transition: opacity .5s;
  36. }
  37. .fade-enter, .fade-leave-to {
  38. opacity: 0;
  39. }
  40. </style>
  41. <script type="text/javascript">
  42. export default {
  43. data() {
  44. return {
  45. announcements: [],
  46. announcement: {},
  47. cursor: 0,
  48. showNext: true,
  49. showPrev: false
  50. }
  51. },
  52. mounted() {
  53. this.fetchAnnouncements();
  54. },
  55. updated() {
  56. $('[data-toggle="tooltip"]').tooltip()
  57. },
  58. methods: {
  59. fetchAnnouncements() {
  60. let self = this;
  61. let key = 'metro-tips-closed';
  62. let cached = JSON.parse(window.localStorage.getItem(key));
  63. axios.get('/api/pixelfed/v1/newsroom/timeline')
  64. .then(res => {
  65. self.announcements = res.data.filter(p => {
  66. if(cached) {
  67. return cached.indexOf(p.id) == -1;
  68. } else {
  69. return true;
  70. }
  71. });
  72. self.announcement = self.announcements[0]
  73. if(self.announcements.length == 1) {
  74. self.showNext = false;
  75. }
  76. })
  77. },
  78. loadNext() {
  79. if(!this.showNext) {
  80. return;
  81. }
  82. this.cursor += 1;
  83. this.announcement = this.announcements[this.cursor];
  84. if((this.cursor + 1) == this.announcements.length) {
  85. this.showNext = false;
  86. }
  87. if(this.cursor >= 1) {
  88. this.showPrev = true;
  89. }
  90. },
  91. loadPrev() {
  92. if(!this.showPrev) {
  93. return;
  94. }
  95. this.cursor -= 1;
  96. this.announcement = this.announcements[this.cursor];
  97. if(this.cursor == 0) {
  98. this.showPrev = false;
  99. }
  100. if(this.cursor < this.announcements.length) {
  101. this.showNext = true;
  102. }
  103. },
  104. closeNewsroomPost(id, index) {
  105. let key = 'metro-tips-closed';
  106. let ctx = [];
  107. let cached = window.localStorage.getItem(key);
  108. if(cached) {
  109. ctx = JSON.parse(cached);
  110. }
  111. ctx.push(id);
  112. window.localStorage.setItem(key, JSON.stringify(ctx));
  113. this.newsroomPosts = this.newsroomPosts.filter(res => {
  114. return res.id !== id
  115. });
  116. if(this.newsroomPosts.length == 0) {
  117. this.showTips = false;
  118. } else {
  119. this.newsroomPost = [ this.newsroomPosts[0] ];
  120. }
  121. },
  122. close() {
  123. window.localStorage.setItem('metro-tips', false);
  124. this.$emit('show-tips', false);
  125. },
  126. markAsRead() {
  127. let vm = this;
  128. axios.post('/api/pixelfed/v1/newsroom/markasread', {
  129. id: this.announcement.id
  130. })
  131. .then(res => {
  132. let cur = vm.cursor;
  133. vm.announcements.splice(cur, 1);
  134. vm.announcement = vm.announcements[0];
  135. vm.cursor = 0;
  136. vm.showPrev = false;
  137. vm.showNext = vm.announcements.length > 1;
  138. })
  139. .catch(err => {
  140. swal('Oops, Something went wrong', 'There was a problem with your request, please try again later.', 'error');
  141. });
  142. }
  143. }
  144. }
  145. </script>