ビルドのネイティブSFDC統合とスラックアプリ


同期データ


ついに、我々はSalesforceのものを使っている我々のシリーズの最終的な部分に到着しましたSlack Starter Kit すぐにSesesforceデータと対話する展開スラックアプリケーションをscaffoldする.スラックスターターキットは非常に簡単にSalesforceで認証するには、再利用可能な塊にコードを整理し、Herokuにライブアクセスのためのプロジェクトを展開します.我々は、主にこのシリーズに基づきました.
我々は、スラックスターターキットと知り合い、我々の開発環境を設定します.私たちのスラックアプリケーションは、Salesforceのorgからデータを取得し、ブロックキットからUIコンポーネントを使用して結果を提示するクエリを発行しました.今、我々はショーケースにどのようにスラッシュ内の完全にSalesforceデータを編集できるパターンを拡張するつもりです.始めましょう!

写真でEdgar Moran on Unsplash

ショートカットの作成


ブロックキットUIの外では、スラックは他の2つの対話システムをサポートしています.Slash Commands and shortcuts . スラッシュのコマンドは、スラックのテキスト入力(ユーザーがすべてのチャネルで利用可能)によって入力されますが、ショートカットは、自然の中でグラフィカルです.彼らは視覚化しやすいので、我々は連絡先のリストを取得し、私たちにそれらを編集する機能を与えるショートカットを作成することによってショートカットを実証します.
ショートカット(またはスラッシュコマンド)を追加するには、まずコマンドの名前をスラックする必要があります.スラックにあなたのアプリケーションの概要ページに移動し、対話とショートカットをクリックします

新しいショートカットを作成し、ショートカットの種類としてグローバルを選択し、[次へ]をクリックします.次のページでこれらの値を入力します.

  • 名前:連絡先を編集

  • 簡単な説明:SFDCの上で編集接触

  • コールバックID :edit-contact-shortcut
  • をクリックし、[変更の保存]をクリックします.あなたのスラックのワークスペースに切り替え、テキスト領域のプラス記号をクリックします.すべてのワークスペースのショートカットを閲覧することができます.ここでは、ちょうど作成した新しいショートカットも参照してください.

    このショートカットはまだ何もしませんが、このプロセスはあなたのショートカットについて知ってスラックするために必要です.次に、このショートカットでクリックしたときに発生するイベントを処理するコードを追加します.

    ショートカットの配線


    コードエディターでapps/slack-salesforce-starter-app/listeners/shortcuts/index.js . これは、ショートカットイベントを実行するコードに接続する点です.もう一つのショートカットがスターターキットで与えられています.whoami . 与えられた行は私たちに何をすべきかを示唆していますshortcut と文字列と関数名を渡します.この場合、私たちのストリングは以前定義されたcallback idです、そして、我々の機能名は我々がまだ書いていないコードです.ファイルの内容を以下のように変更します.
    const { whoamiCallback } = require('./whoami');
    const { editContactCallback } = require('./edit-contact');
    
    module.exports.register = (app) => {
       app.shortcut('who_am_i', whoamiCallback);
       app.shortcut('edit-contact-shortcut', editContactCallback);
    };
    
    私たちは次のように言うことによってグラウンドワークを敷設していますedit-contact-shortcut ランeditContactCallback .”
    この同じフォルダで、edit-contact.js , これらの行をペーストします.
    'use strict';
    
    const {
      editContactResponse,
      authorize_sf_prompt
    } = require('../../user-interface/modals');
    
    const editContactCallback = async ({ shortcut, ack, client, context }) => {
      try {
        await ack();
        if (context.hasAuthorized) {
          const conn = context.sfconnection;
          await client.views.open({
            trigger_id: shortcut.trigger_id,
            view: await editContactResponse(conn)
          });
        } else {
          // Get BotInfo
          const botInfo = await client.bots.info({ bot: context.botId });
          // Open a Modal with message to navigate to App Home for authorization
          await client.views.open({
            trigger_id: shortcut.trigger_id,
            view: authorize_sf_prompt(context.teamId, botInfo.bot.app_id)
          });
        }
      } catch (error) {
        // eslint-disable-next-line no-console
        console.error(error);
      }
    };
    
    module.exports = { editContactCallback };
    
    今、これは威嚇するように見えるかもしれません、しかし、それのほとんどは単に認証Boilerplateに関心を持ちます.そして、ユーザーが活発なSFDC接続を確実にします.を返します.context.hasAuthorized is true ), 関数を実行するeditContactResponse , これは我々のオープンセールスフォースを受け入れるconn 登場.否定的な場合では、このチュートリアルのパート1でしたように、ユーザーにホームタブに再認証を要求します.
    移動するapps/slack-salesforce-starter-app/user-interface/modals フォルダを作成し、edit-contact-response.js . ここでは、このチュートリアルのパート2のホームタブで見た行に似た連絡先情報を持つモーダルを開くことができます.
    'use strict';
    const { Elements, Modal, Blocks } = require('slack-block-builder');
    
    const editContactResponse = async (conn) => {
      const result = await conn.query(
        `Select Id, Name, Description FROM Contact`
      );
      let records = result.records;
    
      let blockCollection = records.map((record) => {
        return Blocks.Section({
          text: `*${record.Name}*\n${record.Description}`
        }).accessory(
          Elements.Button()
            .text(`Edit`)
            .actionId(`edit_contact`)
            .value(record.Id)
        );
      });
    
      return Modal({ title: 'Salesforce Slack App', close: 'Close' })
        .blocks(blockCollection)
        .buildToJSON();
    };
    
    module.exports = { editContactResponse };
    
    パート2とこのブロックのコードの主な違いは、私たちがblockCollection , これにより、ブロックの配列(この場合、セクションブロック)を構築できます.blocks この配列をとる方法を知っていて、それがスラックが理解するフォーマットに変える方法を知っています.第2部では、データの巨大な文字列を構築しました.使用によってBlockCollection , しかし、我々は我々がここでしたボタンのような他の弛緩要素を取り付けることができます.
    最後にapps/slack-salesforce-starter-app/user-interface/modals/index.js , 我々はこの機能をエクスポートする必要がありますので、それは我々のインポートすることができますedit-contact.js 機能
    'use strict';
    const { whoamiresponse } = require('./whoami-response');
    const { editContactResponse } = require('./edit-contact-response');
    const { authorize_sf_prompt } = require('./authorize-sf-prompt');
    
    module.exports = { whoamiresponse, editContactResponse, authorize_sf_prompt };
    
    あなたがGitプッシュを介してHerokuにこの新しいコードを展開した後、あなたのスラックのワークスペースに切り替え、ショートカットを実行してみてくださいこのようなダイアログボックスで迎えられます.

    Salesforceデータの更新


    Salesforceデータを取得して表示することができます.今、それはSalesforceデータを変更するには、[編集]ボタンを接続する時間です!
    スラックの対話的なコンポーネントの多くは action_id , これはcallback_id , ユーザーが動作した要素を識別します.スターターキットの他のすべてと同じように、これらのアクションID用のリスナを定義できる特別なディレクトリがあります.apps/slack-salesforce-starter-app/listeners/actions . にindex.js そこにファイルを追加しましょう.
    'use strict';
    const { appHomeAuthorizeButtonCallback } = require('./app-home-authorize-btn');
    const { editContactButtonCallback } = require('./edit-contact-btn');
    
    module.exports.register = (app) => {
      app.action('authorize-with-salesforce', appHomeAuthorizeButtonCallback);
      app.action('edit_contact', editContactButtonCallback);
    };
    
    この同じフォルダで、新しいファイルを作成しますedit-contact-btn.js , これらの行をペーストします.
    'use strict';
    const {
      editIndividualContact,
      authorize_sf_prompt
    } = require('../../user-interface/modals');
    
    const editContactButtonCallback = async ({ body, ack, client, context }) => {
      const contactId = body.actions[0].value;
      try {
        await ack();
      } catch (error) {
        // eslint-disable-next-line no-console
        console.error(error);
      }
    
      if (context.hasAuthorized) {
        const conn = context.sfconnection;
        const result = await conn.query(
          `SELECT Id, Name, Description FROM Contact WHERE Id='${contactId}'`
        );
        let record = result.records[0];
        await client.views.push({
          trigger_id: body.trigger_id,
          view: editIndividualContact(record)
        });
      } else {
        // Get BotInfo
        const botInfo = await client.bots.info({ bot: context.botId });
        // Open a Modal with message to navigate to App Home for authorization
        await client.views.push({
          trigger_id: body.trigger_id,
          view: authorize_sf_prompt(context.teamId, botInfo.bot.app_id)
        });
      }
    };
    
    module.exports = { editContactButtonCallback };
    
    このファイルの開始と終了はよく知らなければなりませんack 応答はバックスラックに我々のアプリは、イベントペイロード(この場合、編集ボタンをクリックしてから)を受け取ったことをお知らせします.また、我々がまだ認証されているかどうかチェックしています.ここでは、私たちは、私たちのUIを構築するときに編集ボタンに値として添付された連絡先のIDを使用して、単一のDBルックアップを行っている.
    このコードのチャンクは、定義する必要のある別のモーダルデザインを作成します.バック・インapps/slack-salesforce-starter-app/user-interface/modals , ファイルを作成するedit-individual-contact.js これらの行をペーストします.
    'use strict';
    const { Elements, Modal, Blocks } = require('slack-block-builder');
    
    const editIndividualContact = (record) => {
      return Modal({ title: 'Edit Contact', close: 'Close' })
        .blocks(
          Blocks.Input({ blockId: 'description-block', label: record.Name }).element(
            Elements.TextInput({
              placeholder: record.Description,
              actionId: record.Id
            })
         )
       )
       .submit('Save')
       .callbackId('edit-individual')
       .buildToJSON();
    };
    
    module.exports = { editIndividualContact };
    
    ここでは、単一のブロックを持つモーダルを作成しました.要素は、連絡先の説明を事前に設定されます.我々はこのブロックを編集することができますし、我々が欲しいものに説明を変更します.
    このコードスニペットには2つの重要な注意点があります.
  • 添付してくださいactionId を返します.これは以前にEditボタンに接続したIDに似ていますが、今回は編集したレコードのIDに基づいて動的に生成されます.
  • また、別のIDを持っていることに気づくでしょうcallbackID , それはモーダルそのものに付けられる.あなたの心の後ろにこれらのIDの存在を保つ:我々はしばらくの間、これらの両方に対処します.今のところ、オープンindex.js この同じディレクトリとrequire/export この新しいモーダル作成機能
  • const { editIndividualContact } = require('./edit-individual-contact');
    // ...
    module.exports = {
      whoamiresponse,
      editContactResponse,
      editIndividualContact,
      authorize_sf_prompt
    };
    
    今、「編集」ボタンをクリックすると、説明を変更するよう求められます.

    我々は今Salesforceにこの更新されたテキストを送信する必要があります.ボタンをクリックして.なぜ?さて、スラックはこれらのような相互作用のためのイベントの異なるセットを持っていますview submissions . スターターキットは、アプリを構築するときに良いジャンプポイントを提供しますが、それはこの1つを含むすべてのスラックユースケースを処理しません.しかし、それは我々自身の機能を追加する問題ではない!
    内部apps/slack-salesforce-starter-app/user-interface folder , 新しいフォルダを作成するviews . 前のように、ここの保存ボタンにはアクションIDがあります.edit-individual-contact . 我々は戻って頭にapps/slack-salesforce-starter-app/listeners/actions/index.js これを関数に設定するには:
    const { editIndividualButtonCallback } = require('./edit-individual-btn);
    
    // ... 
    
    app.action('edit-individual-contact', editIndividualButtonCallback);
    
    新しいファイルを作成するedit-individual-contact.js , これらの行をペーストします.
    'use strict';
    
    const { submitEditCallback } = require('./submit-edit');
    
    module.exports.register = (app) => {
      app.view('edit-individual', submitEditCallback);
    };
    
    この形式は、スラックスターターキットによって提供される他のリスナーと同じです.唯一の違いは、私たちがview メソッド.また、他の人と一緒にこのリスナーを登録する必要があります.開くapps/slack-salesforce-starter-app/listeners/index.js , and require/register 新しいビューリスナー
    const viewListener = require('./views');
    
    module.exports.registerListeners = (app) => {
      // ...
      viewListener.register(app);
    };
    
    次はapps/slack-salesforce-starter-app/listeners/views , 別のファイルをsubmit-edit.js これらの行をペーストします.
    'use strict';
    const { editContactResponse, authorize_sf_prompt } = require('../../user-interface/modals');
    
    const submitEditCallback = async ({ view, ack, client, context }) => {
      try {
        await ack();
      } catch (error) {
        // eslint-disable-next-line no-console
        console.error(error);
      }
    
      if (context.hasAuthorized) {
        const contactId = view.blocks[0].element.action_id;
        const newDescription =
          view.state.values['description-block'][contactId].value;
        const conn = context.sfconnection;
        await conn.sobject('Contact').update({
          Id: contactId,
          Description: newDescription
        });
    
        await client.views.open({
          trigger_id: view.trigger_id,
          view: await editContactResponse(conn)
        });
      } else {
        // Get BotInfo
        const botInfo = await client.bots.info({ bot: context.botId });
        // Open a Modal with message to navigate to App Home for authorization
        await client.views.push({
          trigger_id: view.trigger_id,
           view: authorize_sf_prompt(context.teamId, botInfo.bot.app_id)
        });
      }
    };
    
    module.exports = { submitEditCallback };
    
    前に設定したIDを話し合いましょう.スラックは、我々のアプリにイベントペイロードを送信すると、自動的にデフォルトですべての入力要素のIDを生成します.スラックは、基になるデータが何であるかを知らないからです.アクションIDを介して要素を名前するのはあなたの責任です.スラックはペイロードを設定するキーとしてこれらのIDを使用します.スラックのペイロードを受け取ると、ユーザーが入力したデータを解析するためのキーを使用できます.
    今、あなたの連絡先の説明を編集するには、フローを通過する場合は、モードが正しく保存されることに気づくでしょう.Salesforce側のデータが更新されたことを確認するにはsfdx force:org:open 端末で「連絡先」タブに移動します.

    結論


    スラックスターターキットは、それがユーザーのイベントに耳を傾けるスラックアプリを構築するために絶対微風を作った.それを超えて、しかし、それはまた、SalesforceとHerokuとの絶対的な喜びとの相互作用を行います.我々は、ちょうどスターターキットがすることができるすべてについてカバーしました.あなたがスラックとSalesforceが一緒に働くことができる方法についてもっと学びたいならばbuilding better together . また、Salesforceと対話するバックエンドフレームワークは素晴らしいですJSforce プロジェクトそのドキュメントと両方をチェックアウトしてくださいthe Salesforce API Reference あなたが構築できるものについての詳細を学ぶために!