知ってると嬉しい kintoneプラグイン開発関連のメモ

[kintone Advent Calendar 2018](https://qiita.com/advent-calendar/2018/kintone) の 5日目の記事です。
最近kintoneのプラグイン開発に関する業務を行っているので、プラグイン開発に関係する細かいことをいくつか紹介したいと思います。これからkintoneプラグインを作ってみたい人や現在頑張って作ろうとしている人向けの内容になります。

プラグイン開発方法自体はcybozu developer networkの[kintone プラグイン開発手順の記事](https://developer.cybozu.io/hc/ja/articles/203455680)を参考にしてください。

では、本内容に移ります。

#プラグインには識別子が存在する
kintone環境にインストールされたプラグインには全て『pluginId』という名の識別子が割り当てられています。
この識別子が一番確認しやすい方法は、プラグイン設定画面に遷移してURLを確認することです。
![pluginid.PNG](https://qiita-image-store.s3.amazonaws.com/0/100542/4c2df915-a07b-7b58-1bc0-80416d8afaf1.png)
kintoneはこの識別子を確認して個別のプラグインを判別するので、たとえ同じ名前で同じファイルが組み込まれているプラグインが同じkintone環境にインストールされたとしても、pluginId自体が違っていた場合、kintoneにはこれらのプラグインは別々のものだと認識されます。
![pluginids.png](https://qiita-image-store.s3.amazonaws.com/0/100542/f20841d3-7dd0-7ff1-300f-4946b32d8275.png)


もし、kintone環境にすでにインストールされているプラグインと同じpluginIdを持つプラグインを新しくインストールした場合、すでに入っているプラグインは新しいプラグインに上書きされます。この場合、上書きされる前のプラグインを使用していたアプリは新しいプラグインに紐づくことになります。なので、バージョンが上がったプラグインをkintone環境にあてる場合、上記の法則に従ってインストールすれば、うまくバージョンアップを適用することができます。


#キーファイル(.ppkファイル)はプラグインの識別子を維持するもの

cybozu developer networkの[plugin-packerの記事通り](https://developer.cybozu.io/hc/ja/articles/360000910783)にkintoneのプラグインファイル群をパッケージ化すると、『パッケージ化されたプラグイン』と『キーファイル』が生成されます。
この時、pluginIdもパッケージ化したプラグインに新しく付与されます。
もし『プラグインファイル群と一緒にキーファイルも一緒にパッケージ化』という手順をとると、新しいpluginIdは付与されません。以前パッケージ化したときに付与された同じpluginIdが引き続き付与されるようになります。

なので、以前開発したプラグインを改修してバージョンアップしたい場合は、同じキーファイルでパッケージ化をすれば、kintone環境にインストールした時に古いバージョンのプラグインがうまく上書きされるハズです。

#バージョン番号は整数のみしか受け付けない
という縛りがあったのですが、2021年7月からこの縛りはなくなりました。

プラグインにはバージョン番号が存在します。
このバージョン番号は、エンドユーザにとってはプラグイン設定画面の左側に表示されます。
<img width="666" alt="スクリーンショット 2018-12-03 午後9.54.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/100542/0d603b2c-67e1-8bcd-90a6-710ee3fe430f.png">
バージョン番号は勝手に変わることはありません。開発者がmanifestファイルの中で指定する必要があります。

~~ただ、このバージョン番号の使い勝手は少々悪く、『正の整数』しか指定できない、という縛りがあります。~~
~~つまり、細かい修正をしたいときに『3.2.8』などのバージョン番号を指定したいところですが、整数しか指定できないため『3』のままにするか、『4』に変更するか、決めなくてはいけません。~~

~~『細かいバージョン番号まで見せたいんじゃ！』とどうしても思う方は、設定画面のHTMLにバージョン番号を表示するための要素を作成し、そこにバージョン番号を挿入しても良いかもしれません。~~

**[2021年7月版のkintoneアップデート](https://kintone.cybozu.co.jp/update/main/2021-07.html)で、バージョン番号のマイナー指定が出来るようになりました。やったー٩( 'ω' )و**

#画像の扱いは弱い
プラグインの /img に配置する画像ファイルは基本的にアイコンにしか使えません。設定画面のHTML内に画像を使用したり、desktop/mobile 側のJavaScriptで呼び出せるわけではありません。
画像を使用したい場合は、外部のストレージ(dropbox等)を利用したり、Base64形式の画像を使用してください。

#設定画面作成はHTML+JavaScript+CSSの知識が必要
プラグイン開発時、一番時間を使ってしまいそうなところが設定画面の開発です。
設定画面は HTML, JavaScript, CSS に寄って出来上がります。

これから少し詳細に説明をしますが、下記のサンプルプラグインを参考にしながら読んで頂くと、少し理解がしやすいかと思います。
- [Date Input Button Plug-in](https://github.com/kintone-samples/SAMPLE-Date-input-button-Plug-in)
- [1 User Limit Plug-in](https://github.com/kintone-samples/SAMPLE-1-user-limit-plug-in)
- [Show DoW Plug-in](https://github.com/kintone-samples/SAMPLE-Show-DoW-plug-in)

##HTMLとCSSの役割
HTMLとCSSは、プラグイン設定画面の右側の部分を作り上げるために必要です。
何も無い状態だと、下記のように何も表示されません。
![noimage.PNG](https://qiita-image-store.s3.amazonaws.com/0/100542/2ae95ed9-69b0-311f-46df-a06c5654517c.png)
保存やキャンセルボタンも表示されません。
エンドユーザが触るパーツは全て、HTMLで作る必要があります。

シンプルなフォームパーツを設定画面に設定するとします：

```html
<div>
	<div>
		<span>Locale *</span>
		<div>Please select your locale</div>
		<select id="select_locale" name="select_locale">
			<option value="en">en</option>
			<option value="jp">jp</option>
		</select>
	</div>
	<div>
		<span>Message *</span>
		<div>Please select a message</div>
			<select id="select_message" name="select_message">
				<option value="greetings">Greetings</option>
				<option value="goodbye">Goodbye</option>
				<option value="goodnight">Good night</option>
			</select>
	</div>
	<div>
		<button type="button" id="check-plugin-cancel">　Cancel　</button>
		<button type="button" id="check-plugin-submit">　Save　</button>
	</div>
</div>
```


これで出来上がるのは下記の用な画面です。

![simpleparts.PNG](https://qiita-image-store.s3.amazonaws.com/0/100542/e59cea67-1b74-e0cd-775d-996ae8f8b37e.png)


フォームのパーツがくっついて見えるので、間隔の調整などはCSSで補うことができます。

サイボウズは [51-modern-default.css](https://github.com/kintone/plugin-examples/blob/master/stylesheet/51-modern-default.css) というCSSファイルを公開しているので、このCSSを読み込んだ上でcybozu developer network の[スタイルの説明の記事通り](https://developer.cybozu.io/hc/ja/articles/203302214)にHTMLに予めクラス指定などをすれば、kintoneのデザインに合わせたスタイルがあたります。
その場合HTMLはこのように変わります：


```html
<div>
	<div class="block">
		<label class="kintoneplugin-label">
			<span>Locale</span>
			<span class="kintoneplugin-require">*</span>
		</label>
		<div class="kintoneplugin-row">Please select your locale</div>
		<div class="kintoneplugin-select-outer">
			<div class="kintoneplugin-select">
				<select id="select_locale" name="select_locale">
					<option value="en">en</option>
					<option value="jp">jp</option>
				</select>
			</div>
		</div>
	</div>
	<div class="block">
		<label class="kintoneplugin-label">
			<span>Message</span>
			<span class="kintoneplugin-require">*</span>
		</label>
		<div class="kintoneplugin-row">Please select a message</div>
		<div class="kintoneplugin-select-outer">
			<div class="kintoneplugin-select">
				<select id="select_message" name="select_message">
					<option value="greetings">Greetings</option>
					<option value="goodbye">Goodbye</option>
					<option value="goodnight">Good night</option>
				</select>
			</div>
		</div>
	</div>
	<div class="block">
		<button type="button" id="check-plugin-cancel" class="kintoneplugin-button-dialog-cancel">　Cancel　</button>
		<button type="button" id="check-plugin-submit" class="kintoneplugin-button-dialog-ok">　Save　</button>
	</div>
</div>
```


![simplesettingswihtcss.PNG](https://qiita-image-store.s3.amazonaws.com/0/100542/f519e3bc-661f-cd18-6732-0e66d39ce1c7.png)


格好良くはなりましたが、HTMLを読み解くのが非常に辛く、ここで面倒くさくなって躓く開発者もいると思います。
そこまで時間をかけて読み解く必要性も無いと思うので、すでに存在するプラグインを参考にし、HTMLを作成するのが良いと思います。

例えば、[Date Input Button Plug-in](https://github.com/kintone/SAMPLE-Date-input-button-Plug-in)の[config.html](https://github.com/kintone/SAMPLE-Date-input-button-Plug-in/blob/master/src/html/config.html)と実際のアウトプットを見比べて、どのパーツがどのように生成されているのかを参考にすることができます。
![codes_and_output.png](https://qiita-image-store.s3.amazonaws.com/0/100542/82a33804-3388-d327-537d-8499ce0feceb.png)

必要な部分だけ、使いまわしちゃいましょう！


##JavaScriptの役割
JavaScriptはこの画面の開発には必須です。
いくつか用途があるのですが、リストしますと：
1. ダイナミックなドロップダウンの作成
2. 保存やキャンセルボタンを押した時の処理
3. ユーザが過去に設定した設定値を設定画面に再設定

といった役割を持ちます。もう少し詳しく見ていきましょう。

###1. ダイナミックなドロップダウンの作成
例えばドロップダウンの選択肢として『アプリのフォーム内にあるテキストフィールドの一覧』などを設定したい場合、JavaScriptで動的に作る必要があります。この場合HTMLでは初期値を『-----』と設定し、JavaScriptでkintoneのアプリ用のAPIを叩いて、情報を取得することができます。
- スペースフィールドの一覧を取得したい場合は、[/app/form/layout.json](https://developer.cybozu.io/hc/ja/articles/204783170#anchor_getform_layout) のkintone API を叩いて取得することができます。
- それ以外のフォームパーツを取得したい場合は、[/app/form/fields.json](https://developer.cybozu.io/hc/ja/articles/204783170) のkintone API を叩いて取得することができます。

いずれもAPIを叩いた後に、帰ってきたレスポンスをうまく処理して、必要な情報を抜きだし、その後JavaScriptで先程の「-----」が設定されていたドロップダウンに付与する必要があります。



#### スペースフィールドを取得する例
[Date Input Button Plug-inのconfig.js](https://github.com/kintone/SAMPLE-Date-input-button-Plug-in/blob/master/src/js/config.js)
処理が少し長いですが、getLayout関数で[/app/form/layout.json](https://developer.cybozu.io/hc/ja/articles/204783170#anchor_getform_layout)のAPIを叩き、各行の情報をまず切り出しています(行がGROUPの場合、さらにループで回して切り出す必要があります)。この処理が終わり次第、setDropDownForSpace関数でSPACERのプロパティを持つ情報だけ抜き出し、設定画面のドロップダウンの選択肢に足していってます。

#### それ以外のフォームパーツを取得する例
[1 User Limit Plug-inのconfig.js](https://github.com/kintone/SAMPLE-1-user-limit-plug-in/blob/master/src/js/config.js)
setDropDown関数で[/app/form/fields.json](https://developer.cybozu.io/hc/ja/articles/204783170)のAPIを叩き、USER_SELECT(ユーザ選択フィールド)のプロパティを持つ情報だけを抜き出し、設定画面のドロップダウンの選択肢に足していってます。

いずれも「preview」が入っているAPIを叩くようにしています。これは、エンドユーザがフォームの変更を行う際に、アプリを更新する前に(本番環境に適用する前に)プラグインの設定をいじるケースが多々あるため、必要としています。


ちなみにですが、/form.json というkintoneの設計情報を取得するAPIも存在するのですが、こちらは脚力使用しない方が良いです。/form.jsonで取得出来る情報が中途半端であり：
- グループフィールド内のレコード番号、作成者、作成日時、更新者、更新日時、スペースの情報が取得出来ない
- ユーザ/グループ/組織選択の初期値が取得出来ない
- カテゴリー、作業者、ステータスの取得が出来ない
という弱点があります。

出来る限り、[/app/form/layout.json](https://developer.cybozu.io/hc/ja/articles/204783170#anchor_getform_layout)と[/app/form/fields.json](https://developer.cybozu.io/hc/ja/articles/204783170)のAPIを活用して情報を取得してください。

###2. 保存やキャンセルボタンを押した時の処理
保存ボタンをクリックしたら、設定画面に入力した情報をプラグインのストレージに保存する必要があります。
これはkintoneのAPIでメソッドが用意されており、[kintone.plugin.app.setConfig](https://developer.cybozu.io/hc/ja/articles/203661160#step2) というメソッドを使います。

```JavaScript
config.date = date; //1個目の設定に入力された値
config.space = space; //2個目の設定に入力された値
kintone.plugin.app.setConfig(config);
```

###3. ユーザが過去に設定した設定値を設定画面に再設定
上記で設定した内容は、再度ユーザがプラグイン設定画面に遷移した場合に、初期値として設定する必要があります。
これはkintoneの[kintone.plugin.app.getConfig](https://developer.cybozu.io/hc/ja/articles/203661160#step1)というメソッドを使います

```JavaScript
var CONFIG = kintone.plugin.app.getConfig(PLUGIN_ID);
//CONFIG.date は dateの情報を含む
//CONFIG.space は spaceの情報を含む

// デフォルト値を設定項目に反映する
$('#date_setting_field').val(CONF.date); //特定のidを持つ項目に値を付与する
$('#space_setting_field').val(CONF.space); //特定のidを持つ項目に値を付与する
```

#モバイル対応は考慮しないといけない
desktop.js に記載したJavaScriptはデスクトップ上のkintoneでは動きますが、モバイルの画面(ストアに公開されてるモバイルアプリ及びブラウザからアクセスしたkintone)ではdesktop.jsは作動しません。モバイルでプラグインを動かすにはモバイル用のJavaScriptも設定する必要があります。これはデスクトップとは別のイベントやメソッドを使用しているためです。
![desktopvsmobile.png](https://qiita-image-store.s3.amazonaws.com/0/100542/5e0617ba-eea6-5862-e36e-3383f9626876.png)

実際にモバイルでカスタマイズが動かない場合、問題があるかどうかの検証はしておきましょう。


#manifest.jsonのrequired_paramsの役割

manifest.json の内容はcybozu developer networkの[kintone プラグイン開発手順の記事を参考](https://developer.cybozu.io/hc/ja/articles/203455680#step2)に設定をします。
required_paramsの役割だけ説明が足りないので、補足させていただきます。
required_paramsには、プラグインの設定画面で設定値の入力が必須な項目を指定します(項目というより、その項目の値を格納する変数名ですね)。

たとえば

```json
    "required_params": [
      "option1",
      "option2"
    ]
```

と設定した場合、エンドユーザは設定画面内の『option1』と『option2』の設定を入力して保存する必要があります。

ただ、required_paramsを設定したからって、設定画面内でバリデーションを行ってくれるわけではありません。値が入っているか入っていないかのチェックは、設定画面で使用してるJavaScriptファイルで行う必要があります。
required_paramsの役割は、保存した設定値が入っているオブジェクトの中身を確認し、required_paramsで指定された値がオブジェクトのキーとして存在しない場合、特定の画面でエラーを表示させることです。

具体的には：
・アプリのプラグイン一覧画面
![error1.PNG](https://qiita-image-store.s3.amazonaws.com/0/100542/010b6614-a906-afa5-e0fe-212d3f0d8145.png)
・アプリのレコード一覧画面
![error2.PNG](https://qiita-image-store.s3.amazonaws.com/0/100542/0d89534d-ae72-d24f-b831-e6604546650b.png)

この2つの画面でエラー文言が出るようになります。



#終わりに
思いつくまま、バーーーっとプラグイン関連の情報を書かせて頂きました。
解釈が間違っている項目があったりしたらすみません。
皆様のkintoneプラグイン開発に役立てられると嬉しいですm(_ _)m