【kintone】kintone上で座席表を作る

kintoneの上で画像をドラッグで動かしたい～という願望があって、
↓のjCanvasというライブラリで実現できそうだったので試してみました。

https://projects.calebevans.me/jcanvas/

試しに座席表でも作ってみようかな。
というわけで、ちょっと試すつもりだったのですが
うっかり、ガッツリ作ってしまったので今回は紹介＆作り方、次回（余裕があれば）は説明・・・ということで、
前後編に分けて書いていこうと思います。

# 背景画像を準備する

## 背景画像用アプリを作る
（１）フィールドが「添付ファイル」だけのアプリを作成し、背景画像をアップロードします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/568e676b-bfe6-db36-27f3-0a2dbe9fdc6c.png" width=400px>

※背景画像が欲しいよ～という方いたら↓をどうぞ
![zaseki.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/12096be5-8fd6-bb09-574f-d48e76218e9e.png)

（２）画像のアドレスをコピーする
①添付ファイル画像をクリック
②大きい画像を右クリック
③画像アドレスをコピー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/fd774fec-4a03-be75-7257-c4eeb57903ce.png)

ここでコピーした画像アドレスを控えておきましょう。

# アプリをつくる
やっと今からアプリを作り始めます。

## 完成予想図　
こんな感じ。座席表のテンプレみたいのを準備して、その上に名前入りのプレートを置きたい感じ。
とりあえず今回は、「今日の俺の席はここだ！用座席アプリ」を想定。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/8617ca49-988f-a637-3c5d-350b093013c2.png" width=300px>

## フォームをつくる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/99014dd4-ab5a-0f64-693f-6b8c34fd30a8.png" width=600px>

フィールドはこんなかんじ

| フィールド種類 | フィールドコード・フィールド名 |備考 |
|:-:|:-:|:-:|
|  数値 |  x |   |   
|  数値 |  y |   |   
|  文字列(1行) | 作成者名  |   |   
|  文字列(1行) | 作成者ID  | 重複禁止  |   

## 一覧を作る

カスタマイズビューにしてhtmlを書きます。

一覧IDを控えておきましょう。

```html
<div>
    <button id="btnJibun" > 自分の名前がないときクリック</button>
    <button id="btnSrv" > 保存</button>
</div>

<div>
    <canvas width="699" height="850"></canvas>
</div>
```


## JavaScript
アップロードの仕方などはヘルプを見てね♡
[kintoneヘルプ](https://jp.cybozu.help/k/ja/admin/system_customization/javascript_fullcustomize.html)

### jQuery（CDN）
2020/11/06現在では↓が最新です
https://js.cybozu.com/jquery/3.5.1/jquery.min.js

### jCanvas
こちらからjCanvas.jsをダウンロードして、kintoneにアップロード
https://projects.calebevans.me/jcanvas/

### JavaScriptを書いてアップロードする

・控えておいた画像アドレス
・控えておいた一覧ID

を使いますので、ソースの中から探して入れ替えといてください。

また、コードに見にくいところとかリファクタリングできるところむっちゃあるかもしれませんが、
大目に見てください（ぴえん）

説明などは次回にしようとおもいます！

```js
(($)=>{
    const onDoubleClick = ()=>{
        $('canvas').removeLayerGroup(kintone.getLoginUser().id);
    }

    const loadPics = async ()=>{
        const getMemberParam = {
            app: kintone.app.getId()
        };
        let memberRecords = await kintone.api('/k/v1/records', 'GET', getMemberParam);
        
        memberRecords.records.forEach(r=>{
             let drawR ={
                layer: true,
                groups: [ r.作成者ID.value],
                id: r.作成者ID.value,
                fillStyle: '#eee' ,
                strokeStyle: '#000',
                strokeWidth: 3,
                x: r.x.value,
                y: r.y.value,
                width: 100,
                height: 30,
                cornerRadius: 5,

                draggable:  Number(r.作成者ID.value) ===Number(kintone.getLoginUser().id),
                dblclick: onDoubleClick
            };
            let drawT ={
                layer: true,
                groups: [ r.作成者ID.value],
                id: r.作成者ID.value,
                text: r.作成者名.value,
                fillStyle: '#191970',
                fontSize: '10pt',
                fontFamily: 'Verdana, sans-serif',
                fontStyle: 'bold',
                strokeWidth: 2,
                x: r.x.value,
                y: r.y.value,
                draggable: false,
                dblclick: onDoubleClick 
            };
            if(Number(r.作成者ID.value) ===Number(kintone.getLoginUser().id)){
                drawR['dragGroups'] =[r.作成者ID.value]
                drawT['dragGroups'] =[r.作成者ID.value]
            }
            $('canvas').drawRect(drawR).drawText(drawT);
        });
    }
 
    //一覧表示
    kintone.events.on([
        'app.record.index.show'        
    ], async event => {
        if(event.viewId != 【控えておいた一覧ID】){return event;}
        //背景設定
        $('canvas').drawImage({
            source: '【控えておいた画像アドレス】',
            x: 349, y: 250,
            layer: true,
            draggable: false,
            name:"zaseki",
        });

        //座席表示
        const findTargetElement = ()=> {
            // 要素を見つける処理
            let c = $("canvas").getLayers().filter(v=>{return v.name==="zaseki";});
            if(c) {
                loadPics();
                clearInterval(set_interval_id);
            }
        }
        const set_interval_id = setInterval(findTargetElement, 100);
        
        //ボタン効果
        $('#btnJibun').on('click', onClickBtnJibun);
        $('#btnSrv').on('click', saveCanvas);
  
        return event;
    });

   let onClickBtnJibun =()=>{
        let userName = kintone.getLoginUser().name;
        let userId = kintone.getLoginUser().id
        let c = $("canvas").getLayers().filter(v=>{return Number(v.id)===Number(userId);});
        if (c.length === 0 ){
                $('canvas').drawRect({
                layer: true,
                groups: [ userId],
                dragGroups: [userId],
                id:userId,
                fillStyle: '#fff' ,
                strokeStyle: '#000',
                strokeWidth: 3,
                x: 150,
                y: 150,
                width: 100,
                height: 30,
                cornerRadius: 5,
                draggable: true,
                dblclick: onDoubleClick
            })
            .drawText({
                layer: true,
                groups: [ userId],
                dragGroups: [userId],
                id: userId,
                text: userName,
                fillStyle: '#000',
                fontSize: '10pt',
                fontFamily: 'Verdana, sans-serif',
                fontStyle: 'bold',
                strokeWidth: 2,
                x: 150,
                y: 150,
                draggable: false,
                dblclick: onDoubleClick 
            });
        }
   }
   
    //座標を保存
    let saveCanvas =async ()=>{
        let c = $("canvas").getLayers().filter(v=>{return Number(v.id)===Number(kintone.getLoginUser().id);});
        const getUidParam = {
            app: kintone.app.getId(),
            query:'作成者ID = "'+kintone.getLoginUser().id+'"'
        };
        const getResp = await kintone.api('/k/v1/records', 'GET', getUidParam);
        if(getResp.records.length === 0){
            const body={
                app:kintone.app.getId(),
                record:{
                    x:{value:c[0].x},
                    y:{value:c[0].y},
                    "作成者ID":{value:kintone.getLoginUser().id},
                    "作成者名":{value:kintone.getLoginUser().name}
                }
            }
            kintone.api("/k/v1/record","POST",body).then(function(resp){
                console.log(resp);
            },(err)=>{
                console.log(err);
                alert(err);
            });
        }else{                                              
            const body={
                app:kintone.app.getId(),
                "updateKey": {
                    "field": "作成者ID",
                    "value": kintone.getLoginUser().id
                },
                record:{
                    x:{value:c[0].x},
                    y:{value:c[0].y},
                }
            }
            kintone.api("/k/v1/record","PUT",body).then(function(resp){
                console.log(resp);
            },(err)=>{
                console.log(err);
                alert(err);
            });
        }
    }
})(jQuery.noConflict(true));

```

# 使い方

自分の名前がないときクリックボタンをクリックすると、自分の名前のプレートが現れます。
ドラッグできます。
保存ボタンをクリックするとその位置に保存されます。
ダブルクリックで自分のプレートを削除できます。

・・・という感じです。

自分の座席だけいじれます。（地味に困る）
誰か一人が座席表作りたいときは権限周りを工夫してください～。

動きはこんな感じ↓
![zaswki.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/dc11f6c5-f502-b7a2-4690-566b3b43cc64.gif)

# まとめ

座席表みたいなものも工夫次第でできます！！！
余裕があれば説明記事もupしようとおもいます～。