### Complete Example: Custom Resource Handling in Google Workspace Add-ons (Apps Script) Source: https://developers.google.com/workspace/add-ons/studio/custom-resources This comprehensive example demonstrates the integration of `onConfigResourceFunction`, `onMessageResourceFunction`, and `onExecuteResourceFunction` for managing custom resources within a Google Workspace Add-on. It showcases card building and resource retrieval logic. ```javascript function onConfigResourceFunction() { let section = CardService.newCardSection() .addWidget( CardService.newTextParagraph() .setText("This is the Custom Resource Demo card") ); const card = CardService.newCardBuilder() .addSection(section) .build(); return card; } function onMessageResourceFunction(e) { console.log("Payload in onMessageResourceFunction: " + JSON.stringify(e)); var resource_id = e.workflow.resourceRetrieval.resourceReference.resourceId; let fieldValue_1; let fieldValue_2; // Using a if-condition to mock a database call. if (resource_id == "sample_resource_reference_id") { fieldValue_1 = AddOnsResponseService.newVariableData() .addStringValue("value1"); fieldValue_2 = AddOnsResponseService.newVariableData() .addStringValue("value2"); } else { fieldValue_1 = AddOnsResponseService.newVariableData() .addStringValue("field_1 value not found"); fieldValue_2 = AddOnsResponseService.newVariableData() .addStringValue("field_2 value not found"); } let resourceData = AddOnsResponseService.newResourceData() .addVariableData("field_1", fieldValue_1) .addVariableData("field_2", fieldValue_2) let workflowAction = AddOnsResponseService.newResourceRetrievedAction() .setResourceData(resourceData) let hostAppAction = AddOnsResponseService.newHostAppAction() .setWorkflowAction(workflowAction); return AddOnsResponseService.newRenderActionBuilder() .setHostAppAction(hostAppAction) .build(); } function onExecuteResourceFunction(e) { console.log("Payload in onExecuteResourceFunction: " + JSON.stringify(e)); let outputVariables = AddOnsResponseService.newVariableData() .addResourceReference("sample_resource_reference_id"); let workflowAction = AddOnsResponseService.newReturnOutputVariablesAction() .addVariableData("resource_data", outputVariables); let hostAppAction = AddOnsResponseService.newHostAppAction() .setWorkflowAction(workflowAction); return AddOnsResponseService.newRenderActionBuilder() .setHostAppAction(hostAppAction) .build(); } ``` -------------------------------- ### Configure Calculator Step Manifest (appsscript.json) Source: https://developers.google.com/workspace/add-ons/studio/quickstart-calculator The appsscript.json file defines the manifest for the Google Apps Script project. It specifies project information, add-on details, and the configuration for a custom workflow step named 'Calculate', including its inputs, outputs, and associated functions. ```json { "timeZone": "America/Los_Angeles", "exceptionLogging": "STACKDRIVER", "runtimeVersion": "V8", "addOns": { "common": { "name": "Calculator", "logoUrl": "https://www.gstatic.com/images/branding/productlogos/calculator_search/v1/web-24dp/logo_calculator_search_color_1x_web_24dp.png", "useLocaleFromApp": true }, "flows": { "workflowElements": [ { "id": "actionElement", "state": "ACTIVE", "name": "Calculate", "description": "Asks the user for two values and a math operation, then performs the math operation on the values and outputs the result.", "workflowAction": { "inputs": [ { "id": "value1", "description": "value1", "cardinality": "SINGLE", "dataType": { "basicType": "INTEGER" } }, { "id": "value2", "description": "value2", "cardinality": "SINGLE", "dataType": { "basicType": "INTEGER" } }, { "id": "operation", "description": "operation", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } } ], "outputs": [ { "id": "result", "description": "Calculated result", "cardinality": "SINGLE", "dataType": { "basicType": "INTEGER" } } ], "onConfigFunction": "onConfigCalculateFunction", "onExecuteFunction": "onExecuteCalculateFunction" } } ] } } } ``` -------------------------------- ### Execute Calculator Step Logic (Apps Script) Source: https://developers.google.com/workspace/add-ons/studio/quickstart-calculator_hl=pl Handles the execution of the 'Calculate' step. This function retrieves the input values (two numbers and an operation) and performs the specified calculation. It returns the result of the calculation, which can then be used in subsequent steps. Includes a helper function to safely parse integer values from input. ```Apps Script /** * Gets an integer value from variable data, handling both string and integer formats. * * This function is a utility to safely parse integer inputs from the card configuration. * It checks if the input is already an integer or attempts to parse it if it's a string. * Returns null if the input cannot be converted to an integer. * * @param {string|number} value The input value to parse. * @return {number|null} The parsed integer value, or null if parsing fails. */ function getIntValue(value) { if (typeof value === 'number') { return value; } if (typeof value === 'string') { return parseInt(value, 10); } return null; } /** * Executes the calculation based on the provided inputs. * * This function is triggered when the 'Calculate' step is run. It retrieves * the first value, operation, and second value from the workflow context. * It uses `getIntValue` to parse the numeric inputs and then performs the * calculation based on the selected operation. The result is returned as an output. * * @param {Object} e The event object containing workflow context and inputs. * @return {Object} An object containing the result of the calculation. */ function onExecuteCalculateFunction(e) { var value1 = getIntValue(e.workflow.inputs.value1); var operation = e.workflow.inputs.operation; var value2 = getIntValue(e.workflow.inputs.value2); if (value1 === null || value2 === null || !operation) { throw new Error('Invalid input. Please provide two numbers and an operation.'); } var result; switch (operation) { case '+': result = value1 + value2; break; case '-': result = value1 - value2; break; case 'x': result = value1 * value2; break; case '/': if (value2 === 0) { throw new Error('Division by zero is not allowed.'); } result = value1 / value2; break; default: throw new Error('Unsupported operation: ' + operation); } return { outputs: { result: result } }; } ``` -------------------------------- ### Google Workspace Studio Calculator Step Configuration and Execution Source: https://developers.google.com/workspace/add-ons/studio/quickstart-calculator This Apps Script code defines a custom step for Google Workspace Studio. It includes functions to build the configuration UI using cards, handle user input for a calculator, and execute the calculation logic. The `onConfigCalculateFunction` sets up the UI with input fields and a dropdown for operations, while `onExecuteCalculateFunction` performs the actual calculation based on the provided inputs. ```javascript /** * This script defines a custom step for Google Workspace Studio. * The step, named "Calculate", takes two numbers and an operation as input * and returns the result of the calculation. * * The script includes functions to: * * 1. Define the configuration UI for the step using Card objects: * * - `onConfigCalculateFunction()`: Generates the main configuration card. * - Helper functions like `pushCard()`, `saveButton()` to build card components. * * 2. Handle the execution of the step. * * - `onExecuteCalculateFunction()`: Retrieves inputs, performs the calculation, * and returns outputs. * * To learn more, see the following quickstart guide: * https://developers.google.com/workspace/add-ons/studio/quickstart */ /** * Creates an action response to push a new card onto the card stack. * * This function generates an action object that, when returned, causes the * provided card to be pushed onto the card stack, making it the currently * displayed card in the configuration UI. * @param {Object} card The Card object to push. * @return {Object} The action response object. */ function pushCard(card) { return { "action": { "navigations": [{ "push_card": card } ] } }; } /** * Creates an action response to update the currently displayed card. * * This function generates an action object that, when returned, causes the * currently displayed card to be replaced with the provided card in the * configuration UI. * @param {Object} card The Card object to update. * @return {Object} The render actions object. */ function updateCard(card) { return { "render_actions": { "action": { "navigations": [{ "update_card": card } ] } } }; } /** * Creates a button configuration object for saving the step. * * This function generates a button definition that, when clicked, triggers * a save action for the current step configuration. * @return {Object} The button widget object. */ function saveButton() { return { "text": "Save", "onClick": { "hostAppAction" : { "workflowAction" : { "saveWorkflowAction" : {} } } }, }; } /** * Creates a button configuration object for a refresh action. * * This function generates a button definition that, when clicked, triggers * a function to refresh the current card. * @param {string} functionName The name of the Apps Script function to call on click. * @return {Object} The button widget object. */ function refreshButton(functionName) { return { "text": "Refresh", "onClick": { "action" : { "function" : functionName } }, }; } /** * Generates and displays a configuration card for the sample calculation action. * * This function creates a card with input fields for two values and a dropdown * for selecting an arithmetic operation. The card also includes a "Save" * button to save the action configuration for the step. * * The input fields are configured to let the user select outputs from previous * steps as input values using the `hostAppDataSource` property. * This function is called when the user adds or edits the "Calculate" step in the UI. * @return {Object} The action response object containing the card to display. */ function onConfigCalculateFunction() { var card = { "sections": [ { "header": "Action sample: Calculate", "widgets": [ { "textInput": { "name": "value1", "label": "First value", "hostAppDataSource" : { "workflowDataSource" : { "includeVariables" : true } } } }, { "selectionInput": { "name": "operation", "label": "Operation", "type": "DROPDOWN", "items": [ { "text": "+", "value": "+", }, { "text": "-", "value": "-", }, { "text": "x", "value": "x", }, { "text": "/", "value": "/", } ] } }, { "textInput": { "name": "value2", "label": "Second value", "hostAppDataSource" : { "workflowDataSource" : { "includeVariables" : true } } } } ] } ] }; return pushCard(card); } /** * Gets an integer value from variable data, handling both string and integer formats. * */ ``` -------------------------------- ### Configure Calculator Step UI (Apps Script) Source: https://developers.google.com/workspace/add-ons/studio/quickstart-calculator_hl=fr Defines the user interface for the 'Calculate' step in Google Workspace Studio. It creates a configuration card with input fields for two values and a dropdown for selecting an arithmetic operation. The UI allows users to select outputs from previous steps as input values. This function is invoked when the user adds or edits the 'Calculate' step. ```Apps Script /** * Generates and displays a configuration card for the sample calculation action. * * This function creates a card with input fields for two values and a dropdown * for selecting an arithmetic operation. The card also includes a "Save" * button to save the action configuration for the step. * * The input fields are configured to let the user select outputs from previous * steps as input values using the `hostAppDataSource` property. * This function is called when the user adds or edits the "Calculate" step in the UI. * @return {Object} The action response object containing the card to display. */ function onConfigCalculateFunction() { var card = { "sections": [ { "header": "Action sample: Calculate", "widgets": [ { "textInput": { "name": "value1", "label": "First value", "hostAppDataSource" : { "workflowDataSource" : { "includeVariables" : true } } } }, { "selectionInput": { "name": "operation", "label": "Operation", "type": "DROPDOWN", "items": [ { "text": "+", "value": "+", }, { "text": "-", "value": "-", }, { "text": "x", "value": "x", }, { "text": "/", "value": "/", } ] } }, { "textInput": { "name": "value2", "label": "Second value", "hostAppDataSource" : { "workflowDataSource" : { "includeVariables" : true } } } } ] } ] }; return pushCard(card); } ``` -------------------------------- ### Configure Calculator Step UI (Apps Script) Source: https://developers.google.com/workspace/add-ons/studio/quickstart-calculator_hl=pl Defines the user interface for the 'Calculate' step in Google Workspace Studio. It uses Card objects to create input fields for two values and a dropdown for selecting an operation. Includes a save button to finalize the configuration. This function is invoked when the user adds or edits the 'Calculate' step. ```Apps Script /** * Creates an action response to push a new card onto the card stack. * * This function generates an action object that, when returned, causes the * provided card to be pushed onto the card stack, making it the currently * displayed card in the configuration UI. * @param {Object} card The Card object to push. * @return {Object} The action response object. */ function pushCard(card) { return { "action": { "navigations": [{ "push_card": card } ] } }; } /** * Creates an action response to update the currently displayed card. * * This function generates an action object that, when returned, causes the * currently displayed card to be replaced with the provided card in the * configuration UI. * @param {Object} card The Card object to update. * @return {Object} The render actions object. */ function updateCard(card) { return { "render_actions": { "action": { "navigations": [{ "update_card": card } ] } } }; } /** * Creates a button configuration object for saving the step. * * This function generates a button definition that, when clicked, triggers * a save action for the current step configuration. * @return {Object} The button widget object. */ function saveButton() { return { "text": "Save", "onClick": { "hostAppAction" : { "workflowAction" : { "saveWorkflowAction" : {} } } }, }; } /** * Creates a button configuration object for a refresh action. * * This function generates a button definition that, when clicked, triggers * a function to refresh the current card. * @param {string} functionName The name of the Apps Script function to call on click. * @return {Object} The button widget object. */ function refreshButton(functionName) { return { "text": "Refresh", "onClick": { "action" : { "function" : functionName } }, }; } /** * Generates and displays a configuration card for the sample calculation action. * * This function creates a card with input fields for two values and a dropdown * for selecting an arithmetic operation. The card also includes a "Save" * button to save the action configuration for the step. * * The input fields are configured to let the user select outputs from previous * steps as input values using the `hostAppDataSource` property. * This function is called when the user adds or edits the "Calculate" step in the UI. * @return {Object} The action response object containing the card to display. */ function onConfigCalculateFunction() { var card = { "sections": [ { "header": "Action sample: Calculate", "widgets": [ { "textInput": { "name": "value1", "label": "First value", "hostAppDataSource" : { "workflowDataSource" : { "includeVariables" : true } } } }, { "selectionInput": { "name": "operation", "label": "Operation", "type": "DROPDOWN", "items": [ { "text": "+", "value": "+", }, { "text": "-", "value": "-", }, { "text": "x", "value": "x", }, { "text": "/", "value": "/", } ] } }, { "textInput": { "name": "value2", "label": "Second value", "hostAppDataSource" : { "workflowDataSource" : { "includeVariables" : true } } } } ] } ] }; return pushCard(card); } ``` -------------------------------- ### Helper Functions for UI Navigation and Buttons (Apps Script) Source: https://developers.google.com/workspace/add-ons/studio/quickstart-calculator_hl=fr Provides utility functions for managing the card stack and creating interactive buttons within the Google Workspace Studio UI. `pushCard` adds a new card, `updateCard` replaces the current one, `saveButton` creates a save action, and `refreshButton` creates a refresh action linked to a specified function. ```Apps Script /** * Creates an action response to push a new card onto the card stack. * * This function generates an action object that, when returned, causes the * provided card to be pushed onto the card stack, making it the currently * displayed card in the configuration UI. * @param {Object} card The Card object to push. * @return {Object} The action response object. */ function pushCard(card) { return { "action": { "navigations": [{ "push_card": card } ] } }; } /** * Creates an action response to update the currently displayed card. * * This function generates an action object that, when returned, causes the * currently displayed card to be replaced with the provided card in the * configuration UI. * @param {Object} card The Card object to update. * @return {Object} The render actions object. */ function updateCard(card) { return { "render_actions": { "action": { "navigations": [{ "update_card": card } ] } } }; } /** * Creates a button configuration object for saving the step. * * This function generates a button definition that, when clicked, triggers * a save action for the current step configuration. * @return {Object} The button widget object. */ function saveButton() { return { "text": "Save", "onClick": { "hostAppAction" : { "workflowAction" : { "saveWorkflowAction" : {} } } }, }; } /** * Creates a button configuration object for a refresh action. * * This function generates a button definition that, when clicked, triggers * a function to refresh the current card. * @param {string} functionName The name of the Apps Script function to call on click. * @return {Object} The button widget object. */ function refreshButton(functionName) { return { "text": "Refresh", "onClick": { "action" : { "function" : functionName } }, }; } ``` -------------------------------- ### Handle Autocomplete Request and Return Suggestions (Apps Script) Source: https://developers.google.com/workspace/add-ons/studio/configuration-cards Implements the function triggered by server-side autocomplete. This function checks the invoked function name, retrieves user input, queries an external data source, and returns up to 100 suggestions in the required format. The example shows how to construct suggestions with text, values, icons, and descriptions. ```Apps Script function handleAutocompleteRequest(event) { var invokedFunction = event.workflow.elementUiAutocomplete.invokedFunction; var query = event.workflow.elementUiAutocomplete.query; if (invokedFunction != "getAutocompleteResults" || query == undefined || query == "") { return {}; } // Query your data source to get results based on the query let autocompleteResponse = AddOnsResponseService.newUpdateWidget() .addSuggestion( query + " option 1", query + "_option1", false, "https://developers.google.com/workspace/add-ons/images/person-icon.png", "option 1 bottom text" ) .addSuggestion( query + " option 2", query + "_option2", false, "https://developers.google.com/workspace/add-ons/images/person-icon.png", "option 2 bottom text" ).addSuggestion( query + " option 3", query + "_option3", false, "https://developers.google.com/workspace/add-ons/images/person-icon.png", "option 3 bottom text" ); const modifyAction = AddOnsResponseService.newAction() .addModifyCard( AddOnsResponseService.newModifyCard() .setUpdateWidget(autocompleteResponse) ); return AddOnsResponseService.newRenderActionBuilder() .setAction(modifyAction) .build(); } // In your onConfig function, handle the autocomplete event function onConfigAutocompleteTest(event) { // Handle autocomplete request if (event.workflow && event.workflow.elementUiAutocomplete) { return handleAutocompleteRequest(event); } // ... rest of your card building logic ... } ``` -------------------------------- ### Define Calculator Step Logic (Calculator.gs) Source: https://developers.google.com/workspace/add-ons/studio/quickstart-calculator The Calculator.gs file contains the Google Apps Script code to define a custom step for Google Workspace Studio. This step, named 'Calculate', handles the logic for taking two numbers and an arithmetic operation as input and returning the computed result. ```javascript // This file defines the custom step for Google Workspace Studio. // It includes functions to handle the configuration and execution of the calculator step. /** * Configuration function for the calculator step. * This function is called when the user configures the step in Workspace Studio. * @param {Object} e The event object. * @return {Object} The configuration card. */ function onConfigCalculateFunction(e) { // Implementation for configuration card goes here // This would typically involve returning a CardService.newCardBuilder() object // to define the UI for configuring the step. return CardService.newCardBuilder().build(); } /** * Execution function for the calculator step. * This function is called when the user executes the step in Workspace Studio. * @param {Object} e The event object containing inputs. * @return {Object} The result of the calculation. */ function onExecuteCalculateFunction(e) { const eventObject = e; const { value1, value2, operation } = eventObject.parameters; let result; switch (operation) { case '+': result = value1 + value2; break; case '-': result = value1 - value2; break; case '*': result = value1 * value2; break; case '/': if (value2 === 0) { throw new Error('Division by zero is not allowed.'); } result = value1 / value2; break; default: throw new Error(`Unsupported operation: ${operation}`); } return { 'result': result }; } ``` -------------------------------- ### Configure SelectionInput for Server Autocomplete (Apps Script) Source: https://developers.google.com/workspace/add-ons/studio/configuration-cards Configures a SelectionInput widget to use server-side autocomplete by specifying a remote data source. This requires defining a `DataSourceConfig` pointing to an Apps Script function that will fetch suggestions. The example demonstrates setting up a multi-select input with a maximum of 3 selected items. ```Apps Script // In your onConfig function: var multiSelect1 = CardService.newSelectionInput() .setFieldName("value1") .setTitle("Server Autocomplete") .setType(CardService.SelectionInputType.MULTI_SELECT) .setMultiSelectMaxSelectedItems(3) .addDataSourceConfig( CardService.newDataSourceConfig() .setRemoteDataSource( CardService.newAction().setFunctionName('getAutocompleteResults') ) ) .addDataSourceConfig( CardService.newDataSourceConfig() .setPlatformDataSource( CardService.newPlatformDataSource() .setHostAppDataSource( CardService.newHostAppDataSource() .setWorkflowDataSource( CardService.newWorkflowDataSource() .setIncludeVariables(true) )) ) ); // ... add widget to card ... ``` -------------------------------- ### Configure TextInput with RICH_TEXT and PLAIN_TEXT modes in JSON Manifest Source: https://developers.google.com/workspace/add-ons/studio/input-variables Defines the structure for TextInput widgets within a Google Workspace Add-on's manifest file. It specifies workflow elements, input parameters, and data types, enabling the configuration of 'Rich Text' and 'Plain text' input modes for user interaction. This JSON configuration is part of the add-on's overall setup. ```json { "timeZone": "America/Toronto", "dependencies": {}, "exceptionLogging": "STACKDRIVER", "runtimeVersion": "V8", "addOns": { "common": { "name": "Text and output variable demo", "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png", "useLocaleFromApp": true }, "flows": { "workflowElements": [ { "id": "richTextDemo", "state": "ACTIVE", "name": "Rich Text Demo", "description": "Show the difference between rich text and plain text TextInput widgets", "workflowAction": { "inputs": [ { "id": "value1", "description": "First user input", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } }, { "id": "value2", "description": "Second user input", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } } ], "onConfigFunction": "onConfiguration", "onExecuteFunction": "onExecution" } } ] } } } ``` -------------------------------- ### Replace CardWidget in Add-ons Studio Source: https://developers.google.com/workspace/add-ons/studio/update-cards Replaces an existing CardWidget in a Google Workspace Add-on card with a new widget of the same ID. This example replaces a text input widget with a new text paragraph widget. ```javascript function replaceWidget(event) { console.log("event: " + JSON.stringify(event, null, 3)); const replacementWidget = CardService.newTextParagraph().setText("This is a replacement widget!").setId("text_input_3"); const modifyAction = AddOnsResponseService.newAction() .addModifyCard(AddOnsResponseService.newModifyCard().setReplaceWidget(replacementWidget)); return AddOnsResponseService.newRenderActionBuilder().setAction(modifyAction).build(); } ``` -------------------------------- ### Workspace Studio resourceRetrieval Event Example Source: https://developers.google.com/workspace/add-ons/studio/event-objects This JSON object demonstrates the structure of an event when a custom resource is requested from a Workspace Studio flow. It details the resource being retrieved, including its type and ID, along with common event information. ```json { "workflow": { "resourceRetrieval": { "resourceReference": { "resourceType": { "workflowBundleId": "workflow_bundle_id", "workflowResourceDefinitionId": "workflow_resource_definition_id" }, "resourceId": "resource_id" } } }, "userLocale": "en", "hostApp": "flows", "clientPlatform": "web", "commonEventObject": { "timeZone": { "offset": -14400000, "id": "America/New_York" }, "userLocale": "en-US", "hostApp": "WORKFLOW", "platform": "WEB" }, "userCountry": "US", "userTimezone": { "id": "America/New_York", "offSet": "-14400000" } } ``` -------------------------------- ### Get Integer Value from Variable Data (Apps Script) Source: https://developers.google.com/workspace/add-ons/studio/quickstart-calculator_hl=es-419 This function is designed to extract an integer value from a variable, accommodating both string and integer formats. It's a utility for safely parsing numerical inputs within the script. ```Apps Script /** * Gets an integer value from variable data, handling both string and integer formats. * */ function getIntValue(variable) { // Implementation details for parsing integer from string or integer would go here. // For example: // if (typeof variable === 'string') { // return parseInt(variable, 10); // } else if (typeof variable === 'number' && Number.isInteger(variable)) { // return variable; // } // return NaN; // Or throw an error if parsing fails } ``` -------------------------------- ### Configure Drive Picker Card and Handle Selection (Apps Script) Source: https://developers.google.com/workspace/add-ons/studio/drive-picker This Apps Script code defines the `onConfig` and `onExecute` functions for a Google Workspace Add-on step. `onConfig` builds a card with a Drive Picker allowing selection of spreadsheets and PDFs. `onExecute` retrieves the selected file ID and returns it as an output variable. ```javascript /** * Returns a configuration card for the step. * This card includes a selection input widget configured as a Google Picker * that lets users select spreadsheets and PDFs. */ function onConfig() { // Allows users to select either spreadsheets or PDFs const driveSpec = CardService.newDriveDataSourceSpec() .addItemType( CardService.DriveItemType.SPREADSHEETS ) .addItemType( CardService.DriveItemType.PDFS ); const platformSource = CardService.newPlatformDataSource() .setCommonDataSource( CardService.CommonDataSource.DRIVE ) .setDriveDataSourceSpec(driveSpec); const selectionInput = CardService.newSelectionInput() .setFieldName("drive_picker_1") .setPlatformDataSource(platformSource) .setTitle("Drive Picker") .setType( CardService.SelectionInputType.MULTI_SELECT ); var sectionBuilder = CardService.newCardSection() .addWidget(selectionInput) return CardService.newCardBuilder() .addSection(sectionBuilder) .build(); } /** * Executes when the step runs. * This function retrieves the file ID of the item selected in the Google Picker * and returns it as an output variable. * @param {Object} event The event object passed by the Flows runtime. * @return {Object} The output variables object. */ function onExecute(event) { //Extract the selected file's ID during execution console.log("eventObject: " + JSON.stringify(event)); var fileId = event.workflow.actionInvocation.inputs["drive_picker_1"].stringValues[0]; const variableData = AddOnsResponseService.newVariableData() .addStringValue(fileId); let textFormatElement = AddOnsResponseService.newTextFormatElement() .setText("A file has been selected!"); let workflowTextFormat = AddOnsResponseService.newWorkflowTextFormat() .addTextFormatElement(textFormatElement); let workflowAction = AddOnsResponseService.newReturnOutputVariablesAction() .addVariableData("fileId", variableData) .setLog(workflowTextFormat); let hostAppAction = AddOnsResponseService.newHostAppAction() .setWorkflowAction(workflowAction); return AddOnsResponseService.newRenderActionBuilder() .setHostAppAction(hostAppAction) .build(); } ``` -------------------------------- ### Workspace Studio actionInvocation Event Example Source: https://developers.google.com/workspace/add-ons/studio/event-objects This JSON object showcases the structure of an event when an action is invoked within a Workspace Studio flow. It includes details about the trigger, the action's inputs, and common event data like user locale and client platform. ```json { "workflow": { "triggerEventSource": "TRIGGER_EVENT_SOURCE_AUTOMATED", "actionInvocation": { "inputs": { "operation": { "stringValues": [ "+" ] }, "value2": { "integerValues": [ 2 ] }, "value1": { "integerValues": [ 2 ] } } } }, "userLocale": "en", "hostApp": "flows", "clientPlatform": "web", "commonEventObject": { "timeZone": { "offset": -14400000, "id": "America/New_York" }, "userLocale": "en-US", "hostApp": "WORKFLOW", "platform": "WEB" }, "userCountry": "US", "userTimezone": { "id": "America/New_York", "offSet": "-14400000" } } ``` -------------------------------- ### Get Integer Value from Variable Data (Apps Script) Source: https://developers.google.com/workspace/add-ons/studio/quickstart-calculator_hl=ja A utility function designed to extract an integer value from variable data. It handles cases where the input might be a string representation of a number or an actual integer, ensuring consistent data type for calculations. ```javascript /** * Gets an integer value from variable data, handling both string and integer formats. * @param {Object} variable The variable object containing the value. * @return {number} The integer value. */ function getIntValue(variable) { if (typeof variable === 'string') { return parseInt(variable, 10); } return variable; } ``` -------------------------------- ### Return Actionable or Non-Actionable Errors in Workspace Add-ons Source: https://developers.google.com/workspace/add-ons/studio/handle-errors This snippet demonstrates how to return an error status for a Workspace Add-on step. You can specify if the error is actionable, allowing users to fix it by returning to the configuration card, or non-actionable. This is crucial for guiding user interaction when errors occur. ```Java return AddOnsResponseService.newCardBuilder() .addSection(Section.newSection() .addWidget(TextParagraph.newTextParagraph("Error message here."))) .setErrorActionability(AddOnsResponseService.ErrorActionability.ACTIONABLE) .build(); // For non-actionable errors: // return AddOnsResponseService.newCardBuilder() // .addSection(Section.newSection( // TextParagraph.newTextParagraph("Error message here."))) // .setErrorActionability(AddOnsResponseService.ErrorActionability.NOT_ACTIONABLE) // .build(); ``` -------------------------------- ### Build and Render Host App Action with Error Message (Java) Source: https://developers.google.com/workspace/add-ons/studio/activity-logs This Java code snippet demonstrates how to construct a Host App Action within Google Workspace Add-ons Studio. It includes setting an error message for the user, specifying the reason for failure (OAuth verification), and providing necessary authorization scopes. The action is then built and rendered. ```java .setTextFormatChip(errorChip) ) .addTextFormatElement( AddOnsResponseService.newTextFormatElement() .setText("Unable to create Google Document because OAuth verification failed. Grant one of these authorization scopes and try again: https://www.googleapis.com/auth/documents, \nhttps://www.googleapis.com/auth/drive, \nhttps://www.googleapis.com/auth/drive.file") ) ); let hostAppAction = AddOnsResponseService.newHostAppAction() .setWorkflowAction(workflowAction); return AddOnsResponseService.newRenderActionBuilder() .setHostAppAction(hostAppAction) .build(); } } ``` -------------------------------- ### Configure Drive Picker for Spreadsheets and PDFs (JSON) Source: https://developers.google.com/workspace/add-ons/studio/drive-picker This JSON configuration defines a step in Google Workspace Add-ons Studio that includes a Drive Picker. It specifies input and output variables for file selection and links to the Apps Script functions for configuration and execution. The `runtimeVersion` is set to 'V8'. ```JSON { "timeZone": "America/Los_Angeles", "exceptionLogging": "STACKDRIVER", "runtimeVersion": "V8", "addOns": { "common": { "name": "Drive Picker Demo", "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png", "useLocaleFromApp": true }, "flows": { "workflowElements": [ { "id": "file_selection", "state": "ACTIVE", "name": "File selection", "workflowAction": { "inputs": [ { "id": "drive_picker_1", "description": "Choose a file from Google Drive", "dataType": { "basicType": "STRING" } } ], "outputs": [ { "id": "fileId", "description": "The id of the selected file", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } } ], "onConfigFunction": "onConfig", "onExecuteFunction": "onExecute" } } ] } } } ``` -------------------------------- ### Output Variables from Step (JavaScript) Source: https://developers.google.com/workspace/add-ons/studio/quickstart-calculator_hl=de This function constructs an object to return variable values as output from a workflow step. It utilizes the AddOnsResponseService to create a workflow action and host app action, then builds a render action to send these outputs back to the host application. Debugging logs are also included. ```javascript /** * Returns output variables from a step. * * This function constructs an object that, when returned, sends the * provided variable values as output from the current step. * The variable values are logged to the console for debugging purposes. */ function outputVariables(variableDataMap) { const workflowAction = AddOnsResponseService.newReturnOutputVariablesAction() .setVariableDataMap(variableDataMap); const hostAppAction = AddOnsResponseService.newHostAppAction() .setWorkflowAction(workflowAction); const renderAction = AddOnsResponseService.newRenderActionBuilder() .setHostAppAction(hostAppAction) .build(); return renderAction; } ``` -------------------------------- ### Build Return Action with Variables and Logging Source: https://developers.google.com/workspace/add-ons/studio/update-cards_hl=hi Constructs a return action for a workflow, setting variables and logging information. It utilizes AddOnsResponseService to define the action and its associated data. ```javascript function buildReturnAction(variableData, workflowTextFormat) { // The string key for each variableData must match with the IDs of the // outputs defined in the manifest. let returnAction = AddOnsResponseService.newReturnOutputVariablesAction() .setVariables({ "result": variableData }) .setLog(workflowTextFormat); let hostAppAction = AddOnsResponseService.newHostAppAction() .setWorkflowAction(returnAction); return AddOnsResponseService.newRenderActionBuilder() .setHostAppAction(hostAppAction).build(); } ``` -------------------------------- ### Configure Card with Dynamic UI Elements (JSON) Source: https://developers.google.com/workspace/add-ons/studio/update-cards This JSON configuration defines a workflow element for a Google Workspace Add-on. It specifies input and output parameters for a configuration function ('onConfig') and an execution function ('onExecute'), enabling dynamic card modifications. ```JSON { "timeZone": "America/Los_Angeles", "exceptionLogging": "STACKDRIVER", "runtimeVersion": "V8", "addOns": { "common": { "name": "Test Project", "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png", "useLocaleFromApp": true }, "flows": { "workflowElements": [ { "id": "modify_card", "state": "ACTIVE", "name": "Modify Card", "workflowAction": { "inputs": [ { "id": "value1", "description": "The first input", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } }, { "id": "value2", "description": "The second number", "cardinality": "SINGLE', "dataType": { "basicType": "STRING" } }, { "id": "value3", "description": "The third number", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } } ], "outputs": [ { "id": "result", "description": "Modify Card result", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } } ], "onConfigFunction": "onConfig", "onExecuteFunction": "onExecute" } } ] } } } ``` -------------------------------- ### Build Configuration Card with UI Modification Buttons (Apps Script) Source: https://developers.google.com/workspace/add-ons/studio/update-cards This Apps Script function, `onConfig`, generates a configuration card for a Google Workspace Add-on. It includes text input fields and buttons that trigger actions to insert new sections or widgets onto the card, demonstrating dynamic UI manipulation. ```javascript // Return a configuration Card for the step. function onConfig() { const textInput_1 = CardService.newTextInput() .setFieldName("value1") .setTitle("First Value!") .setId("text_input_1") .setHostAppDataSource( CardService.newHostAppDataSource() .setWorkflowDataSource( CardService.newWorkflowDataSource() .setIncludeVariables(true) ) ); const textInput_2 = CardService.newTextInput() .setFieldName("value2") .setTitle("Second Value!") .setId("text_input_2") .setHostAppDataSource( CardService.newHostAppDataSource() .setWorkflowDataSource( CardService.newWorkflowDataSource() .setIncludeVariables(true) ) ); // Create buttons that call functions to modify the card. const buttonSet = CardService.newButtonSet() .setId("card_modification_buttons") .addButton( CardService.newTextButton() .setAltText("Insert Card Section") .setText("Insert Card Section") .setOnClickAction( CardService.newAction() .setFunctionName('insertSection') ) ) .addButton( CardService.newTextButton() .setAltText("Insert Text Widget") .setText("Insert Text Widget") .setOnClickAction( CardService.newAction() .setFunctionName('insertWidget') ) ); var firstSection = CardService.newCardSection() .setId("card_section_1") .addWidget(textInput_1) .addWidget(textInput_2) .addWidget(buttonSet); var card = CardService.newCardBuilder() .addSection(firstSection) .build(); var navigation = AddOnsResponseService.newNavigation() .pushCard(card); var action = AddOnsResponseService.newAction() .addNavigation(navigation); return AddOnsResponseService.newRenderActionBuilder() .setAction(action) .build(); } ```