feat(#10903): sub contact attachment routing#10923
Conversation
16849ee to
75a7787
Compare
|
This is ready for review. |
jkuester
left a comment
There was a problem hiding this comment.
@benkags once again, I am so glad you are working through this! ✨ I spent hours this afternoon reading through and debugging around this code. I have not finished reading it all yet, but I ran out of time today and wanted to push the thoughts that I have so for. 👍
|
@jkuester please take another look |
There was a problem hiding this comment.
Okay, I have been deep down the rabbit hole here. 😬 🐇
All of this is so complicated and interlocked that I ended up just creating benkags#10 with my suggested changes instead of trying to put everything in comments here. 😓 The main focus of my changes was getting all the attachments for the main report and sub-reports to be rendered as expected when viewing the report in the "Reports" tab.
I used file_uploads.xlsx to test with.
A couple things I learned in all my testing and debugging:
Current attachment naming strategies (before this PR):
- New-style
filetype attachements (>=4.9.0):- Property value set to attachment name
- Attachment name has
user-file-prefix + property value
- Old-style
filetype attachments (<4.9.0):- Property value set to attachment name
- Attachment name has
user-file/prefex + path/to/property
- All
binarytype attachments:- Property value set to
"" - Attachment name has
user-file/prefex + path/to/property
- Property value set to
#1 and #2 are what you got when using any of the image/audio/file/etc types in your xform and the user selects a file from the device to upload.
#3 should mainly be coming from the external Android app integration where you are getting base64 data loaded as the value for a field in the form with instance:: binary set to true. (Technically can also enter base64 text right in the form or load it as a default value.) This data does not go through the Enekto file manager.
Editing docs with attachments
Currently, (before this PR) you can edit docs with file attachments. The attachments with type=file are rendered properly in the form, but the type=binary attachments are not rendered. Depending on how we plan to load profile pictures into a contact form, this may or may not be something we need to worry about....
The rendering of the type=binary attachments is not fixed (even by my changes in the linked PR). I was up way too late last night trying to sort out a solution (see the first commit in my PR for what I came up with). I think there is something viable here that we could move forwards with in the future, but ultimately I felt it was out of scope for your PR here since the existing functionality remains unchanged.
The changes in my PR come without any updates to the tests 😓 or even any manual validation of the contact-attachment flow. I have been purely testing with reports. I am out of time for the week, though, and I figured I would post what I have and get your thoughts. 👍
|
Thanks @jkuester for going down the rabbit hole. I have been down there myself a couple of times with this PR 😃 . Thanks for PR benkags#10 - I agree, it a much better PR review feedback approach. This is what I picked from PR as net change. Let me know if I missed something
I think it really comes down to what approach to adopt between Approach A (the one I have here) and Approach B (in your PR) from a design perpective
|
|
I think you have pretty clearly understood my PR. 👍 Just a couple comments:
I 100% was hoping this would work out as you have described. 😓 Unfortunately, it did not really seem to save us any complexity.
The On top of that, changing to store the attachment name as the property value for
It ended up being similar complexity to just properly calculate the field path (even for the sub-docs). That was the point where I started trying to figure out what benefits I was actually getting from On the other hand, with @benkags if you have a strong preference for Also happy to jump on a call to discuss further if that would be helpful! 👍 |
39ccc3c to
69fe840
Compare
e26b095 to
e850f29
Compare
|
Ready for review @jkuester |
e850f29 to
19e33c9
Compare
…rt forms (medic#10922) Co-authored-by: Bernard K. <kagondubernard81@gmail.com>
…rt forms When a report form contains [db-doc="true"] sub-documents with binary/file fields, attachments are now routed to the owning sub-document instead of always attaching to the main report doc. - Add resolveOwnerDoc() to walk up XML tree to nearest db-doc ancestor - Route FileManager file uploads to correct owner doc - Route inline binary blobs to correct owner doc - Fall back to main report doc when element is not inside a sub-doc
processAllAttachments now walks the parsed XML to determine which prepared doc owns each [type=binary] element (main / sibling / repeat child) and attaches files accordingly, instead of dumping every upload on preparedDocs[0]. Field-value sanitization and orphan cleanup also run per-doc. Adds two private helpers: - resolveContactOwnerDoc: DOM-walk from any element to its section root, then to the owning prepared doc (with mainDoc fallback). - findContactOwnerForFilename: locates the [type=binary] node whose text matches a FileManager filename and resolves its owner. No public API changes; no new service dependencies.
saveContact now uses validateAttachments(preparedDocs.preparedDocs)
New 'attachment routing to sub-contacts' describe block exercising: - file uploaded inside a sibling section -> sibling doc - file uploaded inside a repeat child -> i-th repeat doc - mixed uploads across main / sibling / repeat -> each owner - FileManager file with no matching binary node -> main doc fallback - inline binary (draw widget) inside sibling -> sibling doc - per-doc field-value sanitization (sibling field rewritten, main untouched) - main-doc orphan cleanup on edit path with per-doc loop
- main-doc & sub-doc oversize attachment fails saveContact - normal-sized attachment passes validation
Enketo's setVal rewrites uploaded binary nodes to type="file" the moment a value is set.
add sub-contact attachment routing form fixtures & testes
Co-authored-by: Joshua Kuestersteffen <jkuester@kuester7.com>
…t attachments Inline-binary form fields (`<foo type="binary">…base64…</foo>` populated by form `<instance>` defaults, `calculate` expressions, or external `instanceData` injection) previously had attachments stored under `user-file/<xpath>` while the saved field was blanked, requiring downstream binary fields attachment name reconstruction from `label` at render time. That reconstruction was broken for sub-docs, where the parent-form prefix in the attachment name is not derivable from the sub-doc alone. With this change, a media field's value is the name of its attachment, regardless of how the attachment was produced. Inline-binary fields keep their stable, xml based name (`user-file/<xpath>`), which is also written back into the field value so the renderer can resolve the image by value alone, consistent with file-widget uploads. - `nodesToJs` no longer sets `[type=binary]` to ''. - `bindJsonToXml` skips binding into `[type=binary]` for empty & attachmentment name reference. inline base64 still binds. - `xmlToDocs` attaches `[type=binary]` blob under the xpath-derived name and rewrites the element text to that name. - `getImagePath` gets the value directly when it starts with `user-file/` and preserves the legacy fetch path Existing data behavior: - Pre-existing docs with `<binary>=""` and a `user-file/<xpath>` attachment, gets overwrite-in-place on edit-re-save as the base64 is supplied for re-attachment under the same xpath-derived key. - Un-edited legacy main-doc records continue to render via the legacy `user-file/<label-path>` fallback in `getImagePath`. - Sub-doc image rendering, previously broken because the parent-form prefix was unreachable from sub-doc field paths, now works once the field has been rewrittento the literal attachment name. - `calculate`-derived per-doc base64 is preserved across edits via re-computation at Enketo's form-init
The report path was searching [type=binary] for file-widget filenames, so modern [type=file] widgets in sub-docs fell back to the main report doc. Narrow both report and contact paths to [type=file] (inline binaries are handled by their own loops).
A media field's value is now uniformly its attachment name minus the
USER_FILE_PREFIX, for both file-widget uploads and inline-binary fields.
- export USER_FILE_PREFIX from enketo.service; use it for both file and
inline-binary attachment names (binary -> user-file-<formId>/<xpath>/<field>)
- store the bare reference (<formId>/<xpath>/<field>) as the binary field value
- add EnketoTranslationService.isAttachmentRef (path-pattern regex) and use it
in the three former startsWith('user-file/') guards
- remove the dedicated user-file/ branch from getImagePath; the bare value
resolves through the unified user-file- + value branch
- reduce processAllAttachments cognitive complexity (extract helpers)
- reduce bindJsonToXml cognitive complexity (extract shouldSkipBinaryBind,
bindArrayToXml, bindObjectToXml)
- namespace report sub-doc binaries by ownerDoc.type
- update unit specs; fix stale type="binary" file-widget fixtures to type="file"
Make the sub-contact badge assertions robust to the exact xpath: verify the inline-binary attachment exists and the field value is that name minus the user-file- prefix, and that the value is preserved unchanged on edit.
Sub-docs carry their own form, so revert attachInlineBinary to `ownerDoc.form || doc.form`. Update the db-doc-with-binary fixture so its sub-docs include a <form> element, matching real sub-report shape.
- fill unit-coverage gaps: binary-in-repeat, empty binary, file dedup - gitignore tmep folder - tests hygiene: variable renaming and comments clean up
19e33c9 to
d3f9c15
Compare



Description
Every uploaded file is attached to the main doc regardless of the sibling (contact) or child doc it was uploaded in. For example, if you upload a photo inside a CHW (sibling) form during a health CHW Area creation, the photo is attached to the CHW Area doc.
This PR fixes that for contact forms only by
Closes #10903
Code review checklist
can_view_old_navigationpermission to see the old design. Test it has appropriate design for RTL languages.License
The software is provided under AGPL-3.0. Contributions to this project are accepted under the same license.