diff --git a/internal/routerConfig/routes.go b/internal/routerConfig/routes.go index 218384e0..e24038e2 100644 --- a/internal/routerConfig/routes.go +++ b/internal/routerConfig/routes.go @@ -405,10 +405,22 @@ func buildFilterPresets(query url.Values) map[string]any { if query.Get("energy") != "" { parts := strings.Split(query.Get("energy"), "-") if len(parts) == 2 { - a, e1 := strconv.Atoi(parts[0]) - b, e2 := strconv.Atoi(parts[1]) - if e1 == nil && e2 == nil { - filterPresets["energy"] = map[string]int{"from": a, "to": b} + if parts[0] == "lessthan" { + lt, lte := strconv.Atoi(parts[1]) + if lte == nil { + filterPresets["energy"] = map[string]int{"from": 1, "to": lt} + } + } else if parts[0] == "morethan" { + mt, mte := strconv.Atoi(parts[1]) + if mte == nil { + filterPresets["energy"] = map[string]int{"from": mt, "to": 0} + } + } else { + a, e1 := strconv.Atoi(parts[0]) + b, e2 := strconv.Atoi(parts[1]) + if e1 == nil && e2 == nil { + filterPresets["energy"] = map[string]int{"from": a, "to": b} + } } } } @@ -417,15 +429,37 @@ func buildFilterPresets(query url.Values) map[string]any { for _, statEntry := range query["stat"] { parts := strings.Split(statEntry, "-") if len(parts) == 3 { // Metric Footprint Stat Field, from - to - a, e1 := strconv.ParseInt(parts[1], 10, 64) - b, e2 := strconv.ParseInt(parts[2], 10, 64) - if e1 == nil && e2 == nil { - statEntry := map[string]any{ - "field": parts[0], - "from": a, - "to": b, + if parts[1] == "lessthan" { + lt, lte := strconv.ParseInt(parts[2], 10, 64) + if lte == nil { + statEntry := map[string]any{ + "field": parts[0], + "from": 1, + "to": lt, + } + statList = append(statList, statEntry) + } + } else if parts[1] == "morethan" { + mt, mte := strconv.ParseInt(parts[2], 10, 64) + if mte == nil { + statEntry := map[string]any{ + "field": parts[0], + "from": mt, + "to": 0, + } + statList = append(statList, statEntry) + } + } else { + a, e1 := strconv.ParseInt(parts[1], 10, 64) + b, e2 := strconv.ParseInt(parts[2], 10, 64) + if e1 == nil && e2 == nil { + statEntry := map[string]any{ + "field": parts[0], + "from": a, + "to": b, + } + statList = append(statList, statEntry) } - statList = append(statList, statEntry) } } } diff --git a/web/frontend/src/generic/Filters.svelte b/web/frontend/src/generic/Filters.svelte index 162082c0..02f801a0 100644 --- a/web/frontend/src/generic/Filters.svelte +++ b/web/frontend/src/generic/Filters.svelte @@ -206,7 +206,7 @@ items.push({ duration: { to: filters.duration.lessThan, from: 0 } }); if (filters.duration.moreThan) items.push({ duration: { to: 0, from: filters.duration.moreThan } }); - if (filters.energy.from || filters.energy.to) + if (filters.energy.from != null || filters.energy.to != null) items.push({ energy: { from: filters.energy.from, to: filters.energy.to }, }); @@ -301,11 +301,20 @@ if (filters.node) opts.push(`node=${filters.node}`); if (filters.node && filters.nodeMatch != "eq") // "eq" is default-case opts.push(`nodeMatch=${filters.nodeMatch}`); - if (filters.energy.from && filters.energy.to) + if (filters.energy.from > 1 && filters.energy.to > 0) opts.push(`energy=${filters.energy.from}-${filters.energy.to}`); - if (filters.stats.length != 0) + else if (filters.energy.from > 1 && filters.energy.to == 0) + opts.push(`energy=morethan-${filters.energy.from}`); + else if (filters.energy.from == 1 && filters.energy.to > 0) + opts.push(`energy=lessthan-${filters.energy.to}`); + if (filters.stats.length > 0) for (let stat of filters.stats) { + if (stat.from > 1 && stat.to > 0) opts.push(`stat=${stat.field}-${stat.from}-${stat.to}`); + else if (stat.from > 1 && stat.to == 0) + opts.push(`stat=${stat.field}-morethan-${stat.from}`); + else if (stat.from == 1 && stat.to > 0) + opts.push(`stat=${stat.field}-lessthan-${stat.to}`); } // Build && Return if (opts.length == 0 && window.location.search.length <= 1) return; @@ -550,18 +559,36 @@ {/if} - {#if filters.energy.from || filters.energy.to} + {#if filters.energy.from > 1 && filters.energy.to > 0} (isEnergyOpen = true)}> - Total Energy: {filters.energy.from} - {filters.energy.to} + Total Energy: {filters.energy.from} - {filters.energy.to} kWh + + {:else if filters.energy.from > 1 && filters.energy.to == 0} + (isEnergyOpen = true)}> + Total Energy ≥ {filters.energy.from} kWh + + {:else if filters.energy.from == 1 && filters.energy.to > 0} + (isEnergyOpen = true)}> + Total Energy ≤ {filters.energy.to} kWh {/if} {#if filters.stats.length > 0} - (isStatsOpen = true)}> - {filters.stats - .map((stat) => `${stat.field}: ${stat.from} - ${stat.to}`) - .join(", ")} - + {#each filters.stats as stat} + {#if stat.from > 1 && stat.to > 0} + (isStatsOpen = true)}> + {stat.field}: {stat.from} - {stat.to} {stat.unit} +   + {:else if stat.from > 1 && stat.to == 0} + (isStatsOpen = true)}> + {stat.field} ≥ {stat.from} {stat.unit} +   + {:else if stat.from == 1 && stat.to > 0} + (isStatsOpen = true)}> + {stat.field} ≤ {stat.to} {stat.unit} +   + {/if} + {/each} {/if} {/if} diff --git a/web/frontend/src/generic/filters/Energy.svelte b/web/frontend/src/generic/filters/Energy.svelte index 4d542add..648fdb4d 100644 --- a/web/frontend/src/generic/filters/Energy.svelte +++ b/web/frontend/src/generic/filters/Energy.svelte @@ -15,54 +15,90 @@ ModalBody, ModalHeader, ModalFooter, + Tooltip, + Icon } from "@sveltestrap/sveltestrap"; import DoubleRangeSlider from "../select/DoubleRangeSlider.svelte"; /* Svelte 5 Props */ let { isOpen = $bindable(false), - presetEnergy = { - from: null, - to: null - }, + presetEnergy = { from: null, to: null }, setFilter, } = $props(); + /* Const */ + const minEnergyPreset = 1; + const maxEnergyPreset = 1000; + /* Derived */ - let energyState = $derived(presetEnergy); + // Pending + let pendingEnergyState = $derived({ + from: presetEnergy?.from ? presetEnergy.from : minEnergyPreset, + to: !(presetEnergy.to == null || presetEnergy.to == 0) ? presetEnergy.to : maxEnergyPreset, + }); + // Changable + let energyState = $derived({ + from: presetEnergy?.from ? presetEnergy.from : minEnergyPreset, + to: !(presetEnergy.to == null || presetEnergy.to == 0) ? presetEnergy.to : maxEnergyPreset, + }); + + const energyActive = $derived(!(JSON.stringify(energyState) === JSON.stringify({ from: minEnergyPreset, to: maxEnergyPreset }))); + // Block Apply if null + const disableApply = $derived(energyState.from === null || energyState.to === null); + + /* Function */ + function setEnergy() { + if (energyActive) { + pendingEnergyState = { + from: energyState.from, + to: (energyState.to == maxEnergyPreset) ? 0 : energyState.to + }; + } else { + pendingEnergyState = { from: null, to: null}; + }; + } (isOpen = !isOpen)}> Filter based on energy
-
Total Job Energy (kWh)
+
+ Total Job Energy (kWh) + +
+ + Generalized Presets. Use input fields to change to higher values. + { energyState.from = detail[0]; energyState.to = detail[1]; }} - sliderMin={0.0} - sliderMax={1000.0} - fromPreset={energyState?.from? energyState.from : 0.0} - toPreset={energyState?.to? energyState.to : 1000.0} + sliderMin={minEnergyPreset} + sliderMax={maxEnergyPreset} + fromPreset={energyState.from} + toPreset={energyState.to} />
diff --git a/web/frontend/src/generic/filters/InfoBox.svelte b/web/frontend/src/generic/filters/InfoBox.svelte index 0c249980..35af4635 100644 --- a/web/frontend/src/generic/filters/InfoBox.svelte +++ b/web/frontend/src/generic/filters/InfoBox.svelte @@ -20,7 +20,7 @@ } = $props(); - diff --git a/web/frontend/src/generic/select/DoubleRangeSlider.svelte b/web/frontend/src/generic/select/DoubleRangeSlider.svelte index c655087f..958db598 100644 --- a/web/frontend/src/generic/select/DoubleRangeSlider.svelte +++ b/web/frontend/src/generic/select/DoubleRangeSlider.svelte @@ -165,11 +165,11 @@ }} /> - {#if inputFieldFrom != "1" && inputFieldTo != sliderMax?.toString() } + {#if inputFieldFrom != sliderMin?.toString() && inputFieldTo != sliderMax?.toString() } Selected: Range {inputFieldFrom} - {inputFieldTo} - {:else if inputFieldFrom != "1" && inputFieldTo == sliderMax?.toString() } + {:else if inputFieldFrom != sliderMin?.toString() && inputFieldTo == sliderMax?.toString() } Selected: More than {inputFieldFrom} - {:else if inputFieldFrom == "1" && inputFieldTo != sliderMax?.toString() } + {:else if inputFieldFrom == sliderMin?.toString() && inputFieldTo != sliderMax?.toString() } Selected: Less than {inputFieldTo} {:else} No Selection diff --git a/web/frontend/src/generic/utils.js b/web/frontend/src/generic/utils.js index 09239ec8..82da21b8 100644 --- a/web/frontend/src/generic/utils.js +++ b/web/frontend/src/generic/utils.js @@ -341,26 +341,28 @@ export function getStatsItems(presetStats = []) { if (gm?.footprint) { const mc = getMetricConfigDeep(gm.name, null, null) if (mc) { - const presetEntry = presetStats.find((s) => s?.field === (gm.name + '_' + gm.footprint)) + const presetEntry = presetStats.find((s) => s.field == `${gm.name}_${gm.footprint}`) if (presetEntry) { return { - field: gm.name + '_' + gm.footprint, - text: gm.name + ' (' + gm.footprint + ')', + field: presetEntry.field, + text: `${gm.name} (${gm.footprint})`, metric: gm.name, from: presetEntry.from, - to: presetEntry.to, + to: (presetEntry.to == 0) ? mc.peak : presetEntry.to, peak: mc.peak, - enabled: true + enabled: true, + unit: `${gm?.unit?.prefix ? gm.unit.prefix : ''}${gm.unit.base}` } } else { return { - field: gm.name + '_' + gm.footprint, - text: gm.name + ' (' + gm.footprint + ')', + field: `${gm.name}_${gm.footprint}`, + text: `${gm.name} (${gm.footprint})`, metric: gm.name, - from: 0, + from: 1, to: mc.peak, peak: mc.peak, - enabled: false + enabled: false, + unit: `${gm?.unit?.prefix ? gm.unit.prefix : ''}${gm.unit.base}` } } }