Hexabase(ヘキサベース)は企業においても安心して利用できるBaaS(Backend as a Service)を提供しています。多くのBaaSがそうであるように、主にフロントエンド開発者に利用してもらいたいと考えています。そこで現在、TypeScript SDKの開発が進められています。
元々TypeScriptで作られていることもあって、Next.jsやVue.jsなどでimportして利用することができます。しかし、もっと普通のWebアプリケーションなどで使う際には、CDN経由で利用したいと考える方もいるでしょう。そこで、UMD版Hexabase JavaScript SDKを作成しました。
今回は、そのUMD版Hexabase JavaScript SDKを使ったTodoアプリのデモを紹介します。今回はタスクの表示と、編集機能を解説します。一覧の表示、タスクの追加と削除および編集は以下を参照してください。
デモ
デモはこちらのURLで体験できます。
SDKの読み込み
SDKは下記URLで読み込めます。
<script src="https://cdn.jsdelivr.net/npm/@hexabase/hexabase-js@latest/dist/umd/hexabase.min.js"></script>
バージョン指定する場合は、以下のようになります。メジャーバージョンが上がらない限りはlatest指定をお勧めします。
<script src="https://cdn.jsdelivr.net/npm/@hexabase/hexabase-js@2.0.6/dist/umd/hexabase.min.js"></script>
モジュールとして使う場合には、以下のようになります。
<script type="module">
import hexabase from 'https://cdn.jsdelivr.net/npm/@hexabase/hexabase-js@latest/+esm'
</script>
SDKの初期化
SDKは以下のようコードで初期化します。これさえ終われば、後はTypeScriptと同じように使えます。
const { HexabaseClient } = hexabase;
const client = new HexabaseClient();
HTMLについて
HTMLはBootstrapを使って、以下のように作成しています。上半分が既存タスクの表示、下半分はタスクの追加・編集用フォームになっています。 #Status
にステータス変更の表示を行います。
<div class="container" style="padding-top: 1em;">
<div class="row justify-content-md-center">
<div class="col-10">
<div class="row justify-content-end">
<div class="col-5">
<button type="button" id="add" class="btn btn-primary">➕ 新しいタスク</button>
</div>
</div>
<table class="table">
<thead>
<tr>
<th scope="col">タスク</th>
<th scope="col">担当者名</th>
<th scope="col">カテゴリ</th>
<th scope="col">ステータス</th>
<th scope="col">アクション</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<form>
<div class="row g-3">
<input type="hidden" name="id" />
<div class="col">
<input type="text" class="form-control" name="Title" aria-describedby="emailHelp" placeholder="新しいタスク">
</div>
<div class="col">
<input type="text" class="form-control" name="Assignee" placeholder="担当者名">
</div>
<div class="col">
<select name="Category" class="form-control">
</select>
</div>
<div class="col">
<button type="submit" name="Button" id="button" class="btn btn-primary" disabled>追加</button>
</div>
</div>
</form>
<div class="row g-3" style="padding-top: 1em;">
<div class="col">
<div id="Status">
</div>
</div>
</div>
</div>
</div>
</div>
初期設定
まずコード内で使う変数、DOMを定義します。
// 認証用のメールアドレスとパスワード
const email = 'demo5@moongift.jp';
const password = 'K4c%j%vzR7sQKS$u&Uo%';
// Hexabaseのワークスペース、プロジェクト、ワークスペースのID
const workspaceId = '644f6e5ab30d853869ec919f';
const projectId = '650a30501222568b1ae7a2c2';
const datastoreId = '65895ba97b4300d37757d562';
// 複数の処理で使う変数用
const params = {
datastore: null, // データストア
items: [], // 既存タスク一覧
};
// DOM
const table = document.querySelector('.table tbody');
const form = document.querySelector('form');
const addButton = document.querySelector('#add');
初期表示処理
初期表示の処理は以下のようになります。初期設定、データの読み込み、そしてフォームへの値設定となります。
// 画面が読み込まれたときの処理
(async () => {
await init();
load();
await makeForm();
})();
初期設定
初期設定用の init
関数ではログインやワークスペース・プロジェクト・データストアの取得を行っています。
// 初期設定
const init = async () => {
// ログイン
const res = await client.login({email, password});
// ワークスペース・プロジェクト・データストアの取得
await client.setWorkspace(workspaceId);
const project = await client.currentWorkspace.project(projectId);
params.datastore = await project.datastore(datastoreId);
// 追加ボタンを押せるようにする
addButton.disabled = false;
};
データの読み込み
load
関数は既存のタスク一覧を読み込み、テーブルに表示します。
// 既存のアイテム一覧を取得する処理
const load = async () => {
const query = client.query(projectId);
const items = await query
.from(datastoreId)
.select('*');
params.items = items;
// 表示更新
showTable();
};
showTable
関数は、取得したアイテム一覧をテーブルに表示します。また、削除ボタンのイベントリスナーも設定しています。編集ボタンは .edit
で、クリックすると editItem
関数を呼び出します。
// タスク一覧の更新と、タスクへのアクション設定
const showTable = () => {
// params.itemsに沿って、表示を更新
table.innerHTML = params.items.map(item => `
<tr data-id="${item.id}">
<td>${item.get('Title')}</td>
<td>${item.get('Assignee')}</td>
<td>${item.get('Category').ja}</td>
<td>${item._status ? item._status.name : item.statusLabel}</td>
<td>
<span class="edit">📝</span>
<span class="delete">🗑️</span>
</td>
</tr>`).join('');
// 表示リセット
form.reset();
Status.innerHTML = '';
// 削除のイベントリスナー
table.querySelectorAll('.delete').forEach(dom => {
dom.addEventListener('click', deleteItem);
});
table.querySelectorAll('.edit').forEach(dom => {
dom.addEventListener('click', editItem);
});
};
フォームの作成
makeForm
関数は、フォームの select
タグに対して、Hexabaseで設定しているオプションを取得し、描画します。
ja
は日本語で、 en
に英語が設定されています。
// フォームの作成処理
const makeForm = async () => {
// ドロップダウンの項目を取得
const field = await params.datastore.field('Category');
// オプション項目を取得
const options = await field.options();
// HTMLに反映
const html = options.map(option => `
<option id="${option.id}">${option.value.ja}</option>
`);
document.querySelector('form [name="Category"]').innerHTML = html;
}
タスクの編集
既存タスクの編集アイコンをクリックすると editItem
関数が呼ばれます。これは、既存データをフォームに表示する処理です。ドロップダウンのoptionを選択状態にするところで多少工夫が必要です。
item.statusActions
を実行すると、次のステータスに変更するためのアクションが取得できます。これをボタンにして表示しています。ボタンをクリックすると updateStatus
関数が呼ばれます。
// 編集フォームの作成・項目を表示する処理
const editItem = async (e) => {
const id = e.target.closest('tr').getAttribute('data-id');
// 該当するアイテムを探す
const item = params.items.find(item => item.id === id);
form.elements.id.value = id;
form.elements.Title.value = item.get('Title');
form.elements.Assignee.value = item.get('Assignee');
const category = item.get('Category');
const field = await params.datastore.field('Category');
// オプション項目を取得
const options = await field.options();
const option = options.find(option => option.value.ja === category.ja);
form.elements.Category.options[option.id].selected = true;
form.elements.Button.innerText = '更新';
form.elements.Button.disabled = false;
// アイテムの詳細情報取得(ステータス用)
await item.fetch();
// 次のステータスをボタンで表示
Status.innerHTML = item.statusActions.map(action => `
<button class="btn btn-success" data-id="${action.id}">${action.name}</button>
`).join(' ');
// 各ボタンにイベント設定
Status.querySelectorAll('button').forEach(dom => {
dom.addEventListener('click', (e) => updateStatus(item, e));
});
};
上記の画像の場合、 作業中に戻す
や 完了する
がステータス変更のアクションになります。
ステータスとは
Hexabaseのデータストア(RDBMSでいうテーブル相当)ではステータスという特別なフィールドが用意されています。
ステータスは、データの状態を表すためのフィールドです。例えば、案件のデータを管理する場合、ステータスには「新規」「進行中」「完了」などの値を設定します。そして、ステータスは直接変更はできず、ステータス変更のアクションを実行して変更します。
たとえば以下のようになります。
データの状態 | ステータス |
---|---|
新規保存 | 起票 |
プロジェクト開始 | 開始 |
納品完了 | 検収中 |
プロジェクト終了 | 請求前 |
請求書発行 | 入金前 |
入金確認 | 完了 |
そして、このステータスの中には差し戻しが発生することもあるでしょう。検収中のステータスから開始に戻すこともあるでしょう。このような場合も、ステータスの変更はアクションを実行することで行います。
Hexabaseでは、特定のステータスから別なステータスに変更するアクションは、あらかじめ定義したものだけが指定できます。
ステータスの作成
ステータスは管理画面で作成します。ここで各ステータスが別なステータスに変更できるアクションを定義します。
ステータスの更新
ステータスの更新は updateStatus
関数で行います。ステータス変更を行うアクションIDを取得して、 item.execute
メソッドで実行します。
// ステータスの更新処理
const updateStatus = async (item, e) => {
e.preventDefault();
// 次のステータスに移動するアクション
const actionId = e.target.getAttribute('data-id');
await item.execute(actionId);
// 再描画
showTable();
}
まとめ
今回はUMD版Hexabase JavaScript SDKを使って、Todoアプリを作成するデモを紹介しました。UMD版Hexabase JavaScript SDKは、CDN経由で利用できるため、jQueryなど普通のWebアプリケーションでも利用できます。また、TypeScript SDKと同じように使えるため、TypeScript SDKを使っている方でも移行が容易です。
ぜひHexabaseを使ってWebアプリケーション開発を行ってください。