⟨/⟩ Nts/35_ChangeRequests/DOC_CR_2026_10_30_CalcConfirmAndStickyActions.cs

137 строк · в начало

using Rugrid.Sdaid.Notation.Documents;

namespace Rugrid.Sdaid.Epas.Nts.ChangeRequests
{
    /// <summary>
    /// Модалка подтверждения операции «Сохранить и рассчитать» была чисто информационной и
    /// перекрывала кнопки действий; кнопки действий на длинной странице уезжали за пределы
    /// экрана. Решение: подтверждение — самогаснущее уведомление, лог ошибок — постоянная
    /// ссылка у поля «Ошибка», кнопки действий закреплены у угла экрана.
    /// </summary>
    public class DOC_CR_2026_10_30_CalcConfirmAndStickyActions : IChangeRequestDocument, IHasStructuralLinks, IFolder<NtsChangeRequestsFolder>
    {
        public SdaidLink[] Links => new[]
        {
            Rel.Uses<Rugrid.Sdaid.Epas.Nts.Ui.DOC_VehicleCard>(),
        };

        public static string _refName = "CR 2026-10-30: модалка подтверждения расчёта и закрепление кнопок действий";

        public string Name => "Модалка подтверждения расчёта и закрепление кнопок действий";

        public string Description =>
            @"Модалка подтверждения операции «Сохранить и рассчитать» в карточке ТС чисто
            информационная (не запрашивает решение пользователя) и перекрывает собой кнопки
            действий «Сохранить и рассчитать»/«Отменить», требуя ручного закрытия. Кнопки действий
            на длинной странице уезжают за пределы экрана — не закреплены.";

        public string Version => "0.2";
        public string Status => "done";
        public string[] Comments => new string[0];

        public static string Source = """"
            ## Источник (как есть)

            По итогам ручного тестирования карточки ТС:

            1. При нажатии «Сохранить и рассчитать» всплывает модалка подтверждения операции.
               Модалка чисто информационная — не запрашивает у пользователя решения, просто
               сообщает о ходе/результате. При этом она перекрывает собой кнопки «Сохранить и
               рассчитать» и «Отменить» внизу карточки — их не видно, пока модалка не закрыта.
               Модалку приходится закрывать вручную, хотя сообщать ей, по сути, нечего, на что
               нужно было бы реагировать.
            2. Кнопки действий («Сохранить и рассчитать», «Отменить») на длинной странице (много
               полей, как у специальных автомобилей с развёрнутым блоком «Результаты расчёта»)
               уезжают за пределы видимой области экрана при прокрутке — к ним приходится
               прокручивать страницу отдельно.
            """";

        public static string Analysis = """"
            ## Разбор

            Решение опирается на то, что уже умеет окно операции (`openOperation()`,
            `Ntr/65_Ui/html/shell.js:729-749` до правки): показывало два шага («Сохранение» →
            «Расчёт») и при ошибке — ссылку «Открыть лог ошибок», при успехе — просто текст
            «Расчёт выполнен». То есть содержательна только ссылка на лог при ошибке; текст
            успеха и сам пошаговый индикатор — чистое дублирование того, что уже видно по
            бейджам «Статус расчёта»/«Статус обработки» на карточке.

            **По п. 1 (модалка).** Решение (а) из названных направлений: самогаснущее
            уведомление. В кодовой базе уже есть готовый механизм — `showNotice()`
            (`shell.js:718-727`), используемый, например, для «Сведения о ТС обновлены из АИС
            ОИА ПЭО». Переиспользуется без изменений. Единственная содержательная часть прежнего
            окна — ссылка на лог ошибок — переносится в постоянное место: рядом с полем «Ошибка»
            в группе «Результаты расчёта», видна всё время, пока ошибка актуальна, а не только
            в момент, сразу следующий за нажатием «Сохранить и рассчитать». Это и есть направление
            (б) в применении не к дате/времени расчёта, а к самому логу — тот же принцип
            («сигнал — постоянная часть экрана карточки, а не всплывающее окно»), применённый
            к действительно содержательной части, а не к тексту успеха.

            **По п. 2 (закрепление кнопок).** Подтверждён прецедент `.footer` (`shell.css:352`) —
            `.actions` закрепляется тем же приёмом. Конфликта с `.op-panel` больше нет: он
            упраздняется вместе с окном операции (п. 1), остаётся только `.log-drawer` (открывается
            по клику, не висит на экране постоянно) — пересечения с закреплёнными кнопками нет.
            """";

        public static string BlastRadius = $""""
            ## Blast radius

            ### Спецификация

            | Документ | Правка |
            |---|---|
            | {SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Ui.DOC_VehicleCard>()} | раздел «Поведение»: окно операции → самогаснущее уведомление + постоянная ссылка на лог у поля «Ошибка»; кнопки действий закреплены у угла экрана |

            ### Прототип

            | Файл | Правка |
            |---|---|
            | `Ntr/65_Ui/html/shell.js` | обработчик `[data-save-calc]` — `openOperation(...)` заменён на `showNotice(...)`; функция `openOperation()` удалена; `setStatus()` добавляет иконку `.log-icon.calc` рядом с бейджем «Статус расчёта», только при статусе «Успешно выполнен»; `setError()` добавляет отдельную иконку `.log-icon.error` рядом с полем «Ошибка», только при ошибке — условия показа не пересекаются |
            | `Ntr/65_Ui/html/shell.css` | `.actions` — `position: fixed` по образцу `.footer`; CSS-классы `.op-panel`/`.op-head`/`.op-steps`/`.op-step`/`.op-arrow`/`.op-mark`/`.op-desc` удалены (не используются); `.op-close` сохранён — общий класс для крестика закрытия, используется `openConfirm`/`openLog`; добавлены `.log-icon`/`.log-icon.calc`/`.log-icon.error` |
            """";

        public static string Plan = """"
            ## План

            1. `shell.css` — `.actions` закреплена у угла экрана; удалены неиспользуемые
               `.op-panel`-классы.
            2. `shell.js` — обработчик сохранения вызывает `showNotice()` вместо `openOperation()`;
               `openOperation()` удалена; `setError()` добавляет постоянную ссылку на лог.
            3. `VehicleCard.cs` — раздел «Поведение» согласован с новым поведением.
            4. Собрать (`dotnet build`, `build-html.cmd`).
            5. Зафиксировать «Итог».
            """";

        public static string Acceptance = """"
            ## Acceptance criteria

            - **AC-1.** После «Сохранить и рассчитать» появляется самогаснущее уведомление
              («Расчёт выполнен» при успехе, «Ошибка расчёта...» при ошибке), не блокирующее
              экран и не требующее закрытия.
            - **AC-2.** Две отдельные иконки лога, не одна общая ссылка, с непересекающимися
              условиями показа: (а) иконка лога расчёта рядом с бейджем «Статус расчёта» — видна
              только при статусе «Успешно выполнен» (журнала формул без успешного расчёта не
              существует); (б) иконка лога ошибок рядом с полем «Ошибка» — видна, только пока есть
              ошибка.
            - **AC-3.** Кнопки «Сохранить и рассчитать» и «Отменить» видны на экране при любой
              прокрутке длинной карточки, не уезжают за пределы видимой области.
            """";

        public static string Result = """"
            ## Итог

            Реализовано. `showNotice()` переиспользован для подтверждения; окно операции
            (`openOperation()`, `.op-panel` и связанные CSS-классы) удалено; `.actions` закреплена
            у угла экрана по образцу `.footer`. Доступ к логу — две отдельные иконки (`.log-icon
            .calc` у статуса расчёта — только при «Успешно выполнен»; `.log-icon .error` у поля
            «Ошибка» — только при ошибке), условия показа не пересекаются. Итерация решения прошла
            путь ссылка-только-при-ошибке (ошибочно, поймано пользователем) → общая ссылка при
            любом исходе → две раздельные иконки → иконка лога расчёта сужена до случая реального
            успеха (была видна и при ошибке — тоже поймано пользователем). Иконки выровнены по
            DOM-паттерну `.hint`/`addHintSpan` (прямые дети `.row`, не вложены в `.val`); иконка
            лога расчёта — зелёная галочка `✓` (`var(--green)`), не произвольная буква. Сборка и
            генерация сайта прошли без ошибок.
            """";
    }
}