News.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <script setup lang="ts">
  2. import { ref } from "vue";
  3. import { useStore } from "vuex";
  4. import Toast from "toasters";
  5. import AdvancedTable from "@/components/AdvancedTable.vue";
  6. const store = useStore();
  7. const { socket } = store.state.websockets;
  8. const columnDefault = ref({
  9. sortable: true,
  10. hidable: true,
  11. defaultVisibility: "shown",
  12. draggable: true,
  13. resizable: true,
  14. minWidth: 150,
  15. maxWidth: 600
  16. });
  17. const columns = ref([
  18. {
  19. name: "options",
  20. displayName: "Options",
  21. properties: ["_id"],
  22. sortable: false,
  23. hidable: false,
  24. resizable: false,
  25. minWidth: 85,
  26. defaultWidth: 85
  27. },
  28. {
  29. name: "status",
  30. displayName: "Status",
  31. properties: ["status"],
  32. sortProperty: "status",
  33. defaultWidth: 150
  34. },
  35. {
  36. name: "showToNewUsers",
  37. displayName: "Show to new users",
  38. properties: ["showToNewUsers"],
  39. sortProperty: "showToNewUsers",
  40. defaultWidth: 180
  41. },
  42. {
  43. name: "title",
  44. displayName: "Title",
  45. properties: ["title"],
  46. sortProperty: "title"
  47. },
  48. {
  49. name: "createdBy",
  50. displayName: "Created By",
  51. properties: ["createdBy"],
  52. sortProperty: "createdBy",
  53. defaultWidth: 150
  54. },
  55. {
  56. name: "markdown",
  57. displayName: "Markdown",
  58. properties: ["markdown"],
  59. sortProperty: "markdown"
  60. }
  61. ]);
  62. const filters = ref([
  63. {
  64. name: "status",
  65. displayName: "Status",
  66. property: "status",
  67. filterTypes: ["contains", "exact", "regex"],
  68. defaultFilterType: "contains"
  69. },
  70. {
  71. name: "showToNewUsers",
  72. displayName: "Show to new users",
  73. property: "showToNewUsers",
  74. filterTypes: ["boolean"],
  75. defaultFilterType: "boolean"
  76. },
  77. {
  78. name: "title",
  79. displayName: "Title",
  80. property: "title",
  81. filterTypes: ["contains", "exact", "regex"],
  82. defaultFilterType: "contains"
  83. },
  84. {
  85. name: "createdBy",
  86. displayName: "Created By",
  87. property: "createdBy",
  88. filterTypes: ["contains", "exact", "regex"],
  89. defaultFilterType: "contains"
  90. },
  91. {
  92. name: "markdown",
  93. displayName: "Markdown",
  94. property: "markdown",
  95. filterTypes: ["contains", "exact", "regex"],
  96. defaultFilterType: "contains"
  97. }
  98. ]);
  99. const events = ref({
  100. adminRoom: "news",
  101. updated: {
  102. event: "admin.news.updated",
  103. id: "news._id",
  104. item: "news"
  105. },
  106. removed: {
  107. event: "admin.news.deleted",
  108. id: "newsId"
  109. }
  110. });
  111. const openModal = payload =>
  112. store.dispatch("modalVisibility/openModal", payload);
  113. const remove = id => {
  114. socket.dispatch("news.remove", id, res => new Toast(res.message));
  115. };
  116. </script>
  117. <template>
  118. <div class="admin-tab container">
  119. <page-metadata title="Admin | News" />
  120. <div class="card tab-info">
  121. <div class="info-row">
  122. <h1>News</h1>
  123. <p>Create and update news items</p>
  124. </div>
  125. <div class="button-row">
  126. <button
  127. class="is-primary button"
  128. @click="
  129. openModal({
  130. modal: 'editNews',
  131. data: { createNews: true }
  132. })
  133. "
  134. >
  135. Create News Item
  136. </button>
  137. </div>
  138. </div>
  139. <advanced-table
  140. :column-default="columnDefault"
  141. :columns="columns"
  142. :filters="filters"
  143. data-action="news.getData"
  144. name="admin-news"
  145. :max-width="1200"
  146. :events="events"
  147. >
  148. <template #column-options="slotProps">
  149. <div class="row-options">
  150. <button
  151. class="button is-primary icon-with-button material-icons"
  152. @click="
  153. openModal({
  154. modal: 'editNews',
  155. data: { newsId: slotProps.item._id }
  156. })
  157. "
  158. content="Edit News"
  159. v-tippy
  160. >
  161. edit
  162. </button>
  163. <quick-confirm
  164. @confirm="remove(slotProps.item._id)"
  165. :disabled="slotProps.item.removed"
  166. >
  167. <button
  168. class="button is-danger icon-with-button material-icons"
  169. content="Remove News"
  170. v-tippy
  171. >
  172. delete_forever
  173. </button>
  174. </quick-confirm>
  175. </div>
  176. </template>
  177. <template #column-status="slotProps">
  178. <span :title="slotProps.item.status">{{
  179. slotProps.item.status
  180. }}</span>
  181. </template>
  182. <template #column-showToNewUsers="slotProps">
  183. <span :title="slotProps.item.showToNewUsers">{{
  184. slotProps.item.showToNewUsers
  185. }}</span>
  186. </template>
  187. <template #column-title="slotProps">
  188. <span :title="slotProps.item.title">{{
  189. slotProps.item.title
  190. }}</span>
  191. </template>
  192. <template #column-createdBy="slotProps">
  193. <user-link
  194. :user-id="slotProps.item.createdBy"
  195. :alt="slotProps.item.createdBy"
  196. />
  197. </template>
  198. <template #column-markdown="slotProps">
  199. <span :title="slotProps.item.markdown">{{
  200. slotProps.item.markdown
  201. }}</span>
  202. </template>
  203. </advanced-table>
  204. </div>
  205. </template>