From 110f128661bca6929c4ee67595030bf6fd097b9a Mon Sep 17 00:00:00 2001 From: Jeffrey Smith Date: Thu, 2 Apr 2026 22:21:38 +0000 Subject: [PATCH] Fix workflow entry token resolution and fieldset submit guard RenderWorkflow() was passing the route param (instance ID) as the entry token to the template JS. The advance API needs the actual entry token from the instance. Now resolves from inst.EntryToken and checks the ?token= query param from the landing page redirect. Also fix submitForm() early-return guard that blocked progressive forms using fieldsets (checked FORM_TPL.fields but not .fieldsets). Co-Authored-By: Claude Opus 4.6 (1M context) --- server/pages/pages.go | 23 +++++++++++++++++++---- server/pages/templates/workflow.html | 2 +- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/server/pages/pages.go b/server/pages/pages.go index 2cd2bc3..486e436 100644 --- a/server/pages/pages.go +++ b/server/pages/pages.go @@ -673,18 +673,27 @@ type WorkflowLandingPageData struct { func (e *Engine) RenderWorkflow() gin.HandlerFunc { return func(c *gin.Context) { ctx := c.Request.Context() - entryToken := c.Param("id") + routeID := c.Param("id") sessionID := c.GetString("session_id") sessionName := "Visitor" instanceName, _, _ := e.loadBranding() - // Try to load instance by entry token, then by ID + // Try to load instance — the route param may be an instance ID + // or an entry token. Also check the ?token= query param. var inst *models.WorkflowInstance if e.stores.Workflows != nil { - inst, _ = e.stores.Workflows.GetInstanceByToken(ctx, entryToken) + // First try: query param token (from landing page redirect) + if qToken := c.Query("token"); qToken != "" { + inst, _ = e.stores.Workflows.GetInstanceByToken(ctx, qToken) + } + // Second try: route param as entry token if inst == nil { - inst, _ = e.stores.Workflows.GetInstance(ctx, entryToken) + inst, _ = e.stores.Workflows.GetInstanceByToken(ctx, routeID) + } + // Third try: route param as instance ID + if inst == nil { + inst, _ = e.stores.Workflows.GetInstance(ctx, routeID) } } @@ -730,6 +739,12 @@ func (e *Engine) RenderWorkflow() gin.HandlerFunc { } } + // Resolve the actual entry token from the instance (used by JS API calls) + entryToken := "" + if inst.EntryToken != nil { + entryToken = *inst.EntryToken + } + e.Render(c, "workflow.html", PageData{ Surface: "workflow", InstanceName: instanceName, diff --git a/server/pages/templates/workflow.html b/server/pages/templates/workflow.html index 13705fa..d4e5108 100644 --- a/server/pages/templates/workflow.html +++ b/server/pages/templates/workflow.html @@ -398,7 +398,7 @@ } window.submitForm = async function() { - if (!FORM_TPL || !FORM_TPL.fields) return; + if (!FORM_TPL || (!FORM_TPL.fields && !FORM_TPL.fieldsets)) return; var btn = document.getElementById('formSubmitBtn'); if (btn) btn.disabled = true;