A Template is a named batch of pre-filled entries bound to a Trackable: a recipe on Diet, a circuit on the Set. A trackable’s templates are made, edited and deleted in the Templates section of its page, since the trackable is what gives their lines meaning. Picked in the trackable’s form, a template of one line fills the form, the start and stop, time and note staying the form’s own; a template of several lines stamps out one editable row per line, which are tweaked or skipped and then logged inside one entry that stands in for them: it names the template, holds no value of its own, and reads as the template’s name wherever entries are listed (Egg & Cheese, holding the egg and the cheddar). Each row is an entry of its own and counts as one (Entry, Reading). Opened from any list, the entry standing in shows what it holds instead of a value form: for a Trackable that logs items with an amount, its totals and its items as the day’s Diet shows them; otherwise its parts in a list. A part opens to be changed or removed, another is added into it (a slice of tomato), and the whole is deleted, asking whether what it holds goes too. None of this changes the template. Issues skip it: it has nothing of its own to fill in, and its parts are checked as entries of their own.
A template is not a catalog item: its lines carry the trackable’s fields, reps and weight or a food and its amount. A recipe is a template. Chad’s Egg & Cheese is one on Diet, and logged it is a Diet entry holding his egg and his cheddar, so each counts as itself in every total, which a food computed from its ingredients never could.
Definition
| table | columns |
|---|---|
template | name, trackable_id (its trackable), weighed (what the whole weighs once made, optional) |
template_line | template_id, entity_id (the item it names, optional), field_values, sort_order, trackable_id (optional), depth, stands_for (the template a line stands in for, its lines beneath it; optional) |
A line is a pre-filled entry. entity_id is a real foreign key to the item the line names, so “which templates use Zottman Curl?” is a query rather than a scan of JSON, and deleting the item deletes the lines that name it; it is empty for a trackable with no item field. A line’s item is one its trackable can log, from the catalog its item field names: writing a template’s lines refuses an exercise as a line of a Diet template, and any item on a trackable that logs none, before anything is written (setLines in packages/core/src/template-repository.ts, the one write path: the form and the seeds write through it, and a line that arrives by sync was checked on the device that wrote it, since sync applies rows as they were written). field_values holds the entry’s other fields. Deleting the trackable deletes its templates.
- Egg & Cheese on Diet: lines
(Egg, quantity 100)and(Cheddar, quantity 30). - Arm Circuit on the Set: lines of its own,
(Zottman Curl, reps 10, weight 16)and three more, three rounds.
One path, no domain code
Which field a line’s item lands in is read from the trackable’s value schema (referenceSlotOf): the item field that carries the amount, else the first item field. So (exercise, reps, weight) and (food, quantity, unit) are the same code reading two schemas, and a template over a new catalog needs no new code. A line that leaves out what its trackable fills from its item, such as a push-up’s weight from bodyweight, is filled the way the form fills it (Capture Model).
An Event’s template
A Event’s template holds other trackables’ entries, so each line names its own trackable_id; a line naming a trackable that does not exist is skipped. A line’s depth nests it: one deeper than the line before it, it goes inside that line’s Event. Saving an Event’s entry as a template keeps what its Events held the same way. Chad’s Push, Pull and Legs on the Workout are a stretch and then each lift’s sets in a row.
- Chosen, then logged. In an Event’s form a template is chosen, not acted on: the form’s own Log or Open logs the Event and then applies the template. With no end yet the choice reads Start with; with an end, Log with.
- Started, it becomes the Event’s plan. An Event started from a template logs nothing yet: its lines, each given an id, are the Event’s plan (the setting
routine:plan, per entry, kept while the Event runs and for two days after it ends), and its page shows them as rows to tick (Events). A row keeps the values it was planned with apart from those it holds now, so a set done at 70 kg where 75 was planned starts the next one planned the same at 70. A template added while it runs adds its rows to the plan. - Logged after the fact, it holds them all, done in order: an interval starts where the one before it in the same Event ended, and an Event’s lines start with it.
- The Event’s entry names its template (
entry.template_id), whether started with it, logged with it, or saved as it. The link has no foreign key, aspart_ofhas none, so an entry outlives a deleted template, which then names nothing.
Found from anywhere
Log or search finds a template by its name once something is typed, beside the trackables, its trackable named beside it (Frictionless Capture). Choosing it opens its trackable’s log form started with it, as picking it there would (StartTemplate in apps/renderer/src/components/entries/start-template.ts): Egg & Cheese opens on its lines to log, a one-line template fills the form, and Push opens the Workout’s form with Push chosen, so Open starts a Workout with its lines planned. In a trackable’s own log form, its item picker offers its templates beside its items, and an Event’s form offers its kind’s as Start with.
Editing one can fix the past
What is logged from a template is an instance: changing the template leaves it alone, so two slices of cheese today as a treat is an ordinary edit of that day’s sandwich. Saving a template of a thing made of parts with new lines offers to fix the past (FixPast in apps/renderer/src/components/templates/). Each entry made from it is compared with what its lines as they were before the edit would have logged (templatePast in packages/core/src/template-past.ts, stillStamped the comparison): one still as stamped takes the new lines; one changed since, by hand or as a portion, is listed to tick or open; one already as the new lines needs nothing. Updating replaces what each holds in one batch (replaceParts), each new part checked as any entry is, and one Undo puts the old parts back. An Event’s template does not offer it: a Workout holds what was done, not its plan.
A portion of the whole
A template of amounts of items can be logged as a share of the whole: batch cooking. The whole weighs what its lines do, in their items’ basis (linesWeight in packages/core/src/portion.ts), until the template’s form says what it weighed once made (template.weighed), since cooking adds or loses water. Logging it asks for the Portion, the whole by default; a 350 g bowl of a 2400 g pot takes 350/2400 of every line in the line’s own unit (portionLines), each row’s quantity its line’s share, its base frozen from that as any amount’s is. A row’s other values, and a row skipped, stay as they were changed.
The card reads its lines as the entries they log
A template’s card shows what its lines come to, read as the entries logging it would write (entriesFromLines), so the card and the log agree: an amount of an item with its base frozen from the item’s units, an interval as long as its line keeps. Each Trackable’s share is read by that Trackable’s own rules, written once on it and never per template: Diet’s food totals as its Today strip has them, the exercise Trackable’s summary strip (sets, volume, top set, and the muscles worked from each exercise’s own muscles), any other Trackable its Reading. Egg & Cheese reads its calories; Arm Circuit its sets, volume and muscles. An entry made from a template and an Event’s page show the same figures over what they hold. A template has no rules of its own for this: two templates of one Trackable read alike.
Code
packages/core/src/template-repository.ts; the tables inpackages/core/src/schema.ts.apps/renderer/src/components/templates/:TemplateForm.tsx,TemplateExpander.tsx,TemplatesSection.tsx; the card’s figures inapps/renderer/src/components/entries/PartsFigures.tsx.packages/core/src/routines.ts(entriesFromLines) andentity-units.ts(withBase): the entries a template’s lines log.apps/renderer/src/components/entries/RoutineField.tsxandapps/renderer/src/hooks/useRoutinePlan.tsfor an Event’s template.
Related
Catalog Entities · Events · Entry · Trackable · Value Types · Exercise & Strength · Diet and Nutrition · Capture Model