0.はじめに
cybozu.com に登録されているユーザー情報の一覧を、kintone アプリで、簡単に取得したかったので、やってみました。
1. kintone アプリに JavaScript ライブラリ (reloadCybozuUsers.js) を追加する。
-
まずは、kintone アプリの「アプリの設定」を開きます。
-
「設定」タブを選択し、「カスタマイズ/サービス連携」→「JavaScript / CSSでカスタマイズ」を開きます。
-
以下の JavaScript ライブラリを追加します。
reloadCybozuUsers.js/* cybozu.com ユーザー一覧更新処理 */ // kintone API – cybozu developer network //https://developer.cybozu.io/hc/ja/articles/360028177472 // PromiseがわからないのでAsync/Awaitを使う - Qiita // https://qiita.com/_muraham/items/697e1d53a09ff40530e5 // プログレスバーを簡単に実装できるprogressbar.js - bagelee(ベーグリー) // https://bagelee.com/design/javascript/create_progress_bars_with_progressbarjs/ // https://rawgit.com/kimmobrunfeldt/progressbar.js/master/dist/progressbar.js // https://rawgit.com/kimmobrunfeldt/progressbar.js/master/dist/progressbar.min.js (function() { "use strict"; kintone.events.on('app.record.index.show', function(event) { var myProgressDiv = document.createElement('div'); myProgressDiv.id = "my_progress_container"; //myProgressDiv.style.backgroundColor = 'red'; myProgressDiv.style.width = '600px'; myProgressDiv.style.height = '8px'; if (document.getElementById('my_index_button') !== null) { return; } var myIndexButton = document.createElement('button'); myIndexButton.id = 'my_index_button'; myIndexButton.innerText = ' 更 新 '; myIndexButton.onclick = async function() { var bar = new ProgressBar.Line(my_progress_container, { strokeWidth: 4, easing: 'easeInOut', duration: 100, color: '#FFEA82', trailColor: '#eee', trailWidth: 1, svgStyle: {width: '100%', height: '100%'}, text: { style: { color: '#999', position: 'relative', left: '560px', top: '-70px', padding: 0, margin: 0, transform: null }, autoStyleContainer: false }, from: {color: '#FFEA82'}, to: {color: '#ED6A5A'}, step: (state, bar) => { bar.path.setAttribute('stroke', state.color); bar.setText(Math.round(bar.value() * 100) + ' %'); } }); //console.log(event.records); var respUsers = await kintone.api(kintone.api.url('/v1/users', true), 'GET', {}); //console.log(respUsers); var respRecords = await kintone.api(kintone.api.url('/k/v1/records', true), 'GET', { 'app': kintone.app.getId() }); //console.log(respRecords); var recordIDs = {}; var postRecords = []; var putRecords = []; for(let i = 0; i < respRecords.records.length; i++) { recordIDs[respRecords.records[i]['$id']['value']] = { 'userid': respRecords.records[i]['id']['value'], 'idx': i } } //console.log(recordIDs); for(let i = 0; i < respUsers.users.length; i++) { bar.animate(i/respUsers.users.length); var respUserOrgs = await kintone.api(kintone.api.url('/v1/user/organizations', true), 'GET', { 'code': respUsers.users[i]['code'] }); //console.log(respUserOrgs); var organizations = [] for(let ii = 0; ii < respUserOrgs['organizationTitles'].length; ii++) { organizations.push({ 'code': respUserOrgs['organizationTitles'][ii]['organization']['code'], 'name': respUserOrgs['organizationTitles'][ii]['organization']['name'] }); } let record = {}; record['id'] = {'value': respUsers.users[i]['id']} record['name'] = {'value': respUsers.users[i]['name']} record['surName'] = {'value': respUsers.users[i]['surName']} record['givenName'] = {'value': respUsers.users[i]['givenName']} record['surNameReading'] = {'value': respUsers.users[i]['surNameReading']} record['givenNameReading'] = {'value': respUsers.users[i]['givenNameReading']} record['code'] = {'value': respUsers.users[i]['code']} record['email'] = {'value': respUsers.users[i]['email']} if (respUsers.users[i]['valid']) { record['valid'] = {'value': ['使用中']} } else { record['valid'] = {'value': []} } record['organizations'] = {'value': organizations} record['primaryOrganization'] = {'value': respUsers.users[i]['primaryOrganization']} record['phone'] = {'value': respUsers.users[i]['phone']} record['url'] = {'value': respUsers.users[i]['url']} // record['callto'] = {'value': respUsers.users[i]['callto']} record['mobilePhone'] = {'value': respUsers.users[i]['mobilePhone']} record['locale'] = {'value': respUsers.users[i]['locale']} record['timezone'] = {'value': respUsers.users[i]['timezone']} record['localNameLocale'] = {'value': respUsers.users[i]['localNameLocale']} record['localName'] = {'value': respUsers.users[i]['localName']} // record['employeeNumber'] = {'value': respUsers.users[i]['employeeNumber']} record['joinDate'] = {'value': respUsers.users[i]['joinDate']} record['birthDate'] = {'value': respUsers.users[i]['birthDate']} record['sortOrder'] = {'value': respUsers.users[i]['sortOrder']} record['description'] = {'value': respUsers.users[i]['description']} // record['customItemValues'] = {'value': respUsers.users[i]['customItemValues']} record['extensionNumber'] = {'value': respUsers.users[i]['extensionNumber']} // record['ctime'] = {'value': respUsers.users[i]['ctime']} record['mtime'] = {'value': respUsers.users[i]['mtime']} //console.log(record); var matchRecordIDs = [] Object.keys(recordIDs).forEach(function(key) { if (this[key]['userid'] == respUsers.users[i]['id']) { matchRecordIDs.push({ 'key': key, 'idx': this[key]['idx'] }); } }, recordIDs); //console.log(matchRecordIDs); if (matchRecordIDs.length > 0) { //console.log(respRecords.records[matchRecordIDs[0]['idx']]); if (record['id']['value'] != respRecords.records[matchRecordIDs[0]['idx']]['id']['value'] || record['name']['value'] != respRecords.records[matchRecordIDs[0]['idx']]['name']['value'] || record['surName']['value'] != respRecords.records[matchRecordIDs[0]['idx']]['surName']['value'] || record['givenName']['value'] != respRecords.records[matchRecordIDs[0]['idx']]['givenName']['value'] || record['surNameReading']['value'] != respRecords.records[matchRecordIDs[0]['idx']]['surNameReading']['value'] || record['givenNameReading']['value'] != respRecords.records[matchRecordIDs[0]['idx']]['givenNameReading']['value'] || record['valid']['value'] != respRecords.records[matchRecordIDs[0]['idx']]['valid']['value'] || record['code']['value'] != respRecords.records[matchRecordIDs[0]['idx']]['id']['code'] || record['email']['value'] != respRecords.records[matchRecordIDs[0]['idx']]['id']['email'] ) { putRecords.push({'id': matchRecordIDs[0]['key'], 'record': record}); } delete recordIDs[matchRecordIDs[0]['key']]; } else { postRecords.push(record); } } console.log("recordIDs :"); //console.log(recordIDs); console.log(Object.keys(recordIDs)); console.log("putRecords :"); console.log(putRecords); console.log("postRecords :"); console.log(postRecords); if (Object.keys(recordIDs).length > 0) { var resp = await kintone.api(kintone.api.url('/k/v1/records', true), 'DELETE', { 'app': kintone.app.getId(), 'ids': Object.keys(recordIDs) }); } if (putRecords.length > 0) { var resp = await kintone.api(kintone.api.url('/k/v1/records', true), 'PUT', { 'app': kintone.app.getId(), 'records': putRecords }); } if (postRecords.length > 0) { var resp = await kintone.api(kintone.api.url('/k/v1/records', true), 'POST', { 'app': kintone.app.getId(), 'records': postRecords }); } bar.animate(1.0); location.reload(); return event; }; kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton); kintone.app.getHeaderMenuSpaceElement().appendChild(myProgressDiv); //kintone.app.getHeaderSpaceElement().appendChild(myProgressDiv); }); })();
<br>
* ※ 以降は、コードの簡単な説明。
<br><br>
* ユーザー情報の取得
* [ユーザーエクスポートAPI – cybozu developer network](https://developer.cybozu.io/hc/ja/articles/202363040-%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88API#step2)
```javascript
var respUsers = await kintone.api(kintone.api.url('/v1/users', true), 'GET', {});
* アプリのレコード情報の取得
* [レコードの取得(GET) – cybozu developer network](https://developer.cybozu.io/hc/ja/articles/202331474-%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E5%8F%96%E5%BE%97-GET-#step2)
```javascript
var respRecords = await kintone.api(kintone.api.url('/k/v1/records', true), 'GET', {
'app': kintone.app.getId()
});
* ユーザーの所属する組織情報の取得
* [ユーザーの所属組織エクスポートAPI – cybozu developer network](https://developer.cybozu.io/hc/ja/articles/202124774#step2)
```javascript
var respUserOrgs = await kintone.api(kintone.api.url('/v1/user/organizations', true), 'GET', {
'code': respUsers.users[i]['code']
});
* アプリのレコード情報の削除
* [レコード削除(DELETE) – cybozu developer network](https://developer.cybozu.io/hc/ja/articles/201941794)
```javascript
var resp = await kintone.api(kintone.api.url('/k/v1/records', true), 'DELETE', {
'app': kintone.app.getId(),
'ids': Object.keys(recordIDs)
});
* アプリのレコード情報の更新
* [レコードの更新(PUT) – cybozu developer network](https://developer.cybozu.io/hc/ja/articles/201941784)
```javascript
var resp = await kintone.api(kintone.api.url('/k/v1/records', true), 'PUT', {
'app': kintone.app.getId(),
'records': putRecords
});
* アプリのレコード情報の登録
* [レコードの登録(POST) – cybozu developer network](https://developer.cybozu.io/hc/ja/articles/202166160)
```javascript
var resp = await kintone.api(kintone.api.url('/k/v1/records', true), 'POST', {
'app': kintone.app.getId(),
'records': postRecords
});
# 2. [kintone](https://kintone.cybozu.co.jp/) アプリに JavaScript ライブラリ ([ProgressBar.js](https://kimmobrunfeldt.github.io/progressbar.js/#intro)) を追加する。
1. こちらの手順に従って、追加します。
* [Kintone アプリにプログレスバーを表示してみる。 \- Qiita](https://qiita.com/kusokamayarou/items/70acde31d3fd4e790478#%EF%BC%91-kintone-%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AB-javascript-%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA-progressbarjs-%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B)
# 3. [kintone](https://kintone.cybozu.co.jp/) アプリにフォームを設定する。
1. 以下のデータ構造に合わせて、項目を追加します。
* [User APIで使用するデータの構造 – cybozu developer network](https://developer.cybozu.io/hc/ja/articles/205309740)
* ※ フィールドコードには、上記のデータ構造のキーを設定します。
* ※ 上記のデータ構造の項目を全て追加しなくても、大丈夫です。
* ![FireShot Capture 383 - アプリの設定 - genbasupport.cybozu.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161939/265f21c9-6cbf-9c10-8b82-8808cc91f697.png)
# 99.ハマりポイント
* ハマりポイントというか、そもそも [kintone](https://kintone.cybozu.co.jp/) アプリの JavaScript カスタマイズとか、HTML とか、JavaScript とかを普段あまりいじっておらず…、慣れてないので時間掛かっちゃいました…。
<br><br>
* Async/Await の使い方もよく知らなかったので、こちらの記事を参考にさせて頂きました。クロージャ使わないと、コードが綺麗になって見易くて Good !!!
* [PromiseがわからないのでAsync/Awaitを使う \- Qiita](https://qiita.com/_muraham/items/697e1d53a09ff40530e5)
<br><br>
* あと、これは [kintone](https://kintone.cybozu.co.jp/) アプリの JavaScript カスタマイズでいつも困るんですが、POST や PUT の際の JSON フォーマットの形式ですね。いつもどの形式で登録するのかわからなくて、今回も結構ハマりました…。
# XX.まとめ
[cybozu\.com](https://www.cybozu.com/jp/) に登録されているユーザー情報について、組織によっては、全てのユーザー情報は見せられない、といった場合もあるかと思いますので、今回の Tips がそのまま使えるか難しい面もあるかと思いますが…。
参考になれば♪
👋👋👋