You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@eagle.apache.org by ji...@apache.org on 2016/10/26 02:46:28 UTC
incubator-eagle git commit: Eagle-631 Policy UI refactory
Repository: incubator-eagle
Updated Branches:
refs/heads/master 852bac94e -> 1f5126a14
Eagle-631 Policy UI refactory
for https://issues.apache.org/jira/browse/EAGLE-627 , use the validate api to check policy.
Author: zombieJ <sm...@gmail.com>
Closes #562 from zombieJ/EAGLE-631.
Project: http://git-wip-us.apache.org/repos/asf/incubator-eagle/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-eagle/commit/1f5126a1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-eagle/tree/1f5126a1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-eagle/diff/1f5126a1
Branch: refs/heads/master
Commit: 1f5126a1481ac3557247e6711e0f94880bd8b662
Parents: 852bac9
Author: zombieJ <sm...@gmail.com>
Authored: Wed Oct 26 10:46:18 2016 +0800
Committer: zombieJ <sm...@gmail.com>
Committed: Wed Oct 26 10:46:18 2016 +0800
----------------------------------------------------------------------
eagle-server/src/main/webapp/app/dev/index.html | 1 +
.../webapp/app/dev/partials/alert/main.html | 7 +-
.../app/dev/partials/alert/policyEdit.back.html | 108 -----
.../partials/alert/policyEdit/advancedMode.html | 294 +++++++++++++
.../app/dev/partials/alert/policyEdit/main.html | 19 +
.../app/dev/partials/alert/policyList.html | 8 +-
.../src/main/webapp/app/dev/public/css/main.css | 58 +++
.../src/main/webapp/app/dev/public/js/app.js | 18 +-
.../dev/public/js/components/staticInclude.js | 33 ++
.../webapp/app/dev/public/js/ctrls/alertCtrl.js | 19 -
.../dev/public/js/ctrls/alertEditCtrl.bac.js | 297 +++++++++++++
.../app/dev/public/js/ctrls/alertEditCtrl.js | 436 ++++++++++++-------
.../app/dev/public/js/services/pageSrv.js | 2 +-
13 files changed, 985 insertions(+), 315 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/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
index d791819..64c8c57 100644
--- a/eagle-server/src/main/webapp/app/dev/index.html
+++ b/eagle-server/src/main/webapp/app/dev/index.html
@@ -242,6 +242,7 @@
<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>
+ <script src="public/js/components/staticInclude.js" type="text/javascript" charset="utf-8"></script>
<!-- Controllers -->
<script src="public/js/ctrls/main.js" type="text/javascript" charset="utf-8"></script>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/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
index 2e14db9..83db262 100644
--- a/eagle-server/src/main/webapp/app/dev/partials/alert/main.html
+++ b/eagle-server/src/main/webapp/app/dev/partials/alert/main.html
@@ -18,14 +18,9 @@
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
- <li ng-class="{active: getState() === 'alert.list'}"><a href="#/alert/">Alerts</a></li>
+ <!--li ng-class="{active: getState() === 'alert.list'}"><a href="#/alert/">Alerts</a></li-->
<li ng-class="{active: getState() === 'alert.policyList'}"><a href="#/alert/policyList">Policies</a></li>
<li ng-class="{active: getState() === 'alert.streamList'}"><a href="#/alert/streamList">Streams</a></li>
-
- <li
- ng-class="{active: ['alert.policyCreate', 'alert.policyEdit'].indexOf(getState()) >= 0}"
- ng-if="['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>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/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
deleted file mode 100644
index 3c335f7..0000000
--- a/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit.back.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!--
- 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/1f5126a1/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit/advancedMode.html
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit/advancedMode.html b/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit/advancedMode.html
new file mode 100644
index 0000000..624acaa
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit/advancedMode.html
@@ -0,0 +1,294 @@
+<!--
+ 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 flex">
+ <div class="col-md-4">
+ <div class="box box-primary">
+ <div class="box-header with-border">
+ <span class="fa fa-rocket"></span>
+ <h3 class="box-title">
+ Source Stream
+ </h3>
+ <div class="box-tools pull-right">
+ <div class="btn-group" data-toggle="btn-toggle">
+ <button class="btn btn-default btn-sm" ng-class="{active: sourceTab === 'all'}" ng-click="setSourceTab('all')">
+ All
+ </button>
+ <button class="btn btn-default btn-sm" ng-class="{active: sourceTab === 'selected'}" ng-click="setSourceTab('selected')">
+ Selected
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="box-body">
+ <div ng-show="sourceTab === 'all'">
+ <div class="input-with-icon">
+ <input type="text" class="form-control" placeholder="Search..." ng-model="searchSourceKey" />
+ <span class="fa fa-search"></span>
+ </div>
+ <div ng-repeat="(app, streams) in getSearchApplication() track by app" class="policy-app-list">
+ <a data-toggle="collapse" href="[data-id='SP_{{app}}']">
+ <strong>{{app}}</strong>
+ </a>
+ <ul data-id="SP_{{app}}" class="collapse in list-unstyled">
+ <li ng-repeat="stream in streams track by stream.streamId">
+ <a data-toggle="collapse" href="[data-id='SP_{{app}}_{{stream.streamId}}']">
+ <span class="fa fa-{{isInputStreamSelected(stream.streamId) ? 'check-square' : 'square'}}"></span>
+ {{stream.streamId}}
+ </a>
+ <ul data-id="SP_{{app}}_{{stream.streamId}}" class="collapse in">
+ <li ng-repeat="column in stream.columns track by $index">
+ <span class="text-primary">[{{column.type}}]</span>
+ {{column.name}}
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ </div>
+ <div ng-show="sourceTab === 'selected'">
+ <div ng-repeat="stream in policy.inputStreams">
+ <a data-toggle="collapse" href="[data-id='SS_{{stream}}']">
+ <strong>{{stream}}</strong>
+ </a>
+ <ul class="sm-padding collapse in" data-id="SS_{{stream}}">
+ <li ng-repeat="column in streams[stream].columns track by $index">
+ <span class="text-primary">[{{column.type}}]</span>
+ {{column.name}}
+ </li>
+ </ul>
+ </div>
+ <p class="text-muted" ng-if="policy.inputStreams.length === 0">No Stream selected</p>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="col-md-8">
+ <div class="box box-primary">
+ <div class="box-header with-border">
+ <span class="fa fa-pencil"></span>
+ <h3 class="box-title">Policy</h3>
+ </div>
+ <div class="box-body">
+ <div class="row">
+ <div class="col-md-8">
+ <div class="form-group">
+ <label>* Name</label>
+ <input type="text" class="form-control" ng-model="policy.name" ng-readonly="newPolicy" ng-disabled="policyLock" />
+ </div>
+ </div>
+ <div class="col-md-4">
+ <div class="form-group">
+ <label>* Parallelism Hint</label>
+ <input type="text" class="form-control" ng-model="policy.parallelismHint" ng-disabled="policyLock" />
+ </div>
+ </div>
+ </div>
+
+
+ <div class="form-group">
+ <label>Description</label>
+ <textarea class="form-control" ng-model="policy.description" rows="2" ng-disabled="policyLock"></textarea>
+ </div>
+
+ <div class="form-group" ng-class="{'has-error': !!definitionMessage}">
+ <label>* Definition</label>
+ <textarea class="form-control" ng-model="policy.definition.value" rows="10" ng-change="checkDefinition()" ng-disabled="policyLock"></textarea>
+ <p class="text-danger">{{definitionMessage}}</p>
+ </div>
+
+ <!--label>
+ Input Stream Partition
+ </label>
+ <ul class="sm-padding">
+ <li ng-repeat="partition in policy.partitionSpec track by $index">
+ <[<a class="fa fa-times" ng-click="removePartition(partition)"></a>]>
+ <strong class="text-primary">{{partition.streamId}}:</strong>
+ <p>
+ <strong>{{partition.type}}</strong> on
+ <strong class="text-success">[{{partition.columns.join(", ")}}]</strong>
+ <span ng-if="partition.sortSpec.windowPeriod">
+ sort in window:
+ <strong class="text-info">[{{partition.sortSpec.windowPeriod}}]</strong>
+ </span>
+ </p>
+ </li>
+ <li class="text-warning" ng-if="policy.partitionSpec.length === 0">No partition yet.</li>
+ <li>
+ <a ng-click="addPartition()">+ Add Partition</a>
+ </li>
+ </ul-->
+
+ <label>
+ Alert Stream
+ </label>
+ <ul class="sm-padding">
+ <li ng-repeat="stream in outputStreams track by $index">
+ <label>
+ <input type="checkbox" ng-checked="isOutputStreamSelected(stream)" ng-click="checkOutputStream(stream)" ng-disabled="policyLock" />
+ {{stream}}
+ </label>
+ </li>
+ <li class="text-warning" ng-if="policy.outputStreams.length === 0">No alert stream yet.</li>
+ </ul>
+
+ <label>
+ Publisher
+ </label>
+ <ul class="sm-padding">
+ <li ng-repeat="publisher in policyPublisherList track by $index">
+ <span>
+ [<a class="fa fa-times" ng-click="removePublisher(publisher)"></a>]
+ <strong>
+ <span>({{publisherTypes[publisher.type].name}})</span>
+ {{publisher.name}}
+ </strong>
+ </span>
+ <p class="offset" ng-repeat="field in publisherTypes[publisher.type].displayFields track by $index">
+ <span>{{field}}:</span>
+ <span>{{publisher.properties[field]}}</span>
+ </p>
+ </li>
+ <li>
+ <a ng-click="addPublisher()">+ Add Publisher</a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+</div>
+
+<div class="text-right">
+ <button class="btn btn-primary" ng-disabled="!saveCheck()" ng-click="saveConfirm()">
+ <span class="fa fa-floppy-o"></span>
+ Save
+ </button>
+</div>
+
+<!------------------------- Modal: Partition ------------------------->
+<div class="modal fade" tabindex="-1" data-id="partitionMDL">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">
+ <span aria-hidden="true">×</span>
+ </button>
+ <h4 class="modal-title">Add Partition</h4>
+ </div>
+ <div class="modal-body">
+ <div class="form-group">
+ <label>Stream</label>
+ <select class="form-control" ng-model="partition.streamId">
+ <option ng-repeat="stream in policy.inputStreams track by stream">{{stream}}</option>
+ </select>
+ </div>
+ <div class="form-group">
+ <label>Type</label>
+ <select class="form-control" ng-model="partition.type">
+ <option value="GROUPBY">GroupBy</option>
+ <option value="GLOBAL">Global</option>
+ <option value="SHUFFLE">Shuffle</option>
+ </select>
+ </div>
+ <div class="form-group">
+ <label>columns</label>
+ <ul class="list-unstyled">
+ <li ng-repeat="column in streams[partition.streamId].columns track by $index">
+ <label>
+ <input type="checkbox" ng-checked="newPartitionCheckColumn(column.name)"
+ ng-click="newPartitionClickColumn(column.name)" />
+ <span class="text-primary">[{{column.type}}]</span>
+ {{column.name}}
+ </label>
+ </li>
+ </ul>
+ </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" data-dismiss="modal"
+ ng-disabled="partition.columns.length === 0" ng-click="addPartitionConfirm()">Add</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<!------------------------- Modal: Publisher ------------------------->
+<div class="modal fade" tabindex="-1" data-id="publisherMDL">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">
+ <span aria-hidden="true">×</span>
+ </button>
+ <h4 class="modal-title">Add Publisher</h4>
+ </div>
+ <div class="modal-body">
+ <div class="radio" ng-show="publisherList.length > 0">
+ <label class="radio-inline">
+ <input type="radio" value="exist" ng-model="addPublisherType">
+ From exist publisher
+ </label>
+ <label class="radio-inline">
+ <input type="radio" value="new" ng-model="addPublisherType">
+ Create new publisher
+ </label>
+ </div>
+
+ <!-- Publisher: Exist -->
+ <div ng-if="addPublisherType === 'exist'">
+ <div class="form-group">
+ <label>Publisher</label>
+ <select class="form-control" ng-model="publisher.existPublisher"
+ ng-options="publisher as publisher.name for publisher in publisherList track by publisher.name"></select>
+ </div>
+ </div>
+
+ <div ng-if="addPublisherType === 'new'">
+ <div class="form-group" ng-class="{'has-error': checkPublisherName()}">
+ <label>
+ Name
+ <small ng-if="checkPublisherName()">({{checkPublisherName()}})</small>
+ </label>
+ <input class="form-control" ng-model="publisher.name" />
+ </div>
+ <div class="form-group">
+ <label>Dedup-Interval Minutes</label>
+ <input class="form-control" ng-model="publisher.dedupIntervalMin" />
+ </div>
+ <div class="form-group">
+ <label>Type</label>
+ <select class="form-control" ng-model="publisher.type">
+ <option ng-repeat="(type, fields) in publisherTypes track by type">{{type}}</option>
+ </select>
+ </div>
+ <div class="form-group" ng-repeat="field in publisherTypes[publisher.type].fields track by $index">
+ <label>{{field}}</label>
+ <input class="form-control" ng-model="publisher.properties[field]" />
+ </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" data-dismiss="modal"
+ ng-disabled="addPublisherType === 'new' && !publisher.name" ng-click="addPublisherConfirm()">Add</button>
+ </div>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit/main.html
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit/main.html b/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit/main.html
new file mode 100644
index 0000000..db687c4
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/partials/alert/policyEdit/main.html
@@ -0,0 +1,19 @@
+<!--
+ 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 static-include="partials/alert/policyEdit/advancedMode.html?_={{_TRS}}"></div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/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
index 35d9696..862f944 100644
--- a/eagle-server/src/main/webapp/app/dev/partials/alert/policyList.html
+++ b/eagle-server/src/main/webapp/app/dev/partials/alert/policyList.html
@@ -35,7 +35,7 @@
<span class="fa fa-square" ng-class="item.policyStatus === 'ENABLED' ? 'text-green' : 'text-muted'"></span>
</td>
<td>
- <a ui-sref="policyDetail({name: item.name})" target="_blank">{{item.name}}</a>
+ <a ui-sref="policyDetail({name: item.name})">{{item.name}}</a>
</td>
<td class="text-center"><span class="label label-primary">{{item.definition.type}}</span></td>
<td>{{item.description}}</td>
@@ -47,7 +47,7 @@
<button class="btn btn-default opt" ng-if="item.policyStatus === 'ENABLED'" ng-click="stopPolicy(item)">
<span class="fa fa-stop"></span>
</button>
- <a ui-sref="alert.policyEdit({name: item.name})" target="_blank" class="btn btn-default opt"><span class="fa fa-pencil"></span></a>
+ <a ui-sref="policyEdit({name: item.name})" class="btn btn-default opt"><span class="fa fa-pencil"></span></a>
<button class="btn btn-danger opt" ng-click="deletePolicy(item)"><span class="fa fa-trash"></span></button>
</div>
</td>
@@ -58,7 +58,7 @@
<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>
+ <p>You have not create policy yet. Click <a ui-sref="policyCreate()">here</a> to create a new policy.</p>
</div>
</div>
@@ -67,6 +67,6 @@
</div>
<div class="box-footer text-right">
- <a href="#/alert/policyCreate" class="btn btn-primary">New Policy</a>
+ <a ui-sref="policyCreate()" class="btn btn-primary">New Policy</a>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/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
index 16136c8..4b7a799 100644
--- a/eagle-server/src/main/webapp/app/dev/public/css/main.css
+++ b/eagle-server/src/main/webapp/app/dev/public/css/main.css
@@ -184,6 +184,44 @@ ul.stepGuide li > .title {
}
/* ========================================================================
+ * = Input =
+ * ======================================================================== */
+.input-with-icon {
+ position: relative;
+ margin-bottom: 10px;
+}
+
+.input-with-icon .fa {
+ position: absolute;
+ left: 10px;
+ top: 10px;
+ pointer-events: none;
+ opacity: 0.6;
+}
+
+.input-with-icon input {
+ padding-left: 28px;
+}
+
+/* ========================================================================
+ * = Policy =
+ * ======================================================================== */
+.policy-app-list > a {
+ display: block;
+ font-size: 18px;
+}
+
+.policy-app-list > ul {
+ margin: 0;
+ padding: 0 0 0 5px;
+}
+
+.policy-app-list > ul > li input[type='checkbox'] {
+ vertical-align: middle;
+ margin: 0;
+}
+
+/* ========================================================================
* = Box =
* ======================================================================== */
.box .box-title .label {
@@ -270,6 +308,26 @@ ul.stepGuide li > .title {
display: inline-block;
}
+ul.sm-padding {
+ padding: 0 0 0 25px;
+}
+
+ul.sm-padding > li {
+ list-style: circle;
+}
+
+ul > li > label {
+ font-weight: normal;
+}
+ul > li > label > input[type='checkbox'] {
+ margin: 0;
+ vertical-align: middle;
+}
+
+ul > li > p.offset {
+ padding-left: 25px;
+}
+
/* ========================================================================
* = label =
* ======================================================================== */
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/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
index 39c84c5..277d0fa 100644
--- a/eagle-server/src/main/webapp/app/dev/public/js/app.js
+++ b/eagle-server/src/main/webapp/app/dev/public/js/app.js
@@ -109,15 +109,15 @@ var app = {};
controller: "alertStreamListCtrl",
resolve: routeResolve()
})
- .state('alert.policyCreate', {
- url: "policyCreate",
- templateUrl: "partials/alert/policyEdit.html?_=" + window._TRS(),
+ .state('policyCreate', {
+ url: "/alert/policyCreate",
+ templateUrl: "partials/alert/policyEdit/main.html?_=" + window._TRS(),
controller: "policyCreateCtrl",
resolve: routeResolve()
})
- .state('alert.policyEdit', {
- url: "policyEdit/{name}",
- templateUrl: "partials/alert/policyEdit.html?_=" + window._TRS(),
+ .state('policyEdit', {
+ url: "/alert/policyEdit/{name}",
+ templateUrl: "partials/alert/policyEdit/main.html?_=" + window._TRS(),
controller: "policyEditCtrl",
resolve: routeResolve()
})
@@ -185,7 +185,7 @@ var app = {};
$stateProvider.state(route.state, config);
});
- $httpProvider.interceptors.push(function($q) {
+ /* $httpProvider.interceptors.push(function($q) {
function eagleRequestHandle(res) {
var data = res.data || {
exception: "",
@@ -218,7 +218,7 @@ var app = {};
return $q.reject(eagleRequestHandle(res));
}
};
- });
+ }); */
});
// ======================================================================================
@@ -236,6 +236,8 @@ var app = {};
window._Time = $scope.Time = Time;
$scope.common = common;
+ $scope._TRS = window._TRS();
+
Object.defineProperty(window, "scope", {
get: function () {
var ele = $("#content .nav-tabs-custom.ng-scope .ng-scope[ui-view], #content .ng-scope[ui-view]").last();
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/eagle-server/src/main/webapp/app/dev/public/js/components/staticInclude.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/components/staticInclude.js b/eagle-server/src/main/webapp/app/dev/public/js/components/staticInclude.js
new file mode 100644
index 0000000..707a747
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/public/js/components/staticInclude.js
@@ -0,0 +1,33 @@
+/*
+ * 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.directive('staticInclude', function($http, $templateCache, $compile) {
+ return function(scope, element, attrs) {
+ var templatePath = attrs.staticInclude;
+ $http.get(templatePath, { cache: $templateCache }).success(function(response) {
+ var contents = element.html(response).contents();
+ $compile(contents)(scope);
+ });
+ };
+ });
+})();
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertCtrl.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertCtrl.js b/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertCtrl.js
index eeea083..e52fc3c 100644
--- a/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertCtrl.js
+++ b/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertCtrl.js
@@ -21,25 +21,6 @@
var eagleControllers = angular.module('eagleControllers');
- // TODO: Mock data
- var publishmentTypes = [
- {
- "type": "email",
- "className": "org.apache.eagle.alert.engine.publisher.impl.AlertEmailPublisher",
- "description": "send alert to email",
- "enabled":true,
- "fields": [{"name":"sender"},{"name":"recipients"},{"name":"subject"},{"name":"smtp.server", "value":"host1"},{"name":"connection", "value":"plaintext"},{"name":"smtp.port", "value": "25"}]
- },
- {
- "type": "kafka",
- "className": "org.apache.eagle.alert.engine.publisher.impl.AlertKafkaPublisher",
- "description": "send alert to kafka bus",
- "enabled":true,
- "fields": [{"name":"kafka_broker","value":"sandbox.hortonworks.com:6667"},{"name":"topic"}]
- }
- ];
-
-
// ======================================================================================
// = Main =
// ======================================================================================
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertEditCtrl.bac.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertEditCtrl.bac.js b/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertEditCtrl.bac.js
new file mode 100644
index 0000000..3bcd8d8
--- /dev/null
+++ b/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertEditCtrl.bac.js
@@ -0,0 +1,297 @@
+/*
+ * 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 eagleControllers = angular.module('eagleControllers');
+
+ var publisherTypes = {
+ 'org.apache.eagle.alert.engine.publisher.impl.AlertEmailPublisher': ["subject", "template", "sender", "recipients", "mail.smtp.host", "connection", "mail.smtp.port"],
+ 'org.apache.eagle.alert.engine.publisher.impl.AlertKafkaPublisher': ["topic", "kafka_broker", "rawAlertNamespaceLabel", "rawAlertNamespaceValue"],
+ 'org.apache.eagle.alert.engine.publisher.impl.AlertSlackPublisher': ["token", "channels", "severitys", "urltemplate"]
+ };
+
+ // ======================================================================================
+ // = Policy Create =
+ // ======================================================================================
+ function connectPolicyEditController(entity, args) {
+ var newArgs = [entity];
+ Array.prototype.push.apply(newArgs, args);
+ /* jshint validthis: true */
+ policyEditController.apply(this, newArgs);
+ }
+
+ eagleControllers.controller('policyCreateCtrl', function ($scope, $wrapState, PageConfig, Entity) {
+ PageConfig.subTitle = "Define Alert Policy";
+ connectPolicyEditController({}, arguments);
+ });
+ eagleControllers.controller('policyEditCtrl', function ($scope, $wrapState, PageConfig, Entity) {
+ PageConfig.subTitle = "Edit Alert Policy";
+ var args = arguments;
+
+ // TODO: Wait for backend data update
+ $scope.policyList = Entity.queryMetadata("policies/" + encodeURIComponent($wrapState.param.name));
+
+ $scope.policyList._promise.then(function () {
+ var policy = $scope.policyList[0];
+
+ if(policy) {
+ connectPolicyEditController(policy, args);
+ } else {
+ $.dialog({
+ title: "OPS",
+ content: "Policy '" + $wrapState.param.name + "' not found!"
+ }, function () {
+ $wrapState.go("alert.policyList");
+ });
+ }
+ });
+ });
+
+ function policyEditController(policy, $scope, $wrapState, PageConfig, Entity) {
+ $scope.newPolicy = !policy.name;
+ $scope.policyLock = false;
+
+ $scope.publisherTypes = publisherTypes;
+
+ $scope.selectedApplication = null;
+ $scope.selectedStream = null;
+
+ $scope.outputStream = "";
+
+ $scope.partitionStream = null;
+ $scope.partitionType = "GROUPBY";
+ $scope.partitionColumns = {};
+
+ $scope.publisherType = "org.apache.eagle.alert.engine.publisher.impl.AlertEmailPublisher";
+ $scope.publisher = {
+ dedupIntervalMin: "PT1M"
+ };
+ $scope.publisherProps = {};
+
+ $scope.policy = common.merge({
+ name: "",
+ description: "",
+ inputStreams: [],
+ outputStreams: [],
+ definition: {
+ type: "siddhi",
+ value: ""
+ },
+ partitionSpec: [],
+ parallelismHint: 2
+ }, policy);
+
+ $scope.policy.definition = {
+ type: $scope.policy.definition.type,
+ value: $scope.policy.definition.value
+ };
+
+ console.log("[Policy]", $scope.policy);
+
+ // =========================================================
+ // = Check Logic =
+ // =========================================================
+ $scope.checkBasicInfo = function () {
+ return !!$scope.policy.name;
+ };
+
+ $scope.checkAlertStream = function () {
+ return $scope.checkBasicInfo() &&
+ $scope.policy.inputStreams.length > 0 &&
+ $scope.policy.outputStreams.length > 0;
+ };
+
+ $scope.checkNumber = function (str) {
+ str = (str + "").trim();
+ return str !== "" && common.number.isNumber(Number(str));
+ };
+
+ $scope.checkDefinition = function () {
+ return $scope.checkAlertStream() &&
+ !!$scope.policy.definition.value.trim() &&
+ $scope.policy.parallelismHint > 0;
+ };
+
+ // =========================================================
+ // = Stream =
+ // =========================================================
+ $scope.refreshStreamSelect = function() {
+ var appStreamList;
+
+ if(!$scope.selectedApplication) {
+ $scope.selectedApplication = common.getKeys($scope.applications)[0];
+ }
+
+ appStreamList = $scope.applications[$scope.selectedApplication] || [];
+ if(!common.array.find($scope.selectedStream, appStreamList)) {
+ $scope.selectedStream = appStreamList[0].streamId;
+ }
+ if(!common.array.find($scope.partitionStream, $scope.policy.inputStreams)) {
+ $scope.partitionStream = $scope.policy.inputStreams[0];
+ }
+ };
+
+ $scope.streamList = Entity.queryMetadata("streams");
+ $scope.streamList._then(function () {
+ $scope.applications = {};
+
+ $.each($scope.streamList, function (i, stream) {
+ var list = $scope.applications[stream.dataSource] = $scope.applications[stream.dataSource] || [];
+ list.push(stream);
+ });
+
+ console.log("=>", $scope.streamList);
+ $scope.refreshStreamSelect();
+ });
+
+ $scope.getStreamList = function () {
+ return common.array.minus($scope.streamList, $scope.policy.inputStreams, "streamId", "");
+ };
+
+ $scope.addStream = function () {
+ $scope.policy.inputStreams.push($scope.selectedStream);
+ $scope.refreshStreamSelect();
+ };
+
+ $scope.removeStream = function (streamId) {
+ $scope.policy.inputStreams = common.array.remove(streamId, $scope.policy.inputStreams);
+ $scope.refreshStreamSelect();
+ };
+
+ $scope.checkAddStream = function (streamId) {
+ return !common.array.find(streamId, $scope.policy.inputStreams);
+ };
+
+ $scope.addOutputStream = function () {
+ $scope.policy.outputStreams.push($scope.outputStream);
+ $scope.outputStream = "";
+ };
+
+ $scope.removeOutputStream = function (streamId) {
+ $scope.policy.outputStreams = common.array.remove(streamId, $scope.policy.outputStreams);
+ };
+
+ $scope.checkAddOutputStream = function () {
+ return $scope.outputStream !== "" && !common.array.find($scope.outputStream, $scope.policy.outputStreams);
+ };
+
+ // =========================================================
+ // = Definition =
+ // =========================================================
+ $scope.getPartitionColumns = function () {
+ var stream = common.array.find($scope.partitionStream, $scope.streamList, "streamId");
+ return (stream || {}).columns;
+ };
+
+ $scope.addPartition = function () {
+ $scope.policy.partitionSpec.push({
+ streamId: $scope.partitionStream,
+ type: $scope.partitionType,
+ columns: $.map($scope.getPartitionColumns(), function (column) {
+ return $scope.partitionColumns[column.name] ? column.name : null;
+ })
+ });
+
+ $scope.partitionColumns = {};
+ };
+
+ $scope.checkAddPartition = function () {
+ var match = false;
+
+ $.each($scope.getPartitionColumns(), function (i, column) {
+ if($scope.partitionColumns[column.name]) {
+ match = true;
+ return false;
+ }
+ });
+
+ return match;
+ };
+
+ $scope.removePartition = function (partition) {
+ $scope.policy.partitionSpec = common.array.remove(partition, $scope.policy.partitionSpec);
+ };
+
+ // =========================================================
+ // = Publisher =
+ // =========================================================
+ $scope.publisherList = [];
+
+ if(!$scope.newPolicy) {
+ $scope.publisherList = Entity.queryMetadata("policies/" + encodeURIComponent($scope.policy.name) + "/publishments");
+ }
+
+ $scope.addPublisher = function () {
+ var publisherProps = {};
+ $.each($scope.publisherTypes[$scope.publisherType], function (i, field) {
+ publisherProps[field] = $scope.publisherProps[field] || "";
+ });
+ $scope.publisherList.push({
+ name: $scope.publisher.name,
+ type: $scope.publisherType,
+ policyIds: [$scope.policy.name],
+ properties: publisherProps,
+ dedupIntervalMin: $scope.publisher.dedupIntervalMin,
+ serializer : "org.apache.eagle.alert.engine.publisher.impl.StringEventSerializer"
+ });
+ $scope.publisher = {
+ dedupIntervalMin: "PT1M"
+ };
+ $scope.publisherProps = {};
+ };
+
+ $scope.removePublisher = function (publisher) {
+ $scope.publisherList = common.array.remove(publisher, $scope.publisherList);
+ };
+
+ $scope.checkAddPublisher = function () {
+ return $scope.publisher.name &&
+ !common.array.find($scope.publisher.name, $scope.publisherList, "name");
+ };
+
+ // =========================================================
+ // = Policy =
+ // =========================================================
+ $scope.createPolicy = function () {
+ // TODO: Need check the policy or publisher exist.
+
+ $scope.policyLock = true;
+
+ var policyPromise = Entity.create("metadata/policies", $scope.policy)._promise;
+ var publisherPromiseList = $.map($scope.publisherList, function (publisher) {
+ return Entity.create("metadata/publishments", publisher)._promise;
+ });
+ common.deferred.all(publisherPromiseList.concat(policyPromise)).then(function () {
+ $.dialog({
+ title: "Done",
+ content: "Close dialog to go to the policy detail page."
+ }, function () {
+ $wrapState.go("policyDetail", {name: $scope.policy.name});
+ });
+ }, function (failedList) {
+ $.dialog({
+ title: "OPS",
+ content: $("<pre>").text(JSON.stringify(failedList, null, "\t"))
+ });
+ $scope.policyLock = false;
+ });
+ };
+ }
+})();
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertEditCtrl.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertEditCtrl.js b/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertEditCtrl.js
index 3bcd8d8..8fde4b1 100644
--- a/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertEditCtrl.js
+++ b/eagle-server/src/main/webapp/app/dev/public/js/ctrls/alertEditCtrl.js
@@ -22,9 +22,21 @@
var eagleControllers = angular.module('eagleControllers');
var publisherTypes = {
- 'org.apache.eagle.alert.engine.publisher.impl.AlertEmailPublisher': ["subject", "template", "sender", "recipients", "mail.smtp.host", "connection", "mail.smtp.port"],
- 'org.apache.eagle.alert.engine.publisher.impl.AlertKafkaPublisher': ["topic", "kafka_broker", "rawAlertNamespaceLabel", "rawAlertNamespaceValue"],
- 'org.apache.eagle.alert.engine.publisher.impl.AlertSlackPublisher': ["token", "channels", "severitys", "urltemplate"]
+ 'org.apache.eagle.alert.engine.publisher.impl.AlertEmailPublisher': {
+ name: "Email",
+ displayFields: ["recipients"],
+ fields: ["subject", "template", "sender", "recipients", "mail.smtp.host", "connection", "mail.smtp.port"]
+ },
+ 'org.apache.eagle.alert.engine.publisher.impl.AlertKafkaPublisher': {
+ name: "Kafka",
+ displayFields: ["topic"],
+ fields: ["topic", "kafka_broker", "rawAlertNamespaceLabel", "rawAlertNamespaceValue"]
+ },
+ 'org.apache.eagle.alert.engine.publisher.impl.AlertSlackPublisher': {
+ name: "Slack",
+ displayFields: ["channels"],
+ fields: ["token", "channels", "severitys", "urltemplate"]
+ }
};
// ======================================================================================
@@ -37,17 +49,15 @@
policyEditController.apply(this, newArgs);
}
- eagleControllers.controller('policyCreateCtrl', function ($scope, $wrapState, PageConfig, Entity) {
- PageConfig.subTitle = "Define Alert Policy";
+ eagleControllers.controller('policyCreateCtrl', function ($scope, $q, $wrapState, $timeout, PageConfig, Entity) {
+ PageConfig.title = "Define Policy";
connectPolicyEditController({}, arguments);
});
- eagleControllers.controller('policyEditCtrl', function ($scope, $wrapState, PageConfig, Entity) {
- PageConfig.subTitle = "Edit Alert Policy";
+ eagleControllers.controller('policyEditCtrl', function ($scope, $q, $wrapState, $timeout, PageConfig, Entity) {
+ PageConfig.title = "Edit Policy";
var args = arguments;
- // TODO: Wait for backend data update
$scope.policyList = Entity.queryMetadata("policies/" + encodeURIComponent($wrapState.param.name));
-
$scope.policyList._promise.then(function () {
var policy = $scope.policyList[0];
@@ -64,27 +74,15 @@
});
});
- function policyEditController(policy, $scope, $wrapState, PageConfig, Entity) {
- $scope.newPolicy = !policy.name;
- $scope.policyLock = false;
-
+ function policyEditController(policy, $scope, $q, $wrapState, $timeout, PageConfig, Entity) {
$scope.publisherTypes = publisherTypes;
- $scope.selectedApplication = null;
- $scope.selectedStream = null;
-
- $scope.outputStream = "";
-
- $scope.partitionStream = null;
- $scope.partitionType = "GROUPBY";
- $scope.partitionColumns = {};
-
- $scope.publisherType = "org.apache.eagle.alert.engine.publisher.impl.AlertEmailPublisher";
- $scope.publisher = {
- dedupIntervalMin: "PT1M"
- };
- $scope.publisherProps = {};
+ PageConfig.navPath = [
+ {title: "Policy List", path: "/alert/policyList"},
+ {title: "Policy"}
+ ];
+ $scope.policy = policy;
$scope.policy = common.merge({
name: "",
description: "",
@@ -95,202 +93,302 @@
value: ""
},
partitionSpec: [],
- parallelismHint: 2
- }, policy);
-
- $scope.policy.definition = {
- type: $scope.policy.definition.type,
- value: $scope.policy.definition.value
- };
-
+ parallelismHint: 5
+ }, $scope.policy);
console.log("[Policy]", $scope.policy);
- // =========================================================
- // = Check Logic =
- // =========================================================
- $scope.checkBasicInfo = function () {
- return !!$scope.policy.name;
- };
-
- $scope.checkAlertStream = function () {
- return $scope.checkBasicInfo() &&
- $scope.policy.inputStreams.length > 0 &&
- $scope.policy.outputStreams.length > 0;
- };
-
- $scope.checkNumber = function (str) {
- str = (str + "").trim();
- return str !== "" && common.number.isNumber(Number(str));
- };
-
- $scope.checkDefinition = function () {
- return $scope.checkAlertStream() &&
- !!$scope.policy.definition.value.trim() &&
- $scope.policy.parallelismHint > 0;
+ var cacheSearchSourceKey;
+ var searchApplications;
+ $scope.searchSourceKey = "";
+ $scope.applications = {};
+ $scope.newPolicy = !!$scope.policy.name;
+
+ // ==============================================================
+ // = UI =
+ // ==============================================================
+ $scope.sourceTab = "all";
+ $scope.setSourceTab = function (tab) {
+ $scope.sourceTab = tab;
};
- // =========================================================
- // = Stream =
- // =========================================================
- $scope.refreshStreamSelect = function() {
- var appStreamList;
-
- if(!$scope.selectedApplication) {
- $scope.selectedApplication = common.getKeys($scope.applications)[0];
- }
-
- appStreamList = $scope.applications[$scope.selectedApplication] || [];
- if(!common.array.find($scope.selectedStream, appStreamList)) {
- $scope.selectedStream = appStreamList[0].streamId;
- }
- if(!common.array.find($scope.partitionStream, $scope.policy.inputStreams)) {
- $scope.partitionStream = $scope.policy.inputStreams[0];
+ // ==============================================================
+ // = Input Stream =
+ // ==============================================================
+ $scope.getSearchApplication = function() {
+ if(cacheSearchSourceKey !== $scope.searchSourceKey.toUpperCase()) {
+ cacheSearchSourceKey = $scope.searchSourceKey.toUpperCase();
+
+ searchApplications = {};
+ $.each($scope.applications, function (appName, streams) {
+ if(appName.toUpperCase().indexOf(cacheSearchSourceKey) >= 0) {
+ searchApplications[appName] = streams;
+ } else {
+ var streamList = [];
+ $.each(streams, function (i, stream) {
+ if(stream.streamId.toUpperCase().indexOf(cacheSearchSourceKey) >= 0) {
+ streamList.push(stream);
+ }
+ });
+
+ if(streamList.length > 0) {
+ searchApplications[appName] = streamList;
+ }
+ }
+ });
}
+ return searchApplications;
};
+ $scope.streams = {};
$scope.streamList = Entity.queryMetadata("streams");
$scope.streamList._then(function () {
$scope.applications = {};
+ cacheSearchSourceKey = null;
$.each($scope.streamList, function (i, stream) {
var list = $scope.applications[stream.dataSource] = $scope.applications[stream.dataSource] || [];
list.push(stream);
+ $scope.streams[stream.streamId] = stream;
});
-
- console.log("=>", $scope.streamList);
- $scope.refreshStreamSelect();
});
- $scope.getStreamList = function () {
- return common.array.minus($scope.streamList, $scope.policy.inputStreams, "streamId", "");
+ $scope.isInputStreamSelected = function (streamId) {
+ return $.inArray(streamId, $scope.policy.inputStreams) >= 0;
};
- $scope.addStream = function () {
- $scope.policy.inputStreams.push($scope.selectedStream);
- $scope.refreshStreamSelect();
- };
+ /*$scope.checkInputStream = function (streamId) {
+ if($scope.isInputStreamSelected(streamId)) {
+ $scope.policy.inputStreams = common.array.remove(streamId, $scope.policy.inputStreams);
+ } else {
+ $scope.policy.inputStreams.push(streamId);
+ }
+ };*/
- $scope.removeStream = function (streamId) {
- $scope.policy.inputStreams = common.array.remove(streamId, $scope.policy.inputStreams);
- $scope.refreshStreamSelect();
+ // ==============================================================
+ // = Definition =
+ // ==============================================================
+ var checkPromise;
+ $scope.definitionMessage = "";
+ $scope.checkDefinition = function () {
+ $timeout.cancel(checkPromise);
+ checkPromise = $timeout(function () {
+ Entity.post("metadata/policies/parse", $scope.policy.definition.value)._then(function (res) {
+ var data = res.data;
+ console.log(data);
+ if(data.success) {
+ $scope.definitionMessage = "";
+ if(data.policyExecutionPlan) {
+ // Input streams
+ $scope.policy.inputStreams = $.map(data.policyExecutionPlan.inputStreams, function (value, stream) {
+ return stream;
+ });
+
+ // Output streams
+ var outputStreams= $.map(data.policyExecutionPlan.outputStreams, function (value, stream) {
+ return stream;
+ });
+ $scope.policy.outputStreams = outputStreams.concat();
+ $scope.outputStreams = outputStreams;
+
+ // Partition
+ $scope.policy.partitionSpec = data.policyExecutionPlan.streamPartitions;
+ }
+ } else {
+ $scope.definitionMessage = data.message;
+ }
+ });
+ }, 350);
};
- $scope.checkAddStream = function (streamId) {
- return !common.array.find(streamId, $scope.policy.inputStreams);
- };
+ // ==============================================================
+ // = Output Stream =
+ // ==============================================================
+ $scope.outputStreams = ($scope.policy.outputStreams || []).concat();
- $scope.addOutputStream = function () {
- $scope.policy.outputStreams.push($scope.outputStream);
- $scope.outputStream = "";
+ $scope.isOutputStreamSelected = function (streamId) {
+ return $.inArray(streamId, $scope.policy.outputStreams) >= 0;
};
- $scope.removeOutputStream = function (streamId) {
- $scope.policy.outputStreams = common.array.remove(streamId, $scope.policy.outputStreams);
+ $scope.checkOutputStream = function (streamId) {
+ if($scope.isOutputStreamSelected(streamId)) {
+ $scope.policy.outputStreams = common.array.remove(streamId, $scope.policy.outputStreams);
+ } else {
+ $scope.policy.outputStreams.push(streamId);
+ }
};
- $scope.checkAddOutputStream = function () {
- return $scope.outputStream !== "" && !common.array.find($scope.outputStream, $scope.policy.outputStreams);
- };
-
- // =========================================================
- // = Definition =
- // =========================================================
- $scope.getPartitionColumns = function () {
- var stream = common.array.find($scope.partitionStream, $scope.streamList, "streamId");
- return (stream || {}).columns;
- };
+ // ==============================================================
+ // = Partition =
+ // ==============================================================
+ $scope.partition = {};
$scope.addPartition = function () {
- $scope.policy.partitionSpec.push({
- streamId: $scope.partitionStream,
- type: $scope.partitionType,
- columns: $.map($scope.getPartitionColumns(), function (column) {
- return $scope.partitionColumns[column.name] ? column.name : null;
- })
- });
-
- $scope.partitionColumns = {};
+ $scope.partition = {
+ streamId: $scope.policy.inputStreams[0],
+ type: "GROUPBY",
+ columns: []
+ };
+ $(".modal[data-id='partitionMDL']").modal();
};
- $scope.checkAddPartition = function () {
- var match = false;
+ $scope.newPartitionCheckColumn = function (column) {
+ return $.inArray(column, $scope.partition.columns) >= 0;
+ };
- $.each($scope.getPartitionColumns(), function (i, column) {
- if($scope.partitionColumns[column.name]) {
- match = true;
- return false;
- }
- });
+ $scope.newPartitionClickColumn = function (column) {
+ if($scope.newPartitionCheckColumn(column)) {
+ $scope.partition.columns = common.array.remove(column, $scope.partition.columns);
+ } else {
+ $scope.partition.columns.push(column);
+ }
+ };
- return match;
+ $scope.addPartitionConfirm = function () {
+ $scope.policy.partitionSpec.push($scope.partition);
};
$scope.removePartition = function (partition) {
$scope.policy.partitionSpec = common.array.remove(partition, $scope.policy.partitionSpec);
};
- // =========================================================
- // = Publisher =
- // =========================================================
- $scope.publisherList = [];
-
- if(!$scope.newPolicy) {
- $scope.publisherList = Entity.queryMetadata("policies/" + encodeURIComponent($scope.policy.name) + "/publishments");
- }
+ // ==============================================================
+ // = Publisher =
+ // ==============================================================
+ $scope.publisherList = Entity.queryMetadata("publishments");
+ $scope.addPublisherType = "";
+ $scope.policyPublisherList = [];
+ $scope.publisher = {};
+
+ Entity.queryMetadata("policies/" + $scope.policy.name + "/publishments/")._then(function (res) {
+ $scope.policyPublisherList = $.map(res.data, function (publisher) {
+ return $.extend({
+ _exist: true
+ }, publisher);
+ });
+ });
$scope.addPublisher = function () {
- var publisherProps = {};
- $.each($scope.publisherTypes[$scope.publisherType], function (i, field) {
- publisherProps[field] = $scope.publisherProps[field] || "";
- });
- $scope.publisherList.push({
- name: $scope.publisher.name,
- type: $scope.publisherType,
- policyIds: [$scope.policy.name],
- properties: publisherProps,
- dedupIntervalMin: $scope.publisher.dedupIntervalMin,
- serializer : "org.apache.eagle.alert.engine.publisher.impl.StringEventSerializer"
- });
$scope.publisher = {
- dedupIntervalMin: "PT1M"
+ existPublisher: $scope.publisherList[0],
+ type: "org.apache.eagle.alert.engine.publisher.impl.AlertEmailPublisher",
+ dedupIntervalMin: "PT1M",
+ serializer : "org.apache.eagle.alert.engine.publisher.impl.StringEventSerializer",
+ properties: {}
};
- $scope.publisherProps = {};
+ if($scope.publisherList.length) {
+ $scope.addPublisherType = "exist";
+ } else {
+ $scope.addPublisherType = "new";
+ }
+
+ $(".modal[data-id='publisherMDL']").modal();
};
$scope.removePublisher = function (publisher) {
- $scope.publisherList = common.array.remove(publisher, $scope.publisherList);
+ $scope.policyPublisherList = common.array.remove(publisher, $scope.policyPublisherList);
+ };
+
+ $scope.checkPublisherName = function () {
+ if(common.array.find($scope.publisher.name, $scope.publisherList.concat($scope.policyPublisherList), ["name"])) {
+ return "'" + $scope.publisher.name + "' already exist";
+ }
+ return false;
+ };
+
+ $scope.addPublisherConfirm = function () {
+ if($scope.addPublisherType === "exist") {
+ $scope.publisher = $.extend({
+ _exist: true
+ }, $scope.publisher.existPublisher);
+ }
+ var properties = {};
+ $.each($scope.publisherTypes[$scope.publisher.type].fields, function (i, field) {
+ properties[field] = $scope.publisher.properties[field] || "";
+ });
+ $scope.policyPublisherList.push($.extend({}, $scope.publisher, {properties: properties}));
};
- $scope.checkAddPublisher = function () {
- return $scope.publisher.name &&
- !common.array.find($scope.publisher.name, $scope.publisherList, "name");
+ // ==============================================================
+ // = Save =
+ // ==============================================================
+ $scope.saveLock = false;
+ $scope.saveCheck = function () {
+ if($scope.saveLock) return false;
+
+ if(!$scope.policy.name) return false;
+ if(!$scope.policy.parallelismHint) return false;
+ if(!$scope.policy.definition.value) return false;
+ if(!$scope.policy.outputStreams.length) return false;
+ return true;
};
- // =========================================================
- // = Policy =
- // =========================================================
- $scope.createPolicy = function () {
- // TODO: Need check the policy or publisher exist.
+ $scope.saveConfirm = function () {
+ $scope.saveLock = true;
+
+ // Check policy
+ Entity.post("metadata/policies/validate", $scope.policy)._then(function (res) {
+ var validate = res.data;
+ console.log(validate);
+ if(!validate.success) {
+ $.dialog({
+ title: "OPS",
+ content: validate.message
+ });
+ $scope.saveLock = false;
+ return;
+ }
- $scope.policyLock = true;
+ // Create publisher
+ var publisherPromiseList = $.map($scope.policyPublisherList, function (publisher) {
+ if(publisher._exist) return;
- var policyPromise = Entity.create("metadata/policies", $scope.policy)._promise;
- var publisherPromiseList = $.map($scope.publisherList, function (publisher) {
- return Entity.create("metadata/publishments", publisher)._promise;
- });
- common.deferred.all(publisherPromiseList.concat(policyPromise)).then(function () {
- $.dialog({
- title: "Done",
- content: "Close dialog to go to the policy detail page."
- }, function () {
- $wrapState.go("policyDetail", {name: $scope.policy.name});
+ return Entity.create("metadata/publishments", publisher)._promise;
});
- }, function (failedList) {
- $.dialog({
- title: "OPS",
- content: $("<pre>").text(JSON.stringify(failedList, null, "\t"))
+ if(publisherPromiseList.length) console.log("Creating publishers...", $scope.policyPublisherList);
+
+ $q.all(publisherPromiseList).then(function () {
+ console.log("Create publishers success...");
+
+ // Create policy
+ Entity.create("metadata/policies", $scope.policy)._then(function () {
+ console.log("Create policy success...");
+ // Link with publisher
+ Entity.post("metadata/policies/" + $scope.policy.name + "/publishments/", $.map($scope.policyPublisherList, function (publisher) {
+ return publisher.name;
+ }))._then(function () {
+ // Link Success
+ $.dialog({
+ title: "Done",
+ content: "Close dialog to go to the policy detail page."
+ }, function () {
+ $wrapState.go("policyDetail", {name: $scope.policy.name});
+ });
+ }, function (res) {
+ // Link Failed
+ $.dialog({
+ title: "OPS",
+ content: "Link publishers failed:" + res.data.message
+ });
+ }).finally(function () {
+ $scope.policyLock = false;
+ });
+ }, function (res) {
+ $.dialog({
+ title: "OPS",
+ content: "Create policy failed: " + res.data.message
+ });
+ $scope.policyLock = false;
+ });
+ }, function (args) {
+ $.dialog({
+ title: "OPS",
+ content: "Create publisher failed. More detail please check output in 'console'."
+ });
+ console.log("Create publishers failed:", args);
+ $scope.policyLock = false;
});
- $scope.policyLock = false;
+ }, function () {
+ $scope.saveLock = false;
});
};
}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1f5126a1/eagle-server/src/main/webapp/app/dev/public/js/services/pageSrv.js
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/webapp/app/dev/public/js/services/pageSrv.js b/eagle-server/src/main/webapp/app/dev/public/js/services/pageSrv.js
index faea8ba..6327e22 100644
--- a/eagle-server/src/main/webapp/app/dev/public/js/services/pageSrv.js
+++ b/eagle-server/src/main/webapp/app/dev/public/js/services/pageSrv.js
@@ -53,7 +53,7 @@
var defaultPortalList = [
{name: "Home", icon: "home", path: "#/"},
{name: "Alert", icon: "bell", showFunc: checkApplication, list: [
- {name: "Explore Alerts", path: "#/alert/"},
+ // {name: "Explore Alerts", path: "#/alert/"},
{name: "Policies", path: "#/alert/policyList"},
{name: "Streams", path: "#/alert/streamList"},
{name: "Define Policy", path: "#/alert/policyCreate"}