build a table filter by providing editor fields

This commit is contained in:
2020-10-08 15:12:46 +02:00
parent 27cf0dfb87
commit 85ffdaacc9
6 changed files with 254 additions and 7 deletions
@@ -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);
});
}
}
}
+8 -2
View File
@@ -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",