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 viasplit_long_row()— tables repeat the header, text continues on the next page; anything else moves whole to a fresh page; - the
ctxinjects the unit conversion (editor =mm·PX_PER_MM·zoomin px; print = physicalmm) and ameasure(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 apublicflag. - Full text:
component_text_areais 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.
Related
tool_export— flat tabular export (the data path / preset modeltool_printmirrors).tool_subtitles,tool_tr_print— transcription-specific surfaces.- Creating new tools, Server contract, Security.