前回のVol.2でワークフロー機能を取り入れて、より図書管理みたいなことができるようになりました。
さらに使い勝手のいいものを作ろうとすると避けては通れないのが、スクリプト機能ですね。スクリプト機能を活用することで標準機能では提供されていない独自の機能を追加してより使いやすいPleasanterを作ることもできます。
スクリプトとは?
スクリプトは、標準機能では実現できない操作を実現できるようにするために独自でプログラムを書いて拡張する開発者向けツールです。非エンジニアからすると難易度が高くなります。スクリプトでは、JavaScriptを使って記述するため、JavaScriptやフロントエンド系の開発したことがある方にとっては、そこまで学習コストが高くなく扱えます。むしろ、フロントエンド系の知識やテクニックが大活躍するかもしれませんね。
スクリプトの種類
スクリプトは、Pleasanterの画面上ではフロントエンド向けの処理を書く部分を差しますが、少し広い意味でのスクリプトから学んでみます。
既にWebアプリケーションの基本について理解されている方にとっては難しくない話だと思いますが、知らない方向けにフロントエンドとバックエンドで処理を実行するときの注意点を簡単に説明します。
フロントエンド(Pleasanter: スクリプト、独自実装)
- ブラウザからローカルリソースへのアクセスや画面の入力項目への操作(値の取得や設定など)ができる
- 重い処理を書くとクライアント側のマシンスペックやネットワーク環境影響されブラウザ動作が重くなりやすい
- アプリケーションエラーが発生したとしても該当のスクリプトだけが実行できなくなる
- ブラウザの開発者ツールからソースコードの閲覧が可能
バックエンド(Pleasanter: サーバースクリプト)
- クレデンシャル情報を隠すことができる
- 外部システムとの連携処理に適している
- アプリケーションエラーが発生した場合に作成や保存など特定の機能が使えなくなる
Pleasanterのスクリプトの種類を見てみましょう。
- スクリプト: フロントエンド向けのスクリプトで画面描画時に実行される
- サーバースクリプト: バックエンド向けのスクリプトで作成や保存ボタンを押した際にバックエンドで実行される
- 独自実装(HTMLタブ): フロントエンド向け。拡張HTMLのところで
<script>
タグを用いて定義でき、独自ボタンとの組み合わせやプロセスのOnClickなどで利用できる
それぞれを上手く使いこなすのは慣れが必要そうですが、どこに書くとどこで作用するのかについては理解できました。
今回やりたいこと
再び図書管理の話に戻りましょう。今回やりたいことについて整理ました。
- 新規作成時にISBNを入力して
書籍情報取得
ボタンをクリックしたら、外部APIを使って書籍情報を取得 - 取得した書籍情報から書籍名などを取得し、入力項目に設定する
作ってみる
では、実際に作ってみます。どこで作ってみようかとあれこれ考えながらしばらく試していました。
最初に拡張HTML + 独自実装(HTMLタブ)で入力フォームの横にボタンを置いて作ってみようと画像みたいなイメージで作ってみました。
画面サイズを変えた時に思ったような場所に要素が表示されなかったり、レイアウトが崩れてしまったりするのでCSSのテクニックが必要そうでした。今回は作り込みたくはなかったので早々に見切りりをつけて次の方法へ。
次に考えたのがプロセスを使って実現する方法です。プロセスには2回目で紹介を省略したOnClickの機能を使うことで、ボタンクリック時に独自関数を実行させることができるみたいです。
各項目で設定している内容はこんな感じです。
項目 | 説明 | 値 |
---|---|---|
名称 | プロセス名を設定 | getBookInfo |
表示名 | プロセスの表示名を設定。画面に表示されるもの | 書籍情報取得 |
画面種別 | プロセスを適用する画面 | 新規作成 |
現在の状況 | プロセスを表示する状況 | * (すべて) |
変更後の状況 | プロセス実行後に変更する状況 | * (変更しない) |
説明 | プロセスの説明 | (お好みで) |
ツールチップ | ボタンにマウスオーバーした際に表示される説明 | (お好みで) |
OnClick | 実行させたい処理※1 | getBookInfo(); |
アクション種別 | 保存や作成など標準的な操作を指定できる。無し の場合は、標準的な処理を実行しない |
無し |
※1: 複雑なスクリプトをここに直接は書けず、ワンライナー(1行で書ける範囲くらい)。後で説明する独自実装で作成した関数を呼び出す形が一般的な使い方みたいです。
ちょうどOnClickって何に使うんだろう?と思っていたところで使う機会があり、記憶が新しいうちに学ぶことができて理解が進みますね。
独自実装
独自実装は、HTMLタブから任意のHTMLを直接埋め込むことができます。<header>
タグ内の上下、<body>
タグの上下などHTMLを直接描いたことがある方であれば、馴染みがある場所ではないでしょうか。もちろん、外部で公開されているスクリプトファイルや、スタイルシートなどをここで読み込むことで、組み込むことができます。
今回は、ここにやりたい関数を事前に定義しておいて、プロセスから呼び出してみます。
作成方法は、管理 > テーブルの管理 > HTMLタグ
を開き、新しく新規作成から新しく作成します。
項目 | 説明 | 設定値 |
---|---|---|
タイトル | getBookInfo |
|
挿入位置 | HTMLを挿入する位置 | Body script bottom |
HTML | (あとで解説) | |
出力先 | HTMLを反映する先を指定 | 新規作成 のみ |
あとで解説と言っていたスクリプトについて説明します。
最近、話題のChatGPTにfetchを使ったデータ取得のコードを生成してみてもらいました。JavaScriptに慣れていない方は、非同期通信の仕組みにはなれないと思いますが今回のfetchは非同期な通信になるので少しコツが必要です。
非同期通信は実行した処理のレスポンスを待たずに、次の行の処理が実行されます。まさにここが上手く使うと便利な機能ではあるのですが、知らずに使ってしまうと、おかしな動きに感じてしまうので、慣れていない人にとっては混乱ポイントです。
ソースコードの全体はこんな感じです。
<script type="text/javascript"> function getBookInfo() { const isbn = $p.getControl("NumA").val(); fetch(`https://api.openbd.jp/v1/get?isbn=${isbn}`) .then(response => { if (!response.ok) { throw new Error("Network response was not ok"); } return response.json(); // レスポンスをJSON形式で取得 }) .then(data => { const title = data[0]["onix"]["DescriptiveDetail"]["TitleDetail"]["TitleElement"]["TitleText"]["content"]; $p.set($p.getControl("Title"), title); }) .catch(error => { console.error("There was a problem with the fetch operation:", error); }); } </script>
ポイントに絞りながら少し解説します。
const isbn = $p.getControl("NumA").val();
$p
はPleasanterが提供している標準スクリプトで、これを使うことで画面の入力項目の情報を簡単に取得することができます。
NumA
は、予め決められた名前なのでブラウザの開発者ツールの要素から該当する入力項目を選択してID属性から取得します。
次に実際にAPIのリクエストを投げるところではfetchを使います。fetchは、HTTP リクエストを行い、レスポンスを処理するためのJavaScriptインターフェイスです。
fetch(...).then(...).catch(...);
非同期な通信といっても何か難しい実装をするわけではなく、レスポンスに応じて正常系であればthen(...)
の関数が実行され、異常系であればcatch(...)
をPromise チェーンと呼ばれる形でつなげて書くことで実装できます。
then(...)
は、複数を連続的に書くこともでき、処理が正常に完了すると次のthen(...)
へ処理が続いていきます。もし、途中で例外が発生した場合には、catch(...)
が捕捉します。
then(...)
の処理ではレスポンスデータをJSON形式に変換(1つ目のthen)してからタイトルを取得してPleasanterの標準スクリプトを使って入力項目に値を設定(2つ目のthen)しています。
1つ目
.then(response => { if (!response.ok) { throw new Error("Network response was not ok"); } return response.json(); // レスポンスをJSON形式で取得 })
2つ目
.then(data => { const title = data[0]["onix"]["DescriptiveDetail"]["TitleDetail"]["TitleElement"]["TitleText"]["content"]; $p.set($p.getControl("Title"), title); })
新規作成を押してみるとボタンが表示されていて、ISBNを入力後に取得を押すと無事に書籍タイトルが取得できました。
同じような要領で著者や出版社も取得して反映することができます。
おわりに
今回でテーブルを使った一連の流れは理解できたように思います。まだまだ改善の余地は大いにあるので、より細かく作り込んだりしながら使い勝手の良い形に整えていければと思います。今後も社内のあれこれをPleasanter上でやれるように作りながらあれこれ機能への理解を深めていきたいですね。
これからも自分でお題を決めながらブログにまとめていくと思いますので、一緒にPleasanterマスターを目指しましょう。