이 빠른 시작에서는 Google Apps Script를 사용하여 Workspace Studio의 맞춤 단계를 만드는 방법을 설명합니다. 커스텀 단계는 두 숫자와 산술 연산을 입력으로 사용하고 계산을 수행하고 결과를 출력합니다.
목표
- Google Apps Script를 사용하여 Workspace Studio의 맞춤 단계를 만듭니다.
- 자체 Google Workspace 조직에 맞춤 단계를 배포합니다.
- Workspace Studio에서 커스텀 단계를 테스트합니다.
기본 요건
- Workspace Studio에 액세스할 수 있는 Google 계정
스크립트 설정
스크립트를 설정하려면 새 Apps Script 프로젝트를 만들고 빠른 시작 코드를 추가합니다.
다음 버튼을 클릭하여 새 Apps Script 프로젝트를 만듭니다.
Apps Script 프로젝트의 이름을 지정합니다.
제목 없는 프로젝트를 클릭합니다.
프로젝트 제목에
Calculator quickstart를 입력합니다.이름 바꾸기를 클릭합니다.
Code.gs파일 옆에 있는 더보기 > 이름 바꾸기를 클릭합니다. 파일 이름을Calculator으로 지정합니다.Calculator.gs의 내용을 다음 코드로 바꿉니다. 이 파일은 두 숫자와 연산을 입력으로 받아 계산 결과를 반환하는 'Calculate'라는 Google Workspace Studio의 커스텀 단계를 정의합니다.Calculator.gs코드 보기/** * 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. * * This function attempts to extract an integer value from the provided variable data. * It checks if the data contains string values and, if so, parses the first string * as an integer. If integer values are present, it returns the first integer. * @param {Object} variableData The variable data object from the event. * @return {number} The extracted integer value. */ function getIntValue(variableData) { if (variableData.stringValues) { return parseInt(variableData.stringValues[0]); } return variableData.integerValues[0]; } /** * 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; } /** * Executes the calculation action based on the inputs from an event. * * This function retrieves input values ("value1", "value2") and the "operation" * from the event, performs the calculation, and returns the "result" and * "log" as output variables. * This function is called when the flow reaches this custom step. * @param {Object} event The event object passed by the runtime. * @return {Object} The output variables object. */ function onExecuteCalculateFunction(event) { console.log("output: " + JSON.stringify(event)); var calculatedValue = 0; var value1 = event.workflow.actionInvocation.inputs["value1"].integerValues[0]; var value2 = event.workflow.actionInvocation.inputs["value2"].integerValues[0]; var operation = event.workflow.actionInvocation.inputs["operation"].stringValues[0]; if (operation == "+") { calculatedValue = value1 + value2; } else if (operation == "-") { calculatedValue = value1 - value2; } else if (operation == "x") { calculatedValue = value1 * value2; } else if (operation == "/") { calculatedValue = value1 / value2; } const variableDataMap = { "result": AddOnsResponseService.newVariableData().addIntegerValue(calculatedValue) }; return outputVariables(variableDataMap); }
프로젝트 설정 을 클릭하고 편집기에 'appsscript.json' 매니페스트 파일 표시 체크박스를 선택합니다.
편집기 를 클릭하고
appsscript.json매니페스트 파일을 연 후 콘텐츠를 다음 코드로 바꿉니다.appsscript.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" } } ] } } }
저장 를 클릭합니다.
단계 배포 및 테스트
단계를 테스트하려면 부가기능의 테스트 배포를 설정하고 흐름에 단계를 추가한 후 흐름을 실행합니다.
부가기능의 테스트 배포를 설정합니다.
- Apps Script 편집기에서 스크립트 프로젝트를 엽니다.
- 배포 > 테스트 배포를 클릭합니다.
- 설치를 클릭합니다.
- 하단에서 완료를 클릭합니다.
Apps Script 프로젝트를 다른 사용자의 계정과 공유하여 다른 사용자가 부가기능을 테스트하도록 할 수 있습니다(수정 액세스 권한 필요). 그런 다음 사용자에게 이전 단계를 따르도록 안내합니다.
설치되면 부가기능을 흐름에서 즉시 사용할 수 있습니다. 부가기능이 표시되기 전에 흐름을 새로고침해야 할 수 있습니다. 부가기능을 사용하기 전에 승인해야 합니다.
테스트 배포에 대한 자세한 내용은 게시되지 않은 부가기능 설치를 참조하세요.
흐름을 엽니다.
단계를 포함하는 흐름을 만듭니다.
- 새 플로우를 클릭합니다.
- 플로우가 시작되는 방식을 선택합니다. 단계에 입력 변수가 필요한 경우 입력 변수를 시작 도구 출력의 일부로 구성합니다.
- 단계 추가를 클릭합니다. 빌드하거나 업데이트한 단계인 Calculate를 선택합니다.
- 단계를 구성합니다. 계산 단계에서 두 값과 수학 연산을 선택합니다. 단계가 자동으로 저장됩니다.
- 단계의 출력을 테스트하려면 다른 단계를 추가하세요. 예를 들어 Google Chat 메시지에 출력을 추가하려면 Chat의 Chat에서 알림 받기 단계를 추가합니다. 메시지에서 변수를 클릭하고 단계의 출력을 선택합니다. 계산 단계에서 변수 > 2단계: 계산 > 계산된 결과를 선택합니다. 변수가 메시지 필드에 칩으로 표시됩니다.
- 사용 설정을 클릭합니다. 흐름을 실행할 준비가 되었습니다.
플로우의 시작 조건을 트리거하여 플로우를 실행합니다. 예를 들어 플로우가 일정에 따라 시작되는 경우 지정된 날짜와 시간에 실행됩니다.
흐름이 예상대로 실행되는지 확인합니다. 흐름 빌더의 활동 탭을 방문하여 로그를 확인합니다. 활동 탭에서 커스텀 로그를 만드는 방법은 활동 로그를 참조하세요.
다음 단계
Workspace Studio용 맞춤 단계를 만들고 테스트했습니다. 이제 다음과 작업을 수행할 수 있습니다.
Gemini에 더 복잡한 로직을 구현하는 데 도움이 되는 프롬프트를 입력하여 단계를 계속 맞춤설정합니다.
구성 카드를 빌드하여 단계 구성을 맞춤설정합니다.
활동 기록 및 오류를 로깅하여 단계 실행을 기록하고 문제를 해결합니다.
이벤트 객체를 검토하여 단계가 실행될 때 흐름이 전송하고 수신하는 JSON 페이로드를 검토합니다.
맞춤 Workspace Studio 시작 및 작업 단계 빌드 Codelab을 통해 Apps Script로 맞춤 시작 및 맞춤 단계를 빌드해 보세요.