Özel Workspace Studio Başlatıcı ve İşlem Adımları Oluşturma

1. Giriş

Bu codelab'de, doğrudan Google Workspace Studio ile arayüz oluşturan etkileşimli bir Destek Hızlı Portalı oluşturacaksınız. Üçüncü taraf altyapısına ihtiyaç duymadan anında test edilebilen özel bir başlangıç adımı ve özel bir işlem adımı oluşturmayı öğreneceksiniz.

Aşağıdakileri oluşturmak için Google Apps Komut Dosyası'nı kullanacağız:

  • Kullanıcıların destek kayıtlarını manuel olarak göndermeleri için şık bir form içeren web uygulaması.
  • Bu Web Uygulaması gönderimlerini yakalayan ve Workspace Studio akışını tetikleyen bir Özel Başlangıç.
  • Gelen destek kaydının açıklamasını analiz ederek aciliyet düzeylerini ("Yüksek" veya "Normal") belirleyen bir Özel Adım.

Neler öğreneceksiniz?

  • appsscript.json manifest dosyanızda başlangıçları ve adımları yapılandırma
  • Başlangıç kaydı yaşam döngüsü sırasında notifyUri nasıl oluşturulur?
  • UrlFetchApp kullanarak harici koddan Workspace Studio akışını programatik olarak tetikleme
  • Verileri aşağı akışa aktarmak için özel adımlarınızda çıkış değişkenlerini nasıl oluşturacağınız.

Ön koşullar

  • Google Workspace Studio'nun etkin olduğu bir Google Workspace hesabı
  • Alanınızın Yönetici Konsolu'nda (Uygulamalar > Google Workspace > Workspace Studio > özel adım ayarları bölümünde) Yayınlanmamış (test) özel adımlara izin ver ayarı etkinleştirilmiş olmalıdır.
  • Google Apps Komut Dosyası hakkında bilgi sahibi olmak

2. Apps Komut Dosyası projesini ayarlama

Öncelikle, kodumuzu barındıracak yeni bir Apps Komut Dosyası projesi oluşturalım:

  1. script.google.com adresine gidin ve Yeni proje'yi tıklayın.
  2. Projeyi Support Quick Portal (Hızlı Destek Portalı) olarak adlandırın.
  3. Sol kenar çubuğunda Proje Ayarları Proje Ayarları'nı tıklayın.
  4. appsscript.json manifest dosyasını düzenleyicide göster kutusunu işaretleyin.
  5. Düzenleyici Düzenleyici görünümüne dönün.

Apps Komut Dosyası projeleri varsayılan olarak gizli bir varsayılan Google Cloud projesiyle ilişkilendirilir. Google Workspace Studio API'yi çağırmak ve PERMISSION_DENIED hatalarını önlemek için komut dosyanızı standart bir Cloud projesine geçirmeniz, API'yi etkinleştirmeniz ve Google Auth Platform'u düzgün şekilde yapılandırmanız gerekir.

  1. Proje seçin veya oluşturun: Google Cloud Console'a gidin ve sayfanın üst kısmındaki proje açılır menüsünü kullanarak mevcut bir projeyi seçin veya yeni bir proje oluşturun.
  2. API'yi etkinleştirin: Seçtiğiniz proje üst çubukta etkin olduğunda API Etkinleştirme Akışı'nı açın ve Workspace Studio API için Sonraki ve Etkinleştir'i tıklayın.
  3. OAuth Markasını Yapılandırma: Google Auth Platform Branding sayfasını açın.
    1. İstenirse Başlayın'ı tıklayın. (Daha önce yapılandırıldıysa 4. adıma geçin.)
    2. Uygulama Bilgileri bölümünde bir uygulama adı ve kullanıcı desteği e-posta adresi girin. Next'i (Sonraki) tıklayın.
    3. Kitle bölümünde Şirket içi'ni (Şirket içi seçeneği yoksa Harici'yi) seçin ve Sonraki'yi tıklayın.
    4. İletişim bilgilerini girin, Veri Politikası'nı kabul edin ve Oluştur'u tıklayın.
  4. Veri erişimini yapılandırma: Veri erişimi sayfasını açın ve Kapsam ekle veya kaldır'ı tıklayın.
    1. Kapsamları manuel olarak ekle bölümünde https://www.googleapis.com/auth/workspace.studio.trigger yapıştırın.
    2. Tabloya Ekle'yi, ardından Güncelle'yi ve son olarak sayfanın alt kısmındaki Kaydet'i tıklayın.
  5. IAM ve Yönetici > Ayarlar'a (veya Cloud Console kontrol paneline) gidip Proje numarası'nı kopyalayın.
  6. Apps Komut Dosyası projenize dönün ve sol kenar çubuğunda Proje Ayarları Proje Ayarları'nı tıklayın.
  7. Google Cloud Platform (GCP) Projesi bölümünde Projeyi değiştir'i tıklayın.
  8. Kopyaladığınız GCP proje numarasını girin ve Projeyi ayarla'yı tıklayın.

Manifest dosyasını yapılandırma

Yeni görünür hale gelen appsscript.json dosyasını açın. İçeriğini aşağıdaki kodla değiştirin. Bu manifest, gerekli OAuth kapsamlarımızı açıkça listeler ve studio.flows.workflowElements bloğunda başlangıç olarak workflowTrigger, işlem olarak workflowAction tanımlar.

{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "webapp": {
     "executeAs": "USER_ACCESSING",
     "access": "MYSELF"
  },
  "oauthScopes": [
    "https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/workspace.studio.trigger",
    "https://www.googleapis.com/auth/script.storage",
    "https://www.googleapis.com/auth/script.locale"
  ],
  "urlFetchWhitelist": [
    "https://workspacestudio.googleapis.com/"
  ],
  "addOns": {
    "common": {
      "name": "Support Extension",
      "logoUrl": "https://www.gstatic.com/images/branding/productlogos/buganizer/v1/192px.svg",
      "useLocaleFromApp": true
    },
    "studio": {
      "flows": {
        "workflowElements": [
          {
            "id": "supportTicketTrigger",
            "state": "ACTIVE",
            "name": "New Support Ticket",
            "description": "Fires when someone submits a ticket via the Web App.",
            "workflowTrigger": {
              "inputs": [],
              "outputs": [
                {
                  "id": "ticketTitle",
                  "description": "The title of the ticket",
                  "cardinality": "SINGLE",
                  "dataType": { "basicType": "STRING" }
                },
                {
                  "id": "ticketDescription",
                  "description": "The full description of the issue",
                  "cardinality": "SINGLE",
                  "dataType": { "basicType": "STRING" }
                }
              ],
              "onConfigFunction": "onConfigTrigger",
              "onManageFunction": "onManageTrigger"
            }
          },
          {
            "id": "urgencyDetectorStep",
            "state": "ACTIVE",
            "name": "Detect Urgency",
            "description": "Scans the ticket description to detect High or Normal urgency.",
            "workflowAction": {
              "inputs": [
                {
                  "id": "ticketDescription",
                  "description": "The ticket description",
                  "cardinality": "SINGLE",
                  "dataType": { "basicType": "STRING" }
                }
              ],
              "outputs": [
                {
                  "id": "urgencyLevel",
                  "description": "The urgency High/Normal",
                  "cardinality": "SINGLE",
                  "dataType": { "basicType": "STRING" }
                }
              ],
              "onConfigFunction": "onConfigUrgency",
              "onExecuteFunction": "onExecuteUrgency"
            }
          }
        ]
      }
    }
  }
}

3. Web uygulaması kullanıcı arayüzünü oluşturma

Başlatıcımızı terminal araçlarını veya üçüncü taraf webhook'ları kullanmadan tetiklemek için görsel ve test edilebilir bir yöntem sunmak amacıyla Apps Komut Dosyası web uygulaması oluşturacağız.

Apps Komut Dosyası Düzenleyici'de Dosyalar'ın yanındaki Dosya ekle Dosya ekle'yi tıklayın ve HTML'yi seçin. index.html olarak adlandırın (.html uzantısı otomatik olarak eklenir).

Aşağıdaki basitleştirilmiş kullanıcı arayüzü kodunu yapıştırın:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
      body { font-family: Arial, sans-serif; padding: 20px; max-width: 500px; margin: auto; }
      label { font-weight: bold; display: block; margin-top: 15px; }
      input, textarea { width: 100%; margin-top: 5px; padding: 10px; box-sizing: border-box; }
      button { background-color: #1a73e8; color: white; border: none; padding: 10px 15px; margin-top: 15px; font-weight: bold; cursor: pointer; border-radius: 4px; }
      button:hover { background-color: #1557b0; }
      #status { margin-top: 15px; color: green; font-weight: bold; }
    </style>
  </head>
  <body>
    <h2>Support Quick Portal</h2>
    <p>Submit your issue below to trigger the Workspace Studio flow.</p>

    <label for="title">Ticket Title</label>
    <input type="text" id="title" placeholder="e.g. Broken monitor">

    <label for="description">Issue Description</label>
    <textarea id="description" rows="4" placeholder="Explain your issue (use words like 'urgent' to test the step!)..."></textarea>

    <button onclick="submitTicket()">Submit Ticket</button>
    <div id="status"></div>

    <script>
      function submitTicket() {
        const title = document.getElementById('title').value;
        const description = document.getElementById('description').value;
        const statusEl = document.getElementById('status');

        if (!title || !description) {
           statusEl.style.color = "red";
           statusEl.innerText = "Please fill out both fields.";
           return;
        }

        statusEl.style.color = "green";
        statusEl.innerText = "Submitting ticket...";

        google.script.run
          .withSuccessHandler(function(response) {
            statusEl.innerText = response;
          })
          .withFailureHandler(function(error) {
            statusEl.style.color = 'red';
            statusEl.innerText = 'Error: ' + error.message;
          })
          .submitTicketToStudio(title, description);
      }
    </script>
  </body>
</html>

4. Arka uç komut dosyalarını oluşturma

Şimdi hepsini birbirine bağlayalım. Kodu okunabilir tutmak için Web Uygulaması, Başlangıç mantığı ve İşlem Adımı mantığını üç farklı komut dosyasına ayıracağız.

WebApp.gs

Düzenleyicideki varsayılan Code.gs dosyasını WebApp.gs olarak yeniden adlandırın, standart metin myFunction'yi silin ve aşağıdaki bloğu kopyalayıp dosyaya yapıştırın. Bu dosya, web uygulaması barındırma işlemini yönetir:

/** --- WEB APP HOSTING --- **/

/**
 * Serves the HTML UI when users visit the web app URL.
 */
function doGet() {
  return HtmlService.createHtmlOutputFromFile('index')
      .setTitle('Support Quick Portal')
      .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

/**
 * Called by the Web App form. It calls the Workspace Studio API.
 */
function submitTicketToStudio(title, description) {
  const props = PropertiesService.getUserProperties();
  const notifyUri = props.getProperty('notifyUri');
  const triggerId = props.getProperty('triggerId');

  if (!notifyUri || !triggerId) {
    throw new Error('Trigger URL missing! Make sure the flow is enabled in Workspace Studio.');
  }

  // Use ScriptApp.getOAuthToken() (requires the workspace.studio.trigger scope in manifest)
  const token = ScriptApp.getOAuthToken();
  const requestId = Utilities.getUuid();

  // Package our outputs mapped in appsscript.json
  const payload = {
    "name": "triggers/" + triggerId,
    "outputs": {
      "ticketTitle": { "stringValues": [title] },
      "ticketDescription": { "stringValues": [description] }
    },
    "requestId": requestId
  };

  const options = {
    "method": "POST",
    "contentType": "application/json",
    "headers": { "Authorization": "Bearer " + token },
    "payload": JSON.stringify(payload),
    "muteHttpExceptions": true
  };

  // Fire!
  const response = UrlFetchApp.fetch(notifyUri, options);
  if (response.getResponseCode() !== 200) {
    console.error(response.getContentText());
    throw new Error('Workspace Studio API Error: ' + response.getResponseCode());
  }
  return 'Ticket successfully routed to Workspace Studio!';
}

Starter.gs

Ardından, Dosyalar'ın üzerine gelin, Dosya ekle Dosya ekle'yi tıklayın, Komut dosyası'nı seçin ve Starter.gs olarak adlandırın. Aşağıdaki bloğu kopyalayıp bu dosyaya yapıştırın. Bu dosya, Başlatıcı yapılandırmasını ve Workspace Studio yaşam döngüsü yönetimini işler:

/** --- STARTER LOGIC --- **/

/**
 * Workspace Studio calls this to display the config UI when the user adds the starter.
 * We just return a static message since there are no properties to configure.
 */
function onConfigTrigger() {
  const section = CardService.newCardSection()
      .setHeader("Configure Web App Starter")
      .addWidget(CardService.newTextParagraph().setText("Ready to go! Once you enable this flow, deploy your Apps Script project as a Web App to submit tickets."));

  return CardService.newCardBuilder().addSection(section).build();
}

/**
 * Workspace Studio posts data here to manage the lifecycle (enable/disable the trigger).
 * Critically, we must construct or save the `notifyUri` and `triggerId` to call it later.
 */
function onManageTrigger(event) {
  const triggerCreation = event.workflow.triggerCreation;
  const triggerDeletion = event.workflow.triggerDeletion;

  const props = PropertiesService.getUserProperties();

  if (triggerCreation) {
    // Save the unique URL and ID when the flow is enabled
    // Note: notifyUri might be omitted, so fallback to constructing it dynamically
    const notifyUri = triggerCreation.notifyUri || `https://workspacestudio.googleapis.com/v1/triggers/${triggerCreation.triggerId}:fire`;
    props.setProperty('notifyUri', notifyUri);
    props.setProperty('triggerId', triggerCreation.triggerId);
  } else if (triggerDeletion) {
    // Cleanup if the user deletes the flow
    props.deleteProperty('notifyUri');
    props.deleteProperty('triggerId');
  }
}

Action.gs

Ardından, Dosyalar'ın üzerine gelin, Dosya ekle Dosya ekle'yi tıklayın, Komut dosyası'nı seçin ve Action.gs olarak adlandırın. Aşağıdaki Aciliyet Adımı mantığını kopyalayıp yapıştırın:

/** --- ACTION STEP LOGIC --- **/

/**
 * Workspace Studio configuration card for the Step.
 * We prompt the user to bind a variable to our "ticketDescription" input.
 */
function onConfigUrgency() {
  const input = CardService.newTextInput()
      .setFieldName("ticketDescription")
      .setTitle("Source Description")
      .setHint('Select the description variable outputted by the starter')
      .setHostAppDataSource(
        CardService.newHostAppDataSource().setWorkflowDataSource(CardService.newWorkflowDataSource().setIncludeVariables(true))
      );

  const section = CardService.newCardSection()
      .setHeader("Urgency Detector Step")
      .addWidget(input);

  return CardService.newCardBuilder().addSection(section).build();
}

/**
 * The synchronous logic executed during the Step.
 */
function onExecuteUrgency(event) {
  // Read mapped inputs
  let description = event.workflow.actionInvocation.inputs["ticketDescription"].stringValues[0];
  if (!description) description = "";

  const urgentKeywords = ['urgent', 'crash', 'broken', 'down', 'fire'];
  let urgencyLevel = 'Normal';

  if (urgentKeywords.some(keyword => description.toLowerCase().includes(keyword))) {
    urgencyLevel = 'High';
  }

  // Package outputs correctly
  const variableDataMap = {
    "urgencyLevel": AddOnsResponseService.newVariableData().addStringValue(urgencyLevel)
  };

  return outputVariables(variableDataMap);
}

/**
 * Helper strictly enforcing the expected Step object return type.
 */
function outputVariables(variableDataMap) {
  const workflowAction = AddOnsResponseService.newReturnOutputVariablesAction()
      .setVariableDataMap(variableDataMap);
  const hostAppAction = AddOnsResponseService.newHostAppAction()
      .setWorkflowAction(workflowAction);
  return AddOnsResponseService.newRenderActionBuilder()
      .setHostAppAction(hostAppAction)
      .build();
}

5. Dağıtma ve Test Etme

Kodumuzu yazdığımıza göre projeyi dağıtıp yapılandıralım.

1. adım: Komut dosyasını yeniden yetkilendirin

Yeni bir standart Google Cloud projesi bağladığınız için komut dosyasının kapsamlarını (ör. UrlFetchApp tarafından kullanılan script.external_request) yeni projeye karşı açıkça yetkilendirmeniz gerekir.

  1. Apps Komut Dosyası Düzenleyici'de Dosyalar'ın altında WebApp.gs simgesini, ardından üst araç çubuğu açılır listesinden doGet işlevini seçin.
  2. Çalıştır'ı tıklayın.
  3. "Yetkilendirme gerekli" istemi gösterilir. İzinleri incele'yi tıklayın.
  4. Hesabınızı seçin ve komut dosyasını yetkilendirin. "Doğrulanmamış uygulama" uyarısı görürseniz atlamak için Gelişmiş -> Destek Hızlı Portalı'na git'i tıklayın.
  5. Yürütme günlüğünde Yürütme tamamlandı mesajının gösterilmesini bekleyin. Bu mesaj, komut dosyasının artık tamamen yetkilendirildiğini onaylar.

2. adım: Uzantıyı ve web uygulamasını test edin

appsscript.json dosyanız hem eklentiyi hem de web uygulamasını tanımladığından ikisini de aynı anda yapılandırabilirsiniz.

  1. Apps Komut Dosyası'nın sağ üst köşesindeki Dağıt > Test dağıtımları'nı tıklayın.
  2. Tür seçin'in yanındaki Dağıtım türlerini etkinleştirme Dağıtım türlerini etkinleştir'i tıklayın ve Google Workspace Eklentileri'nin işaretli olduğundan emin olun, ardından Yükle'yi tıklayın.
  3. Dağıtım türlerini etkinleştirme Dağıtım türlerini etkinleştir'i tekrar tıklayın, Web uygulaması'nın işaretli olduğundan emin olun ve URL'yi kopyalayın (/dev ile biter). Bu, oluşturduğunuz Destek Hızlı Portalı web uygulamasının URL'sidir.
  4. Bitti'yi tıklayın. Workspace Studio'nun eklentiyi kaydetmesi için tarayıcınızı yenilemeniz gerekebilir.

3. adım: Studio Flow'u yapılandırın

  1. studio.workspace.google.com adresinden Google Workspace Studio'yu açın.
  2. Sol tarafta Araç ekleme Araç ekle'yi tıklayın ve Akış'ı seçin.
  3. Başlangıç şablonunu yapılandırmak için Başlangıç şablonu seçin'i tıklayın, ardından yüklediğiniz Destek Uzantısı > Yeni Destek Kaydı'nı seçin. "İzin gerekli" mesajı gösterilirse eklentinin verilerinize erişmesine izin vermek için İzin ver'i tıklayın.
  4. Ardından, İşlemler bölümünde Adım seçin'i tıklayın, "Destek Uzantısı"na gidin ve Aciliyet Algıla adımını seçin.
  5. Kaynak Açıklaması'nda Ekle Değişkenler'i tıklayın ve 1. Adım: Yeni Destek Kaydı > Sorunun tam açıklaması'nı (ticketDescription) seçin.
  6. Bir adım seçin'i tekrar tıklayın ve Gmail > E-posta gönder veya Chat > Chat'ten bildirim gönder gibi yerleşik bir adımı seçin.
    • Gmail'i seçtiyseniz:
      • Alıcı: Kendi e-posta adresinizi girin.
      • Konu: ticketTitle numaralı destek kaydının önceliği urgencyLevel
      • Mesaj: ticketDescription
    • Sohbet'i seçtiyseniz:
      • Mesaj: Bilet ticketTitle önceliği urgencyLevel. ticketDescription
  7. İş akışını etkinleştirin. Akışınızı yeniden adlandırmanız istenirse Support Ticket Router gibi bir ad girin ve kaydedin. Bu işlem, onManageTrigger yaşam döngüsünü tetikleyerek notifyUri tasarrufu sağlar.

4. adım: Simülasyonu çalıştırın

  1. Bu sayfanın 2. adımında daha önce kopyaladığınız web uygulaması URL'sini yeni bir tarayıcı sekmesinde açın (/dev ile biter).
  2. Formu doldurun. Açıklamaya tetikleyici bir anahtar kelime (ör. "acil" veya "çökme") eklediğinizden emin olun.
  3. Gönder'i tıklayın. "Bilet başarıyla yönlendirildi" mesajını bekleyin.
  4. Workspace Studio Etkinlik Günlüğünüzü, Gmail gelen kutunuzu veya Google Chat'i (seçtiğiniz işleme bağlı olarak) kontrol edin. Özel Apps Komut Dosyası öğeleriniz kullanılarak yerel olarak entegre edilmiş, "Yüksek" öncelikli olarak etiketlenmiş bir mesaj veya e-posta görmeniz gerekir.

6. Temizleme

Çalışma alanınızda ve Google Cloud hesabınızda karmaşa oluşmasını önlemek için bu codelab sırasında oluşturduğunuz kaynakları temizleyebilirsiniz.

  1. Workspace Studio akışını silme:
    • studio.workspace.google.com adresini açın.
    • Support Ticket Router Akışınızı kurgulayın.
    • Yanındaki üç nokta menüsünü tıklayın ve Sil'i seçin.
  2. Apps Komut Dosyası projesini silme:
    • script.google.com adresine gidin.
    • Support Quick Portal projesini bulun.
    • Üç nokta menüsünü tıklayıp Kaldır'ı seçin.
  3. Google Cloud projesini kapatın:
    • Google Cloud Console'a gidin.
    • Üstteki açılır listede yeni projenizin seçili olduğundan emin olun.
    • IAM ve Yönetici > Ayarlar'a gidin ve Kapat'ı tıklayın.

7. Sonuç

Herhangi bir harici üçüncü taraf aboneliğine güvenmeden Google Workspace Studio özel uzantıları için eksiksiz bir ekosistem oluşturmayı başardınız.

İşlediğimiz konular:

  • Google'ın yaşam döngüsü etkinliklerini doğru şekilde yakalamak ve işlemek için workflowTrigger ile birlikte onManageFunction kullanma.
  • ScriptApp.getOAuthToken() API uç noktalarına karşı workspacestudio.googleapis.com kullanarak arka uç isteklerinin kimliğini doğrulama.
  • Giriş değişkenlerini eşzamanlı olarak işlemek ve sonraki çıkışları oluşturmak için workflowAction kullanma.

Web uygulamanızın (veya gelen webhook'un) tetiklendiği yeri değiştirerek bu ilkeleri artık Jira, Salesforce veya Zendesk gibi gerçek SaaS platformlarına bağlayacak şekilde genişletebilirsiniz.