Auraでユーティリティバーをクリックすると新規コンソールタブを立ち上げるコンポーネントを作る

# はじめに

今回は、
クリックすると設定したページの新規コンソールタブを開く、ユーティリティバーのコンポーネントをAuraで作成します。

# できあがったもの

アプリケーションマネージャーでユーティリティ項目として
遷移させたいURLを設定。

![スクリーンショット 2023-12-17 16.59.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/45868032-da97-dc31-3f61-1683dd5f94e0.png)

設置した項目をクリックすると設定したページが新規コンソールタブで開きます。
URLを設定しているだけなので、Salesforce内のページ・WEBタブ・WEBページ なども開けます。

:::note warn
Salesforce外のWEBページを開く場合は、Salesforce内にiframeで呼び出すことになるため
iframe呼び出しが禁止されているサイトでは使えません。
:::

![最近参照したデータ-取引先-Salesforce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/3d7b850b-3028-3c99-c214-863a223e3f20.png)

# なぜ作ろうと思ったのか

- 一つのアプリケーションを`フィールド` `インサイド`のように職能としては同じだけど役割が違う場合
    - Salesforce内でのページや、WEBサイト、カスタムWEBタブの利用頻度が異なってくる
 
- いろんなやり方はあるけど`ユーティリティバー`を使った場合だとどうするのか？
    - 特にクリック数を少なくするには？

という考えから`ユーティリティバー`に単純なリンクを開くボタンを設置したくて作ってみました。


# この記事で書かないこと

- Auraの基本説明
- Auraコンポーネントの作り方
- SalesforceDXのセットアップ

# できあがったコード

コンポーネント名：utilitySingleLinkButton

```html:utilitySingleLinkButton.cmp
<aura:component implements="flexipage:availableForAllPageTypes" access="global">
  <lightning:utilityBarAPI aura:id="utilitybar" />
  <aura:handler name="init" value="{!this}" action="{!c.init}" />
  <aura:attribute name="url" type="String" />
  <aura:attribute name="label" type="String" />
  <aura:attribute name="isFocus" type="Boolean" />
  <lightning:workspaceAPI aura:id="workspace" />
</aura:component>
```

```html:utilitySingleLinkButton.design
<design:component label="新規タブ表示ボタン">
  <design:attribute name="url" required="true" description="クリックで開きたいリンク、相対リンク使用可（lightning.force.com の後ろの /から入力）" />
  <design:attribute name="label" required="true" description="タブ名" />
  <design:attribute name="isFocus" description="タブにフォーカスを当てるかどうか" default="true" />
</design:component>
```

```javascript: utilitySingleLinkButtonController.js
({
  init: function (component) {
    var openTab = function () {
      var workspaceAPI = component.find("workspace");
      var label = component.get("v.label");
      workspaceAPI
        .openTab({
          url: component.get("v.url"),
          label: label,
          focus: component.get("v.isFocus")
        })
        .then(function (response) {
          workspaceAPI.setTabIcon({
            tabId: response,
            icon: "utility:people",
            iconAlt: label
          });
          var utilityAPI = component.find("utilitybar");
          utilityAPI.minimizeUtility();
        })
        .catch(function () {});
    };
    openTab();
    // utilitybar APIがinit時に即時使用ができないため、setTimeoutで遅延させる
    setTimeout(function () {
      var utilityAPI = component.find("utilitybar");
      utilityAPI.minimizeUtility();
      utilityAPI
        .onUtilityClick({
          eventHandler: openTab
        })
        .then(function () {})
        .catch(function () {});
    }, 500);
  }
});

```

# コード解説

## 1. Auraでユーティリティバーを扱うための設定

https://developer.salesforce.com/docs/atlas.ja-jp.lightning.meta/lightning/components_config_for_app_builder.htm

>flexipage:availableForAllPageTypes
レコードページと他の種別のページ (Lightning アプリケーションのユーティリティバーを含む) でコンポーネントを使用できます。

`implements="flexipage:availableForAllPageTypes"`でアプリケーションのユーティリティ項目に設定できます。

```html:utilitySingleLinkButton.cmp
<aura:component implements="flexipage:availableForAllPageTypes" access="global"> 
.
.
.
</aura:component>
```

## 2. ユーティリティ項目設定時にプロパティを設定できるようにする

https://developer.salesforce.com/docs/atlas.ja-jp.lightning.meta/lightning/components_config_for_app_builder_design_files.htm

`design`ファイルでプロパティの項目を作成できます。

```html:utilitySingleLinkButton.design
<design:component label="新規タブ表示ボタン">
  <design:attribute name="url" required="true" description="クリックで開きたいリンク、相対リンク使用可（lightning.force.com の後ろの /から入力）" />
  <design:attribute name="label" required="true" description="タブ名" />
  <design:attribute name="isFocus" description="タブにフォーカスを当てるかどうか" default="true" />
</design:component>
```

![スクリーンショット 2023-12-17 16.59.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/45868032-da97-dc31-3f61-1683dd5f94e0.png)


設定した値を利用できるように、`cmp`にも同じ`attribute`名の受け皿を設定します。

```html:utilitySingleLinkButton.cmp
<aura:component implements="flexipage:availableForAllPageTypes" access="global">
  <aura:attribute name="url" type="String" />
  <aura:attribute name="label" type="String" />
  <aura:attribute name="isFocus" type="Boolean" />
</aura:component>
```


## 3. workspaceAPI・utilityBarAPIを利用可能にする

`<lightning:utilityBarAPI aura:id="utilitybar" />`でutilityBarAPIの有効
`<lightning:workspaceAPI aura:id="workspace" />`でworkspaceAPIの有効
をしています。


```html:utilitySingleLinkButton.cmp
<aura:component implements="flexipage:availableForAllPageTypes" access="global">
  <lightning:utilityBarAPI aura:id="utilitybar" />
  <lightning:workspaceAPI aura:id="workspace" />
</aura:component>
```


utilityBarAPIは、ユーティリティバーに関する操作（開く・閉じる等）ができます。

https://developer.salesforce.com/docs/component-library/bundle/lightning:utilityBarAPI/documentation

workspaceAPIは、コンソールアプリケーションに関する操作（タブの開く・閉じる等）ができます。

https://developer.salesforce.com/docs/component-library/bundle/lightning:workspaceAPI/documentation

# 4. クリックされたらリンクを開くようにする

初期化処理として`aura:handler`を設定しています。

https://developer.salesforce.com/docs/atlas.ja-jp.lightning.meta/lightning/events_component_handling_intro.htm

```html:utilitySingleLinkButton.cmp
<aura:component implements="flexipage:availableForAllPageTypes" access="global">
  ・
  ・
  <aura:handler name="init" value="{!this}" action="{!c.init}" />
  ・
  ・
  ・
</aura:component>
```

utilityBarAPIでやりたいこと
- クリックした時に`workspaceAPI`を使って新規コンソールタブを開く
- ページを開いたら、開いたユーティリティ項目を閉じる

`onUtilityClick`でクリックした時に実行するfunctionを設定。
`minimizeUtility`でユーティリティ項目を閉じています。

https://developer.salesforce.com/docs/atlas.ja-jp.api_console.meta/api_console/sforce_api_console_lightning_onUtilityClick.htm

https://developer.salesforce.com/docs/atlas.en-us.api_console.meta/api_console/sforce_api_console_lightning_minimizeItem.htm

本当はinitの状態で、`setTimeout`を使わずにそのまま
onUtilityClickを設定したかったのですが、`init`でutilityBarAPIを使うとutilityIdを取得できずエラーになるので`setTimeout`で遅延させています。
クリックイベント時に動作させたい、極力ボタンのようなユーザ体験にしたいので
init内で現在書いています。

https://salesforce.stackexchange.com/questions/267258/utility-bar-api-unable-to-obtain-eclosing-utility-id

```javascript: utilitySingleLinkButtonController.js
({
  init: function (component) {
    var openTab = function () {
      // タブを開く処理
    };
    openTab();
    // utilitybar APIがinit時に即時使用ができないため、setTimeoutで遅延させる
    setTimeout(function () {
      var utilityAPI = component.find("utilitybar");
      utilityAPI.minimizeUtility();
      utilityAPI
        .onUtilityClick({
          eventHandler: openTab
        })
        .then(function () {})
        .catch(function () {});
    }, 500);
  }
});

```


workspaceAPIでやりたいこと
- クリックした時に設定したURLを新規プライマリータブで開く
- 開く際に、フォーカスをオンにしタブ名を設定する

openTabの`url`に開きたいURL、`label`にタブ名、`focus` trueで開いたタブをフォーカス状態にします。

新規タブを開いた後は、挙動としてボタンを同じように見せたいので
`minimizeUtility`を使ってユーティリティ項目を閉じています。


https://developer.salesforce.com/docs/atlas.ja-jp.api_console.meta/api_console/sforce_api_console_lightning_opentab.htm

```javascript: utilitySingleLinkButtonController.js
({
  init: function (component) {
    var openTab = function () {
      var workspaceAPI = component.find("workspace");
      var label = component.get("v.label");
      workspaceAPI
        .openTab({
          url: component.get("v.url"),
          label: label,
          focus: component.get("v.isFocus")
        })
        .then(function (response) {
          workspaceAPI.setTabIcon({
            tabId: response,
            icon: "utility:people",
            iconAlt: label
          });
          var utilityAPI = component.find("utilitybar");
          utilityAPI.minimizeUtility();
        })
        .catch(function () {});
    };
  }
});

```

# 最後に

ユーティリティバーをボタンのように見せる方法他にあれば、ぜひコメント等にご意見いただきたいです。
（実は標準機能にあったりして？）

今回の`workspaceAPI`も使用しましたが、
`workspaceAPI`はなんとLWCでもベータですが対応しましたね。

LWCでできないことを現在Auraで書くのですが、ついにAura離れも近くなっているかもです。

https://help.salesforce.com/s/articleView?id=release-notes.rn_lwc_workspaceAPI.htm&release=246&type=5