You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

listView.vue 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /* eslint-disable no-restricted-syntax */
  2. /* eslint-disable guard-for-in */
  3. <template>
  4. <div>
  5. <div class="d-flex justify-content-between" v-if="!hideSearch">
  6. <div class="p-2">
  7. <input v-model="searchItem" class="form-control" placeholder="Search ..." />
  8. </div>
  9. </div>
  10. <table id="table" class="table table-bordered table-hover">
  11. <thead>
  12. <tr class="dnd-moved">
  13. <th v-for="(column, c) in Columns" :key="c">
  14. <div @click="sortBy(column)">{{ column }}</div>
  15. </th>
  16. <th v-if="editable"></th>
  17. <th v-if="deleteable"></th>
  18. </tr>
  19. </thead>
  20. <tbody>
  21. <tr
  22. v-for="(item, i) in DisplayItems"
  23. :key="i"
  24. class="text-left dnd-moved"
  25. @click="onRowClick(item)"
  26. >
  27. <td
  28. v-for="(column, c) in Columns"
  29. :key="c"
  30. >{{ isObject(item[column]) ? item[column].display : item[column] }}</td>
  31. <td v-if="editable" class="my-width">
  32. <button type="button" class="btn my-btn" @click="onEdit(item)">Edit</button>
  33. </td>
  34. <td v-if="deleteable" class="my-width">
  35. <button type="button" class="btn my-btn" @click="onDelete(item)">Delete</button>
  36. </td>
  37. </tr>
  38. </tbody>
  39. </table>
  40. <div class="d-flex justify-content-between">
  41. <div class="p-1">{{ currentPage + ' / ' + PageCount }}</div>
  42. <div class="p-1">
  43. <BasePagination
  44. :currentPage="currentPage"
  45. :pageCount="PageCount"
  46. @nextPage="pageChangeHandle('next')"
  47. @previousPage="pageChangeHandle('previous')"
  48. @loadPage="pageChangeHandle"
  49. />
  50. </div>
  51. <div class="p-2">
  52. <div class="d-flex flex-row">
  53. <div>
  54. <select
  55. class="form-control"
  56. v-model="visibleItemsPerPageCount"
  57. @change="onChangeItemsPerPage()"
  58. >
  59. <option v-for="(item, i) in itemsPerPageList" :key="i">{{ item }}</option>
  60. </select>
  61. </div>
  62. </div>
  63. </div>
  64. </div>
  65. </div>
  66. </template>
  67. <script>
  68. import _ from 'lodash';
  69. import ItemsPerPageList from '../../assets/staticData/itemsPerPage';
  70. import BasePagination from './basePagination.vue';
  71. export default {
  72. components: {
  73. BasePagination,
  74. },
  75. mounted() {
  76. try {
  77. // to assign initial value to itemsPerPage
  78. if (this.itemsPerPageList && this.itemsPerPageList.length > 0) {
  79. const [startItem] = this.itemsPerPageList;
  80. this.visibleItemsPerPageCount = startItem;
  81. }
  82. } catch (error) {
  83. throw error;
  84. }
  85. },
  86. props: {
  87. hideSearch: {
  88. default: false,
  89. },
  90. items: undefined,
  91. editable: {
  92. default: false,
  93. },
  94. deleteable: {
  95. default: false,
  96. },
  97. columnsCount: {
  98. default: 6,
  99. },
  100. },
  101. data() {
  102. return {
  103. showControl: false,
  104. sortKey: '',
  105. reverse: false,
  106. searchItem: '',
  107. itemsPerPageList: ItemsPerPageList,
  108. visibleItemsPerPageCount: 0,
  109. currentPage: 1,
  110. };
  111. },
  112. methods: {
  113. isObject(item) {
  114. return !!item && item.constructor === Object;
  115. },
  116. onEdit(item) {
  117. this.$emit('onEdit', item);
  118. },
  119. onDelete(item) {
  120. this.$emit('onDelete', item);
  121. },
  122. onRowClick(item) {
  123. this.$emit('onRowClick', item);
  124. },
  125. changeColumn(title, checked) {
  126. if (checked) {
  127. this.myColumns.push(title);
  128. } else {
  129. const ind = this.myColumns.indexOf(title);
  130. if (ind > -1) {
  131. this.myColumns.splice(ind, 1);
  132. }
  133. }
  134. },
  135. onControlVisibilityChange() {
  136. this.showControl = !this.showControl;
  137. },
  138. sortBy(sortKey) {
  139. this.reverse = this.sortKey === sortKey ? !this.reverse : false;
  140. this.sortKey = sortKey;
  141. },
  142. async pageChangeHandle(value) {
  143. console.log(value);
  144. switch (value) {
  145. case 'next':
  146. this.currentPage += 1;
  147. break;
  148. case 'previous':
  149. this.currentPage -= 1;
  150. break;
  151. default:
  152. this.currentPage = value;
  153. }
  154. },
  155. onChangeItemsPerPage() {
  156. if (this.currentPage !== 1) {
  157. this.currentPage = 1;
  158. }
  159. },
  160. },
  161. computed: {
  162. ListWidth() {
  163. if (this.showControl) {
  164. return 'col-md-9';
  165. }
  166. return 'col-md-12';
  167. },
  168. SortDirection() {
  169. return this.reverse ? 'desc' : 'asc';
  170. },
  171. PageCount() {
  172. return this.visibleItemsPerPageCount !== 0
  173. ? Math.ceil(this.FilteredItems.length / this.visibleItemsPerPageCount)
  174. : 1;
  175. },
  176. Columns() {
  177. const list = [];
  178. if (this.items) {
  179. for (const i in Object.keys(this.items)) {
  180. const item = this.items[i];
  181. for (const o in Object.keys(item)) {
  182. if (
  183. !list.includes(Object.keys(item)[o])
  184. && !Array.isArray(Object.values(item)[o])
  185. ) {
  186. if (list.length < this.columnsCount) {
  187. list.push(Object.keys(item)[o]);
  188. }
  189. }
  190. }
  191. }
  192. }
  193. return list;
  194. },
  195. FilteredItems() {
  196. const list = _.filter(this.items, item => Object.values(item).some(
  197. i => JSON.stringify(i)
  198. .toLowerCase()
  199. .indexOf(this.searchItem.toLowerCase()) > -1,
  200. ),);
  201. return _.orderBy(list, this.sortKey, this.SortDirection);
  202. },
  203. DisplayItems() {
  204. const list = this.FilteredItems;
  205. const startSlice = (this.currentPage - 1) * this.visibleItemsPerPageCount;
  206. let endSlice = this.currentPage * this.visibleItemsPerPageCount;
  207. if (endSlice > list.length) {
  208. endSlice = list.length;
  209. }
  210. return list.slice(startSlice, endSlice);
  211. },
  212. },
  213. };
  214. </script>
  215. <style scoped>
  216. th[draggable] a,
  217. th[draggable] {
  218. cursor: move;
  219. }
  220. th[draggable] a:hover,
  221. th[draggable] a {
  222. display: block;
  223. text-decoration: none;
  224. color: #333333;
  225. }
  226. .table > tbody > tr > td {
  227. vertical-align: middle;
  228. }
  229. .my-width {
  230. width: 20px;
  231. }
  232. .drag {
  233. background-color: rgba(0, 255, 0, 0.35);
  234. opacity: 0.25;
  235. }
  236. .dnd-drag {
  237. opacity: 0.25;
  238. }
  239. .over {
  240. background-color: rgba(0, 0, 255, 0.35);
  241. }
  242. </style>