Drizzle Studioにレコードのコピペ機能を追加する

目次

Drizzle Studio ?

ブラウザで良い感じのUIでDBを触れるツール。 基本的なDBには全て対応している事もあり、私はできる限りこれを使いたいです。

Drizzle ORM - Meet Drizzle Studio

成果物(執筆時点)

waonpad/drizzle-studio-custom-monkey

課題

MySQL Workbenchをそこそこ使う機会があったのですが、コピペ機能が開発の際にデータをいじいじするのに大いに役立ちました。 Drizzle Studioはレコードのコピペが出来ません。 そのため、特定のレコードを簡単に複製するとか、一時的にあるレコードを削除して復活させたい、といった時に困りました。

対応方法を考える

Drizzle StudioはUIのソースコードを公開しておらず、普通には機能を追加できません。

Tampermonkeyを使いましょう。 任意のページにJSを差し込んでスクリプトを実行する事ができます。

コピー機能を実装する

ユーザースクリプトなので、HTML要素を愚直にセレクタで取得してコピーしたい行を取ってきます。

あとはClipboard.write()で良い感じにテーブル構造を持たせたままクリップボードにレコードの情報をぶち込みます。 クリップボードにはtext/htmlやtext/plain等、任意のMIMEタイプをキーとして情報を入れる事が出来ます。面白い。

text/htmlとしてコピーする

ここで問題が起きました。

Drizzle StudioのテーブルのUIは見た目上tableっぽく組まれていますが、実際はdivの塊です。

Image

divをtext/htmlとしてコピーした場合、テーブル構造が消えてしまいます。

これは、table要素を作成してレコードをtr, td等に詰め替えて対応しました。

HTMLの構造をしっかり組む事で、ペーストされる側が「これはテーブルらしいから構造を維持したまま貼り付けるか」と解釈してくれます。 スプシの1セルに1カラムずつペーストされるのは、この構造がしっかりしている場合です。

Image

text/plainとしてコピーする

スプシの1セルに1カラムずつペーストされる

これは、わざわざHTMLを組まなくてもTSVという形式でも問題ありません。 TSVはCSVの親戚みたいなやつです。初めて知りました。

むしろこっちの方がシンプルで、text/plainは確実にどこにでもペーストできるのでこっちだけでも良いですね・・・。 文字色等を維持したいならHTMLでコピーする必要がありますが。

HTMLをTSVに変換する処理はCopilotが良い感じにやってくれました。

ペースト機能を実装する

コピーできたので、クリップボードに入っている情報をペーストできるようにします。 先述の通り、今はHTMLである必要が無いので、TSV形式が入っている事を想定して処理します。

ここで難しいのが、Drizzle Studioの実装上の問題です。

添付の2枚の画像をご覧ください。 新規レコードを作成する時、カラムの値はspanの中に入っています。 このカラムをクリックする事で、input要素が出現し、入力できるようになります。

Image Image

で、spanの値をJSで単純に書き換えるだけではDrizzle Studio自体は入力された事を検知しません。 当然と言えば当然です。 入力を検知してもらうには、人間が操作するようにinput要素を出現させて入力する必要があります。

これは、document.execCommand("insertText", ...)を使用します。execCommandメソッドは非推奨となっていますが、これは現在時点ではおそらく代替不可能です。 execCommandメソッドを使用しないとinputに入力する事ができません。仕方なく使用します。

この一連の処理はinputを1つ1つ出現させる必要がある都合時間的にかなり遅く、気持ち悪いので今後どうにかしたいところです。 こんな感じになります。100レコードコピペしたいとかになったらかなりストレスですね。

終わり

ペーストの課題が残っているので、後で考えます。

余談

今回全ての処理はキーボードショートカットから実行するようにしました。 ユーザースクリプトはUIを差し込んで違和感なく動作させるのが面倒なので、ショートカットにするのが安牌です。

このライブラリを使用しました。いいね。 jaywcjlove/hotkeys-js: ➷ A robust Javascript library for capturing keyboard input. It has no dependencies.