99 lines
10 KiB
Markdown
99 lines
10 KiB
Markdown
## ADDED Requirements
|
||
|
||
### Requirement: Проект в приложении
|
||
Доска и список задач SHALL показывать один проект — текущий. Текущий проект SHALL задаваться параметром `project` в
|
||
адресе `/app/board` и `/app/issues`; без параметра — последний выбранный в этом браузере (`localStorage`), если он есть
|
||
в `GET /projects`, иначе первый из `GET /projects`; выбранный проект записывается в адрес без новой записи истории.
|
||
Проекта из адреса нет в `GET /projects` — страница SHALL показывать «проект <метка> не найден» и выпадающий список
|
||
проектов вместо данных. Проектов нет — доска и список SHALL показывать приглашение создать проект («+ Новый проект…»).
|
||
Переходы «Доска» / «Задачи» SHALL сохранять текущий проект. Карточка задачи (`/app/issues/{key}`) от проекта не зависит.
|
||
|
||
Доска SHALL загружать `GET /board?project=<текущий>`; «Обновить из Jira» — как прежде, `POST /refresh {full: true}`,
|
||
обновляет все проекты. Раскладка, дорожки и фильтры доски в `localStorage` SHALL храниться отдельно для каждого проекта;
|
||
у проекта `AWPCA` — на прежних ключах (раскладка, сделанная до проектов, сохраняется). Фильтр спринтов SHALL
|
||
показываться, только если хотя бы у одной своей задачи снимка (`neighbor = false`) есть спринт; иначе — «колонки
|
||
«Спринт» нет — показаны все задачи».
|
||
|
||
Форма «Новый проект» (пункт «+ Новый проект…» выпадающего списка) SHALL открываться окном поверх страницы: метка,
|
||
название, номер доски Jira (необязательно; подсказка «scrum или kanban определится сам»). «Создать» — `POST /projects`
|
||
с автором `viewer`; ошибка хаба 409/422 — текст `detail` рядом с кнопкой, окно остаётся открытым; успех — окно
|
||
закрывается, текущим становится новый проект, доска подхватывает пакет обновления (`refresh` автора `viewer`) и
|
||
показывает его ход.
|
||
|
||
#### Scenario: Первый вход после выкатки
|
||
- **WHEN** открыт `/app/board` без `project`, в `localStorage` выбора нет, проекты `AWPCA` и `STOCKS_DRRK`
|
||
- **THEN** адрес — `/app/board?project=AWPCA`, доска — `GET /board?project=AWPCA` с прежней раскладкой карточек
|
||
|
||
#### Scenario: Переключение проекта
|
||
- **WHEN** на доске `AWPCA` в выпадающем списке выбран `STOCKS_DRRK`, затем открыт раздел «Задачи»
|
||
- **THEN** доска — `GET /board?project=STOCKS_DRRK` со своей раскладкой; адрес «Задач» — `/app/issues?project=STOCKS_DRRK`
|
||
|
||
#### Scenario: Неизвестный проект в адресе
|
||
- **WHEN** открыт `/app/issues?project=NOPE`
|
||
- **THEN** «проект NOPE не найден» и список проектов; запроса `GET /issues` нет
|
||
|
||
#### Scenario: Создание проекта из формы
|
||
- **WHEN** в форме введены `STOCKS_DRRK`, «Запасы ДРРК», доска пусто; нажато «Создать»
|
||
- **THEN** `POST /projects {label: "STOCKS_DRRK", name: "Запасы ДРРК", author: "viewer"}`; текущий проект — `STOCKS_DRRK`;
|
||
шапка доски показывает «пакет #N выполняется»
|
||
|
||
#### Scenario: Метка занята
|
||
- **WHEN** в форме введена метка `awpca`, хаб ответил 409
|
||
- **THEN** окно открыто, рядом с «Создать» — текст ошибки хаба
|
||
|
||
#### Scenario: Канбан-проект
|
||
- **WHEN** текущий проект — `STOCKS_DRRK`, ни у одной своей задачи снимка нет спринта (у соседа из `AWPCA` спринт есть)
|
||
- **THEN** вместо фильтра спринтов — «колонки «Спринт» нет — показаны все задачи»
|
||
|
||
## MODIFIED Requirements
|
||
|
||
### Requirement: Оболочка и адреса
|
||
Приложение SHALL открываться под префиксом `/app/` и иметь страницы `/app/board` (доска связей), `/app/issues` (список
|
||
задач) и `/app/issues/{key}` (карточка задачи — окно поверх страницы, требование «Карточка задачи»); `/app` и `/app/` SHALL вести на `/app/board`, неизвестный путь —
|
||
на страницу «не найдено» со ссылками на разделы. Верхняя панель SHALL содержать выпадающий список проектов рядом с
|
||
названием («<метка> — <название>», текущий отмечен, в конце «+ Новый проект…»; требование «Проект в приложении»),
|
||
переходы «Доска», «Задачи» и действие «Сменить токен». Неожиданная ошибка отрисовки страницы SHALL показываться
|
||
сообщением с кнопкой «Перезагрузить», не пустым экраном.
|
||
|
||
#### Scenario: Переход между разделами
|
||
- **WHEN** на доске выбран раздел «Задачи»
|
||
- **THEN** адрес — `/app/issues` с текущим проектом, показан список задач; «назад» возвращает на доску
|
||
|
||
### Requirement: Список задач
|
||
Страница `/app/issues` SHALL показывать задачи текущего проекта из `GET /issues?project=<текущий>` таблицей: ключ (открывает карточку задачи окном поверх списка), тема,
|
||
тип, статус Jira, исполнитель, спринт, срок (`planned_end`, иначе `duedate`), эпик (имя эпика, иначе ключ), вид работы,
|
||
признак «сосед» (относительно проекта); статуса по факту в списке нет. Фильтры SHALL соответствовать параметрам `GET /issues` (спринт, исполнитель, вид
|
||
работы, статус Jira, метка, эпик, только соседи, поиск по ключу или теме, скрыть закрытые), храниться в query-строке
|
||
адреса вместе с `project` и применяться сервером; варианты выпадающих списков SHALL браться из снимка `GET /board?project=<текущий>`; значение фильтра из адреса, которого нет среди
|
||
вариантов, SHALL показываться в списке с пометкой «(нет на доске)». Флажок «скрыть закрытые» SHALL
|
||
быть включён по умолчанию (в адресе ничего), снятый — `closed=1` в адресе; включённый — запрос с `hide_closed=1`,
|
||
кроме случая, когда в фильтре «Статус Jira» выбран статус из `closed_statuses`. Параметр `fact_status` в адресе
|
||
игнорируется. Задачи SHALL
|
||
загружаться порциями по 50 строк; «Показать ещё» SHALL быть доступна, пока последняя порция полная.
|
||
|
||
#### Scenario: Фильтр в адресе
|
||
- **WHEN** выбран спринт «AWPCA_Спринт 2» и исполнитель
|
||
- **THEN** адрес содержит `project=`, `sprint=` и `assignee=`, таблица — результат `GET /issues` с этими параметрами; открытие этого
|
||
адреса в новой вкладке показывает ту же выборку
|
||
|
||
#### Scenario: Конец списка
|
||
- **WHEN** вторая порция вернула 17 задач
|
||
- **THEN** в таблице 67 задач, «Показать ещё» не показана
|
||
|
||
#### Scenario: Фильтр по закрытому спринту
|
||
- **WHEN** открыт адрес `/app/issues?project=AWPCA&sprint=AWPCA_Спринт 0`, а в снимке доски такого спринта нет
|
||
- **THEN** выпадающий список «Спринт» показывает «AWPCA_Спринт 0 (нет на доске)» выбранным, таблица — по этому фильтру
|
||
|
||
#### Scenario: Карточка поверх списка
|
||
- **WHEN** список отфильтрован по спринту, прокручен и догружен «Показать ещё», открыта карточка задачи и окно закрыто
|
||
- **THEN** адрес списка с тем же фильтром, в таблице те же строки, прокрутка та же
|
||
|
||
#### Scenario: Закрытые скрыты по умолчанию
|
||
- **WHEN** открыт `/app/issues`, в зеркале задачи в статусах «В работе», «Готово», «Снято»
|
||
- **THEN** флажок «скрыть закрытые» включён, запрос `GET /issues` с `hide_closed=1`, в таблице только «В работе»; после
|
||
снятия флажка адрес содержит `closed=1`, в таблице все три
|
||
|
||
#### Scenario: Выбран закрытый статус
|
||
- **WHEN** флажок «скрыть закрытые» включён и в «Статус Jira» выбрано «Готово»
|
||
- **THEN** запрос `GET /issues?status=Готово` без `hide_closed`, в таблице задачи в статусе «Готово»
|