Skip to content

Instantly share code, notes, and snippets.

@mattsahr
Last active June 22, 2016 20:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattsahr/b14bb5b7a0c983c39c018dcb4445002d to your computer and use it in GitHub Desktop.
Save mattsahr/b14bb5b7a0c983c39c018dcb4445002d to your computer and use it in GitHub Desktop.
Filter preferences

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...]
				}
			}
		}
	}
}

The issue of states / congressional districts / counties

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 issue of the arrival of Next Month:

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment