News.vue 5.0 KB

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