feat(recipes): add recipe management with download/upload of tag values - #2492
feat(recipes): add recipe management with download/upload of tag values#2492JordiB-Inserma wants to merge 40 commits into
Conversation
…olation, sanitize CSV, prune generation map
…ula prefix on import
…ead of silent 202
The generation re-check ran only at the top of the download/upload loop. If a cancel landed while the final entry's setTagValue/getTagValue was in flight, the loop exited naturally with canceled still false, so upload persisted a half-read recipe (the behavior 900dea20 claimed to prevent) and both directions emitted *_COMPLETE on a cancelled run. For a 1-entry recipe this was the normal cancel path. Re-check the running generation after every entry's device op and treat a mismatch as cancel/supersede: emit RECIPE_CANCELED only when no successor owns the slot, skip persistence and skip the COMPLETE emit.
…undary Only the two client save paths sanitized ''; the server still accepted and stored a literal '' from import (CSV/JSON round-trip, hand-made CSV with an empty cell), direct API POST, or any recipe saved before the earlier fix. Those '' values were written verbatim via setTagValue, violating the invariant that a download never writes '' to a numeric/bool tag. Map '' to the type's neutral default in coerceValue (0 for numeric families, false for bool) so the download boundary is safe regardless of what was ever stored, and coerce '' in place during recipe validation so new saves (import or POST) store 0/false instead of ''. String tags still legitimately keep ''.
…ize widget strings
|
Hi @JordiB-Inserma Great job on this feature, thanks for putting it together. The recipe type + recipe instances model looks like a really useful addition for FUXA. I’d like to help refine this PR before merge. I found a couple of functional edge cases, and I also think the UX could be aligned more closely with the existing FUXA layout. Since maintainers are allowed to edit this PR, I’d prepare a few focused commits on top of your branch, keeping functional fixes, wording, busy states, and layout changes separated so we can discuss them individually. Would that work for you? |
|
Hi @unocelli, Thank you for the review and for the positive feedback, I really appreciate it. Your proposal sounds great to me. Feel free to prepare the commits on top of my branch and keep the different types of changes separated as you suggested. I think that will make the review process much easier. I'm happy to help with anything related to this feature, whether it's reviewing the proposed changes, providing context on the implementation, testing, or discussing alternative approaches. The same applies to any of the maintainers involved in the review. Thanks again for taking the time to improve the PR. I look forward to collaborating on it. |
|
Hi @JordiB-Inserma I think we should clarify the recipe data model before going too far with the UX. Currently both recipe types and recipe instances are stored in recipes.db, and each instance stores a full copy of the entries. This means that if a recipe type/template is changed later, for example by adding or removing tags, existing instances are not updated and the widget keeps showing the entries stored in the instance. This also raises an ownership question. Recipe types reference project tags, so they look closer to project configuration, similarly to alarm definitions in FUXA. Alarms keep their definitions in the project, while runtime state/history is stored separately in the DB. Maybe recipes should follow a similar split:
That would make project export/import, backup, tag consistency, and template updates easier to reason about. In a second step, recipes.db could also be a good place for operational history, such as download/upload executions, user, timestamp, result, and per-tag errors. But I think that can come later, after the core data model is clear. What do you think if I work on this change as part of the PR? |
…ecipes.db. Split the API into explicit template and instance endpoints, and apply admin-only protection to template changes in secure mode.
|
Hi @unocelli, your proposal looks great to me. I had planned to tackle this topic in later iterations, but I get that your goal is to ship a much more mature feature from the start. The idea of splitting templates and instances makes total sense, and it gives us a cleaner and more scalable foundation for the data model. Let me share a few thoughts I had in mind for future improvements, which might be worth considering now that you’re opening the door to a deeper redesign: One thing I’ve been thinking about is enforcing a stricter data structure for recipe templates. That would allow us to define min/max values, defaults, and proper validation rules for each field. With that in place, instances would behave more predictably and we’d avoid runtime inconsistencies. I also had the idea of adding template versioning. This would let us track which template version was used to create each instance, ensuring that template updates don’t silently affect existing instances. On the opposite end, we could enable a stricter mode where instances must be validated against the current template, and if the template has changed, the instance would need to be updated as well. Overall, I think all these points align nicely with the direction you’re proposing and could help reinforce the model even further. I’m fully open to collaborating on this evolution of the system and happy to work together on the PR or any adjustments needed. |
|
Hi @JordiB-Inserma, thanks for the feedback. I agree with your points, especially around stricter template validation and versioning. They fit well with the direction of the redesign. I’ve pushed a first WIP iteration to your branch focused on the foundation: splitting templates and instances, aligning storage/API/security with that model, and keeping the scope manageable for this step. Please don’t hesitate to review it critically or push back on anything you’d like to discuss. We can iterate together from there. |
Description
Adds a Recipes feature to FUXA: manage recipe types vs instances and push/pull tag values to/from devices.
HtmlRecipeViewgauge control with per-user permissions and configurable visible actions (New, Delete, Save, Download, Upload).docs/HowTo-Recipes.md.The implementation went through two adversarial fresh-context reviews; all findings (1 CRITICAL + 7 WARNINGs + 5 SUGGESTIONs across both rounds) were fixed and verified:
''to numeric/bool tags (server-side coercion boundary).Type of Change
Build Artifacts Check
/client/distChecklist
ng buildAOT clean)docs/HowTo-Recipes.md)Documentation Checklist (if applicable)
mkdocs serveimages/example.png)mkdocs.yml(if required)Additional Notes
Main files:
server/runtime/recipes/recipe-service.jsserver/runtime/recipes/recipe-storage.jsserver/api/recipes/index.jsclient/src/app/recipes/*client/src/app/gauges/controls/html-recipe/*docs/HowTo-Recipes.md