build a table filter by providing editor fields
This commit is contained in:
@@ -1,6 +1,20 @@
|
||||
<template>
|
||||
<div class="ui-daterangepicker" :class="{'is-disabled': disabled }">
|
||||
<button type="button" class="ui-link" @click="schedule" v-localize="scheduleLocalize" :disabled="disabled"></button>
|
||||
<button v-if="!inline" type="button" class="ui-link" @click="schedule" v-localize="scheduleLocalize" :disabled="disabled"></button>
|
||||
<div v-if="inline" class="ui-daterangepicker-inline">
|
||||
<div class="ui-split">
|
||||
<div class="ui-daterangepicker-group">
|
||||
<ui-property :label="fromText" :vertical="true">
|
||||
<ui-datepicker v-model="value.from" :time="time" />
|
||||
</ui-property>
|
||||
</div>
|
||||
<div class="ui-daterangepicker-group">
|
||||
<ui-property :label="toText" :vertical="true">
|
||||
<ui-datepicker v-model="value.to" :time="time" />
|
||||
</ui-property>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -60,6 +74,10 @@
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
inline: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => { }
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<ui-form class="ui-table-filter-overlay" ref="form" v-slot="form" @submit="onSubmit" @load="onLoad">
|
||||
<ui-overlay-editor class="ui-module-overlay">
|
||||
|
||||
<template v-slot:header>
|
||||
<ui-header-bar :title="config.title" :back-button="false" :close-button="true" />
|
||||
</template>
|
||||
|
||||
<template v-slot:footer>
|
||||
<ui-button type="light onbg" label="@ui.close" @click="config.hide"></ui-button>
|
||||
<ui-button type="primary" :submit="true" label="@ui.confirm" :state="form.state" :disabled="loading || disabled"></ui-button>
|
||||
</template>
|
||||
|
||||
<ui-loading v-if="loading" :is-big="true" />
|
||||
|
||||
<!--<div v-if="!loading" class="ui-box">
|
||||
<ui-property label="Name" :required="true">
|
||||
<input v-model="model.name" type="text" class="ui-input" maxlength="300" />
|
||||
</ui-property>
|
||||
</div>-->
|
||||
|
||||
<div v-if="!loading" class="ui-box">
|
||||
<div v-for="(group, index) in groups" class="ui-table-filter-overlay-group" :class="{ 'is-open': activeGroup === index, 'has-value': typeof group.hasValue === 'function' ? group.hasValue(model[group.field]) : null }">
|
||||
<div class="ui-table-filter-overlay-group-head">
|
||||
<ui-select-button :label="group.label" :icon="group.icon" :description="typeof group.preview === 'function' ? group.preview(model[group.field]) : null" @click="toggleGroup(group, index)" />
|
||||
<ui-button class="ui-table-filter-overlay-group-clear" type="blank" label="Clear" @click="clearGroup(group, index)" />
|
||||
</div>
|
||||
<div v-show="activeGroup === index" class="ui-table-filter-overlay-group-content">
|
||||
<editor-component :config="group" v-model="model" @input="onFieldChange" :disabled="disabled" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</ui-overlay-editor>
|
||||
</ui-form>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import EditorComponent from 'zero/editor/editor-component';
|
||||
import { find as _find } from 'deps/underscore';
|
||||
|
||||
export default {
|
||||
|
||||
props: {
|
||||
config: Object
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
loading: false,
|
||||
disabled: false,
|
||||
defaults: {},
|
||||
model: {},
|
||||
activeGroup: null,
|
||||
groups: []
|
||||
}),
|
||||
|
||||
components: { EditorComponent },
|
||||
|
||||
methods: {
|
||||
|
||||
toggleGroup(group, index)
|
||||
{
|
||||
this.activeGroup = this.activeGroup === index ? null : index;
|
||||
},
|
||||
|
||||
onFieldChange(value)
|
||||
{
|
||||
//this.$emit('input', this.value);
|
||||
},
|
||||
|
||||
clearGroup(group, index)
|
||||
{
|
||||
this.model[group.field] = JSON.parse(JSON.stringify(this.defaults[group.field]));
|
||||
},
|
||||
|
||||
onLoad()
|
||||
{
|
||||
this.groups = this.config.fields;
|
||||
this.model = JSON.parse(JSON.stringify(this.config.model || {}));
|
||||
this.defaults = JSON.parse(JSON.stringify(this.config.defaults || {}));
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
onSubmit()
|
||||
{
|
||||
this.config.confirm(this.model);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.ui-table-filter-overlay
|
||||
{
|
||||
.ui-box + .ui-box
|
||||
{
|
||||
margin-top: var(--padding-s);
|
||||
}
|
||||
}
|
||||
|
||||
.ui-table-filter-overlay-group
|
||||
{
|
||||
&:not(.is-open) + .ui-table-filter-overlay-group
|
||||
{
|
||||
margin-top: var(--padding-s);
|
||||
border-top: 1px solid var(--color-line);
|
||||
padding-top: var(--padding-s);
|
||||
}
|
||||
|
||||
&:not(.has-value) .ui-table-filter-overlay-group-clear
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-table-filter-overlay-group-head
|
||||
{
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
grid-gap: 20px;
|
||||
}
|
||||
|
||||
.ui-table-filter-overlay-group-clear .ui-button-text
|
||||
{
|
||||
font-weight: 400;
|
||||
color: var(--color-text-dim);
|
||||
}
|
||||
|
||||
.ui-table-filter-overlay-group-content
|
||||
{
|
||||
background: var(--color-box);
|
||||
margin: var(--padding-s) -32px;
|
||||
padding: var(--padding-m) var(--padding);
|
||||
border-top: 1px solid var(--color-line);
|
||||
border-bottom: 1px solid var(--color-line);
|
||||
|
||||
> .ui-property > .ui-property-label
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,16 @@
|
||||
<template>
|
||||
<div class="ui-table-filter">
|
||||
<ui-search v-if="!hideSearch" v-model="value.search" class="onbg" />
|
||||
<ui-button v-if="!hideFilter" type="light onbg" label="Filter" caret="down" />
|
||||
<ui-dropdown v-if="!hideFilter && filters.length" align="right">
|
||||
<template v-slot:button>
|
||||
<ui-button v-if="!hideFilter" type="light onbg" label="Filter" caret="down" />
|
||||
</template>
|
||||
<ui-dropdown-button label="@ui.add" icon="fth-plus" @click="onFilterAdd" />
|
||||
<ui-dropdown-button label="Clear filter" icon="fth-x" @click="onFilterClear" />
|
||||
<ui-dropdown-separator v-if="filters.length" />
|
||||
<ui-dropdown-button v-if="filters.length" v-for="(filter, index) in filters" :key="index" :value="filter" :label="filter.label" :icon="filter.icon" @click="onFiltered" />
|
||||
</ui-dropdown>
|
||||
<ui-button v-if="!hideFilter && !filters.length" type="light onbg" label="Filter" @click="onFilterAdd" />
|
||||
<ui-dropdown v-if="!hideSelection && selection.length > 0" align="right">
|
||||
<template v-slot:button>
|
||||
<ui-button type="light" :label="selectedText" caret="down" />
|
||||
@@ -19,6 +28,10 @@
|
||||
|
||||
|
||||
<script>
|
||||
import Overlay from 'zero/services/overlay';
|
||||
import FilterOverlay from './table-filter-overlay';
|
||||
import { isArray as _isArray } from 'underscore';
|
||||
|
||||
export default {
|
||||
name: 'uiTableFilter',
|
||||
|
||||
@@ -52,7 +65,8 @@
|
||||
data: () => ({
|
||||
hideFilter: true,
|
||||
hideSearch: true,
|
||||
hideSelection: true
|
||||
hideSelection: true,
|
||||
filters: []
|
||||
}),
|
||||
|
||||
created()
|
||||
@@ -71,7 +85,7 @@
|
||||
|
||||
reload()
|
||||
{
|
||||
this.hideFilter = typeof this.value.filter === 'undefined';
|
||||
this.hideFilter = typeof this.value.filter !== 'object';
|
||||
this.hideSearch = typeof this.value.search === false;
|
||||
this.hideSelection = this.value.selectable !== true;
|
||||
},
|
||||
@@ -79,6 +93,37 @@
|
||||
onActionClicked(action, opts)
|
||||
{
|
||||
action.action(opts);
|
||||
},
|
||||
|
||||
|
||||
onFilterAdd()
|
||||
{
|
||||
this.openFilter();
|
||||
},
|
||||
|
||||
onFilterClear()
|
||||
{
|
||||
|
||||
},
|
||||
|
||||
onFiltered()
|
||||
{
|
||||
|
||||
},
|
||||
|
||||
openFilter()
|
||||
{
|
||||
return Overlay.open({
|
||||
component: FilterOverlay,
|
||||
display: 'editor',
|
||||
title: 'Filter',
|
||||
defaults: this.value.filter.model,
|
||||
model: this.value.filter.model,
|
||||
fields: this.value.filter.fields
|
||||
}).then(value =>
|
||||
{
|
||||
console.info(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,11 +30,17 @@
|
||||
},
|
||||
renderer: {
|
||||
type: Object,
|
||||
required: true
|
||||
default: () =>
|
||||
{
|
||||
return {};
|
||||
}
|
||||
},
|
||||
meta: {
|
||||
type: Object,
|
||||
default: () => { }
|
||||
default: () =>
|
||||
{
|
||||
return {};
|
||||
}
|
||||
},
|
||||
depth: {
|
||||
type: Number,
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div class="ui-box">
|
||||
<ui-daterangepicker :value="value" @input="$emit('input', $event.target.value)" :disabled="disabled"
|
||||
:format="config.format"
|
||||
:time="config.time || false"
|
||||
:max ="config.max" :min="config.min"
|
||||
:from-text="config.fromText || '@ui.date.range_from'"
|
||||
:to-text="config.toText || '@ui.date.range_to'"
|
||||
:amPm="config.amPm || false"
|
||||
:inline="config.inline || false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
default: {
|
||||
from: null,
|
||||
to: null
|
||||
}
|
||||
},
|
||||
config: Object,
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -57,7 +57,9 @@
|
||||
"free": "Free",
|
||||
"xtoy": "from {x} to {y}",
|
||||
"x": "from {x}",
|
||||
"y": "to {y}"
|
||||
"y": "to {y}",
|
||||
"range_from": "Price from",
|
||||
"range_to": "Price to"
|
||||
},
|
||||
"sort": {
|
||||
"title": "Sort",
|
||||
|
||||
Reference in New Issue
Block a user