Applications and Board are one page in two shapes, and the switch loses your filters #102

Closed
opened 2026-09-07 15:31:24 +00:00 by tiagoagueda · 2 comments
Owner

Observation

for 0.4.0 target: Unify Applications and Board into a single app

They are already one app; what is split is the person's experience

Both live in postulo.applications, both are ListViews, and both already share their
filtering:

class ApplicationFilterMixin:
    """Shared filtering for the table and the board.

    Both views answer the same question -- "which of my applications am I looking at?" --
    so the filters live in one place rather than drifting apart.
    """

The docstring has the argument for this issue in it. Two views answering the same question
are one page with two shapes, and they are presented as two places: two URLs
(/applications/ and /applications/board/), two entries in the navigation, and a
button on each pointing at the other.

And the split loses your filters, today

The two switch buttons are bare links:

<a href="{% url 'applications:board' %}">{% translate "Board" %}</a>   {# in the table  #}
<a href="{% url 'applications:list' %}">{% translate "Table" %}</a>    {# in the board  #}

No query string. So narrowing the table to quiet applications at Acme, then pressing
Board to see them arranged by status, throws the filter away and shows everything. The
filters are shared in the code and discarded in the interface, which is close to the worst of
both.

That is fixable in two lines without any of the rest of this issue, and it is also the
clearest evidence that these want to be one page: nobody would build a view switcher that
forgets what you were looking at.

What unifying means

One place called Applications, one entry in the navigation, and a view switch that
changes the shape without changing what you are looking at:

  • The filters, the search and the sort survive the switch, because they are already one set
    of parameters.
  • The choice is remembered -- Profile.table_settings already keeps per-table layout, so
    there is somewhere for "this person prefers the board" to live.
  • /applications/board/ keeps working and redirects, because it is a URL people have
    bookmarked.

Three things that need handling rather than noticing later

The board shows less on purpose. ApplicationBoardView says "Only open statuses get a
column. Rejections and withdrawals belong in the table and the figures, not taking up space
on a board meant to show what is still live."
That is a real difference in what is
displayed, not just how. Carrying filters across a switch means deciding what happens when
somebody filters to Rejected and switches to a board that has no column for it -- show an
empty board, add the column, or say so. Silently showing nothing is the wrong answer.

hidden_nav_items holds "board" for anybody who hid it. navigation.HIDEABLE covers
every item and a person's hidden list is stored JSON. Removing the item leaves a dead key in
those rows, and anybody who hid Board but not Applications should not lose the board
entirely -- their preference was about a navigation entry that no longer exists. A data
migration, and a decision about what their preference becomes.

The board is where drag and drop lives, and tests/e2e/test_board_drag.py covers it,
including that the menu stays because "drag and drop does not fire on touch screens and is
not reachable from a keyboard"
. Whatever the page becomes, that has to remain true, and the
existing test should go on passing rather than be rewritten to fit.

Worth doing first, and cheaply

The filter-carrying fix stands on its own and does not need 0.4.0. If this issue waits, that
one should not.

Classification

Enhancement, interface. Not breaking as long as the old URL redirects.

## Observation > for 0.4.0 target: Unify Applications and Board into a single app ## They are already one app; what is split is the person's experience Both live in `postulo.applications`, both are `ListView`s, and both already share their filtering: ```python class ApplicationFilterMixin: """Shared filtering for the table and the board. Both views answer the same question -- "which of my applications am I looking at?" -- so the filters live in one place rather than drifting apart. """ ``` The docstring has the argument for this issue in it. Two views answering the same question are one page with two shapes, and they are presented as two places: two URLs (`/applications/` and `/applications/board/`), **two entries in the navigation**, and a button on each pointing at the other. ## And the split loses your filters, today The two switch buttons are bare links: ```django <a href="{% url 'applications:board' %}">{% translate "Board" %}</a> {# in the table #} <a href="{% url 'applications:list' %}">{% translate "Table" %}</a> {# in the board #} ``` No query string. So narrowing the table to *quiet applications at Acme*, then pressing **Board** to see them arranged by status, throws the filter away and shows everything. The filters are shared in the code and discarded in the interface, which is close to the worst of both. That is fixable in two lines without any of the rest of this issue, and it is also the clearest evidence that these want to be one page: nobody would build a view switcher that forgets what you were looking at. ## What unifying means One place called **Applications**, one entry in the navigation, and a view switch that changes the shape without changing what you are looking at: - The filters, the search and the sort survive the switch, because they are already one set of parameters. - The choice is remembered -- `Profile.table_settings` already keeps per-table layout, so there is somewhere for "this person prefers the board" to live. - `/applications/board/` keeps working and redirects, because it is a URL people have bookmarked. ## Three things that need handling rather than noticing later **The board shows less on purpose.** `ApplicationBoardView` says *"Only open statuses get a column. Rejections and withdrawals belong in the table and the figures, not taking up space on a board meant to show what is still live."* That is a real difference in what is displayed, not just how. Carrying filters across a switch means deciding what happens when somebody filters to *Rejected* and switches to a board that has no column for it -- show an empty board, add the column, or say so. Silently showing nothing is the wrong answer. **`hidden_nav_items` holds `"board"` for anybody who hid it.** `navigation.HIDEABLE` covers every item and a person's hidden list is stored JSON. Removing the item leaves a dead key in those rows, and anybody who hid *Board* but not *Applications* should not lose the board entirely -- their preference was about a navigation entry that no longer exists. A data migration, and a decision about what their preference becomes. **The board is where drag and drop lives**, and `tests/e2e/test_board_drag.py` covers it, including that the menu stays because *"drag and drop does not fire on touch screens and is not reachable from a keyboard"*. Whatever the page becomes, that has to remain true, and the existing test should go on passing rather than be rewritten to fit. ## Worth doing first, and cheaply The filter-carrying fix stands on its own and does not need 0.4.0. If this issue waits, that one should not. ## Classification Enhancement, interface. Not breaking as long as the old URL redirects.
tiagoagueda added this to the 0.4.0 milestone 2026-09-07 15:31:24 +00:00
tiagoagueda modified the milestone from 0.4.0 to 0.3.0 2026-09-12 11:15:47 +00:00
Author
Owner

Decided: this release, and both views are kept

Moved to 0.3.0 and re-tiered to tier/3. Applications becomes one tab with two
shapes
; neither shape is dropped. That is what this issue already proposed —

One place called Applications, one entry in the navigation, and a view switch that
changes the shape without changing what you are looking at

— so what is settled is the when, and the one question that was genuinely open: the board
is not being retired in favour of the table, nor the table in favour of the board. Both stay,
and the switch between them stops losing your filters.

What that leaves to decide, which this issue already names

Keeping both views does not answer the three it lists, and none of them should be discovered
during the work:

  1. The board shows less on purpose. ApplicationBoardView: "Only open statuses get a
    column. Rejections and withdrawals belong in the table and the figures, not taking up
    space on a board meant to show what is still live."
    Carrying a filter across the switch
    means deciding what a person sees when they filter to Rejected and press Board —
    an empty board, a column that usually is not there, or a sentence saying why. Silently
    showing nothing is the wrong answer, and it is the one that happens by default.
  2. hidden_nav_items holds "board" for anybody who hid it. Removing the navigation
    entry leaves a dead key, and somebody who hid Board but not Applications was
    expressing a preference about a navigation entry rather than asking to lose the board.
    Needs a data migration and a decision about what their preference becomes.
  3. Drag and drop lives on the board and test_board_drag.py covers it — including that
    the status menu stays, because dragging fires on neither a touch screen nor a keyboard.
    That test should go on passing rather than be rewritten to fit the new page.

Worth taking first, separately

The issue's own closing point still holds: the filters are discarded in two lines and
fixed in two.
Both switch buttons are bare links with no query string, so narrowing the
table and pressing Board throws the filter away. That is a bug inside this issue that does
not need the rest of it, and landing it first makes the unification a layout change rather
than a layout change plus a bug fix.

One thing that has changed since this was written

#174 fixed the board's drag — it never cancelled dragenter, so moving a card between
columns did nothing in Firefox, and the synthetic-event tests agreed with Chromium. Whatever
the unified page becomes, it inherits the fix and the test that now asks the handlers the
question a browser asks.

Related in this release: #188 takes the 1280px cap off <main>, and a board with a
column per status is one of the pages that most wants the width. Worth knowing which lands
first, since both touch the same page's outer layout.

## Decided: this release, and both views are kept Moved to **0.3.0** and re-tiered to **tier/3**. Applications becomes **one tab with two shapes**; neither shape is dropped. That is what this issue already proposed — > One place called **Applications**, one entry in the navigation, and a view switch that > changes the shape without changing what you are looking at — so what is settled is the *when*, and the one question that was genuinely open: the board is not being retired in favour of the table, nor the table in favour of the board. Both stay, and the switch between them stops losing your filters. ### What that leaves to decide, which this issue already names Keeping both views does not answer the three it lists, and none of them should be discovered during the work: 1. **The board shows less on purpose.** `ApplicationBoardView`: *"Only open statuses get a column. Rejections and withdrawals belong in the table and the figures, not taking up space on a board meant to show what is still live."* Carrying a filter across the switch means deciding what a person sees when they filter to *Rejected* and press **Board** — an empty board, a column that usually is not there, or a sentence saying why. Silently showing nothing is the wrong answer, and it is the one that happens by default. 2. **`hidden_nav_items` holds `"board"`** for anybody who hid it. Removing the navigation entry leaves a dead key, and somebody who hid *Board* but not *Applications* was expressing a preference about a navigation entry rather than asking to lose the board. Needs a data migration and a decision about what their preference becomes. 3. **Drag and drop lives on the board** and `test_board_drag.py` covers it — including that the status menu stays, because dragging fires on neither a touch screen nor a keyboard. That test should go on passing rather than be rewritten to fit the new page. ### Worth taking first, separately The issue's own closing point still holds: **the filters are discarded in two lines and fixed in two.** Both switch buttons are bare links with no query string, so narrowing the table and pressing *Board* throws the filter away. That is a bug inside this issue that does not need the rest of it, and landing it first makes the unification a layout change rather than a layout change plus a bug fix. ### One thing that has changed since this was written **#174 fixed the board's drag** — it never cancelled `dragenter`, so moving a card between columns did nothing in Firefox, and the synthetic-event tests agreed with Chromium. Whatever the unified page becomes, it inherits the fix and the test that now asks the handlers the question a browser asks. Related in this release: **#188** takes the 1280px cap off `<main>`, and a board with a column per status is one of the pages that most wants the width. Worth knowing which lands first, since both touch the same page's outer layout.
Author
Owner

Restated, 2026-09-13, as the requirement to build against

Applications and Board live on one page, called Applications, and the table and the
board are a switch inside that page.
Not two entries in the navigation with a button
between them: one entry, one address, and a control on the page — beside the search box
and the filters, where the Columns control sits — that changes the shape of what is
below it and nothing else.

Checked against main today, nothing has moved since this was written:

  • navigation.py:57-62 still lists applications and board as two items.
  • The two switch buttons are still bare links with no query string
    (application_list.html:75, application_board.html:17), so narrowing the table and
    pressing Board still shows everything.
  • Both views still share ApplicationFilterMixin and its parameters, which is what makes
    the switch a shape rather than a page.

The three questions in the body and in the comment above stand as the things to decide
before the work — the board's missing columns for settled statuses, the dead "board"
key in hidden_nav_items, and the drag-and-drop test staying as it is. One more from the
restatement: the switch is inside the table's page, so the board is drawn by the same
view under the same address with a parameter or a remembered preference, and
/applications/board/ becomes a redirect that carries whatever query string it was given.

## Restated, 2026-09-13, as the requirement to build against **Applications and Board live on one page, called *Applications*, and the table and the board are a switch inside that page.** Not two entries in the navigation with a button between them: one entry, one address, and a control on the page — beside the search box and the filters, where the *Columns* control sits — that changes the shape of what is below it and nothing else. Checked against `main` today, nothing has moved since this was written: - `navigation.py:57-62` still lists `applications` and `board` as two items. - The two switch buttons are still bare links with no query string (`application_list.html:75`, `application_board.html:17`), so narrowing the table and pressing *Board* still shows everything. - Both views still share `ApplicationFilterMixin` and its parameters, which is what makes the switch a shape rather than a page. The three questions in the body and in the comment above stand as the things to decide before the work — the board's missing columns for settled statuses, the dead `"board"` key in `hidden_nav_items`, and the drag-and-drop test staying as it is. One more from the restatement: the switch is *inside the table's page*, so the board is drawn by the same view under the same address with a parameter or a remembered preference, and `/applications/board/` becomes a redirect that carries whatever query string it was given.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Postulo/postulo#102
No description provided.