+ )}
+ {!this.state.confirmName && !this.state.confirmDelete && (
+
+ {this.state.showMore && (
+
+
+ )}
+
+ {!this.state.showMore && (
+ this.setState({ confirmName: true })}
+ />
+ )}
{(() => {
const currentFilter = this.getCurrentFilterInfo();
const isAppliedSavedFilter = currentFilter.isApplied && this.props.filters.size > 0;
- if (isAppliedSavedFilter) {
+ if (isAppliedSavedFilter && !this.state.showMore) {
return (
this.toggleMore()}
/>
);
- } else {
+ } else if (!this.state.showMore) {
return (
);
}
+ return null;
})()}
diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js
index 2953969b1a..ed4681af1b 100644
--- a/src/dashboard/Data/Browser/Browser.react.js
+++ b/src/dashboard/Data/Browser/Browser.react.js
@@ -227,6 +227,7 @@ class Browser extends DashboardView {
this.getClassRelationColumns = this.getClassRelationColumns.bind(this);
this.showCreateClass = this.showCreateClass.bind(this);
this.refresh = this.refresh.bind(this);
+ this.deleteFilter = this.deleteFilter.bind(this);
this.selectRow = this.selectRow.bind(this);
this.updateRow = this.updateRow.bind(this);
this.updateOrdering = this.updateOrdering.bind(this);
@@ -1281,6 +1282,24 @@ class Browser extends DashboardView {
super.forceUpdate();
}
+ deleteFilter(filterId) {
+ const preferences = ClassPreferences.getPreferences(
+ this.context.applicationId,
+ this.props.params.className
+ );
+
+ if (preferences.filters) {
+ const updatedFilters = preferences.filters.filter(filter => filter.id !== filterId);
+ ClassPreferences.updatePreferences(
+ { ...preferences, filters: updatedFilters },
+ this.context.applicationId,
+ this.props.params.className
+ );
+ }
+
+ super.forceUpdate();
+ }
+
updateOrdering(ordering) {
const source = this.state.relation || this.props.params.className;
this.setState(
@@ -2278,6 +2297,7 @@ class Browser extends DashboardView {
filters={this.state.filters}
onFilterChange={this.updateFilters}
onFilterSave={(...args) => this.saveFilters(...args)}
+ onDeleteFilter={this.deleteFilter}
onRemoveColumn={this.showRemoveColumn}
onDeleteRows={this.showDeleteRows}
onDropClass={this.showDropClass}
diff --git a/src/dashboard/Data/Browser/BrowserToolbar.react.js b/src/dashboard/Data/Browser/BrowserToolbar.react.js
index b28aad55c8..a311ce5188 100644
--- a/src/dashboard/Data/Browser/BrowserToolbar.react.js
+++ b/src/dashboard/Data/Browser/BrowserToolbar.react.js
@@ -32,6 +32,7 @@ const BrowserToolbar = ({
setCurrent,
onFilterChange,
onFilterSave,
+ onDeleteFilter,
onAddColumn,
onAddRow,
onAddRowWithModal,
@@ -401,6 +402,7 @@ const BrowserToolbar = ({
filters={filters}
onChange={onFilterChange}
onSaveFilter={onFilterSave}
+ onDeleteFilter={onDeleteFilter}
className={classNameForEditors}
blacklistedFilters={onAddRow ? [] : ['unique']}
disabled={isPendingEditCloneRows}
From 294ce66586bd6e7eab0ff3ce8320b6a2c569cd15 Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 03:50:56 +0200
Subject: [PATCH 06/23] Update Browser.react.js
---
src/dashboard/Data/Browser/Browser.react.js | 36 ++++++++++++---------
1 file changed, 21 insertions(+), 15 deletions(-)
diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js
index ed4681af1b..b4cc87268e 100644
--- a/src/dashboard/Data/Browser/Browser.react.js
+++ b/src/dashboard/Data/Browser/Browser.react.js
@@ -1263,23 +1263,29 @@ class Browser extends DashboardView {
}
removeFilter(filter) {
- const preferences = ClassPreferences.getPreferences(
- this.context.applicationId,
- this.props.params.className
- );
- let i = preferences.filters.length;
- while (i--) {
- const item = preferences.filters[i];
- if (JSON.stringify(item) === JSON.stringify(filter)) {
- preferences.filters.splice(i, 1);
+ // Use the new deleteFilter method for consistency
+ if (filter && filter.id) {
+ this.deleteFilter(filter.id);
+ } else {
+ // Fallback to old method if no ID is available
+ const preferences = ClassPreferences.getPreferences(
+ this.context.applicationId,
+ this.props.params.className
+ );
+ let i = preferences.filters.length;
+ while (i--) {
+ const item = preferences.filters[i];
+ if (JSON.stringify(item) === JSON.stringify(filter)) {
+ preferences.filters.splice(i, 1);
+ }
}
+ ClassPreferences.updatePreferences(
+ preferences,
+ this.context.applicationId,
+ this.props.params.className
+ );
+ super.forceUpdate();
}
- ClassPreferences.updatePreferences(
- preferences,
- this.context.applicationId,
- this.props.params.className
- );
- super.forceUpdate();
}
deleteFilter(filterId) {
From 2b9267ef3c9f098aaaed225412859bafa3860051 Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 03:55:55 +0200
Subject: [PATCH 07/23] remove X to delete filter
---
.../CategoryList/CategoryList.react.js | 9 ----
src/dashboard/Data/Browser/Browser.react.js | 49 +++++++------------
2 files changed, 18 insertions(+), 40 deletions(-)
diff --git a/src/components/CategoryList/CategoryList.react.js b/src/components/CategoryList/CategoryList.react.js
index b7409030bf..01a01bf9e4 100644
--- a/src/components/CategoryList/CategoryList.react.js
+++ b/src/components/CategoryList/CategoryList.react.js
@@ -168,15 +168,6 @@ export default class CategoryList extends React.Component {
>
{name}
-
{
- e.preventDefault();
- this.props.removeFilter(filterData);
- }}
- >
- ×
-
);
})}
diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js
index b4cc87268e..7494cca870 100644
--- a/src/dashboard/Data/Browser/Browser.react.js
+++ b/src/dashboard/Data/Browser/Browser.react.js
@@ -1262,32 +1262,6 @@ class Browser extends DashboardView {
super.forceUpdate();
}
- removeFilter(filter) {
- // Use the new deleteFilter method for consistency
- if (filter && filter.id) {
- this.deleteFilter(filter.id);
- } else {
- // Fallback to old method if no ID is available
- const preferences = ClassPreferences.getPreferences(
- this.context.applicationId,
- this.props.params.className
- );
- let i = preferences.filters.length;
- while (i--) {
- const item = preferences.filters[i];
- if (JSON.stringify(item) === JSON.stringify(filter)) {
- preferences.filters.splice(i, 1);
- }
- }
- ClassPreferences.updatePreferences(
- preferences,
- this.context.applicationId,
- this.props.params.className
- );
- super.forceUpdate();
- }
- }
-
deleteFilter(filterId) {
const preferences = ClassPreferences.getPreferences(
this.context.applicationId,
@@ -1295,7 +1269,24 @@ class Browser extends DashboardView {
);
if (preferences.filters) {
- const updatedFilters = preferences.filters.filter(filter => filter.id !== filterId);
+ // Try to find by ID first (modern approach)
+ let updatedFilters = preferences.filters.filter(filter => filter.id !== filterId);
+
+ // If no filter was removed (ID not found), use fallback method
+ if (updatedFilters.length === preferences.filters.length && filterId) {
+ // Fallback: try to find by comparing the entire filter object if filterId is actually a filter object
+ if (typeof filterId === 'object') {
+ let i = preferences.filters.length;
+ updatedFilters = [...preferences.filters];
+ while (i--) {
+ const item = updatedFilters[i];
+ if (JSON.stringify(item) === JSON.stringify(filterId)) {
+ updatedFilters.splice(i, 1);
+ }
+ }
+ }
+ }
+
ClassPreferences.updatePreferences(
{ ...preferences, filters: updatedFilters },
this.context.applicationId,
@@ -2121,10 +2112,6 @@ class Browser extends DashboardView {
this.resetPage();
this.props.navigate(generatePath(this.context, url));
}}
- removeFilter={filter => {
- this.resetPage();
- this.removeFilter(filter);
- }}
classClicked={() => {
this.resetPage();
}}
From 02da43772267e10d38b1f6039ec53779cbe61279 Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 04:38:00 +0200
Subject: [PATCH 08/23] arrows
---
.../BrowserFilter/BrowserFilter.react.js | 113 +++++++++++++-----
1 file changed, 81 insertions(+), 32 deletions(-)
diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js
index 84351b69c0..46353c8de7 100644
--- a/src/components/BrowserFilter/BrowserFilter.react.js
+++ b/src/components/BrowserFilter/BrowserFilter.react.js
@@ -52,6 +52,29 @@ export default class BrowserFilter extends React.Component {
}
}
+ isCurrentFilterSaved() {
+ // Check if current filter structure matches any saved filter
+ const preferences = ClassPreferences.getPreferences(
+ this.context.applicationId,
+ this.props.className
+ );
+
+ if (!preferences.filters || this.props.filters.size === 0) {
+ return false;
+ }
+
+ const currentFiltersString = JSON.stringify(this.props.filters.toJS());
+
+ return preferences.filters.some(savedFilter => {
+ try {
+ const savedFiltersString = JSON.stringify(JSON.parse(savedFilter.filter));
+ return savedFiltersString === currentFiltersString;
+ } catch {
+ return false;
+ }
+ });
+ }
+
getCurrentFilterInfo() {
// Extract filterId from URL if present
const urlParams = new URLSearchParams(window.location.search);
@@ -581,12 +604,17 @@ export default class BrowserFilter extends React.Component {
{this.state.showMore && (
- this.toggleMore()}
- />
+ >
+
+
this.save()}
/>
- this.setState({ confirmDelete: true })}
- />
+ {this.isCurrentFilterSaved() && (
+ this.setState({ confirmDelete: true })}
+ />
+ )}
)}
- {!this.state.showMore && (
-
this.setState({ confirmName: true })}
- />
- )}
{(() => {
const currentFilter = this.getCurrentFilterInfo();
const isAppliedSavedFilter = currentFilter.isApplied && this.props.filters.size > 0;
if (isAppliedSavedFilter && !this.state.showMore) {
return (
- this.toggleMore()}
- />
+ <>
+ this.toggleMore()}
+ >
+
+
+ this.clear()}
+ />
+ >
);
} else if (!this.state.showMore) {
return (
- this.clear()}
- />
+ <>
+ this.toggleMore()}
+ >
+
+
+ this.clear()}
+ />
+ >
);
}
return null;
From 2ac80a4202aee193773e38b809bba620a30026fc Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 04:39:58 +0200
Subject: [PATCH 09/23] margin fix
---
src/components/BrowserFilter/BrowserFilter.react.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js
index 46353c8de7..69c4079d34 100644
--- a/src/components/BrowserFilter/BrowserFilter.react.js
+++ b/src/components/BrowserFilter/BrowserFilter.react.js
@@ -603,7 +603,7 @@ export default class BrowserFilter extends React.Component {
{!this.state.confirmName && !this.state.confirmDelete && (
{this.state.showMore && (
-
+
this.toggleMore()}
From 65542302d4c3de257f4cb4dbb7b58da651881f4c Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 04:50:05 +0200
Subject: [PATCH 10/23] remove unused filer fields
---
.../BrowserFilter/BrowserFilter.react.js | 49 +------------------
1 file changed, 1 insertion(+), 48 deletions(-)
diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js
index 69c4079d34..ff7875025c 100644
--- a/src/components/BrowserFilter/BrowserFilter.react.js
+++ b/src/components/BrowserFilter/BrowserFilter.react.js
@@ -34,7 +34,6 @@ export default class BrowserFilter extends React.Component {
open: false,
editMode: true,
filters: new List(),
- confirmName: false,
name: '',
blacklistedFilters: Filters.BLACKLISTED_FILTERS.concat(props.blacklistedFilters),
relativeDates: false,
@@ -299,7 +298,6 @@ export default class BrowserFilter extends React.Component {
open: !prevState.open,
filters: filters,
name: '',
- confirmName: false,
editMode: this.props.filters.size === 0,
relativeDates: false, // Reset relative dates state when opening/closing
showMore: false, // Reset showMore state when opening/closing
@@ -474,33 +472,6 @@ export default class BrowserFilter extends React.Component {
/>
)}
/>
- {this.state.confirmName && (
- <>
- }
- input={
- this.setState({ name })}
- />
- }
- />
- {hasDateState &&
- }
- input={
- this.setState({ relativeDates: checked })}
- className={styles.checkbox}
- />
- }
- />
- }
- >
- )}
-
{this.state.showMore && (
<>
)}
- {this.state.confirmName && (
-
- this.setState({ confirmName: false })}
- />
- this.save()}
- />
-
- )}
{this.state.confirmDelete && (
)}
- {!this.state.confirmName && !this.state.confirmDelete && (
+ {!this.state.confirmDelete && (
{this.state.showMore && (
From 80a74d435c1723d1f81b6fa10aecd446a0e2d205 Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 04:50:19 +0200
Subject: [PATCH 11/23] fix filter not deletable
---
.../BrowserFilter/BrowserFilter.react.js | 21 ++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js
index ff7875025c..f56e63b58e 100644
--- a/src/components/BrowserFilter/BrowserFilter.react.js
+++ b/src/components/BrowserFilter/BrowserFilter.react.js
@@ -52,7 +52,26 @@ export default class BrowserFilter extends React.Component {
}
isCurrentFilterSaved() {
- // Check if current filter structure matches any saved filter
+ // First check if there's a filterId in the URL (means we're definitely viewing a saved filter)
+ const urlParams = new URLSearchParams(window.location.search);
+ const filterId = urlParams.get('filterId');
+
+ if (filterId) {
+ const preferences = ClassPreferences.getPreferences(
+ this.context.applicationId,
+ this.props.className
+ );
+
+ if (preferences.filters) {
+ // If filterId exists in saved filters, it's definitely a saved filter
+ const savedFilter = preferences.filters.find(filter => filter.id === filterId);
+ if (savedFilter) {
+ return true;
+ }
+ }
+ }
+
+ // Fallback: Check if current filter structure matches any saved filter
const preferences = ClassPreferences.getPreferences(
this.context.applicationId,
this.props.className
From 6f8ff696357894145f3e1d5a0d0c8d2fe25f87cb Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 05:10:09 +0200
Subject: [PATCH 12/23] fix
---
.../BrowserFilter/BrowserFilter.react.js | 61 +++++++++++--------
src/dashboard/Data/Browser/Browser.react.js | 35 ++++++-----
2 files changed, 56 insertions(+), 40 deletions(-)
diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js
index f56e63b58e..1872230614 100644
--- a/src/components/BrowserFilter/BrowserFilter.react.js
+++ b/src/components/BrowserFilter/BrowserFilter.react.js
@@ -55,13 +55,13 @@ export default class BrowserFilter extends React.Component {
// First check if there's a filterId in the URL (means we're definitely viewing a saved filter)
const urlParams = new URLSearchParams(window.location.search);
const filterId = urlParams.get('filterId');
-
+
if (filterId) {
const preferences = ClassPreferences.getPreferences(
this.context.applicationId,
this.props.className
);
-
+
if (preferences.filters) {
// If filterId exists in saved filters, it's definitely a saved filter
const savedFilter = preferences.filters.find(filter => filter.id === filterId);
@@ -70,19 +70,19 @@ export default class BrowserFilter extends React.Component {
}
}
}
-
+
// Fallback: Check if current filter structure matches any saved filter
const preferences = ClassPreferences.getPreferences(
this.context.applicationId,
this.props.className
);
-
+
if (!preferences.filters || this.props.filters.size === 0) {
return false;
}
-
+
const currentFiltersString = JSON.stringify(this.props.filters.toJS());
-
+
return preferences.filters.some(savedFilter => {
try {
const savedFiltersString = JSON.stringify(JSON.parse(savedFilter.filter));
@@ -97,13 +97,13 @@ export default class BrowserFilter extends React.Component {
// Extract filterId from URL if present
const urlParams = new URLSearchParams(window.location.search);
const filterId = urlParams.get('filterId');
-
+
if (filterId) {
const preferences = ClassPreferences.getPreferences(
this.context.applicationId,
this.props.className
);
-
+
if (preferences.filters) {
const savedFilter = preferences.filters.find(filter => filter.id === filterId);
if (savedFilter) {
@@ -118,7 +118,7 @@ export default class BrowserFilter extends React.Component {
// If parsing fails, assume no relative dates
hasRelativeDates = false;
}
-
+
return {
id: savedFilter.id,
name: savedFilter.name,
@@ -128,7 +128,7 @@ export default class BrowserFilter extends React.Component {
}
}
}
-
+
return {
id: null,
name: '',
@@ -139,7 +139,7 @@ export default class BrowserFilter extends React.Component {
toggleMore() {
const currentFilter = this.getCurrentFilterInfo();
-
+
this.setState(prevState => {
let filtersToUse;
if (!prevState.showMore) {
@@ -155,7 +155,7 @@ export default class BrowserFilter extends React.Component {
// Exiting edit mode - preserve current state filters
filtersToUse = prevState.filters;
}
-
+
return {
showMore: !prevState.showMore,
name: prevState.showMore ? prevState.name : currentFilter.name,
@@ -171,7 +171,7 @@ export default class BrowserFilter extends React.Component {
this.context.applicationId,
this.props.className
);
-
+
if (preferences.filters && name) {
return preferences.filters.some(filter =>
filter.name === name && filter.id !== this.getCurrentFilterInfo().id
@@ -366,7 +366,7 @@ export default class BrowserFilter extends React.Component {
save() {
// Store the original UI-friendly filters before any conversion
const originalUIFilters = this.state.filters;
-
+
let formatted = this.state.filters.map(filter => {
const isComparable = Filters.Constraints[filter.get('constraint')].comparable;
if (!isComparable) {
@@ -402,21 +402,32 @@ export default class BrowserFilter extends React.Component {
return filter;
});
}
-
+
// If we're in showMore mode, we're editing an existing filter
const currentFilterInfo = this.getCurrentFilterInfo();
const filterId = this.state.showMore ? currentFilterInfo.id : null;
-
- this.props.onSaveFilter(formatted, this.state.name, this.state.relativeDates, filterId);
-
+
+ const savedFilterId = this.props.onSaveFilter(formatted, this.state.name, this.state.relativeDates, filterId);
+
// Only close the dialog if we're not in edit mode (showMore)
if (!this.state.showMore) {
+ // For new filters, apply the saved filter and update URL
+ this.props.onChange(formatted);
+
+ // Update URL with the new filter ID if we got one back
+ if (savedFilterId) {
+ const urlParams = new URLSearchParams(window.location.search);
+ urlParams.set('filterId', savedFilterId);
+ const newUrl = `${window.location.pathname}?${urlParams.toString()}`;
+ window.history.replaceState({}, '', newUrl);
+ }
+
this.toggle();
} else {
// In edit mode, update the original filter name but keep the original UI-friendly filters
// Convert any Parse Date objects in the UI filters to JavaScript Date objects for proper display
const uiFilters = this.convertDatesForDisplay(originalUIFilters);
-
+
this.setState({
originalFilterName: this.state.name,
filters: uiFilters, // Ensure UI stays with JavaScript Date objects
@@ -448,7 +459,7 @@ export default class BrowserFilter extends React.Component {
const compareTo = filter.get('compareTo');
return compareTo && (compareTo instanceof Date || compareTo.__type === 'Date' || compareTo.__type === 'RelativeDate');
});
-
+
popover = (
filter.id !== currentFilterInfo.id);
ClassPreferences.updatePreferences(
@@ -548,18 +559,18 @@ export default class BrowserFilter extends React.Component {
{ ...preferences, filters: updatedFilters }
);
}
-
+
// Remove filterId from URL
const urlParams = new URLSearchParams(window.location.search);
urlParams.delete('filterId');
const newUrl = `${window.location.pathname}${urlParams.toString() ? '?' + urlParams.toString() : ''}`;
window.history.replaceState({}, '', newUrl);
-
+
// Clear current filters and close dialog
this.props.onChange(new Map());
this.setState({ confirmDelete: false });
this.toggle();
-
+
// Call onDeleteFilter prop if provided
if (this.props.onDeleteFilter) {
this.props.onDeleteFilter(currentFilterInfo.id);
@@ -609,7 +620,7 @@ export default class BrowserFilter extends React.Component {
{(() => {
const currentFilter = this.getCurrentFilterInfo();
const isAppliedSavedFilter = currentFilter.isApplied && this.props.filters.size > 0;
-
+
if (isAppliedSavedFilter && !this.state.showMore) {
return (
<>
diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js
index 7494cca870..c510eed03d 100644
--- a/src/dashboard/Data/Browser/Browser.react.js
+++ b/src/dashboard/Data/Browser/Browser.react.js
@@ -1224,7 +1224,9 @@ class Browser extends DashboardView {
this.context.applicationId,
this.props.params.className
);
-
+
+ let newFilterId = filterId;
+
if (filterId) {
// Update existing filter
const existingFilterIndex = preferences.filters.findIndex(filter => filter.id === filterId);
@@ -1236,23 +1238,23 @@ class Browser extends DashboardView {
};
} else {
// Fallback: if filter not found, create new one
+ newFilterId = crypto.randomUUID();
preferences.filters.push({
name,
- id: crypto.randomUUID(),
+ id: newFilterId,
filter: _filters,
});
}
} else {
- // Create new filter only if it doesn't already exist
- if (!preferences.filters.find(filter => filter.filter === _filters)) {
- preferences.filters.push({
- name,
- id: crypto.randomUUID(),
- filter: _filters,
- });
- }
+ // Create new filter
+ newFilterId = crypto.randomUUID();
+ preferences.filters.push({
+ name,
+ id: newFilterId,
+ filter: _filters,
+ });
}
-
+
ClassPreferences.updatePreferences(
preferences,
this.context.applicationId,
@@ -1260,6 +1262,9 @@ class Browser extends DashboardView {
);
super.forceUpdate();
+
+ // Return the filter ID for new filters so the caller can apply them
+ return newFilterId;
}
deleteFilter(filterId) {
@@ -1267,11 +1272,11 @@ class Browser extends DashboardView {
this.context.applicationId,
this.props.params.className
);
-
+
if (preferences.filters) {
// Try to find by ID first (modern approach)
let updatedFilters = preferences.filters.filter(filter => filter.id !== filterId);
-
+
// If no filter was removed (ID not found), use fallback method
if (updatedFilters.length === preferences.filters.length && filterId) {
// Fallback: try to find by comparing the entire filter object if filterId is actually a filter object
@@ -1286,14 +1291,14 @@ class Browser extends DashboardView {
}
}
}
-
+
ClassPreferences.updatePreferences(
{ ...preferences, filters: updatedFilters },
this.context.applicationId,
this.props.params.className
);
}
-
+
super.forceUpdate();
}
From e76cf089e7bb771c9b11ac823b34bdd9aba58c3a Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 05:16:36 +0200
Subject: [PATCH 13/23] fix sidebar filter highlight
---
.../BrowserFilter/BrowserFilter.react.js | 9 ++++----
.../CategoryList/CategoryList.react.js | 21 ++++++++++++++++---
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js
index 1872230614..5543b4daaf 100644
--- a/src/components/BrowserFilter/BrowserFilter.react.js
+++ b/src/components/BrowserFilter/BrowserFilter.react.js
@@ -69,9 +69,12 @@ export default class BrowserFilter extends React.Component {
return true;
}
}
+ // If filterId is in URL but not found in saved filters, it's not saved
+ return false;
}
- // Fallback: Check if current filter structure matches any saved filter
+ // Fallback only when no filterId in URL: Check if current filter structure matches any saved filter
+ // This is for legacy compatibility
const preferences = ClassPreferences.getPreferences(
this.context.applicationId,
this.props.className
@@ -91,9 +94,7 @@ export default class BrowserFilter extends React.Component {
return false;
}
});
- }
-
- getCurrentFilterInfo() {
+ } getCurrentFilterInfo() {
// Extract filterId from URL if present
const urlParams = new URLSearchParams(window.location.search);
const filterId = urlParams.get('filterId');
diff --git a/src/components/CategoryList/CategoryList.react.js b/src/components/CategoryList/CategoryList.react.js
index 01a01bf9e4..8c94ff3e76 100644
--- a/src/components/CategoryList/CategoryList.react.js
+++ b/src/components/CategoryList/CategoryList.react.js
@@ -6,12 +6,12 @@
* the root directory of this source tree.
*/
import styles from 'components/CategoryList/CategoryList.scss';
+import Icon from 'components/Icon/Icon.react';
import { CurrentApp } from 'context/currentApp';
import generatePath from 'lib/generatePath';
import PropTypes from 'lib/PropTypes';
import React from 'react';
import { Link } from 'react-router-dom';
-import Icon from 'components/Icon/Icon.react';
export default class CategoryList extends React.Component {
static contextType = CurrentApp;
@@ -57,7 +57,14 @@ export default class CategoryList extends React.Component {
const filterId = query.get('filterId');
for (let i = 0; i < c.filters?.length; i++) {
const filter = c.filters[i];
- if (queryFilter === filter.filter || filterId && filterId === filter.id) {
+ // Prioritize filterId matching, only fall back to content comparison if no filterId
+ if (filterId) {
+ if (filterId === filter.id) {
+ height += (i + 1) * 20;
+ break;
+ }
+ } else if (queryFilter === filter.filter) {
+ // Legacy fallback: match by filter content when no filterId is present
height += (i + 1) * 20;
break;
}
@@ -113,7 +120,15 @@ export default class CategoryList extends React.Component {
const queryFilterId = query.get('filterId');
for (let i = 0; i < c.filters?.length; i++) {
const filter = c.filters[i];
- if (queryFilter === filter.filter || queryFilterId && queryFilterId === filter.id) {
+ // Prioritize filterId matching, only fall back to content comparison if no filterId
+ if (queryFilterId) {
+ if (queryFilterId === filter.id) {
+ selectedFilter = i;
+ className = '';
+ break;
+ }
+ } else if (queryFilter === filter.filter) {
+ // Legacy fallback: match by filter content when no filterId is present
selectedFilter = i;
className = '';
break;
From 31ee8f03b343d9d658ab945e300417fc2b1077f0 Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 11:31:12 +0200
Subject: [PATCH 14/23] fix button style on click
---
src/components/Button/Button.react.js | 4 ++++
src/components/Button/Button.scss | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/components/Button/Button.react.js b/src/components/Button/Button.react.js
index 267dbdabe0..20cb426270 100644
--- a/src/components/Button/Button.react.js
+++ b/src/components/Button/Button.react.js
@@ -53,6 +53,10 @@ const Button = props => {
e.target.blur();
}
}}
+ onMouseLeave={e => {
+ // Remove focus when mouse leaves to prevent sticky focus states
+ e.target.blur();
+ }}
>
{props.value}
diff --git a/src/components/Button/Button.scss b/src/components/Button/Button.scss
index 6612992b9e..1b37c76540 100644
--- a/src/components/Button/Button.scss
+++ b/src/components/Button/Button.scss
@@ -77,7 +77,7 @@
border-color: $white;
line-height: 28px;
- &:hover, &:focus{
+ &:hover, &:focus {
background-color: $white;
color: $blue;
}
From 864d583a975bb72fe9f9bb833e47838cd7a80ab7 Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 11:44:50 +0200
Subject: [PATCH 15/23] fix save button on change
---
.../BrowserFilter/BrowserFilter.react.js | 94 +++++++++----------
src/components/Button/Button.react.js | 4 +-
2 files changed, 48 insertions(+), 50 deletions(-)
diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js
index 5543b4daaf..a881362aa0 100644
--- a/src/components/BrowserFilter/BrowserFilter.react.js
+++ b/src/components/BrowserFilter/BrowserFilter.react.js
@@ -40,6 +40,7 @@ export default class BrowserFilter extends React.Component {
showMore: false,
originalFilterName: '',
confirmDelete: false,
+ originalFilters: new List(), // Track original filters when entering edit mode
};
this.toggle = this.toggle.bind(this);
this.wrapRef = React.createRef();
@@ -143,8 +144,13 @@ export default class BrowserFilter extends React.Component {
this.setState(prevState => {
let filtersToUse;
+ let originalFiltersToStore = prevState.originalFilters;
+
if (!prevState.showMore) {
// Entering edit mode
+ // Store the original applied filters for comparison
+ originalFiltersToStore = this.props.filters;
+
// If we already have filters in state (e.g., user added fields), use those but convert only Parse dates
// Otherwise, convert the props filters for display (preserving RelativeDate objects)
if (prevState.filters.size > 0) {
@@ -163,6 +169,7 @@ export default class BrowserFilter extends React.Component {
originalFilterName: currentFilter.name,
relativeDates: currentFilter.hasRelativeDates,
filters: filtersToUse,
+ originalFilters: originalFiltersToStore,
};
});
}
@@ -181,25 +188,49 @@ export default class BrowserFilter extends React.Component {
return false;
}
+ // Helper method to normalize filters for comparison
+ // Converts all date formats to a consistent format for comparison
+ normalizeFiltersForComparison(filters) {
+ return filters.map(filter => {
+ const compareTo = filter.get('compareTo');
+ if (!compareTo) {
+ return filter;
+ }
+
+ // Convert all date types to ISO string for consistent comparison
+ if (compareTo instanceof Date) {
+ return filter.set('compareTo', compareTo.toISOString());
+ } else if (compareTo.__type === 'Date') {
+ return filter.set('compareTo', compareTo.iso);
+ } else if (compareTo.__type === 'RelativeDate') {
+ // Convert RelativeDate to ISO string
+ const now = new Date();
+ const date = new Date(now.getTime() + compareTo.value * 1000);
+ return filter.set('compareTo', date.toISOString());
+ }
+ return filter;
+ });
+ }
+
hasFilterContentChanged() {
// If we're not in showMore mode (editing a saved filter), return false
if (!this.state.showMore) {
return false;
}
- // Compare current state filters with the originally applied filters
- const currentFilters = this.state.filters;
- const appliedFilters = this.props.filters;
+ // Compare current state filters with the original filters stored when entering edit mode
+ const currentFilters = this.normalizeFiltersForComparison(this.state.filters);
+ const originalFilters = this.normalizeFiltersForComparison(this.state.originalFilters);
// If the sizes are different, content has changed
- if (currentFilters.size !== appliedFilters.size) {
+ if (currentFilters.size !== originalFilters.size) {
return true;
}
// Compare each filter
for (let i = 0; i < currentFilters.size; i++) {
const currentFilter = currentFilters.get(i);
- const appliedFilter = appliedFilters.get(i);
+ const originalFilter = originalFilters.get(i);
// Compare each property of the filter
const currentClass = currentFilter.get('class');
@@ -207,49 +238,16 @@ export default class BrowserFilter extends React.Component {
const currentConstraint = currentFilter.get('constraint');
const currentCompareTo = currentFilter.get('compareTo');
- const appliedClass = appliedFilter.get('class');
- const appliedField = appliedFilter.get('field');
- const appliedConstraint = appliedFilter.get('constraint');
- const appliedCompareTo = appliedFilter.get('compareTo');
+ const originalClass = originalFilter.get('class');
+ const originalField = originalFilter.get('field');
+ const originalConstraint = originalFilter.get('constraint');
+ const originalCompareTo = originalFilter.get('compareTo');
- // Check basic properties
- if (currentClass !== appliedClass ||
- currentField !== appliedField ||
- currentConstraint !== appliedConstraint) {
- return true;
- }
-
- // Special handling for date comparisons
- if (currentCompareTo && currentCompareTo.__type === 'Date' && appliedCompareTo && appliedCompareTo.__type === 'RelativeDate') {
- // Convert RelativeDate to Date for comparison
- const now = new Date();
- const appliedDate = new Date(now.getTime() + appliedCompareTo.value * 1000);
- const currentDate = new Date(currentCompareTo.iso);
- if (Math.abs(currentDate.getTime() - appliedDate.getTime()) > 1000) { // Allow 1 second tolerance
- return true;
- }
- } else if (currentCompareTo instanceof Date && appliedCompareTo && appliedCompareTo.__type === 'RelativeDate') {
- // Convert RelativeDate to Date for comparison
- const now = new Date();
- const appliedDate = new Date(now.getTime() + appliedCompareTo.value * 1000);
- if (Math.abs(currentCompareTo.getTime() - appliedDate.getTime()) > 1000) { // Allow 1 second tolerance
- return true;
- }
- } else if (!currentCompareTo && !appliedCompareTo) {
- // Both are null/undefined, continue
- continue;
- } else if (currentCompareTo instanceof Date && appliedCompareTo instanceof Date) {
- // Both are Date objects
- if (currentCompareTo.getTime() !== appliedCompareTo.getTime()) {
- return true;
- }
- } else if (currentCompareTo && currentCompareTo.__type === 'Date' && appliedCompareTo && appliedCompareTo.__type === 'Date') {
- // Both are Parse Date objects
- if (currentCompareTo.iso !== appliedCompareTo.iso) {
- return true;
- }
- } else if (currentCompareTo !== appliedCompareTo) {
- // Other types or one is Date and other is not
+ // Check all properties for equality
+ if (currentClass !== originalClass ||
+ currentField !== originalField ||
+ currentConstraint !== originalConstraint ||
+ currentCompareTo !== originalCompareTo) {
return true;
}
}
@@ -600,7 +598,7 @@ export default class BrowserFilter extends React.Component {
/>
{};
From b66beb847130c0a0f9f0195484c94252f9ef3a57 Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 11:46:45 +0200
Subject: [PATCH 16/23] Update Button.react.js
---
src/components/Button/Button.react.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/components/Button/Button.react.js b/src/components/Button/Button.react.js
index 5b878fe903..f4360136c4 100644
--- a/src/components/Button/Button.react.js
+++ b/src/components/Button/Button.react.js
@@ -5,7 +5,6 @@
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*/
-import React from 'react';
import styles from 'components/Button/Button.scss';
import PropTypes from 'lib/PropTypes';
import baseStyles from 'stylesheets/base.scss';
From ff1261511794b88d8736b68d7d4ebefb6a3a70b1 Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 11:47:10 +0200
Subject: [PATCH 17/23] Revert "Update Button.react.js"
This reverts commit b66beb847130c0a0f9f0195484c94252f9ef3a57.
---
src/components/Button/Button.react.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/components/Button/Button.react.js b/src/components/Button/Button.react.js
index f4360136c4..5b878fe903 100644
--- a/src/components/Button/Button.react.js
+++ b/src/components/Button/Button.react.js
@@ -5,6 +5,7 @@
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*/
+import React from 'react';
import styles from 'components/Button/Button.scss';
import PropTypes from 'lib/PropTypes';
import baseStyles from 'stylesheets/base.scss';
From b50b761314ce6f5de95a0b9f4f5a39e0ea4057a0 Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 11:48:29 +0200
Subject: [PATCH 18/23] lint
---
src/components/BrowserFilter/BrowserFilter.react.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js
index a881362aa0..7c22110255 100644
--- a/src/components/BrowserFilter/BrowserFilter.react.js
+++ b/src/components/BrowserFilter/BrowserFilter.react.js
@@ -145,12 +145,12 @@ export default class BrowserFilter extends React.Component {
this.setState(prevState => {
let filtersToUse;
let originalFiltersToStore = prevState.originalFilters;
-
+
if (!prevState.showMore) {
// Entering edit mode
// Store the original applied filters for comparison
originalFiltersToStore = this.props.filters;
-
+
// If we already have filters in state (e.g., user added fields), use those but convert only Parse dates
// Otherwise, convert the props filters for display (preserving RelativeDate objects)
if (prevState.filters.size > 0) {
From 51280265bb8f75399a88ab8ccd107bb48b50a23e Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 12:27:15 +0200
Subject: [PATCH 19/23] coderabbit
---
.../BrowserFilter/BrowserFilter.react.js | 166 ++++++++----------
src/dashboard/Data/Browser/Browser.react.js | 12 +-
2 files changed, 76 insertions(+), 102 deletions(-)
diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js
index 7c22110255..d6ca49a2b8 100644
--- a/src/components/BrowserFilter/BrowserFilter.react.js
+++ b/src/components/BrowserFilter/BrowserFilter.react.js
@@ -16,7 +16,7 @@ import Label from 'components/Label/Label.react';
import Popover from 'components/Popover/Popover.react';
import TextInput from 'components/TextInput/TextInput.react';
import { CurrentApp } from 'context/currentApp';
-import { List, Map } from 'immutable';
+import { List, Map as ImmutableMap } from 'immutable';
import * as ClassPreferences from 'lib/ClassPreferences';
import * as Filters from 'lib/Filters';
import Position from 'lib/Position';
@@ -116,8 +116,9 @@ export default class BrowserFilter extends React.Component {
hasRelativeDates = filterData.some(filter =>
filter.compareTo && filter.compareTo.__type === 'RelativeDate'
);
- } catch {
- // If parsing fails, assume no relative dates
+ } catch (error) {
+ // Log parsing errors for debugging
+ console.warn('Failed to parse saved filter:', error);
hasRelativeDates = false;
}
@@ -279,7 +280,7 @@ export default class BrowserFilter extends React.Component {
});
return result;
} // Helper method to convert RelativeDate objects to Parse Date format for saving
- convertRelativeDatesForDisplay(filters) {
+ convertRelativeDatesToParseFormat(filters) {
return filters.map(filter => {
const compareTo = filter.get('compareTo');
if (compareTo && compareTo.__type === 'RelativeDate') {
@@ -295,6 +296,45 @@ export default class BrowserFilter extends React.Component {
});
}
+ deleteCurrentFilter() {
+ const currentFilterInfo = this.getCurrentFilterInfo();
+ if (!currentFilterInfo.id) {
+ this.setState({ confirmDelete: false });
+ return;
+ }
+
+ // Delete the filter from ClassPreferences
+ const preferences = ClassPreferences.getPreferences(
+ this.context.applicationId,
+ this.props.className
+ );
+
+ if (preferences.filters) {
+ const updatedFilters = preferences.filters.filter(filter => filter.id !== currentFilterInfo.id);
+ ClassPreferences.updatePreferences(
+ this.context.applicationId,
+ this.props.className,
+ { ...preferences, filters: updatedFilters }
+ );
+ }
+
+ // Remove filterId from URL
+ const urlParams = new URLSearchParams(window.location.search);
+ urlParams.delete('filterId');
+ const newUrl = `${window.location.pathname}${urlParams.toString() ? '?' + urlParams.toString() : ''}`;
+ window.history.replaceState({}, '', newUrl);
+
+ // Clear current filters and close dialog
+ this.props.onChange(new ImmutableMap());
+ this.setState({ confirmDelete: false });
+ this.toggle();
+
+ // Call onDeleteFilter prop if provided
+ if (this.props.onDeleteFilter) {
+ this.props.onDeleteFilter(currentFilterInfo.id);
+ }
+ }
+
toggle() {
let filters = this.props.filters;
if (this.props.filters.size === 0) {
@@ -306,7 +346,7 @@ export default class BrowserFilter extends React.Component {
);
const { filterClass, filterField, filterConstraint } = Filters.getFilterDetails(available);
filters = new List([
- new Map({ class: filterClass, field: filterField, constraint: filterConstraint }),
+ new ImmutableMap({ class: filterClass, field: filterField, constraint: filterConstraint }),
]);
} else {
// Convert only Parse Date objects to JavaScript Date objects, preserve RelativeDate objects
@@ -333,14 +373,14 @@ export default class BrowserFilter extends React.Component {
const { filterClass, filterField, filterConstraint } = Filters.getFilterDetails(available);
this.setState(({ filters }) => ({
filters: filters.push(
- new Map({ class: filterClass, field: filterField, constraint: filterConstraint })
+ new ImmutableMap({ class: filterClass, field: filterField, constraint: filterConstraint })
),
editMode: true,
}));
}
clear() {
- this.props.onChange(new Map());
+ this.props.onChange(new ImmutableMap());
}
apply() {
@@ -542,42 +582,7 @@ export default class BrowserFilter extends React.Component {
primary={true}
width="120px"
onClick={() => {
- const currentFilterInfo = this.getCurrentFilterInfo();
- if (currentFilterInfo.id) {
- // Delete the filter from ClassPreferences
- const preferences = ClassPreferences.getPreferences(
- this.context.applicationId,
- this.props.className
- );
-
- if (preferences.filters) {
- const updatedFilters = preferences.filters.filter(filter => filter.id !== currentFilterInfo.id);
- ClassPreferences.updatePreferences(
- this.context.applicationId,
- this.props.className,
- { ...preferences, filters: updatedFilters }
- );
- }
-
- // Remove filterId from URL
- const urlParams = new URLSearchParams(window.location.search);
- urlParams.delete('filterId');
- const newUrl = `${window.location.pathname}${urlParams.toString() ? '?' + urlParams.toString() : ''}`;
- window.history.replaceState({}, '', newUrl);
-
- // Clear current filters and close dialog
- this.props.onChange(new Map());
- this.setState({ confirmDelete: false });
- this.toggle();
-
- // Call onDeleteFilter prop if provided
- if (this.props.onDeleteFilter) {
- this.props.onDeleteFilter(currentFilterInfo.id);
- }
- } else {
- // Close the confirmation dialog if no filter ID
- this.setState({ confirmDelete: false });
- }
+ this.deleteCurrentFilter();
}}
/>
@@ -616,59 +621,28 @@ export default class BrowserFilter extends React.Component {
)}
- {(() => {
- const currentFilter = this.getCurrentFilterInfo();
- const isAppliedSavedFilter = currentFilter.isApplied && this.props.filters.size > 0;
-
- if (isAppliedSavedFilter && !this.state.showMore) {
- return (
- <>
- this.toggleMore()}
- >
-
-
- this.clear()}
- />
- >
- );
- } else if (!this.state.showMore) {
- return (
- <>
- this.toggleMore()}
- >
-
-
- this.clear()}
- />
- >
- );
- }
- return null;
- })()}
+ {!this.state.showMore && (
+ <>
+ this.toggleMore()}
+ >
+
+
+ this.clear()}
+ />
+ >
+ )}
filter.id !== filterId);
+ let updatedFilters = preferences.filters.filter(filter => filter.id !== filterIdOrObject);
// If no filter was removed (ID not found), use fallback method
- if (updatedFilters.length === preferences.filters.length && filterId) {
- // Fallback: try to find by comparing the entire filter object if filterId is actually a filter object
- if (typeof filterId === 'object') {
+ if (updatedFilters.length === preferences.filters.length && filterIdOrObject) {
+ // Fallback: try to find by comparing the entire filter object if filterIdOrObject is actually a filter object
+ if (typeof filterIdOrObject === 'object') {
let i = preferences.filters.length;
updatedFilters = [...preferences.filters];
while (i--) {
const item = updatedFilters[i];
- if (JSON.stringify(item) === JSON.stringify(filterId)) {
+ if (JSON.stringify(item) === JSON.stringify(filterIdOrObject)) {
updatedFilters.splice(i, 1);
}
}
From 96aa9f1deeddc09d0175393cc0bbaa8325000faf Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 12:46:56 +0200
Subject: [PATCH 20/23] fix date filter in URL
---
src/dashboard/Data/Browser/Browser.react.js | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js
index fc1807cba0..c5f7bbd212 100644
--- a/src/dashboard/Data/Browser/Browser.react.js
+++ b/src/dashboard/Data/Browser/Browser.react.js
@@ -524,10 +524,23 @@ class Browser extends DashboardView {
if (query.has('filters')) {
const queryFilters = JSON.parse(query.get('filters'));
queryFilters.forEach(
- filter =>
- (filters = filters.push(
- new Map({ ...filter, class: filter.class || props.params.className })
- ))
+ filter => {
+ // Convert date strings to Parse Date objects for proper Parse query functionality
+ const processedFilter = { ...filter, class: filter.class || props.params.className };
+
+ // Check if compareTo is a date string and convert it to a Parse Date object
+ if (processedFilter.compareTo &&
+ typeof processedFilter.compareTo === 'string' &&
+ !isNaN(Date.parse(processedFilter.compareTo))) {
+ // Convert string date to Parse Date format for proper query functionality
+ processedFilter.compareTo = {
+ __type: 'Date',
+ iso: new Date(processedFilter.compareTo).toISOString()
+ };
+ }
+
+ filters = filters.push(Map(processedFilter));
+ }
);
}
return filters;
From 6711f5220d3b30c017db59374b5ca54f95392f2a Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 13:09:42 +0200
Subject: [PATCH 21/23] fix apply button on saved filter
---
src/dashboard/Data/Browser/Browser.react.js | 45 +++++++++++++++++----
1 file changed, 37 insertions(+), 8 deletions(-)
diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js
index c5f7bbd212..0119bac954 100644
--- a/src/dashboard/Data/Browser/Browser.react.js
+++ b/src/dashboard/Data/Browser/Browser.react.js
@@ -1201,9 +1201,28 @@ class Browser extends DashboardView {
} else {
const source = this.props.params.className;
const _filters = JSON.stringify(filters.toJSON());
- const url = `browser/${source}${
- filters.size === 0 ? '' : `?filters=${encodeURIComponent(_filters)}`
- }`;
+
+ // Preserve filterId from current URL if it exists
+ const currentUrlParams = new URLSearchParams(window.location.search);
+ const currentFilterId = currentUrlParams.get('filterId');
+
+ let url = `browser/${source}`;
+ if (filters.size === 0) {
+ // If no filters, don't include any query parameters
+ url = `browser/${source}`;
+ } else {
+ // Build query parameters
+ const queryParams = new URLSearchParams();
+ queryParams.set('filters', _filters);
+
+ // Preserve filterId if it exists in current URL
+ if (currentFilterId) {
+ queryParams.set('filterId', currentFilterId);
+ }
+
+ url = `browser/${source}?${queryParams.toString()}`;
+ }
+
// filters param change is making the fetch call
this.props.navigate(generatePath(this.context, url));
}
@@ -1349,13 +1368,23 @@ class Browser extends DashboardView {
data: null,
},
() => {
- let filterQueryString;
+ // Preserve filterId from current URL if it exists
+ const currentUrlParams = new URLSearchParams(window.location.search);
+ const currentFilterId = currentUrlParams.get('filterId');
+
+ let url = this.getRelationURL();
if (filters && filters.size) {
- filterQueryString = encodeURIComponent(JSON.stringify(filters.toJSON()));
+ const queryParams = new URLSearchParams();
+ queryParams.set('filters', JSON.stringify(filters.toJSON()));
+
+ // Preserve filterId if it exists in current URL
+ if (currentFilterId) {
+ queryParams.set('filterId', currentFilterId);
+ }
+
+ url = `${url}?${queryParams.toString()}`;
}
- const url = `${this.getRelationURL()}${
- filterQueryString ? `?filters=${filterQueryString}` : ''
- }`;
+
this.props.navigate(url);
}
);
From 1fb4727a5803b1fef6120f197fd5f45450ecedca Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 26 Jul 2025 13:30:59 +0200
Subject: [PATCH 22/23] use icons for space rasons
---
.../BrowserFilter/BrowserFilter.react.js | 78 +++++++++++++++----
.../BrowserFilter/BrowserFilter.scss | 25 ++++++
2 files changed, 88 insertions(+), 15 deletions(-)
diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js
index d6ca49a2b8..a15e362740 100644
--- a/src/components/BrowserFilter/BrowserFilter.react.js
+++ b/src/components/BrowserFilter/BrowserFilter.react.js
@@ -335,6 +335,20 @@ export default class BrowserFilter extends React.Component {
}
}
+ copyCurrentFilter() {
+ // Remove filterId from URL so when saving it will create a new filter instead of updating
+ const urlParams = new URLSearchParams(window.location.search);
+ urlParams.delete('filterId');
+ const newUrl = `${window.location.pathname}${urlParams.toString() ? '?' + urlParams.toString() : ''}`;
+ window.history.replaceState({}, '', newUrl);
+
+ // Clear the filter name so user can enter a new name
+ this.setState({
+ name: '',
+ originalFilterName: ''
+ });
+ }
+
toggle() {
let filters = this.props.filters;
if (this.props.filters.size === 0) {
@@ -592,7 +606,7 @@ export default class BrowserFilter extends React.Component {
{this.state.showMore && (
this.toggleMore()}
>
-
this.save()}
+
- {this.isCurrentFilterSaved() && (
- this.setState({ confirmDelete: true })}
+ {
+ if (this.state.name && (this.state.name !== this.state.originalFilterName || this.hasFilterContentChanged()) && !this.isFilterNameExists(this.state.name)) {
+ this.save();
+ }
+ }}
+ >
+
+
+ {this.isCurrentFilterSaved() && (
+ <>
+ this.copyCurrentFilter()}
+ >
+
+
+ this.setState({ confirmDelete: true })}
+ >
+
+
+ >
)}
)}
@@ -624,7 +672,7 @@ export default class BrowserFilter extends React.Component {
{!this.state.showMore && (
<>
this.toggleMore()}
>
Date: Sat, 26 Jul 2025 13:31:17 +0200
Subject: [PATCH 23/23] lint
---
src/dashboard/Data/Browser/Browser.react.js | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js
index 0119bac954..6faaf967d9 100644
--- a/src/dashboard/Data/Browser/Browser.react.js
+++ b/src/dashboard/Data/Browser/Browser.react.js
@@ -1201,11 +1201,11 @@ class Browser extends DashboardView {
} else {
const source = this.props.params.className;
const _filters = JSON.stringify(filters.toJSON());
-
+
// Preserve filterId from current URL if it exists
const currentUrlParams = new URLSearchParams(window.location.search);
const currentFilterId = currentUrlParams.get('filterId');
-
+
let url = `browser/${source}`;
if (filters.size === 0) {
// If no filters, don't include any query parameters
@@ -1214,15 +1214,15 @@ class Browser extends DashboardView {
// Build query parameters
const queryParams = new URLSearchParams();
queryParams.set('filters', _filters);
-
+
// Preserve filterId if it exists in current URL
if (currentFilterId) {
queryParams.set('filterId', currentFilterId);
}
-
+
url = `browser/${source}?${queryParams.toString()}`;
}
-
+
// filters param change is making the fetch call
this.props.navigate(generatePath(this.context, url));
}
@@ -1371,20 +1371,20 @@ class Browser extends DashboardView {
// Preserve filterId from current URL if it exists
const currentUrlParams = new URLSearchParams(window.location.search);
const currentFilterId = currentUrlParams.get('filterId');
-
+
let url = this.getRelationURL();
if (filters && filters.size) {
const queryParams = new URLSearchParams();
queryParams.set('filters', JSON.stringify(filters.toJSON()));
-
+
// Preserve filterId if it exists in current URL
if (currentFilterId) {
queryParams.set('filterId', currentFilterId);
}
-
+
url = `${url}?${queryParams.toString()}`;
}
-
+
this.props.navigate(url);
}
);