Персист модалок: черновики, восстановление после F5, предупреждение при выходе (#30)
Модалки по жёлтым кнопкам теряли введённое при случайном клике мимо окна. **Формы создания** (типы заявок, доступ к заявкам, маршруты, шаги маршрута) - Черновик полей хранится в localStorage (useFormDraft) и переживает закрытие окна, «Отмену» и F5. - Окно, открытое в момент F5, открывается снова (usePersistedOpen); закрытие сбрасывает только признак, черновик остаётся. - Черновик стирается после успешного сохранения или кнопкой «Очистить» в подвале. **Формы редактирования** - Не персистятся — открываются с данными сервера. - При выходе с несохранёнными правками (крестик, «Отмена», клик мимо) — диалог «Закрыть без сохранения?» (isDirty в FormModal). **Устойчивость к старым данным в localStorage** - coerceStored приводит сохранённое значение к форме текущего дефолта по полям: новое поле — дефолт, удалённое отбрасывается, значение другого типа и null заменяются дефолтом. Покрыто тестами. **Прочее** - Modal и ConfirmDialog рендерятся порталом в body поверх шапки SharePoint — на живой странице верх высокого окна уезжал под шапку. - Убраны Sass-предупреждения mixed-decls в Card.module.scss. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz> Reviewed-on: http://git.tnsu.kz/gorbenko.pavel/tnsu-approval-route/pulls/30
This commit was merged in pull request #30.
This commit is contained in:
+4
-3
@@ -1,6 +1,7 @@
|
||||
using FluentResults;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Tnsu.ApprovalRoute.Application.Common;
|
||||
using Tnsu.ApprovalRoute.Application.Common.Errors;
|
||||
using Tnsu.ApprovalRoute.Application.Common.Interfaces;
|
||||
using Tnsu.ApprovalRoute.Domain.Entities;
|
||||
@@ -82,7 +83,7 @@ public sealed class TemplateRouteStepService(
|
||||
|
||||
if (await HasDuplicateHeadTypeAsync(route.Id, r.HeadType, r.Conditions, r.ConditionsLogic, excludeId: null, cancellationToken))
|
||||
return Result.Fail<TemplateRouteStepDto>(new ConflictError(
|
||||
$"В маршруте уже есть шаг с типом руководителя «{r.HeadType}» и таким же условием появления — второй такой шаг недопустим."));
|
||||
$"В маршруте уже есть шаг с типом руководителя «{StepLabels.Of(r.HeadType!.Value)}» и таким же условием появления — второй такой шаг недопустим."));
|
||||
|
||||
var entity = new TemplateRouteStep
|
||||
{
|
||||
@@ -141,7 +142,7 @@ public sealed class TemplateRouteStepService(
|
||||
|
||||
if (await HasDuplicateHeadTypeAsync(route.Id, r.HeadType, r.Conditions, r.ConditionsLogic, excludeId: entity.Id, cancellationToken))
|
||||
return Result.Fail<TemplateRouteStepDto>(new ConflictError(
|
||||
$"В маршруте уже есть шаг с типом руководителя «{r.HeadType}» и таким же условием появления — второй такой шаг недопустим."));
|
||||
$"В маршруте уже есть шаг с типом руководителя «{StepLabels.Of(r.HeadType!.Value)}» и таким же условием появления — второй такой шаг недопустим."));
|
||||
|
||||
entity.OrderNo = r.OrderNo;
|
||||
entity.ExecutorEmail = r.ExecutorEmail;
|
||||
@@ -210,7 +211,7 @@ public sealed class TemplateRouteStepService(
|
||||
|
||||
if (await HasDuplicateHeadTypeAsync(route.Id, headType, conditions, conditionsLogic, excludeId: entity.Id, cancellationToken))
|
||||
return Result.Fail<TemplateRouteStepDto>(new ConflictError(
|
||||
$"В маршруте уже есть шаг с типом руководителя «{headType}» и таким же условием появления — второй такой шаг недопустим."));
|
||||
$"В маршруте уже есть шаг с типом руководителя «{StepLabels.Of(headType!.Value)}» и таким же условием появления — второй такой шаг недопустим."));
|
||||
|
||||
entity.OrderNo = r.OrderNo ?? entity.OrderNo;
|
||||
entity.ExecutorEmail = executorEmail;
|
||||
|
||||
Reference in New Issue
Block a user