1
0

AnnouncementsCard.vue 4.1 KB

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