Three shared features work on every record card of the web app: a Documents row (docs.section) that attaches files to the record, an in-app viewer that opens files instead of downloading them, and a share sheet. This page lists the calls each feature makes and the rules it follows. The documents module itself is on documents module.
Scope and source¶
- Defined in:
webapp/js/record-docs.js(recordDocsRow,makeRecordDocsScreen,makeAddDocView,createDocsCollector),webapp/js/viewer.js(openViewer,openViewerFromPath,registerRenderer,triggerDownload),webapp/js/vendor/pdfjs/,webapp/js/share.js(openShareSheet,buildRecordShare,buildRecordsShare) - Count: 2 viewer renderers (
registerRenderercalls inwebapp/js/viewer.js:151andwebapp/js/viewer.js:381); 3 share targets (webapp/js/share.js:84-86)
Record documents¶
Provider lookup¶
The documents feature never names the documents module. docsProvider() asks providerOf('record_documents') for the module that declares the capability in ModuleMeta.provides, and builds the list and type paths from that module's entity metadata (webapp/js/record-docs.js:23-37). Permission codes are <entity_type>.read, .create, and .delete of the provider's entity (webapp/js/record-docs.js:40). tests/test_metadata_driven_rules.py:63 checks that the provider is declared by capability.
Calls¶
| Step | Call | Source |
|---|---|---|
| Show the row with a count | GET <documents list>?entity_type=<type>&entity_id=<id>&limit=1 |
webapp/js/record-docs.js:294-326 |
| List a record's documents | GET <documents list>?entity_type=<type>&entity_id=<id>&limit=200 |
webapp/js/record-docs.js:58-63 |
| Load document types | GET <types list>?active_only=true |
webapp/js/record-docs.js:106, webapp/js/record-docs.js:207 |
| Add a document | POST <documents list>, then POST /attachments/ with the file, then POST <documents list><doc_id>/versions |
webapp/js/record-docs.js:103-194 |
| Open or download | GET <documents list><doc_id>/versions, then GET /attachments/<attachment_id>/download of the active version, else the newest |
webapp/js/record-docs.js:65-78 |
| Remove | DELETE <documents list><doc_id> after a confirm |
webapp/js/record-docs.js:262-280 |
The row appears on a record card unless the entity sets record_documents to false (webapp/js/gen-form.js:2477-2483), and only when a provider exists and the user holds its read permission (webapp/js/record-docs.js:294-296). An entity with create_with_documents collects documents on its create form through createDocsCollector and attaches them after the record exists (webapp/js/record-docs.js:328-457, webapp/js/gen-form.js:1914-1920). Attachments are stored by the platform; see attachments, notes, and storage.
Document viewer¶
openViewer({title, blob, contentType, filename}) pushes a viewer screen and picks a renderer by content type and file extension. Later registered renderers win ties (webapp/js/viewer.js:14-28, webapp/js/viewer.js:89-125).
| Renderer | Matches | Features | Source |
|---|---|---|---|
pdf |
application/pdf or .pdf |
Pages rendered to canvas, page indicator and navigation, zoom, download | webapp/js/viewer.js:151-380 |
image |
image/* or .png, .jpg, .jpeg, .gif, .webp, .svg |
Image display and download | webapp/js/viewer.js:381-456 |
A file without a matching renderer shows viewer.unsupported with a download button; a renderer failure shows viewer.error with the same button (webapp/js/viewer.js:98-123). openViewerFromPath fetches a path as an authenticated blob first (webapp/js/viewer.js:127-133). A metadata action with a GET endpoint opens its result in the viewer; see actions and action sheet.
The PDF library is imported only when a PDF is opened. Its worker runs from webapp/js/vendor/pdfjs/pdf.worker.min.mjs (webapp/js/viewer.js:134-149). The vendored build is pdfjs-dist 6.2.108 under the Apache-2.0 licence (webapp/js/vendor/pdfjs/README.txt).
Share sheet¶
openShareSheet(ctx) raises a bottom sheet with a summary of one or more records and three targets (webapp/js/share.js:80-140).
| Target | Label key | State | Effect | Source |
|---|---|---|---|---|
share.mail |
live | Dispatches cluster:share-via-mail with a subject and body |
webapp/js/share.js:84, webapp/js/share.js:124-131 |
|
| Message | share.message |
not live | Shows Coming soon (common.coming_soon) |
webapp/js/share.js:85, webapp/js/share.js:132-134 |
share.print |
not live | Shows Coming soon | webapp/js/share.js:86, webapp/js/share.js:132-134 |
buildRecordShare makes the subject <entity label>: <record title> and a body of up to 14 Label: value lines from simple form fields. buildRecordsShare lists several records with up to 6 lines each (webapp/js/share.js:15-57). Identifiers, files, and relations are left out because only simple field types are read (webapp/js/share.js:15-33). The home screen handles cluster:share-via-mail by queuing a prefilled draft and opening the Mail app (webapp/js/home.js:4658-4665).
Share is offered from a record card's navigation bar and from a list's selection bar (webapp/js/gen-form.js:2330-2333, webapp/js/gen-list.js:641-643).
Constraints and validation¶
- A document without a file version shows
docs.no_fileinstead of opening (webapp/js/record-docs.js:69-73). - Object URLs created for blobs are revoked after use (
webapp/js/viewer.js:37-47,webapp/js/avatar.js:37-38). - Browser tests:
web-client/_e2e_record_docs.mjs,web-client/_e2e_doc_viewer.mjs,web-client/_e2e_doc_version.mjs,web-client/_e2e_intranet_mydocs.mjs.
Terms introduced¶
| Term | Code identifier | Definition | Turkish term | Source |
|---|---|---|---|---|
| record documents | record_documents |
Files attached to any record through the documents provider. | Belgeler | webapp/js/record-docs.js:26 |
| document viewer | openViewer |
The in-app screen that renders a file by its type. | belge görüntüleyici | webapp/js/viewer.js:89 |
| share sheet | openShareSheet |
The bottom sheet that sends a record summary to a target. | paylaşım kartı | webapp/js/share.js:80 |
Related pages¶
- Web app platform
- Generic form
- Mail and profile screens
- Documents module
- Attachments, notes, and storage
Verified against commit 92f8051 on 2026-11-13.