”ダウンロード” ボタンをダッシュボードに追加する

Node-REDダッシュボードにダウンロードボタンを作ります。
これは、先行するフローの処理で生成・加工した任意のデータをダウンロードできるボタンです。

ダッシュボードに表示中のデータや、データストアから取得した何らかのデータを、ブラウザで気軽にダウンロードしたい場面で使えます。

_完成図_

![sample-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303867/568b11d0-0b46-ed9b-ce39-94a264118f2f.png)

![sample-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303867/e0e545db-7d61-bc1a-1425-0cb7437da17c.png)

また、このフローを[enebular-editor](https://docs.enebular.com/ja/EnebularEditor/)でも実行して、データをダウンロードすることができます。便利です。

![sample-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303867/d8c48370-a6f7-3697-653f-4ff6e4a48ab1.png)

# 用意するもの

- enebular
    - プロジェクトが作成済みであること
    - [node-red-dashboard](https://flows.nodered.org/node/node-red-dashboard)のインストール
    - enebularからHerokuデプロイした状態のアプリまたはブラウザでフローを実行できる環境


# 手順

## enebular

[各ノードの実装](#各ノードの実装)どおりに実装します。

一番の要点は、ダウンロードしたいデータを`msg.payload`に渡すことです。

フローを作った後、ダッシュボードのページを開きます。

”ダウンロード”ボタンをクリックすると、JSONファイルをブラウザからダウンロードすることができました :tada:

![sample-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303867/20dec27e-cdb0-f55c-7577-5bd5eabaee29.png)


### フロー全体の実装

下記にフロー全体の実装を記載します。

```
[
    {
        "id": "e428e286.d7fe1",
        "type": "tab",
        "label": "Flow 1",
        "disabled": false,
        "info": ""
    },
    {
        "id": "2f780a0.3fc0af6",
        "type": "http in",
        "z": "e428e286.d7fe1",
        "name": "",
        "url": "/download",
        "method": "get",
        "upload": false,
        "swaggerDoc": "",
        "x": 120,
        "y": 80,
        "wires": [
            [
                "7613dde2.fd29f4"
            ]
        ]
    },
    {
        "id": "cbcb3d32.634f2",
        "type": "ui_template",
        "z": "e428e286.d7fe1",
        "group": "36d8cbaa.9ec0e4",
        "name": "ダウンロードボタン",
        "order": 0,
        "width": 0,
        "height": 0,
        "format": "<div ng-bind-html=\"msg.payload\"></div>\n<form method=\"get\" action=\"/download\">\n    <button type=\"submit\">ダウンロード</button>\n</form>",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "x": 120,
        "y": 260,
        "wires": [
            []
        ]
    },
    {
        "id": "7613dde2.fd29f4",
        "type": "function",
        "z": "e428e286.d7fe1",
        "name": "JSONをpayloadにセット",
        "func": "msg.payload = {\n    hoge: 1,\n    foo: 2\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 290,
        "y": 140,
        "wires": [
            [
                "67714159.c3c2"
            ]
        ]
    },
    {
        "id": "67714159.c3c2",
        "type": "file",
        "z": "e428e286.d7fe1",
        "name": "/tmpディレクトリ以下に書き出し",
        "filename": "/tmp/tmp.json",
        "appendNewline": false,
        "createDir": true,
        "overwriteFile": "false",
        "encoding": "none",
        "x": 500,
        "y": 200,
        "wires": [
            [
                "743f75d0.a98dbc"
            ]
        ]
    },
    {
        "id": "743f75d0.a98dbc",
        "type": "http response",
        "z": "e428e286.d7fe1",
        "name": "レスポンスヘッダーをセット",
        "statusCode": "",
        "headers": {
            "content-type": "application/json",
            "Content-Disposition": "attachment"
        },
        "x": 620,
        "y": 260,
        "wires": []
    },
    {
        "id": "36d8cbaa.9ec0e4",
        "type": "ui_group",
        "name": "Group 1",
        "tab": "f436e0bd.16842",
        "order": 1,
        "disp": true,
        "width": 6
    },
    {
        "id": "f436e0bd.16842",
        "type": "ui_tab",
        "name": "Tab 1",
        "icon": "dashboard",
        "order": 1
    }
]
```


### 各ノードの実装

下記に各ノードの実装を記載します。

#### ダウンロードボタン

`node-red-dashboard `の`template`ノードを使います。

```
<div ng-bind-html="msg.payload"></div>
<form method="get" action="/download">
    <button type="submit">ダウンロード</button>
</form>
```

#### `http in`ノード

![http-in.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303867/0b9ae445-21da-c672-e1ab-07c1d7d0388b.png)


#### ダミーのJSONをpayloadにセット

```
// functionノード

msg.payload = {
    hoge: 1,
    foo: 2
}

return msg;
```

#### `file`ノード

![file.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303867/63eb7c07-d98a-ddf1-4ed4-899deffc3e49.png)

#### `http response`ノード

- `Content-Type: application/json`

- `Content-Disposition: attachment`

![http-response.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303867/b8216fae-f7a0-1c89-e7da-4c418c9f3c64.png)