LoginSignup
2
5

LINE WORKS の WOFF アプリから kintone アプリにデータ入力

Last updated at Posted at 2023-08-20

サイボウズさん主催の kintone devCamp Boost! のセッションで提供したハンズオンの内容を記事にしました。

LINE WORKS の WOFF を利用した入力画面から kintone アプリにデータを入力します。

WOFF とは

WORKS Front-end Framework(以下、WOFF)は、「LINE WORKS」上で動くWeb アプリを実装できる開発プラットフォームです。このWOFFで作られた Web アプリ(以下、WOFFアプリ)は、トークメッセージなどからシームレスに立ち上がるミニアプリとして、幅広い連携を実現します。
WOFFアプリは HTML と JavaScript をベースとした Web アプリです。WOFF アプリを実行したユーザーの情報の取得や、WOFF アプリを呼び出したトークルームへのメッセージの送信などができるようになります。

image.png

Power Automate で WOFF を作成

トリガー作成

フローのトリガーとして [HTTP 要求の受信時] を用います。
一覧から探すか、または検索して "要求" を選択してください。

image.png

トリガーで "HTTP 要求の受信時" を選択。
image.png

[詳細オプションを表示する] をクリックします。
l_147288799_194_01d893b21ddb6b4c6f94aaee2badc0ba.png

[method] で "GET" を選択します。
l_147288799_193_7703a7cab797b3770f7b6c323965f181.png

アクション作成

[+ 新しいステップ] をクリック。
l_147288799_195_8ca8f510221da877d5de0dfcf68db8f5.png

"Http 要求の受信時" で受けた Get のリクエストに応じて WOFF を表示するために、[応答] のアクションを追加します。
一覧から探すか、または検索して [要求] を選択し、[応答] のアクションを指定してください。
l_147288799_181_ed0bed98cdbf8f86f6884dad2703b483.png

l_147288799_182_66bf83f05cf08e08b2b4564a5f289b32.png

[応答] のアクションが追加されました。
l_147288799_196_b40fd63af2743aade8c9abc213ed146c.png

各項目を以下のとおり指定します。

ヘッダーは以下のとおりです。

キー:

Content-Type

値:

text/html; charset=UTF-8

本文は以下をコピー、ペーストしてください。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title>devCamp Boost ハンズオン</title>
<script>
// WOFF ID を書き換えてください
const WOFF_ID = "i658h0DFhT-mSlGssQa6_Q";
// HTTP POST の URL を書き換えてください
const url = "https://prod-13.japaneast.logic.azure.com:443/workflows/4f8b1e46a6df44e1b48b0939a1e62f35/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=lrPlc5_GGqRmHuux_XVD7VU8TsnKss2yr7N2zmTOmwc";
</script>
    <script charset="utf-8" src="https://static.worksmobile.net/static/wm/woff/edge/3.6/sdk.js"></script>
    <style>
        /* Global Styles */
        body {
            font-family: 'Arial', sans-serif;
            padding: 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        h1 {
            margin-bottom: 15px;
        }

        input, select, button {
            width: 100%;
            margin-bottom: 15px;
            padding: 10px;
            box-sizing: border-box;
            font-size: 16px;
        }

        /* Toggle Switch CSS */
        .switch {
            position: relative;
            width: 60px;
            height: 34px;
        }

        .switch input { 
            opacity: 0;
            width: 0;
            height: 0;
        }

        .slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: #ccc;
            transition: .4s;
        }

        .slider:before {
            position: absolute;
            content: "";
            height: 26px;
            width: 26px;
            left: 4px;
            bottom: 4px;
            background-color: white;
            transition: .4s;
        }

        input:checked + .slider {
            background-color: #2196F3;
        }

        input:checked + .slider:before {
            transform: translateX(26px);
        }

        .slider.round {
            border-radius: 34px;
        }

        .slider.round:before {
            border-radius: 50%;
        }

        /* Label for Toggle */
        label {
            display: flex;
            align-items: center;
            justify-content: space-between;
            width: 100%;
        }
    </style>
</head>
<body>
<h1>devCamp Boost</h1>

<label for="displayNameInput">表示名:</label>
<input type="text" id="displayNameInput" placeholder="名前を入力" required>

<label for="dateInput">日付:</label>
<input type="date" id="dateInput" required>

<label for="timeInput">開始時刻:</label>
<input type="time" id="timeInput" required>

<label for="workTypeSelect">作業種別:</label>
<select id="workTypeSelect">
    <option value="組み立て">組み立て</option>
    <option value="検査">検査</option>
    <option value="洗浄">洗浄</option>
    <option value="塗装">塗装</option>
</select>

<label>
    位置情報を送信: 
    <div class="switch">
        <input type="checkbox" id="locationToggle">
        <span class="slider round"></span>
    </div>
</label>

<button onclick="sendData()">送信</button>

    <script>
        document.addEventListener("DOMContentLoaded", function() {
            woff.init({
                woffId: WOFF_ID
            })
            .then(() => {
                return woff.getProfile();
            })
            .then(profile => {
                const input = document.getElementById("displayNameInput");
                input.value = profile.displayName;
            })
            .catch(err => {
                console.log(err.code, err.message);
            });
        });

        function getLocation() {
            return new Promise((resolve, reject) => {
                if (!navigator.geolocation) {
                    reject(new Error("Geolocation is not supported by your browser."));
                } else {
                    navigator.geolocation.getCurrentPosition(
                        position => {
                            resolve({
                                lat: position.coords.latitude,
                                lng: position.coords.longitude
                            });
                        },
                        error => {
                            reject(new Error("Unable to retrieve your location."));
                        }
                    );
                }
            });
        }

        async function sendData() {
            const displayNameValue = document.getElementById("displayNameInput").value;
            const dateValue = document.getElementById("dateInput").value;
            const timeValue = document.getElementById("timeInput").value;
            const workTypeValue = document.getElementById("workTypeSelect").value;
            const locationToggle = document.getElementById("locationToggle").checked;
            let locationData = null;

            if (locationToggle) {
                try {
                    locationData = await getLocation();
                } catch (err) {
                    console.error(err.message);
                    return;
                }
            }

            const data = {
                displayName: displayNameValue,
                date: dateValue,
                time: timeValue,
                workType: workTypeValue,
                location: locationData
            };



            fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(data)
            })
            .then(response => {
                if (response.ok) {
                    woff.closeWindow();
                } else {
                    return response.json();
                }
            })
            .then(dataResponse => {
                if (dataResponse) {
                    console.log(dataResponse);
                }
            })
            .catch(error => {
                console.error('Error:', error);
            });
        }
    </script>
</body>
</html>

WOFF ID と HTTP POST の URL

以下の部分は後ほど書き換えます。

// WOFF ID を書き換えてください
const WOFF_ID = "i658h0DFhT-mSlGssQa6_Q";
// HTTP POST の URL を書き換えてください
const url = "https://prod-13.japaneast.logic.azure.com:443/workflows/4f8b1e46a6df44e1b48b0939a1e62f35/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=lrPlc5_GGqRmHuux_XVD7VU8TsnKss2yr7N2zmTOmwc";

[保存] をクリックします。
l_147288799_185_45a3436af6fb589bf4f779078b611a43.png

"HTTP 要求の受信時" の "HTTP POST の URL" が生成されているので、コピーボタンをクリックし、いずれかの場所にメモしてください。
l_147288799_186_5acb734325516d8e82c476ec7de90d75.png

LINE WORKS Developer Console で WOFF アプリ登録

LINE WORKS Developer Console にアクセスします。
https://dev.worksmobile.com/jp/console/openapi/v2/app/list/view

WOFF アプリを登録します。
https://developers.worksmobile.com/jp/docs/woff-guide#create-woff-app

WOFFアプリで [登録] ボタンをクリック。
l_147288799_188_b9761640c2522b6c793d4908b3573392.png

WOFF名: 任意の名前を指定
Endpoint URL を PowerAutomate で生成された HTTP 要求の受信時の URL を指定
サイズ: [Tall] を選択

[保存] ボタンをクリックしてください。
l_147288799_189_d298ebf8a6090fa2f2a4d26a2a6504fa.png

WOFF ID をコピーします。
image.png

[応答] アクションの本文の WOFF ID を書き換えてください。
l_147288799_295_d9ecebddfc57a19fdb61372ebb6e238a.png

[保存] してください。
l_147288799_296_b4b49d490bc6c80d54335308c83272d6.png

動作確認

WOFF アプリの [URL] コピー ボタンをクリックします。
l_147288799_190_e75690d9382079a5e9d743415e764cb6.png

コピーした URL を LINE WORKS のトークで自分に送ります。
l_217128028_5_a601005897c9ea57ec7608d42a4b07fa.png

トークルームで URL をタップすると WOFF アプリが表示されます。
モバイルアプリで実行すると、[表示名] に WOFF SDK で取得されたログイン中の LINE WORKS ID の表示名が既定値として入力された状態になります。
l_217128028_7_4eb67a1bfbb91ad7284889faef4b8eef.png

この時点では [送信ボタン] は、まだ正しく動作しません。タップしないでください。

Power Automate で WOFF アプリからのデータを受信するフローを作成

Kintone アプリの APIトークンの設定

Kintone アプリの APIトークンを設定します。
該当のヘルプ記事は以下です。
https://jp.cybozu.help/k/ja/user/app_settings/api_token.html

アプリの画面の右側の歯車アイコン横の下向き矢印をクリックするとプルダウン メニュが表示されます。
[カスタマイズ/サービス連携] の [APIトークン] をクリックします。
l_147288799_279_74a9033e0f7d33f7d39d00e81cea2676.png

APIトークンの設定画面で [生成する] をクリックします。
l_147288799_289_3f9f1e367d253733646164e28a0e0e20.png

生成された APIトークンはメモしてください。また、アクセス権で [レコード追加] を選択してください。
[保存] します。
l_147288799_290_0b1746d356b6a8141f09c2ad44b0caf6.png

[アプリの設定] で [アプリを更新] をクリック。
l_147288799_285_14408cfeed2974e8b0e96128b167af73.png

トリガー作成

Power Automate のフローのトリガーとして [HTTP 要求の受信時] を用います。
これにより、WOFF のフォームから送信されたメッセージを受信します。

一覧から探すか、または検索して "要求" を選択してください。
image.png

トリガーで "HTTP 要求の受信時" を選択。
image.png

要求本文の JSON スキーマに以下を記入。
l_147288799_255_3c12b5132a12f241454bec708cf4e83c.png

{
    "type": "object",
    "properties": {
        "displayName": {
            "type": "string"
        },
        "date": {
            "type": "string"
        },
        "time": {
            "type": "string"
        },
        "workType": {
            "type": "string"
        },
        "location": {
            "type": "object",
            "properties": {
                "lat": {
                    "type": "number"
                },
                "lng": {
                    "type": "number"
                }
            }
        }
    }
}

[詳細オプションを表示する] をクリックします。
l_147288799_194_01d893b21ddb6b4c6f94aaee2badc0ba.png

method で "POST" を選択。
l_147288799_197_f5be79d230db5900d7cc3d5d0a597e6e.png

アクション作成

[+ 新しいステップ] をクリック。
image.png

"Http 要求の受信時" で受けた内容を基に kintone の API リクエストを送信するために[HTTP] のアクションを追加します。
一覧から探すか、または検索して "HTTP" を選択し、[HTTP] のアクションを指定してください。
image.png

[HTTP] が追加されました。
image.png

以下のとおり、各入力項目の値を登録します。
方法: プルダウンから "POST" を選択
image.png

URI: 自分の環境の URL を基に記述します。
l_147288799_291_e67f426a99557d7316aa06195d5729cd.png

https://sample.cybozu.com/k/v1/record.json

cybozu developer network の以下の記事を参照してください。
https://cybozu.dev/ja/kintone/docs/rest-api/records/get-record/

l_147288799_231_d3775bd2811134a35c28c6822c7f8464.png

ヘッダーは以下のとおりです。

キー:

X-Cybozu-API-Token

値:

kintone アプリの設定で生成したトークン値

キー:

Content-Type

値:

application/json

本文は以下をコピー、ペーストしたうえで、

{
  "app": <アプリ ID を記入>,
  "record": {
    "worker": {
      "type": "SINGLE_LINE_TEXT",
      "value": "@{triggerBody()?['displayName']}"
    },
    "日付": {
      "type": "DATE",
      "value": "@{triggerBody()?['date']}"
    },
    "時刻": {
      "type": "TIME",
      "value": "@{triggerBody()?['time']}"
    },
    "workType": {
      "type": "SINGLE_LINE_TEXT",
      "value": "@{triggerBody()?['workType']}"
    },
    "lng": {
      "type": "SINGLE_LINE_TEXT",
      "value": "@{triggerBody()?['location']?['lng']}"
    },
    "lat": {
      "type": "SINGLE_LINE_TEXT",
      "value": "@{triggerBody()?['location']?['lat']}"
    }
  }
}

app の id は対象のアプリの id に書き換えてください。

l_147288799_291_e67f426a99557d7316aa06195d5729cd.png

URL 末尾の数字が ID です。

[+ 新しいステップ] をクリック。
image.png

kintone アプリのレコード登録完了を LINE WORKS の Bot で通知するため [HTTP] のアクションを追加します。
一覧から探すか、または検索して "HTTP" を選択し、[HTTP] のアクションを指定してください。
image.png

[HTTP] が追加されました。
image.png

以下のとおり、各入力項目の値を登録します。
方法: プルダウンから "POST" を選択
image.png

URI: Bot ID は LINE WORKS Developer Console で登録した自分の Bot の Bot ID を記述します。先ほどメモしたものです。

https://www.worksapis.com/v1.0/bots/{botId}/users/{userId}/messages

l_1517737_1831_40de7112ec6d55361af480116326d9a0.png

userID は、自分の LINE WORKS ID を指定します。

ヘッダーは以下のとおりです。

キー:

Content-Type

値:

application/json

キー:

Authorization

値:

Bearer <token>

本文は以下をコピー、ペーストします。

{
  "content": {
    "type": "text",
    "text": "kintone アプリに登録したよ!\nレコード番号 @{outputs('HTTP')?['body']?['id']}  \nお疲れ様でした☺"
  }
}

[保存] をクリックします。
image.png

"HTTP 要求の受信時" の "HTTP POST の URL" が生成されているので、コピーボタンをクリックし、いずれかの場所にメモしてください。
image.png

この URL を以下の記事のスクリプト内に記述します。
https://qiita.com/iwaohig/private/5273a52bad121449403f#woff-id-%E3%81%A8-http-post-%E3%81%AE-url
l_147288799_297_c8e52a8b6a47820f4faef9d06f161437.png

動作確認

前の手順で自分に送信した WOFF URL から WOFF の画面を表示します。
l_217128028_5_a601005897c9ea57ec7608d42a4b07fa.png

各項目を入力します。

モバイルアプリから実行すると表示名が WOFF SDK の woff.getProfile() で取得した値が初期値として示されます。
https://developers.worksmobile.com/jp/docs/woff-api#woff-getprofile

日付、時刻、リストボックスなどは Bot のテキストより直感的な UI を提供できます。
l_217128028_7_4eb67a1bfbb91ad7284889faef4b8eef.png
l_217128028_12_675dbb99b307f9ee29ce2bb2506f5b5e.png
l_217128028_13_4d7f0596872d4925432388a24cf4169d.png

[位置情報を送信] のトグル スイッチを有効にすると、位置情報を取得して送信されます。
l_217128028_15_96bf66c3b61e71c89fd810f5baca5f5f.png

送信ボタンをタップまたはクリックし、正しくデータ送信されると WOFF SDK の woff.closeWindow() メソッドでアプリが終了します。
https://developers.worksmobile.com/jp/docs/woff-api#close-woff-app

kintone アプリにデータが登録されます。
l_217128028_16_b3013c29059090c63b11757df45c1189.png

また通知 Bot からレコード登録のお知らせが届きます。
l_147288799_293_4a72558df2e4276edce7ca72e06a7e52.png

WOFF を固定メニューから起動できるようにする

LINE WORKS の Bot の固定メニューから WOFF を起動できるように登録します。

トリガー作成

[モバイルの Flow ボタン] を選択します。
image.png

フローのトリガーとして [手動でフローをトリガーします] を選択します。
image.png

アクション作成

[+ 新しいステップ] をクリック。
image.png

[HTTP] のアクションを追加します。
一覧から探すか、または検索して "HTTP" を選択し、[HTTP] のアクションを指定してください。
image.png

[HTTP] が追加されました。
image.png

以下のとおり、各入力項目の値を登録します。
方法: プルダウンから "POST" を選択
image.png

URI: 以下の URI を使います。

https://www.worksapis.com/v1.0/bots/{botId}/persistentmenu

{BotID} は書き換えてください。

ヘッダーは以下のとおりです。

キー:

Content-Type

値:

application/json

キー:

Authorization

値:

Bearer <token>

本文は以下です。
LINE WORKS Developer Console で生成されたものに書き換えてください。

{
  "content": {
    "actions": [
      {
        "type": "uri",
        "label": "WOFF",
        "uri": "<WOFF URL>"
      }
    ]
  }
}

[保存] をクリックします。
image.png

実行

フローを実行します。
l_147288799_323_ebbc39cdf38c19ef9e746086c87fea19.png

l_147288799_324_2251b11e64f93ec03b4e28f083663127.png

固定メニューから WOFF アプリを実行できます。
l_147288799_327_1577fb2eec82520ff4d34e0f123aec33.png

l_147288799_328_e626bf7ff442fa1f6ebbbaf80b165fc8.png

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5