From b8cb7ca2679863548758bad2ab7a00e85bad3cd1 Mon Sep 17 00:00:00 2001 From: forbes Date: Sat, 21 Feb 2026 09:06:36 -0600 Subject: [PATCH] feat(templates): document templating system for .kc files Add a template system integrated with Silo new-item creation that lets users create parts from pre-configured .kc templates and save existing documents as reusable templates. Changes: - mods/silo: template discovery, picker UI, Save as Template command, 3-tier search paths (system, personal, org-shared) - docs: template guide, SUMMARY.md entry, silo.md command reference --- docs/src/SUMMARY.md | 11 +++ docs/src/guide/silo.md | 5 +- docs/src/guide/templates.md | 140 ++++++++++++++++++++++++++++++++++++ mods/silo | 2 +- 4 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 docs/src/guide/templates.md diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index d70fff7760..29fe819bca 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -12,6 +12,7 @@ - [Workbenches](./guide/workbenches.md) - [ztools](./guide/ztools.md) - [Silo](./guide/silo.md) + - [Document Templates](./guide/templates.md) # Architecture @@ -49,6 +50,16 @@ - [Solver Service](./silo-server/SOLVER.md) - [Roadmap](./silo-server/ROADMAP.md) +# Kindred Solver + +- [Overview](./solver/overview.md) +- [Expression DAG](./solver/expression-dag.md) +- [Constraints](./solver/constraints.md) +- [Solving Algorithms](./solver/solving.md) +- [Diagnostics](./solver/diagnostics.md) +- [Assembly Integration](./solver/assembly-integration.md) +- [Writing a Custom Solver](./solver/writing-a-solver.md) + # Reference - [Configuration](./reference/configuration.md) diff --git a/docs/src/guide/silo.md b/docs/src/guide/silo.md index b1c7be1d5f..43efc69d99 100644 --- a/docs/src/guide/silo.md +++ b/docs/src/guide/silo.md @@ -53,6 +53,7 @@ The silo-mod repository was split from a monorepo into three repos: `silo-client | `Silo_TagProjects` | Multi-select dialog for assigning project tags to items | | `Silo_Rollback` | Select a previous revision and create a new revision from that point with optional comment | | `Silo_SetStatus` | Change revision lifecycle status: draft → review → released → obsolete | +| `Silo_SaveAsTemplate` | Save a copy of the current document as a reusable [template](./templates.md) with metadata | ### Administration @@ -129,9 +130,11 @@ mods/silo/ ├── freecad/ │ ├── InitGui.py # SiloWorkbench registration │ ├── schema_form.py # Schema-driven item creation dialog (SchemaFormDialog) -│ ├── silo_commands.py # 14 commands + dock widgets +│ ├── silo_commands.py # 15 commands + dock widgets │ ├── silo_origin.py # FileOrigin backend │ ├── silo_start.py # Native start panel (database items, activity feed) +│ ├── templates.py # Template discovery, filtering, injection +│ ├── templates/ # System template .kc files + CLI injection tool │ └── resources/icons/ # 10 silo-*.svg icons ├── silo-client/ # Shared Python API client (nested submodule) │ └── silo_client/ diff --git a/docs/src/guide/templates.md b/docs/src/guide/templates.md new file mode 100644 index 0000000000..3657a53954 --- /dev/null +++ b/docs/src/guide/templates.md @@ -0,0 +1,140 @@ +# Document Templates + +Templates let you create new parts and assemblies from pre-configured `.kc` files. Instead of starting from a bare `App::Part` or `Assembly::AssemblyObject`, a template can include predefined tree structures, jobs, metadata, and workbench-specific features. + +## How templates work + +A template is a normal `.kc` file with an extra `silo/template.json` descriptor inside the ZIP archive. When you select a template during **Silo > New**: + +1. The template `.kc` is **copied** to the canonical file path +2. `silo/template.json` and `silo/manifest.json` are **stripped** from the copy +3. The document is **opened** in FreeCAD +4. Silo properties (part number, item ID, revision, type) are **stamped** onto the root object +5. On **save**, `kc_format.py` auto-creates a fresh manifest + +The original template file is never modified. + +## Using templates + +### Creating a new item from a template + +1. **Silo > New** (Ctrl+N) +2. Select an **Item Type** (Part, Assembly, etc.) +3. The **Template** dropdown shows templates matching the selected type and category +4. Select a template (or leave as "No template" for a blank document) +5. Fill in the remaining fields and click **Create** + +The template combo updates automatically when you change the item type or category. + +### Saving a document as a template + +1. Open the document you want to use as a template +2. **Silo > Save as Template** +3. Fill in the template metadata: + - **Name** — display name shown in the template picker (pre-filled from document label) + - **Description** — what the template is for + - **Item Types** — which types this template applies to (part, assembly, etc.) + - **Categories** — category prefix filter (e.g. `F`, `M01`); leave empty for all categories + - **Author** — pre-filled from your Silo login + - **Tags** — comma-separated search tags +4. Click **Save Template** +5. Optionally upload to Silo for team sharing + +The template is saved as a copy to your personal templates directory. The original document is unchanged. + +## Template search paths + +Templates are discovered from three locations, checked in order. Later paths shadow earlier ones by name (so you can override a system template with a personal one). + +| Priority | Path | Purpose | +|----------|------|---------| +| 1 (lowest) | `mods/silo/freecad/templates/` | System templates shipped with the addon | +| 2 | `~/.local/share/FreeCAD/Templates/` | Personal templates (sister to `Macro/`) | +| 3 (highest) | `~/projects/templates/` | Org-shared project templates | + +The personal templates directory (`Templates/`) is created automatically when you first save a template. It lives alongside the `Macro/` directory in your FreeCAD user data. + +## Template descriptor schema + +The `silo/template.json` file inside the `.kc` ZIP has the following structure: + +```json +{ + "template_version": "1.0", + "name": "Sheet Metal Part", + "description": "Body with SheetMetal base feature and laser-cut job", + "item_types": ["part"], + "categories": [], + "icon": "sheet-metal", + "author": "Kindred Systems", + "tags": ["sheet metal", "fabrication"] +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `template_version` | string | yes | Schema version, currently `"1.0"` | +| `name` | string | yes | Display name in the template picker | +| `description` | string | no | Human-readable purpose | +| `item_types` | string[] | yes | Controls visibility — `["part"]`, `["assembly"]`, or both | +| `categories` | string[] | no | Category prefix filter. Empty array means all categories | +| `icon` | string | no | Icon identifier (reserved for future use) | +| `author` | string | no | Template author | +| `tags` | string[] | no | Searchable metadata tags | + +### Filtering rules + +- **item_types**: The template only appears when the selected item type is in this list +- **categories**: If non-empty, the template only appears when the selected category starts with one of the listed prefixes. An empty list means the template is available for all categories + +## Creating templates from the command line + +The `inject_template.py` CLI tool can inject `silo/template.json` into any `.kc` file: + +```bash +cd mods/silo/freecad/templates/ + +# Create a template from an existing .kc file +python inject_template.py my-part.kc "My Custom Part" \ + --type part \ + --description "Part with custom features" \ + --author "Your Name" \ + --tag "custom" + +# Assembly template +python inject_template.py my-assembly.kc "My Assembly" \ + --type assembly \ + --description "Assembly with predefined joint groups" + +# Template with category filtering +python inject_template.py sheet-metal.kc "Sheet Metal Part" \ + --type part \ + --category S \ + --category X \ + --tag "sheet metal" \ + --tag "fabrication" +``` + +## Module structure + +``` +mods/silo/freecad/ +├── templates.py # Discovery, filtering, injection helpers +├── templates/ +│ └── inject_template.py # CLI tool for injecting template.json +├── schema_form.py # Template combo in New Item form +└── silo_commands.py # SaveAsTemplateDialog, Silo_SaveAsTemplate, + # SiloSync.create_document_from_template() +``` + +### Key functions + +| Function | File | Purpose | +|----------|------|---------| +| `discover_templates()` | `templates.py` | Scan search paths for `.kc` files with `silo/template.json` | +| `filter_templates()` | `templates.py` | Filter by item type and category prefix | +| `inject_template_json()` | `templates.py` | Inject/replace `silo/template.json` in a `.kc` ZIP | +| `get_default_template_dir()` | `templates.py` | Returns `{userAppData}/Templates/`, creating if needed | +| `get_search_paths()` | `templates.py` | Returns the 3-tier search path list | +| `create_document_from_template()` | `silo_commands.py` | Copy template, strip identity, stamp Silo properties | +| `_clean_template_zip()` | `silo_commands.py` | Strip `silo/template.json` and `silo/manifest.json` from a copy | diff --git a/mods/silo b/mods/silo index dfa1da97dd..a88e104d94 160000 --- a/mods/silo +++ b/mods/silo @@ -1 +1 @@ -Subproject commit dfa1da97dd1f661a0e69f6b656900e55bd9dfb79 +Subproject commit a88e104d9489d72462b0580d6f9ef6df3314dd52 -- 2.49.1