diff --git a/docs/REPORT BUILDER/reports-examples/_order.yaml b/docs/REPORT BUILDER/reports-examples/_order.yaml index b4ef2010..19869665 100644 --- a/docs/REPORT BUILDER/reports-examples/_order.yaml +++ b/docs/REPORT BUILDER/reports-examples/_order.yaml @@ -15,6 +15,7 @@ - repeatable-field-child-records - resize - signature +- sketches - section - modifying-the-widthheight-of-the-table - timezone diff --git a/docs/REPORT BUILDER/reports-examples/sketches.md b/docs/REPORT BUILDER/reports-examples/sketches.md new file mode 100644 index 00000000..cebce1bc --- /dev/null +++ b/docs/REPORT BUILDER/reports-examples/sketches.md @@ -0,0 +1,60 @@ +--- +title: Sketches +excerpt: "" +deprecated: false +hidden: false +metadata: + title: "" + description: "" + robots: noindex +next: + description: "" +--- + +## Display Sketches in Reports + +In the BODY section, search for `element.isSketchElement`. If it doesn't exist, you can add it to your `RENDERVALUES` loop. + +```javascript +<% } else if (element.isSketchElement) { %> +
+

<%= element.label %>

+
+ <% value && value.items.forEach((item, index) => { %> + + <% if (item.caption) { %> +

<%= item.caption %>

+ <% } %> <% }); %> +
+
+<% } %> +``` + +## Resize Sketches + +You can control the size of sketches in the STYLES section by targeting the `.sketch` class. + +```css +.sketch { + max-width: 100%; + height: auto; +} +``` + +## Accessing a specific sketch by its field name + +If you want to display the first sketch from a specific field: + +```javascript +
+ <% + var sketchField = record.formValues.find('my_sketch_field'); + var sketchId = sketchField && sketchField.items[0] && sketchField.items[0].mediaID; + %> + <% if (sketchId) { %> +
+ +
+ <% } %> +
+``` diff --git a/docs/REPORT BUILDER/reports-introduction/functions.md b/docs/REPORT BUILDER/reports-introduction/functions.md index 39afe8e6..9dc4a587 100644 --- a/docs/REPORT BUILDER/reports-introduction/functions.md +++ b/docs/REPORT BUILDER/reports-introduction/functions.md @@ -1,15 +1,16 @@ --- title: Functions -excerpt: '' +excerpt: "" deprecated: false hidden: false metadata: - title: '' - description: '' + title: "" + description: "" robots: index next: - description: '' + description: "" --- + ## API Make a Fulcrum [REST API](https://fulcrum.readme.io/reference) call @@ -27,10 +28,10 @@ String ### Examples ```js -API('/choice_lists', {qs: {per_page: 1}}) +API("/choice_lists", { qs: { per_page: 1 } }); ``` -*** +--- ## AUDIOURL @@ -49,10 +50,10 @@ String ### Examples ```js -AUDIOURL($my_audio_field[0].audio_id, {version: 'original'}) +AUDIOURL($my_audio_field[0].audio_id, { version: "original" }); ``` -*** +--- ## FORMATDATE @@ -71,10 +72,10 @@ String ### Examples ```js -FORMATDATE(new Date()) +FORMATDATE(new Date()); ``` -*** +--- ## GET @@ -93,10 +94,10 @@ String ### Examples ```js -GET('https://jsonplaceholder.typicode.com/posts', {qs: {userId: 1}}) +GET("https://jsonplaceholder.typicode.com/posts", { qs: { userId: 1 } }); ``` -*** +--- ## GETBLOB @@ -115,10 +116,10 @@ String ### Examples ```js -GETBLOB('https://learn.fulcrumapp.com/img/branding/fulcrum-icon.png') +GETBLOB("https://learn.fulcrumapp.com/img/branding/fulcrum-icon.png"); ``` -*** +--- ## JSONREQUEST @@ -135,10 +136,13 @@ String ### Examples ```js -JSONREQUEST({url: 'https://jsonplaceholder.typicode.com/posts', qs: {userId: 1}}) +JSONREQUEST({ + url: "https://jsonplaceholder.typicode.com/posts", + qs: { userId: 1 }, +}); ``` -*** +--- ## LOG @@ -155,10 +159,10 @@ String ### Examples ```js -LOG('Hello World') +LOG("Hello World"); ``` -*** +--- ## PHOTOURL @@ -177,10 +181,10 @@ String ### Examples ```js -PHOTOURL($my_photo_field[0].photo_id, {version: 'thumb'}) +PHOTOURL($my_photo_field[0].photo_id, { version: "thumb" }); ``` -*** +--- ## QS @@ -202,7 +206,7 @@ QS({name: "Robert", age: "20"} // name=Robert&age=20 ``` -*** +--- ## QUERY @@ -221,10 +225,10 @@ String ### Examples ```js -QUERY('SELECT name FROM forms', {format: 'json'}) +QUERY("SELECT name FROM forms", { format: "json" }); ``` -*** +--- ## QUERYVALUE @@ -241,10 +245,10 @@ String ### Examples ```js -QUERYVALUE(`SELECT form_id FROM forms WHERE name = '${form.name}'`) +QUERYVALUE(`SELECT form_id FROM forms WHERE name = '${form.name}'`); ``` -*** +--- ## RENDER @@ -252,7 +256,7 @@ The RENDER function is created automatically in all new advanced report template ### Parameters -`feature` Record or RepeatableItemValue (**required**) - The feature you are looking to render. +`feature` Record or RepeatableItemValue (**required**) - The feature you are looking to render. `options` System level variable that does not need to be defined. @@ -263,7 +267,12 @@ The RENDER function is created automatically in all new advanced report template ### Function Definition ```javascript -const RENDER = (feature, options, eachFunction, {container, parent, index, allValues} = {}) => { +const RENDER = ( + feature, + options, + eachFunction, + { container, parent, index, allValues } = {}, +) => { if (!container) { container = feature.formValues.container; } @@ -275,40 +284,74 @@ const RENDER = (feature, options, eachFunction, {container, parent, index, allVa for (const element of container.elements) { const formValue = feature.formValues.get(element.key); - const renderSection = element.isSectionElement ? () => { - global.RENDER(feature, options, eachFunction, {container: element, parent, feature, index, allValues}); - } : null; - - const renderRepeatableItems = element.isRepeatableElement ? (eachItemFunction) => { - if (!formValue) { - return; - } - - for (let i = 0; i < formValue.items.length; ++i) { - const item = formValue.items[i]; - - const newAllValues = allValues.copy(); - - newAllValues.merge(item.formValues); - newAllValues.merge(feature.formValues); // Add parent values too - - const renderItem = () => { - global.RENDER(item, options, eachFunction, {container: element, parent: feature, feature: item, index: i, allValues: newAllValues}); - }; - - eachItemFunction({element, value: item, renderItem, container: element, parent: feature, feature: item, index: i, allValues: newAllValues}); - } - } : null; + const renderSection = element.isSectionElement + ? () => { + global.RENDER(feature, options, eachFunction, { + container: element, + parent, + feature, + index, + allValues, + }); + } + : null; + + const renderRepeatableItems = element.isRepeatableElement + ? (eachItemFunction) => { + if (!formValue) { + return; + } + + for (let i = 0; i < formValue.items.length; ++i) { + const item = formValue.items[i]; + + const newAllValues = allValues.copy(); + + newAllValues.merge(item.formValues); + newAllValues.merge(feature.formValues); // Add parent values too + + const renderItem = () => { + global.RENDER(item, options, eachFunction, { + container: element, + parent: feature, + feature: item, + index: i, + allValues: newAllValues, + }); + }; + + eachItemFunction({ + element, + value: item, + renderItem, + container: element, + parent: feature, + feature: item, + index: i, + allValues: newAllValues, + }); + } + } + : null; if (eachFunction) { - eachFunction({element, value: formValue, renderSection, renderRepeatableItems, container, feature, index, parent, allValues}); + eachFunction({ + element, + value: formValue, + renderSection, + renderRepeatableItems, + container, + feature, + index, + parent, + allValues, + }); } } }; - ``` -*** +---
@@ -330,58 +373,69 @@ JSON - the feature `elements` and `values` ### Examples -```html -<% RENDERVALUES(record, null, function(element, value) { %> - <% if (element.isSectionElement) { %> -

<%= element.label %>

- <% } else if (element.isRepeatableElement) { %> - <% if (value.length) { %> -

<%= element.label %> <%= value && `(${value.displayValue})` %>

- <% } else { %> -

<%= value && value.displayValue %>

- <% } %> - <% } else if (element.isPhotoElement) { %> -
-

<%= element.label %>

-
- <% value && value.items.forEach((item, index) => { %> - - <% if (item.caption) { %> -

<%= item.caption %>

- <% } %> - <% }); %> -
-
- <% } else if (element.isSignatureElement) { %> -
-

<%= element.label %>

- <% if (value && !value.isEmpty) { %> -
- - <% if (value.timestamp) { %> -

<%= element.agreementText %>

-

Signed <%= FORMATDATE(value.timestamp) %>

- <% } %> -
- <% } %> -
- <% } else if (element.isRecordLinkElement) { %> -
-

<%= element.label %>

- <% if (value && !value.isEmpty) { %> -
<%= value.items.map(item => item.displayValue).join(', ') %>
- <% } %> -
- <% } else { %> -
-

<%= element.label %>

-
<%= value && value.displayValue %>
-
+<% RENDERVALUES(record, null, function(element, value) { %> <% if +(element.isSectionElement) { %> + +

<%= element.label %>

+<% } else if (element.isRepeatableElement) { %> <% if (value.length) { %> +

+ <%= element.label %> <%= value && `(${value.displayValue})` %> +

+<% } else { %> +

<%= value && value.displayValue %>

+<% } %> <% } else if (element.isPhotoElement) { %> +
+

<%= element.label %>

+
+ <% value && value.items.forEach((item, index) => { %> + + <% if (item.caption) { %> +

<%= item.caption %>

+ <% } %> <% }); %> +
+
+<% } else if (element.isSketchElement) { %> +
+

<%= element.label %>

+
+ <% value && value.items.forEach((item, index) => { %> + + <% if (item.caption) { %> +

<%= item.caption %>

+ <% } %> <% }); %> +
+
+<% } else if (element.isSignatureElement) { %> +
+

<%= element.label %>

+ <% if (value && !value.isEmpty) { %> +
+ + <% if (value.timestamp) { %> +

<%= element.agreementText %>

+

Signed <%= FORMATDATE(value.timestamp) %>

+ <% } %> +
<% } %> -<% }) %> +
+<% } else if (element.isRecordLinkElement) { %> +
+

<%= element.label %>

+ <% if (value && !value.isEmpty) { %> +
+ <%= value.items.map(item => item.displayValue).join(', ') %> +
+ <% } %> +
+<% } else { %> +
+

<%= element.label %>

+
<%= value && value.displayValue %>
+
+<% } %> <% }) %> ``` -*** +---
@@ -402,10 +456,34 @@ String ### Examples ```js -SIGNATUREURL($my_signature_field.signature_id, {version: 'original'}) +SIGNATUREURL($my_signature_field.signature_id, { version: "original" }); ``` -*** +--- + +
+ +## SKETCHURL + +Generate a public sketch URL + +### Parameters + +`id` String (**required**) - The ID of the sketch + +`options` Object - `{version: 'large', expires: null}` + +### Returns + +String + +### Examples + +```js +SKETCHURL($my_sketch_field[0].sketch_id, { version: "large" }); +``` + +--- ## STATICMAP @@ -430,14 +508,16 @@ STATICMAP({mapEngine: ‘google’,markers: '34.052230,-118.243680', maptype: 'h ``` ```js Esri - + ``` ```html - + ``` -*** +--- ## TOJSON @@ -454,10 +534,10 @@ String ### Examples ```js -TOJSON(API('/choice_lists').choice_lists[0].name) +TOJSON(API("/choice_lists").choice_lists[0].name); ``` -*** +--- ## VIDEOURL @@ -476,5 +556,5 @@ String ### Examples ```js -VIDEOURL($my_video_field[0].video_id, {version: 'original'}) +VIDEOURL($my_video_field[0].video_id, { version: "original" }); ``` diff --git a/reference/ATTACHMENTS/_order.yaml b/reference/ATTACHMENTS/_order.yaml index bbe2c045..72739aae 100644 --- a/reference/ATTACHMENTS/_order.yaml +++ b/reference/ATTACHMENTS/_order.yaml @@ -3,4 +3,5 @@ - get-single-attachment - create-attachment - finalize-attachment +- copy-all-attachments - delete-attachment diff --git a/reference/ATTACHMENTS/copy-all-attachments.md b/reference/ATTACHMENTS/copy-all-attachments.md new file mode 100644 index 00000000..20e1d6b5 --- /dev/null +++ b/reference/ATTACHMENTS/copy-all-attachments.md @@ -0,0 +1,23 @@ +--- +title: Copy All Reference Files +excerpt: >- + Copy all reference files from one form to another. +api: + file: rest-api.json + operationId: copy-all-attachments +deprecated: false +hidden: false +metadata: + title: "" + description: "" + robots: noindex +next: + description: "" +--- + +This endpoint allows you to copy all reference files from a source form to a destination form. + +# Limits + +- **100 reference files** per form. +- **1GB** total reference file size per form. diff --git a/reference/rest-api.json b/reference/rest-api.json index 0a342280..c4930255 100644 --- a/reference/rest-api.json +++ b/reference/rest-api.json @@ -511,6 +511,43 @@ }, "description": "Location metadata captured at creation or update time." }, + "AttachmentCopyAllRequest": { + "type": "object", + "required": [ + "source_parent_id", + "destination_parent_id", + "parent_type" + ], + "properties": { + "source_parent_id": { + "type": "string", + "description": "The ID of the source parent (e.g. form ID) to copy reference files from" + }, + "destination_parent_id": { + "type": "string", + "description": "The ID of the destination parent (e.g. form ID) to copy reference files to" + }, + "parent_type": { + "type": "string", + "description": "The type of the parent resource", + "enum": [ + "form" + ] + } + } + }, + "AttachmentCopyAllResponse": { + "type": "object", + "properties": { + "ref_file_mapping": { + "type": "object", + "description": "A mapping of original reference file attachment IDs to their new copies", + "additionalProperties": { + "type": "string" + } + } + } + }, "AttachmentCreateRequest": { "type": "object", "required": [ @@ -10211,6 +10248,46 @@ "deprecated": false } }, + "/v2/attachments/copy_all": { + "post": { + "summary": "Copy all reference files", + "description": "Copy all reference files from one form to another. Limits: 100 reference files per form, 1GB total per form.", + "operationId": "copy-all-attachments", + "parameters": [ + { + "name": "X-ApiToken", + "in": "header", + "description": "API Token. Required to authenticate the request.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AttachmentCopyAllRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AttachmentCopyAllResponse" + } + } + } + } + } + } + }, "/v2/attachments/finalize": { "post": { "summary": "Finalize Attachment",