ContentTopicList.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <template>
  2. <div class="ContentTopicList"
  3. :style="localOptions.style">
  4. <template v-if="mounted">
  5. <breadcrumbs class="q-mb-lg" />
  6. <div class="ContentTopicList__header">
  7. <q-banner>
  8. جستجوی پیشرفته محتوایی
  9. </q-banner>
  10. <!-- <q-btn color="primary"-->
  11. <!-- @click="downloadExcel">-->
  12. <!-- <q-icon name="file_download" />-->
  13. <!-- دریافت-->
  14. <!-- </q-btn>-->
  15. </div>
  16. <div class="ContentTopicList__top-filter">
  17. <form-builder v-model:value="topFilterInputs"
  18. @update:value="onTopFilterChange" />
  19. </div>
  20. <div class="ContentTopicList__main">
  21. <div class="ContentTopicList__sidebar">
  22. <sidebar @onChangeFilters="onChangeSidebarFilters" />
  23. </div>
  24. <div class="ContentTopicList__result">
  25. <entity-index v-if="mounted"
  26. ref="entityIndex"
  27. v-model:value="inputs"
  28. :api="api"
  29. :table="table"
  30. :table-keys="tableKeys"
  31. :table-grid-size="true"
  32. :default-layout="false"
  33. :create-route-name="createRouteName"
  34. :show-search-button="false"
  35. :show-expand-button="false"
  36. :show-reload-button="false">
  37. <template #entity-index-table-item-cell="{inputData}">
  38. <topic-item class="topic-item"
  39. :topic="inputData.props.row" />
  40. </template>
  41. </entity-index>
  42. </div>
  43. </div>
  44. </template>
  45. </div>
  46. </template>
  47. <script>
  48. import { shallowRef } from 'vue'
  49. import { EntityIndex } from 'quasar-crud'
  50. import { Ticket } from 'src/models/Ticket.js'
  51. import Sidebar from './components/sidebar.vue'
  52. import TopicItem from './components/TopicItem.vue'
  53. import { mixinWidget } from 'src/mixin/Mixins.js'
  54. import { APIGateway } from 'src/api/APIGateway.js'
  55. import { FormBuilder, FormBuilderAssist } from 'quasar-form-builder'
  56. import Breadcrumbs from 'src/components/Widgets/Breadcrumbs/Breadcrumbs.vue'
  57. import HashtagSelector from 'src/components/FormBuilderCustumComponents/Hashtags/HashtagSelector.vue'
  58. const HashtagSelectorComp = shallowRef(HashtagSelector)
  59. export default {
  60. name: 'ContentList',
  61. components: { EntityIndex, Breadcrumbs, Sidebar, FormBuilder, TopicItem },
  62. mixins: [mixinWidget],
  63. data () {
  64. return {
  65. breadcrumbs: {
  66. visible: true,
  67. loading: false,
  68. path: [
  69. {
  70. label: 'خانه',
  71. to: { name: 'Public.Home' }
  72. },
  73. {
  74. label: 'جستجوی پیشرفته محتوایی',
  75. to: { name: 'Public.PostTopic.List' }
  76. }
  77. ]
  78. },
  79. api: APIGateway.contentTopic.APIAdresses.base,
  80. tableKeys: {
  81. data: 'results',
  82. total: 'count',
  83. currentPage: 'current',
  84. perPage: 'per_page',
  85. pageKey: 'page'
  86. },
  87. inputs: [
  88. { type: 'hidden', name: 'category__in', value: null },
  89. { type: 'hidden', name: 'hashtags__id__in', value: null }
  90. ],
  91. topFilterInputs: [
  92. { type: HashtagSelectorComp, name: 'hashtags', responseKey: 'hashtags_info', col: 'col-12' }
  93. ],
  94. topFilter: {
  95. hashtags: null
  96. },
  97. table: {
  98. columns: [
  99. {
  100. name: 'title',
  101. required: true,
  102. label: 'موضوع پیام',
  103. align: 'left',
  104. field: row => row.title
  105. },
  106. {
  107. name: 'sender',
  108. required: true,
  109. label: 'فرستنده',
  110. align: 'left',
  111. field: row => row.creator_info.firstname + ' ' + row.creator_info.lastname
  112. },
  113. {
  114. name: 'status',
  115. required: true,
  116. label: 'وضعیت',
  117. align: 'left',
  118. field: row => (new Ticket(row)).status_info.label
  119. },
  120. {
  121. name: 'action',
  122. required: true,
  123. label: 'جزییات',
  124. align: 'left',
  125. field: row => ''
  126. }
  127. ]
  128. },
  129. mounted: false,
  130. sidebarFilters: { categories: [] },
  131. createRouteName: ''
  132. }
  133. },
  134. mounted() {
  135. this.$store.commit('AppLayout/updateBreadcrumbs', this.breadcrumbs)
  136. this.mounted = true
  137. },
  138. methods: {
  139. onChangeSidebarFilters (filters) {
  140. this.sidebarFilters = Object.assign(filters, { categories: [] })
  141. this.search()
  142. },
  143. onTopFilterChange () {
  144. this.topFilter = FormBuilderAssist.getFormData(this.topFilterInputs)
  145. this.search()
  146. },
  147. search () {
  148. this.updateFilters()
  149. if (!this.$refs.entityIndex) {
  150. return
  151. }
  152. this.$refs.entityIndex.search()
  153. },
  154. updateFilters () {
  155. FormBuilderAssist.setAttributeByName(this.inputs, 'category__in', 'value', this.sidebarFilters.category__in?.join())
  156. FormBuilderAssist.setAttributeByName(this.inputs, 'hashtags__id__in', 'value', this.topFilter.hashtags?.join())
  157. },
  158. downloadExcel () {
  159. }
  160. }
  161. }
  162. </script>
  163. <style scoped lang="scss">
  164. .ContentTopicList {
  165. .ContentTopicList__header {
  166. display: flex;
  167. justify-content: space-between;
  168. margin-bottom: 24px;
  169. }
  170. .ContentTopicList__top-filter {
  171. margin-bottom: 24px;
  172. }
  173. .ContentTopicList__main {
  174. $gap: 24px;
  175. display: flex;
  176. gap: $gap;
  177. flex-wrap: wrap;
  178. justify-content: flex-start;
  179. $sidebar-width: 312px;
  180. .ContentTopicList__sidebar {
  181. width: $sidebar-width;
  182. @media screen and (max-width: 800px) {
  183. & {
  184. width: 100%;
  185. }
  186. }
  187. }
  188. .ContentTopicList__result {
  189. width: calc( 100% - #{$sidebar-width} - #{$gap} );
  190. .topic-item {
  191. width: 100%;
  192. }
  193. @media screen and (max-width: 800px) {
  194. & {
  195. width: 100%;
  196. }
  197. }
  198. }
  199. }
  200. }
  201. </style>