{% extends "scitex_app/app_shell.html" %} {% load static scitex_paths %} {% comment %} project_board.html — the PROJECT-SCOPED board (Hub PR #923, section 5 "Cards": "current project, canonical picker, authorized cards only"). SELECTORS: every control and every state carries a stable data-stx-* hook rather than a visible label. Hub PR #923 requires the video/docs pipeline to locate controls by stable attributes "not translated labels", so the labels below are free to move and translate without breaking a recording. THE PICKER IS THE SDK's. When the host registers a project provider, the {% templatetag openblock %} include {% templatetag closeblock %} below renders the canonical selector and this page adds no second one. Only a STANDALONE mount (no host provider) falls back to the plain form below, which offers exactly the projects the viewer's own authorized cards name — the same set the provider would answer with, so the two can never disagree. STATES ARE DISTINCT ON PURPOSE: no-project, denied, unavailable, empty and filtered-empty each need a different action from the reader, and the HTTP status matches (403 denied, 503 unavailable). A single "nothing here" panel would make the reader guess which of the five they are looking at. {% endcomment %} {% block extra_css %} {% endblock %} {% block scitex_app_content %}

SciTeX Cards

v{{ scitex_cards_version }} {% if board.project %} Project {{ board.project }} {% else %} No project selected {% endif %}
{% if host_picker_available %} {% include "scitex_cards/_project_picker.html" with current=board.project picker_scope="project" %} {% elif board.projects %}
{% endif %}
{% if board.state == "ready" or board.state == "filtered-empty" %} {% endif %}
{% if created_id %}

Card created: {{ created_id }}

{% endif %} {% if updated_id %}

Card updated: {{ updated_id }}

{% endif %} {% if create_error %} {% endif %} {% if board.state == "ready" or board.state == "empty" %} {% comment %} CREATE. Plain form controls, keyboard-first, no drag and nothing that needs JavaScript — "accessible non-drag alternatives" is the product requirement, and a server-rendered form satisfies it by construction rather than by adding an alternative beside a drag-only control. NO {% templatetag openblock %} csrf_token {% templatetag closeblock %} HERE ON PURPOSE, and it is a stated gap rather than an oversight: this app's settings install no CsrfViewMiddleware, so no cookie would ever be set and a token that cannot be validated would break the form outright. Writes on this board therefore inherit the same stance as the existing DM POST endpoints (csrf-exempt). Flagged to the package owner as a decision for the write surface rather than silently assumed safe; the page is loopback-only by default and behind the hub's auth + Cloudflare Access when exposed. {% endcomment %}
{% endif %} {% if board.state == "no-project" %}

Choose a project

A project board shows the cards of one project. Pick one above to open it. {% if not board.projects %} You have no cards in any project yet, so there is nothing to pick. {% endif %}

{% elif board.state == "denied" %}

No access to this project

This project is not one you can open, so no cards from it are shown. {% if board.projects %}Pick one of your own projects above.{% endif %}

{% elif board.state == "unavailable" %}

The card store could not be read

This is a temporary failure between this page and the store — not a problem with your projects. Try again; if it keeps failing, the deployment's store needs attention.

Retry
{% elif board.state == "empty" %}

No cards in {{ board.project }}

This project has no cards yet. Create the first one below.

{% elif board.state == "filtered-empty" %}

No cards match these filters

{{ board.project }} has {{ board.project_total }} card{{ board.project_total|pluralize }}, none of which match the filters above. The board is not empty — the filters are.

Clear filters
{% else %}

showing {{ board.shown_from }}–{{ board.shown_to }} of {{ board.total }} card{{ board.total|pluralize }} in {{ board.project }}

{% if board.has_prev or board.has_next %} {% endif %} {% for group in groups %}

{{ group.status|default:"other" }} {{ group.count }}

    {% for row in group.rows %}
  • {{ row.title|default:row.id }}

    {{ row.status|default:"—" }} assignee {{ row.assignee|default:"—" }} priority {{ row.priority|default:"—" }} {% if row.blocker %}gate {{ row.blocker }}{% endif %} {{ row.id }}

    {% comment %} ACT ON A CARD — status, assignee, archive. Plain form controls, no drag, no JavaScript, keyboard-first: the product requires "accessible non-drag alternatives", and a server-rendered form satisfies it by construction rather than by bolting an alternative beside a drag-only control. The form carries the card id, and the SERVER refuses any id that is not already in the rows this page rendered — so the tenancy check does not depend on the client sending an honest id. {% endcomment %}
  • {% endfor %}
{% endfor %} {% endif %}
{% endblock %}