実は誰でも簡単にNotion のウィジェットを作れちゃう（勤怠管理ウィジェット in Notion）

# 初めに
タイトルの通りNotionのウイジェットって誰でも作れるんです！作ってみたら意外とウケが良かった！でも作り方知られてないみたいだし、ネットにも転がってなかったので記事書く！

### 背景
以前AWSの勉強も兼ねて、チームの勤怠管理を作った（[その１](https://qiita.com/waiiioss/items/6c2ca747a55d3dca9224)、[その２](https://qiita.com/waiiioss/items/f35c1729bb3d17cfbc9e)、[その３](https://qiita.com/waiiioss/items/29a51fb8b8d63bd173c3)の三段に分けて記事にしたので良かったらみてください！）

### 問題点
必要システムとして作ったけど、実際に使うようになって感じた問題点を列挙すると
1. 勤怠を登録するために勤怠管理ページを開くのがめんどくさい
1. めんどくさいが故に忘れがち
2. 可視化意外と誰もみてない

機能だけしっかり作っても**体験してほしいUX**を考えられていないとこうゆう問題点が出てきがちですよね！

### 解決案
我々のチームはNotionを多様に使っていることもあり、Notion上で勤怠管理の可視化機能を使うことができれば「勤怠をつける」のも「確認する」のもうまくいきそうだなと思ってしまった。
**そうだNotionのウィジェットを作ろう!**

### 実際に活用すると
使い勝手が格段に向上してウケも良かった！タスクを始める前に必ずと言っていいほど全員がNotionを開く。Notionのトップページにあることで勤怠つけるのを忘れないはず！
（なんか見覚えがある人もいそうですが、デザインの参考にしたのはGithubのコントリブーションヒートマップです！）

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788759/e87929de-03f3-0da1-a76c-4c608f8e7619.png">
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788759/5ef49ce8-cbc1-a16e-7409-3870321a0dd8.png">

てことで本記事を参考にして、気軽にNotionのウィジェット作ってみてはいかがでしょうか！！

# 記事の内容
本記事は以下の順番で説明していく！（[以前書いた勤怠管理の記事](https://qiita.com/waiiioss/items/f35c1729bb3d17cfbc9e)の続きとして書く！）

:::note info
**ウィジェットのことだけ知りたい人は3に飛んでください**
:::

ちょっと手順長いけど本当に簡単だから！
1. DynamoDBのデータのデータを取得するLambdaを書き、API化する
1. JSからAPIを呼び出せるようにする
1. ChatGPTにWebを作ってもらう
1. HTML, CSS, JSをGithubにあげて、Amplifyでデプロイする
1. Notionに埋め込む
1. Chat GPTに感謝する

**使ったツール**
AWS (API Gateway, Lambda, Amplify), Github, ChatGPT
どれも簡単なのでここで諦めるとかはしないでほしい！Chat GPTに頼めば基本何とかなる！

# 1. DynamoDBのデータを取得するLambdaを書き、API化する
[以前書いた記事](https://qiita.com/waiiioss/items/f35c1729bb3d17cfbc9e)の続きからする。（この記事にもある程度似たようなことは書いてる）状況としてはDynamoDBに [Name (文字列), Timestamp (文字列), EndTime, WorkHours] がカラムとして存在することが前提である。これらのデータにアクセスしてデータをとるLambdaをまず書こう！
TimestampとEndTimeはTime Stampの文字列形で記録されているからそこだけ気をつけて！

もう一つ気をつけないといけないところは、ロールの付与！LambdaにDynamoDBのロールを付与しよう今回はRead Accessだけでいい！

**Lambda関数**

``` python
import json
import boto3
import json
from decimal import Decimal

def decimal_default(obj):
    if isinstance(obj, Decimal):
        return str(obj)
    raise TypeError

# Lambdaハンドラ内のコード
def lambda_handler(event, context):
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table('TableName')  # DynamoDBのテーブル名を設定

    try:
        response = table.scan()  # テーブルの全データをスキャン
        items = response['Items']
        
        # Decimalオブジェクトを文字列に変換してからJSONにシリアライズ
        serialized_items = json.dumps(items, default=decimal_default)
        
        return {
            'statusCode': 200,
            'body': serialized_items
        }
    except Exception as e:
        return {
            'statusCode': 500,
            'body': json.dumps(str(e))
        }
```

### API化
API Gatewayを使って、さっき作ったLambdaをアタッチする。リソースを作った後に、メソッドを作成する。メソッドはGET！ステージを選択して右上チョイ下に出てくる「CORSを有効」でGETを選択して有効にする。
その後、デプロイボタンを押して、新しいステージを作成を押す。適当にステージ名を決めてデプロイ！
これでオッケーーー！
Lambda関数に戻って、設定->トリガーからエンドポイントをコピーする！
[Postman](https://www.postman.com/)とかで確認できれば確実！

# 2. JSからAPIを呼び出せるようにする
ここからはChat GPT君を召喚しよう！↓みたいなプロンプトを伝えることでしっかり作ってもらえると思う。
``` text
お願いがある。
APIを呼び出すJSを作ってほしい。
ウェブがロードされたタイミングでfetchしてデータをrawdataという名前も変数に保持することができるようにしてほしい。
APIのメソッドはGETですぞ
エンドポイントはhttps://endpoint.desu
後でhtml, cssと繋げるからその辺も留意して！
<script>ここにコード</script>みたいな感じで出力してもらえればいいかな
てな感じで頼んだ！
```
これを使うと↓みたいな出力が出るはず、ひとまずこれでオッケーあってるかわわからないけど確かめる必要もまだない

``` HTML
<script>
        document.addEventListener('DOMContentLoaded', (event) => {
            fetch('https://endpoint.desu', {
                method: 'GET'
            })
            .then(response => {
                if (!response.ok) {
                    throw new Error('Network response was not ok ' + response.statusText);
                }
                return response.json();
            })
            .then(data => {
                window.rawdata = data;
                console.log('Fetched data:', rawdata);
            })
            .catch(error => {
                console.error('There has been a problem with your fetch operation:', error);
            });
        });
</script>
```


# 3. ChatGPTにWebを作ってもらう
次に、CHat GPTにウィジェットのサイズに合ったwebを作ってもらおう！
プロンプトはこんな感じ
下の画像を添付しつつプロンプトを打ち込む

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788759/cf814f80-7468-ab8c-d4fb-00afaf4f95cc.png">

```text
HTML. CSS, JSを書いてWebを作ってください。

rawdata = {
    "statusCode": 200,
    "body": "[{\"Name\": \"Namae\", \"Timestamp\": \"タイムスタンプで発行された日時\", \"EndTime\": \"タイムスタンプで発行された日時\", \"WorkHours\": \"1.53\"}]"
}
の形のrawdataという変数があります。

"先ほど出てきたAPIを呼び出すJSを貼り付ける" ##ここだけかえる
このscriptによってデータが得られます

添付してある写真みたいにデータを表示したい。
少し変えてカレンダーみたいにしたいから何月何日や曜日みたいな情報を入れてほしい
誰も働いてない時は白で黒枠で表示して、ホバーしたら誰が働いたか見えるようにしてほしい

カレンダーなので、今月分を全て表示して。勤務している人がいれば色を塗るようにしてください
月を移動できるようにして！！

webの中心において、小さめに
ファイルはhtml, css, jsに分けてください！
```

このようにプロンプトを書くと、HTML, CSS, JSに分けられたコードを出力してくれる。
VS Codeでファイルを作成して、
index.htmlとstyle.cssとscript.jsの三つのファイルを同じディレクトリーに作成しコピペしていく。index.htmlをchromeで開けば、webを確認することができる。

:::note info
もちろん一度に全てできると思わず、何度もChat GPTと対話しながら、自分の理想に近づけてください。
:::

**大事**
ここで重要なのがChromeで確認したときに、中心に見せたいアイテムが来ること
↓がChromeで開いた様子！
![mosaic_20240515193037.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788759/932fc1b9-1f5b-32d1-916a-9cd2d9d691df.png)

しっかり、中心に表示したいものが来るようにしよう！サイズ感はできるだけ小さい方がnotionのウィジェットとしてみやすいので
``` css
.container{
    width: 350px;
    height: 350px;
}
```
これくらい！縦横ともに**300~400px**くらいにするとちょうどいい気がする。

# 4. HTML, CSS, JSをGithubにあげて、Amplifyでデプロイする
では作ったものを、世に公開してNotionからアクセスできるようにする！
1. Githubにあげよう！privateでいい！
1. GithubにあげたらAWS Amplifyに行く！
1. Amplifyの右上の「新しいアプリを作成」を押して、Githubを選択する。
1. するとGithubのログインとかの情報が出てくると思う。
1. ログインとかしてさっき作ったリポジトリーの名前の項目を選択する。
1. アプリの名前を決めて、次々進めていくとデプロイ完了すると思う。
1. デプロイが完了したらURLが出てくると思うからそのURLをコピーする！

次のステップに行く前にURLをChromeに入れてみてみるといい！


# 5. Notionに埋め込む
ここからは誰でもできる超簡単！
URLをコピペして、「embed(埋め込み)」を選択する！
![埋め込みの選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788759/990301c3-250d-f294-8a00-1394c0caf418.png)

すると簡単完成！
サイズ感とかを直しながら、Notionを整える！
埋め込めばホバーとかクリックしたりもできる！！
![notionwidget.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788759/7a94edd4-63b2-577b-84f0-3c8fdbec12a0.png)

**背景色をNotionと揃えておくとかっこいいよね！！**
ちなみにノーションの背景カラーコードは
ライトモード：`#ffffff`
ダークモード：`#191919`


# 6. Chat GPTに感謝する
これまで働いてくれたChat GPTに感謝する！

# 最後に
ここまでNotionのウィジェットという大層な名前を使ってみたけど、実はただwebを埋め込むだけ！でも埋め込むだけでウィジェットのように使えることは意外と知られてないかも！
本記事はほとんどhtml, css, jsをどう作るかだけど、意外と**Notionのウィジェットを意識しつつ適切なサイズのwebを作ること**が大事だったりする。
そこさえできれば誰でもNotionのウィジェットが作れると思う。
あとは適宜Chat GPTと協働して自分の作りたいものを作る！