技術は私たちの力。技術は私たちの楽しみ。 Creative Developer BLOG 技術部ブログ
Technology is our strength. Technology is what we enjoy.

Works専用のGoogle拡張機能作ってみた!!

2025-09-29 勉強会
works-addon

1.はじめに...

近年、さまざまな便利ツール・便利アプリが乱立する中、どれだけ使いこなせるかが自身の戦闘力(=仕事力)に直結すると言っても過言ではないはずです。

そんな中、下記のような悩みを抱えている方も少なくはないはずです。
・コピペしたいのに、元データが画像/コピーできない文字列
・ディスプレイ上でウィンドウが乱立しがち...
・ブラウザのタブが増えすぎる...(=タブの押し間違いが多発)

(こうなりがちですよね...)
タブ乱立

それってWorksでも起こりうるよね...

データの一元管理ができる自社の「Works」でも起こりうる問題ですね...

・タブで開かなくても簡易的な登録・編集機能があれば便利っぽい?
・コピペできなくても、ポップアップウィンドウで登録できたら便利だよね
・(ついでに、もっと気軽に登録できる機能があれば便利だよね)

って想いから、Works専用のGoogle拡張機能を作ろうと思ったのが今回の勉強会です!(一般公開するかは未定ですが...)

2.機能構成

新機能を作る上で必ず必要になるのが、まず機能構成の考慮から...
※今回は、ポップアップで表示されるタイプの拡張機能を実装

Worksとどうやって連携する?

今回はベースとして、「自社サービスとの連携」があるので、まずどうやって連携するかの課題からですが、自社サービスWorksにはAPIが用意されているので、今回はサクッとこちらを利用していく形で進めていきます。
WorksAPI

どんな機能を盛り込む?

言うても拡張機能なので、あまり多くの機能を追加してもブラウザ自体が重くなってしまいます。今回は、一旦最小構成として下記3つのモード(+設定画面)を実装していこうと思います。

0.モード切り替え画面

TOP画面。この画面でモード選択をする。
できるだけシンプルにスタイリッシュにしたい。

1.新規登録/編集モード

新規登録と編集ができるモード。基本機能になるため必須。
拡張機能の画面に合わせてどこまで簡略化する?

2.閲覧モード

閲覧専用モード。「新規登録/編集モード」では表示されない登録者や登録日時まで閲覧できる。
コピー時に書き換える心配もないので安心

3.ワンクリック編集モード

拡張機能専用機能。個人的に欲しかった機能を盛り込む。
(時間計測して登録の手間がめんどくさいから、ストップウォッチみたいに計測開始と終了を押したら自動で登録して欲しい)

4.設定画面

拡張機能の設定画面。画面サイズやAPIキーの登録ができる画面。
(ダークモードも欲しいよね)

3.コーディング開始〜空拡張機能作成

では、早速拡張機能の作成に入ります。
細かい説明については別の方の勉強会で詳しく解説されていたので割愛します。
※下記リンクから飛べます

挫折しない!非プログラマーのためのChrome拡張機能入門

「manifest.json」の作成

拡張機能の基本設定ファイルの「manifest.json」を作成して、早速からアプリの作成を行なってみます。また、簡易的に拡張機能用のアイコンも作成し、拡張機能名を「Works Plus」としてみました。

manifest.json


{
"manifest_version": 3,
"name": "Works Plus",
"version": "1.1.1",
"description": "サスケWorks拡張機能(Works Plus)",
"action": {
"default_title": "Mode Switcher",
"default_popup": "popup.html",
"default_icon": {
"16": "icons/logo/works_plus.png",
"32": "icons/logo/works_plus.png",
"48": "icons/logo/works_plus.png"
}
},
"icons": {
"16": "icons/logo/works_plus.png",
"32": "icons/logo/works_plus.png",
"48": "icons/logo/works_plus.png",
"128": "icons/logo/works_plus.png"
},
"permissions": [
"storage"
],
"host_permissions": [
"https://api.works.app/*"
],
"web_accessible_resources": [
{
"resources": [
"icons/fa/*.svg",
"icons/logo/*.png"
],
"matches": [
""
]
}
]
}

拡張機能として読み込んでみた

こちらの「manifest.json」とアイコン画像を1つのフォルダにしてChromで読み込んでみます。
拡張機能

出来た

特に機能は追加していないので、挙動はしないですが無事作成には成功しました。

4.〜モード選択画面の作成

TOP画面となるモード画面の作成です。
今回はポップアップ型の拡張機能のため、画面の出力範囲が狭い分表示方法にも工夫が必要になります。無骨に4モードを1画面に表示しても良かったんですが、面白みがなさすぎるのと、当初述べていた押し間違いの防止のためにもボタンは大きくしました。

モード選択画面完成!

モード選択画面

各画面にアイコンを表示させること、各モードごとに配色を分けることで、視覚的なわかりやすさを向上させました。

5.設定画面の作成

「ダークモードの切り替え」「ウィンドウサイズの変更」「APIキー設定」を行える設定画面を作成します。

設定値ってどう保存しておくの??

拡張機能は、マウスフォーカスが外れると自動で閉じられる仕様のため一度カーソルを外すと設定データ諸共全て飛んでしまいます。そのため、「chrome.storage」なる拡張機能で使用できる専用ストレージが用意されています。
※使い方は、cookieとかとあまり変わらない

ダークモードの設定値保存

  
if (toggle) {
chrome.storage.sync.get({ theme: 'light' }, (data) => {
const isDark = data.theme === 'dark';
document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
toggle.checked = isDark;
});
toggle.addEventListener('change', () => {
const isDark = toggle.checked;
document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
chrome.storage.sync.set({ theme: isDark ? 'dark' : 'light' });
});
}
chrome.storage.sync.set();の部分で「chrome.storage」への値の保存を行なっています。chrome.storage.sync.set({ 保存名: '保存値' });とすることで単一のデータ登録は行えます。

「chrome.storage」の呼び出し

chrome.storage.sync.set();で登録したデータですが、chrome.storage.sync.get();で呼び出すことが可能です。

設定値の受け取り


chrome.storage.sync.get(['key1', 'key2'], (data) => {
console.log(data.key1);
console.log(data.key2);
});
「chrome.storage.sync.get」は、複数個を同時に取得することも可能です。また、['key1', 'key2']部分を指定しないことで「登録されている全てのデータ」を一括で取得することも可能です。

設定画面完成!

設定画面

それぞれの設定値はリアルタイムで反映されるようにしているため、設定画面で確かめながら設定することができます。
※起動設定については後ほど説明します。

6.新規登録/編集モードの作成

ここまできてやっとモードの開発です...
(1から作成すると事前準備が大変ですね...)

worksは、使用用途別に「アプリ」が作成でき、アプリごとに登録できるデータ形式・登録されているデータが異なります。そのため、「新規登録/編集モード」でも最初にアプリの選択画面を作成する必要があります。

アプリ一覧(イメージ)

アプリ一覧

アプリ一覧画面の作成

APIにアプリ一覧取得があるので、こちらを流用して一覧画面を作成します。(アイコン画像も取得できるみたいだから、表示もしてみる)
アプリ取得API

アプリ一覧画面完成

選択中のアプリはホバー表示されるように調整してみました。(アプリ名だけだと視認性低そうなので、アプリアイコンをつけたのは正解かも)
アプリ一覧

レコード一覧の作成・新規登録・編集機能の作成

アプリに登録されているデータはレコードという名称で管理されており、編集機能を使用する上で、これらのレコードの選択機能も必要になります。「https://api.works.app/v1/{appKey}/records/」のAPIを使用することで、登録レコードの情報を取得することができます。また、対象のアプリに設定されているデータと登録形式も取得できるため、こちらのレスポンスをもとに「レコード一覧」と「新規登録・編集用のフォーム」を作成していきます。

レコード一覧完成!

※ほぼアプリ一覧の流用
レコード一覧

新規登録/編集機能にひと工夫...

自動で拡張機能が閉じてしまう仕様上、閉じた場合に「TOP画面に戻ってしまう」「入力値が消えてしまう」の2つの問題が生まれました。

そのため、ウィンドウからフォーカスが消えた(=別ウィンドウのクリック)イベントをトリガーに、「chrome.storage」へ「次回の復帰画面」と「現在入力中の値」を保存するようにコードを追記しました。
※故意的にTOP画面に戻ることで保存値を解放

フォーカス消滅時の保存処理


function saveDraft() {
const draftKey = getDraftStorageKey();
if (!draftKey) return;
const payload = collectValues();
chrome.storage.sync.set({ [draftKey]: payload });
}
「getDraftStorageKey()」で入力値分のキーを作成(複数可)、「collectValues()」で現在の入力値を取得することで「chrome.storage.sync.set({ [draftKey]: payload })」での「chrome.storage」へのデータ保存が可能になります。この時一緒に、アプリ情報や入力中のレコード情報を一緒に保存することで次回の復帰先も一緒に保存することができます。
※次回の復帰時にこれらを読み込むことで、擬似的な「続きから」が可能

最後に...(長くない?)

APIからの登録では、細かい登録設定ができないため事前に登録設定を準備しておく必要があります。今回はテスト用アプリ向けにメインレコードとサブレコード用の登録設定を用意しました。
登録設定

やっと完成

復帰機能も動いていて一安心
※登録設定は動いてないけどね...

編集について

編集機能についても特に変わり映えはないので割愛します(すごく長くなりそうなので...)新規登録のフォームに元から元データが入っているイメージです。

実際に登録されたレコード

登録画像

7.閲覧モードの作成

(長くなっているのでサクッといきます。)
基本的には、「新規登録/編集モード」と大差がなく、書き換えができない代わりに全てのデータが表示されているモードです。
動画の通り...

特に解説することもない

特にデータが見れるからなんだといった感じですが...(説明終了)

8.ワンクリック編集モードの作成

拡張機能ならではの機能が欲しいなと思ったので作成した機能です。

作業中に1項目だけ書き換えたいのに、アプリ選んで、レコード選んで、編集して...ってめんどくさいですよね?そんなところに手が届く拡張機能です。
もしその機能が時間計測もできて計測した時間もそのまま登録できたら?便利ですよね。そんな機能です。

機能設計

試作も試作なので、時間計測ができてその時間を直で書き込めるような機能を作成しようと思います。イメージとしては、ストップウォッチでタイム計測したらそのまま登録されるみたいな...?

レコード間(サブレコード間)も跨いで、切り替えれるようにもしたいので、極力シンプルに。

こうなりました

事前に対象のアプリや対象の項目(フィールド)、登録設定などを設定しておく。
・現状、新規登録はできないので既存データの編集のみ
・既存値への登録方法として「上書き」or「加算」が可能
・時間形式も「秒~時」まで選択可能

見た方が早いので挙動動画

挙動説明

動画中で、背景にあるレコード画面が拡張機能で登録操作を行なった対象です。

今回の設定内容は、計測した「秒数」をサブレコードの「作業時間」に登録するものでした。現在の計測対象は、オレンジ色で強調表示されます。その状態で「計測停止」を押下することで計測が停止され、その時点での計測タイムが記録されます。(次回の計測対象が青色の枠で選択されている場合は計測対象が切り替わる)

動画内では、サブレコードID「S216-21」「S216-22」「S216-23」の順で計測対象となり、それぞれの切り替わったタイミングでの行数が記録されています。
※切り替わりに数秒のラグがありますが、計測秒数自体は押下時点で確定しています。

9.最後に...

長々と試作機能について解説した感じになってしまいましたが、こちらで以上となります!

当初は軽い気持ちで進めたため、結論としては拡張機能は簡単に便利なものが作れる...という結論で結ぼうと思いましたが、実際に取り組んでみるとそうでもなかったかなという気持ちです。凝れる箇所があると時間を使ってしまうエンジニアの性ですね...

参考程度に...ファイル構成と機能別コード行数です
>> 基本ファイル
・manifest.json - 38 lines
>> モード選択画面(TOP) - 419 lines
・popup.js - 172 lines
・popup.html - 34 lines
・popup.css - 213 lines
>> 新規・編集モード - 1178 lines
・composer.js - 182 lines
・composer.html - 25 lines
・composer_edit.js - 942 lines
・composer_edit.html - 29 lines
・cssは「viewer.css」を流用
>> 閲覧モード - 469 lines
・viewer.js - 343 lines
・viewer.html - 25 lines
・viewer.css - 101 lines
>> ワンクリック編集モード - 1316 lines
・oneclick.js - 1290 lines
・oneclick.html - 26 lines
・cssは「viewer.css」を流用
>> 設定画面 - 347 lines
・settings.js - 123 lines
・settings.html - 79 lines
・settings.css - 145 lines

総合lines : 3767 lines
記事一覧へ

New!

Member

システム部開発ユニット
クリエイティブ戦略部デザインユニット
クリエイティブ戦略部プランニングユニット
管理部