Compare commits
7 Commits
feat/ztool
...
fix/submod
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d28c54b54f | ||
| 0bc2cf3b6a | |||
|
|
0330396843 | ||
| 7fe046379b | |||
|
|
0bc03ea421 | ||
| 0c43957e9b | |||
|
|
2ce00a527a |
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -13,6 +13,8 @@
|
|||||||
[submodule "mods/ztools"]
|
[submodule "mods/ztools"]
|
||||||
path = mods/ztools
|
path = mods/ztools
|
||||||
url = https://git.kindred-systems.com/forbes/ztools.git
|
url = https://git.kindred-systems.com/forbes/ztools.git
|
||||||
|
branch = main
|
||||||
[submodule "mods/silo"]
|
[submodule "mods/silo"]
|
||||||
path = mods/silo
|
path = mods/silo
|
||||||
url = https://git.kindred-systems.com/kindred/silo-mod.git
|
url = https://git.kindred-systems.com/kindred/silo-mod.git
|
||||||
|
branch = main
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ Pure Python addons with `package.xml` manifests. Self-contained with `Init.py`,
|
|||||||
|
|
||||||
**Implementation:** `mods/sdk/kindred_sdk/` package with wrappers for editing contexts, theme tokens, FileOrigin registration, and dock panel creation. YAML-driven palette system (`palettes/catppuccin-mocha.yaml`) replaces hardcoded color dicts that were duplicated across 5+ locations.
|
**Implementation:** `mods/sdk/kindred_sdk/` package with wrappers for editing contexts, theme tokens, FileOrigin registration, and dock panel creation. YAML-driven palette system (`palettes/catppuccin-mocha.yaml`) replaces hardcoded color dicts that were duplicated across 5+ locations.
|
||||||
|
|
||||||
**Migration:** Both ztools and Silo have been migrated to use the SDK (#250). No addon code calls `FreeCADGui.registerEditingOverlay()`, `FreeCADGui.addOrigin()`, or defines hardcoded MOCHA dicts directly.
|
**Migration:** Silo has been migrated to use the SDK (#250) — it declares `<dependency>sdk</dependency>` and uses `kindred_sdk` for overlay registration and theme tokens. ztools has **not yet been migrated**: its `package.xml` lacks `<kindred>` metadata and its `InitGui.py` does not import from `kindred_sdk`. See KNOWN_ISSUES.md next step #9.
|
||||||
|
|
||||||
### Phase 1.75: C++ module scaffold -- DONE
|
### Phase 1.75: C++ module scaffold -- DONE
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
5. **No unit tests.** Zero test coverage for ztools and Silo FreeCAD commands. Silo Go backend also lacks tests.
|
5. **No unit tests.** Zero test coverage for ztools and Silo FreeCAD commands. Silo Go backend also lacks tests.
|
||||||
|
|
||||||
6. **Assembly solver datum handling is minimal.** The `findPlacement()` fix in `src/Mod/Assembly/UtilsAssembly.py` extracts placement from `obj.Shape.Faces[0]` for `PartDesign::Plane` and from shape vertex for `PartDesign::Point`. Does not handle empty shapes or non-planar datum objects.
|
6. **Assembly solver datum handling is minimal.** `UtilsAssembly.findPlacement()` handles standard shapes (faces, edges, vertices) and `App::Line` origin objects. It does not extract placement from `PartDesign::Plane` or `PartDesign::Point` datum objects — when no element is selected, it returns a default `App.Placement()`. This means assembly joints referencing datum planes/points may produce incorrect placement.
|
||||||
|
|
||||||
### Medium
|
### Medium
|
||||||
|
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
|
|
||||||
9. **tangent_to_cylinder falls back to manual placement.** TangentPlane MapMode requires a vertex reference not collected by the current UI.
|
9. **tangent_to_cylinder falls back to manual placement.** TangentPlane MapMode requires a vertex reference not collected by the current UI.
|
||||||
|
|
||||||
10. **`delete_bom_entry()` bypasses error normalization.** Uses raw `urllib.request` instead of `SiloClient._request()`.
|
10. ~~**`delete_bom_entry()` bypasses error normalization.**~~ Resolved. `delete_bom_entry()` uses `self._request("DELETE", ...)` which routes through `SiloClient._request()` with proper error handling.
|
||||||
|
|
||||||
11. **Missing Silo icons.** Three commands reference icons that don't exist: `silo-tag.svg` (`Silo_TagProjects`), `silo-rollback.svg` (`Silo_Rollback`), `silo-status.svg` (`Silo_SetStatus`). The `_icon()` function returns an empty string, so these commands render without toolbar icons.
|
11. ~~**Missing Silo icons.**~~ Resolved. All three icons now exist: `silo-tag.svg`, `silo-rollback.svg`, `silo-status.svg` in `mods/silo/freecad/resources/icons/`.
|
||||||
|
|
||||||
### Fixed (retain for reference)
|
### Fixed (retain for reference)
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
| CSRF protection | Implemented | `nosurf` library on web form routes |
|
| CSRF protection | Implemented | `nosurf` library on web form routes |
|
||||||
| File locking | Not implemented | Needed to prevent concurrent edits |
|
| File locking | Not implemented | Needed to prevent concurrent edits |
|
||||||
| Odoo ERP integration | Stub only | Returns "not yet implemented" |
|
| Odoo ERP integration | Stub only | Returns "not yet implemented" |
|
||||||
| Part number date segments | Broken | `formatDate()` returns error |
|
| Part number date segments | Unknown | `formatDate()` reference is stale — function not found in codebase |
|
||||||
| Location/inventory APIs | Tables exist, no handlers | |
|
| Location/inventory APIs | Tables exist, no handlers | |
|
||||||
| CSV import rollback | Not implemented | `bom_handlers.go` |
|
| CSV import rollback | Not implemented | `bom_handlers.go` |
|
||||||
| SSE event streaming | Implemented | Reconnect logic with exponential backoff |
|
| SSE event streaming | Implemented | Reconnect logic with exponential backoff |
|
||||||
@@ -71,14 +71,20 @@
|
|||||||
|
|
||||||
1. **Authentication hardening** -- Deploy FreeIPA and Keycloak infrastructure. End-to-end test LDAP and OIDC flows. Harden token rotation and session expiry.
|
1. **Authentication hardening** -- Deploy FreeIPA and Keycloak infrastructure. End-to-end test LDAP and OIDC flows. Harden token rotation and session expiry.
|
||||||
|
|
||||||
2. **BOM-Assembly bridge** -- Auto-populate Silo BOM from Assembly component links on save.
|
2. **BOM-Assembly bridge** -- Auto-populate Silo BOM from Assembly component links on save. See `docs/BOM_MERGE.md` for specification.
|
||||||
|
|
||||||
3. **File locking** -- Pessimistic locks on `Silo_Open` to prevent concurrent edits. Requires server-side lock table and client-side lock display.
|
3. **File locking** -- Pessimistic locks on `Silo_Open` to prevent concurrent edits. Requires server-side lock table and client-side lock display.
|
||||||
|
|
||||||
4. **Build system** -- CMake install rules for `mods/` submodules so packages include ztools and Silo without manual steps.
|
4. ~~**Build system**~~ Done. CMake install rules in `src/Mod/Create/CMakeLists.txt` handle all `mods/` submodules.
|
||||||
|
|
||||||
5. **Test coverage** -- Unit tests for ztools datum creation, Silo FreeCAD commands, and Go API endpoints.
|
5. **Test coverage** -- Unit tests for ztools datum creation, Silo FreeCAD commands, and Go API endpoints.
|
||||||
|
|
||||||
6. **QSS consolidation** -- Eliminate the 3-copy QSS duplication via build-time copy or symlinks. The canonical source is `resources/preferences/KindredCreate/KindredCreate.qss`.
|
6. ~~**QSS consolidation**~~ Done. Canonical QSS is `src/Gui/Stylesheets/KindredCreate.qss`; PreferencePacks copy generated at build time via `configure_file()`.
|
||||||
|
|
||||||
7. **Update notification UI** -- Display in-app notification when a new release is available (issue #30). The update checker backend is already implemented.
|
7. **Update notification UI** -- Display in-app notification when a new release is available (issue #30). The update checker backend (`update_checker.py`) runs at startup; notification UI still needed.
|
||||||
|
|
||||||
|
8. **KC file format completion** -- Populate `silo_instance` and `revision_hash` in manifest.json. Implement write-back for history.json, approvals.json, dependencies.json. See `docs/KC_SPECIFICATION.md`.
|
||||||
|
|
||||||
|
9. **ztools SDK migration** -- Add `<kindred>` metadata to `mods/ztools/package.xml` (load priority, version bounds, SDK dependency). Migrate `InitGui.py` to use `kindred_sdk` APIs for context/overlay registration.
|
||||||
|
|
||||||
|
10. **DAG cross-item edges** -- Assembly constraints referencing geometry in child parts should populate `dag_cross_edges`. Deferred until assembly constraint model is finalized.
|
||||||
|
|||||||
Submodule mods/silo updated: edbaf65923...dfa1da97dd
Submodule mods/ztools updated: e256e0b81f...08e439b9ca
@@ -136,6 +136,12 @@
|
|||||||
<FCParamGroup Name="Sketcher">
|
<FCParamGroup Name="Sketcher">
|
||||||
<FCUInt Name="GridLineColor" Value="1162304255" />
|
<FCUInt Name="GridLineColor" Value="1162304255" />
|
||||||
</FCParamGroup>
|
</FCParamGroup>
|
||||||
|
<FCParamGroup Name="Spreadsheet">
|
||||||
|
<FCText Name="TextColor">#cdd6f4</FCText>
|
||||||
|
<FCText Name="AliasedCellBackgroundColor">#313244</FCText>
|
||||||
|
<FCText Name="PositiveNumberColor">#a6e3a1</FCText>
|
||||||
|
<FCText Name="NegativeNumberColor">#f38ba8</FCText>
|
||||||
|
</FCParamGroup>
|
||||||
</FCParamGroup>
|
</FCParamGroup>
|
||||||
</FCParamGroup>
|
</FCParamGroup>
|
||||||
</FCParamGroup>
|
</FCParamGroup>
|
||||||
|
|||||||
@@ -48,12 +48,6 @@ install(
|
|||||||
DESTINATION
|
DESTINATION
|
||||||
mods/ztools
|
mods/ztools
|
||||||
)
|
)
|
||||||
install(
|
|
||||||
DIRECTORY
|
|
||||||
${CMAKE_SOURCE_DIR}/mods/ztools/CatppuccinMocha
|
|
||||||
DESTINATION
|
|
||||||
mods/ztools
|
|
||||||
)
|
|
||||||
install(
|
install(
|
||||||
FILES
|
FILES
|
||||||
${CMAKE_SOURCE_DIR}/mods/ztools/package.xml
|
${CMAKE_SOURCE_DIR}/mods/ztools/package.xml
|
||||||
|
|||||||
@@ -45,6 +45,51 @@ def _metadata_save_hook(doc, filename, entries):
|
|||||||
register_pre_reinject(_metadata_save_hook)
|
register_pre_reinject(_metadata_save_hook)
|
||||||
|
|
||||||
|
|
||||||
|
def _manifest_enrich_hook(doc, filename, entries):
|
||||||
|
"""Populate silo_instance and part_uuid from the tracked Silo object."""
|
||||||
|
raw = entries.get("silo/manifest.json")
|
||||||
|
if raw is None:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
manifest = json.loads(raw)
|
||||||
|
except (json.JSONDecodeError, ValueError):
|
||||||
|
return
|
||||||
|
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
# Populate part_uuid from SiloItemId if available.
|
||||||
|
for obj in doc.Objects:
|
||||||
|
if hasattr(obj, "SiloItemId") and obj.SiloItemId:
|
||||||
|
if manifest.get("part_uuid") != obj.SiloItemId:
|
||||||
|
manifest["part_uuid"] = obj.SiloItemId
|
||||||
|
changed = True
|
||||||
|
break
|
||||||
|
|
||||||
|
# Populate silo_instance from Silo settings.
|
||||||
|
if not manifest.get("silo_instance"):
|
||||||
|
try:
|
||||||
|
import silo_commands
|
||||||
|
|
||||||
|
api_url = silo_commands._get_api_url()
|
||||||
|
if api_url:
|
||||||
|
# Strip /api suffix to get base instance URL.
|
||||||
|
instance = api_url.rstrip("/")
|
||||||
|
if instance.endswith("/api"):
|
||||||
|
instance = instance[:-4]
|
||||||
|
manifest["silo_instance"] = instance
|
||||||
|
changed = True
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
entries["silo/manifest.json"] = (json.dumps(manifest, indent=2) + "\n").encode(
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
register_pre_reinject(_manifest_enrich_hook)
|
||||||
|
|
||||||
|
|
||||||
KC_VERSION = "1.0"
|
KC_VERSION = "1.0"
|
||||||
|
|
||||||
|
|
||||||
@@ -133,6 +178,34 @@ class _KcFormatObserver:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def update_manifest_fields(filename, updates):
|
||||||
|
"""Update fields in an existing .kc manifest after save.
|
||||||
|
|
||||||
|
*filename*: path to the .kc file.
|
||||||
|
*updates*: dict of field_name -> value to merge into the manifest.
|
||||||
|
|
||||||
|
Used by silo_commands to write ``revision_hash`` after a successful
|
||||||
|
upload (which happens after the ZIP has already been written by save).
|
||||||
|
"""
|
||||||
|
if not filename or not filename.lower().endswith(".kc"):
|
||||||
|
return
|
||||||
|
if not os.path.isfile(filename):
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
with zipfile.ZipFile(filename, "a") as zf:
|
||||||
|
if "silo/manifest.json" not in zf.namelist():
|
||||||
|
return
|
||||||
|
raw = zf.read("silo/manifest.json")
|
||||||
|
manifest = json.loads(raw)
|
||||||
|
manifest.update(updates)
|
||||||
|
zf.writestr(
|
||||||
|
"silo/manifest.json",
|
||||||
|
json.dumps(manifest, indent=2) + "\n",
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
FreeCAD.Console.PrintWarning(f"kc_format: failed to update manifest: {e}\n")
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
"""Connect to application-level save signals."""
|
"""Connect to application-level save signals."""
|
||||||
FreeCAD.addDocumentObserver(_KcFormatObserver())
|
FreeCAD.addDocumentObserver(_KcFormatObserver())
|
||||||
|
|||||||
Reference in New Issue
Block a user