123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554 |
- /* eslint-disable no-restricted-syntax */ /* eslint-disable guard-for-in */
- <template>
- <div>
- <div style="height:5px"></div>
- <div class="d-flex justify-content-between">
- <div class="p-2" v-if="!hideSearch">
- <float-label label="SEARCH">
- <input v-model="searchItem" class="form-control uniInput mt-3" placeholder="Search..." />
- </float-label>
- </div>
- <div class="p-2" v-if="title">
- <h2>{{ title }}</h2>
- </div>
- <div class="p-2">
- <div class="d-flex flex-row">
- <div class="p2" v-if="showColumnChooser">
- <div
- class="btn-solid-blue cursor-pointer"
- data-toggle="modal"
- data-target="#myModal"
- >Column Chooser</div>
- <div class="col-md-12">
- <div id="myModal" class="modal fade" role="dialog">
- <div class="modal-dialog modal-lg" style="width:500px">
- <!-- Modal content-->
- <div class="modal-content">
- <div class="modal-header">
- <h5>Column Chooser</h5>
- <button type="button" class="close" data-dismiss="modal">×</button>
- </div>
- <div style="margin-bottom:50px;">
- <ListViewControl :items="allColumn" @checkItem="checkItem" />
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="p2" v-if="selectedItems.length > 0">
- <div class="btn-solid-blue cursor-pointer" @click="onClearSelected()">Clear Selected</div>
- </div>
- <div class="p2" v-if="showNew">
- <div class="btn-solid-blue cursor-pointer" @click="onNew()">New</div>
- </div>
- </div>
- </div>
- </div>
- <div style="height:5px"></div>
- <div v-if="items && items.length > 0" class="table-responsive">
- <table
- id="table"
- class="table table-striped"
- :class="{ 'table table-hover': 1 === 1, 'table-sm': compact, 'table-bordered': bordered }"
- >
- <thead>
- <tr class="dnd-moved">
- <th v-for="(column, c) in Columns" :key="c">
- <div
- @click="sortBy(column)"
- @mouseover="hover = c"
- @mouseleave="hover = -1"
- :class="{ active: hover === c }"
- >
- <div class="d-flex bd-highlight">
- <div
- v-if="displayHeaders.length === 0"
- class="p-2 w-100 bd-highlight"
- >{{ column | toProper }}</div>
- <div
- v-else
- class="p-2 w-100 bd-highlight"
- >{{ displayHeaders[c] !== "" ? displayHeaders[c] : column | toProper }}</div>
- <div class="p-2 flex-shrink-1 bd-highlight">
- <img
- src="../../../public/img/sort-up.png"
- height="8px;"
- v-if="sortKey === column && reverse"
- />
- <img
- src="../../../public/img/sort-down.png"
- height="8px;"
- v-if="sortKey === column && !reverse"
- />
- </div>
- </div>
- </div>
- </th>
- <th v-if="showCustomAction"></th>
- <th v-if="editable"></th>
- <th v-if="deleteable"></th>
- </tr>
- </thead>
- <tbody class="table">
- <tr
- v-for="(item, i) in DisplayItems"
- :key="i"
- @click="onRowClick(item, i)"
- :class="{ selected: isSelected(i), 'cursor-pointer': allowSelect }"
- >
- <td v-for="(column, c) in Columns" :key="c">
- <div
- v-if="displayFormats.length === 0"
- >{{ isObject(item[column]) ? item[column].display : item[column] }}</div>
- <div v-else-if="displayFormats.length > 0 && displayFormats[c] === 'date'">
- <div
- v-if="item[column] !== '0001-01-01T00:00:00'"
- >{{ isObject(item[column]) ? item[column].display : item[column] | toDate }}</div>
- </div>
- <div
- v-else-if="displayFormats.length > 0 && displayFormats[c] === 'money'"
- >{{ isObject(item[column]) ? item[column].display : item[column] | toCurrency }}</div>
- <div v-else-if="displayFormats.length > 0 && displayFormats[c] === 'image'">
- <img :src="item[column]" style="height:100px; width:100px; object-fit: cover;" />
- </div>
- <div v-else>{{ isObject(item[column]) ? item[column].display : item[column] }}</div>
- </td>
- <td v-if="showCustomAction" class="my-width">
- <button
- type="button"
- class="btn my-btn"
- @click="onCustomClick(item)"
- >{{ CustomActionHeading }}</button>
- </td>
- <td v-if="editable" class="my-width">
- <a @click="onEdit(item)" class="p-3">
- <img src="../../../public/img/icons/Edit.png" height="25" width="25" />
- </a>
- <!-- <button type="button" class="btn my-btn" @click="onEdit(item)">Edit</button> -->
- </td>
- <td v-if="deleteable" class="my-width">
- <a @click="onDelete(item)" class="p-3">
- <img src="../../../public/img/icons/delete.png" height="25" width="25" />
- </a>
- <!-- <button type="button" class="btn my-btn" @click="onDelete(item)">Delete</button> -->
- </td>
- </tr>
- </tbody>
- </table>
- <div class="d-flex justify-content-between" v-if="showPager">
- <div class="p-1">
- {{
- currentPage +
- " / " +
- PageCount +
- (!hideItemCount ? " - (" + FilteredItems.length + " items)" : "")
- }}
- </div>
- <div class="p-1">
- <BasePagination
- :currentPage="currentPage"
- :pageCount="PageCount"
- @nextPage="pageChangeHandle('next')"
- @previousPage="pageChangeHandle('previous')"
- @loadPage="pageChangeHandle"
- />
- </div>
- <div class="p-2">
- <div class="d-flex flex-row">
- <div>
- <select
- class="form-control"
- v-model="visibleItemsPerPageCount"
- @change="onChangeItemsPerPage()"
- >
- <option v-for="(item, i) in itemsPerPageList" :key="i">{{ item }}</option>
- </select>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div v-else>
- <Alert :text="'No items found ^-^'" :type="'INFO'" />
- </div>
- </div>
- </template>
-
- <script>
- /* eslint-disable */
- import _ from "lodash";
- import ItemsPerPageList from "../../assets/staticData/itemsPerPage";
- import BasePagination from "./basePagination.vue";
- import Alert from "./alert.vue";
- import ListViewControl from "./listViewControl.vue";
-
- export default {
- components: {
- BasePagination,
- Alert,
- ListViewControl,
- },
- mounted() {
- try {
- // to assign initial value to itemsPerPage
- if (this.itemsPerPageList && this.itemsPerPageList.length > 0) {
- const [startItem] = this.itemsPerPageList;
- this.visibleItemsPerPageCount = startItem;
- }
- } catch (error) {
- throw error;
- }
- this.getInitColumn();
- },
- props: {
- compact: {
- default: true,
- },
- allowSelect: {
- default: true,
- },
- allowMultipleSelect: {
- default: false,
- },
- hideSearch: {
- default: false,
- },
- showNew: {
- default: true,
- },
- items: undefined,
- editable: {
- default: false,
- },
- deleteable: {
- default: false,
- },
- columnCount: {
- default: 6,
- },
- showPager: {
- default: true,
- },
- title: {
- default: undefined,
- },
- sortKey: {
- default: "id",
- },
- hideItemCount: {
- default: false,
- },
- currentPage: {
- default: 1,
- },
- bordered: {
- default: true,
- },
- striped: {
- default: true,
- },
- showColumnChooser: {
- default: true,
- },
- displayColumns: {
- type: Array,
- default: () => [],
- },
- displayFormats: {
- type: Array,
- default: () => [],
- },
- displayHeaders: {
- type: Array,
- default: () => [],
- },
- showCustomAction: {
- default: false,
- },
- CustomActionHeading: {
- default: "",
- },
- CustomActionCondition: {
- default: "",
- },
- },
- data() {
- return {
- hover: -1,
- selectedItems: [],
- showControl: false,
- sortKey: "",
- reverse: false,
- searchItem: "",
- visibleItemsPerPageCount: 20,
- itemsPerPageList: ItemsPerPageList,
- visibleColumn: [],
- allColumn: [],
- };
- },
- methods: {
- checkItem(column, show) {
- const list = [];
- for (const i in this.allColumn) {
- const item = this.allColumn[i];
- if (item && item.column === column) {
- item.show = show;
- }
- list.push(item);
- }
- this.allColumn = list;
- },
- getInitColumn() {
- const list = [];
- const listAll = [];
- if (this.items) {
- for (const i in Object.keys(this.items)) {
- const item = this.items[i];
- for (const o in Object.keys(item)) {
- if (
- !listAll.includes(Object.keys(item)[o]) &&
- !Array.isArray(Object.values(item)[o])
- ) {
- const columnName = Object.keys(item)[o];
- if (!listAll.some((x) => x.column === columnName)) {
- listAll.push({
- column: columnName,
- show:
- _.filter(listAll, (x) => x.show).length < this.columnCount,
- });
- }
- }
- }
- }
- }
- this.allColumn = listAll;
- },
- onClearSelected() {
- this.selectedItems = [];
- this.$emit("onClearSelected");
- },
- isSelected(i) {
- const ind = this.getActualIndex(i);
- return _.some(this.selectedItems, (x) => x === ind);
- },
- onNew() {
- this.$emit("onNew");
- },
- isObject(item) {
- return !!item && item.constructor === Object;
- },
- isDate(item) {
- return !!item && item.constructor === Date;
- },
- isDecimal(item) {
- if (!!item && item.constructor === Number && item.indexOf(".") > 0) {
- return true;
- }
- return false;
- },
- isImage(item) {
- return (
- !!item &&
- item.constructor === String &&
- item.length > 9 &&
- item.substring(0, 9) === "data:image"
- );
- },
- onEdit(item) {
- this.$emit("onEdit", item);
- },
- onDelete(item) {
- this.$emit("onDelete", item);
- },
- onCustomClick(item) {
- this.$emit("onCustomClick", item);
- },
- onRowClick(item, i) {
- const ind = this.getActualIndex(i);
- if (_.some(this.selectedItems, (x) => x === ind)) {
- this.selectedItems = this.selectedItems.filter((x) => x !== ind);
- } else {
- if (!this.allowMultipleSelect) {
- this.selectedItems = [];
- }
- this.selectedItems.push(item);
- }
- this.$emit("onRowClick", this.selectedItems);
- },
- getActualIndex(index) {
- return (this.currentPage - 1) * this.visibleItemsPerPageCount + index;
- },
- changeColumn(title, checked) {
- if (checked) {
- this.myColumns.push(title);
- } else {
- const ind = this.myColumns.indexOf(title);
- if (ind > -1) {
- this.myColumns.splice(ind, 1);
- }
- }
- },
- onControlVisibilityChange() {
- this.showControl = !this.showControl;
- },
- sortBy(sortKey) {
- this.reverse = this.sortKey === sortKey ? !this.reverse : false;
- this.sortKey = sortKey;
- },
- async pageChangeHandle(value) {
- console.log(value);
- switch (value) {
- case "next":
- this.currentPage += 1;
- break;
- case "previous":
- this.currentPage -= 1;
- break;
- default:
- this.currentPage = value;
- }
- },
- onChangeItemsPerPage() {
- if (this.currentPage !== 1) {
- this.currentPage = 1;
- }
- },
- inArray(array, value) {
- const lenght = array.length;
- for (let i = 0; i < lenght; i++) {
- if (array[i] === value) return true;
- }
- return false;
- },
- },
- computed: {
- ListWidth() {
- if (this.showControl) {
- return "col-md-9";
- }
- return "col-md-12";
- },
- SortDirection() {
- return this.reverse ? "desc" : "asc";
- },
- PageCount() {
- return this.visibleItemsPerPageCount !== 0
- ? Math.ceil(this.FilteredItems.length / this.visibleItemsPerPageCount)
- : 1;
- },
- Columns() {
- const listColumns = [];
- if (!this.allColumn || this.allColumn.length === 0) {
- this.getInitColumn();
- }
- if (this.displayColumns.length > 0) {
- for (let i = 0; i < this.displayColumns.length; i++) {
- listColumns.push(this.displayColumns[i]);
- }
- } else {
- const list = _.filter(this.allColumn, (x) => x.show);
- for (const i in list) {
- const item = list[i];
- if (item) {
- listColumns.push(item.column);
- }
- }
- }
- return listColumns;
- },
- AllColumns() {
- const list = [];
- if (this.items) {
- }
- return list;
- },
- FilteredItems() {
- const list = _.filter(this.items, (item) =>
- Object.values(item).some(
- (i) =>
- JSON.stringify(i)
- .toLowerCase()
- .indexOf(this.searchItem.toLowerCase()) > -1
- )
- );
- return _.orderBy(list, this.sortKey, this.SortDirection);
- },
- DisplayItems() {
- const list = this.FilteredItems;
- const startSlice = (this.currentPage - 1) * this.visibleItemsPerPageCount;
- let endSlice = this.currentPage * this.visibleItemsPerPageCount;
- if (endSlice > list.length) {
- endSlice = list.length;
- }
- return list.slice(startSlice, endSlice);
- },
-
- GetAllColumn() {},
- },
- };
- </script>
- <style scoped>
- th[draggable] a,
- th[draggable] {
- cursor: move;
- }
- th[draggable] a:hover,
- th[draggable] a {
- display: block;
- text-decoration: none;
- color: #333333;
- }
- .table-striped > tbody > tr:nth-child(2n + 1) > td,
- .table-striped > tbody > tr:nth-child(2n + 1) > th {
- background-color: rgba(225, 225, 225, 0.8);
- }
- .active {
- background-color: rgba(255, 255, 255, 0.5);
- cursor: pointer;
- }
- .table > tbody > tr > td {
- vertical-align: middle;
- }
- .my-width {
- width: 20px;
- }
- .drag {
- background-color: rgba(0, 255, 0, 0.35);
- opacity: 0.25;
- }
- .dnd-drag {
- opacity: 0.25;
- }
- .over {
- background-color: rgba(0, 0, 255, 0.35);
- }
- .my-border {
- border: solid 3px silver;
- }
- .selected {
- background-color: rgba(96, 203, 235, 0.5);
- border: white 2px double;
- }
- .selected:hover {
- background-color: rgba(96, 203, 235, 0.85);
- }
- .btn-width {
- width: 125px;
- }
- .table-title {
- padding: 5px;
- border: rgba(200, 200, 200, 0.66) double 2px;
- border-radius: 5px;
- background-color: rgba(96, 203, 235, 0.25);
- }
- .table-title:hover {
- background-color: rgba(96, 203, 235, 0.4);
- }
- .table-header {
- background-color: rgba(200, 200, 200, 0.66);
- }
- .my-table {
- border: rgba(150, 150, 150, 0.75) 3px double;
- }
- </style>
|