Skip to content

Commit

Permalink
refractor and increase filter performance
Browse files Browse the repository at this point in the history
* refactor multiple filtering removing a lot of nested loops
* add a "buffer" (wait some time before filtering that there aren't another filter input) in order to avoid calling too many time the filter and avoir freeze on template
  • Loading branch information
syrk4web committed Jul 12, 2024
1 parent 540ecfd commit f7ced2e
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 33 deletions.
8 changes: 3 additions & 5 deletions src/client/vite/src/components/Forms/Group/Multiple.vue
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,6 @@ const props = defineProps({
});
const multiples = reactive({
// Store props.multiples on multiples.data and then use multiples.data to render increase performance
data: props.multiples,
invisible: [],
toDelete: [],
});
Expand Down Expand Up @@ -245,7 +243,7 @@ function delGroup(group, multName, groupName) {
</script>

<template>
<template :key="multName" v-for="(multObj, multName, id) in multiples.data">
<template :key="multObj" v-for="(multObj, multName, id) in props.multiples">
<Container
data-is="multiple"
class="layout-settings-multiple"
Expand All @@ -262,7 +260,7 @@ function delGroup(group, multName, groupName) {

<template
:key="groupId"
v-for="(group, groupName, groupId) in multiples.data[multName]"
v-for="(group, groupName, groupId) in props.multiples[multName]"
>
<Container
data-group="multiple"
Expand All @@ -279,7 +277,7 @@ function delGroup(group, multName, groupName) {
:subtitle="`${multName.replaceAll('-', ' ')} #${+groupName + 1}`"
/>
<template
:key="settingName"
:key="setting"
v-for="(setting, settingName, settingId) in group"
>
<Fields :setting="setting" />
Expand Down
100 changes: 72 additions & 28 deletions src/client/vite/src/components/Widget/Filter.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup>
import { defineProps, reactive, watch } from "vue";
import { defineProps, onUpdated, reactive, watch } from "vue";
import Container from "@components/Widget/Container.vue";
import Input from "@components/Forms/Field/Input.vue";
Expand Down Expand Up @@ -71,18 +71,19 @@ const emits = defineEmits(["filter"]);
const filters = reactive({
base: JSON.parse(JSON.stringify(props.filters)),
bufferCount: 0,
isFiltering: false,
});
watch(props.data, () => {
filterData();
});
// Case we are changing a filter value
// We only have to check data for this filter
function filterData(filter = {}, value = "") {
function startFilter(filter = {}, value) {
filters.isFiltering = true;
// Case we have new filter value, update it
// Loop on filter.base and update the "value" key when matching filterName
if (filter?.filterName && value) {
if (filter?.filterName && value !== null) {
filters.base.forEach((f) => {
if (f.filterName === filter.filterName) {
f.value = value;
Expand Down Expand Up @@ -133,8 +134,26 @@ function filterData(filter = {}, value = "") {
// Remove empty row
template = template.filter((row) => row.length > 0);
}
console.log("filter");
emits("filter", template);
// Allow filtering again after 100ms
setTimeout(() => {
filters.isFiltering = false;
}, 100);
}
// Case we are changing a filter value
// We only have to check data for this filter
function filterData(filter = {}, value = null) {
// Wait for buffer input
filters.bufferCount++;
const currBufferCount = filters.bufferCount;
// Wait time to check if not another input (count) to filter
setTimeout(() => {
// Case another input, don't filter and wait again
if (currBufferCount < filters.bufferCount) return;
startFilter(filter, value);
}, 50);
}
function filterRegularSettings(filterSettings, template) {
Expand All @@ -156,34 +175,57 @@ function filterRegularSettings(filterSettings, template) {
}
function filterMultiplesSettings(filterSettings, template) {
// Loop on plugins and get multiples settings like this
template.forEach((plugin, id) => {
// loop on plugin settings dict
const filterMultiple = {};
const multiples = plugin?.multiples;
if (!multiples || Object.keys(multiples).length <= 0) return;
for (const [multName, multGroups] of Object.entries(multiples)) {
for (const [groupId, groupSettings] of Object.entries(multGroups)) {
const multiples = [];
// Format to filter
for (let i = 0; i < template.length; i++) {
const plugin = template[i];
if (!plugin?.multiples || Object.keys(plugin.multiples).length <= 0)
continue;
for (const [multName, multGroups] of Object.entries(plugin.multiples)) {
for (const [groupName, groupSettings] of Object.entries(multGroups)) {
// Check if inpid is mathing a groupSettings key
const settings = [];
for (const [key, value] of Object.entries(groupSettings)) {
settings.push({ ...value, setting_name: key });
}
const filterSettingsData = useFilter(settings, filterSettings);
const settingsData = {};
filterSettingsData.forEach((setting) => {
settingsData[setting.setting_name] = setting;
delete settingsData[setting.setting_name]?.setting_name;
});
// Check if at least one setting is matching
if (Object.keys(settingsData).length > 0) {
if (!filterMultiple[multName]) filterMultiple[multName] = {};
filterMultiple[multName][groupId] = settingsData;
multiples.push({
...value,
setting_name: key,
plugin_id: plugin.id,
group_name: groupName,
mult_name: multName,
});
}
}
}
template[id].multiples = filterMultiple;
}
// Remove multiples from template
template.forEach((plugin) => {
delete plugin.multiples;
});
// Add filtered multiples
const filterSettingsData = useFilter(multiples, filterSettings);
for (let i = 0; i < filterSettingsData.length; i++) {
const setting = filterSettingsData[i];
const pluginId = setting?.plugin_id;
const groupName = setting?.group_name;
const multName = setting?.mult_name;
const settingName = setting?.setting_name;
delete setting.plugin_id;
delete setting.group_name;
delete setting.setting_name;
// Find the plugin in template
const pluginIndex = template.findIndex((plugin) => plugin.id === pluginId);
if (pluginIndex < 0) continue;
if (!("multiples" in template[pluginIndex]))
template[pluginIndex]["multiples"] = {};
if (!(multName in template[pluginIndex]["multiples"]))
template[pluginIndex]["multiples"][multName] = {};
if (!(groupName in template[pluginIndex]["multiples"][multName]))
template[pluginIndex]["multiples"][multName][groupName] = {};
template[pluginIndex]["multiples"][multName][groupName][settingName] =
setting;
}
}
</script>
Expand All @@ -194,11 +236,13 @@ function filterMultiplesSettings(filterSettings, template) {
<Input
v-if="filter.type === 'keyword'"
@inp="(v) => filterData(filter, v)"
@change="(v) => filterData(filter, v)"
v-bind="filter.field"
/>
<Select
v-if="filter.type === 'select'"
@inp="(v) => filterData(filter, v)"
@change="(v) => filterData(filter, v)"
v-bind="filter.field"
/>
</template>
Expand Down

0 comments on commit f7ced2e

Please sign in to comment.