LINE Engineering
Blog
Excel管理の座席表をLeafletでWeb化した話
こんにちは、LINEのIT支援室で社内システムの開発と運用をしている岩月です。この記事はLINE Advent Calendar 2017の6日目の記事です。
人員の増加に対応するために、今年の4月、LINEはJR新宿ミライナタワーに移転しました。移転に伴い、IT支援室ではいくつかの新しい社内システムを導入しましたが、今日はその1つである「座席表」についてお話させていただきます。
移転前、座席の管理は以下のようにExcelで行われていました(名前は消しています)。
◯◯さんの座席を調べたいと思ったら、Excelもしくは変換されたPDFをダウンロードして、ビューアーの検索機能で名前を調べる必要がありました。恐らくよくある運用ということもあり、利用者から多少の不満の声はあるものの、使えている状態でした。
しかしながら、座席表を管理している総務担当者の負荷は、人員の増加に伴う管理コストの増加で限界に来ていました。管理の中で特に問題だったのは「各々が変更したExcelをマージするのが面倒」「そもそも席替えの連絡が総務担当者まで伝わらず、座席情報の信頼性が低い」という点でした。そのため、これらの問題点を解決するには、ユーザが座席情報を自分で変更できるWebシステムが必要という結論に至りました。
そこで、最初は既存のシステムを導入する方向で考えていましたが、機能的に足りなかったり、価格が高すぎたり、Flashが使われていたりと、ちょうどよい製品が見当たりませんでした。
その結果、LINEの社内事情にフィットする座席表システムを開発することになりました。
座席表を開発するにあたって、以下のことが重要だと考えました。
仕様を決める中で最も難しかったのが、レイアウト管理をどうするかでした。最初は、Excelの座席表情報を利用したかったのですが、図形が多用されており、Excelファイルから正確に座標情報を取得するのが難しかったため、断念しました。しかしながら、総務担当者はExcelを使った座席レイアウトの編集作業に慣れているので、何とかExcelの情報を利用したいと考えました。そこで、Web画面の背景にExcelの座席表をキャプチャしたレイアウト画像を表示し、座席として使える座標をWeb画面から設定する方法を採用しました。
また、ユーザのロールは、席替えだけできるユーザと、レイアウト変更もできる管理者の2種類と、シンプルな構成にしました。
検索については、Excelの場合はセルに入っている名前でしか検索できませんでしたが、部署によってニックネームで呼び合う文化もあるため、ニックネームでも検索できるようにしました。
それほど工数をかけるシステムでもないため、開発は基本的に私1人が担当することになりました。しかし、私自身のJavaScriptでの開発歴が浅く、時間も多くはかけられないため、簡単に地図アプリ風に描画できるJavaScriptのライブラリが必要でした。そこで行き着いたのがLeafletでした。
モバイルとPCのブラウザに対応したWeb地図のためのJavaScriptライブラリです。2011年にバージョン0.1がリリースされ、2016年9月にバージョン1.0がリリースされています。2017年12月現在の最新バージョンは1.2です。このライブラリは、LINEの座席表に必要な機能を一通り押さえており、プログラムもかなりシンプルに記述できます。また、ドキュメントも分かりやすくまとまっている印象です。Google Maps APIを使ったことがある方であれば、似ている部分もあるため、比較的簡単に開発できるのではないかと思います。
以下のHTMLは簡単なLeafletの使用例です。
<!DOCTYPE html>
<html>
<head>
<title>Floor Map Example - Leaflet</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css" integrity="sha512-M2wvCLH6DSRazYeZRIm1JnYyh22purTM+FDB5CsyxtQJYeKq83arPe5wgbNmcFXGqiSH2XR8dT/fJISVA1r/zQ==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet.js" integrity="sha512-lInM/apFSqyy1o6s89K4iQUKg6ppXEgsVxT35HbzUupEVRh2Eu9Wdl4tHj7dZO0s1uvplcYGmt3498TtHq+log==" crossorigin=""></script>
</head>
<body>
<div id="map" style="width: 600px; height: 400px;"></div>
<script>
var map = L.map('map', {crs: L.CRS.Simple});
var bounds = [[0,0], [480,640]]; // ここでは画像の解像度をboundsに設定する。
L.imageOverlay('seat.png', bounds).addTo(map); // 背景画像を設定する。
L.circle([170, 170], {color: 'green',radius: 35}).addTo(map)
.bindTooltip("iwatsuki", {permanent: true, direction: 'center'}).openTooltip()
.bindPopup("iwatsuki <br />IT Support Department");
L.circle([170, 290], {color: 'green',radius: 35}).addTo(map)
.bindTooltip("Name A", {permanent: true, direction: 'center'}).openTooltip();
L.circle([170, 410], {color: 'green',radius: 35}).addTo(map)
.bindTooltip("Name B", {permanent: true, direction: 'center'}).openTooltip();
L.circle([60, 170], {color: 'green',radius: 35}).addTo(map)
.bindTooltip("Name C", {permanent: true, direction: 'center'}).openTooltip();
L.circle([60, 290], {color: 'green',radius: 35}).addTo(map)
.bindTooltip("Name D", {permanent: true, direction: 'center'}).openTooltip();
L.circle([60, 410], {color: 'gray',radius: 35}).addTo(map)
.bindTooltip("Name E", {permanent: true, direction: 'center'}).openTooltip();
map.fitBounds(bounds); // 描画領域を設定する。
</script>
</body>
</html>
このHTMLをブラウザで表示すると、以下のような画面が表示されます。
いかがでしょうか?これだけでも座席表のように見えるのではないかと思います。
Leafletのツールチップに名前を{permanent: true}
で表示することで、ExcelやPDFと同様に、どの座席に誰が座っているかを一覧で見せることが可能になります。また、スクロールにはマウスドラッグで、ズームイン、ズームアウトについては、画像左上の"+"と"-"ボタンをクリックするかマウスホイールを前後に回すことで、何もプログラムを書かなくても対応します。以下は、ズームイン後に"iwatsuki"の円をクリックした後の画像です。
座席表として使うのであれば、名前の他にも部署名や顔画像、連絡先などが欲しいところです。このような詳細情報は、上の画像のようにLeafletのポップアップ機能を使うことで、非常に簡単に表示することができます。
検索については、map.fitBounds(bounds);
のようにLeafletで描画領域を設定できるので、キーワードに応じて座標情報を返すAPIをバックエンドに作れば実現できます。
また、LINEはミライナタワーの15Fから23Fを使用しているため、フロアの表示切り替えが必須になります。フロアの切り替えはLeafletのレイヤー機能で対応できます。以下のようにプログラムを書くと、画面右上にレイヤーの切り替えボタンが追加され、マウスオーバー時に、「21F」、「22F」、「23F」を選択できるようになります。
var map = L.map('map', {crs: L.CRS.Simple});
var bounds = [[0,0], [428,608]];
var baseMaps = {
"21F": L.imageOverlay('21F Image Link', bounds),
"22F": L.imageOverlay('22F Image Link', bounds),
"23F": L.imageOverlay('22F Image Link', bounds)
}
L.control.layers(baseMaps).addTo(map);
map.on("baselayerchange", (event) => {
console.log(event.name); // 切り替わり後のフロア名が出力される。
// フロア毎の処理を書く。
});
map.addLayer(baseMaps["15F"]);
map.fitBounds(bounds);
その他にも、クリックやマウスオーバーなどのイベントが発生した際の座標の取得が簡単にできたり、オブジェクトをグループでまとめて処理できたりと、便利なAPIが揃っています。詳しくは、公式ドキュメントをご覧ください。
座席表の開発にはフロントエンドにAngular 4、バックエンドにRails 5をAPIモードで使用しました。これらの開発の詳細については、特別なことは何もないので省略します。そして、完成したLINE Floor Mapがこちらです。
モザイクをかけていますが、名前や部署名の他にも顔写真やメールアドレスを表示させています。また、ポップアップ左上の赤い消しゴムマークで座席を削除でき、その右のボタンでは座席へのパーマリンクをコピーできるようになっています。空席をクリックした場合は、名前を入力することで誰の席でも自由に設定できるようになっています。ただし、自由すぎるのもトラブルの元ですので、自席を他の人が変更した場合は、誰が変更したかがメールで通知されるようにしました。
検索については、社員の他に会議室などの施設の検索もできるようにして、Excelで利用できた機能をきっちりカバーできるようにしました。
しかし、分かっていたことではあるのですが、Excelの座席表を背景として使用しているので、オシャレ感はイマイチありません。そういった部分を反省(?)した結果か、少し遅れて導入したLINE Fukuokaの座席表はなかなかオシャレな感じに背景をデザインしてもらえました。
良い感じではないでしょうか!(ズームアウトするとツールチップが重なってしまうため、一定以上のズームアウトでツールチップを非表示にしています)
また、今回開発した座席表では、社員だけでなく「作業用」や「入社者用」といったメモ書きも追加できるようにし、会議室と同様に検索できるように対応しています。もちろん、スマートフォンからの閲覧にも対応しています。
今回開発した座席表は総務の業務軽減に始まったプロジェクトでした。そして実際に導入後には、座席表の管理にかけていた総務の業務を大幅に削減することに成功しました。また、利用者からもかなり好評で、「これを待っていたんですよ!」といった声もあり、社内コミュニケーションの円滑化に一役買うことができているようです。誰の席でも自由に変更できるという点についても、これまでのところトラブルの報告を受けることなく運用できています。
ただし、「席替えの配置の検討」についてはExcelと比べて不便になってしまいました。Excelで管理されていれば、現在の座席が存在するExcelファイルを少し編集するだけで席替えを検討できたのですが、Web化されたことによって、手元での席替えの検討が難しくなってしまいました。現在のところ、空白のExcelの座席表に既存の座席配置を1つずつコピー&ペーストする作業が発生してしまっている状況です。
少し課題もありますが、Excelでの座席管理に苦労されている場合や、座席を調べるのにExcelは面倒だと感じられている場合は、この記事が少しでも参考になれば嬉しいです。
明日はHiraiさんによる「LINE STOREにおけるテスト自動化の取り組み」についての記事です。お楽しみに!