Datagrid Breaked

This commit is contained in:
Devansh 2022-04-04 15:23:53 +05:30
parent 07ded4cd3e
commit 4bde5ca931
15 changed files with 1005 additions and 866 deletions

View File

@ -106,6 +106,15 @@ class OrderDataGrid extends DataGrid
'index' => 'status',
'label' => trans('admin::app.datagrid.status'),
'type' => 'string',
'options' => [
'processing' => trans('shop::app.customer.account.order.index.processing'),
'completed' => trans('shop::app.customer.account.order.index.completed'),
'canceled' => trans('shop::app.customer.account.order.index.canceled'),
'closed' => trans('shop::app.customer.account.order.index.closed'),
'pending' => trans('shop::app.customer.account.order.index.pending'),
'pending_payment' => trans('shop::app.customer.account.order.index.pending-payment'),
'fraud' => trans('shop::app.customer.account.order.index.fraud'),
],
'sortable' => true,
'searchable' => true,
'filterable' => true,

View File

@ -77,13 +77,13 @@ class OrderDataGrid extends DataGrid
'label' => trans('shop::app.customer.account.order.index.status'),
'type' => 'string',
'options' => [
'processing' => 'Processing',
'completed' => 'Completed',
'canceled' => 'Cancelled',
'closed' => 'Closed',
'pending' => 'Pending',
'pending_payment' => 'Pending Payment',
'fraud' => 'Fraud',
'processing' => trans('shop::app.customer.account.order.index.processing'),
'completed' => trans('shop::app.customer.account.order.index.completed'),
'canceled' => trans('shop::app.customer.account.order.index.canceled'),
'closed' => trans('shop::app.customer.account.order.index.closed'),
'pending' => trans('shop::app.customer.account.order.index.pending'),
'pending_payment' => trans('shop::app.customer.account.order.index.pending-payment'),
'fraud' => trans('shop::app.customer.account.order.index.fraud'),
],
'searchable' => false,
'sortable' => true,

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{
"/js/ui.js": "/js/ui.js?id=2d5e481fb67990d5d925",
"/js/ui.js": "/js/ui.js?id=6abdc1fc415a79d9293d",
"/css/ui.css": "/css/ui.css?id=c8a7ade09358a1d61a4a"
}

View File

@ -0,0 +1,39 @@
<template>
<span class="filter-tag" style="text-transform: capitalize">
<span v-if="filter.column == 'perPage'">perPage</span>
<span v-else>{{ filter.label }}</span>
<span class="wrapper" v-if="filter.prettyValue">
{{ filter.prettyValue }}
<span
class="icon cross-icon"
v-on:click="removeFilter(filter)"
></span>
</span>
<span class="wrapper" v-else>
{{ decodeURIComponent(filter.val) }}
<span
class="icon cross-icon"
v-on:click="removeFilter(filter)"
></span>
</span>
</span>
</template>
<script>
export default {
props: ['filter'],
data() {
return {};
},
methods: {
removeFilter() {
this.$emit('onRemoveFilter');
}
}
};
</script>

View File

@ -0,0 +1,48 @@
<template>
<div
class="pagination shop mt-50"
v-if="
typeof paginated !== 'undefined' &&
paginated &&
records.last_page > 1
"
>
<a
v-for="(link, index) in records.links"
:key="index"
href="javascript:void(0);"
:data-page="link.url"
:class="
`page-item ${index == 0 ? 'previous' : ''} ${
link.active ? 'active' : ''
} ${index == records.links.length - 1 ? 'next' : ''}`
"
@click="changePage(link.url)"
>
<i class="icon angle-left-icon" v-if="index == 0"></i>
<i
class="icon angle-right-icon"
v-else-if="index == records.links.length - 1"
></i>
<span v-text="link.label" v-else></span>
</a>
</div>
</template>
<script>
export default {
props: ['paginated', 'records'],
data() {
return {};
},
methods: {
changePage(pageLink) {
this.$emit('onChangePage', { data: { pageLink } });
}
}
};
</script>

View File

@ -1,38 +0,0 @@
<template>
<Flatpickr class="datetime-field" :options="fpOptions" />
</template>
<script>
window.Vue = require("vue");
import VueFlatpickr from "vue-flatpickr";
import "vue-flatpickr/theme/airbnb.css";
Vue.use(VueFlatpickr);
export default {
data() {
const now = new Date();
return {
fpOptions: {
utc: false,
defaultDate: now,
enableTime: true
}
};
},
mounted: function() {
console.log("Date time compoenent mounted");
}
};
</script>
<style>
.datetime-field {
border: 2px solid #c7c7c7;
border-radius: 3px;
font-family: "Montserrat", sans-serif;
height: 35px;
padding-left: 5px;
color: gray;
}
</style>

View File

@ -0,0 +1,37 @@
<template>
<div class="control-group">
<select class="control" name="channel" @change="changeChannel($event)">
<option
value="all"
:selected="extraFilters.current.channel == 'all'"
v-text="translations.allChannels"
></option>
<option
:key="channelKey"
v-for="(channel, channelKey) in extraFilters.channels"
v-text="channel.name"
:value="channel.code"
:selected="channel.code == extraFilters.current.channel"
></option>
</select>
</div>
</template>
<script>
export default {
props: ['translations', 'extraFilters'],
data() {
return {};
},
methods: {
changeChannel({ target }) {
this.$emit('onFilter', {
data: { type: 'channel', value: target.value }
});
}
}
};
</script>

View File

@ -0,0 +1,457 @@
<template>
<div>
<div class="dropdown-toggle">
<div class="grid-dropdown-header">
<span class="name" v-text="translations.filter"></span>
<i class="icon arrow-down-icon active"></i>
</div>
</div>
<div class="dropdown-list dropdown-container" style="display: none">
<ul>
<li>
<div class="control-group">
<select
class="filter-column-select control"
v-model="filterColumn"
v-on:change="getColumnOrAlias(filterColumn)"
>
<option
v-text="translations.column"
selected
disabled
></option>
<option
:key="columnKey"
v-for="(column, columnKey) in columns"
:value="column.index"
v-text="column.label"
v-if="
typeof column.filterable !== 'undefined' &&
column.filterable
"
></option>
</select>
</div>
</li>
<li v-if="stringConditionSelect">
<div class="control-group">
<select class="control" v-model="stringCondition">
<option
v-text="translations.condition"
selected
disabled
></option>
<option
v-text="translations.contains"
value="like"
></option>
<option
v-text="translations.ncontains"
value="nlike"
></option>
<option
v-text="translations.equals"
value="eq"
></option>
<option
v-text="translations.nequals"
value="neqs"
></option>
</select>
</div>
</li>
<li v-if="stringCondition != null">
<div
class="control-group"
v-if="isCurrentFilterColumnHasOptions()"
>
<select class="control" v-model="stringValue">
<option
:key="key"
v-text="option"
v-value="key"
v-for="(option,
key) in this.getCurrentFilterOptions()"
></option>
</select>
</div>
<div class="control-group" v-else>
<input
type="text"
class="control response-string"
:placeholder="translations.valueHere"
v-model="stringValue"
/>
</div>
</li>
<li v-if="numberConditionSelect">
<div class="control-group">
<select class="control" v-model="numberCondition">
<option
v-text="translations.condition"
selected
disabled
></option>
<option
v-text="translations.equals"
value="eq"
></option>
<option
v-text="translations.nequals"
value="neqs"
></option>
<option
v-text="translations.greater"
value="gt"
></option>
<option
v-text="translations.less"
value="lt"
></option>
<option
v-text="translations.greatere"
value="gte"
></option>
<option
v-text="translations.lesse"
value="lte"
></option>
</select>
</div>
</li>
<li v-if="numberCondition != null">
<div class="control-group">
<input
type="text"
class="control response-number"
v-on:input="filterNumberInput"
v-model="numberValue"
:placeholder="translations.numericValueHere"
/>
</div>
</li>
<li v-if="booleanConditionSelect">
<div class="control-group">
<select class="control" v-model="booleanCondition">
<option
v-text="translations.condition"
selected
disabled
></option>
<option
v-text="translations.equals"
value="eq"
></option>
<option
v-text="translations.nequals"
value="neqs"
></option>
</select>
</div>
</li>
<li v-if="booleanCondition != null">
<div class="control-group">
<select class="control" v-model="booleanValue">
<option
v-text="translations.value"
selected
disabled
></option>
<option
v-text="translations.true"
value="1"
></option>
<option
v-text="translations.false"
value="0"
></option>
</select>
</div>
</li>
<li v-if="datetimeConditionSelect">
<div class="control-group">
<select class="control" v-model="datetimeCondition">
<option
v-text="translations.condition"
selected
disabled
></option>
<option
v-text="translations.equals"
value="eq"
></option>
<option
v-text="translations.nequals"
value="neqs"
></option>
<option
v-text="translations.greater"
value="gt"
></option>
<option
v-text="translations.less"
value="lt"
></option>
<option
v-text="translations.greatere"
value="gte"
></option>
<option
v-text="translations.lesse"
value="lte"
></option>
</select>
</div>
</li>
<li v-if="datetimeCondition != null">
<div class="control-group">
<input
class="control"
v-model="datetimeValue"
type="date"
/>
</div>
</li>
<button
v-text="translations.apply"
class="btn btn-sm btn-primary apply-filter"
v-on:click="getResponse"
></button>
</ul>
</div>
</div>
</template>
<script>
export default {
props: ['columns', 'translations'],
data() {
/**
* To Do (@devansh-webkul):
*
* - Try to minimize these data props also.
* - Refactor all repeative properties.
*/
return {
type: null,
columnOrAlias: '',
stringConditionSelect: false,
numberConditionSelect: false,
booleanConditionSelect: false,
datetimeConditionSelect: false,
stringCondition: null,
numberCondition: null,
booleanCondition: null,
datetimeCondition: null,
stringValue: null,
numberValue: 0,
booleanValue: null,
datetimeValue: '2000-01-01'
};
},
methods: {
filterNumberInput: function(e) {
this.numberValue = e.target.value.replace(/[^0-9\,\.]+/g, '');
},
getCurrentFilterColumn() {
return this.columns.find(
column => column.index === this.filterColumn
);
},
isCurrentFilterColumnHasOptions() {
let currentFilterColumn = this.getCurrentFilterColumn();
return (
currentFilterColumn && currentFilterColumn.options !== undefined
);
},
getCurrentFilterOptions() {
if (this.isCurrentFilterColumnHasOptions()) {
return this.getCurrentFilterColumn().options ?? [];
}
throw "Options are not defined. Don't use this method if options are not available.";
},
getColumnOrAlias(columnOrAlias) {
this.columnOrAlias = columnOrAlias;
for (let column in this.columns) {
if (this.columns[column].index === this.columnOrAlias) {
this.type = this.columns[column].type;
switch (this.type) {
case 'string': {
this.stringConditionSelect = true;
this.numberConditionSelect = false;
this.booleanConditionSelect = false;
this.datetimeConditionSelect = false;
this.nullify();
break;
}
case 'datetime': {
this.stringConditionSelect = false;
this.numberConditionSelect = false;
this.booleanConditionSelect = false;
this.datetimeConditionSelect = true;
this.nullify();
break;
}
case 'boolean': {
this.stringConditionSelect = false;
this.numberConditionSelect = false;
this.booleanConditionSelect = true;
this.datetimeConditionSelect = false;
this.nullify();
break;
}
case 'number': {
this.stringConditionSelect = false;
this.numberConditionSelect = true;
this.booleanConditionSelect = false;
this.datetimeConditionSelect = false;
this.nullify();
break;
}
case 'price': {
this.stringConditionSelect = false;
this.numberConditionSelect = true;
this.booleanConditionSelect = false;
this.datetimeConditionSelect = false;
this.nullify();
break;
}
}
}
}
},
getResponse: function() {
let label = '';
for (let colIndex in this.columns) {
if (this.columns[colIndex].index == this.columnOrAlias) {
label = this.columns[colIndex].label;
break;
}
}
if (this.type === 'string' && this.stringValue !== null) {
this.$emit('onFilter', {
data: {
column: this.columnOrAlias,
condition: this.stringCondition,
response: encodeURIComponent(this.stringValue),
label
}
});
} else if (this.type === 'number') {
let indexConditions = true;
if (
this.filterIndex === this.columnOrAlias &&
(this.numberValue === 0 || this.numberValue < 0)
) {
indexConditions = false;
alert(this.translations.zeroIndex);
}
if (indexConditions) {
this.$emit('onFilter', {
data: {
column: this.columnOrAlias,
condition: this.numberCondition,
response: this.numberValue,
label
}
});
}
} else if (this.type === 'boolean') {
this.$emit('onFilter', {
data: {
column: this.columnOrAlias,
condition: this.booleanCondition,
response: this.booleanValue,
label
}
});
} else if (this.type === 'datetime') {
this.$emit('onFilter', {
data: {
column: this.columnOrAlias,
condition: this.datetimeCondition,
response: this.datetimeValue,
label
}
});
} else if (this.type === 'price') {
this.$emit('onFilter', {
data: {
column: this.columnOrAlias,
condition: this.numberCondition,
response: this.numberValue,
label
}
});
}
},
nullify() {
this.stringCondition = null;
this.datetimeCondition = null;
this.booleanCondition = null;
this.numberCondition = null;
}
}
};
</script>

View File

@ -0,0 +1,45 @@
<template>
<div class="control-group">
<select
class="control"
id="customer-group-switcher"
name="customer_group"
@change="changeCustomerGroup($event)"
>
<option
value="all"
:selected="extraFilters.current.customer_group == 'all'"
v-text="translations.allCustomerGroups"
></option>
<option
:key="customerGroupKey"
v-for="(customerGroup,
customerGroupKey) in extraFilters.customer_groups"
v-text="customerGroup.name"
:value="customerGroup.id"
:selected="
customerGroup.id == extraFilters.current.customer_group
"
></option>
</select>
</div>
</template>
<script>
export default {
props: ['extraFilters', 'translations'],
data() {
return {};
},
methods: {
changeCustomerGroup({ target }) {
this.$emit('onFilter', {
data: { type: 'customer_group', value: target.value }
});
}
}
};
</script>

View File

@ -0,0 +1,37 @@
<template>
<div class="control-group">
<select class="control" name="locale" @change="changeLocale($event)">
<option
value="all"
:selected="extraFilters.current.locale == 'all'"
v-text="translations.allLocales"
></option>
<option
:key="localeKey"
v-for="(locale, localeKey) in extraFilters.locales"
v-text="locale.name"
:value="locale.code"
:selected="locale.code == extraFilters.current.locale"
></option>
</select>
</div>
</template>
<script>
export default {
props: ['extraFilters', 'translations'],
data() {
return {};
},
methods: {
changeLocale({ target }) {
this.$emit('onFilter', {
data: { type: 'locale', value: target.value }
});
}
}
};
</script>

View File

@ -0,0 +1,44 @@
<template>
<div class="control-group">
<label
class="per-page-label"
for="perPage"
v-text="translations.itemsPerPage"
></label>
<select
id="perPage"
class="control"
name="perPage"
v-model="currentSelection"
v-on:change="paginate"
>
<option
v-for="index in this.perPageCount"
v-text="index"
:key="index"
:value="index"
></option>
</select>
</div>
</template>
<script>
export default {
props: ['perPage', 'perPageCount', 'translations'],
data() {
return {
currentSelection: this.perPage
};
},
methods: {
paginate() {
this.$emit('onFilter', {
data: { perPage: this.currentSelection }
});
}
}
};
</script>

View File

@ -0,0 +1,37 @@
<template>
<div class="search-filter">
<input
type="search"
id="search-field"
class="control"
:placeholder="translations.search"
v-model="searchValue"
v-on:keyup.enter="search(searchValue)"
/>
<div class="icon-wrapper">
<span
class="icon search-icon search-btn"
v-on:click="search(searchValue)"
></span>
</div>
</div>
</template>
<script>
export default {
props: ['translations'],
data() {
return {
searchValue: ''
};
},
methods: {
search(searchValue) {
this.$emit('onFilter', { data: { searchValue } });
}
}
};
</script>

View File

@ -0,0 +1,99 @@
export default {
methods: {
getDatagridsInfoStorageKey() {
return 'datagridsInfo';
},
analyzeDatagridsInfo() {
if (!this.isDataLoaded && this.url === `${this.src}?v=1`) {
let datagridInfo = this.getCurrentDatagridInfo();
if (datagridInfo) {
/**
* Will check this later. Don't remove it.
*/
// this.filterCurrentDatagridFromDatagridsInfo();
this.url = datagridInfo.previousUrl;
this.filters = datagridInfo.previousFilters;
}
} else {
let datagridsInfo = this.getDatagridsInfo();
if (datagridsInfo && datagridsInfo.length > 0) {
if (this.isCurrentDatagridInfoExists()) {
datagridsInfo = datagridsInfo.map(datagrid => {
if (datagrid.id === this.id) {
return this.getDatagridsInfoDefaults();
}
return datagrid;
});
} else {
datagridsInfo.push(this.getDatagridsInfoDefaults());
}
} else {
datagridsInfo = [this.getDatagridsInfoDefaults()];
}
this.updateDatagridsInfo(datagridsInfo);
}
},
isCurrentDatagridInfoExists() {
let datagridsInfo = this.getDatagridsInfo();
return !!datagridsInfo.find(({ id }) => id === this.id);
},
getCurrentDatagridInfo() {
let datagridsInfo = this.getDatagridsInfo();
return this.isCurrentDatagridInfoExists()
? datagridsInfo.find(({ id }) => id === this.id)
: null;
},
getDatagridsInfoDefaults() {
return {
id: this.id,
previousFilters: this.filters,
previousUrl: this.url
};
},
getDatagridsInfo() {
let storageInfo = localStorage.getItem(
this.getDatagridsInfoStorageKey()
);
return !this.isValidJsonString(storageInfo)
? []
: JSON.parse(storageInfo) ?? [];
},
updateDatagridsInfo(info) {
localStorage.setItem(
this.getDatagridsInfoStorageKey(),
JSON.stringify(info)
);
},
filterCurrentDatagridFromDatagridsInfo() {
let datagridsInfo = this.getDatagridsInfo();
datagridsInfo = datagridsInfo.filter(({ id }) => id !== this.id);
this.updateDatagridsInfo(datagridsInfo);
},
isValidJsonString(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
}
};