You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by ma...@apache.org on 2015/05/15 07:21:47 UTC

[18/52] [abbrv] incubator-kylin git commit: show models list page

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/modelDesigner/model_dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_dimensions.html b/webapp/app/partials/modelDesigner/model_dimensions.html
new file mode 100644
index 0000000..9067807
--- /dev/null
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -0,0 +1,354 @@
+<!--
+* 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 ng-controller="ModelDimensionsCtrl">
+
+<!-- Dimensions Summary -->
+<div class="dataTables_wrapper form-inline no-footer">
+    <div class="row">
+        <div class="col-xs-6" ng-if="state.mode=='edit'">
+            <div class="btn-group">
+                <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
+                    <i class="fa fa-plus"></i> Add Dimension <span class="ace-icon fa fa-caret-down icon-on-right"></span>
+                </button>
+                <ul class="dropdown-menu" role="menu">
+                    <li><a ng-click="addDim('normal')">Normal</a></li>
+                    <li><a ng-click="addDim('hierarchy')">Hierarchy</a></li>
+                    <li><a ng-click="addDim('derived')">Derived</a></li>
+                </ul>
+            </div>
+            <button type="button" class="btn btn-default" ng-disabled="!model.fact_table.length"
+                    ng-click="openAutoGenModal()">
+                <i class="fa fa-building-o"></i> Auto Generator
+            </button>
+        </div>
+        <div class="col-xs-6" ng-if="state.mode!='edit'">
+            <b>Dimensions</b>
+        </div>
+        <div class="col-xs-6">
+            <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
+                <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
+                <i class="ace-icon fa fa-search nav-search-icon"></i>
+            </span>
+        </div>
+    </div>
+    <table class="table table-striped table-hover" ng-if="model.dimensions.length > 0">
+        <thead>
+            <tr>
+                <th>ID</th>
+                <th>Name</th>
+                <th>Table Name</th>
+                <th>Type</th>
+                <th></th>
+                <th ng-if="state.mode=='edit'">Actions</th>
+            </tr>
+        </thead>
+        <tbody class="cube-dimension">
+            <tr ng-repeat="dimension in model.dimensions | filter:dimState.filter track by $index">
+                <!--ID -->
+                <td>
+                    <b>{{dimension.id = ($index + 1)}}</b>
+                </td>
+                <!--Name -->
+                <td>
+                    <span>{{dimension.name}}</span>
+                </td>
+                <!--Table Name -->
+                <td>
+                    <span tooltip="{{dimension.table == model.fact_table ? 'Fact Table' : 'Lookup Table'}}">{{dimension.table}}</span>
+                </td>
+                <!--Type-->
+                <td>
+                    <span class="label label-primary" ng-repeat="t in getDimType(dimension)">{{t}}</span>
+                </td>
+                <!--Columns-->
+                <td>
+                    <div ng-repeat="t in getDimType(dimension)">
+                        <div ng-switch="t">
+                            <dl class="dl-horizontal" ng-switch-when="hierarchy">
+                                <dt>Hierarchy</dt>
+                                <dd>{{dimension.column}}</dd>
+                            </dl>
+                            <dl class="dl-horizontal" ng-switch-when="derived">
+                                <dt>Derived</dt>
+                                <dd>{{dimension.derived}}</dd>
+                            </dl>
+                            <dl class="dl-horizontal" ng-switch-when="normal">
+                                <dt>Column</dt>
+                                <dd>{{dimension.column}}</dd>
+                            </dl>
+                        </div>
+                    </div>
+                </td>
+                <td ng-if="state.mode=='edit'">
+                    <!--edit button-->
+                    <button class="btn btn-xs btn-info"
+                            ng-click="editDim(dimension)"><i class="fa fa-pencil"></i>
+                    </button>
+                    <!-- remove button-->
+                    <button class="btn btn-xs btn-danger"
+                            ng-click="removeDim(dimension)"><i class="fa fa-trash-o"></i>
+                    </button>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
+
+<div class="space-16"></div>
+<div class="callout callout-warning dimensions-conflict-area" ng-if="dimConflicts.length">
+    <h4>There are following columns defined in multiple dimensions. <small>This is not recommended!</small></h4>
+    <div class="row" ng-repeat="c in dimConflicts">
+        <div class="col-xs-3">
+            <code>{{c.table}}.{{c.column}}</code>
+        </div>
+        <div class="col-xs-3">
+            <ul class="list-unstyled">
+                <li ng-repeat="d in c.dims">{{d.id}} - {{d.name}}</li>
+            </ul>
+        </div>
+    </div>
+</div>
+
+<!-- Edit Dimension Form -->
+<script type="text/ng-template" id="addEditDimension.html">
+    <div class="modal-header">
+        <h4 class="box-title lighter">{{dimState.editing ? 'Edit' : 'Add'}} Dimension
+            <span class="label label-primary" ng-repeat="t in dimType">{{t}}</span>
+        </h4>
+    </div>
+    <div class="modal-body">
+        <ng-form name="edit_dim_form">
+        <div class="row">
+            <div class="col-xs-8">
+                <!--Name-->
+                <div class="form-group">
+                    <div class="row">
+                        <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Name</b></label>
+                        <div class="col-xs-12 col-sm-6">
+                            <input type="text" placeholder="Name.." class="form-control" name="dim_name"
+                                   tooltip="dimension name.." tooltip-trigger="focus"
+                                   ng-model="newDimension.name" required />
+                        </div>
+                        <div class="col-xs-12 col-sm-3">
+                            <div class="text-warning" ng-if="edit_dim_form.dim_name.$error.required  && edit_dim_form.dim_name.$dirty">
+                                The Dimension Name is required.
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <!--Table Name: derived dimension only allows lookup tables-->
+                <div class="form-group">
+                    <div class="row">
+                        <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Table Name</b></label>
+                        <div class="col-xs-12 col-sm-6" ng-if="dimType.indexOf('derived') >= 0">
+                            <select class="form-control" required="true" chosen data-placeholder="Select a lookup table"
+                                    ng-model="newDimension.table" ng-options="table for table in availableTables.slice(1)">
+                                <option value=""></option>
+                            </select>
+                        </div>
+                        <div class="col-xs-12 col-sm-6" ng-if="dimType.indexOf('derived') == -1">
+                            <select class="form-control" required="true" chosen data-placeholder="Select a table"
+                                    ng-model="newDimension.table" ng-options="table for table in availableTables">
+                                <option value=""></option>
+                            </select>
+                        </div>
+                        <div class="col-xs-12 col-sm-3">
+                            <div class="text-info" ng-if="dimType.indexOf('derived') >= 0">
+                                Derived dimension only comes from lookup table.
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <!--Normal Dimension: choose one column-->
+                <div class="form-group" ng-if="dimType.indexOf('normal') >= 0">
+                    <div class="row">
+                        <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Column Name</b></label>
+                        <div class="col-xs-12 col-sm-6">
+                            <select class="form-control" required="true" chosen data-placeholder="Select a column"
+                                    ng-model="newDimension.column[0]" ng-options="column.name as column.name for column in getColumnsByTable(newDimension.table)">
+                                <option value=""></option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+
+                <!--Hierarchy Dimension-->
+                <div class="form-group" ng-if="dimType.indexOf('hierarchy') >= 0">
+                    <div class="row">
+                        <div class="col-sm-6 col-sm-offset-3">
+                            <div ui-sortable="{containment: 'parent', placeholder: 'hierarchy-item-placeholder', forcePlaceholderSize: true, opacity: 0.8}"
+                                 ng-model="newDimension.column" class="hierarchy-container">
+                                <div ng-repeat="hierarchyIndex in [] | range: newDimension.column.length" class="hierarchy-item">
+                                    <div class="row">
+                                        <div class="col-xs-2">
+                                            <span class="badge">{{$index + 1}}</span>
+                                        </div>
+                                        <div class="col-xs-8">
+                                            <select chosen style="width: 100%"
+                                                    data-placeholder="Dimension Hierarchy Column"
+                                                    ng-model="newDimension.column[$index]"
+                                                    ng-options="columns.name as columns.name for columns in getColumnsByTable(newDimension.table)" >
+                                                <option value="">-- Select Column --</option>
+                                            </select>
+                                        </div>
+                                        <div class="col-xs-2">
+                                            <button type="button" class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
+                                                    ng-click="newDimension.column.splice($index, 1);">
+                                                <i class="fa fa-trash-o"></i>
+                                            </button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+
+                            <div class="space-8"></div>
+
+                            <div class="row">
+                                <div class="col-xs-4">
+                                    <button class="btn btn-xs btn-info"
+                                            ng-click="newDimension.column.push('');">
+                                        <i class="fa fa-plus"></i> New Hierarchy</button>
+                                </div>
+                                <div class="col-xs-8">
+                                    <p class="help-block">Drag level into the order you prefer.</p>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <!--Derived Dimension-->
+                <div ng-if="dimType.indexOf('derived') >= 0">
+                    <div class="form-group">
+                        <div class="row">
+                            <div class="col-sm-6 col-sm-offset-3">
+                                <div ng-repeat="derived in newDimension.derived track by $index">
+                                    <div>
+                                        <select chosen style="width: 80%;" data-placeholder="Derived Columns.."
+                                                ng-model="newDimension.derived[$index]"
+                                                ng-options="columns.name as columns.name for columns in getColumnsByTable(newDimension.table)" >
+                                            <option value=""></option>
+                                        </select>
+                                        <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
+                                                ng-click="newDimension.derived.splice($index, 1);">
+                                            <i class="fa fa-trash-o"></i>
+                                        </button>
+                                        <div class="space-4"></div>
+                                    </div>
+                                </div>
+                                <button class="btn btn-xs btn-info" ng-click="newDimension.derived.push('');">
+                                    <i class="fa fa-plus"></i> New Derived</button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <!--Tips-->
+            <div class="col-xs-4">
+                <div class="box box-solid">
+                    <div class="box-header">
+                        <h4 class="box-title">Tips</h4>
+                    </div>
+                    <div class="box-body">
+                        <div class="row">
+                            <div class="col-xs-12">
+                                <ol class="text-info">
+                                    <li>Type in any input box for auto suggestion</li>
+                                    <li>Pick up Fact Table from Star Schema Tables first</li>
+                                    <li>Data Type should match with Hive Table's Data Type</li>
+                                    <li>Join Type have to be same as will be used in query</li>
+                                    <li>Using Hierarchy to inherit one dimension another</li>
+                                    <li>Using Derived for One-One relationship between columns, like ID and Name</li>
+                                </ol>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        </ng-form>
+    </div>
+    <div class="modal-footer">
+        <button class="btn btn-primary" ng-disabled="edit_dim_form.$invalid" ng-click="ok()">OK</button>
+        <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
+    </div>
+</script>
+
+
+<script type="text/ng-template" id="autoGenDimension.html">
+    <div class="modal-header">
+        <h4 class="box-title lighter">Auto Generate Dimensions <small>This is a helper for you to batch generate dimensions.</small></h4>
+    </div>
+    <div class="modal-body">
+        <div class="row">
+            <div class="col-xs-8">
+                <div class="box box-solid">
+                    <div class="box-header"><h4>Columns</h4></div>
+                    <div class="box-body">
+                        <ul class="list-unstyled columns-region">
+                            <li ng-repeat="table in availableTables track by $index">
+                                <h5 class="table-name-underline">
+                                    <b>{{table}}</b>{{$index == 0 ? ' [Fact Table]' : ' [Lookup Table]'}}
+                                </h5>
+                                <ul class="list-unstyled">
+                                    <li ng-repeat="col in availableColumns[table] track by col.table + '.' + col.name">
+                                        <label>
+                                            <input type="checkbox" ng-model="selectedColumns[table][col.name].selected"
+                                                   ng-disabled="selectedColumns[table][col.name].disabled">
+                                            {{col.name}}
+                                        </label>
+                                    </li>
+                                </ul>
+                            </li>
+                        </ul>
+                    </div>
+                </div>
+            </div>
+
+            <!--Tips-->
+            <div class="col-xs-4">
+                <div class="box box-solid">
+                    <div class="box-header">
+                        <h4 class="box-title">Auto Generate Rules</h4>
+                    </div>
+                    <div class="box-body">
+                        <div class="row">
+                            <div class="col-xs-12">
+                                <ol class="text-info">
+                                    <li>Column is disabled once there is already a dimension referred this column.</li>
+                                    <li>In fact table: one normal dimension will be auto generated per column.</li>
+                                    <li>In lookup table: one derived dimension will be auto generated for all the selected columns.</li>
+                                </ol>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="modal-footer">
+        <button class="btn btn-primary" ng-disabled="" ng-click="ok()">OK</button>
+        <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
+    </div>
+</script>
+
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/modelDesigner/model_measures.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_measures.html b/webapp/app/partials/modelDesigner/model_measures.html
new file mode 100644
index 0000000..88b7baf
--- /dev/null
+++ b/webapp/app/partials/modelDesigner/model_measures.html
@@ -0,0 +1,185 @@
+<!--
+* 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.
+-->
+
+<!-- Measures Summary -->
+<div class="dataTables_wrapper form-inline no-footer" ng-if="model.metrics.length > 0">
+    <div class="row">
+        <span class="nav-search input-icon input-icon-right" style="margin-left: 22px;">
+            <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="state.dimensionFilter"/>
+            <i class="ace-icon fa fa-search nav-search-icon"></i>
+        </span>
+    </div>
+    <table class="table table-striped table-hover">
+        <thead>
+            <tr>
+                <th>ID</th>
+                <th>Column</th>
+                <th ng-if="state.mode=='edit'">Actions</th>
+            </tr>
+        </thead>
+        <tbody>
+            <tr ng-repeat="measure in model.metrics track by $index">
+                <td>
+                    <!--ID -->
+                    <b>{{$index + 1}}</b>
+                </td>
+                <td>
+                    <!--Name -->
+                    <span tooltip="measure name..">{{measure}}</span>
+                </td>
+                <td ng-if="state.mode=='edit'">
+                    <!--Edit Button -->
+                    <button class="btn btn-xs btn-info" ng-click="addNewMeasure(measure)">
+                        <i class="fa fa-pencil"></i>
+                    </button>
+                    <!--Remove Button -->
+                    <button class="btn btn-xs  btn-danger" ng-click="removeElement(cubeMetaFrame.measures, measure)">
+                        <i class="fa fa-trash-o"></i>
+                    </button>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
+
+<!--Add Measures Button-->
+<div class="form-group">
+    <button class="btn btn-sm btn-info" ng-click="addNewMeasure()" ng-show="state.mode=='edit' && !newMeasure">
+        <i class="fa fa-plus"></i> Measure
+    </button>
+</div>
+
+<!--Edit Measure-->
+<ng-form name="edit_mes_form">
+<div class="box box-solid" ng-if="newMeasure">
+    <div class="box-header">
+        <h4 class="box-title text-info">Edit Measure</h4>
+    </div>
+    <div class="box-body">
+        <div class="row">
+            <div class="col-xs-8">
+                    <!--Name-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Name</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <input type="text" placeholder="Name.." class="form-control"
+                                    tooltip="measure name.." tooltip-trigger="focus"
+                                    ng-model="newMeasure.name" required />
+                            </div>
+                        </div>
+                    </div>
+                    <!--Expression-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Expression</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <select class="form-control"
+                                    ng-init="newMeasure.function.expression = (!!newMeasure.function.expression)?newMeasure.function.expression:cubeConfig.dftSelections.measureExpression" chosen ng-model="newMeasure.function.expression" required
+                                    ng-change="measureReturnTypeUpdate();"
+                                    ng-options="me as me for me in cubeConfig.measureExpressions">
+                                    <option value=""></option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                    <!--Param Type-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Param Type</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <select class="form-control" ng-if="newMeasure.function.expression != 'COUNT'"
+                                    ng-init="newMeasure.function.parameter.type=(!!newMeasure.function.parameter.type)?newMeasure.function.parameter.type: 'column' "
+                                    chosen ng-model="newMeasure.function.parameter.type" required
+                                    ng-options="mpt as mpt for mpt in cubeConfig.measureParamType">
+                                    <option value=""></option>
+                                </select>
+                                <span class="font-color-default"
+                                       ng-if="newMeasure.function.expression == 'COUNT'"
+                                       ng-init="newMeasure.function.parameter.type= 'constant' "><b>&nbsp;&nbsp;constant</b>
+                                </span>
+                            </div>
+                        </div>
+                    </div>
+                    <!--Param Value-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Param Value</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <span class="font-color-default"
+                                    ng-if="newMeasure.function.parameter.type == 'constant'"
+                                    ng-init="newMeasure.function.parameter.value = 1"><b>&nbsp;&nbsp;1</b></span>
+                                <select class="form-control" chosen
+                                    ng-if="newMeasure.function.parameter.type == 'column'"
+                                    ng-model="newMeasure.function.parameter.value"
+                                    ng-change="measureReturnTypeUpdate();"
+                                    ng-options="columns.name as columns.name for columns in getColumnsByTable(metaModel.model.fact_table)" >
+                                    <option value="">-- Select a Fact Table Column --</option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                    <!--Return Type-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Return Type</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <select class="form-control"
+                                    ng-if="newMeasure.function.expression == 'COUNT_DISTINCT'"
+                                    ng-init="newMeasure.function.returntype = (!!newMeasure.function.returntype)?newMeasure.function.returntype:cubeConfig.dftSelections.distinctDataType.value"
+                                    chosen ng-model="newMeasure.function.returntype" required
+                                    ng-options="ddt.value as ddt.name for ddt in cubeConfig.distinctDataTypes">
+                                    <option value=""></option>
+                                </select>
+                                <span class="font-color-default"
+                                      ng-if="newMeasure.function.expression != 'COUNT_DISTINCT'"
+                                     ><b>&nbsp;&nbsp;{{newMeasure.function.returntype | uppercase}}</b>
+                                </span>
+                            </div>
+                        </div>
+                    </div>
+            </div>
+
+            <!--Tips-->
+            <div class="col-xs-4">
+                <div class="box box-solid">
+                    <div class="box-header">
+                        <h4 class="box-title">Tips</h4>
+                    </div>
+                    <div class="box-body">
+                        <div class="row">
+                            <div class="col-xs-12">
+                                <ol class="text-info">
+                                    <li>All cubes have to contain one measure for Count(1), suggest use "_Count_" as name (Has been generated automatically)</li>
+                                    <li>Only accept single column in param value with "Column" type</li>
+                                    <li>Distinct Count is approximate, please indicate Error Rate, higher accuracy degree accompanied with larger storage size and longer build time</li>
+                                </ol>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="box-footer">
+        <button class="btn btn-sm btn-info" ng-disabled="edit_mes_form.$invalid"
+                ng-click="saveNewMeasure()" ng-show="state.mode=='edit'">OK</button>
+        <button class="btn btn-link" ng-click="clearNewMeasure()">Cancel</button>
+    </div>
+</div>
+</ng-form>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/models/model_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_detail.html b/webapp/app/partials/models/model_detail.html
new file mode 100644
index 0000000..96a64c0
--- /dev/null
+++ b/webapp/app/partials/models/model_detail.html
@@ -0,0 +1,43 @@
+<!--
+* 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 ng-controller="CubeModelCtrl" class="nav-tabs-custom">
+    <ul class="nav nav-tabs">
+        <li class="{{(!model.visiblePage || model.visiblePage=='metadata')? 'active':''}}">
+            <a href="" ng-click="model.visiblePage='metadata'">Grid</a>
+        </li>
+        <li class="{{model.visiblePage=='graph'? 'active':''}}">
+            <a href="" ng-click="model.visiblePage='graph';buildGraph(model);">Visualization</a>
+        </li>
+        <li class="{{model.visiblePage=='json_model'? 'active':''}}"
+            ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, 16) && !newAccess">
+            <a href="" ng-click="model.visiblePage='json_model';">JSON</a>
+        </li>
+    </ul>
+
+    <div class="model-detail" ng-if="!model.visiblePage || model.visiblePage=='metadata'">
+        <div ng-include="'partials/models/model_schema.html'" ng-controller="ModelSchemaCtrl"
+             ng-init="state={mode:'view', modelName:model.name}"></div>
+    </div>
+    <div ng-show="model.visiblePage=='json_model'" class="model-detail">
+          <pre
+               style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(model), true)}}</pre>
+    </div>
+    <div ng-show="model.visiblePage=='graph'" id="model_graph_{{model.name}}" class="cube-detail cube_graph">
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/models/model_edit.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_edit.html b/webapp/app/partials/models/model_edit.html
new file mode 100644
index 0000000..07c3913
--- /dev/null
+++ b/webapp/app/partials/models/model_edit.html
@@ -0,0 +1,34 @@
+<!--
+* 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">
+    <div class="col-xs-3">
+        <div ng-include src="'partials/tables/source_table_tree.html'" ng-controller="SourceMetaCtrl"></div>
+    </div>
+    <div class="col-xs-9">
+        <form role="form" name="cube_form" novalidate>
+            <!-- This margin in order to align with table tree in left part -->
+            <div style="margin-top: 20px;">
+                <div ng-include="'partials/cubes/cube_schema.html'" ng-controller="CubeSchemaCtrl"
+                     ng-init="state={mode:'edit', cubeName: routeParams.cubeName}">
+                </div>
+            </div>
+        </form>
+    </div>
+</div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
new file mode 100644
index 0000000..ab9564a
--- /dev/null
+++ b/webapp/app/partials/models/model_schema.html
@@ -0,0 +1,68 @@
+<!--
+* 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-primary">
+    <div class="box-header widget-header-blue widget-header-flat">
+        <h4 class="box-title text-info">Cube Designer</h4>
+    </div>
+    <div class="box-body">
+        <ng-form name="design_form" ng-submit="">
+            <!-- Add a mock button to avoid auto submit-->
+            <button ng-click="" ng-show="false"></button>
+            <div>
+                <ul class="wizard-steps">
+                    <li ng-repeat="step in wizardSteps"
+                        class="{{step==curStep?'active':''}} {{step.isComplete?'complete':''}}">
+                        <span style="cursor:pointer;" ng-click="goToStep($index)" class="step">{{step.step = ($index + 1)}}</span>
+                        <span class="title">{{step.title}}</span>
+                     </li>
+                </ul>
+            </div>
+            <hr/>
+            <div class="step-content pos-rel" id="step-container">
+                <div ng-include src="curStep.src"></div>
+            </div>
+            <hr/>
+            <div class="wizard-actions">
+                <div class="row">
+                    <div class="col-xs-8">
+                        <p style="color: #808080;text-align: left;"><b>Note:</b> inputs with <span style="color: lightblue">light blue</span> border are mandatory.</p>
+                        <div>
+                            <a href="cubes" class="pull-left"><i class="fa fa-arrow-left"></i> Back to My Cubes</a>
+                        </div>
+                    </div>
+                    <div class="col-xs-4">
+                        <button class="btn btn-prev" ng-click="preView()" ng-show="curStep.title!='Cube Info'">
+                            <i class="ace-icon fa fa-arrow-left"></i>
+                            Prev
+                        </button>
+                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="nextView()" ng-disabled="design_form.$invalid"
+                                ng-show="curStep.title!='Overview'">
+                            Next
+                            <i class="ace-icon fa fa-arrow-right icon-on-right"></i>
+                        </button>
+                        <button class="btn btn-primary" ng-click="prepareCube();saveCube(design_form)" ng-disabled="design_form.$invalid"
+                                ng-if="curStep.title=='Overview' && state.mode=='edit'">
+                            Save
+                        </button>
+                    </div>
+                </div>
+            </div>
+        </ng-form>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
new file mode 100644
index 0000000..85f7cad
--- /dev/null
+++ b/webapp/app/partials/models/models.html
@@ -0,0 +1,117 @@
+<!--
+* 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="page-header row">
+    <!--Project-->
+    <div class="col-xs-3">
+        <form ng-if="userService.isAuthorized()">
+            <div class="form-group">
+                <!--Project-->
+                <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
+                <a class="btn btn-xs btn-primary" style="width: 29px" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'"  tooltip="Add Project" ng-click="toCreateProj()">
+                    <i class="fa fa-plus"></i>
+                </a>
+            </div>
+        </form>
+    </div>
+    <!--Model Name-->
+    <div class="col-xs-3">
+        <form ng-submit="" style="display: inline" >
+            <span class="input-icon input-icon-right nav-search" style="font-size:14px;"><b>Model Name:</b>
+                <input type="text" placeholder="Filter ..." class="nav-search-input"  ng-model="listParams.modelName"/>
+                <i class="ace-icon fa fa-search blue"  ng-click="modelList.removeAll();list()"></i>
+            </span>
+        </form>
+    </div>
+    <div class="pull-right">
+        <a class="btn btn-primary btn-sm" href="models/add"  ng-if="userService.hasRole('ROLE_MODELER')" id="addModelButton"><i class="fa fa-plus"></i> Model</a>
+    </div>
+</div>
+<div ng-if="!loading && modelList.models.length == 0">
+    <div no-result text="No Model."></div>
+</div>
+<loading ng-if="loading" text="Loading Models..."></loading>
+
+<div ng-if="modelList.models.length > 0" class="dataTables_wrapper no-footer">
+    <div class="row">
+        <div class="col-xs-12"><label class="table-header-text">Models</label></div>
+    </div>
+    <table class="table table-striped table-bordered table-hover dataTable no-footer">
+        <!--Header-->
+        <thead>
+        <tr style="cursor: pointer">
+            <th ng-repeat="theaditem in modelConfig.theaditems"
+                ng-click="state.filterAttr= theaditem.attr;state.reverseColumn=theaditem.attr;state.filterReverse=!state.filterReverse;">
+                {{theaditem.name}}
+                <i ng-if="state.reverseColumn!= theaditem.attr"
+                   class="fa fa-unsorted"></i>
+                <i ng-if="state.reverseColumn== theaditem.attr && !state.filterReverse"
+                   class="fa fa-sort-asc"></i>
+                <i ng-if="state.reverseColumn== theaditem.attr && state.filterReverse"
+                   class="fa fa-sort-desc"></i>
+            </th>
+            <th>Actions</th>
+        </tr>
+        </thead>
+        <!--Body-->
+        <tbody ng-repeat="model in modelList.models | orderObjectBy:state.filterAttr:state.filterReverse">
+        <tr ng-class="{accordion:true}" style="cursor: pointer"  ng-click="model.showDetail=!model.showDetail;loadDetail(model)">
+            <td>
+                <i ng-show="!model.showDetail" class="fa fa-chevron-circle-right blue"></i>
+                <i ng-show="model.showDetail" class="fa fa-chevron-circle-down blue"></i>
+                {{ model.name}}
+            </td>
+            <td>
+                    {{ model.fact_table}}
+            </td>
+            <td>
+                    {{ model.last_modified | utcToConfigTimeZone}}
+            </td>
+            <td>
+                <div ng-click="$event.stopPropagation();" class="btn-group" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
+                    <button type="button" class="btn btn-default btn-xs dropdown-toggle"
+                            data-toggle="dropdown" ng-click="listAccess(model, 'ModelInstance')">
+                        Action <span class="ace-icon fa fa-caret-down icon-on-right"></span>
+                    </button>
+                    <ul class="dropdown-menu" role="menu">
+                        <li><a href="models/edit/{{model.name}}">Edit</a></li>
+                        <li ng-if="userService.hasRole('ROLE_ADMIN')">
+                            <a ng-click="dropModel(model)" tooltip="Drop the model, related cubes and data permanently.">Drop</a></li>
+
+                    </ul>
+                </div>
+                <span ng-if="!(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))">
+                    N/A
+                </span>
+            </td>
+        </tr>
+        <tr ng-show="model.showDetail">
+            <td colspan="9" style="padding: 10px 30px 10px 30px;">
+                <div ng-include src="'partials/models/model_detail.html'"></div>
+            </td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
+
+<div class="row">
+    <div class="col-xs-12">
+        <kylin-pagination data="modelList.models" load-func="list" action="action"/>
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/routes.json
----------------------------------------------------------------------
diff --git a/webapp/app/routes.json b/webapp/app/routes.json
index 8a72f09..0b4af3f 100644
--- a/webapp/app/routes.json
+++ b/webapp/app/routes.json
@@ -103,5 +103,13 @@
             "controller": "LoginCtrl",
             "reloadOnSearch": false
         }
+    },
+    {
+        "url": "/models",
+        "params": {
+            "templateUrl": "partials/models/models.html",
+            "tab": "models",
+            "controller": "ModelsCtrl"
+        }
     }
 ]
\ No newline at end of file