A filter store in the app currently looks like this
fiters: {
...
filters: {
'555pageId': {
"member_region": {
"items": {
"domestic": false,
"international": true
}
},
"member_type": {
"items": {
"Electronic Forum Member": true,
"Corporate Sponsor": true,
"Member": true,
"Senior Fellow": true,
"Associate Member": true
}
}
"fip_code": {
"items": {
123454: true,
647894: false,
[...too many to list here...]
}
}
}
}
}
These lists are big (roughly 50, 500, 5000 items)
To generate the "saved" version of a filter, I suggest a one step compacting for big sets.
forEach (page.filters): // only concern ourselves with what is visible to the user
arbitraryCuttoff = 24
count TRUE items, FALSE items and ALL items
if ALL.count > arbitraryCutoff
if TRUE.count => FALSE.count
thisSavedFilter = {
exclude: ["array", "of", "false", "items", "possibly", "empty", "array"]
}
else
thisSavedFilter = {
include: ["array", "of", "true", "items"]
}
else // not so many items
The end result is to look something like this:
user: {
preferences: {
ux: {
// to be tackled at a later time
// should actually be pretty straightforward
// for each UX item
// strip out data objects (they can be huge)
// save the rest
}
filters: {
555pageId: {
"member_region": {
"items": {
"domestic": false,
"international": true
}
},
"member_type": {
"items": {
"Electronic Forum Member": true,
"Corporate Sponsor": true,
"Member": true,
"Senior Fellow": true,
"Associate Member": true
}
}
"fip_code": {
"include": ["45678", "78945", "all", "the", "included", "fipcodes"]
}
}
}
}
Right now I plan to avoid the question of WHEN we should save filters. I feel like we can address that separately. For version one, we could put a "save settings" button in the footer.
The "arbitraryCutoff" step in the above pseudo-code is meant to address reasonable bounds of this problem. In specific, if you have 25 months listed, and visibly filterable, and you are showing more than half of them in the filter, then "Next Month" would still be a problem.
However, in the "natural" save state (total items under the cutoff limit), we can account for the existence of a filterable item, like "jul-2016" when it shows up in the view-data, combined with its commensurate "undefined" status in the saved filterState.
In /reducers/filters.js
, we have an "updateFilters" method that runs when a view arrives. Views arrival means that we would already have our user-preferences on hand. So inside "updateFilters", we currently build the filterList out of available data from the views. After that, we could apply these "saved" filters from the user.
const itemsIntersection = ... // existing code that makes the filter "items" list.
const filterPreferenceItems = ... // fetch the right one from the user prefs
_forOwn(itemsIntersection, (val, key) => {
if (!filterPreferenceItems[key] && typeof filterPreferenceItems[key] !== 'undefined') {
itemsIntersection[key] = false;
}
});
Uhm. That's all it should take.