Module: Ecoportal::API::GraphQL::Model::Template::Read

Defined in:
lib/ecoportal/api/graphql/model/template/read.rb

Overview

Live read for Instance.load/StagedExecutor's between-phase re-reads.

*** PLATFORM FACT — workflow-first, DO NOT collapse onto page.stages alone ***

Ported verbatim (query shape) from a downstream script repo's template-fields read service, itself verified live 2026-08-01 and re-confirmed 2026-08-09: a command-bus-built template's PAGE projection can be EMPTY while its WORKFLOW carries the full structure (Workflow Builder / this gem's own updatePageTemplate writes workflow stage/section/field docs; the page projection does not always materialise from them), whereas a web-editor-built template DOES project page stages. Read workflow { stages { sections } } FIRST; fall back to the page projection only when the workflow yields nothing — never the other way round.

SplitSection has NO dataFields — leftDataFields/rightDataFields only. Forces are read from workflow.stages.forces only (18_template_editor_save_path.md section A.1, TemplateStageFields.forces); the page projection carries no forces at all, so there is no fallback for that part of the read.

Helper's own five fields -- id name filePath script contentB64 -- are LIVE- VERIFIED (not merely mirrored from the write side): a downstream script repo's template force-read case selects helpers { id name filePath script contentB64 } on exactly this same forces field, and that read has run live against pre_prod across 47 templates (that file's own header, lines 29-31/90). Use these five with confidence.

UNVERIFIED against a live schema this session: any Force field beyond the Helper sub-fields cited above (e.g. a top-level script alongside customScript, or a plain url/contentB64 on the force itself) -- cite before relying on anything not confirmed above.

Constant Summary collapse

STRUCTURE_QUERY =
"query TemplateModelRead($id: ID!) {\n  currentOrganization {\n    page(id: $id, showHiddenData: true) {\n      __typename\n      ... on BasicPage {\n        id\n        name\n        patchVer\n        workflow { stages { ...wfStage } }\n        sections { ...sectionFields }\n      }\n      ... on PhasedPage {\n        id\n        name\n        patchVer\n        workflow { stages { ...wfStage } }\n        stages { id name ordering sections { ...sectionFields } }\n      }\n    }\n  }\n}\n\nfragment wfStage on Stage {\n  id\n  name\n  ordering\n  sections { ...sectionFields }\n  forces {\n    id\n    name\n    customScript\n    url\n    contentB64\n    bindings { name referenceId }\n    helpers { id name filePath script contentB64 }\n  }\n}\n\nfragment sectionFields on SectionUnion {\n  __typename\n  ... on ContentSection {\n    id\n    heading\n    dataFields { ...tf }\n  }\n  ... on SplitSection {\n    id\n    heading\n    leftHeading\n    rightHeading\n    leftDataFields { ...tf }\n    rightDataFields { ...tf }\n  }\n}\n\nfragment tf on DataFieldUnion {\n  __typename\n  ... on DataFieldsInterface {\n    id\n    label\n    description\n    tooltip\n    hidden\n    required\n  }\n  ... on Select {\n    options { id value name }\n  }\n}\n".freeze

Class Method Summary collapse

Class Method Details

.call(client, id) ⇒ Hash

Returns the raw page doc (string keys, as the server sent it).

Parameters:

  • client (Ecoportal::API::GraphQL) —

    the top-level gem client (has #client / .http_client, matching every other read in this gem).

  • id (String) —

    the template's page id.

Returns:

  • (Hash) —

    the raw page doc (string keys, as the server sent it).



114
115
116
117
118
119
120
# File 'lib/ecoportal/api/graphql/model/template/read.rb', line 114

def call(client, id)
  raw  = http(client).execute(STRUCTURE_QUERY, variables: { id: id })
  page = raw.dig('data', 'currentOrganization', 'page')
  raise "Template '#{id}' not readable as page" unless page

  page
end

.stages(page) ⇒ Array<Hash>

Fields in document order, workflow-first, exactly TemplateFieldsRead.fields's own semantics (kept as a module method so StagedExecutor's re-read cross-checks can call it against a freshly re-fetched page doc without going through the whole Instance construction).

Returns:

  • (Array<Hash>) —

    each entry carries stage_id/section_id/section_side alongside the field's own doc, in document order.



129
130
131
132
133
134
# File 'lib/ecoportal/api/graphql/model/template/read.rb', line 129

def stages(page)
  from_workflow = Array(page.dig('workflow', 'stages'))
  return from_workflow unless from_workflow.empty?

  fallback_stages(page)
end