コラボフローの申請書にコメント機能を追加する

[コラボフロー Advent Calendar 2023](https://qiita.com/advent-calendar/2023/collaboflow) 6日目です。

去年はコラボフロー REST APIを利用するための[紹介記事](https://qiita.com/collabo-hiroaki/items/a6af87a471267619b600)だったので、今年は利用のヒントになるような記事にしてみたいと思います。

## はじめに

コラボフローを利用していて、申請の進行中に関係するユーザーに確認したいことや伝えたいことがあると思ったことはありませんか？

この記事では、申請開始後に利用できるコメント機能を追加する方法について説明します。

機能の実現方法は様々ありますが、コラボフローの機能だけで追加することもできます。
プログラムの内容についても人それぞれなので割愛して、機能の要点について説明していきます。

![１行コメント機能](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003588/683c097d-6046-c6d6-7a67-bb80bd727b23.png)

## コメント機能の構成

大きく分けて以下のような構成になります。

#### １．コメントデータを読み込んで一覧で表示する

#### ２．コメントデータを投稿する

#### ３．コメント機能の表示、非表示を切り替える

## 仕組みの概要

コラボフローの機能だけで構築する仕組みは以下の通りです。

#### １．コメントデータの保存先

コメントデータ用のフォームと経路を作成します。

#### ２．コメントデータの投稿（保存）処理

コラボフローJavaScriptAPIの、コラボフローREST APIのPOSTメソッドを使用して、申請書の申請・下書き保存APIを利用します。

[コラボフロー-REST-APIを実行する](https://collaboflow.zendesk.com/hc/ja/articles/360000262896)

#### ３．コメントデータの読み出し処理

コラボフローRESTAPIの申請書の検索APIと申請文書の詳細を取得するAPIを利用します。

[コラボフローAPI](http://docs.collaboflow.com/api-docs/#/)

#### ４．コメント機能の表示

コラボフローのラベルパーツを利用して追加します。

## フォームと経路の準備

#### １．コメント機能を追加するフォームの設定

コメント機能を追加するフォームには、**ラベルパーツ**を一つ追加します。
追加する位置はどこでも問題ありませんが、申請書の邪魔にならない位置が良いと思います。

![ラベルパーツの設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003588/5adeac99-652e-4704-9548-69379e2fecc5.png)

この例ではフォームの一番上に配置しています。

パーツIDは自動でも任意につけてもどちらでも問題ありませんが、この**パーツID**をプログラムで使用します。

#### ２．コメント機能を追加する経路の設定

経路の設定は、申請書類の段階設定で**追加したラベルの表示をオフ**にしておきます。
その他の段階はオンです。

![申請開始時はラベルパーツを表示しない](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003588/e778b2dd-414f-6f93-524c-4534562f1137.png)

#### ３．コメントデータを保存するフォーム

コメントデータ保存用のフォームは以下の通りです。
コメントを保存するパーツが設定されていれば問題ありません。
その他の情報を保存するパーツは事情に合わせて任意に設定してください。

コメントを保存するパーツの**パーツID**は、コメントの投稿やデータ取得のプログラムで使用します。

![コメントデータ用フォーム](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003588/0f8b4292-39ad-e20c-6d53-104f73b10ee7.png)

#### ４．コメントデータを保存する経路

経路の設定は、申請開始後に終了する経路にします。
自動で割り当てられる**経路ID**をコメントを投稿するプログラムで使用します。

![コメントデータ用経路](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003588/26a9c8e4-c223-9d88-ad22-88ffe1e183dc.png)

## プログラムの要点

各機能ごとにプログラムの要点を書きます。

#### １．コメントデータの投稿（保存）と検索のための仕組み

コメントデータ用の申請経路で申請を行うことで保存を行います。
コラボフローRESTAPIでの検索のための仕組みとして、**申請のタイトル**に、コメント機能を実行した申請書の**文書ID**を設定することで対応します。

コメント機能から申請されたコメント申請書は、以下のような内容になります。
申請書のタイトルが、コメント機能を実行した申請書の文書IDになっています。

![2023-12-05 21 21 14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003588/d7798ac5-5193-d155-1894-5f1a63bdd29b.png)

コメントデータ申請書の申請を行うプログラムのサンプルは以下の通りです。

```javascript:申請書の申請サンプルプログラム
    const commentDocument_app_cd = 1; // コメントデータ申請書があるアプリケーションのコード
    const CommentDocumentProcessesId = 1; // コメントデータ申請書の経路ID

    const myData = collaboflow.getLoginUser(); // ログインユーザーの情報を取得

    let DocumentID = data.document_id; // 申請書データから文書IDを取得
        
    // reqestdataの作成
    let requestdata = {
        "processes_id": CommentDocumentProcessesId,
        "request_userid": myData.userid,
        "app_cd": commentDocument_app_cd,
        "title": DocumentID,
        "document": {
            "fidDocumentId": DocumentID,
            "fidComment": CommentText
        }
    };
        
    // postメソッドで申請
    collaboflow.api.post('/v1/documents', requestdata)
    .then(function(response){
        // 応答時処理
        if(response.body.error) {
            // エラーコードが返ってきたときの処理
        }
    })
    .catch(function(err) {
        // エラー時処理
    });
```

APIの詳細は、[コラボフローAPI](http://docs.collaboflow.com/api-docs/#/)の「[POST Documentの/vi/documents](http://docs.collaboflow.com/api-docs/#/Document/requestDocument)」で確認してください。

:::note info
申請書データについて
申請書データはコラボフローの各画面のイベント処理を実行したときに取得できます。
コメント機能は申請開始後に利用する想定なので、申請書閲覧・判定画面イベントの表示イベント「request.detail.show」で取得しています。
詳しくは、[申請書閲覧・判定画面イベント](https://collaboflow.zendesk.com/hc/ja/articles/360000262856)で確認してください。
:::

#### ２．コメントデータの検索

コメントデータの検索には、コラボフロー REST APIの「[**POST /v1/documents/search**](http://docs.collaboflow.com/api-docs/#/Document/searchDocument)」を使用します。

ただ、このAPIは「**監査権限が付与されたグループに所属するユーザー**」か、「**システム管理者ユーザー**」でなければ利用できません。
このため、申請書の申請のようにコラボフローREST APIのPOSTメソッドを利用した場合、**権限のないユーザーはデータを取得することができません**。

この対策として、コメントデータの検索には「監査権限が付与されたグループに所属するユーザー」か、「システム管理者ユーザー」の認証情報でfetchを使用して情報を取得します。

```javascript:申請書の検索サンプルプログラム
    const commentDocument_app_cd = 1; // コメントデータ申請書があるアプリケーションのコード
    const CollaboflowAuthorization = "Basic [Base64エンコード済み認証データ]"; // 認証情報
    const DocumentLimit = 10; // 1回に取得するデータの件数
	let DocumentOffset = 0; // データ取得の開始位置
    let DocumentID = data.document_id; // 申請書データから文書IDを取得
	
    return new Promise((resolve,reject)=>{
        // APIリクエストの作成
	    const collaboflowRequest = new Request('https://cloud.collaboflow.com/[インスタンス名]/api/index.cfm/v1/documents/search');

        // APIリクエストヘッダーの作成
	    const collaboflowRequestHeaders = new Headers();
        collaboflowRequestHeaders.append('Content-Type', 'application/json');
	    collaboflowRequestHeaders.append('X-Collaboflow-Authorization', CollaboflowAuthorization);

        // APIリクエストデータの作成
        let querystring = "title = '" + DocumentID + "'"; // 検索する申請書のクエリー
        let requestdata = {
            "app_cd": commentDocument_app_cd,
            "query": querystring,
            "offset": DocumentOffset,
            "limit": DocumentLimit
        };

        // fetchのオプション設定
		const collaboflowRequestInit = {
			method: 'POST',
			headers: collaboflowRequestHeaders,
			mode: 'same-origin',
			credentials: 'omit',
            body: JSON.stringify(requestdata),
		};

    	// fetchの実行
        fetch(collaboflowRequest, collaboflowRequestInit)
		.then((response) => response.json())
		.then((data) => {
			// 応答時処理
			resolve([応答データ]);
		})
		.catch(function(err) {
            // エラー時処理
            reject();
		});
	});

```

#### ３．コメントデータの詳細の取得

申請書の検索APIで取得できるデータは、申請書の基本情報になります。
このため、保存されているコメントを取得するためには、申請内容の詳細を取得する「[**GET /v1/documents/文書ID/contents**](http://docs.collaboflow.com/api-docs/#/Document/getDocumentContents)」を使用します。

コラボフローREST APIのGETメソッドを利用した場合、取得できる申請書のデータは**閲覧権限がある申請書**に限られます。
このため、ここでも「監査権限が付与されたグループに所属するユーザー」か、「システム管理者ユーザー」の認証情報でfetchを使用して情報を取得します。

```javascript:申請内容の詳細を取得するサンプルプログラム
    const commentDocument_app_cd = 1; // コメントデータ申請書があるアプリケーションのコード
    const CollaboflowAuthorization = "Basic [Base64エンコード済み認証データ]"; // 認証情報
    const fidkey = "[コメントを保存するパーツのパーツID]"; // コメントの取り出し用
    let DocumentID = [コメントデータの申請書の文書ID]; // コメントデータ申請書の検索で取得した文書ID
	
    return new Promise((resolve,reject)=>{
        // APIリクエストの作成
        const collaboflowRequest = new Request('https://cloud.collaboflow.com/[インスタンス名]/api/index.cfm/v1/documents/' + DocumentID + '/contents?app_cd=' + commentDocument_app_cd);

        // APIリクエストヘッダーの作成
	    const collaboflowRequestHeaders = new Headers();
	    collaboflowRequestHeaders.append('X-Collaboflow-Authorization', CollaboflowAuthorization);

        // fetchのオプション設定
		const collaboflowRequestInit = {
			method: 'GET',
			headers: collaboflowRequestHeaders,
			mode: 'same-origin',
			credentials: 'omit',
		};

        // fetchの実行
		fetch(collaboflowRequest, collaboflowRequestInit)
		.then((response) => response.json())
		.then((data) => {
            // コメントを取得して返す
            let contentsdata = data.contents;
            let returnData = contentsdata[fidkey].value;
			resolve(returnData);
		})
		.catch(function(err) {
			// エラー時処理
			reject();
		});
	});
```

サンプルではコメントが保存されているパーツの**パーツID**を使用して、ピンポイントで値を取得して返しています。

#### ４．申請書内にコメント機能を追加する仕組み

コメント機能を申請書内に表示する位置は、ラベルパーツを利用して決定します。

ラベルパーツの**ラベルの内容**は、「**div_[パーツID]**」という**id**を持つ**divタグ**に表示されます。
この**divタグ**をターゲットに、コメント機能を追加します。

機能の実現の方法はいろいろあると思いますので、サンプルは一例としてDOMを利用して記述した場合のプログラムになります。

```javascript:DOMを利用した例
    // コメント機能を格納するdivを用意する
    let subWindowArea = document.createElement('div');
    subWindowArea.setAttribute('id','comment_area');
    subWindowArea.style.display = 'none';
    subWindowArea.appendChild([コメント機能]);
    
    // コメント機能を表示するためのボタンを用意する
    let btn = document.createElement('button');
    btn.setAttribute('id','commentbtn');
    btn.textContent = '開く';
    btn.setAttribute('type','button');
    btn.addEventListener ('click', function () {
        let commentbtn = document.getElementById('commentbtn');
        let comment_area = document.getElementById('comment_area');
        if (comment_area.style.display == 'block') {
            comment_area.style.display = 'none';
            commentbtn.textContent = '開く';
        } else {
            comment_area.style.display = 'block';
            commentbtn.textContent = '閉じる';
        };
    }, false);

    // コメント機能をラベルの表示用タグに追加する
    let target = document.getElementById('div_[ラベルパーツのパーツID]');
    target.appendChild(btn); // コメント機能ボタン
    target.appendChild(subWindowArea); // コメント機能本体
```

これで、コメント機能を作成するために必要な要素は一通りそろいました。
要素を組み合わせて、お好みの方法でコメント機能のプログラムを構築してください。

## さいごに

コラボフローには様々な機能があります。
コラボフロー単体でも工夫次第でいろいろな機能を追加できる例として、今回の記事を作成しました。

この記事が、何かのお役に立てれば幸いです。