mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-19 16:02:15 +00:00
- filter aus dem defaultfilter entfernt
- tagfilter hinzugefuegt - clear filter hinzugefuegt - persistence default auf false gesetzt
This commit is contained in:
@@ -582,7 +582,16 @@ var FHC_TableWidget = {
|
||||
|
||||
options.columns = arrayTabulatorColumns;
|
||||
options.data = data.dataset;
|
||||
options.persistence = (typeof options.persistence == 'undefined') ? true : options.persistence; // enables persistence (default store in localStorage if available, else in cookie)
|
||||
|
||||
let defaultPersistence = {
|
||||
sort: true,
|
||||
columns: true,
|
||||
filter: false,
|
||||
headerFilter: false,
|
||||
group: false,
|
||||
page: false,
|
||||
}
|
||||
options.persistence = (typeof options.persistence == 'undefined') ? defaultPersistence : options.persistence; // enables persistence (default store in localStorage if available, else in cookie)
|
||||
options.persistenceID = (typeof options.persistenceID == 'undefined') ? data.tableUniqueId : options.persistenceID; // persistenceID to store persistence data seperately for multiple tables
|
||||
options.movableColumns = (typeof options.movableColumns == 'undefined') ? true : options.movableColumns; // allows changing column order
|
||||
options.tooltipsHeader = (typeof options.tooltipsHeader == 'undefined') ? true : options.tooltipsHeader; // set header tooltip with column title
|
||||
|
||||
@@ -20,7 +20,6 @@ import FilterConfig from './Filter/Config.js';
|
||||
import FilterColumns from './Filter/Columns.js';
|
||||
import TableDownload from './Table/Download.js';
|
||||
import collapseAutoClose from '../../directives/collapseAutoClose.js';
|
||||
import { defaultHeaderFilter } from '../../tabulator/filters/defaultHeaderFilter.js';
|
||||
|
||||
//
|
||||
const FILTER_COMPONENT_NEW_FILTER = 'Filter Component New Filter';
|
||||
@@ -81,6 +80,7 @@ export const CoreFilterCmpt = {
|
||||
uuid: 0,
|
||||
// FilterCmpt properties
|
||||
filterName: null,
|
||||
filterActive: false,
|
||||
fields: null,
|
||||
dataset: null,
|
||||
datasetMetadata: null,
|
||||
@@ -100,7 +100,15 @@ export const CoreFilterCmpt = {
|
||||
tabulator: null,
|
||||
tableBuilt: false,
|
||||
tabulatorHasSelector: false,
|
||||
selectedData: []
|
||||
selectedData: [],
|
||||
persistence: {
|
||||
sort: true,
|
||||
columns: true,
|
||||
filter: false,
|
||||
headerFilter: false,
|
||||
group: false,
|
||||
page: false,
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -207,12 +215,11 @@ export const CoreFilterCmpt = {
|
||||
layout: "fitDataStretch",
|
||||
movableColumns: true,
|
||||
columnDefaults:{
|
||||
tooltip: true,
|
||||
headerFilterFunc: defaultHeaderFilter,
|
||||
tooltip: true
|
||||
},
|
||||
placeholder,
|
||||
reactiveData: true,
|
||||
persistence: true
|
||||
persistence: this.persistence,
|
||||
}, ...(this.tabulatorOptions || {})};
|
||||
|
||||
if (!this.tableOnly) {
|
||||
@@ -278,11 +285,15 @@ export const CoreFilterCmpt = {
|
||||
const cols = this.tabulator.getColumns();
|
||||
this.fields = cols.map(col => col.getField());
|
||||
this.selectedFields = cols.filter(col => col.isVisible()).map(col => col.getField());
|
||||
|
||||
if (this.tabulator.options.persistence.headerFilter)
|
||||
this._setHeaderFilter();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
this.tabulator.on("dataFiltered", filters => {
|
||||
this.filterActive = filters.length > 0;
|
||||
});
|
||||
},
|
||||
updateTabulator() {
|
||||
if (this.tabulator) {
|
||||
@@ -296,6 +307,23 @@ export const CoreFilterCmpt = {
|
||||
this.tabulatorHasSelector = this.tabulatorOptions.selectable || this.filteredColumns.filter(el => el.formatter == 'rowSelection').length;
|
||||
this.tabulator.setColumns(this.filteredColumns);
|
||||
this.tabulator.setData(this.filteredData);
|
||||
this._setHeaderFilter()
|
||||
},
|
||||
clearFilters()
|
||||
{
|
||||
let existingFilters = this.tabulator.getHeaderFilters();
|
||||
existingFilters.forEach(filter => {
|
||||
this.tabulator.setHeaderFilterValue(filter.field, "");
|
||||
});
|
||||
this.tabulator.clearFilter();
|
||||
this.filterActive = false;
|
||||
},
|
||||
_setHeaderFilter()
|
||||
{
|
||||
const existingFilters = this.tabulator.getHeaderFilters();
|
||||
existingFilters.forEach(filter => {
|
||||
this.tabulator.setHeaderFilterValue(filter.field, filter.value);
|
||||
});
|
||||
},
|
||||
/**
|
||||
*
|
||||
@@ -578,16 +606,21 @@ export const CoreFilterCmpt = {
|
||||
alert('"nwNewEntry" listener is mandatory when sideMenu is true');
|
||||
this.uuid = _uuid++;
|
||||
this.$emit('uuidDefined', this.uuid)
|
||||
if (!this.tableOnly)
|
||||
this.getFilter(); // get the filter data
|
||||
},
|
||||
mounted() {
|
||||
this.initTabulator();
|
||||
|
||||
this.initTabulator().then(() => {
|
||||
if (!this.tableOnly) {
|
||||
this.selectedFilter = window.location.hash ? window.location.hash.slice(1) : null;
|
||||
this.getFilter(); // get the filter data
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
template: `
|
||||
<!-- Load filter data -->
|
||||
<core-fetch-cmpt
|
||||
v-if="!tableOnly"
|
||||
v-if="!tableOnly && fetchCmptApiFunction"
|
||||
v-bind:api-function="fetchCmptApiFunction"
|
||||
v-bind:api-function-parameters="fetchCmptApiFunctionParams"
|
||||
v-bind:refresh="fetchCmptRefresh"
|
||||
@@ -625,6 +658,9 @@ export const CoreFilterCmpt = {
|
||||
<a v-if="!tableOnly || $slots.filter" href="#" class="btn btn-link px-0 text-dark" data-bs-toggle="collapse" :data-bs-target="'#collapseFilters' + idExtra">
|
||||
<span class="fa-solid fa-xl fa-filter"></span>
|
||||
</a>
|
||||
<a v-if="filterActive" class="btn btn-link px-0 text-dark" :title="$p.t('ui','filterdelete')" @click="clearFilters">
|
||||
<span class="fa-solid fa-xl fa-filter-circle-xmark"></span>
|
||||
</a>
|
||||
<a href="#" class="btn btn-link px-0 text-dark" data-bs-toggle="collapse" :data-bs-target="'#collapseColumns' + idExtra">
|
||||
<span class="fa-solid fa-xl fa-table-columns"></span>
|
||||
</a>
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
function parseFilterExpression(expression){
|
||||
const includeGroups = [];
|
||||
const excludeTerms = [];
|
||||
const comparisons = [];
|
||||
|
||||
const andParts = expression.split('&&').map(part => part.trim());
|
||||
|
||||
andParts.forEach(part => {
|
||||
const orTerms = part.split('||').map(p => p.trim());
|
||||
const orRegexes = [];
|
||||
|
||||
orTerms.forEach(term => {
|
||||
|
||||
const comparisonMatch = term.match(/^(<=|>=|<|>|=|!=)\s*(\d+)$/);
|
||||
|
||||
if (comparisonMatch)
|
||||
{
|
||||
const operator = comparisonMatch[1];
|
||||
const number = parseFloat(comparisonMatch[2]);
|
||||
|
||||
comparisons.push({ operator, number });
|
||||
}
|
||||
else if (term.startsWith('!'))
|
||||
{
|
||||
const excludeTerm = term.substring(1).trim().replace(/\*/g, '.*');
|
||||
excludeTerms.push(new RegExp(excludeTerm, 'i'));
|
||||
}
|
||||
else
|
||||
{
|
||||
const includeTerm = term.replace(/\*/g, '.*');
|
||||
orRegexes.push(new RegExp(includeTerm, 'i'));
|
||||
}
|
||||
});
|
||||
|
||||
if (orRegexes.length > 0)
|
||||
{
|
||||
includeGroups.push(orRegexes);
|
||||
}
|
||||
});
|
||||
|
||||
return { includeGroups, excludeTerms, comparisons };
|
||||
}
|
||||
|
||||
export function defaultHeaderFilter(headerValue, rowValue)
|
||||
{
|
||||
const { includeGroups, excludeTerms, comparisons } = parseFilterExpression(headerValue);
|
||||
|
||||
const includes = includeGroups.every(group =>
|
||||
group.some(regex => regex.test(rowValue))
|
||||
);
|
||||
|
||||
const excludes = excludeTerms.every(regex => !regex.test(rowValue));
|
||||
|
||||
const comparisonCheck = comparisons.every(({ operator, number }) => {
|
||||
let value = rowValue;
|
||||
|
||||
if (!isNaN(number))
|
||||
{
|
||||
value = parseFloat(rowValue);
|
||||
if (isNaN(value)) return false;
|
||||
}
|
||||
|
||||
switch (operator) {
|
||||
case '<':
|
||||
return value < number;
|
||||
case '>':
|
||||
return value > number;
|
||||
case '<=':
|
||||
return value <= number;
|
||||
case '>=':
|
||||
return value >= number;
|
||||
case '=':
|
||||
return value === number;
|
||||
case '!=':
|
||||
return value !== number;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return includes && excludes && comparisonCheck;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
function parseFilterExpression(expression)
|
||||
{
|
||||
const collections = [];
|
||||
|
||||
try {
|
||||
const orParts = expression.split('||').map(part => part.trim());
|
||||
|
||||
orParts.forEach(part => {
|
||||
|
||||
const andParts = part.split('&&').map(p => p.trim());
|
||||
|
||||
const collection = { positives: [], negatives: [] };
|
||||
|
||||
andParts.forEach(term => {
|
||||
|
||||
const comparisonMatch = term.match(/^(<=|>=|<|>|=|!=)\s*(\d+(?:[.,]\d+)?)$/);
|
||||
|
||||
if (comparisonMatch)
|
||||
{
|
||||
const operator = comparisonMatch[1];
|
||||
const numberStr = comparisonMatch[2].replace(',', '.');
|
||||
const number = parseFloat(numberStr);
|
||||
collection.positives.push({ type: 'comparison', operator, number });
|
||||
}
|
||||
else if (term.startsWith('!'))
|
||||
{
|
||||
const excludeTerm = term.substring(1).trim().replace(/\*/g, '.*');
|
||||
collection.negatives.push({ type: 'regex', regex: new RegExp(excludeTerm, 'i') });
|
||||
}
|
||||
else
|
||||
{
|
||||
const includeTerm = term.replace(/\*/g, '.*');
|
||||
collection.positives.push({ type: 'regex', regex: new RegExp(includeTerm, 'i') });
|
||||
}
|
||||
});
|
||||
collections.push(collection);
|
||||
});
|
||||
} catch (e) {}
|
||||
return collections;
|
||||
}
|
||||
|
||||
export function extendedHeaderFilter(headerValue, rowValue)
|
||||
{
|
||||
if (typeof headerValue === 'boolean')
|
||||
{
|
||||
return rowValue === headerValue;
|
||||
}
|
||||
|
||||
const collections = parseFilterExpression(headerValue);
|
||||
|
||||
try {
|
||||
|
||||
return collections.some(collection => {
|
||||
|
||||
let positives = collection.positives.length === 0 || collection.positives.every(condition => {
|
||||
|
||||
if (condition.type === 'comparison')
|
||||
{
|
||||
let value = parseFloat(rowValue);
|
||||
if (isNaN(value)) return false;
|
||||
|
||||
switch (condition.operator) {
|
||||
case '<':
|
||||
return value < condition.number;
|
||||
case '>':
|
||||
return value > condition.number;
|
||||
case '<=':
|
||||
return value <= condition.number;
|
||||
case '>=':
|
||||
return value >= condition.number;
|
||||
case '=':
|
||||
return value === condition.number;
|
||||
case '!=':
|
||||
return value !== condition.number;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (condition.type === 'regex')
|
||||
{
|
||||
return condition.regex.test(rowValue);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
let negatives = collection.negatives.every(condition => {
|
||||
return !condition.regex.test(rowValue);
|
||||
});
|
||||
|
||||
return positives && negatives;
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
export function tagHeaderFilter(headerValue, rowValue) {
|
||||
|
||||
let data;
|
||||
|
||||
try {
|
||||
data = typeof rowValue === 'string' ? JSON.parse(rowValue) : rowValue;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let combinedText;
|
||||
|
||||
if (Array.isArray(data))
|
||||
{
|
||||
combinedText = data
|
||||
.map(item => `${item.beschreibung} ${item.notiz}`)
|
||||
.join(' ');
|
||||
}
|
||||
else if (typeof data === 'object' && data !== null)
|
||||
{
|
||||
combinedText = `${data.beschreibung} ${data.notiz}`;
|
||||
}
|
||||
else
|
||||
{
|
||||
combinedText = String(data);
|
||||
}
|
||||
|
||||
return extendedHeaderFilter(headerValue, combinedText)
|
||||
}
|
||||
|
||||
@@ -1775,6 +1775,26 @@ $phrases = array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'filterdelete',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Filter löschen',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Clear filter',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'anrechnung',
|
||||
|
||||
Reference in New Issue
Block a user