Merge: t-paliad-344 — fix stale deadlines.rule_id refs + builder null-guards (m/paliad#154)
Some checks failed
Paliad CI gate / build (push) Has been cancelled
Paliad CI gate / test-go (push) Has been cancelled
Paliad CI gate / deploy (push) Has been cancelled

This commit is contained in:
mAi
2026-05-28 00:48:17 +02:00
4 changed files with 18 additions and 3 deletions

View File

@@ -815,6 +815,13 @@ async function loadScenario(id: string): Promise<void> {
setSaveState("error");
return;
}
// Defensive: Go's encoding/json serialises a nil slice as `null`, not
// `[]`. The server initialises these arrays today, but normalising on
// the client too means a future regression (or an older deployed
// build) can't crash renderCanvas with `null.filter(...)`.
if (!Array.isArray(deep.proceedings)) deep.proceedings = [];
if (!Array.isArray(deep.events)) deep.events = [];
if (!Array.isArray(deep.shares)) deep.shares = [];
state.active = deep;
state.pending = {};
writeScenarioToUrl(id);

View File

@@ -265,7 +265,7 @@ func (s *DeadlineService) ListVisibleForUser(ctx context.Context, userID uuid.UU
query := `
SELECT f.id, f.project_id, f.title, f.description, f.due_date, f.original_due_date,
f.warning_date, f.source, f.rule_id, f.rule_code, f.custom_rule_text, f.status, f.completed_at,
f.warning_date, f.source, f.sequencing_rule_id, f.rule_code, f.custom_rule_text, f.status, f.completed_at,
f.caldav_uid, f.caldav_etag, f.notes, f.created_by,
f.created_at, f.updated_at,
f.approval_status, f.pending_request_id, f.approved_by, f.approved_at,

View File

@@ -1247,7 +1247,7 @@ func (s *ProjectionService) collectActualsForOverrides(
}
var dRows []drow
scopeFilter := scopeProjectIDFilter("d", "project_id", projectID, directOnly)
q := `SELECT d.rule_id, d.rule_code, d.due_date, d.completed_at, d.status
q := `SELECT d.sequencing_rule_id AS rule_id, d.rule_code, d.due_date, d.completed_at, d.status
FROM paliad.deadlines d
WHERE ` + scopeFilter
if err := s.db.SelectContext(ctx, &dRows, q, projectID); err != nil {

View File

@@ -204,7 +204,15 @@ func (s *ScenarioBuilderService) GetScenarioDeep(ctx context.Context, userID, sc
return nil, ErrScenarioBuilderNotVisible
}
deep := &BuilderScenarioDeep{BuilderScenario: *sc}
deep := &BuilderScenarioDeep{
BuilderScenario: *sc,
// Initialise to empty so the JSON response always carries arrays,
// not null — the builder frontend's renderCanvas calls .filter on
// proceedings/events unconditionally once state.active is set.
Proceedings: []BuilderProceeding{},
Events: []BuilderEvent{},
Shares: []BuilderShare{},
}
if err := s.db.SelectContext(ctx, &deep.Proceedings, `
SELECT id, scenario_id, proceeding_type_id, primary_party, scenario_flags,