AirtableAPI, YoutubeAPIと連動したVideoMemoAPPをNuxtJSで構築
1. アプリの概要
Youtube の PlayLis 等から動画のリストデータを作成し、これら動画に対して学んだことや、動画に対する評価(5 段階)を付与し一覧画面で確認できる、動画学習支援アプリケーション。また、一覧画面で登録したビデオとメモを記入した本数が表示され、学習の進捗も確認できます。
2. メイン機能概要
左から、
-
トップページ(再生リストの一覧)
再生リスト名称と、それぞれの再生リスト毎のビデオの総本数と memo を記入したビデオの本数が表示されます。 -
VideoList ページ(それぞれの再生リストの一覧)
タイトル名称によるフィルタ機能とソート機能(rating、memo の有り無し、ビデオ公開日)があります。 -
個別 Video ページ
YoutubeVideo を再生しながら、memo の記入と rating の入力ができます。
3. コードの説明
3.1. Airtable データの取得(vuex)
Airtable データベースとの連携については、以下の通り整理しました。<br />
データ取得側は、vuex から、Airtable の API エンドポイントにアクセスし、store に一旦データを格納する。
データ更新側は、各ページから、直接 Airtable の API エンドポイントにアクセスしデータの更新を行う。
今回の開発では、Nuxt の動的ルーティングと vuex の store のデータ更新のタイミングが合わず、ページが開かれたとき、ひとつ前に表示したページのデータが表示されてしまい、問題となりました。
ページの中のコードとしては、以下のようなイメージでした。
async mounted () {
await '(1)ストアのfetch関数(action)をdispatchする処理'
await '(2)ストアのデータを取得する処理(getters)'
}
このように async/await で非同期処理を記述することで、(1)の処理がおわってから、(2)の処理が始まるはずなので、問題ないとおもっていましたが、実際には、(1)の処理:action の dispatch が完了すると、vuex 内の store の更新を待たず、(2)の処理がはじまってしまい、問題となっていました。
暫定処置として、(2)の処理については、setTimeout を設定することにしましたが、これは本質的な対応ではないと思っていました。
これについては、Nuxt の asyncData メソッド、fetch メソッド、prefetch の設定等いろいろ試してみましたが、どれもうまく行きませんでした。最終的に、vuex の store を watch することが必要だと気づきました。
公式:Vuex.Store インスタンスメソッド - watch -
最終的なコードは以下のようになりました。
(個別 Video ページの例)
async mounted() {
this.isLoading = true;
const queryString = await this.$nuxt.$route.query.id.split("?");
this.recordId = await queryString[0];
this.tableId = await queryString[1];
const dispatchInfo = {
tableId: this.tableId,
currentPage: "VideoPage",
recordId: this.recordId
};
await this.$store.dispatch("fetchAirTableRecord", dispatchInfo);
this.$store.watch(
() => this.$store.getters["airTableRecord"],
record => {
const airtableRecord = this.$store.getters["airTableRecord"];
this.rating = airtableRecord.rating;
this.memoData = airtableRecord.memo;
this.isLoading = false;
}
);
},
AirtableAPI を使用する際に、今回気づいた注意点は以下になります。
-
値がないもの、checkbox が false の場合、フィールドそのものがないので注意が必要、fetch 関数内で、ブランクの値を付与し、undefined とならないようにする必要があります。
-
Airtable フィールドの初期設定の頭文字が大文字なので、必要に応じて小文字にする。
-
post、update 時にテーブル側の型と合わせないとエラー(ratiing 情報の扱いで数値型と文字型で不一致の際にエラーがでました)
<a id="markdown-32-個別-video-表示画面airtable-データの更新" name="32-個別-video-表示画面airtable-データの更新"></a>
3.2. 個別 Video 表示画面(Airtable データの更新)
データの更新は、個別 Video の表示とメモの入力が一体となった画面で行います。youtube 画面の表示と rating の ★ 印を表示・入力する為に、それぞれ以下のライブラリを使用しました。
-
vue-youtube
https://www.npmjs.com/package/vue-youtube
データ更新のタイミングとしては、★rating については、クリックして rating を変更した場合は値は即時更新、メモデータについては、データを入力し、送信ボタンを押したときに更新するようにしました。
最終的なコードは以下のようになりました。
(メモデータ送信の submitMemo 関数)
submitMemo() {
const app_id = process.env.AIRTABLE_APP_ID;
const app_key = process.env.AIRTABLE_API_KEY;
const tableId = this.tableId;
const data = {
records: [
{
id: this.recordId,
fields: {
memo: this.memoData
}
}
]
};
this.$axios
.patch("https://api.airtable.com/v0/" + app_id + "/" + tableId, data, {
headers: {
Authorization: "Bearer " + app_key,
"Content-Type": "application/json"
}
})
.then(response => {
const items = response.data.records;
this.$toast.show("Item Saved");
})
.catch(error => {
console.log(error);
});
}
3.3. ログイン認証機能(FirebaseAuth を使用)
今回のアプリは個人利用を想定していますので、ログイン認証機能については、FirebaseAuth を使用し、シンプルなものを実装しました。ナビゲーションガードは middleware に記述しました。
import { auth } from "../plugins/firebase";
const middleware = ({ route, store, redirect }) => {
auth().onAuthStateChanged((user) => {
if (user) {
return;
} else if (!user && (route.path == "/SignUp" || route.path == "/SignUp/")) {
return;
} else if (!user && !(route.path == "/login" || route.path == "/login/")) {
return redirect("/login");
}
});
};
export default middleware;
3.4. YoutubePlayList データ csv ダウンロード機能。
初期設定の為に必要な、YoutubePlayList データを取得する為に、YoutubeAPI 経由で、PlayList データを csv ダウンロードする機能を作成しました。入力フィールドに任意の PlayListId を入力すると、該当の csv データが出力されます。デフォルトでは、一度に 50 件までしかデータを取得できませんが、これを 100 件取得できるようにしました。
csv 出力用のコードは以下のリンクのものを参考にさせていただきました。
4. 初期設定について
- ソースコードの.env ファイルに、Yotube,Airtable,Firebase に関する情報を設定します。
- Airtable の設定
base テーブルを新規に作成し、PlayListIndex と各 VideoList のテーブルを設定します。 - VideoMemoApp の Settings の画面から、自分が取り込みたい、Youtube の PlaylistId を入力すると csv データが出力されます。この csv ファイルを Airtable の各 VideoList のテーブルにコピーします。
5. 技術スタック
- NuxtJs
- Vuex
- FirebaseAuth
- Airtable(AirtableAPI)
- YoutubeAPI
- tailwindCSS
6. 主な使用ライブラリ
- vue-star-rating https://www.npmjs.com/package/vue-star-rating
- vue-loading-overlay https://www.npmjs.com/package/vue-loading-overlay
- vue-youtube https://www.npmjs.com/package/vue-youtube
7.拡張
-
PlayList の登録は初回は一括して、csv ファイル経由で行いますが、VideoData の追加は、zappier と airtable 連携機能を使用し自動化できます。
-
記入した Videomemo データは、Airtable の API を介して、Web サイトに展開することも可能です。
Discussion