تعديل بطاقة إعداد

يوضِّح هذا الدليل كيفية تعديل بطاقة إعدادات بشكل ديناميكي استجابةً لإجراءات المستخدم، مثل النقر على زر أو اختيار عنصر من قائمة.

يمكنك إدراج أقسام البطاقات وعناصر واجهة المستخدم أو إزالتها أو استبدالها لإنشاء واجهات مستجيبة تتكيّف مع إدخالات المستخدم. على سبيل المثال، يمكنك تعديل واجهة البطاقة لعرض رسالة خطأ في التحقّق للمستخدمين الذين يُدخلون سلسلة في حقل إدخال يتوقّع عددًا صحيحًا، ثم تعديلها مرة أخرى لإخفاء الرسالة بعد أن يُدخل المستخدم عددًا صحيحًا.

تعديل أقسام البطاقات وعناصر واجهة المستخدم

لتعديل بطاقة، يجب أن يستدعي إجراء عنصر واجهة المستخدم (مثل onClickAction) دالة تعرض كائن RenderActions يحتوي على تعليمات التعديل.

في أقسام البطاقات، يمكنك إجراء التعديلات التالية:

  • إدراج قسم: يمكنك إضافة قسم في أعلى البطاقة أو أسفل قسم حالي محدّد حسب رقم التعريف باستخدام setInsertSection.
  • إزالة قسم: يمكنك إزالة قسم محدّد حسب رقم التعريف باستخدام setRemoveSection.
  • استبدال قسم: يمكنك استبدال قسم حالي بقسم جديد محدّد حسب رقم التعريف باستخدام setReplaceSection.

في عناصر واجهة المستخدم للبطاقات، يمكنك إجراء التعديلات التالية:

  • إدراج عنصر واجهة مستخدم: يمكنك إضافة عنصر واجهة مستخدم قبل عنصر واجهة مستخدم حالي أو بعده محدّد حسب رقم التعريف باستخدام setInsertWidget.
  • إزالة عنصر واجهة مستخدم: يمكنك إزالة عنصر واجهة مستخدم محدّد حسب رقم التعريف باستخدام setRemoveWidget.
  • استبدال عنصر واجهة مستخدم: يمكنك استبدال عنصر واجهة مستخدم حالي بعنصر واجهة مستخدم جديد باستخدام setReplaceWidget.

مثال: إدراج أقسام وعناصر واجهة مستخدم وإزالتها

ينشئ المثال التالي بطاقة إعدادات تحتوي على أزرار تستدعي دوالاً لتعديل البطاقة من خلال إدراج عناصر واجهة مستخدم وأقسام أو إزالتها.

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"
          }
        }
      ]
    }
  }
}

برمجة التطبيقات

// 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();
}
// If the step runs, return output variables.
function onExecute(event) {
  var value1 = event.workflow.actionInvocation.inputs["value1"].stringValues[0];
  var value2 = event.workflow.actionInvocation.inputs["value2"].stringValues[0];
  var value3; // Declare value3
  var result;
  // Check if the "value3" key exists in the inputs, which only exists if
  // the third text input is inserted to the Card.
  if (event.workflow.actionInvocation.inputs["value3"]) {
    value3 = event.workflow.actionInvocation.inputs["value3"].stringValues[0];

    result = value1 + "\n" + value2 + "\n" + value3;
  } else {
    result = value1 + "\n" + value2;
  }
  // Output the file ID through a variableData, which can be used by
  // later steps in a workflow.
  const variableData = AddOnsResponseService.newVariableData()
    .addStringValue(result);

  let textFormatElement = AddOnsResponseService.newTextFormatElement()
    .setText("Output: " + JSON.stringify(variableData));

  let workflowTextFormat = AddOnsResponseService.newWorkflowTextFormat()
    .addTextFormatElement(textFormatElement);

  // 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();
}

/**
 * Inserts a new CardSection with several widgets.
 */
function insertSection(event) {
  console.log("event: " + JSON.stringify(event, null, 3));

  const optionalSection = CardService.newCardSection().setId("card_section_2")
    .addWidget(
      CardService.newTextParagraph().setText("This is a text paragraph inside the new card section")
    )
    .addWidget(
      CardService.newButtonSet().addButton(
        CardService.newTextButton().setText("Remove Card Section").setOnClickAction(CardService.newAction().setFunctionName("removeSection"))))
    .addWidget(
      CardService.newButtonSet().addButton(
        CardService.newTextButton().setText("Replace Card Section").setOnClickAction(CardService.newAction().setFunctionName("replaceSection"))));

  // Insert the new section beneath section "card_section_1".
  // You can also insert at the top of a Card.
  const sectionInsertion = AddOnsResponseService.newInsertSection().insertBelowSection("card_section_1").setSection(optionalSection);

  const modifyAction = AddOnsResponseService.newAction()
    .addModifyCard(AddOnsResponseService.newModifyCard().setInsertSection(sectionInsertion));

  return AddOnsResponseService.newRenderActionBuilder().setAction(modifyAction).build();
}
/**
 * Replaces an existing CardSection with a new CardSection with the same ID.
 */
function replaceSection(event) {
  console.log("event: " + JSON.stringify(event, null, 3));

  const replacementSection = CardService.newCardSection().setId("card_section_2")
    .addWidget(
      CardService.newTextParagraph().setText("Card Section replaced!")
    )
    .addWidget(
      CardService.newButtonSet().addButton(
        CardService.newTextButton().setText("Remove Card Section").setOnClickAction(CardService.newAction().setFunctionName("removeSection"))));

  const modifyAction = AddOnsResponseService.newAction()
    .addModifyCard(AddOnsResponseService.newModifyCard().setReplaceSection(replacementSection));

  return AddOnsResponseService.newRenderActionBuilder().setAction(modifyAction).build();
}

/**
* Replaces an existing CardWidget with a new CardWidget with the same ID.
*/
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();
}

/**
 * Inserts an additional text input widget and a button that can remove it.
 */
function insertWidget(event) {
  console.log("event: " + JSON.stringify(event, null, 3));

  const buttonSet = CardService.newButtonSet().setId("widget_1")
    .addButton(
      CardService.newTextButton()
        .setAltText("Remove Widget")
        .setText("Remove Widget")
        .setOnClickAction(
          CardService.newAction().setFunctionName('removeWidget')
        ))
    .addButton(
      CardService.newTextButton()
        .setAltText("Replace Widget")
        .setText("Replace Widget")
        .setOnClickAction(
          CardService.newAction().setFunctionName('replaceWidget')
        ));

  const textInput_3 = CardService.newTextInput().setFieldName("value3").setTitle("Third Value").setId("text_input_3");

  // Widgets can be inserted either before or after another widget.
  // This example inserts a button below a text input, then inserts
  // another text input between the existing text input and the new button.
  const buttonSetInsertion = AddOnsResponseService.newInsertWidget().insertBelowWidget("text_input_2").setWidget(buttonSet);
  const textInputInsertion = AddOnsResponseService.newInsertWidget().insertAboveWidget("widget_1").setWidget(textInput_3);

  const modifyAction = AddOnsResponseService.newAction()
    .addModifyCard(AddOnsResponseService.newModifyCard().setInsertWidget(buttonSetInsertion))
    .addModifyCard(AddOnsResponseService.newModifyCard().setInsertWidget(textInputInsertion));

  return AddOnsResponseService.newRenderActionBuilder().setAction(modifyAction).build();
}

/**
 * Removes one or more existing widgets by ID.
 */
function removeWidget(event) {
  console.log("event: " + JSON.stringify(event, null, 3));

  const textInputDeletion = AddOnsResponseService.newRemoveWidget().setWidgetId("text_input_3");
  const buttonSetDeletion = AddOnsResponseService.newRemoveWidget().setWidgetId("widget_1");

  const modifyAction = AddOnsResponseService.newAction()
    .addModifyCard(
      AddOnsResponseService.newModifyCard().setRemoveWidget(textInputDeletion)
    )
    .addModifyCard(
      AddOnsResponseService.newModifyCard().setRemoveWidget(buttonSetDeletion)
    );

  return AddOnsResponseService.newRenderActionBuilder().setAction(modifyAction).build();
}

/**
 * Removes an existing card section by ID.
 */
function removeSection(event) {
  console.log("event: " + JSON.stringify(event, null, 3));

  const sectionDeletion = AddOnsResponseService.newRemoveSection().setSectionId('card_section_2');

  const modifyAction = AddOnsResponseService.newAction()
    .addModifyCard(
      AddOnsResponseService.newModifyCard().setRemoveSection(sectionDeletion)
    );

  return AddOnsResponseService.newRenderActionBuilder().setAction(modifyAction).build();
}