HTML 5

CSS 3/SASS

AngularJS

NodeJS

Express

MongoDB

Labosalem production

ウェブアプリケーションのデザインと開発

Labosalem Production は医薬品卸売業者が製品購入や注文管理をできるように作られた、オンラインWebアプリケーションです。私は AngularJS MEAN スタックを使ってこのアプリケーションのデザインと構築を行いました。

in_browser
01
コンセプト

ウェブbサイトからウェブアプリケーションまで

Laboratoires Salem Production は、Laboratoires Salem が販売している製品を登録卸売業者が購入したり注文トラッキングしたりできるウェブサイトです。VM Report という前バージョンサイトはすでに4、5年間ほど存在していましたが、顧客には利用されておらず、注文は主に電話で行われている状態でした。

ユーザーに同プラットフォームに戻っていただけるよう、現ウェブサイトである新バージョンのサイトの再設計と開発を私が任されることになりました。

最初のステップとして私が取ったのは、既存サイトの主な問題を特定することでした。それでわかったのは、前バージョンが大変遅いということでした。つまり製品購入のプロセスに時間やステップがかかりすぎていたのです。特にメインメニューそのものに最大10ものサブカテゴリーがあり、レベルが余分にあるものもありました。さらに、インターフェースが複雑すぎて個々の情報を見つけるのが大変でした。また、レスポンシブなサイトではなく、小さめの画面では使用不可能でした。それで顧客は他の方法で注文を行うしかなかったのです。

顧客の問題を解決してくれるツールとしてではなく、製品購入や注文管理を面倒で不確かなものにする、厄介で遅いシステムとしてサイトが見られていたのです。

これから手掛けるウェブサイトは、簡単かつ直感的でレスポンシブなユーザーインターフェースにより、ユーザーが手間や時間をあまりかけずに注文できるようにしてあげる必要があります。ユーザーとの対話性は迅速で、新しく製品を購入するプロセスは容易なものにしてあげなければなりません。最終的にはウェブアプリケーションと同じような感覚がもてるWebサイトを作る必要があるのです。

02
デザイン

オンデマンドの情報

ユーザーインターフェース(UI)のデザインにおいては、簡潔さが大事です。ページにコントロールの表示が多ければ多いほど、ユーザーが特定の行為を済ませる時間がより長くかかってしまいます。チョイスが少ないほど利用可能な機能がより明白になり、さっと目渡しやすくなります。

ナビゲーションをより分かりやすくするために、私はメニューのメインカテゴリーのみを表示することにしました。

  • ダッシュボード(主な顧客用情報が集まった部分)
  • 注文(ユーザーが製品を注文できる場所)
  • マイページ(ユーザーが個人的な情報や以前のアクティビティを集めたものをすべて見ることができる場所)
  • 連絡先

ページ内部で入手可能な追加情報を隠すのには、簡単なタブシステムを使用しました。アクションボタンをクリックすれば新たにポップアップウィンドウが開き、そこから追加情報を読み出すことができるようになっています。

img-project-center

この方法を使えば、情報はまだ見えてはいますが、その全部が表示されるのはユーザーが必要とした場合のみとなり、ユーザー体験がより簡単でフレンドリーなものになります。

訪問者に集中して見てもらえるよう、要素間に色彩のコントラストや面積比を付けるようにしました。注文やメッセージは小さな白のボックスに、データ量の多めの情報はより大きく暗めのボックス内に表示されます。

img-project-center

ダッシュボードのゾーニング

img-project-center

最終のデザイン

03
デベロップメント

迅速でレスポンシブなフロントエンドの構築

フロントエンドのフレームワークには、AngularJS を選びました。双方向データバインディング機能があるからです。データをこうして取り扱うと、UIインタラクションがより簡単で迅速になります。

この原則のよい例が、注文ページです。

img-project-center

双方向データバインディングの能力のお蔭で、情報はリアルタイムで更新され、ユーザーは即座にフィードバックを得られることができるのです。

サーバー側には、MEANスタックの4つの主要コンポーネントのうち、この他の3つの部分を使用しました:

  • データベースとしてMongoDB
  • WebフレームワークとしてExpress
  • フロントエンドのフレームワークとしてAngularJS
  • サーバープラットフォームとしてNodeJS

MEANスタックは、SPA の長所をすべて提供してくれるだけでなく、その他のメリットも提供してくれます。LAMPスタックは幾つかの異なった言語に基いていますが、MEAN スタックは完全なJavaScriptスタックですから、MEAN ベースのアプリケーションのプログラミングが大幅にやりやすくなります。NodeJS もまた、ノンブロッキング・アーキテクチャであることから、LAMP を含む他のサーバー側テクノロジーよりもより速くスケーラブルです。

MEAN スタックの例:請求書

請求書は同アプリケーションを使って注文がある度に作成され、MongoDB データベースに格納され、後で見られるようになっています。同アプリケーションの他の部分と同様に、請求書は以下の構造を持つモジュールです:

Invoices
    view
         invoices.html
    controller.js
    factory.js

ォルダ view には請求書のHTMLテンプレートのすべてが含まれています。

controller.jsファイルは、factory からデータを取ってきて、その scope を介しビューに送る役目をします。


                      						angular.module('factures').controller('facturesCtrl', function(facturesFact, $resource, $scope) {

                      							// get all the invoics of the currently logged in client
                      						    facturesFact.list.query({client_id : Cookies.getJSON('globals').currentUser.id}, function(data) {
                      						        $scope.factures = data.factures;
                      						     });

                      						    // display order details when
                      						    $scope.getInvoice = function(invoice){
                      						    	$scope.lineOrder = invoice
                      						    	showPopUp('invoice_details');
                      						    }


                      						});
                      				

factory.jsファイルは$ressourceオブジェクトを使って特定のURLからデータを回収します。


                      						angular.module('factures').factory('facturesFact', function ($resource) {

                      							return {

                      									// Get all invoices
                      							    	list 			: $resource(
                      									    			'/api/factures',
                      													{client_id : '@client_id'},
                      										    	 	{'query': { method: 'GET',isArray:false }}
                      										    	 	),

                      									// Update invoice statut
                      							    	updateStatue 	: $resource('/api/facture-updatStatue',
                      													{id:'@id', statue:'@statue', client_id:'@client_id'},
                      								    	 			{'query': { method: 'PUT' }}
                      								    	 			),

                      							}

                      						})
                      				

サーバー側では、Mongoose を使って MongoDB データベースにデータがリクエストされます。Mongoose はオブジェクトモデリングツールで、データベースのデータを JavaScript オブジェクトへ変換(そうするとこれをアプリケーションに使える)しやすいように設計されています。


                      					        // retreve all Orders
                      					         app.get('/api/factures', function(req, res) {

                      					            var client_id = req.query.client_id;

                      					                    //find the right client and retreave commandes
                      					                    clients.findOne({_id: client_id}, {'factures':1}, function(err, factures) {

                      					                        if(err)
                      					                             {
                      					                                return res.send(err);
                      					                             }
                      					                             else
                      					                             {
                      					                                return res.json(factures);
                      					                             }

                      					                    });

                      					        })
                                

この方法を使うと、アプリケーションの各部が個々のモジュール(注文、請求書、ログイン、お知らせ等)に分かれますので、コードがよりスケーラブルになりメンテナンスしやすくなります。複数のモジュール間で共有されたデータとビジネスロジックは、サービス内部に格納されます。

タブモジュール

アプリケーション上にデータを表示する主な方法の 1 つ(この記事のデザインに関する部分でご覧いただける通り)が、タブシステムです。アプリケーション全体でよく利用されてますし、異なったデータを数多く取り扱う必要もあるため、簡潔な HTML 属性のセットを使って追加や削除、変更、表示が簡単にできるモジュラータブシステムを作りたかったのです。

Angular のカスタムディレクティブを使用すると、下の HTML コードは注文、ストック、メッセージという3つのタブを含む 1 ブロックを、それらに対応するデータと共に表示します。


                      				  <div module structure="tab" content="commandes,stocks, messages"> <div>
                      				 

このタブモジュールは、タブそのものの構造とタブおよびデータそのもの、という2つの主要部分に分かれます。正しい構造は HTML マークアップ(structure="tab")に提供されたストラクチャ引数値に基づき、モジュールディレクティブを使ってロードされます。各タブブロック内部でロードの必要のあるデータは引数のコンテンツから特定され、TabsData という配列内部に格納されます。


                          						angular.module('panel')

                          							// get attribute strcture and load coressponding structure
                          							.directive('module', function() {

                          								    return {

                          								        restrict: 'A',
                          								        scope: {},

                          								        //send value to template
                          								        link: function(scope, element, attrs) {

                          								           scope.TabsData = attrs.content.split(','); // contruct the array

                          								       },

                          										templateUrl: function(elem, attrs){
                          										      return 'modules/'+attrs.skin+'/views/'+attrs.skin+'.html';
                          										}

                          								    }

                          						})
                          			

テンプレートタブがタブ構造と名前を表示し、それからng-includeを使ってデータテンプレートに呼び出しをかけます。


                        						<section class="m-tabs" ng-controller="TabCtrl">

                        						      <ul>
                        						            <li ng-repeat="name in TabsData ng-class="{active:isSet($index)}">
                        						                <h2 ng-click="setTab($index)">{{name}}>/h2>

                        						            </li>
                        						      </ul>

                        						       <div  ng-show="isSet($index)" ng-repeat="data in TabsData" ng-include src="'modules/' + data + '/views/' + data + '.html'"><div>


                        						</section>
                        				

フロントエンド構築プロセスには、SASS ファイルのプロセスと同じように、自動タスク用に Grunt の使用や、開発サーバーの実行、そしてより優れたパフォーマンスのためのファイルの集中化や最小限化などが含まれます。