Skip to content

tool_print

A visual print-layout / report designer for a section: arrange a record's components into a paginated document and print it. The layout is a reusable, per-section template saved in the ontology. UI-driven; it has no remotely callable server methods (it prints from the browser).

What it does / why & when to use it

tool_print is a section toolbar button (like tool_export) that opens a document editor. The cataloguer drags a section's components into a page and the tool renders real record data into a print-ready document that can span multiple A4/A3/Letter pages. The arrangement is saved as a named template and reused for every record of that section; at print time the current record (in edit mode) or the records matching the user's current filter (in list mode) fill the template.

It exists because nothing else produces a positioned, paginated, record-driven document: tool_export makes flat tables, tool_tr_print only handles transcripts. tool_print is for catalogue cards, study sheets, index pages and full transcriptions — anything that needs components laid out on paper with continuous flow.

The layout model is a document flow of grid rows (a word-processor-with-a-grid, not free-floating boxes):

  • The document is an ordered, top-to-bottom stack of rows; each row is a horizontal grid of cells (1…N, adjustable widths); each cell holds one component (or free text, or is empty).
  • Rows stack and paginate automatically — pages are generated by the content, not added by hand.
  • A full-width table (portal/relation) or a long text_area transcription splits across pages, and everything after it reflows with no gaps. So a record whose Bibliografía has 2 rows and one whose has 25 rows both keep the same offset from the end of the table — the following components simply move down / onto later pages.

Use it when: you need a printable, reusable, per-section report where component data flows and paginates (a numismatic catalogue card, an oral-history interview sheet with a multi-page transcription, a bibliography index). Not for flat tabular CSV (that is tool_export) or VTT subtitles (tool_subtitles).

Concrete scenario: a numismatics catalogue. The editor opens Cecas record 2, presses Print, and builds a template: a 3-cell header row (Id · centred title · Localización), a full-width Información pública row (a long description), and a full-width Bibliografía table. They drop the relation into a cell, drill into it in the left panel, and drop Página / Número onto the table to add columns. They name the template "Catalogue card", Guardar, and print. Opening another record reuses the template; the Bibliografía table and the description grow or shrink per record and the document repaginates.

How it works (server + client)

Server. tools/tool_print/ ships no server/ package — confirmed: there is no tools/tool_print/server/ directory. All persistence rides the generic core data API (dd_core_api.save/read on sections dd25/dd625) — the same path tool_export presets use — so there is no bespoke tool endpoint, no bespoke table, and no PDF-generation server action on this engine.

Storage (ontology). Templates are records of section dd25, with the whole layout blob stored in a dd625 component_json. The blob itself carries the template metadata (name, target_section_tipo, owner_user_id, visibility) — the tool does not rely on separate name/user/public components (only dd625 is required to be a child of dd25). The picker reads every dd25 record's blob and filters client-side by target section + owner/public.

Caller context (js/tool_print.js). init() captures the calling section's source / sqo / target_section_tipo / mode and a preview_section_id (the record to fill boxes with). get_record_ids() resolves what to print: the single edit record, or the records matching the list filter SQO (respecting limit/offset).

The layout engine (js/flow_engine.js). One engine serves both the on-screen editor and print. layout_flow(self, ctx) lays the flow.rows[] into a content column and paginates, generating .print_page nodes:

  • each row is rendered as a flex of cells; a cell's component value is produced by the shared render_box_content (so the literal / relation-table / cell-cache rendering is identical to what the editor shows);
  • when a row doesn't fit, splittable_container() decides: a table (<tbody> rows) or a long text block (paragraphs) is split at its unit boundaries via split_long_row() — tables repeat the header, text continues on the next page; anything else moves whole to a fresh page;
  • the ctx injects the unit conversion (editor = mm·PX_PER_MM·zoom in px; print = physical mm) and a measure(node) function, so the page breaks are computed in the right units in either mode.

The editor (js/canvas_tool_print.js + js/render_tool_print.js). render_canvas() runs layout_flow then decorate_editor() adds the editor chrome to the generated pages: per-row grip / ▲▼ reorder / +cell / ✕, an insert row / spacer bar, per-cell and drag-to-resize dividers, selection, and the Delete key removing the selected cell/row. The left palette is the section's component list with a replace-and-breadcrumb drill-down for relations; dropping a component into a cell fills it, onto a table cell adds a related field as a column (a non-matching field replaces the cell), and onto the page appends a new row. The right inspector edits the selected row/cell: cell width %, row gap, font / alignment / text color / border, show-label, show-table-header, and the per-table column manager (drag-reorder, width, header rename/hide). The toolbar carries the template picker + name field, New / Guardar / Guardar como… / Delete, Add row / Add text / Add spacer, snap, preview-with-record, zoom and Print.

Printing. do_print() resolves the record ids, runs the same layout_flow in mm, injects an @page size, hides the editor and calls window.print(). Because editor and print share one engine, paper output matches the on-screen preview page-for-page.

Data model (the dd625 blob, schema_version 2)

{
  schema_version: 2, kind: "tool_print_layout", uid, name,
  target_section_tipo, visibility: "user"|"public", owner_user_id, units: "mm",
  page_defaults: { size, width_mm, height_mm, orientation, margins_mm },
  style_defaults: { font_family, font_size_pt, align, valign, text_color, border_show, border_color },
  flow: {
    rows: [
      { id, kind: "row", space_after_mm,
        cells: [
          { id, width: 0.25,                 // fraction of the content column
            block: {                          // one component | static text | empty
              type: "component"|"static_text"|"empty",
              component_ref: { tipo, section_tipo, model, view, label_snapshot }, path,
              render: { value_view, lang, multivalue },
              show_label, table_columns, show_table_header, style: { … }, static: { text }
            } } ] },
      { id, kind: "spacer", height_mm }       // deliberate whitespace
    ]
  }
}

A full-width component (a long table or a transcription) is simply a 1-cell row. Pages are not stored — they are regenerated from the flow per record at render/print time.

Actions & options

tool_print exposes no API actions:

apiActions Form Notes
(no server module) UI-only. Printing happens in the browser; saving/loading templates uses the generic core data API on dd25/dd625.

There is no server-side PDF-generation action on this engine — printing happens entirely in the browser via window.print().

Usage notes & limitations

  • Per-section template: the design applies to every record of the target_section_tipo; the current record's data fills it at print time. Templates are per-user with a public flag.
  • Full text: component_text_area is truncated to ~220 chars in list mode, so text areas render in edit mode for the full value (and split across pages for long transcriptions).
  • Cell colors are paper colors: the page is white, so component values and editor chrome on the page use fixed/inherited colors, never theme tokens (which would turn light-gray on the white page in dark mode).
  • Not migrated: schema_version 2 is the document-flow model; older test blobs are not migrated.