What is shown, as data.
A filter is a query string and a set of switches on four axes — the card's
state, its column on the board, its labels and its assignees. apply/2 is a
pure function from a filter and every card to the cards that pass it, which is
the whole of the filtering logic and is tested without a terminal or a network
in sight.
The query
Whitespace splits the query into terms and every term has to match somewhere in the row — its number, title, repository, column, author, milestone, labels, assignees, state or kind. That makes narrowing additive: typing another word can only ever shorten the list, which is what a search field that filters as you type has to do to stay predictable.
"bug ready" both words, in any field, in any order
"#42" the number, because "#42" is part of the haystack
"e-matrix/eec" the repository, on a board that spans severalThe switches
Every switch is on until it is turned off, which is why the filter stores what is off rather than what is on. A board that grows a column between one reload and the next, or a card that arrives wearing a label nobody has seen before, is then shown rather than silently dropped — the alternative is a filter that hides things because of a switch that did not exist yet.
An axis is either single-valued or multi-valued, and they are filtered differently:
- state and column — a card is in exactly one, so it passes when that one is on.
- labels and assignees — a card can be in several, so it passes when any of them is on. Turning one label off therefore hides the cards that wear only that label, not every card that happens to wear it too.
Each axis has a :none bucket — no column, unlabelled, unassigned — so the
cards that nobody has got to yet are a switch of their own rather than a gap.
Where the options come from
The columns come from the board, so a column with nothing in it is still a
switch you can turn off. The states, labels and assignees come from the cards,
because nothing else knows what is on the board — put_options/3 is how the
list view hands them over once they have loaded, and it keeps the switches
that were already set.
Summary
Functions
The cards that pass the filter, in the order they were given.
The axes, in the order the popup lists them.
How an axis is titled on screen.
Every switch the filter knows about, as {axis, key} pairs.
True while a switch is off — the query is not counted.
How a key is written on screen, without its axis to name it by.
How a switch's key is written on screen.
True when this filter can remove a row at all.
A filter that hides nothing, with a switch for each of the board's columns.
Whether a switch is on. A switch nobody has touched is on.
The switches on axis, in the order they are listed.
Replaces one axis's switches, keeping the ones already set.
Replaces the query string.
Turns every switch on or off at once, the query untouched.
A one-line description of the switches, for the footer.
Splits a query into the lowercased terms every row has to match.
Flips one switch.
Types
Functions
@spec apply(t(), [Gitpro.Item.t()]) :: [Gitpro.Item.t()]
The cards that pass the filter, in the order they were given.
Order is the board's, not the filter's: a list that reshuffles itself as you type is unusable, so filtering only ever takes rows away.
@spec axes() :: [axis()]
The axes, in the order the popup lists them.
How an axis is titled on screen.
Every switch the filter knows about, as {axis, key} pairs.
True while a switch is off — the query is not counted.
How a key is written on screen, without its axis to name it by.
How a switch's key is written on screen.
The empty bucket is named for its axis — "Unassigned" says what it holds, and four switches all called "(none)" would not.
True when this filter can remove a row at all.
A filter that hides nothing, with a switch for each of the board's columns.
The other three axes start empty and are filled in by put_options/3 once the
cards are in — until then they hide nothing, which is what an axis with no
switches on it should do.
Whether a switch is on. A switch nobody has touched is on.
The switches on axis, in the order they are listed.
Replaces one axis's switches, keeping the ones already set.
The :none bucket is appended rather than expected in keys: a card with no
column, no label or no assignee is always possible, whatever the cards that
have loaded happen to show. State has no such bucket — every card is in one of
the states, and a switch that can never match anything is a switch that only
wastes a row.
Replaces the query string.
Turns every switch on or off at once, the query untouched.
set_all(filter, false) can only turn off the switches the filter knows
about, so a label that arrives afterwards is on — see the note on where the
options come from.
A one-line description of the switches, for the footer.
Answers nil when nothing is narrowed, so the footer can leave the space to
the shortcuts rather than saying "all".
Splits a query into the lowercased terms every row has to match.
Flips one switch.