http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/index.html
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/index.html 
b/eagle-server/src/main/webapp/app/dev/index.html
new file mode 100644
index 0000000..56850d7
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/index.html
@@ -0,0 +1,250 @@
+<!DOCTYPE html>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<html ng-controller="MainCtrl">
+       <head>
+               <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
+               <meta http-equiv="Content-Type" content="text/html; 
charset=utf-8">
+               <meta charset="UTF-8">
+               <meta content='width=device-width, initial-scale=1, 
maximum-scale=1, user-scalable=no' name='viewport'>
+               <link rel="shortcut icon" href="public/images/favicon.png">
+
+               <title>Eagle</title>
+               <link rel="shortcut icon" type="image/png" 
href="public/images/favicon.png">
+
+               <!-- ref:css public/css/doc.css -->
+               <link href="../node_modules/bootstrap/dist/css/bootstrap.css" 
rel="stylesheet" type="text/css" media="screen">
+               <link 
href="../node_modules/zombiej-bootstrap-components/bootstrap-components/css/bootstrap-components.css"
 rel="stylesheet" type="text/css" media="screen">
+
+               <link href="../node_modules/zombiej-nvd3/build/nv.d3.css" 
rel="stylesheet" type="text/css" />
+
+               <link href="../node_modules/font-awesome/css/font-awesome.css" 
rel="stylesheet" type="text/css" />
+
+               <link href="../node_modules/admin-lte/dist/css/AdminLTE.css" 
rel="stylesheet" type="text/css" />
+               <link 
href="../node_modules/admin-lte/dist/css/skins/skin-blue.css" rel="stylesheet" 
type="text/css" />
+
+               <link href="public/css/animation.css" rel="stylesheet" 
type="text/css" media="screen">
+               <link href="public/css/sortTable.css" rel="stylesheet" 
type="text/css" media="screen">
+               <link href="public/css/main.css" rel="stylesheet" 
type="text/css" media="screen">
+               <!-- endref -->
+       </head>
+       <body class="skin-blue sidebar-mini" ng-class="{'no-sidebar' : 
PageConfig.hideSidebar}">
+               <!-- Site wrapper -->
+               <div class="wrapper">
+                       <header class="main-header">
+                               <a href="#/" class="logo">
+                                       <span class="logo-mini"><img 
src="public/images/favicon_white.png" /></span>
+                                       <span class="logo-lg">Apache 
Eagle</span>
+                               </a>
+                               <!-- Header Navbar: style can be found in 
header.less -->
+                               <nav class="navbar navbar-static-top" 
role="navigation">
+                                       <!-- Sidebar toggle button-->
+                                       <a ng-hide="PageConfig.hideSidebar" 
class="sidebar-toggle" data-toggle="offcanvas" role="button">
+                                               <span class="sr-only">Toggle 
navigation</span>
+                                               <span class="icon-bar"></span>
+                                               <span class="icon-bar"></span>
+                                               <span class="icon-bar"></span>
+                                       </a>
+
+                                       <div class="navbar-custom-menu">
+                                               <ul class="nav navbar-nav">
+                                                       <li class="dropdown 
time-picker" ng-if="Time.pickerType === Time.TIME_RANGE_PICKER">
+                                                               <a 
data-toggle="dropdown" aria-expanded="false">
+                                                                       <i 
class="fa fa-calendar"></i>
+                                                                       
{{Time.format("startTime", Time.SHORT_FORMAT)}} ~ {{Time.format("endTime", 
Time.SHORT_FORMAT)}}
+                                                               </a>
+                                                               <ul 
class="dropdown-menu">
+                                                                       <li><a 
ng-click="setLastDuration(2)"><i class="fa fa-clock-o"></i>Last 2 Hours</a></li>
+                                                                       <li><a 
ng-click="setLastDuration(6)"><i class="fa fa-clock-o"></i>Last 6 Hours</a></li>
+                                                                       <li><a 
ng-click="setLastDuration(12)"><i class="fa fa-clock-o"></i>Last 12 
Hours</a></li>
+                                                                       <li><a 
ng-click="setLastDuration(24)"><i class="fa fa-clock-o"></i>Last 24 
Hours</a></li>
+                                                                       <li><a 
ng-click="customizeTimeRange()"><i class="fa fa-clock-o"></i>Customize</a></li>
+                                                               </ul>
+                                                       </li>
+                                                       <li>
+                                                               <a 
data-toggle="dropdown" aria-expanded="false">
+                                                                       <i 
class="glyphicon glyphicon-question-sign"></i>
+                                                               </a>
+
+                                                               <ul 
class="dropdown-menu">
+                                                                       
<li><a>How to start using eagle</a></li>
+                                                                       
<li><a>How to register new site</a></li>
+                                                                       
<li><a>How to install application</a></li>
+                                                                       
<li><a>How to manage application</a></li>
+                                                                       
<li><a>How to develop application</a></li>
+                                                               </ul>
+                                                       </li>
+                                               </ul>
+                                       </div>
+                               </nav>
+                       </header>
+
+                       <!-- =============================================== -->
+                       <!-- Left side column. contains the side bar -->
+                       <aside class="main-sidebar" 
ng-hide="PageConfig.hideSidebar">
+                               <!-- side bar: style can be found in 
sidebar.less -->
+                               <section class="sidebar">
+                                       <ul class="sidebar-menu">
+                                               <li ng-repeat="portal in 
Portal.list track by $index" ng-class="{treeview: portal.list}">
+                                                       <a 
ng-href="{{portal.path}}">
+                                                               <i class="fa 
fa-{{portal.icon || 'circle-o'}}"></i>
+                                                               
<span>{{portal.name}}</span>
+                                                               <i class="fa 
fa-angle-left pull-right" ng-if="portal.list"></i>
+                                                       </a>
+                                                       <ul 
class="treeview-menu" ng-if="portal.list">
+                                                               <li 
ng-repeat="subPortal in portal.list track by $index" ng-class="{active: 
getNavClass(subPortal)}">
+                                                                       <a 
ng-href="{{subPortal.path}}">
+                                                                               
<i class="fa fa-{{subPortal.icon || 'circle-o'}}"></i>
+                                                                               
<span>{{subPortal.name}}</span>
+                                                                       </a>
+                                                               </li>
+                                                       </ul>
+                                               </li>
+                                       </ul>
+                               </section>
+                               <!-- /.sidebar -->
+                       </aside>
+
+                       <!-- =============================================== -->
+                       <!-- Right side column. Contains the navbar and content 
of the page -->
+                       <div class="content-wrapper">
+                               <!-- Content Header (Page header) -->
+                               <section class="content-header" 
ng-hide="PageConfig.hideTitle">
+                                       <h1>
+                                               <span 
class="pageTitle">{{PageConfig.title}}</span>
+                                               <small 
class="pageSubTitle">{{PageConfig.subTitle}}</small>
+                                       </h1>
+
+
+                                       <ol class="breadcrumb">
+                                               <li ng-repeat="navPath in 
PageConfig.navPath">
+                                                       <a 
ng-href="#{{navPath.path}}">
+                                                               <span class="fa 
fa-home" ng-if="$first"></span>
+                                                               {{navPath.title 
|| navPath.path}}
+                                                       </a>
+                                               </li>
+                                       </ol>
+                               </section>
+
+                               <!-- Main content -->
+                               <section class="content">
+                                       <div id="content">
+                                               <div ui-view></div>
+                                       </div>
+                               </section><!-- /.content -->
+                       </div><!-- /.content-wrapper -->
+
+                       <footer class="main-footer">
+                               <div class="pull-right hidden-xs">
+                                       <b>License</b>
+                                       <a 
href="http://www.apache.org/licenses/LICENSE-2.0"; 
class="text-muted">Apache-2.0</a>
+                               </div>
+                               <strong>
+                                       Apache Eagle
+                                       <a target="_blank" 
href="https://eagle.incubator.apache.org/";>Home</a> /
+                                       <a target="_blank" 
href="https://eagle.incubator.apache.org/docs/community.html";>Community</a> /
+                                       <a target="_blank" 
href="https://cwiki.apache.org/confluence/display/EAG/FAQ";>FAQ</a>
+                               </strong>
+                       </footer>
+               </div><!-- ./wrapper -->
+
+               <!-- Modal: Time Range Picker -->
+               <div class="modal fade" tabindex="-1" role="dialog" 
id="eagleTimeRangeMDL">
+                       <div class="modal-dialog" role="document">
+                               <div class="modal-content">
+                                       <div class="modal-header">
+                                               <button type="button" 
class="close" data-dismiss="modal" aria-label="Close"><span 
aria-hidden="true">&times;</span></button>
+                                               <h4 
class="modal-title">Customize Time Range</h4>
+                                       </div>
+                                       <div class="modal-body">
+                                               <div class="row">
+                                                       <div class="col-sm-6">
+                                                               <div 
class="form-group">
+                                                                       <label 
for="eagleStartTime">Start Time</label>
+                                                                       <input 
type="text" class="form-control" data-container="body" data-toggle="datepicker" 
id="eagleStartTime">
+                                                               </div>
+                                                       </div>
+                                                       <div class="col-sm-6">
+                                                               <div 
class="form-group">
+                                                                       <label 
for="eagleEndTime">End Time</label>
+                                                                       <input 
type="text" class="form-control" data-container="body" data-toggle="datepicker" 
id="eagleEndTime" data-position="right">
+                                                               </div>
+                                                       </div>
+                                               </div>
+                                       </div>
+                                       <div class="modal-footer">
+                                               <button type="button" 
class="btn btn-default" data-dismiss="modal">Close</button>
+                                               <button type="button" 
class="btn btn-primary" ng-click="updateTimeRange()">Change</button>
+                                       </div>
+                               </div>
+                       </div>
+               </div>
+
+               <!-- ref:js public/js/modules.js -->
+               <script 
src="../node_modules/jquery/dist/jquery.min.js"></script>
+               <script 
src="../node_modules/jquery-slimscroll/jquery.slimscroll.min.js"></script>
+               <script 
src="../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
+               <script 
src="../node_modules/zombiej-bootstrap-components/bootstrap-components/js/bootstrap-components.min.js"></script>
+               <script 
src="../node_modules/moment/min/moment-with-locales.min.js"></script>
+               <script 
src="../node_modules/moment-timezone/builds/moment-timezone-with-data.min.js"></script>
+               <script 
src="../node_modules/echarts/dist/echarts.min.js"></script>
+               <script 
src="../node_modules/admin-lte/dist/js/app.min.js"></script>
+               <script src="../node_modules/angular/angular.min.js"></script>
+               <script 
src="../node_modules/angular-resource/angular-resource.min.js"></script>
+               <script 
src="../node_modules/angular-route/angular-route.min.js"></script>
+               <script 
src="../node_modules/angular-animate/angular-animate.min.js"></script>
+               <script 
src="../node_modules/angular-ui-bootstrap/dist/ui-bootstrap-tpls.js"></script>
+               <script 
src="../node_modules/angular-ui-router/release/angular-ui-router.min.js"></script>
+               <!-- endref -->
+
+               <!-- ref:js public/js/doc.min.js -->
+               <!-- Worker -->
+               <script src="public/js/worker/sortTableFunc.js" 
type="text/javascript" charset="utf-8"></script>
+
+               <!-- Application -->
+               <script src="public/js/common.js" type="text/javascript" 
charset="utf-8"></script>
+               <script src="public/js/index.js" type="text/javascript" 
charset="utf-8"></script>
+               <script src="public/js/app.js" type="text/javascript" 
charset="utf-8"></script>
+
+               <!-- Service -->
+               <script src="public/js/services/main.js" type="text/javascript" 
charset="utf-8"></script>
+               <script src="public/js/services/timeSrv.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/services/pageSrv.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/services/widgetSrv.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/services/wrapStateSrv.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/services/entitySrv.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/services/siteSrv.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/services/applicationSrv.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/services/uiSrv.js" 
type="text/javascript" charset="utf-8"></script>
+
+               <!-- Components -->
+               <script src="public/js/components/main.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/components/sortTable.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/components/chart.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/components/widget.js" 
type="text/javascript" charset="utf-8"></script>
+
+               <!-- Controllers -->
+               <script src="public/js/ctrls/main.js" type="text/javascript" 
charset="utf-8"></script>
+               <script src="public/js/ctrls/mainCtrl.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/ctrls/alertCtrl.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/ctrls/integrationCtrl.js" 
type="text/javascript" charset="utf-8"></script>
+               <script src="public/js/ctrls/siteCtrl.js" 
type="text/javascript" charset="utf-8"></script>
+               <!-- endref -->
+       </body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/alert/list.html
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/partials/alert/list.html 
b/eagle-server/src/main/webapp/app/dev/partials/alert/list.html
new file mode 100644
index 0000000..d493976
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/alert/list.html
@@ -0,0 +1,21 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="box-body">
+       Good!
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/alert/main.html
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/partials/alert/main.html 
b/eagle-server/src/main/webapp/app/dev/partials/alert/main.html
new file mode 100644
index 0000000..2e062a8
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/alert/main.html
@@ -0,0 +1,29 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="nav-tabs-custom">
+       <ul class="nav nav-tabs">
+               <li ng-class="{active: getState() === 'alert.list'}"><a 
href="#/alert/">Explore Triggered Alerts</a></li>
+               <li ng-class="{active: getState() === 'alert.policyList'}"><a 
href="#/alert/policyList">Manage Policies</a></li>
+               <li ng-class="{active: ['alert.policyCreate', 
'alert.policyEdit'].indexOf(getState()) >= 0}"><a 
href="#/alert/policyCreate">Define Alert Policy</a></li>
+       </ul>
+       <div class="tab-content no-padding">
+               <div ui-view></div>
+       </div>
+</div>
+

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit.back.html
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit.back.html 
b/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit.back.html
new file mode 100644
index 0000000..3c335f7
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit.back.html
@@ -0,0 +1,108 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="box-body">
+       <ul class="timeline">
+               <!-- Base Info -->
+               <li class="time-label">
+                       <span class="bg-blue">#1. Basic Information</span>
+               </li>
+               <li>
+                       <span class="fa fa-file-text bg-aqua"></span>
+                       <div class="timeline-item">
+                               <div class="timeline-body">
+                                       <div class="form-group">
+                                               <label>Policy Name</label>
+                                               <input type="text" 
class="form-control" ng-model="policy.name" />
+                                       </div>
+                                       <div class="form-group">
+                                               <label>Severity</label>
+                                               <select class="form-control" 
ng-model="policy.severity">
+                                                       <option>WARNING</option>
+                                                       
<option>CRITICAL</option>
+                                                       <option>DANGER</option>
+                                               </select>
+                                       </div>
+                                       <div class="form-group">
+                                               <label>Description</label>
+                                               <textarea class="form-control" 
ng-model="policy.description" rows="3"></textarea>
+                                       </div>
+                               </div>
+                       </div>
+               </li>
+
+               <!-- Alert Stream -->
+               <li class="time-label">
+                       <span class="bg-blue">#2. Alert Stream</span>
+               </li>
+               <li>
+                       <span class="fa fa-rocket bg-aqua"></span>
+                       <div class="timeline-item">
+                               <div class="timeline-body">
+                                       <div class="form-group">
+                                               <label>App Integration</label>
+                                               <select 
class="form-control"></select>
+                                       </div>
+                                       <div class="form-group">
+                                               <label>Alert Stream</label>
+                                               <select 
class="form-control"></select>
+                                       </div>
+                               </div>
+                       </div>
+               </li>
+
+               <!-- Streaming Logic -->
+               <li class="time-label">
+                       <span class="bg-blue">#3. Streaming Logic</span>
+               </li>
+               <li>
+                       <span class="fa fa-trophy bg-aqua"></span>
+                       <div class="timeline-item">
+                               <div class="timeline-body">
+                                       <div class="form-group">
+                                               <label>Policy Type</label>
+                                               <select 
class="form-control"></select>
+                                       </div>
+                                       <div class="form-group">
+                                               <label>Policy Logic</label>
+                                               <textarea class="form-control" 
rows="5"></textarea>
+                                       </div>
+                               </div>
+                       </div>
+               </li>
+
+               <!-- Publication Configuration -->
+               <li class="time-label">
+                       <span class="bg-blue">#4. Publication 
Configuration</span>
+               </li>
+               <li>
+                       <span class="fa fa-envelope bg-aqua"></span>
+                       <div class="timeline-item">
+                               <div class="timeline-body">
+                                       <div class="form-group">
+                                               <label>Publication Type</label>
+                                               <select class="form-control">
+                                                       
<option>NOTIFICATION</option>
+                                               </select>
+                                       </div>
+                                       <a>+ New Publication</a>
+                               </div>
+                       </div>
+               </li>
+       </ul>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit.html
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit.html 
b/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit.html
new file mode 100644
index 0000000..9a1cbe4
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit.html
@@ -0,0 +1,29 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="box-body">
+       <ul class="stepGuide">
+               <li>
+                       <span class="icon bg-green">1</span>
+                       <span class="title">This is the title!!!</span>
+               </li>
+               <li>
+                       <span class="icon">2</span>
+               </li>
+       </ul>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/alert/policyList.html
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/webapp/app/dev/partials/alert/policyList.html 
b/eagle-server/src/main/webapp/app/dev/partials/alert/policyList.html
new file mode 100644
index 0000000..2d4703f
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/alert/policyList.html
@@ -0,0 +1,63 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="box box-solid">
+       <div class="box-body">
+               <div sort-table="policyList" ng-show="policyList.length">
+                       <table class="table table-bordered">
+                               <thead>
+                                       <tr>
+                                               <th sortpath="name" 
width="20%">Name</th>
+                                               <th sortpath="definition.type" 
width="70">Type</th>
+                                               <th>Description</th>
+                                               <th width="85">Action</th>
+                                       </tr>
+                               </thead>
+                               <tbody>
+                                       <tr>
+                                               <td>
+                                                       <a 
ng-href="#/alert/policyEdit/{{item.name}}">{{item.name}}</a>
+                                               </td>
+                                               <td class="text-center"><span 
class="label label-primary">{{item.definition.type}}</span></td>
+                                               <td>{{item.description}}</td>
+                                               <td class="text-center">
+                                                       <div class="btn-group 
btn-group-xs">
+                                                               <button 
class="btn btn-default"><span class="fa fa-play"></span></button>
+                                                               <button 
class="btn btn-default"><span class="fa fa-pencil"></span></button>
+                                                               <button 
class="btn btn-danger" ng-click="deletePolicy(item)"><span class="fa 
fa-trash"></span></button>
+                                                       </div>
+                                               </td>
+                                       </tr>
+                               </tbody>
+                       </table>
+               </div>
+
+               <div class="callout callout-warning no-margin" 
ng-show="policyList._done && policyList.length === 0">
+                       <h4>No Policy yet</h4>
+                       <p>You have not create policy yet. Click <a 
href="#/alert/policyCreate">here</a> to create a new policy.</p>
+               </div>
+       </div>
+
+       <div class="overlay" ng-if="!policyList._done">
+               <i class="fa fa-refresh fa-spin"></i>
+       </div>
+
+       <div class="box-footer text-right">
+               <a href="#/alert/policyCreate" class="btn btn-primary">New 
Policy</a>
+       </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/home.html
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/partials/home.html 
b/eagle-server/src/main/webapp/app/dev/partials/home.html
new file mode 100644
index 0000000..ab75b18
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/home.html
@@ -0,0 +1,60 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<!--div class="row" ng-repeat="banner in bannerList track by $index">
+       <div class="col-sm-12" ng-if="banner.title">
+               <h3>{{banner.title}}</h3>
+       </div>
+       <div class="col-sm-6 col-md-4 col-lg-3" ng-repeat="widget in 
banner.list track by $index">
+               <div class="small-box {{widget.color || 'bg-aqua'}}">
+                       <div class="inner">
+                               <h3>{{widget.title || "Untitled"}}</h3>
+                               <p>{{widget.description || "-"}}</p>
+                               <p>{{widget.additionalTips || "&nbsp;"}}</p>
+                       </div>
+                       <div class="icon">
+                               <i class="fa fa-question-circle"></i>
+                       </div>
+                       <a class="small-box-footer">More info <i class="fa 
fa-arrow-circle-right"></i></a>
+               </div>
+       </div>
+</div-->
+<div class="row flex">
+       <div class="col-sm-6 col-md-4 col-lg-3" ng-repeat="widget in 
Widget.list track by $index">
+               <div widget="widget"></div>
+       </div>
+</div>
+
+<!--div class="row flex">
+       <div class="col-md-4">
+               <div style="background: red; height: 200px;">111</div>
+       </div>
+       <div class="col-md-4">
+               <div style="background: green;">222</div>
+               <div style="background: blue;">222</div>
+       </div>
+       <div class="col-md-4">
+               <div style="background: red;">333</div>
+       </div>
+       <div class="col-md-4">
+               <div style="background: green;">444</div>
+       </div>
+       <div class="col-md-4">
+               <div style="background: red;">555</div>
+       </div>
+</div-->

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/integration/applicationList.html
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/webapp/app/dev/partials/integration/applicationList.html
 
b/eagle-server/src/main/webapp/app/dev/partials/integration/applicationList.html
new file mode 100644
index 0000000..bc603a7
--- /dev/null
+++ 
b/eagle-server/src/main/webapp/app/dev/partials/integration/applicationList.html
@@ -0,0 +1,80 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="box-body">
+       <table class="table table-bordered table-striped">
+               <thead>
+               <tr>
+                       <th>Application</th>
+                       <th>Type</th>
+                       <th>Version</th>
+                       <th>Path</th>
+                       <th>Streams</th>
+                       <th>Description</th>
+               </tr>
+               </thead>
+               <tbody>
+                       <tr ng-repeat="app in Application.providerList track by 
$index">
+                               <td class="text-no-break"><a 
ng-click="showAppDetail(app)">{{app.name}}</a></td>
+                               <td>{{app.type}}</td>
+                               <td class="text-no-break">{{app.version}}</td>
+                               <td>{{app.viewPath}}</td>
+                               <td>
+                                       <ul>
+                                               <li ng-repeat="stream in 
app.streams track by $index">
+                                                       {{stream.streamId}}
+                                               </li>
+                                       </ul>
+                               </td>
+                               <td>{{app.description}}</td>
+                       </tr>
+               </tbody>
+       </table>
+</div>
+
+
+<!-- Modal: Application information -->
+<div class="modal fade" role="dialog" id="appMDL">
+       <div class="modal-dialog modal-lg">
+               <div class="modal-content">
+                       <div class="modal-header">
+                               <button type="button" class="close" 
data-dismiss="modal" aria-label="Close">
+                                       <span aria-hidden="true">×</span>
+                               </button>
+                               <h4 class="modal-title" 
id="myModalLabel">{{application.name}}</h4>
+                       </div>
+                       <div class="modal-body">
+                               <ul class="nav nav-tabs">
+                                       <li class="active"><a 
href="[data-id='install']" data-toggle="tab">Install</a></li>
+                                       <li><a href="[data-id='uninstall']" 
data-toggle="tab">Uninstall</a></li>
+                               </ul>
+                               <div class="tab-content">
+                                       <div class="tab-pane active" 
data-id="install">
+                                               <pre 
ng-bind-html="installHTML"></pre>
+                                       </div>
+                                       <div class="tab-pane" 
data-id="uninstall">
+                                               <pre 
ng-bind-html="uninstallHTML"></pre>
+                                       </div>
+                               </div>
+                       </div>
+                       <div class="modal-footer">
+                               <button type="button" class="btn btn-default" 
data-dismiss="modal">Close</button>
+                       </div>
+               </div>
+       </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/integration/main.html
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/webapp/app/dev/partials/integration/main.html 
b/eagle-server/src/main/webapp/app/dev/partials/integration/main.html
new file mode 100644
index 0000000..daea22e
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/integration/main.html
@@ -0,0 +1,29 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="nav-tabs-custom">
+       <ul class="nav nav-tabs">
+               <li ng-class="{active: getState().indexOf('integration.site') 
!== -1}"><a href="#/integration/siteList">Sites</a></li>
+               <li ng-class="{active: getState() === 
'integration.applicationList'}"><a 
href="#/integration/applicationList">Applications</a></li>
+               <li ng-class="{active: getState() === 
'integration.streamList'}"><a href="#/integration/streamList">Streams</a></li>
+       </ul>
+       <div class="tab-content no-padding">
+               <div ui-view></div>
+       </div>
+</div>
+

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/integration/site.html
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/webapp/app/dev/partials/integration/site.html 
b/eagle-server/src/main/webapp/app/dev/partials/integration/site.html
new file mode 100644
index 0000000..b391b49
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/integration/site.html
@@ -0,0 +1,95 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="box-body">
+       <p class="text-danger" ng-if="site.applicationList.length === 0">
+               <span class="fa fa-exclamation-triangle"></span> Site must 
install at least one application to start up.
+       </p>
+       <p class="text-warning" ng-if="site.applicationList.length !== 0 && 
getStartedAppCount() === 0">
+               <span class="fa fa-exclamation-triangle"></span> No application 
started.
+       </p>
+
+       <table class="table table-bordered table-hover">
+               <thead>
+                       <tr>
+                               <th>App</th>
+                               <th width="10">Status</th>
+                               <th>Version</th>
+                               <th>Description</th>
+                               <!--th>Quick Links</th-->
+                               <th width="150">Actions</th>
+                       </tr>
+               </thead>
+               <tbody>
+                       <tr ng-repeat="app in applicationList track by $index">
+                               <td><a 
ng-click="showAppDetail(app)">{{app.origin.name}}</a></td>
+                               <td class="text-center">
+                                       <span class="label 
label-{{getAppStatusClass(app)}}" ng-if="app.installed">{{app.status}}</span>
+                                       <span class="label label-default" 
ng-if="!app.installed">UNINSTALLED</span>
+                               </td>
+                               <td>{{app.origin.version}}</td>
+                               <td>{{app.description}}</td>
+                               <!--td>TODO: ui link</td-->
+                               <td class="text-center">
+                                       <div class="btn-group btn-group-xs" 
ng-if="app.installed">
+                                               <!--button class="btn 
btn-default btn-sm">Monitor</button-->
+                                               <button class="btn btn-default 
btn-sm" ng-click="startApp(app)">Start</button>
+                                               <button class="btn btn-default 
btn-sm" ng-click="stopApp(app)">Stop</button>
+                                               <button class="btn btn-default 
btn-sm" ng-click="uninstallApp(app)">Uninstall</button>
+                                       </div>
+                                       <div class="btn-group btn-group-xs" 
ng-if="!app.installed">
+                                               <button class="btn btn-primary 
btn-sm" ng-click="installApp(app)">Install Application</button>
+                                       </div>
+                               </td>
+                       </tr>
+               </tbody>
+       </table>
+</div>
+
+
+
+<!-- Modal: Application information -->
+<div class="modal fade" role="dialog" id="appMDL">
+       <div class="modal-dialog modal-lg">
+               <div class="modal-content">
+                       <div class="modal-header">
+                               <button type="button" class="close" 
data-dismiss="modal" aria-label="Close">
+                                       <span aria-hidden="true">×</span>
+                               </button>
+                               <h4 class="modal-title" 
id="myModalLabel">{{application.name}}</h4>
+                       </div>
+                       <div class="modal-body">
+                               <ul class="nav nav-tabs">
+                                       <li class="active"><a 
href="[data-id='install']" data-toggle="tab">Install</a></li>
+                                       <li><a href="[data-id='uninstall']" 
data-toggle="tab">Uninstall</a></li>
+                               </ul>
+                               <div class="tab-content">
+                                       <div class="tab-pane active" 
data-id="install">
+                                               <pre 
ng-bind-html="installHTML"></pre>
+                                       </div>
+                                       <div class="tab-pane" 
data-id="uninstall">
+                                               <pre 
ng-bind-html="uninstallHTML"></pre>
+                                       </div>
+                               </div>
+                       </div>
+                       <div class="modal-footer">
+                               <button type="button" class="btn btn-default" 
data-dismiss="modal">Close</button>
+                       </div>
+               </div>
+       </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/integration/siteList.html
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/webapp/app/dev/partials/integration/siteList.html 
b/eagle-server/src/main/webapp/app/dev/partials/integration/siteList.html
new file mode 100644
index 0000000..491d902
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/integration/siteList.html
@@ -0,0 +1,60 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="box-body">
+       <table class="table table-bordered table-hover">
+               <thead>
+               <tr>
+                       <th>Site</th>
+                       <th>Description</th>
+                       <th>Enabled Apps</th>
+                       <th width="95">Actions</th>
+               </tr>
+               </thead>
+               <tbody>
+                       <tr ng-repeat="site in Site.list track by $index">
+                               <td>
+                                       <a ui-sref="integration.site({id: 
site.siteId})">
+                                               {{site.siteId}}
+                                               <span 
ng-if="site.siteName">({{site.siteName}})</span>
+                                       </a>
+                               </td>
+                               <td>{{site.description}}</td>
+                               <td>
+                                       <span class="text-muted" 
ng-if="site.applicationList.length === 0">(Nothing installed...)</span>
+                                       <ul class="list-inline no-margin">
+                                               <li ng-repeat="app in 
site.applicationList track by $index">
+                                                       <span class="label 
label-primary">
+                                                               
{{app.descriptor.name}}
+                                                       </span>
+                                               </li>
+                                       </ul>
+                               </td>
+                               <td class="text-center">
+                                       <div class="btn-group btn-group-xs">
+                                               <a class="btn btn-default 
btn-sm" ui-sref="integration.site({id: site.siteId})">Edit</a>
+                                               <button class="btn btn-default 
btn-sm" ng-click="deleteSite(site)">Delete</button>
+                                       </div>
+                               </td>
+                       </tr>
+               </tbody>
+       </table>
+</div>
+<div class="box-footer text-right">
+       <button class="btn btn-primary" ng-click="newSite()">New Site</button>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/integration/streamList.html
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/webapp/app/dev/partials/integration/streamList.html 
b/eagle-server/src/main/webapp/app/dev/partials/integration/streamList.html
new file mode 100644
index 0000000..beaf743
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/integration/streamList.html
@@ -0,0 +1,52 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="box-body">
+       <div sort-table="streamList">
+               <table class="table table-bordered table-hover">
+                       <thead>
+                               <tr>
+                                       <th>Stream</th>
+                                       <th>Provider (App)</th>
+                                       <th>Site</th>
+                                       <th>Schema</th>
+                                       <th width="10">Actions</th>
+                               </tr>
+                       </thead>
+                       <tbody>
+                               <tr>
+                                       <td><span class="label 
label-primary">{{item.streamId}}</span></td>
+                                       <td>{{item.appType}}</td>
+                                       <td>{{item.siteId}}</td>
+                                       <td>
+                                               <ul class="no-margin">
+                                                       <li ng-repeat="column 
in item.schema.columns track by $index">
+                                                               
<strong>{{column.name}}</strong>:
+                                                               {{column.type}}
+                                                       </li>
+                                               </ul>
+                                       </td>
+                                       <td>
+                                               <!-- TODO:link with alert -->
+                                               <button class="btn btn-primary 
btn-sm">New Alert</button>
+                                       </td>
+                               </tr>
+                       </tbody>
+               </table>
+       </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/partials/setup.html
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/partials/setup.html 
b/eagle-server/src/main/webapp/app/dev/partials/setup.html
new file mode 100644
index 0000000..64944fb
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/setup.html
@@ -0,0 +1,46 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<h2>Welcome for using Apache Eagle!</h2>
+<p class="lead">
+       As the first installation, please create a <code>SITE</code>.
+       (A site is a cluster/service which you want to monitor, as a quick 
start, you could use <code>sandbox</code> by default)
+</p>
+
+<div class="box box-primary">
+       <div class="box-header with-border">
+               <h3 class="box-title">Create new site</h3>
+       </div>
+       <div class="box-body">
+               <div class="form-group">
+                       <label>* Site Id</label>
+                       <input class="form-control" placeholder="Site id should 
be unique" ng-model="siteId">
+               </div>
+               <div class="form-group">
+                       <label>Display Name</label>
+                       <input class="form-control" placeholder="Site display 
name in UI" ng-model="siteName">
+               </div>
+               <div class="form-group">
+                       <label>Description</label>
+                       <textarea class="form-control" placeholder="Description 
about current site" ng-model="description" rows="5"></textarea>
+               </div>
+       </div>
+       <div class="box-footer text-right">
+               <button class="btn btn-primary" ng-click="createSite()" 
ng-disabled="site === '' || lock">Next</button>
+       </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/public/css/animation.css
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/css/animation.css 
b/eagle-server/src/main/webapp/app/dev/public/css/animation.css
new file mode 100644
index 0000000..cbf4973
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/public/css/animation.css
@@ -0,0 +1,47 @@
+@CHARSET "UTF-8";
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#content > [ui-view].ng-enter,
+#content > [ui-view].ng-leave {
+       position: absolute;
+       left: 0;
+       right: 0;
+       -webkit-transition: all .5s ease-in-out;
+       -moz-transition: all .5s ease-in-out;
+       -o-transition: all .5s ease-in-out;
+       transition: all .3s ease-in-out;
+}
+
+#content > [ui-view].ng-enter {
+       opacity: 0;
+}
+
+#content > [ui-view].ng-enter-active {
+       opacity: 1;
+}
+
+#content > [ui-view].ng-leave {
+       opacity: 1;
+       transform:translate3d(0, 0, 0);
+}
+
+#content > [ui-view].ng-leave-active {
+       opacity: 0;
+       transform:translate3d(20%, 0, 0);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/public/css/main.css
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/css/main.css 
b/eagle-server/src/main/webapp/app/dev/public/css/main.css
new file mode 100644
index 0000000..83f9b14
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/public/css/main.css
@@ -0,0 +1,317 @@
+@CHARSET "UTF-8";
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+a {
+       cursor: pointer;
+}
+
+/* ========================================================================
+ * =                               Side Bar                               =
+ * ======================================================================== */
+.sidebar-mini.sidebar-collapse .main-header .logo > .logo-mini > img {
+       max-height: 30px;
+}
+
+.main-sidebar .customize-panel {
+       padding: 10px;
+}
+
+.sidebar-collapse .main-sidebar .customize-panel {
+       display: none;
+}
+
+.main-sidebar .customize-panel .btn-group,
+.main-sidebar .customize-panel .btn-group button,
+.main-sidebar .customize-panel .btn-group .dropdown-menu {
+       width: 100%;
+}
+
+.main-sidebar .customize-panel .btn-group button {
+       padding: 5px;
+       background: #374850;
+       border: none;
+       overflow-x: hidden;
+}
+.main-sidebar .customize-panel .btn-group.open button{
+       background: #455b63;
+}
+
+.main-sidebar .customize-panel .btn-group button .caret {
+       position: absolute;
+       right: 10px;
+       top: 13px;
+}
+
+/* ========================================================================
+ * =                                 Main                                 =
+ * ======================================================================== */
+#content {
+       position: relative;
+}
+
+/* ========================================================================
+ * =                                 Grid                                 =
+ * ======================================================================== */
+
+@media (min-width: 1200px) {
+       .row.flex {
+               display: -webkit-box;
+               display: -webkit-flex;
+               display: -ms-flexbox;
+               display: flex;
+               flex-wrap: wrap;
+       }
+
+       .row.flex > [class*='col-'] {
+               display: -webkit-box;
+               display: -webkit-flex;
+               display: -ms-flexbox;
+               display: flex;
+               flex-direction: column;
+               flex-wrap: nowrap;
+       }
+
+       .row.flex > [class*='col-'] > * {
+               flex: auto;
+       }
+}
+
+.row.border-split > div {
+       border: 1px solid #f4f4f4;
+}
+
+.no-padding > .row.border-split {
+       margin-left: 0;
+       margin-right: 0;
+}
+
+/* ========================================================================
+ * =                                Table                                 =
+ * ======================================================================== */
+table .info-wrapper .info-detail {
+       display: none;
+}
+
+table .info-wrapper:hover .info-detail {
+       display: table-row;
+}
+
+table ul {
+       padding: 0 0 0 20px;
+}
+
+table.table pre {
+       white-space: pre-wrap;
+       margin: 0;
+}
+
+table.table pre.inline {
+       padding: 0;
+       border: 0;
+       border-radius: 0;
+       background: transparent;
+}
+
+table.table.table-sm th,
+table.table.table-sm td {
+       padding: 3px 5px;
+       line-height: 120%;
+}
+
+/* ========================================================================
+ * =                              Step Guide                              =
+ * ======================================================================== */
+ul.stepGuide {
+       padding: 0;
+       position: relative;
+       display: inline-block;
+}
+ul.stepGuide:before {
+       display: block;
+       height: 6px;
+       background: #f4f4f4;
+       content: "";
+       position: absolute;
+       top: 12px;
+       left: 5px;
+       right: 5px;
+}
+
+ul.stepGuide li {
+       position: relative;
+       display: inline-block;
+       vertical-align: top;
+       text-align: center;
+}
+ul.stepGuide li:not(:first-child) {
+       margin-left: 15px;
+}
+
+ul.stepGuide li > .icon {
+       display: inline-block;
+       width: 30px;
+       height: 30px;
+       line-height: 30px;
+       text-align: center;
+       background: #f4f4f4;
+       border-radius: 100%;
+}
+
+ul.stepGuide li > .title {
+       display: block;
+}
+
+/* ========================================================================
+ * =                                 Box                                  =
+ * ======================================================================== */
+.box .box-title .label {
+       font-size: 12px;
+       padding: 1px 7px;
+}
+
+.small-box {
+       position: relative;
+       padding-bottom: 30px;
+}
+
+.small-box > .inner a {
+       color: #FFFFFF;
+}
+
+.small-box > .inner a:hover {
+       text-decoration: underline;
+}
+
+.small-box > .small-box-footer {
+       position: absolute;
+       left: 0;
+       right: 0;
+       bottom: 0;
+}
+
+       /* 
========================================================================
+     * =                                 Tab                                  =
+     * 
======================================================================== */
+.tab-content.keepContent > .tab-pane {
+       display: block;
+}
+
+.tab-content.keepContent > .tab-pane:not(.active) {
+       max-height: 0;
+       overflow: hidden;
+}
+
+/* ========================================================================
+ * =                                Modal                                 =
+ * ======================================================================== */
+.modal .nav-tabs li {
+       border-top: 3px solid transparent;
+}
+
+.modal .nav-tabs li.active {
+       border-top-color: #3c8dbc;
+}
+
+.modal .nav-tabs li a {
+       padding: 8px 15px;
+       border-radius: 0;
+       margin: 0;
+}
+
+.modal .nav-tabs li a,
+.modal .nav-tabs li.active a,
+.modal .nav-tabs li:hover a {
+       border-top: 0;
+}
+
+.modal .tab-content {
+       padding-top: 10px;
+}
+
+/* ========================================================================
+ * =                               Call out                               =
+ * ======================================================================== */
+.callout p,
+.callout span {
+       color: #FFF;
+}
+
+/* ========================================================================
+ * =                                 list                                 =
+ * ======================================================================== */
+.list-inline > li > .label {
+       margin-bottom: 2px;
+       display: inline-block;
+}
+
+/* ========================================================================
+ * =                                 label                                =
+ * ======================================================================== */
+.label.label-sm {
+       padding: .1em .4em .2em;
+}
+
+/* ========================================================================
+ * =                               Timeline                               =
+ * ======================================================================== */
+.nav-tabs-custom .timeline li .timeline-item {
+       background: #f4f4f4;
+}
+
+/* ========================================================================
+ * =                                Widget                                =
+ * ======================================================================== */
+@media (min-width: 1200px) {
+       .row.flex div[widget] {
+               height: 100%;
+       }
+}
+
+/* ========================================================================
+ * =                                 Misc                                 =
+ * ======================================================================== */
+.ng-hide.ng-hide-animate.no-animate {
+       -webkit-transition: none !important;
+       transition: none !important;
+}
+
+.ng-hide.ng-hide-animate.no-animate {
+       display: none;
+}
+
+.text-break {
+       word-break:break-all;
+}
+
+.text-no-break {
+       white-space: nowrap;
+}
+
+.no-select {
+       -webkit-touch-callout: none;
+       -webkit-user-select: none;
+       -khtml-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+.bsc-datepicker {
+       z-index: 2000;
+}

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/public/css/sortTable.css
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/css/sortTable.css 
b/eagle-server/src/main/webapp/app/dev/public/css/sortTable.css
new file mode 100644
index 0000000..529eb1a
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/public/css/sortTable.css
@@ -0,0 +1,61 @@
+@CHARSET "UTF-8";
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+[sort-table] .tool-container .search-box {
+       margin: 0 0 10px 0;
+       position: relative;
+       max-width: 250px;
+       float: left;
+}
+
+[sort-table] .tool-container .search-box input {
+       padding-left: 28px;
+}
+
+[sort-table] .tool-container .search-box .fa-search {
+       pointer-events:none;
+       position: absolute;
+       top: 8px;
+       left: 8px;
+       opacity: 0.5;
+}
+
+[sort-table] .tool-container .page-size {
+       float: right;
+}
+
+[sort-table] .tool-container .page-size select {
+       width: initial;
+       display: inline-block;
+       margin: 0 7px;
+       height: 26px;
+       padding: 0 5px;
+}
+
+[sort-table] .fa.sort-mark {
+       float: right;
+       margin-top: 3px;
+       pointer-events: none;
+       color: #AAA;
+}
+
+[sort-table] .navigation-bar .pagination {
+       float: right;
+       margin-top: 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/public/images/favicon.png
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/images/favicon.png 
b/eagle-server/src/main/webapp/app/dev/public/images/favicon.png
new file mode 100644
index 0000000..3bede2a
Binary files /dev/null and 
b/eagle-server/src/main/webapp/app/dev/public/images/favicon.png differ

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/public/images/favicon_white.png
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/webapp/app/dev/public/images/favicon_white.png 
b/eagle-server/src/main/webapp/app/dev/public/images/favicon_white.png
new file mode 100644
index 0000000..9879e92
Binary files /dev/null and 
b/eagle-server/src/main/webapp/app/dev/public/images/favicon_white.png differ

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/public/js/app.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/app.js 
b/eagle-server/src/main/webapp/app/dev/public/js/app.js
new file mode 100644
index 0000000..4ec77d9
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/public/js/app.js
@@ -0,0 +1,311 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var app = {};
+
+(function() {
+       'use strict';
+
+       $(document).on("APPLICATION_READY", function (event, register) {
+               console.info("[Eagle] Angular bootstrap...");
+
+               var STATE_NAME_MATCH = /^[^.]*/;
+               var state_next;
+               var state_current;
+               var param_next;
+               var param_current;
+
+               // 
======================================================================================
+               // =                                   Initialization           
                        =
+               // 
======================================================================================
+               var eagleApp = angular.module('eagleApp', ['ngRoute', 
'ngAnimate', 'ui.router', 'eagleControllers', 
'eagle.service'].concat(register.appList));
+
+               // 
======================================================================================
+               // =                                   Router config            
                        =
+               // 
======================================================================================
+               function routeResolve(config) {
+                       var resolve = {};
+                       if(config === false) return resolve;
+
+                       config = $.extend({
+                               auth: true,
+                               site: true,
+                               application: true
+                       }, config);
+
+                       if(config.auth) {
+                               // TODO: need auth module
+                       }
+
+                       resolve.Site = function (Site) {
+                               return Site.getPromise(config);
+                       };
+
+                       resolve.Application = function (Application) {
+                               return Application.getPromise();
+                       };
+
+                       resolve.Time = function (Time) {
+                               return Time.getPromise(config, state_next, 
param_next);
+                       };
+
+                       return resolve;
+               }
+
+               eagleApp.config(function ($stateProvider, $urlRouterProvider, 
$httpProvider, $animateProvider) {
+                       $urlRouterProvider.otherwise("/");
+                       $stateProvider
+                       // ================================== Home 
==================================
+                               .state('home', {
+                                       url: "/",
+                                       templateUrl: "partials/home.html?_=" + 
window._TRS(),
+                                       controller: "homeCtrl",
+                                       resolve: routeResolve()
+                               })
+                               .state('setup', {
+                                       url: "/setup",
+                                       templateUrl: "partials/setup.html?_=" + 
window._TRS(),
+                                       controller: "setupCtrl",
+                                       resolve: routeResolve({ site: false, 
application: false })
+                               })
+                               // ================================= Alerts 
=================================
+                               .state('alert', {
+                                       abstract: true,
+                                       url: "/alert/",
+                                       templateUrl: 
"partials/alert/main.html?_=" + window._TRS(),
+                                       controller: "alertCtrl",
+                                       resolve: routeResolve(false)
+                               })
+                               .state('alert.list', {
+                                       url: "",
+                                       templateUrl: 
"partials/alert/list.html?_=" + window._TRS(),
+                                       controller: "alertListCtrl",
+                                       resolve: routeResolve()
+                               })
+                               .state('alert.policyList', {
+                                       url: "policyList",
+                                       templateUrl: 
"partials/alert/policyList.html?_=" + window._TRS(),
+                                       controller: "policyListCtrl",
+                                       resolve: routeResolve()
+                               })
+                               .state('alert.policyCreate', {
+                                       url: "policyCreate",
+                                       templateUrl: 
"partials/alert/policyEdit.html?_=" + window._TRS(),
+                                       controller: "policyCreateCtrl",
+                                       resolve: routeResolve()
+                               })
+                               .state('alert.policyEdit', {
+                                       url: "policyEdit/{name}",
+                                       templateUrl: 
"partials/alert/policyEdit.html?_=" + window._TRS(),
+                                       controller: "policyEditCtrl",
+                                       resolve: routeResolve()
+                               })
+                               // =============================== Integration 
==============================
+                               .state('integration', {
+                                       abstract: true,
+                                       url: "/integration/",
+                                       templateUrl: 
"partials/integration/main.html?_=" + window._TRS(),
+                                       controller: "integrationCtrl",
+                                       resolve: routeResolve(false)
+                               })
+                               .state('integration.siteList', {
+                                       url: "siteList",
+                                       templateUrl: 
"partials/integration/siteList.html?_=" + window._TRS(),
+                                       controller: "integrationSiteListCtrl",
+                                       resolve: routeResolve({ application: 
false })
+                               })
+                               .state('integration.site', {
+                                       url: "site/:id",
+                                       templateUrl: 
"partials/integration/site.html?_=" + window._TRS(),
+                                       controller: "integrationSiteCtrl",
+                                       resolve: routeResolve({ application: 
false })
+                               })
+                               .state('integration.applicationList', {
+                                       url: "applicationList",
+                                       templateUrl: 
"partials/integration/applicationList.html?_=" + window._TRS(),
+                                       controller: 
"integrationApplicationListCtrl",
+                                       resolve: routeResolve({ application: 
false })
+                               })
+                               .state('integration.streamList', {
+                                       url: "streamList",
+                                       templateUrl: 
"partials/integration/streamList.html?_=" + window._TRS(),
+                                       controller: "integrationStreamListCtrl",
+                                       resolve: routeResolve()
+                               })
+                               // ================================== Site 
==================================
+                               .state('site', {
+                                       url: "/site/:siteId",
+                                       templateUrl: "partials/home.html?_=" + 
window._TRS(),
+                                       controller: "siteCtrl",
+                                       resolve: routeResolve()
+                               })
+                       ;
+
+                       // =========================== Application States 
===========================
+                       $.each(register.routeList, function (i, route) {
+                               var config = $.extend({}, route.config);
+
+                               var resolve = {};
+                               var resolveConfig = {};
+                               if(route.config.resolve) {
+                                       $.each(route.config.resolve, function 
(key, value) {
+                                               if (typeof value === 
"function") {
+                                                       resolve[key] = value;
+                                               } else {
+                                                       resolveConfig[key] = 
value;
+                                               }
+                                       });
+                               }
+                               config.resolve = 
$.extend(routeResolve(resolveConfig), resolve);
+
+                               $stateProvider.state(route.state, config);
+                       });
+
+                       $httpProvider.interceptors.push(function($q) {
+                               function eagleRequestHandle(res) {
+                                       var data = res.data || {
+                                               exception: "",
+                                               message: ""
+                                       };
+                                       if(res.status === -1) {
+                                               $.dialog({
+                                                       title: "AJAX Failed",
+                                                       content: $("<pre>")
+                                                               .text("url:\n" 
+ common.getValueByPath(res, ["config", "url"]))
+                                               });
+                                       } else if(data.success === false || 
res.status === 404) {
+                                               $.dialog({
+                                                       title: "AJAX Error",
+                                                       content: $("<pre>")
+                                                               .text(
+                                                                       
"url:\n" + common.getValueByPath(res, ["config", "url"]) + "\n\n" +
+                                                                       
"status:\n" + res.status + "\n\n" +
+                                                                       
"exception:\n" + data.exception + "\n\n" +
+                                                                       
"message:\n" + data.message
+                                                               )
+                                               });
+                                       }
+                                       return res;
+                               }
+
+                               return {
+                                       response: eagleRequestHandle,
+                                       responseError: function(res) {
+                                               return 
$q.reject(eagleRequestHandle(res));
+                                       }
+                               };
+                       });
+               });
+
+               // 
======================================================================================
+               // =                                   Main Controller          
                        =
+               // 
======================================================================================
+               eagleApp.controller('MainCtrl', function ($scope, $wrapState, 
$urlRouter, PageConfig, Portal, Widget, Entity, Site, Application, UI, Time) {
+                       window._WrapState = $scope.$wrapState = $wrapState;
+                       window._PageConfig = $scope.PageConfig = PageConfig;
+                       window._Portal = $scope.Portal = Portal;
+                       window._Widget = $scope.Widget = Widget;
+                       window._Entity = $scope.Entity = Entity;
+                       window._Site = $scope.Site = Site;
+                       window._Application = $scope.Application = Application;
+                       window._UI = $scope.UI = UI;
+                       window._Time = $scope.Time = Time;
+                       $scope.common = common;
+
+                       Object.defineProperty(window, "scope", {
+                               get: function () {
+                                       return angular.element("#content 
.ng-scope").scope();
+                               }
+                       });
+
+                       // ============================== Route Update 
==============================
+                       $scope.$on('$stateChangeStart', function (event, next, 
nextParam, current, currentParam) {
+                               console.log("[Switch] current ->", current, 
currentParam);
+                               console.log("[Switch] next ->", next, 
nextParam);
+
+                               state_next = next || {};
+                               state_current = current || {};
+                               param_next = nextParam;
+                               param_current = currentParam;
+
+                               var currentName = (current || {}).name || "";
+                               var nextName = (next || {}).name || "";
+
+                               // Page initialization
+                               if(currentName.match(STATE_NAME_MATCH)[0] !== 
nextName.match(STATE_NAME_MATCH)[0]) {
+                                       PageConfig.reset();
+                               }
+                       });
+
+                       // ================================ Function 
================================
+                       // Get side bar navigation item class
+                       $scope.getNavClass = function (portal) {
+                               var path = (portal.path || "").replace(/^#/, 
'');
+
+                               if ($wrapState.path() === path) {
+                                       return "active";
+                               } else {
+                                       return "";
+                               }
+                       };
+
+                       // Customize time range
+                       $scope.customizeTimeRange = function () {
+                               
$("#eagleStartTime").val(Time.format("startTime"));
+                               $("#eagleEndTime").val(Time.format("endTime"));
+                               $("#eagleTimeRangeMDL").modal();
+                       };
+
+                       $scope.setLastDuration = function (hours) {
+                               var endTime = new Time();
+                               var startTime = endTime.clone().subtract(hours, 
"hours");
+                               Time.timeRange(startTime, endTime);
+                       };
+
+                       $scope.updateTimeRange = function () {
+                               var startTime = 
Time.verifyTime($("#eagleStartTime").val());
+                               var endTime = 
Time.verifyTime($("#eagleEndTime").val());
+                               if(startTime && endTime) {
+                                       Time.timeRange(startTime, endTime);
+                                       $("#eagleTimeRangeMDL").modal("hide");
+                               } else {
+                                       alert("Time range not validate");
+                               }
+                       };
+
+                       // ================================== Init 
==================================
+                       $.each(register.portalList, function (i, config) {
+                               Portal.register(config.portal, config.isSite);
+                       });
+
+                       $.each(register.widgetList, function (i, config) {
+                               Widget.register(config.widget, config.isSite);
+                       });
+               });
+
+               // 
======================================================================================
+               // =                                      Bootstrap             
                        =
+               // 
======================================================================================
+               //noinspection JSCheckFunctionSignatures
+               angular.element(document).ready(function() {
+                       console.info("[Eagle] UI start...");
+                       //noinspection JSCheckFunctionSignatures
+                       angular.bootstrap(document, ['eagleApp']);
+               });
+       });
+})();

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/public/js/common.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/common.js 
b/eagle-server/src/main/webapp/app/dev/public/js/common.js
new file mode 100644
index 0000000..9f5c4b1
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/public/js/common.js
@@ -0,0 +1,387 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       'use strict';
+
+       var scope = {};
+       if(typeof window != 'undefined') {
+               scope = window;
+       } else if(typeof self != 'undefined') {
+               scope = self;
+       }
+       var common = scope.common = {};
+
+       // ============================ Common ============================
+       common.template = function (str, list) {
+               $.each(list, function(key, value) {
+                       var _regex = new RegExp("\\$\\{" + key + "\\}", "g");
+                       str = str.replace(_regex, value);
+               });
+               return str;
+       };
+
+       common.getValueByPath = function (unit, path, defaultValue) {
+               if(unit === null || unit === undefined) throw "Unit can't be 
empty!";
+               if(path === "" || path === null || path === undefined) return 
unit;
+
+               if(typeof path === "string") {
+                       path = path.replace(/\[(\d+)\]/g, ".$1").replace(/^\./, 
"").split(/\./);
+               }
+               for(var i = 0 ; i < path.length ; i += 1) {
+                       unit = unit[path[i]];
+                       if(unit === null || unit === undefined) {
+                               unit = null;
+                               break;
+                       }
+               }
+               if(unit === null && defaultValue !== undefined) {
+                       unit = defaultValue;
+               }
+               return unit;
+       };
+
+       common.setValueByPath = function(unit, path, value) {
+               if(!unit || typeof path !== "string" || path === "") throw 
"Unit or path can't be empty!";
+
+               var _inArray = false;
+               var _end = 0;
+               var _start = 0;
+               var _unit = unit;
+
+               function _nextPath(array) {
+                       var _key = path.slice(_start, _end);
+                       if(_inArray) {
+                               _key = _key.slice(0, -1);
+                       }
+                       if(!_unit[_key]) {
+                               if(array) {
+                                       _unit[_key] = [];
+                               } else {
+                                       _unit[_key] = {};
+                               }
+                       }
+                       _unit = _unit[_key];
+               }
+
+               for(; _end < path.length ; _end += 1) {
+                       if(path[_end] === ".") {
+                               _nextPath(false);
+                               _start = _end + 1;
+                               _inArray = false;
+                       } else if(path[_end] === "[") {
+                               _nextPath(true);
+                               _start = _end + 1;
+                               _inArray = true;
+                       }
+               }
+
+               _unit[path.slice(_start, _inArray ? -1 : _end)] = value;
+
+               return unit;
+       };
+
+       common.parseJSON = function (str, defaultVal) {
+               try {
+                       str = (str + "").trim();
+                       if(Number(str).toString() === str) throw "Number 
format";
+                       return JSON.parse(str);
+               } catch(err) {
+                       if(defaultVal === undefined) {
+                               console.warn("Can't parse JSON: " + str);
+                       }
+               }
+               return defaultVal === undefined ? null : defaultVal;
+       };
+
+       common.stringify = function(json) {
+               return JSON.stringify(json, function(key, value) {
+                       if(/^(_|\$)/.test(key)) return undefined;
+                       return value;
+               });
+       };
+
+       common.isEmpty = function(val) {
+               if($.isArray(val)) {
+                       return val.length === 0;
+               } else {
+                       return val === null || val === undefined;
+               }
+       };
+
+       common.extend = function(target, origin) {
+               $.each(origin, function(key, value) {
+                       if(/^(_|\$)/.test(key)) return;
+
+                       target[key] = value;
+               });
+               return target;
+       };
+
+       function merge(obj1, obj2) {
+               $.each(obj2, function (key, value) {
+                       var oriValue = obj1[key];
+
+                       if(typeof oriValue === "object" && typeof value === 
"object" && !common.isEmpty(value)) {
+                               merge(oriValue, value);
+                       } else {
+                               obj1[key] = value;
+                       }
+               });
+       }
+
+       common.merge = function (mergedObj) {
+               for(var i = 1 ; i < arguments.length ; i += 1) {
+                       var obj = arguments[i];
+                       merge(mergedObj, obj);
+               }
+
+               return mergedObj;
+       };
+
+       // ============================ String ============================
+       common.string = {};
+       common.string.safeText = function (str) {
+               return str
+                       .replace(/&/g, '&amp;')
+                       .replace(/</g, '&lt;')
+                       .replace(/>/g, '&gt;');
+       };
+
+       common.string.capitalize = function (str) {
+               return (str + "").replace(/\b\w/g, function(match) {
+                       return match.toUpperCase();
+               });
+       };
+
+       common.string.preFill = function (str, key, len) {
+               str = str + "";
+               len = len || 2;
+               while(str.length < len) {
+                       str = key + str;
+               }
+               return str;
+       };
+
+       // ============================ Array =============================
+       common.array = {};
+
+       common.array.findIndex = function(val, list, path, findAll, 
caseSensitive) {
+               var _list = [];
+               val = caseSensitive === false ? (val + "").toUpperCase() : val;
+
+               for(var i = 0 ; i < list.length ; i += 1) {
+                       var unit = list[i];
+                       var _val = common.getValueByPath(unit, path);
+                       _val = caseSensitive === false ? (_val + 
"").toUpperCase() : _val;
+
+                       if(_val === val) {
+                               if(!findAll) return i;
+                               _list.push(i);
+                       }
+               }
+
+               return findAll ? _list: -1;
+       };
+
+       common.array.find = function(val, list, path, findAll, caseSensitive) {
+               var index = common.array.findIndex(val, list, path, findAll, 
caseSensitive);
+
+               if(findAll) {
+                       return $.map(index, function (index) {
+                               return list[index];
+                       });
+               } else {
+                       return index === -1 ? null : list[index];
+               }
+       };
+
+       common.array.minus = function (list1, list2, path1, path2) {
+               if(arguments.length === 3) path2 = path1;
+               var list = [];
+               $.each(list1, function (i, item) {
+                       var val1 = common.getValueByPath(item, path1);
+                       if(!common.array.find(val1, list2, path2)) {
+                               list.push(item);
+                       }
+               });
+               return list;
+       };
+
+       common.array.doSort = function (list, path, asc, sortList) {
+               var sortFunc;
+               sortList = sortList || [];
+
+               if(asc !== false) {
+                       sortFunc = function (obj1, obj2) {
+                               var val1 = common.getValueByPath(obj1, path);
+                               var val2 = common.getValueByPath(obj2, path);
+
+                               var index1 = common.array.findIndex(val1, 
sortList);
+                               var index2 = common.array.findIndex(val2, 
sortList);
+
+                               if(index1 !== -1 && index2 === -1) {
+                                       return -1;
+                               } else if(index1 == -1 && index2 !== -1) {
+                                       return 1;
+                               } else if(index1 !== -1 && index2 !== -1) {
+                                       return index1 - index2;
+                               }
+
+                               if (val1 === val2) {
+                                       return 0;
+                               } else if (val1 === null || val1 === undefined 
|| val1 < val2) {
+                                       return -1;
+                               }
+                               return 1;
+                       };
+               } else {
+                       sortFunc = function (obj1, obj2) {
+                               var val1 = common.getValueByPath(obj1, path);
+                               var val2 = common.getValueByPath(obj2, path);
+
+                               var index1 = common.array.findIndex(val1, 
sortList);
+                               var index2 = common.array.findIndex(val2, 
sortList);
+
+                               if(index1 !== -1 && index2 === -1) {
+                                       return -1;
+                               } else if(index1 == -1 && index2 !== -1) {
+                                       return 1;
+                               } else if(index1 !== -1 && index2 !== -1) {
+                                       return index1 - index2;
+                               }
+
+                               if (val1 === val2) {
+                                       return 0;
+                               } else if (val1 === null || val1 === undefined 
|| val1 < val2) {
+                                       return 1;
+                               }
+                               return -1;
+                       };
+               }
+
+               return list.sort(sortFunc);
+       };
+
+       // =========================== Deferred ===========================
+       common.deferred = {};
+
+
+       common.deferred.all = function (deferredList) {
+               var deferred = $.Deferred();
+               var successList = [];
+               var failureList = [];
+               var hasFailure = false;
+               var rest = deferredList.length;
+               function doCheck() {
+                       rest -= 1;
+                       if(rest === 0) {
+                               if(hasFailure) {
+                                       deferred.reject(failureList);
+                               } else {
+                                       deferred.resolve(successList);
+                               }
+                       }
+               }
+
+               $.each(deferredList, function (i, deferred) {
+                       if(deferred && deferred.then) {
+                               deferred.then(function (data) {
+                                       successList[i] = data;
+                               }, function (data) {
+                                       failureList[i] = data;
+                                       hasFailure = true;
+                               }).always(doCheck);
+                       } else {
+                               successList[i] = deferred;
+                               doCheck();
+                       }
+               });
+
+               return deferred;
+       };
+
+       // ============================ Number ============================
+       common.number = {};
+
+       common.number.isNumber = function (num) {
+               return typeof num === "number" && !isNaN(num);
+       };
+
+       common.number.toFixed = function (num, fixed) {
+               if(!common.number.isNumber(num)) return "-";
+               num = Number(num);
+               return num.toFixed(fixed || 0);
+       };
+
+       common.number.format = function (num, fixed) {
+               if(!common.number.isNumber(num)) return "-";
+               return common.number.toFixed(num, 
fixed).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
+       };
+
+       common.number.abbr = function (number, isByte, digits) {
+               digits = digits || 2;
+               var decPlaces = Math.pow(10, digits);
+               var abbrev = isByte ? ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 
'ZB', 'YB'] : ['K', 'M', 'B', 'T', 'Q'];
+               var base = isByte ? 1024 : 1000;
+               var sign = number < 0 ? -1 : 1;
+               var unit = '';
+               number = Math.abs(number);
+
+               for(var i = abbrev.length - 1; i >= 0; i--) {
+                       var size = Math.pow(base, i + 1);
+                       if(size <= number) {
+                               number = Math.round(number * decPlaces / size) 
/ decPlaces;
+                               if((number === base) && (i < abbrev.length - 
1)) {
+                                       number = 1;
+                                       i++;
+                               }
+                               unit = abbrev[i];
+                               break;
+                       }
+               }
+               unit = unit ? unit : "";
+               return (number * sign).toFixed(digits) + unit;
+       };
+
+       common.number.compare = function (num1, num2) {
+               if(!common.number.isNumber(num1) || 
!common.number.isNumber(num2)) return "-";
+               if(num1 === 0) return 'N/A';
+               return (num2 - num1) / num1;
+       };
+
+       common.number.inRange = function (rangList, num) {
+               for(var i = 0 ; i < rangList.length - 1 ; i += 1) {
+                       var start = rangList[i];
+                       var end = rangList[i + 1];
+                       if(start <= num && num < end) return i;
+               }
+               return rangList.length - 1;
+       };
+
+       common.number.sum = function (list, path) {
+               var total = 0;
+               $.each(list, function (i, obj) {
+                       var value = common.getValueByPath(obj, path);
+                       if(typeof value === "number" && !isNaN(value)) {
+                               total += value;
+                       }
+               });
+               return total;
+       };
+})();

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/public/js/components/chart.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/components/chart.js 
b/eagle-server/src/main/webapp/app/dev/public/js/components/chart.js
new file mode 100644
index 0000000..99f74d5
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/public/js/components/chart.js
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function() {
+       'use strict';
+
+       var eagleComponents = angular.module('eagle.components');
+
+       eagleComponents.service('Chart', function () {
+               return {
+                       color: [ "#0073b7", "#dd4b39", "#00a65a", "#f39c12", 
"#605ca8", "#001F3F", "#39CCCC", "#D81B60", "#3c8dbc", "#f56954", "#00c0ef", 
"#3D9970", "#FF851B"  , "#01FF70", "#F012BE"],
+                       //color: ['#4285f4', '#c23531','#2f4554', '#61a0a8', 
'#d48265', '#91c7ae','#749f83',  '#ca8622', '#bda29a','#6e7074', '#546570', 
'#c4ccd3'],
+                       charts: {}
+               };
+       });
+
+       eagleComponents.directive('chart', function(Chart) {
+               var charts = Chart.charts;
+
+               function chartResize() {
+                       setTimeout(function () {
+                               $.each(charts, function (id, chart) {
+                                       chart.resize();
+                               });
+                       }, 310);
+               }
+
+               $(window).resize(chartResize);
+               $("body").on("expanded.pushMenu collapsed.pushMenu", 
chartResize);
+
+               return {
+                       restrict: 'AE',
+                       scope: {
+                               title: "@?title",
+                               series: "=",
+                               category: "=?category",
+                               categoryFunc: "=?categoryFunc",
+                               xTitle: "@?xTitle",
+                               yTitle: "@?yTitle",
+
+                               option: "=?option",
+
+                               click: "=?ngClick",
+
+                               chart: "@?chart"
+                       },
+                       controller: function ($scope, $element, $attrs, Time) {
+                               var i;
+                               var lastTooltipEvent;
+                               var chart = echarts.init($element[0]);
+                               charts[chart.id] = chart;
+
+                               function refreshChart() {
+                                       var maxYAxis = 0;
+                                       var legendList = [];
+                                       var categoryList = $scope.category ? 
$scope.category : [];
+
+                                       var seriesList = $.map($scope.series || 
[], function (series, id) {
+                                               if(id === 0 && 
!$scope.category) {
+                                                       //var preDate = -1;
+                                                       categoryList = 
$.map(series.data, function (point) {
+                                                               /*ivar time = 
new Time(point.x);
+                                                               f(preDate !== 
time.date()) {
+                                                                       preDate 
= time.date();
+                                                                       return 
Time.format(point.x, "MMM.D HH:mm");
+                                                               }*/
+                                                               
if($scope.categoryFunc) {
+                                                                       return 
$scope.categoryFunc(point.x);
+                                                               }
+                                                               return 
Time.format(point.x, "HH:mm");
+                                                       });
+                                               }
+
+                                               legendList.push(series.name);
+                                               if(series.yAxisIndex) maxYAxis 
= Math.max(series.yAxisIndex, maxYAxis);
+
+                                               return $.extend({}, series, {
+                                                       data: $scope.category ? 
series.data : $.map(series.data, function (point) {
+                                                               return point.y;
+                                                       })
+                                               });
+                                       });
+
+                                       var yAxis = [];
+                                       for(i = 0 ; i <= maxYAxis ; i += 1) {
+                                               yAxis.push({
+                                                       name: $scope.yTitle,
+                                                       type: "value"
+                                               });
+                                       }
+
+                                       var option = {
+                                               color: Chart.color.concat(),
+                                               title: [{text: $scope.title}],
+                                               tooltip: {trigger: 'axis'},
+                                               legend: [{
+                                                       data: legendList
+                                               }],
+                                               grid: {
+                                                       top: '30',
+                                                       left: '0',
+                                                       right: '0',
+                                                       bottom: '0',
+                                                       containLabel: true
+                                               },
+                                               xAxis: {
+                                                       name: $scope.xTitle,
+                                                       type: 'category',
+                                                       data: categoryList,
+                                                       axisTick: { show: false 
}
+                                               },
+                                               yAxis: yAxis,
+                                               series: seriesList
+                                       };
+
+                                       if($scope.option) {
+                                               option = common.merge(option, 
$scope.option);
+                                       }
+
+                                       chart.setOption(option);
+                               }
+
+                               // Event handle
+                               var chartClick = false;
+                               chart.on("click", function (e) {
+                                       if($scope.click) {
+                                               if($scope.click(e)) {
+                                                       refreshChart();
+                                               }
+                                       }
+                                       chartClick = true;
+                               });
+
+                               chart.getZr().on('click', function () {
+                                       if(!chartClick && $scope.click) {
+                                               if($scope.click($.extend({
+                                                       componentType: "tooltip"
+                                               }, lastTooltipEvent))) {
+                                                       refreshChart();
+                                               }
+                                       }
+                                       chartClick = false;
+                               });
+
+                               chart.on('showtip', function (e) {
+                                       lastTooltipEvent = e;
+                               });
+
+                               // Insert chart object to parent scope
+                               if($attrs.chart) {
+                                       $scope.$parent.$parent[$attrs.chart] = 
chart;
+                               }
+
+                               chart.refresh = function () {
+                                       refreshChart();
+                               };
+
+                               // Render
+                               refreshChart();
+                               $scope.$watch("series", refreshChart);
+
+                               $scope.$on('$destroy', function() {
+                                       delete charts[chart.id];
+                                       chart.dispose();
+
+                                       delete 
$scope.$parent.$parent[$attrs.chart];
+                               });
+                       },
+                       template: '<div>Loading...</div>',
+                       replace: true
+               };
+       });
+})();

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/afb89794/eagle-server/src/main/webapp/app/dev/public/js/components/main.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/components/main.js 
b/eagle-server/src/main/webapp/app/dev/public/js/components/main.js
new file mode 100644
index 0000000..0c8a54c
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/public/js/components/main.js
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+(function() {
+       'use strict';
+
+       angular.module('eagle.components', []);
+})();

Reply via email to