You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@eagle.apache.org by hd...@apache.org on 2016/02/26 22:26:19 UTC
[1/9] incubator-eagle git commit: Eagle -168 - AlertEmail
Initialization Issue
Repository: incubator-eagle
Updated Branches:
refs/heads/branch-0.3.0 f9a921157 -> 1965b4aff
Eagle -168 - AlertEmail Initialization Issue
https://issues.apache.org/jira/browse/EAGLE-168
1. Fix the alert email initialization issue
2. Not to exclude the zookeeper jar from the assembly
Author: Kumar, Senthil
Reviewer: @yonzhang, @ralphsu
Closes #101
Project: http://git-wip-us.apache.org/repos/asf/incubator-eagle/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-eagle/commit/eb0734b6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-eagle/tree/eb0734b6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-eagle/diff/eb0734b6
Branch: refs/heads/branch-0.3.0
Commit: eb0734b6f1eb0d868f7d8d39d5e543a11d87d0bb
Parents: f9a9211
Author: Ralph, Su <su...@gmail.com>
Authored: Tue Feb 23 09:58:14 2016 +0800
Committer: Ralph, Su <su...@gmail.com>
Committed: Tue Feb 23 09:58:14 2016 +0800
----------------------------------------------------------------------
.../org/apache/eagle/notification/plugin/AlertEmailPlugin.java | 6 ++++--
.../src/assembly/eagle-topology-assembly.xml | 1 -
2 files changed, 4 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/eb0734b6/eagle-core/eagle-alert/eagle-alert-notification-plugin/src/main/java/org/apache/eagle/notification/plugin/AlertEmailPlugin.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-alert/eagle-alert-notification-plugin/src/main/java/org/apache/eagle/notification/plugin/AlertEmailPlugin.java b/eagle-core/eagle-alert/eagle-alert-notification-plugin/src/main/java/org/apache/eagle/notification/plugin/AlertEmailPlugin.java
index 0577f5c..f9a7ed3 100644
--- a/eagle-core/eagle-alert/eagle-alert-notification-plugin/src/main/java/org/apache/eagle/notification/plugin/AlertEmailPlugin.java
+++ b/eagle-core/eagle-alert/eagle-alert-notification-plugin/src/main/java/org/apache/eagle/notification/plugin/AlertEmailPlugin.java
@@ -48,9 +48,11 @@ public class AlertEmailPlugin implements NotificationPlugin {
private final static long DEFAULT_THREAD_POOL_SHRINK_TIME = 60000L; // 1 minute
private transient ThreadPoolExecutor executorPool;
private NotificationStatus status = new NotificationStatus();
+ private Config config;
@Override
public void init(Config config, List<AlertDefinitionAPIEntity> initAlertDefs) throws Exception {
+ this.config = config;
executorPool = new ThreadPoolExecutor(DEFAULT_THREAD_POOL_CORE_SIZE, DEFAULT_THREAD_POOL_MAX_SIZE, DEFAULT_THREAD_POOL_SHRINK_TIME, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
LOG.info(" Creating Email Generator... ");
for( AlertDefinitionAPIEntity entity : initAlertDefs ){
@@ -59,7 +61,7 @@ public class AlertEmailPlugin implements NotificationPlugin {
String notificationType = notificationConfigMap.get(NotificationConstants.NOTIFICATION_TYPE);
// for backward compatibility, default notification is email
if(notificationType == null || notificationType.equalsIgnoreCase(NotificationConstants.EMAIL_NOTIFICATION)){
- AlertEmailGenerator generator = createEmailGenerator(notificationConfigMap);
+ AlertEmailGenerator generator = createEmailGenerator( notificationConfigMap );
this.emailGenerators.put(entity.getTags().get(Constants.POLICY_ID), generator);
LOG.info("Successfully initialized email notification for policy " + entity.getTags().get(Constants.POLICY_ID) + ",with " + notificationConfigMap);
}
@@ -117,7 +119,7 @@ public class AlertEmailPlugin implements NotificationPlugin {
tplFileName = "ALERT_DEFAULT.vm";
}
AlertEmailGenerator gen = AlertEmailGeneratorBuilder.newBuilder().
- withEagleProps(EagleConfigFactory.load().getConfig().getObject("eagleProps")).
+ withEagleProps(this.config.getObject("eagleProps")).
withSubject(notificationConfig.get(NotificationConstants.SUBJECT)).
withSender(notificationConfig.get(NotificationConstants.SENDER)).
withRecipients(notificationConfig.get(NotificationConstants.RECIPIENTS)).
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/eb0734b6/eagle-topology-assembly/src/assembly/eagle-topology-assembly.xml
----------------------------------------------------------------------
diff --git a/eagle-topology-assembly/src/assembly/eagle-topology-assembly.xml b/eagle-topology-assembly/src/assembly/eagle-topology-assembly.xml
index e397efa..2a0d211 100644
--- a/eagle-topology-assembly/src/assembly/eagle-topology-assembly.xml
+++ b/eagle-topology-assembly/src/assembly/eagle-topology-assembly.xml
@@ -47,7 +47,6 @@
<exclude>asm:asm</exclude>
<exclude>org.apache.log4j.wso2:log4j</exclude>
<exclude>log4j:apache-log4j-extras</exclude>
- <exclude>org.apache.zookeeper:zookeeper</exclude>
</excludes>
</dependencySet>
</dependencySets>
[8/9] incubator-eagle git commit: EAGLE-139 EAGLE-163 Eagle UI
Modularization and fix bugs in policy extensions
Posted by hd...@apache.org.
EAGLE-139 EAGLE-163 Eagle UI Modularization and fix bugs in policy extensions
https://issues.apache.org/jira/browse/EAGLE-139
Each site contains multi applications. Application works for different monitoring purpose. Add there is no communication between applications. For example, Eagle Dam is a application for security monitoring.
Each application is made up with serval features. And feature can share between applications. Feature does the basic job of the application. For example, Policies & Alerts in Eagle DAM is the base feature. Each application includes customized application using this feature wills both display the policies & Alerts in navigation bar. If you want to extend the application, you can customize feature. But avoid modify original feature for special usage.
Author:
@zombieJ <ji...@ebay.com>
@haoch <ha...@apache.org>
@qingwen220 <qi...@ebay.com>
Reviewer:
@haoch <ha...@apache.org>
@qingwen220 <qi...@ebay.com>
@anyway1021 <zi...@ebay.com>
Closes #103
Project: http://git-wip-us.apache.org/repos/asf/incubator-eagle/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-eagle/commit/d37643b0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-eagle/tree/d37643b0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-eagle/diff/d37643b0
Branch: refs/heads/branch-0.3.0
Commit: d37643b0ae7c3fe22fe2794a9fa18ec74b8f9eb2
Parents: eb0734b
Author: Hao Chen <ha...@apache.org>
Authored: Thu Feb 25 18:25:07 2016 +0800
Committer: Hao Chen <ha...@apache.org>
Committed: Thu Feb 25 18:25:07 2016 +0800
----------------------------------------------------------------------
.../src/main/bin/eagle-create-table.rb | 54 +-
.../src/main/bin/eagle-drop-tables.sh | 26 +
eagle-assembly/src/main/bin/eagle-env.sh | 4 +
.../src/main/bin/eagle-service-init.sh | 6 +-
.../src/main/bin/eagle-topology-init.sh | 63 +-
.../main/bin/hbase-securitylog-schema-create.sh | 41 -
.../src/test/resources/str.siddhiext | 3 +
.../alert/resolver/SiteApplicationObject.java | 62 ++
.../alert/resolver/SiteApplicationResource.java | 189 ++++
.../alert/entity/AlertDataSourceEntity.java | 1 +
.../alert/entity/AlertEntityRepository.java | 7 +-
.../entity/ApplicationDescServiceEntity.java | 94 ++
.../alert/entity/FeatureDescServiceEntity.java | 59 +
.../alert/entity/GenericResourceEntity.java | 47 +
.../entity/SiteApplicationServiceEntity.java | 60 +
.../alert/entity/SiteDescServiceEntity.java | 48 +
.../apache/eagle/policy/common/Constants.java | 7 +
.../eagle/policy/dao/AlertDataSourceDAO.java | 25 -
.../policy/dao/AlertDataSourceDAOImpl.java | 61 -
.../src/main/resources/str.siddhiext | 4 +
.../generic/GenericEntityServiceResource.java | 41 +
.../src/main/resources/hadoop-metric-init.sh | 25 +-
.../dao/HbaseMetadataAccessConfigDAOImpl.java | 7 +-
.../src/main/resources/application.conf | 4 +-
.../security/hdfs/HDFSResourceUtils.java | 7 +-
.../hdfs/resolver/HDFSCommandResolver.java | 2 +
.../dao/HiveMetadataAccessConfigDAOImpl.java | 19 +-
.../src/main/resources/eagleSecurity.xml | 4 +-
eagle-webservice/src/main/webapp/Gruntfile.js | 31 +-
eagle-webservice/src/main/webapp/app/index.html | 137 ++-
.../webapp/app/partials/config/application.html | 103 ++
.../webapp/app/partials/config/feature.html | 64 ++
.../main/webapp/app/partials/config/site.html | 94 ++
.../webapp/app/partials/dam/alertDetail.html | 61 -
.../main/webapp/app/partials/dam/alertList.html | 83 --
.../src/main/webapp/app/partials/dam/login.html | 49 -
.../src/main/webapp/app/partials/dam/nvd3.html | 19 -
.../webapp/app/partials/dam/policyDetail.html | 171 ---
.../webapp/app/partials/dam/policyEdit.html | 359 ------
.../webapp/app/partials/dam/policyList.html | 98 --
.../webapp/app/partials/dam/sensitivity.html | 32 -
.../app/partials/dam/sensitivity/folder.html | 110 --
.../app/partials/dam/sensitivity/table.html | 150 ---
.../app/partials/dam/sensitivitySummary.html | 143 ---
.../main/webapp/app/partials/dam/siteList.html | 162 ---
.../webapp/app/partials/dam/streamList.html | 179 ---
.../main/webapp/app/partials/dam/summary.html | 45 -
.../app/partials/dam/userProfileDetail.html | 87 --
.../app/partials/dam/userProfileList.html | 138 ---
.../src/main/webapp/app/partials/landing.html | 12 +
.../src/main/webapp/app/partials/login.html | 49 +
.../main/webapp/app/public/css/animation.css | 46 +
.../src/main/webapp/app/public/css/main.css | 206 ++--
.../public/feature/classification/controller.js | 269 +++++
.../classification/page/sensitivity.html | 40 +
.../classification/page/sensitivity/folder.html | 110 ++
.../classification/page/sensitivity/table.html | 150 +++
.../app/public/feature/common/controller.js | 1023 +++++++++++++++++
.../public/feature/common/page/alertDetail.html | 61 +
.../public/feature/common/page/alertList.html | 69 ++
.../feature/common/page/dataSrcConfig.html | 125 +++
.../feature/common/page/policyDetail.html | 172 +++
.../public/feature/common/page/policyEdit.html | 359 ++++++
.../public/feature/common/page/policyList.html | 84 ++
.../app/public/feature/metadata/controller.js | 66 ++
.../feature/metadata/page/streamList.html | 84 ++
.../public/feature/userProfile/controller.js | 268 +++++
.../public/feature/userProfile/page/detail.html | 87 ++
.../public/feature/userProfile/page/list.html | 138 +++
.../webapp/app/public/images/favicon_white.png | Bin 0 -> 1621 bytes
.../src/main/webapp/app/public/js/app.config.js | 179 +--
.../src/main/webapp/app/public/js/app.js | 1042 +++++++-----------
.../src/main/webapp/app/public/js/app.ui.js | 140 +--
.../src/main/webapp/app/public/js/common.js | 435 ++++----
.../app/public/js/ctrl/alertController.js | 128 ---
.../webapp/app/public/js/ctrl/authController.js | 82 +-
.../public/js/ctrl/configurationController.js | 332 ++++++
.../webapp/app/public/js/ctrl/damController.js | 111 --
.../src/main/webapp/app/public/js/ctrl/main.js | 42 +
.../app/public/js/ctrl/policyController.js | 898 ---------------
.../app/public/js/ctrl/sensitivityController.js | 454 --------
.../webapp/app/public/js/ctrl/siteController.js | 209 ----
.../app/public/js/ctrl/streamController.js | 207 ----
.../app/public/js/ctrl/userProfileController.js | 261 -----
.../webapp/app/public/js/srv/applicationSrv.js | 168 +++
.../app/public/js/srv/authorizationSrv.js | 131 +++
.../webapp/app/public/js/srv/entitiesSrv.js | 281 +++++
.../src/main/webapp/app/public/js/srv/main.js | 19 +
.../main/webapp/app/public/js/srv/pageSrv.js | 131 +++
.../main/webapp/app/public/js/srv/siteSrv.js | 193 ++++
.../src/main/webapp/app/public/js/srv/uiSrv.js | 218 ++++
.../webapp/app/public/js/srv/wrapStateSrv.js | 109 ++
eagle-webservice/src/main/webapp/grunt.json | 5 +-
eagle-webservice/src/main/webapp/package.json | 9 +-
94 files changed, 6969 insertions(+), 5518 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-assembly/src/main/bin/eagle-create-table.rb
----------------------------------------------------------------------
diff --git a/eagle-assembly/src/main/bin/eagle-create-table.rb b/eagle-assembly/src/main/bin/eagle-create-table.rb
index cbef6f4..b1b790c 100644
--- a/eagle-assembly/src/main/bin/eagle-create-table.rb
+++ b/eagle-assembly/src/main/bin/eagle-create-table.rb
@@ -20,42 +20,28 @@ import org.apache.hadoop.hbase.HBaseConfiguration
import org.apache.hadoop.hbase.client.HBaseAdmin
def createEagleTable(admin, tableName)
- if !admin.tableExists(tableName)
- # create tableName, {NAME => 'f', VERSIONS => '1', BLOOMFILTER => 'ROW', COMPRESSION => 'GZ'}
- create tableName, {NAME => 'f', VERSIONS => '1', BLOOMFILTER => 'ROW', COMPRESSION => 'SNAPPY'}
- puts "Create Table #{tableName} successfully"
- elsif admin.isTableDisabled(tableName)
- admin.enableTable(tableName)
- puts "Table #{tableName} already exists"
- else
- puts "Table #{tableName} already exists"
- end
+ if !admin.tableExists(tableName)
+ # create tableName, {NAME => 'f', VERSIONS => '1', BLOOMFILTER => 'ROW', COMPRESSION => 'GZ'}
+ create tableName, {NAME => 'f', VERSIONS => '1', BLOOMFILTER => 'ROW', COMPRESSION => 'SNAPPY'}
+ puts "Create Table #{tableName} successfully"
+ elsif admin.isTableDisabled(tableName)
+ admin.enableTable(tableName)
+ puts "Table #{tableName} already exists"
+ else
+ puts "Table #{tableName} already exists"
+ end
end
conf = HBaseConfiguration.new
admin = HBaseAdmin.new(conf)
-createEagleTable(admin, 'alertdef')
-createEagleTable(admin, 'ipzone')
-createEagleTable(admin, 'streamMetadata')
-createEagleTable(admin, 'alertdetail')
-createEagleTable(admin, 'fileSensitivity')
-createEagleTable(admin, 'eaglehdfs_alert')
-createEagleTable(admin, 'streamdef')
-createEagleTable(admin, 'eagle_metric')
-createEagleTable(admin, 'alertDataSource')
-createEagleTable(admin, 'alertExecutor')
-createEagleTable(admin, 'alertStream')
-createEagleTable(admin, 'alertStreamSchema')
-createEagleTable(admin, 'hiveResourceSensitivity')
-createEagleTable(admin, 'hbaseResourceSensitivity')
-createEagleTable(admin, 'mlmodel')
-createEagleTable(admin, 'userprofile')
-createEagleTable(admin, 'hfdsusercommandpattern')
-createEagleTable(admin, 'appCommand')
-createEagleTable(admin, 'appDefinition')
-createEagleTable(admin, 'serviceAudit')
-createEagleTable(admin, 'aggregatedef')
-createEagleTable(admin, 'alertNotifications')
-
-exit
+if ARGV.empty?
+ puts "Table list is empty, please go back to bin/eagle-env.sh and export EAGLE_TABLE_LIST"
+ exit 1
+end
+
+tableListVal=ARGV.first
+
+tableListVal.split(' ').map { |i| createEagleTable(admin, i) }
+
+exit 0
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-assembly/src/main/bin/eagle-drop-tables.sh
----------------------------------------------------------------------
diff --git a/eagle-assembly/src/main/bin/eagle-drop-tables.sh b/eagle-assembly/src/main/bin/eagle-drop-tables.sh
new file mode 100644
index 0000000..37fb540
--- /dev/null
+++ b/eagle-assembly/src/main/bin/eagle-drop-tables.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# 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.
+
+source $(dirname $0)/eagle-env.sh
+
+commands=''
+for i in $EAGLE_TABLE_LIST; do
+ commands="disable '$i'\ndrop '$i'\n"$commands
+done
+
+echo -e $commands | hbase shell
+#echo commands | hbase shell -n > /dev/null 2>&1
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-assembly/src/main/bin/eagle-env.sh
----------------------------------------------------------------------
diff --git a/eagle-assembly/src/main/bin/eagle-env.sh b/eagle-assembly/src/main/bin/eagle-env.sh
index 79ff5fa..cfffa0d 100755
--- a/eagle-assembly/src/main/bin/eagle-env.sh
+++ b/eagle-assembly/src/main/bin/eagle-env.sh
@@ -42,3 +42,7 @@ export EAGLE_CLASSPATH=$EAGLE_HOME/conf
for file in $EAGLE_HOME/lib/share/*;do
EAGLE_CLASSPATH=$EAGLE_CLASSPATH:$file
done
+
+# EAGLE_TABLE_LIST
+export EAGLE_TABLE_LIST='alertdef ipzone streamMetadata alertdetail fileSensitivity eaglehdfs_alert streamdef eagle_metric alertExecutor alertStream alertStreamSchema hiveResourceSensitivity hbaseResourceSensitivity mlmodel userprofile hfdsusercommandpattern appCommand appDefinition serviceAudit aggregatedef alertNotifications eagleSiteDesc eagleSiteApplication eagleApplicationDesc eagleFeatureDesc eagle_metadata'
+
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-assembly/src/main/bin/eagle-service-init.sh
----------------------------------------------------------------------
diff --git a/eagle-assembly/src/main/bin/eagle-service-init.sh b/eagle-assembly/src/main/bin/eagle-service-init.sh
index 01bddb5..a9c1cb2 100755
--- a/eagle-assembly/src/main/bin/eagle-service-init.sh
+++ b/eagle-assembly/src/main/bin/eagle-service-init.sh
@@ -15,7 +15,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-eagle_bin=$(dirname $0)
+source $(dirname $0)/eagle-env.sh
###################################################
### create hbase tables for eagle
@@ -23,7 +23,7 @@ eagle_bin=$(dirname $0)
echo "Creating hbase tables for eagle ... "
-hbase shell $eagle_bin/eagle-create-table.rb
+hbase shell ${EAGLE_HOME}/bin/eagle-create-table.rb "$EAGLE_TABLE_LIST"
if [ $? = 0 ];then
echo "==> Successfully created hbase tables"
@@ -32,6 +32,4 @@ else
exit 1
fi
-echo "Finished initializing for eagle service"
-
exit 0
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-assembly/src/main/bin/eagle-topology-init.sh
----------------------------------------------------------------------
diff --git a/eagle-assembly/src/main/bin/eagle-topology-init.sh b/eagle-assembly/src/main/bin/eagle-topology-init.sh
index 03b2a9a..2a3032e 100755
--- a/eagle-assembly/src/main/bin/eagle-topology-init.sh
+++ b/eagle-assembly/src/main/bin/eagle-topology-init.sh
@@ -24,9 +24,38 @@ eagle_bin=$EAGLE_HOME/bin
#####################################################################
## AlertDataSource: data sources bound to sites
-echo "Importing AlertDataSourceService for HDFS... "
-curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertDataSourceService" -d '[{"prefix":"alertDataSource","tags":{"site" : "sandbox", "dataSource":"hdfsAuditLog"}, "enabled": "true", "config" : "{\"hdfsEndpoint\":\"hdfs://sandbox.hortonworks.com:8020\"}", "desc":"HDFS"}]'
+echo "Begin to initialize HBase tables ..."
+
+echo ""
+echo "Importing sample site ..."
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=SiteDescService" -d '[{"prefix":"eagleSiteDesc","tags":{"site" : "sandbox"}, "enabled": true}]'
+
+echo ""
+echo "Importing applications for sample site ..."
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=SiteApplicationService" -d '[{"prefix":"eagleSiteApplication","tags":{"site" : "sandbox", "application":"hdfsAuditLog"}, "enabled": true, "config" : "{\"hdfsEndpoint\":\"hdfs://sandbox.hortonworks.com:8020\"}"}]'
+
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=SiteApplicationService" -d '[{"prefix":"eagleSiteApplication","tags":{"site" : "sandbox", "application":"hbaseSecurityLog"}, "enabled": true, "config" : "{\"zkClientPort\":\"2181\", \"zkQuorum\":\"localhost\"}"}]'
+
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=SiteApplicationService" -d '[{"prefix":"eagleSiteApplication","tags":{"site" : "sandbox", "application":"hiveQueryLog"}, "enabled": true, "config":"{\"accessType\":\"metastoredb_jdbc\",\"password\":\"hive\",\"user\":\"hive\",\"jdbcDriverClassName\":\"com.mysql.jdbc.Driver\",\"jdbcUrl\":\"jdbc:mysql://sandbox.hortonworks.com/hive?createDatabaseIfNotExist=true\"}"}]'
+
+echo ""
+echo "Importing application definitions ..."
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=ApplicationDescService" -d '[{"prefix":"eagleApplicationDesc","tags":{"application":"hdfsAuditLog"},"desc":"HDFS audit log security check application","alias":"HDFS","group":"DAM","features":["common","classification","userProfile","metadata"],"config":"{\n\t\"view\": {\n\t\t\"prefix\": \"fileSensitivity\",\n\t\t\"service\": \"FileSensitivityService\",\n\t\t\"keys\": [\n\t\t\t\"filedir\",\n\t\t\t\"sensitivityType\"\n\t\t],\n\t\t\"type\": \"folder\",\n\t\t\"api\": \"hdfsResource\"\n\t}\n}"}]'
+
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=ApplicationDescService" -d '[{"prefix":"eagleApplicationDesc","tags":{"application":"hbaseSecurityLog"},"desc":"HBASE audit log security check application","alias":"HBASE","group":"DAM","features":["common","classification","userProfile","metadata"],"config":"{\n\t\"view\": {\n\t\t\"prefix\": \"hbaseResourceSensitivity\",\n\t\t\"service\": \"HbaseResourceSensitivityService\",\n\t\t\"keys\": [\n\t\t\t\"hbaseResource\",\n\t\t\t\"sensitivityType\"\n\t\t],\n\t\t\"type\": \"table\",\n\t\t\"api\": {\n\t\t\t\"database\": \"hbaseResource/namespaces\",\n\t\t\t\"table\": \"hbaseResource/tables\",\n\t\t\t\"column\": \"hbaseResource/columns\"\n\t\t},\n\t\t\"mapping\": {\n\t\t\t\"database\": \"namespace\",\n\t\t\t\"table\": \"table\",\n\t\t\t\"column\": \"columnFamily\"\n\t\t}\n\t}\n}"}]'
+
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=ApplicationDescService" -d '[{"prefix":"eagleApplicationDesc","tags":{"application":"hiveQueryLog"},"desc":"Hive query log security check application","alias":"HIVE","group":"DAM","features":["common","classification","userProfile","metadata"], "config":"{\n\t\"view\": {\n\t\t\"prefix\": \"hiveResourceSensitivity\",\n\t\t\"service\": \"HiveResourceSensitivityService\",\n\t\t\"keys\": [\n\t\t\t\"hiveResource\",\n\t\t\t\"sensitivityType\"\n\t\t],\n\t\t\"type\": \"table\",\n\t\t\"api\": {\n\t\t\t\"database\": \"hiveResource/databases\",\n\t\t\t\"table\": \"hiveResource/tables\",\n\t\t\t\"column\": \"hiveResource/columns\"\n\t\t},\n\t\t\"mapping\": {\n\t\t\t\"database\": \"database\",\n\t\t\t\"table\": \"table\",\n\t\t\t\"column\": \"column\"\n\t\t}\n\t}\n}"}]'
+
+echo ""
+echo "Importing feature definitions ..."
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=FeatureDescService" -d '[{"prefix":"eagleFeatureDesc","tags":{"feature":"common"},"desc":"Provide the Policy & Alert feature.","version":"01"}]'
+
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=FeatureDescService" -d '[{"prefix":"eagleFeatureDesc","tags":{"feature":"classification"},"desc":"Sensitivity browser of the data classification.","version":"01"}]'
+
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=FeatureDescService" -d '[{"prefix":"eagleFeatureDesc","tags":{"feature":"userProfile"},"desc":"Machine learning of the user profile","version":"01"}]'
+
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=FeatureDescService" -d '[{"prefix":"eagleFeatureDesc","tags":{"feature":"metadata"},"desc":"Stream metadata viewer","version":"01"}]'
## AlertStreamService: alert streams generated from data source
@@ -44,14 +73,32 @@ echo ""
echo "Importing AlertStreamSchemaService for HDFS... "
curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertStreamSchemaService" -d '[{"prefix":"alertStreamSchema","tags":{"dataSource":"hdfsAuditLog","streamName":"hdfsAuditLogEventStream","attrName":"src"},"attrDescription":"source directory or file, such as /tmp","attrType":"string","category":"","attrValueResolver":"org.apache.eagle.service.security.hdfs.resolver.HDFSResourceResolver"},{"prefix":"alertStreamSchema","tags":{"dataSource":"hdfsAuditLog","streamName":"hdfsAuditLogEventStream","attrName":"dst"},"attrDescription":"destination directory, such as /tmp","attrType":"string","category":"","attrValueResolver":"org.apache.eagle.service.security.hdfs.resolver.HDFSResourceResolver"},{"prefix":"alertStreamSchema","tags":{"dataSource":"hdfsAuditLog","streamName":"hdfsAuditLogEventStream","attrName":"host"},"attrDescription":"hostname, such as loc
alhost","attrType":"string","category":"","attrValueResolver":""},{"prefix":"alertStreamSchema","tags":{"dataSource":"hdfsAuditLog","streamName":"hdfsAuditLogEventStream","attrName":"timestamp"},"attrDescription":"milliseconds of the datetime","attrType":"long","category":"","attrValueResolver":""},{"prefix":"alertStreamSchema","tags":{"dataSource":"hdfsAuditLog","streamName":"hdfsAuditLogEventStream","attrName":"allowed"},"attrDescription":"true, false or none","attrType":"bool","category":"","attrValueResolver":""},{"prefix":"alertStreamSchema","tags":{"dataSource":"hdfsAuditLog","streamName":"hdfsAuditLogEventStream","attrName":"user"},"attrDescription":"process user","attrType":"string","category":"","attrValueResolver":""},{"prefix":"alertStreamSchema","tags":{"dataSource":"hdfsAuditLog","streamName":"hdfsAuditLogEventStream","attrName":"cmd"},"attrDescription":"file/directory operation, such as getfileinfo, open, listStatus and so on","attrType":"string","category":"","attrVal
ueResolver":"org.apache.eagle.service.security.hdfs.resolver.HDFSCommandResolver"},{"prefix":"alertStreamSchema","tags":{"dataSource":"hdfsAuditLog","streamName":"hdfsAuditLogEventStream","attrName":"sensitivityType"},"attrDescription":"mark such as AUDITLOG, SECURITYLOG","attrType":"string","category":"","attrValueResolver":"org.apache.eagle.service.security.hdfs.resolver.HDFSSensitivityTypeResolver"},{"prefix":"alertStreamSchema","tags":{"dataSource":"hdfsAuditLog","streamName":"hdfsAuditLogEventStream","attrName":"securityZone"},"attrDescription":"","attrType":"string","category":"","attrValueResolver":""}]'
+
#####################################################################
-# Import stream metadata for HIVE
+# Import stream metadata for HBASE
#####################################################################
-## AlertDataSource: data sources bound to sites
+#### AlertStreamService: alert streams generated from data source
+echo ""
+echo "Importing AlertStreamService for HBASE... "
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertStreamService" -d '[{"prefix":"alertStream","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream"},"desc":"alert event stream from hbase security audit log"}]'
+
+
+#### AlertExecutorService: what alert streams are consumed by alert executor
+echo ""
+echo "Importing AlertExecutorService for HBASE... "
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertExecutorService" -d '[{"prefix":"alertExecutor","tags":{"dataSource":"hbaseSecurityLog","alertExecutorId":"hbaseSecurityLogAlertExecutor","streamName":"hbaseSecurityLogEventStream"},"desc":"alert executor for hbase security log event stream"}]'
+
+
+#### AlertStreamSchemaService: schema for event from alert stream
echo ""
-echo "Importing AlertDataSourceService for HIVE... "
-curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertDataSourceService" -d '[{"prefix":"alertDataSource","tags":{"site" : "sandbox", "dataSource":"hiveQueryLog"},"enabled": "true", "config" : "{\"accessType\":\"metastoredb_jdbc\",\"password\":\"hive\",\"user\":\"hive\",\"jdbcDriverClassName\":\"com.mysql.jdbc.Driver\",\"jdbcUrl\":\"jdbc:mysql://sandbox.hortonworks.com/hive?createDatabaseIfNotExist=true\"}", "desc":"HIVE"}]'
+echo "Importing AlertStreamSchemaService for HBASE... "
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertStreamSchemaService" -d '[{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"host"},"attrDescription":"remote ip address to access hbase","attrType":"string","category":"","attrValueResolver":""},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"request"},"attrDescription":"","attrType":"string","category":"","attrValueResolver":"org.apache.eagle.service.security.hbase.resolver.HbaseRequestResolver"},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"status"},"attrDescription":"access status: allowed or denied","attrType":"string","category":"","attrValueResolver":""},{"pre
fix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"user"},"attrDescription":"hbase user","attrType":"string","category":"","attrValueResolver":""},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"timestamp"},"attrDescription":"milliseconds of the datetime","attrType":"long","category":"","attrValueResolver":""},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"scope"},"attrDescription":"the resources which users are then granted specific permissions (Read, Write, Execute, Create, Admin) against","attrType":"string","category":"","attrValueResolver":"org.apache.eagle.service.security.hbase.resolver.HbaseMetadataResolver"},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"action"},"attrDescripti
on":"action types, such as read, write, create, execute, and admin","attrType":"string","category":"","attrValueResolver":"org.apache.eagle.service.security.hbase.resolver.HbaseActionResolver"},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"sensitivityType"},"attrDescription":"","attrType":"string","category":"","attrValueResolver":"org.apache.eagle.service.security.hbase.resolver.HbaseSensitivityTypeResolver"}]'
+
+
+#####################################################################
+# Import stream metadata for HIVE
+#####################################################################
## AlertStreamService: alert streams generated from data source
echo ""
@@ -71,9 +118,7 @@ curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:a
#####################################################################
# Import stream metadata for UserProfile
#####################################################################
-echo ""
-echo "Importing AlertDataSourceService for USERPROFILE"
-curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertDataSourceService" -d '[{"prefix":"alertDataSource","tags":{"site" : "sandbox", "dataSource":"userProfile"}, "enabled": "true", "config" : "{\"features\":\"getfileinfo,open,listStatus,setTimes,setPermission,rename,mkdirs,create,setReplication,contentSummary,delete,setOwner,fsck\"}", "desc":"USERPROFILE"}]'
+
echo ""
echo "Importing AlertDefinitionService for USERPROFILE"
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-assembly/src/main/bin/hbase-securitylog-schema-create.sh
----------------------------------------------------------------------
diff --git a/eagle-assembly/src/main/bin/hbase-securitylog-schema-create.sh b/eagle-assembly/src/main/bin/hbase-securitylog-schema-create.sh
deleted file mode 100755
index 7cdd6de..0000000
--- a/eagle-assembly/src/main/bin/hbase-securitylog-schema-create.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-source $(dirname $0)/eagle-env.sh
-
-echo "Importing AlertDataSourceService for HBase... "
-
-#### AlertStreamService: alert streams generated from data source
-
-curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertStreamService" -d '[{"prefix":"alertStream","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream"},"desc":"alert event stream from hbase security audit log"}]'
-
-
-#### AlertExecutorService: what alert streams are consumed by alert executor
-
-curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertExecutorService" -d '[{"prefix":"alertExecutor","tags":{"dataSource":"hbaseSecurityLog","alertExecutorId":"hbaseSecurityLogAlertExecutor","streamName":"hbaseSecurityLogEventStream"},"desc":"alert executor for hbase security log event stream"}]'
-
-
-#### AlertStreamSchemaService: schema for event from alert stream
-
-curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertStreamSchemaService" -d '[{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"host"},"attrDescription":"remote ip address to access hbase","attrType":"string","category":"","attrValueResolver":""},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"request"},"attrDescription":"","attrType":"string","category":"","attrValueResolver":"org.apache.eagle.service.security.hbase.resolver.HbaseRequestResolver"},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"status"},"attrDescription":"access status: allowed or denied","attrType":"string","category":"","attrValueResolver":""},{"pre
fix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"user"},"attrDescription":"hbase user","attrType":"string","category":"","attrValueResolver":""},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"timestamp"},"attrDescription":"milliseconds of the datetime","attrType":"long","category":"","attrValueResolver":""},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"scope"},"attrDescription":"the resources which users are then granted specific permissions (Read, Write, Execute, Create, Admin) against","attrType":"string","category":"","attrValueResolver":"org.apache.eagle.service.security.hbase.resolver.HbaseMetadataResolver"},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"action"},"attrDescripti
on":"action types, such as read, write, create, execute, and admin","attrType":"string","category":"","attrValueResolver":"org.apache.eagle.service.security.hbase.resolver.HbaseActionResolver"},{"prefix":"alertStreamSchema","tags":{"dataSource":"hbaseSecurityLog","streamName":"hbaseSecurityLogEventStream","attrName":"sensitivityType"},"attrDescription":"","attrType":"string","category":"","attrValueResolver":"org.apache.eagle.service.security.hbase.resolver.HbaseSensitivityTypeResolver"}]'
-
-echo ""
-
-## AlertDataSource: data sources bound to sites
-echo "Importing AlertDataSourceService for hbase... "
-
-curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertDataSourceService" -d '[{"prefix":"alertDataSource","tags":{"site":"sandbox","dataSource":"hbaseSecurityLog"},"enabled":"true","config":"{\"zkClientPort\":\"2181\", \"zkQuorum\":\"localhost\"}","desc":"HBASE"}]'
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-alert/eagle-alert-process/src/test/resources/str.siddhiext
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-alert/eagle-alert-process/src/test/resources/str.siddhiext b/eagle-core/eagle-alert/eagle-alert-process/src/test/resources/str.siddhiext
index 6b64e53..435b4c3 100644
--- a/eagle-core/eagle-alert/eagle-alert-process/src/test/resources/str.siddhiext
+++ b/eagle-core/eagle-alert/eagle-alert-process/src/test/resources/str.siddhiext
@@ -31,6 +31,9 @@ trim=org.wso2.siddhi.extension.string.TrimFunctionExtension
upper=org.wso2.siddhi.extension.string.UpperFunctionExtension
hex=org.wso2.siddhi.extension.string.HexFunctionExtension
unhex=org.wso2.siddhi.extension.string.UnhexFunctionExtension
+contains=org.wso2.siddhi.extension.string.ContainsFunctionExtension
+
+# Eagle Siddhi Extension
equalsIgnoreCase=org.apache.eagle.policy.siddhi.extension.EqualsIgnoreCaseExtension
containsIgnoreCase=org.apache.eagle.policy.siddhi.extension.ContainsIgnoreCaseExtension
regexpIgnoreCase=org.apache.eagle.policy.siddhi.extension.RegexpIgnoreCaseFunctionExtension
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-alert/eagle-alert-service/src/main/java/org/apache/eagle/service/alert/resolver/SiteApplicationObject.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-alert/eagle-alert-service/src/main/java/org/apache/eagle/service/alert/resolver/SiteApplicationObject.java b/eagle-core/eagle-alert/eagle-alert-service/src/main/java/org/apache/eagle/service/alert/resolver/SiteApplicationObject.java
new file mode 100644
index 0000000..42f95f7
--- /dev/null
+++ b/eagle-core/eagle-alert/eagle-alert-service/src/main/java/org/apache/eagle/service/alert/resolver/SiteApplicationObject.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.eagle.service.alert.resolver;
+
+
+import org.apache.eagle.alert.entity.SiteApplicationServiceEntity;
+import org.apache.eagle.log.base.taggedlog.TaggedLogAPIEntity;
+
+import java.util.List;
+import java.util.Map;
+
+public class SiteApplicationObject extends TaggedLogAPIEntity {
+
+ public Boolean getEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(Boolean enabled) {
+ this.enabled = enabled;
+ valueChanged("enabled");
+ }
+
+ public List<SiteApplicationServiceEntity> getApplications() {
+ return applications;
+ }
+
+ public void setApplications(List<SiteApplicationServiceEntity> applications) {
+ this.applications = applications;
+ valueChanged("applicationList");
+ }
+
+ @Override
+ public Map<String, String> getTags() {
+ return tags;
+ }
+
+ @Override
+ public void setTags(Map<String, String> tags) {
+ this.tags = tags;
+ valueChanged("tags");
+ }
+
+ Map<String, String> tags;
+ Boolean enabled;
+ List<SiteApplicationServiceEntity> applications;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-alert/eagle-alert-service/src/main/java/org/apache/eagle/service/alert/resolver/SiteApplicationResource.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-alert/eagle-alert-service/src/main/java/org/apache/eagle/service/alert/resolver/SiteApplicationResource.java b/eagle-core/eagle-alert/eagle-alert-service/src/main/java/org/apache/eagle/service/alert/resolver/SiteApplicationResource.java
new file mode 100644
index 0000000..903a220
--- /dev/null
+++ b/eagle-core/eagle-alert/eagle-alert-service/src/main/java/org/apache/eagle/service/alert/resolver/SiteApplicationResource.java
@@ -0,0 +1,189 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.eagle.service.alert.resolver;
+
+import org.apache.eagle.alert.entity.ApplicationDescServiceEntity;
+import org.apache.eagle.alert.entity.SiteApplicationServiceEntity;
+import org.apache.eagle.alert.entity.SiteDescServiceEntity;
+import org.apache.eagle.log.base.taggedlog.TaggedLogAPIEntity;
+import org.apache.eagle.log.entity.GenericServiceAPIResponseEntity;
+import org.apache.eagle.policy.common.Constants;
+import org.apache.eagle.service.generic.GenericEntityServiceResource;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.type.TypeFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.*;
+
+@Path(SiteApplicationResource.ROOT_PATH)
+public class SiteApplicationResource {
+ private final static Logger LOG = LoggerFactory.getLogger(SiteApplicationResource.class);
+ private final static GenericEntityServiceResource resource = new GenericEntityServiceResource();
+ public final static String ROOT_PATH = "/module";
+
+ @Path("site")
+ @DELETE
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public GenericServiceAPIResponseEntity deleteSite(@QueryParam("site") String site) {
+ String siteQuery = Constants.SITE_DESCRIPTION_SERVICE_ENDPOINT_NAME+ "[@site=\"" + site + "\"]{*}";
+ String siteApplicationQuery = Constants.SITE_APPLICATION_SERVICE_ENDPOINT_NAME + "[@site=\"" + site + "\"]{*}";
+ int pageSize = Integer.MAX_VALUE;
+
+ GenericServiceAPIResponseEntity response = resource.deleteByQuery(siteQuery, null, null, pageSize, null, false, false, 0L, 0, true, 0, null, false);
+ if(response.isSuccess()) {
+ response = resource.deleteByQuery(siteApplicationQuery, null, null, pageSize, null, false, false, 0L, 0, true, 0, null, false);
+ if(!response.isSuccess()) {
+ LOG.error(response.getException());
+ }
+ } else {
+ LOG.error(response.getException());
+ }
+ return response;
+ }
+
+ @Path("application")
+ @DELETE
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public GenericServiceAPIResponseEntity deleteApplication(@QueryParam("application") String application) {
+ String applicationQuery = Constants.APPLICATION_DESCRIPTION_SERVICE_ENDPOINT_NAME+ "[@application=\"" + application + "\"]{*}";
+ String siteApplicationQuery = Constants.SITE_APPLICATION_SERVICE_ENDPOINT_NAME + "[@application=\"" + application + "\"]{*}";
+ int pageSize = Integer.MAX_VALUE;
+
+ GenericServiceAPIResponseEntity response = resource.deleteByQuery(applicationQuery, null, null, pageSize, null, false, false, 0L, 0, true, 0, null, false);
+ if(response.isSuccess()) {
+ response = resource.deleteByQuery(siteApplicationQuery, null, null, pageSize, null, false, false, 0L, 0, true, 0, null, false);
+ if(!response.isSuccess()) {
+ LOG.error(response.getException());
+ }
+ } else {
+ LOG.error(response.getException());
+ }
+ return response;
+ }
+
+ @Path("feature")
+ @DELETE
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public GenericServiceAPIResponseEntity deleteFeature(@QueryParam("feature") String feature) {
+ String featureQuery = Constants.FEATURE_DESCRIPTION_SERVICE_ENDPOINT_NAME+ "[@feature=\"" + feature + "\"]{*}";
+ String applicationQuery = Constants.APPLICATION_DESCRIPTION_SERVICE_ENDPOINT_NAME + "[]{*}";
+ int pageSize = Integer.MAX_VALUE;
+
+ GenericServiceAPIResponseEntity response = resource.deleteByQuery(featureQuery, null, null, pageSize, null, false, false, 0L, 0, true, 0, null, false);
+ if(response.isSuccess()) {
+ response = resource.search(applicationQuery, null, null, pageSize, null, false, false, 0L, 0, true, 0, null, false);
+ if(response.isSuccess()) {
+ List<ApplicationDescServiceEntity> entityList = response.getObj();
+ Boolean isModified = false;
+ for(ApplicationDescServiceEntity entity : entityList) {
+ if(entity.getFeatures().contains(feature)) {
+ List<String> features = entity.getFeatures();
+ features.remove(feature);
+ entity.setFeatures(features);
+ isModified = true;
+ }
+ }
+ if(isModified) {
+ response = resource.updateEntities(entityList, Constants.APPLICATION_DESCRIPTION_SERVICE_ENDPOINT_NAME);
+ }
+ }
+ }
+ if(!response.isSuccess()) {
+ LOG.error(response.getException());
+ }
+ return response;
+ }
+
+ @Path("siteApplication")
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public GenericServiceAPIResponseEntity createSiteApplications(InputStream inputStream) {
+ GenericServiceAPIResponseEntity response = new GenericServiceAPIResponseEntity<>();
+ int pageSize = Integer.MAX_VALUE;
+ try {
+ List<SiteApplicationObject> entities = (List<SiteApplicationObject>) unmarshalSiteApplicationEntities(inputStream);
+ if(entities == null) {
+ throw new IllegalArgumentException("cannot convert to SiteApplicationObject");
+ }
+ List<SiteDescServiceEntity> siteEntities = new LinkedList<>();
+ List<SiteApplicationServiceEntity> applicationEntities = new LinkedList<>();
+ Set<String> sites = new HashSet<>();
+ for(SiteApplicationObject e : entities) {
+ sites.add(e.getTags().get("site"));
+ SiteDescServiceEntity entity = new SiteDescServiceEntity();
+ entity.setEnabled(e.getEnabled());
+ entity.setTags(e.getTags());
+ siteEntities.add(entity);
+ applicationEntities.addAll(e.getApplications());
+ }
+ response = resource.updateEntities(siteEntities, Constants.SITE_DESCRIPTION_SERVICE_ENDPOINT_NAME);
+ if(response.isSuccess()) {
+ String query = buildQueryWithAttributeList(Constants.SITE_APPLICATION_SERVICE_ENDPOINT_NAME, "site", sites);
+ LOG.info("query=" + query);
+ response = resource.search(query, null, null, pageSize, null, false, false, 0L, 0, true, 0, null, false);
+ if(response.isSuccess()) {
+ List<SiteApplicationServiceEntity> applications = response.getObj();
+ for(SiteApplicationServiceEntity app : applications) {
+ app.setEnabled(false);
+ }
+ response = resource.updateEntities(applications, Constants.SITE_APPLICATION_SERVICE_ENDPOINT_NAME);
+ if(response.isSuccess()) {
+ response = resource.updateEntities(applicationEntities, Constants.SITE_APPLICATION_SERVICE_ENDPOINT_NAME);
+ }
+ }
+ }
+ if(!response.isSuccess()) {
+ LOG.error(response.getException());
+ }
+ } catch (Exception ex) {
+ LOG.error(ex.getMessage(), ex);
+ response.setException(ex);
+ }
+ return response;
+ }
+
+ private String buildQueryWithAttributeList(String serviceName, String attr, Set<String> sets) {
+ StringBuilder builder = new StringBuilder(serviceName + "[");
+ String attribute = "@" + attr + "=";
+ String condition = " OR ";
+ for(String s : sets) {
+ String value = String.format("\"%s\"", s);
+ builder.append(attribute + value);
+ builder.append(condition);
+ }
+ String result = builder.substring(0, builder.length()-condition.length());
+ result = result + "]{*}";
+ return result;
+ }
+
+ private List<? extends TaggedLogAPIEntity> unmarshalSiteApplicationEntities(InputStream inputStream) throws IllegalAccessException, InstantiationException, IOException {
+ ObjectMapper objectMapper = new ObjectMapper();
+ return objectMapper.readValue(inputStream, TypeFactory.defaultInstance().constructCollectionType(LinkedList.class, SiteApplicationObject.class));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/AlertDataSourceEntity.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/AlertDataSourceEntity.java b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/AlertDataSourceEntity.java
index 173481d..0778ffc 100644
--- a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/AlertDataSourceEntity.java
+++ b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/AlertDataSourceEntity.java
@@ -30,6 +30,7 @@ import org.codehaus.jackson.map.annotate.JsonSerialize;
@JsonIgnoreProperties(ignoreUnknown = true)
@TimeSeries(false)
@Tags({"site", "dataSource"})
+@Deprecated
public class AlertDataSourceEntity extends TaggedLogAPIEntity{
@Column("a")
private boolean enabled;
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/AlertEntityRepository.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/AlertEntityRepository.java b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/AlertEntityRepository.java
index 0525126..507c482 100644
--- a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/AlertEntityRepository.java
+++ b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/AlertEntityRepository.java
@@ -26,8 +26,13 @@ public class AlertEntityRepository extends EntityRepository {
entitySet.add(AlertDefinitionAPIEntity.class);
entitySet.add(AlertStreamSchemaEntity.class);
entitySet.add(AlertStreamEntity.class);
- entitySet.add(AlertDataSourceEntity.class);
+ //entitySet.add(AlertDataSourceEntity.class);
entitySet.add(AlertExecutorEntity.class);
+ entitySet.add(ApplicationDescServiceEntity.class);
+ entitySet.add(FeatureDescServiceEntity.class);
+ entitySet.add(SiteDescServiceEntity.class);
+ entitySet.add(SiteApplicationServiceEntity.class);
+ this.registerEntity(GenericResourceEntity.class);
entitySet.add(AlertNotificationEntity.class);
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/ApplicationDescServiceEntity.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/ApplicationDescServiceEntity.java b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/ApplicationDescServiceEntity.java
new file mode 100644
index 0000000..76a2500
--- /dev/null
+++ b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/ApplicationDescServiceEntity.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.eagle.alert.entity;
+
+
+import org.apache.eagle.log.base.taggedlog.TaggedLogAPIEntity;
+import org.apache.eagle.log.entity.meta.*;
+import org.apache.eagle.policy.common.Constants;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import java.util.List;
+
+@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+@Table("eagleApplicationDesc")
+@ColumnFamily("f")
+@Prefix("eagleApplicationDesc")
+@Service(Constants.APPLICATION_DESCRIPTION_SERVICE_ENDPOINT_NAME)
+@JsonIgnoreProperties(ignoreUnknown = true)
+@TimeSeries(false)
+@Tags({"application"})
+public class ApplicationDescServiceEntity extends TaggedLogAPIEntity {
+ @Column("a")
+ private String desc;
+ @Column("b")
+ private String alias;
+ @Column("c")
+ private String group;
+ @Column("d")
+ private List<String> features;
+ @Column("e")
+ private String config;
+
+ public String getConfig() {
+ return config;
+ }
+
+ public void setConfig(String config) {
+ this.config = config;
+ valueChanged("config");
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public void setDesc(String desc) {
+ this.desc = desc;
+ valueChanged("desc");
+ }
+
+ public String getGroup() {
+ return group;
+ }
+
+ public void setGroup(String group) {
+ this.group = group;
+ valueChanged("group");
+ }
+
+ public String getAlias() {
+ return alias;
+ }
+
+ public void setAlias(String alias) {
+ this.alias = alias;
+ valueChanged("alias");
+ }
+
+ public List<String> getFeatures() {
+ return features;
+ }
+
+ public void setFeatures(List<String> features) {
+ this.features = features;
+ valueChanged("features");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/FeatureDescServiceEntity.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/FeatureDescServiceEntity.java b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/FeatureDescServiceEntity.java
new file mode 100644
index 0000000..4fc6dac
--- /dev/null
+++ b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/FeatureDescServiceEntity.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.eagle.alert.entity;
+
+
+import org.apache.eagle.log.base.taggedlog.TaggedLogAPIEntity;
+import org.apache.eagle.log.entity.meta.*;
+import org.apache.eagle.policy.common.Constants;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+@Table("eagleFeatureDesc")
+@ColumnFamily("f")
+@Prefix("eagleFeatureDesc")
+@Service(Constants.FEATURE_DESCRIPTION_SERVICE_ENDPOINT_NAME)
+@JsonIgnoreProperties(ignoreUnknown = true)
+@TimeSeries(false)
+@Tags({"feature"})
+public class FeatureDescServiceEntity extends TaggedLogAPIEntity {
+ @Column("a")
+ private String desc;
+ @Column("b")
+ private String version;
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ valueChanged("version");
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public void setDesc(String desc) {
+ this.desc = desc;
+ valueChanged("desc");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/GenericResourceEntity.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/GenericResourceEntity.java b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/GenericResourceEntity.java
new file mode 100644
index 0000000..c855499
--- /dev/null
+++ b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/GenericResourceEntity.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.eagle.alert.entity;
+
+import org.apache.eagle.log.base.taggedlog.TaggedLogAPIEntity;
+import org.apache.eagle.log.entity.meta.*;
+import org.apache.eagle.policy.common.Constants;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+@Table("eagle_metadata")
+@ColumnFamily("f")
+@Prefix("generic_resource")
+@Service(Constants.GENERIC_RESOURCE_SERVICE_ENDPOINT_NAME)
+@JsonIgnoreProperties(ignoreUnknown = true)
+@TimeSeries(false)
+@Tags({"site", "name"})
+public class GenericResourceEntity extends TaggedLogAPIEntity {
+ @Column("a")
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ valueChanged("value");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/SiteApplicationServiceEntity.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/SiteApplicationServiceEntity.java b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/SiteApplicationServiceEntity.java
new file mode 100644
index 0000000..5eea4b3
--- /dev/null
+++ b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/SiteApplicationServiceEntity.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.eagle.alert.entity;
+
+
+import org.apache.eagle.log.base.taggedlog.TaggedLogAPIEntity;
+import org.apache.eagle.log.entity.meta.*;
+import org.apache.eagle.policy.common.Constants;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+
+@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+@Table("eagleSiteApplication")
+@ColumnFamily("f")
+@Prefix("eagleSiteApplication")
+@Service(Constants.SITE_APPLICATION_SERVICE_ENDPOINT_NAME)
+@JsonIgnoreProperties(ignoreUnknown = true)
+@TimeSeries(false)
+@Tags({"site", "application"})
+public class SiteApplicationServiceEntity extends TaggedLogAPIEntity {
+ @Column("a")
+ private String config;
+ @Column("b")
+ private Boolean enabled;
+
+ public String getConfig() {
+ return config;
+ }
+
+ public void setConfig(String config) {
+ this.config = config;
+ valueChanged("config");
+ }
+
+ public Boolean getEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(Boolean enabled) {
+ this.enabled = enabled;
+ valueChanged("enabled");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/SiteDescServiceEntity.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/SiteDescServiceEntity.java b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/SiteDescServiceEntity.java
new file mode 100644
index 0000000..a8245cf
--- /dev/null
+++ b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/alert/entity/SiteDescServiceEntity.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.eagle.alert.entity;
+
+
+import org.apache.eagle.log.base.taggedlog.TaggedLogAPIEntity;
+import org.apache.eagle.log.entity.meta.*;
+import org.apache.eagle.policy.common.Constants;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+@Table("eagleSiteDesc")
+@ColumnFamily("f")
+@Prefix("eagleSiteDesc")
+@Service(Constants.SITE_DESCRIPTION_SERVICE_ENDPOINT_NAME)
+@JsonIgnoreProperties(ignoreUnknown = true)
+@TimeSeries(false)
+@Tags({"site"})
+public class SiteDescServiceEntity extends TaggedLogAPIEntity {
+ @Column("a")
+ private Boolean enabled;
+
+ public Boolean getEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(Boolean enabled) {
+ this.enabled = enabled;
+ valueChanged("enabled");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/common/Constants.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/common/Constants.java b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/common/Constants.java
index 256e46b..ca65669 100644
--- a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/common/Constants.java
+++ b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/common/Constants.java
@@ -26,6 +26,13 @@ public class Constants {
public final static String ALERT_NOTIFICATION_SERVICE_ENDPOINT_NAME = "AlertNotificationService";
public static final String ALERT_EMAIL_ORIGIN_PROPERTY = "alertEmailOrigin";
public static final String ALERT_TIMESTAMP_PROPERTY = "alertTimestamp";
+
+ public static final String SITE_APPLICATION_SERVICE_ENDPOINT_NAME = "SiteApplicationService";
+ public static final String SITE_DESCRIPTION_SERVICE_ENDPOINT_NAME = "SiteDescService";
+ public static final String APPLICATION_DESCRIPTION_SERVICE_ENDPOINT_NAME = "ApplicationDescService";
+ public static final String FEATURE_DESCRIPTION_SERVICE_ENDPOINT_NAME = "FeatureDescService";
+
+ public static final String GENERIC_RESOURCE_SERVICE_ENDPOINT_NAME = "GenericResourceService";
public final static String AGGREGATE_DEFINITION_SERVICE_ENDPOINT_NAME = "AggregateDefinitionService";
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/dao/AlertDataSourceDAO.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/dao/AlertDataSourceDAO.java b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/dao/AlertDataSourceDAO.java
deleted file mode 100644
index 650defc..0000000
--- a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/dao/AlertDataSourceDAO.java
+++ /dev/null
@@ -1,25 +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.
- */
-package org.apache.eagle.policy.dao;
-
-import org.apache.eagle.alert.entity.AlertDataSourceEntity;
-
-import java.util.List;
-
-public interface AlertDataSourceDAO {
- List<AlertDataSourceEntity> findAlertDataSourceBySite(String site) throws Exception;
-}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/dao/AlertDataSourceDAOImpl.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/dao/AlertDataSourceDAOImpl.java b/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/dao/AlertDataSourceDAOImpl.java
deleted file mode 100644
index ca037a3..0000000
--- a/eagle-core/eagle-policy/eagle-policy-base/src/main/java/org/apache/eagle/policy/dao/AlertDataSourceDAOImpl.java
+++ /dev/null
@@ -1,61 +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.
- */
-package org.apache.eagle.policy.dao;
-
-import org.apache.eagle.policy.common.Constants;
-import org.apache.eagle.alert.entity.AlertDataSourceEntity;
-import org.apache.eagle.log.entity.GenericServiceAPIResponseEntity;
-import org.apache.eagle.service.client.EagleServiceConnector;
-import org.apache.eagle.service.client.IEagleServiceClient;
-import org.apache.eagle.service.client.impl.EagleServiceClientImpl;
-import org.apache.commons.lang.time.DateUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-
-public class AlertDataSourceDAOImpl implements AlertDataSourceDAO{
- private final Logger LOG = LoggerFactory.getLogger(AlertDataSourceDAOImpl.class);
- private final EagleServiceConnector connector;
-
- public AlertDataSourceDAOImpl(EagleServiceConnector connector){
- this.connector = connector;
- }
-
- @Override
- public List<AlertDataSourceEntity> findAlertDataSourceBySite(String site) throws Exception{
- try {
- IEagleServiceClient client = new EagleServiceClientImpl(connector);
- String query = Constants.ALERT_STREAM_SERVICE_ENDPOINT_NAME + "[@site=\"" + site + "\"]{*}";
- GenericServiceAPIResponseEntity<AlertDataSourceEntity> response = client.search()
- .startTime(0)
- .endTime(10 * DateUtils.MILLIS_PER_DAY)
- .pageSize(Integer.MAX_VALUE)
- .query(query)
- .send();
- client.close();
- if (response.getException() != null) {
- throw new Exception("Got an exception when query eagle service: " + response.getException());
- }
- return response.getObj();
- }
- catch (Exception ex) {
- LOG.error("Got an exception when query stream metadata service ", ex);
- throw new IllegalStateException(ex);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-policy/eagle-policy-base/src/main/resources/str.siddhiext
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-policy/eagle-policy-base/src/main/resources/str.siddhiext b/eagle-core/eagle-policy/eagle-policy-base/src/main/resources/str.siddhiext
index 8c1672b..479cdb0 100644
--- a/eagle-core/eagle-policy/eagle-policy-base/src/main/resources/str.siddhiext
+++ b/eagle-core/eagle-policy/eagle-policy-base/src/main/resources/str.siddhiext
@@ -31,6 +31,10 @@ trim=org.wso2.siddhi.extension.string.TrimFunctionExtension
upper=org.wso2.siddhi.extension.string.UpperFunctionExtension
hex=org.wso2.siddhi.extension.string.HexFunctionExtension
unhex=org.wso2.siddhi.extension.string.UnhexFunctionExtension
+contains=org.wso2.siddhi.extension.string.ContainsFunctionExtension
+
+# Eagle Siddhi Extension
equalsIgnoreCase=org.apache.eagle.policy.siddhi.extension.EqualsIgnoreCaseExtension
containsIgnoreCase=org.apache.eagle.policy.siddhi.extension.ContainsIgnoreCaseExtension
regexpIgnoreCase=org.apache.eagle.policy.siddhi.extension.RegexpIgnoreCaseFunctionExtension
+
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-core/eagle-query/eagle-service-base/src/main/java/org/apache/eagle/service/generic/GenericEntityServiceResource.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-query/eagle-service-base/src/main/java/org/apache/eagle/service/generic/GenericEntityServiceResource.java b/eagle-core/eagle-query/eagle-service-base/src/main/java/org/apache/eagle/service/generic/GenericEntityServiceResource.java
index 43302c8..fb52352 100644
--- a/eagle-core/eagle-query/eagle-service-base/src/main/java/org/apache/eagle/service/generic/GenericEntityServiceResource.java
+++ b/eagle-core/eagle-query/eagle-service-base/src/main/java/org/apache/eagle/service/generic/GenericEntityServiceResource.java
@@ -73,6 +73,47 @@ public class GenericEntityServiceResource {
return objectMapper.readValue(inputStream, TypeFactory.defaultInstance().constructCollectionType(LinkedList.class, String.class));
}
+
+ public GenericServiceAPIResponseEntity updateDatabase(Statement<ModifyResult<String>> statement) {
+ GenericServiceAPIResponseEntity<String> response = new GenericServiceAPIResponseEntity<>();
+ Map<String,Object> meta = new HashMap<>();
+ StopWatch stopWatch = new StopWatch();
+
+ try {
+ stopWatch.start();
+ DataStorage dataStorage = DataStorageManager.getDataStorageByEagleConfig();
+ if(dataStorage == null){
+ LOG.error("Data storage is null");
+ throw new IllegalDataStorageException("Data storage is null");
+ }
+ ModifyResult<String> result = statement.execute(dataStorage);
+ if(result.isSuccess()) {
+ List<String> keys =result.getIdentifiers();
+ if(keys != null) {
+ response.setObj(keys, String.class);
+ meta.put(TOTAL_RESULTS, keys.size());
+ } else {
+ meta.put(TOTAL_RESULTS, 0);
+ }
+ meta.put(ELAPSEDMS,stopWatch.getTime());
+ response.setMeta(meta);
+ response.setSuccess(true);
+ }
+ } catch (Exception e) {
+ LOG.error(e.getMessage(), e);
+ response.setException(e);
+ }finally {
+ stopWatch.stop();
+ }
+ return response;
+ }
+
+ public GenericServiceAPIResponseEntity updateEntities(List<? extends TaggedLogAPIEntity> entities, String serviceName) {
+ CreateStatement createStatement = new CreateStatement(entities, serviceName);
+ GenericServiceAPIResponseEntity<String> response = updateDatabase(createStatement);
+ return response;
+ }
+
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-hadoop-metric/src/main/resources/hadoop-metric-init.sh
----------------------------------------------------------------------
diff --git a/eagle-hadoop-metric/src/main/resources/hadoop-metric-init.sh b/eagle-hadoop-metric/src/main/resources/hadoop-metric-init.sh
index 8405c19..17923c7 100755
--- a/eagle-hadoop-metric/src/main/resources/hadoop-metric-init.sh
+++ b/eagle-hadoop-metric/src/main/resources/hadoop-metric-init.sh
@@ -25,18 +25,33 @@ source $(dirname $0)/eagle-env.sh
echo "Importing AlertDataSourceService for persist... "
curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' \
- "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=AlertDataSourceService" \
+ "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=SiteApplicationService" \
-d '
[
{
- "prefix":"alertDataSource",
"tags":{
"site":"sandbox",
- "dataSource":"hadoopJmxMetricDataSource"
+ "application":"hadoopJmxMetricDataSource"
},
"enabled": true,
- "config":"",
- "desc":"hadoop"
+ "config":"{}"
+ }
+ ]
+ '
+
+curl -u ${EAGLE_SERVICE_USER}:${EAGLE_SERVICE_PASSWD} -X POST -H 'Content-Type:application/json' \
+ "http://${EAGLE_SERVICE_HOST}:${EAGLE_SERVICE_PORT}/eagle-service/rest/entities?serviceName=ApplicationDescService" \
+ -d '
+ [
+ {
+ "tags":{
+ "application":"hadoopJmxMetricDataSource"
+ },
+ "desc":"hadoop jmx metric monitoring",
+ "alias":"JmxMetricMonitor",
+ "group":"METRIC",
+ "config":"{}",
+ "features":["common","metadata"]
}
]
'
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-security/eagle-security-hbase-web/src/main/java/org/apache/eagle/service/security/hbase/dao/HbaseMetadataAccessConfigDAOImpl.java
----------------------------------------------------------------------
diff --git a/eagle-security/eagle-security-hbase-web/src/main/java/org/apache/eagle/service/security/hbase/dao/HbaseMetadataAccessConfigDAOImpl.java b/eagle-security/eagle-security-hbase-web/src/main/java/org/apache/eagle/service/security/hbase/dao/HbaseMetadataAccessConfigDAOImpl.java
index 1378032..152facb 100644
--- a/eagle-security/eagle-security-hbase-web/src/main/java/org/apache/eagle/service/security/hbase/dao/HbaseMetadataAccessConfigDAOImpl.java
+++ b/eagle-security/eagle-security-hbase-web/src/main/java/org/apache/eagle/service/security/hbase/dao/HbaseMetadataAccessConfigDAOImpl.java
@@ -20,8 +20,9 @@ package org.apache.eagle.service.security.hbase.dao;
import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.eagle.alert.entity.AlertDataSourceEntity;
+import org.apache.eagle.alert.entity.SiteApplicationServiceEntity;
import org.apache.eagle.log.entity.ListQueryAPIResponseEntity;
+import org.apache.eagle.policy.common.Constants;
import org.apache.eagle.security.util.BadMetadataAccessConfigException;
import org.apache.eagle.service.generic.ListQueryResource;
import org.slf4j.Logger;
@@ -49,9 +50,9 @@ public class HbaseMetadataAccessConfigDAOImpl {
ListQueryResource resource = new ListQueryResource();
/* parameters are: query, startTime, endTime, pageSzie, startRowkey, treeAgg, timeSeries, intervalmin, top, filterIfMissing,
* parallel, metricName*/
- String queryFormat = "AlertDataSourceService[@dataSource=\"hbaseSecurityLog\" AND @site=\"%s\"]{*}";
+ String queryFormat = Constants.SITE_APPLICATION_SERVICE_ENDPOINT_NAME + "[@application=\"hbaseSecurityLog\" AND @site=\"%s\"]{*}";
ListQueryAPIResponseEntity ret = resource.listQuery(String.format(queryFormat, site), null, null, Integer.MAX_VALUE, null, false, false, 0L, 0, false, 0, null);
- List<AlertDataSourceEntity> list = (List<AlertDataSourceEntity>) ret.getObj();
+ List<SiteApplicationServiceEntity> list = (List<SiteApplicationServiceEntity>) ret.getObj();
if(list == null || list.size() ==0)
throw new BadMetadataAccessConfigException("config is empty for site " + site);
return convert(list.get(0).getConfig());
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-security/eagle-security-hdfs-auditlog/src/main/resources/application.conf
----------------------------------------------------------------------
diff --git a/eagle-security/eagle-security-hdfs-auditlog/src/main/resources/application.conf b/eagle-security/eagle-security-hdfs-auditlog/src/main/resources/application.conf
index 2f8ea8b..697b4f6 100644
--- a/eagle-security/eagle-security-hdfs-auditlog/src/main/resources/application.conf
+++ b/eagle-security/eagle-security-hdfs-auditlog/src/main/resources/application.conf
@@ -26,12 +26,12 @@
},
"dataSourceConfig": {
"topic" : "sandbox_hdfs_audit_log",
- "zkConnection" : "localhost:2181",
+ "zkConnection" : "sandbox.hortonworks.com:2181",
"zkConnectionTimeoutMS" : 15000,
"consumerGroupId" : "EagleConsumer",
"fetchSize" : 1048586,
"deserializerClass" : "org.apache.eagle.security.auditlog.HdfsAuditLogKafkaDeserializer",
- "transactionZKServers" : "localhost",
+ "transactionZKServers" : "sandbox.hortonworks.com",
"transactionZKPort" : 2181,
"transactionZKRoot" : "/consumers",
"transactionStateUpdateMS" : 2000
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-security/eagle-security-hdfs-web/src/main/java/org/apache/eagle/service/security/hdfs/HDFSResourceUtils.java
----------------------------------------------------------------------
diff --git a/eagle-security/eagle-security-hdfs-web/src/main/java/org/apache/eagle/service/security/hdfs/HDFSResourceUtils.java b/eagle-security/eagle-security-hdfs-web/src/main/java/org/apache/eagle/service/security/hdfs/HDFSResourceUtils.java
index 7d57ef7..bece538 100644
--- a/eagle-security/eagle-security-hdfs-web/src/main/java/org/apache/eagle/service/security/hdfs/HDFSResourceUtils.java
+++ b/eagle-security/eagle-security-hdfs-web/src/main/java/org/apache/eagle/service/security/hdfs/HDFSResourceUtils.java
@@ -18,9 +18,10 @@ package org.apache.eagle.service.security.hdfs;
import java.util.List;
+import org.apache.eagle.alert.entity.SiteApplicationServiceEntity;
+import org.apache.eagle.policy.common.Constants;
import org.apache.eagle.service.generic.ListQueryResource;
-import org.apache.eagle.alert.entity.AlertDataSourceEntity;
import org.apache.eagle.log.entity.ListQueryAPIResponseEntity;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -34,9 +35,9 @@ public class HDFSResourceUtils {
public static HDFSResourceAccessConfig getConfig(String siteId ) throws Exception
{
ListQueryResource resource = new ListQueryResource();
- String queryFormat = "AlertDataSourceService[@dataSource=\""+HDFSResourceConstants.HDFS_DATA_SOURCE+"\" AND @site=\"%s\"]{*}";
+ String queryFormat = Constants.SITE_APPLICATION_SERVICE_ENDPOINT_NAME+"[@application=\""+HDFSResourceConstants.HDFS_DATA_SOURCE+"\" AND @site=\"%s\"]{*}";
ListQueryAPIResponseEntity ret = resource.listQuery(String.format(queryFormat, siteId), null, null,Integer.MAX_VALUE, null, false, false, 0L, 0, false, 0, null);
- List<AlertDataSourceEntity> list = (List<AlertDataSourceEntity>) ret.getObj();
+ List<SiteApplicationServiceEntity> list = (List<SiteApplicationServiceEntity>) ret.getObj();
if (list == null || list.size() == 0)
throw new Exception("Config is empty for site " + siteId +".");
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-security/eagle-security-hdfs-web/src/main/java/org/apache/eagle/service/security/hdfs/resolver/HDFSCommandResolver.java
----------------------------------------------------------------------
diff --git a/eagle-security/eagle-security-hdfs-web/src/main/java/org/apache/eagle/service/security/hdfs/resolver/HDFSCommandResolver.java b/eagle-security/eagle-security-hdfs-web/src/main/java/org/apache/eagle/service/security/hdfs/resolver/HDFSCommandResolver.java
index 23694e5..b2a2671 100644
--- a/eagle-security/eagle-security-hdfs-web/src/main/java/org/apache/eagle/service/security/hdfs/resolver/HDFSCommandResolver.java
+++ b/eagle-security/eagle-security-hdfs-web/src/main/java/org/apache/eagle/service/security/hdfs/resolver/HDFSCommandResolver.java
@@ -37,6 +37,8 @@ public class HDFSCommandResolver implements AttributeResolvable<GenericAttribute
"mkdirs", "listStatus", "setReplication", "setOwner", "setPermission", "setTimes", "setXAttr", "removeXAttr", "getXAttrs",
"contentSummary", "createEncryptionZone", "checkAccess"};
+ //private final static String [] cmdStrs = {"appendToFile","cat","checksum","chgrp","chmod","chown","copyFromLocal","copyToLocal","count","cp","createSnapshot","deleteSnapshot","df","du","dus","expunge","find","get","getfacl","getfattr","getmerge","help","ls","lsr","mkdir","moveFromLocal","moveToLocal","mv","put","renameSnapshot","rm","rmdir","rmr","setfacl","setfattr","setrep","stat","tail","test","text","touchz","truncate","usage"};
+
private final static String HDFS_CMD_RESOLVE_FORMAT_HINT = String.format("hdfs command must be in {%s}", StringUtils.join(cmdStrs, ","));
private final static List<String> commands = Arrays.asList(cmdStrs);
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-security/eagle-security-hive-web/src/main/java/org/apache/eagle/service/security/hive/dao/HiveMetadataAccessConfigDAOImpl.java
----------------------------------------------------------------------
diff --git a/eagle-security/eagle-security-hive-web/src/main/java/org/apache/eagle/service/security/hive/dao/HiveMetadataAccessConfigDAOImpl.java b/eagle-security/eagle-security-hive-web/src/main/java/org/apache/eagle/service/security/hive/dao/HiveMetadataAccessConfigDAOImpl.java
index 8a6f965..d0c18ed 100644
--- a/eagle-security/eagle-security-hive-web/src/main/java/org/apache/eagle/service/security/hive/dao/HiveMetadataAccessConfigDAOImpl.java
+++ b/eagle-security/eagle-security-hive-web/src/main/java/org/apache/eagle/service/security/hive/dao/HiveMetadataAccessConfigDAOImpl.java
@@ -16,8 +16,9 @@
*/
package org.apache.eagle.service.security.hive.dao;
-import org.apache.eagle.alert.entity.AlertDataSourceEntity;
+import org.apache.eagle.alert.entity.SiteApplicationServiceEntity;
import org.apache.eagle.log.entity.ListQueryAPIResponseEntity;
+import org.apache.eagle.policy.common.Constants;
import org.apache.eagle.service.generic.ListQueryResource;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
@@ -36,11 +37,11 @@ public class HiveMetadataAccessConfigDAOImpl implements HiveMetadataAccessConfig
ListQueryResource resource = new ListQueryResource();
/* parameters are: query, startTime, endTime, pageSzie, startRowkey, treeAgg, timeSeries, intervalmin, top, filterIfMissing,
* parallel, metricName*/
- ListQueryAPIResponseEntity ret = resource.listQuery("AlertDataSourceService[@dataSource=\"hiveQueryLog\"]{*}", null, null, Integer.MAX_VALUE, null, false, false, 0L, 0, false,
+ ListQueryAPIResponseEntity ret = resource.listQuery(Constants.SITE_APPLICATION_SERVICE_ENDPOINT_NAME+"[@application=\"hiveQueryLog\"]{*}", null, null, Integer.MAX_VALUE, null, false, false, 0L, 0, false,
0, null);
- List<AlertDataSourceEntity> list = (List<AlertDataSourceEntity>) ret.getObj();
- Map<String, HiveMetadataAccessConfig> siteHiveConfigs = new HashMap<String, HiveMetadataAccessConfig>();
- for(AlertDataSourceEntity hiveDataSource : list){
+ List<SiteApplicationServiceEntity> list = (List<SiteApplicationServiceEntity>) ret.getObj();
+ Map<String, HiveMetadataAccessConfig> siteHiveConfigs = new HashMap<>();
+ for(SiteApplicationServiceEntity hiveDataSource : list){
siteHiveConfigs.put(hiveDataSource.getTags().get("site"), convert(hiveDataSource.getConfig()));
}
return siteHiveConfigs;
@@ -48,7 +49,7 @@ public class HiveMetadataAccessConfigDAOImpl implements HiveMetadataAccessConfig
private HiveMetadataAccessConfig convert(String config){
ObjectMapper mapper = new ObjectMapper();
- HiveMetadataAccessConfig c = null;
+ HiveMetadataAccessConfig c;
try {
c = mapper.readValue(config, HiveMetadataAccessConfig.class);
}catch(Exception ex){
@@ -64,12 +65,12 @@ public class HiveMetadataAccessConfigDAOImpl implements HiveMetadataAccessConfig
ListQueryResource resource = new ListQueryResource();
/* parameters are: query, startTime, endTime, pageSzie, startRowkey, treeAgg, timeSeries, intervalmin, top, filterIfMissing,
* parallel, metricName*/
- String queryFormat = "AlertDataSourceService[@dataSource=\"hiveQueryLog\" AND @site=\"%s\"]{*}";
+ String queryFormat = Constants.SITE_APPLICATION_SERVICE_ENDPOINT_NAME+"[@application=\"hiveQueryLog\" AND @site=\"%s\"]{*}";
ListQueryAPIResponseEntity ret = resource.listQuery(String.format(queryFormat, site), null, null, Integer.MAX_VALUE, null, false, false, 0L, 0, false,
0, null);
- List<AlertDataSourceEntity> list = (List<AlertDataSourceEntity>) ret.getObj();
+ List<SiteApplicationServiceEntity> list = (List<SiteApplicationServiceEntity>) ret.getObj();
if(list == null || list.size() ==0)
throw new BadHiveMetadataAccessConfigException("config is empty for site " + site);
return convert(list.get(0).getConfig());
}
-}
+}
\ No newline at end of file
[9/9] incubator-eagle git commit: EAGLE-167 refactor metric collector
script
Posted by hd...@apache.org.
EAGLE-167 refactor metric collector script
https://issues.apache.org/jira/browse/EAGLE-167
Author: @haoch <ha...@apache.org>
Reviewer: @haoch <ha...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/incubator-eagle/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-eagle/commit/1965b4af
Tree: http://git-wip-us.apache.org/repos/asf/incubator-eagle/tree/1965b4af
Diff: http://git-wip-us.apache.org/repos/asf/incubator-eagle/diff/1965b4af
Branch: refs/heads/branch-0.3.0
Commit: 1965b4aff6f27b971effc7bd5be0fd773a686789
Parents: d37643b
Author: Hao Chen <ha...@apache.org>
Authored: Fri Feb 26 16:17:09 2016 +0800
Committer: Hao Chen <ha...@apache.org>
Committed: Fri Feb 26 16:17:09 2016 +0800
----------------------------------------------------------------------
eagle-external/hadoop_jmx_collector/base.py | 250 -------------
.../hadoop_jmx_collector/hadoop_ha_checker.py | 10 +-
.../hadoop_jmx_collector/hadoop_jmx_kafka.py | 228 ++++--------
.../hadoop_jmx_collector/metric_collector.py | 354 +++++++++++++++++++
.../hadoop_jmx_collector/metric_extensions.py | 95 -----
5 files changed, 420 insertions(+), 517 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1965b4af/eagle-external/hadoop_jmx_collector/base.py
----------------------------------------------------------------------
diff --git a/eagle-external/hadoop_jmx_collector/base.py b/eagle-external/hadoop_jmx_collector/base.py
deleted file mode 100644
index bbb2344..0000000
--- a/eagle-external/hadoop_jmx_collector/base.py
+++ /dev/null
@@ -1,250 +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.
-
-
-# !/usr/bin/python
-
-
-# !/usr/bin/python
-
-import os
-import re
-import time
-import json
-import urllib2
-import sys
-import socket
-import types
-import httplib
-import logging
-import threading
-
-# load six
-sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '', 'lib/six'))
-import six
-
-# load kafka-python
-sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '', 'lib/kafka-python'))
-from kafka import KafkaClient, SimpleProducer, SimpleConsumer
-
-logging.basicConfig(level=logging.INFO,
- format='%(asctime)s %(name)-12s %(levelname)-6s %(message)s',
- datefmt='%m-%d %H:%M')
-
-class Helper:
- def __init__(self):
- pass
-
- @staticmethod
- def load_config(config_file="config.json"):
- """
-
- :param config_file:
- :return:
- """
- # read the self-defined filters
- script_dir = os.path.dirname(__file__)
- rel_path = "./" + config_file
- abs_file_path = os.path.join(script_dir, rel_path)
- if not os.path.isfile(abs_file_path):
- logging.error(abs_file_path + " doesn't exist, please rename config-sample.json to config.json")
- exit(1)
- f = open(abs_file_path, 'r')
- json_file = f.read()
- f.close()
- config = json.loads(json_file)
- return config
-
- @staticmethod
- def is_number(str):
- """
-
- :param str:
- :return:
- """
- try:
- if str == None or isinstance(str, (bool)):
- return False
- float(str)
- return True
- except:
- return False
-
- @staticmethod
- def http_get(host, port, https=False, path=None):
- """
- Read url by GET method
-
- :param path:
- :param url:
- :param https:
- :return:
- """
- url = ":".join([host, str(port)])
- result = None
- response = None
- try:
- if https:
- logging.info("Reading https://" + str(url) + path)
- c = httplib.HTTPSConnection(url, timeout=57)
- c.request("GET", path)
- response = c.getresponse()
- else:
- logging.info("Reading http://" + str(url) + path)
- response = urllib2.urlopen("http://" + str(url) + path, timeout=57)
- logging.debug("Got response")
- result = response.read()
- finally:
- if response is not None:
- response.close()
- return result
-
-
-class JmxReader(object):
- def __init__(self, host, port, https=False):
- self.host = host
- self.port = port
- self.https = https
- self.jmx_json = None
- self.jmx_beans = None
- self.jmx_raw = None
-
- def open(self):
- """
- :return: JmxReader
- """
- self.read_raw()
- self.set_raw(self.jmx_raw)
- return self
-
- def read_raw(self):
- """
- transfer the json string into dict
- :param host:
- :param port:
- :param https:
- :return: text
- """
- self.jmx_raw = Helper.http_get(self.host, self.port, self.https, "/jmx?anonymous=true")
- if self.jmx_raw is None:
- raise Exception("Response from " + url + " is None")
- return self
-
- def set_raw(self, text):
- self.jmx_json = json.loads(text)
- self.jmx_beans = self.jmx_json[u'beans']
- self.jmx_raw = text
- return self
-
- def get_jmx_beans(self):
- return self.jmx_beans
-
- def get_jmx_bean_by_name(self, name):
- for bean in self.jmx_beans:
- if bean.has_key("name") and bean["name"] == name:
- return bean
-
-
-class YarnWSReader:
- def __init__(self, host, port, https=False):
- self.host = host
- self.port = port
- self.https = https
-
- def read_cluster_info(self):
- cluster_info = Helper.http_get(self.host, self.port, self.https, "/ws/v1/cluster/info")
- logging.debug(cluster_info)
- return json.loads(cluster_info)
-
-class MetricSender(object):
- def __init__(self, config):
- pass
-
- def open(self):
- pass
-
- def send(self, msg):
- raise Exception("should be overrode")
-
- def close(self):
- pass
-
-
-class KafkaMetricSender(MetricSender):
- def __init__(self, config):
- super(KafkaMetricSender, self).__init__(config)
- kafka_config = config["output"]["kafka"]
- # default topic
- self.topic = kafka_config["topic"].encode('utf-8')
- # producer
- self.broker_list = kafka_config["brokerList"]
- self.kafka_client = None
- self.kafka_producer = None
-
- def open(self):
- self.kafka_client = KafkaClient(self.broker_list, timeout=59)
- self.kafka_producer = SimpleProducer(self.kafka_client, batch_send=True, batch_send_every_n=500,
- batch_send_every_t=30)
-
- def send(self, msg):
- self.kafka_producer.send_messages(self.topic, json.dumps(msg))
-
- def close(self):
- if self.kafka_producer is not None:
- self.kafka_producer.stop()
- if self.kafka_client is not None:
- self.kafka_client.close()
-
-
-class MetricCollector(threading.Thread):
- def __init__(self):
- threading.Thread.__init__(self)
-
- self.config = Helper.load_config()
- self.sender = KafkaMetricSender(self.config)
-
- def start(self):
- try:
- self.sender.open()
- self.run()
- finally:
- self.sender.close()
-
- def collect(self, msg):
- if not msg.has_key("timestamp"):
- msg["timestamp"] = int(round(time.time() * 1000))
- if msg.has_key("value"):
- msg["value"] = float(str(msg["value"]))
- if not msg.has_key("host") or len(msg["host"]) == 0:
- msg["host"] = socket.getfqdn()
- if not msg.has_key("site"):
- msg["site"] = self.config["env"]["site"]
-
- self.sender.send(msg)
-
- def run(self):
- raise Exception("`run` method should be overrode by sub-class before being called")
-
-class Runner(object):
- @staticmethod
- def run(*threads):
- """
- Execute concurrently
-
- :param threads:
- :return:
- """
- for thread in threads:
- thread.start()
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1965b4af/eagle-external/hadoop_jmx_collector/hadoop_ha_checker.py
----------------------------------------------------------------------
diff --git a/eagle-external/hadoop_jmx_collector/hadoop_ha_checker.py b/eagle-external/hadoop_jmx_collector/hadoop_ha_checker.py
index 063279b..2a5096b 100644
--- a/eagle-external/hadoop_jmx_collector/hadoop_ha_checker.py
+++ b/eagle-external/hadoop_jmx_collector/hadoop_ha_checker.py
@@ -1,3 +1,5 @@
+# !/usr/bin/python
+#
# 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.
@@ -12,14 +14,11 @@
# 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.
+#
-
-# !/usr/bin/python
-
-from base import MetricCollector, JmxReader, YarnWSReader, Runner
+from metric_collector import MetricCollector, JmxReader, YarnWSReader, Runner
import logging
-
class HadoopNNHAChecker(MetricCollector):
def run(self):
if not self.config["env"].has_key("name_node"):
@@ -126,5 +125,4 @@ class HadoopRMHAChecker(MetricCollector):
})
if __name__ == '__main__':
- # HadoopNNHAChecker().start()
Runner.run(HadoopNNHAChecker(), HadoopRMHAChecker())
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1965b4af/eagle-external/hadoop_jmx_collector/hadoop_jmx_kafka.py
----------------------------------------------------------------------
diff --git a/eagle-external/hadoop_jmx_collector/hadoop_jmx_kafka.py b/eagle-external/hadoop_jmx_collector/hadoop_jmx_kafka.py
index b342a5e..8837c30 100644
--- a/eagle-external/hadoop_jmx_collector/hadoop_jmx_kafka.py
+++ b/eagle-external/hadoop_jmx_collector/hadoop_jmx_kafka.py
@@ -1,5 +1,5 @@
-#!/usr/bin/python
-
+# !/usr/bin/python
+#
# 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.
@@ -14,170 +14,66 @@
# 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.
+#
-import os
-import re
-import time
+from metric_collector import JmxMetricCollector,JmxMetricListener,Runner
import json
-import urllib2
-import sys
-import socket
-import types
-import httplib
-
-# load six
-sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '', 'lib/six'))
-import six
-
-# load kafka-python
-sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '', 'lib/kafka-python'))
-from kafka import KafkaClient, SimpleProducer, SimpleConsumer
-
-from util_func import *
-from metric_extensions import *
-
-
-DATA_TYPE = "hadoop"
-
-def readUrl(url, https=False):
- jmxjson = 'error'
- try:
- if https:
- print "Reading https://" + str(url) + "/jmx?anonymous=true"
- c = httplib.HTTPSConnection(url, timeout=57)
- c.request("GET", "/jmx?anonymous=true")
- response = c.getresponse()
- else:
- print "Reading http://" + str(url) + "/jmx?anonymous=true"
- response = urllib2.urlopen("http://" + url + '/jmx?anonymous=true', timeout=57)
- except Exception, e:
- print 'Reason: ', e
- else:
- # everything is fine
- jmxjson = response.read()
- response.close()
- finally:
- return jmxjson
-
-
-def get_metric_prefix_name(mbean_attribute, context):
- mbean_list = list(prop.split("=", 1)
- for prop in mbean_attribute.split(","))
- metric_prefix_name = None
- if context == "":
- metric_prefix_name = '.'.join([i[1] for i in mbean_list])
- else:
- name_index = [i[0] for i in mbean_list].index('name')
- mbean_list[name_index][1] = context
- metric_prefix_name = '.'.join([i[1] for i in mbean_list])
- return (DATA_TYPE + "." + metric_prefix_name).replace(" ","").lower()
-
-def parse_hadoop_jmx(producer, topic, config, beans, dataMap, fat_bean):
- selected_group = [s.encode('utf-8') for s in config[u'filter'].get('monitoring.group.selected')]
- #print selected_group
-
- for bean in beans:
- kafka_dict = dataMap.copy()
-
- # mbean is of the form "domain:key=value,...,foo=bar"
- mbean = bean[u'name']
- mbean_domain, mbean_attribute = mbean.rstrip().split(":", 1)
- mbean_domain = mbean_domain.lower()
-
- # print mbean_domain
- if mbean_domain not in selected_group:
- # print "Unexpected mbean domain = %s on %s" % (mbean_domain, mbean)
- continue
- fat_bean.update(bean)
- context = bean.get("tag.Context", "")
- metric_prefix_name = get_metric_prefix_name(mbean_attribute, context)
-
- # print kafka_dict
- for key, value in bean.iteritems():
- #print key, value
- key = key.lower()
- if re.match(r'tag.*', key):
- continue
-
- if mbean_domain == 'hadoop' and re.match(r'^namespace', key):
- #print key
- items = re.split('_table_', key)
- key = items[1]
- items = re.split('_region_', key)
- kafka_dict['table'] = items[0]
- items = re.split('_metric_', items[1])
- kafka_dict['region'] = items[0]
- key = items[1]
-
- metric = metric_prefix_name + '.' + key
-
- single_metric_callback(producer, topic, kafka_dict, metric, value)
-
-def get_jmx_beans(host, port, https):
- # port = inputConfig.get('port')
- # https = inputConfig.get('https')
- url = host + ':' + port
- #print url
-
- jmxjson = readUrl(url, https)
-
- if jmxjson == 'error':
- print 'jmx load error'
-
- # transfer the json string into dict
- jmx = json.loads(jmxjson)
- beans = jmx[u'beans']
-
- return beans
-
-def main():
- kafka = None
- producer = None
- topic = None
- brokerList = None
-
- try:
- #start = time.clock()
-
- # read the kafka.ini
- if (len(sys.argv) > 1):
- config = load_config(sys.argv[1])
- else:
- config = load_config('config.json')
- #print config
-
- site = config[u'env'].get('site').encode('utf-8')
- component = config[u'input'].get('component').encode('utf-8')
-
- if config[u'input'].has_key("host"):
- host = config[u'input'].get("host").encode('utf-8')
- else:
- host = socket.getfqdn()
-
- port = config[u'input'].get('port')
- https = config[u'input'].get('https')
- kafkaConfig = config[u'output'].get(u'kafka')
- if kafkaConfig != None :
- brokerList = kafkaConfig.get('brokerList')
- topic = kafkaConfig.get('topic').encode('utf-8')
-
- beans = get_jmx_beans(host, port, https)
- #print brokerList
- if brokerList != None:
- kafka, producer = kafka_connect(brokerList)
-
- default_metric = {"site": site, "host": host, "timestamp": '', "component": component, "metric": '', "value": ''}
- fat_bean = dict()
- parse_hadoop_jmx(producer, topic, config, beans, default_metric, fat_bean)
- metrics_bean_callback(producer, topic, default_metric, fat_bean)
- # except Exception, e:
- # print 'main except: ', e
- finally:
- if kafka != None and producer != None:
- kafka_close(kafka, producer)
-
- #elapsed = (time.clock() - start)
- #print("Time used:",elapsed)
-if __name__ == "__main__":
- main()
+class NNSafeModeMetric(JmxMetricListener):
+ def on_metric(self, metric):
+ if metric["metric"] == "hadoop.namenode.fsnamesystemstate.fsstate":
+ if metric["value"] == "safeMode":
+ metric["value"] = 1
+ else:
+ metric["value"] = 0
+ self.collector.collect(metric)
+
+
+class NNHAMetric(JmxMetricListener):
+ PREFIX = "hadoop.namenode.fsnamesystem"
+
+ def on_bean(self, bean):
+ if bean["name"] == "Hadoop:service=NameNode,name=FSNamesystem":
+ if bean[u"tag.HAState"] == "active":
+ self.collector.on_bean_kv(self.PREFIX, "hastate", 0)
+ else:
+ self.collector.on_bean_kv(self.PREFIX, "hastate", 1)
+
+
+class MemortUsageMetric(JmxMetricListener):
+ PREFIX = "hadoop.namenode.jvm"
+
+ def on_bean(self, bean):
+ if bean["name"] == "Hadoop:service=NameNode,name=JvmMetrics":
+ memnonheapusedusage = round(float(bean['MemNonHeapUsedM']) / float(bean['MemNonHeapMaxM']) * 100.0, 2)
+ self.collector.on_bean_kv(self.PREFIX, "memnonheapusedusage", memnonheapusedusage)
+ memnonheapcommittedusage = round(float(bean['MemNonHeapCommittedM']) / float(bean['MemNonHeapMaxM']) * 100,
+ 2)
+ self.collector.on_bean_kv(self.PREFIX, "memnonheapcommittedusage", memnonheapcommittedusage)
+ memheapusedusage = round(float(bean['MemHeapUsedM']) / float(bean['MemHeapMaxM']) * 100, 2)
+ self.collector.on_bean_kv(self.PREFIX, "memheapusedusage", memheapusedusage)
+ memheapcommittedusage = round(float(bean['MemHeapCommittedM']) / float(bean['MemHeapMaxM']) * 100, 2)
+ self.collector.on_bean_kv(self.PREFIX, "memheapcommittedusage", memheapcommittedusage)
+
+
+class JournalTransactionInfoMetric(JmxMetricListener):
+ PREFIX = "hadoop.namenode.journaltransaction"
+
+ def on_bean(self, bean):
+ if bean.has_key("JournalTransactionInfo"):
+ JournalTransactionInfo = json.loads(bean.get("JournalTransactionInfo"))
+ LastAppliedOrWrittenTxId = float(JournalTransactionInfo.get("LastAppliedOrWrittenTxId"))
+ MostRecentCheckpointTxId = float(JournalTransactionInfo.get("MostRecentCheckpointTxId"))
+ self.collector.on_bean_kv(self.PREFIX, "LastAppliedOrWrittenTxId", LastAppliedOrWrittenTxId)
+ self.collector.on_bean_kv(self.PREFIX, "MostRecentCheckpointTxId", MostRecentCheckpointTxId)
+
+
+if __name__ == '__main__':
+ collector = JmxMetricCollector()
+ collector.register(
+ NNSafeModeMetric(),
+ NNHAMetric(),
+ MemortUsageMetric(),
+ JournalTransactionInfoMetric()
+ )
+ Runner.run(collector)
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1965b4af/eagle-external/hadoop_jmx_collector/metric_collector.py
----------------------------------------------------------------------
diff --git a/eagle-external/hadoop_jmx_collector/metric_collector.py b/eagle-external/hadoop_jmx_collector/metric_collector.py
new file mode 100644
index 0000000..939b811
--- /dev/null
+++ b/eagle-external/hadoop_jmx_collector/metric_collector.py
@@ -0,0 +1,354 @@
+# !/usr/bin/python
+#
+# 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.
+#
+
+import os
+import re
+import time
+import json
+import urllib2
+import sys
+import socket
+import types
+import httplib
+import logging
+import threading
+
+# load six
+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '', 'lib/six'))
+import six
+
+# load kafka-python
+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '', 'lib/kafka-python'))
+from kafka import KafkaClient, SimpleProducer, SimpleConsumer
+
+logging.basicConfig(level=logging.INFO,
+ format='%(asctime)s %(name)-12s %(levelname)-6s %(message)s',
+ datefmt='%m-%d %H:%M')
+
+
+class Helper:
+ def __init__(self):
+ pass
+
+ @staticmethod
+ def load_config(config_file="config.json"):
+ """
+
+ :param config_file:
+ :return:
+ """
+ # read the self-defined filters
+ script_dir = os.path.dirname(__file__)
+ rel_path = "./" + config_file
+ abs_file_path = os.path.join(script_dir, rel_path)
+ if not os.path.isfile(abs_file_path):
+ logging.error(abs_file_path + " doesn't exist, please rename config-sample.json to config.json")
+ exit(1)
+ f = open(abs_file_path, 'r')
+ json_file = f.read()
+ f.close()
+ config = json.loads(json_file)
+ return config
+
+ @staticmethod
+ def is_number(str):
+ """
+
+ :param str:
+ :return:
+ """
+ try:
+ if str == None or isinstance(str, (bool)):
+ return False
+ float(str)
+ return True
+ except:
+ return False
+
+ @staticmethod
+ def http_get(host, port, https=False, path=None):
+ """
+ Read url by GET method
+
+ :param path:
+ :param url:
+ :param https:
+ :return:
+ """
+ url = ":".join([host, str(port)])
+ result = None
+ response = None
+ try:
+ if https:
+ logging.info("Reading https://" + str(url) + path)
+ c = httplib.HTTPSConnection(url, timeout=57)
+ c.request("GET", path)
+ response = c.getresponse()
+ else:
+ logging.info("Reading http://" + str(url) + path)
+ response = urllib2.urlopen("http://" + str(url) + path, timeout=57)
+ logging.debug("Got response")
+ result = response.read()
+ finally:
+ if response is not None:
+ response.close()
+ return result
+
+
+class JmxReader(object):
+ def __init__(self, host, port, https=False):
+ self.host = host
+ self.port = port
+ self.https = https
+ self.jmx_json = None
+ self.jmx_beans = None
+ self.jmx_raw = None
+
+ def open(self):
+ """
+ :return: JmxReader
+ """
+ self.read_raw()
+ self.set_raw(self.jmx_raw)
+ return self
+
+ def read_raw(self):
+ """
+ transfer the json string into dict
+ :param host:
+ :param port:
+ :param https:
+ :return: text
+ """
+ self.jmx_raw = Helper.http_get(self.host, self.port, self.https, "/jmx?anonymous=true")
+ if self.jmx_raw is None:
+ raise Exception("Response from " + url + " is None")
+ return self
+
+ def set_raw(self, text):
+ self.jmx_json = json.loads(text)
+ self.jmx_beans = self.jmx_json[u'beans']
+ self.jmx_raw = text
+ return self
+
+ def get_jmx_beans(self):
+ return self.jmx_beans
+
+ def get_jmx_bean_by_name(self, name):
+ for bean in self.jmx_beans:
+ if bean.has_key("name") and bean["name"] == name:
+ return bean
+
+
+class YarnWSReader:
+ def __init__(self, host, port, https=False):
+ self.host = host
+ self.port = port
+ self.https = https
+
+ def read_cluster_info(self):
+ cluster_info = Helper.http_get(self.host, self.port, self.https, "/ws/v1/cluster/info")
+ logging.debug(cluster_info)
+ return json.loads(cluster_info)
+
+
+class MetricSender(object):
+ def __init__(self, config):
+ pass
+
+ def open(self):
+ pass
+
+ def send(self, msg):
+ raise Exception("should be overrode")
+
+ def close(self):
+ pass
+
+
+class KafkaMetricSender(MetricSender):
+ def __init__(self, config):
+ super(KafkaMetricSender, self).__init__(config)
+ kafka_config = config["output"]["kafka"]
+ # default topic
+ self.topic = kafka_config["topic"].encode('utf-8')
+ # producer
+ self.broker_list = kafka_config["brokerList"]
+ self.kafka_client = None
+ self.kafka_producer = None
+
+ def open(self):
+ self.kafka_client = KafkaClient(self.broker_list, timeout=59)
+ self.kafka_producer = SimpleProducer(self.kafka_client, batch_send=True, batch_send_every_n=500,
+ batch_send_every_t=30)
+
+ def send(self, msg):
+ self.kafka_producer.send_messages(self.topic, json.dumps(msg))
+
+ def close(self):
+ if self.kafka_producer is not None:
+ self.kafka_producer.stop()
+ if self.kafka_client is not None:
+ self.kafka_client.close()
+
+
+class MetricCollector(threading.Thread):
+ def __init__(self):
+ threading.Thread.__init__(self)
+ self.config = Helper.load_config()
+ self.sender = KafkaMetricSender(self.config)
+ self.fqdn = socket.getfqdn()
+ self.init(self.config)
+
+ def init(self, config):
+ pass
+
+ def start(self):
+ try:
+ self.sender.open()
+ self.run()
+ finally:
+ self.sender.close()
+
+ def collect(self, msg):
+ if not msg.has_key("timestamp"):
+ msg["timestamp"] = int(round(time.time() * 1000))
+ if msg.has_key("value"):
+ msg["value"] = float(str(msg["value"]))
+ if not msg.has_key("host") or len(msg["host"]) == 0:
+ msg["host"] = self.fqdn
+ if not msg.has_key("site"):
+ msg["site"] = self.config["env"]["site"]
+
+ self.sender.send(msg)
+
+ def run(self):
+ raise Exception("`run` method should be overrode by sub-class before being called")
+
+
+class Runner(object):
+ @staticmethod
+ def run(*threads):
+ """
+ Execute concurrently
+
+ :param threads:
+ :return:
+ """
+ for thread in threads:
+ thread.start()
+
+class JmxMetricCollector(MetricCollector):
+ selected_domain = None
+ component = None
+ https = False
+ port = None
+ listeners = []
+
+ def init(self, config):
+ if config["input"].has_key("host"):
+ self.host = config["input"]["host"]
+ else:
+ self.host = self.fqdn
+ self.port = config["input"]["port"]
+ self.https = config["input"]["https"]
+ self.component = config["input"]["component"]
+ self.selected_domain = [s.encode('utf-8') for s in config[u'filter'].get('monitoring.group.selected')]
+ self.listeners = []
+
+ def register(self, *listeners):
+ """
+ :param listeners: type of HadoopJmxListener
+ :return:
+ """
+ for listener in listeners:
+ listener.init(self)
+ self.listeners.append(listener)
+
+ def run(self):
+ try:
+ beans = JmxReader(self.host, self.port, self.https).open().get_jmx_beans()
+ self.on_beans(beans)
+ except Exception as e:
+ logging.exception("Failed to read jmx for " + self.host)
+
+ def filter_bean(self, bean, mbean_domain):
+ return mbean_domain in self.selected_domain
+
+ def on_beans(self, beans):
+ for bean in beans:
+ self.on_bean(bean)
+
+ def on_bean(self, bean):
+ # mbean is of the form "domain:key=value,...,foo=bar"
+ mbean = bean[u'name']
+ mbean_domain, mbean_attribute = mbean.rstrip().split(":", 1)
+ mbean_domain = mbean_domain.lower()
+
+ if not self.filter_bean(bean, mbean_domain):
+ return
+
+ context = bean.get("tag.Context", "")
+ metric_prefix_name = self.__build_metric_prefix(mbean_attribute, context)
+
+ # print kafka_dict
+ for key, value in bean.iteritems():
+ self.on_bean_kv(metric_prefix_name, key, value)
+
+ for listener in self.listeners:
+ listener.on_bean(bean.copy())
+
+ def on_bean_kv(self, prefix, key, value):
+ # Skip Tags
+ if re.match(r'tag.*', key):
+ return
+ metric_name = (prefix + '.' + key).lower()
+ self.on_metric({
+ "metric": metric_name,
+ "value": value
+ })
+
+ def on_metric(self, metric):
+ metric["component"] = self.component
+
+ if Helper.is_number(metric["value"]):
+ self.collect(metric)
+
+ for listener in self.listeners:
+ listener.on_metric(metric.copy())
+
+ def __build_metric_prefix(self, mbean_attribute, context):
+ mbean_list = list(prop.split("=", 1) for prop in mbean_attribute.split(","))
+ if context == "":
+ metric_prefix_name = '.'.join([i[1] for i in mbean_list])
+ else:
+ name_index = [i[0] for i in mbean_list].index('name')
+ mbean_list[name_index][1] = context
+ metric_prefix_name = '.'.join([i[1] for i in mbean_list])
+ return ("hadoop." + metric_prefix_name).replace(" ", "").lower()
+
+
+class JmxMetricListener:
+ def init(self, collector):
+ self.collector = collector
+
+ def on_bean(self, bean):
+ pass
+
+ def on_metric(self, metric):
+ pass
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/1965b4af/eagle-external/hadoop_jmx_collector/metric_extensions.py
----------------------------------------------------------------------
diff --git a/eagle-external/hadoop_jmx_collector/metric_extensions.py b/eagle-external/hadoop_jmx_collector/metric_extensions.py
deleted file mode 100644
index 0028204..0000000
--- a/eagle-external/hadoop_jmx_collector/metric_extensions.py
+++ /dev/null
@@ -1,95 +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.
-
-
-# !/usr/bin/python
-
-from util_func import *
-import json
-
-
-# Metric Parsing Callback Entry
-def single_metric_callback(producer, topic, kafka_dict, metric, value):
- if isNumber(value):
- numeric_metric_callack(producer, topic, kafka_dict, metric, value)
- else:
- nonnumeric_metric_callack(producer, topic, kafka_dict, metric, value)
-
-
-def metrics_bean_callback(producer, topic, metric, bean):
- cal_mem_usage(producer, topic, bean, metric, "hadoop.namenode.jvm")
- journal_transaction_info(producer, topic, bean, metric, "hadoop.namenode.journaltransaction")
- nn_hastate(producer,topic,bean,metric,"hadoop.namenode.fsnamesystem")
-
-#################################################
-# Metric Parsing Extensions
-#################################################
-
-def numeric_metric_callack(producer, topic, kafka_dict, metric, value):
- # Send out numeric value directly
- send_output_message(producer, topic, kafka_dict, metric, value)
-
-
-def nonnumeric_metric_callack(producer, topic, kafka_dict, metric, value):
- nn_safe_mode_metric(producer, topic, kafka_dict, metric, value)
-
-def nn_safe_mode_metric(producer, topic, kafka_dict, metric, value):
- if metric == "hadoop.namenode.fsnamesystemstate.fsstate":
- if value == "safeMode":
- value = 1
- else:
- value = 0
-
- send_output_message(producer, topic, kafka_dict, metric, value)
-
-def nn_hastate(producer, topic, bean, metricMap, metric_prefix_name="hadoop.namenode.fsnamesystem"):
- kafka_dict = metricMap.copy()
- if bean[u'tag.HAState'] == "active":
- value = 0
- else:
- value = 1
-
- send_output_message(producer, topic, kafka_dict, metric_prefix_name + ".hastate", value)
-
-def cal_mem_usage(producer, topic, bean, metricMap, metric_prefix_name):
- kafka_dict = metricMap.copy()
- PercentVal = None
- PercentVal = round(float(bean['MemNonHeapUsedM']) / float(bean['MemNonHeapMaxM']) * 100.0, 2)
- send_output_message(producer, topic, kafka_dict, metric_prefix_name + ".MemNonHeapUsedUsage", PercentVal)
-
- PercentVal = round(float(bean['MemNonHeapCommittedM']) / float(bean['MemNonHeapMaxM']) * 100, 2)
- send_output_message(producer, topic, kafka_dict, metric_prefix_name + ".MemNonHeapCommittedUsage", PercentVal)
-
- PercentVal = round(float(bean['MemHeapUsedM']) / float(bean['MemHeapMaxM']) * 100, 2)
- send_output_message(producer, topic, kafka_dict, metric_prefix_name + ".MemHeapUsedUsage", PercentVal)
-
- PercentVal = round(float(bean['MemHeapCommittedM']) / float(bean['MemHeapMaxM']) * 100, 2)
- send_output_message(producer, topic, kafka_dict, metric_prefix_name + ".MemHeapCommittedUsage", PercentVal)
-
-
-def journal_transaction_info(producer, topic, bean, metric, metric_prefix_name):
- new_metric = metric.copy()
- if bean.has_key("JournalTransactionInfo"):
- JournalTransactionInfo = json.loads(bean.get("JournalTransactionInfo"))
-
- LastAppliedOrWrittenTxId = int(JournalTransactionInfo.get("LastAppliedOrWrittenTxId"))
- MostRecentCheckpointTxId = int(JournalTransactionInfo.get("MostRecentCheckpointTxId"))
-
- send_output_message(producer, topic, new_metric, metric_prefix_name + ".LastAppliedOrWrittenTxId",
- LastAppliedOrWrittenTxId)
- send_output_message(producer, topic, new_metric, metric_prefix_name + ".MostRecentCheckpointTxId",
- MostRecentCheckpointTxId)
- else:
- raise Exception("JournalTransactionInfo not found")
[5/9] incubator-eagle git commit: EAGLE-139 EAGLE-163 Eagle UI
Modularization and fix bugs in policy extensions
Posted by hd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/common/controller.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/common/controller.js b/eagle-webservice/src/main/webapp/app/public/feature/common/controller.js
new file mode 100644
index 0000000..50f377c
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/common/controller.js
@@ -0,0 +1,1023 @@
+/*
+ * 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 featureControllers = angular.module("featureControllers");
+ var feature = featureControllers.register("common");
+
+ // ==============================================================
+ // = Function =
+ // ==============================================================
+ feature.service("Policy", function(Entities) {
+ var Policy = function () {};
+
+ Policy.updatePolicyStatus = function(policy, status) {
+ $.dialog({
+ title: "Confirm",
+ content: "Do you want to " + (status ? "enable" : "disable") + " policy[" + policy.tags.policyId + "]?",
+ confirm: true
+ }, function(ret) {
+ if(ret) {
+ policy.enabled = status;
+ Entities.updateEntity("AlertDefinitionService", policy);
+ }
+ });
+ };
+ Policy.deletePolicy = function(policy, callback) {
+ $.dialog({
+ title: "Confirm",
+ content: "Do you want to delete policy[" + policy.tags.policyId + "]?",
+ confirm: true
+ }, function(ret) {
+ if(ret) {
+ policy.enabled = status;
+ Entities.deleteEntity("AlertDefinitionService", policy)._promise.finally(function() {
+ if(callback) {
+ callback(policy);
+ }
+ });
+ }
+ });
+ };
+ return Policy;
+ });
+
+ // ==============================================================
+ // = Policies =
+ // ==============================================================
+
+ // ========================= Policy List ========================
+ feature.navItem("policyList", "Policies", "list");
+ feature.controller('policyList', function(PageConfig, Site, $scope, Application, Entities, Policy) {
+ PageConfig.pageTitle = "Policy List";
+ PageConfig.pageSubTitle = Site.current().tags.site;
+
+ // Initial load
+ $scope.policyList = [];
+ $scope.application = Application.current();
+
+ // List policies
+ var _policyList = Entities.queryEntities("AlertDefinitionService", {site: Site.current().tags.site, dataSource: $scope.application.tags.application});
+ _policyList._promise.then(function() {
+ $.each(_policyList, function(i, policy) {
+ policy.__mailStr = common.getValueByPath(common.parseJSON(policy.notificationDef, {}), "0.recipients", "");
+ policy.__mailList = policy.__mailStr.trim() === "" ? [] : policy.__mailStr.split(/[,;]/);
+ policy.__expression = common.parseJSON(policy.policyDef, {}).expression;
+
+ $scope.policyList.push(policy);
+ });
+ });
+ $scope.policyList._promise = _policyList._promise;
+
+ // Function
+ $scope.searchFunc = function(item) {
+ var key = $scope.search;
+ if(!key) return true;
+
+ var _key = key.toLowerCase();
+ function _hasKey(item, path) {
+ var _value = common.getValueByPath(item, path, "").toLowerCase();
+ return _value.indexOf(_key) !== -1;
+ }
+ return _hasKey(item, "tags.policyId") || _hasKey(item, "__expression") || _hasKey(item, "desc") || _hasKey(item, "owner") || _hasKey(item, "__mailStr");
+ };
+
+ $scope.updatePolicyStatus = Policy.updatePolicyStatus;
+ $scope.deletePolicy = function(policy) {
+ Policy.deletePolicy(policy, function(policy) {
+ var _index = $scope.policyList.indexOf(policy);
+ $scope.policyList.splice(_index, 1);
+ });
+ };
+ });
+
+ // ======================= Policy Detail ========================
+ feature.controller('policyDetail', function(PageConfig, Site, $scope, $wrapState, Entities, Policy, nvd3) {
+ var MAX_PAGESIZE = 10000;
+
+ PageConfig.pageTitle = "Policy Detail";
+ PageConfig.lockSite = true;
+ PageConfig
+ .addNavPath("Policy List", "/common/policyList")
+ .addNavPath("Policy Detail");
+
+ $scope.chartConfig = {
+ chart: "line",
+ xType: "time"
+ };
+
+ // Query policy
+ if($wrapState.param.filter) {
+ $scope.policyList = Entities.queryEntity("AlertDefinitionService", $wrapState.param.filter);
+ } else {
+ $scope.policyList = Entities.queryEntities("AlertDefinitionService", {
+ policyId: $wrapState.param.policy,
+ site: $wrapState.param.site,
+ alertExecutorId: $wrapState.param.executor
+ });
+ }
+
+ $scope.policyList._promise.then(function() {
+ var policy = null;
+
+ if($scope.policyList.length === 0) {
+ $.dialog({
+ title: "OPS!",
+ content: "Policy not found!"
+ }, function() {
+ location.href = "#/common/policyList";
+ });
+ return;
+ } else {
+ policy = $scope.policyList[0];
+
+ policy.__mailStr = common.getValueByPath(common.parseJSON(policy.notificationDef, {}), "0.recipients", "");
+ policy.__mailList = policy.__mailStr.trim() === "" ? [] : policy.__mailStr.split(/[,;]/);
+ policy.__expression = common.parseJSON(policy.policyDef, {}).expression;
+
+ $scope.policy = policy;
+ Site.current(Site.find($scope.policy.tags.site));
+ console.log($scope.policy);
+ }
+
+ // Visualization
+ var _endTime = app.time.now().hour(23).minute(59).second(59).millisecond(0);
+ var _startTime = _endTime.clone().subtract(1, "month").hour(0).minute(0).second(0).millisecond(0);
+ var _cond = {
+ dataSource: policy.tags.dataSource,
+ policyId: policy.tags.policyId,
+ _startTime: _startTime,
+ _endTime: _endTime
+ };
+
+ // > eagle.policy.eval.count
+ $scope.policyEvalSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.policy.eval.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
+
+ // > eagle.policy.eval.fail.count
+ $scope.policyEvalFailSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.policy.eval.fail.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
+
+ // > eagle.alert.count
+ $scope.alertSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.alert.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
+
+ // > eagle.alert.fail.count
+ $scope.alertFailSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.alert.fail.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
+
+ // Alert list
+ $scope.alertList = Entities.queryEntities("AlertService", {
+ site: Site.current().tags.site,
+ dataSource: policy.tags.dataSource,
+ policyId: policy.tags.policyId,
+ _pageSize: MAX_PAGESIZE,
+ _duration: 1000 * 60 * 60 * 24 * 30,
+ __ETD: 1000 * 60 * 60 * 24
+ });
+ });
+
+ // Function
+ $scope.updatePolicyStatus = Policy.updatePolicyStatus;
+ $scope.deletePolicy = function(policy) {
+ Policy.deletePolicy(policy, function() {
+ location.href = "#/common/policyList";
+ });
+ };
+ });
+
+ // ======================== Policy Edit =========================
+ function policyCtrl(create, PageConfig, Site, Policy, $scope, $wrapState, $q, Entities, Application, Authorization) {
+ PageConfig.pageTitle = create ? "Policy Create" : "Policy Edit";
+ PageConfig.pageSubTitle = Site.current().tags.site;
+ PageConfig
+ .addNavPath("Policy List", "/common/policyList")
+ .addNavPath("Policy Edit");
+
+ var _winTimeDesc = "Number unit[millisecond, sec, min, hour, day, month, year]. e.g. 23 sec";
+ var _winTimeRegex = /^\d+\s+(millisecond|milliseconds|second|seconds|sec|minute|minutes|min|hour|hours|day|days|week|weeks|month|months|year|years)$/;
+ var _winTimeDefaultValue = '10 min';
+ $scope.config = {
+ window: [
+ // Display name, window type, required columns[Title, Description || "LONG_FIELD", Regex check, default value]
+ {
+ title: "Message Time Slide",
+ description: "Using timestamp filed from input is used as event's timestamp",
+ type: "externalTime",
+ fields:[
+ {title: "Field", defaultValue: "timestamp", hide: true},
+ {title: "Time", description: _winTimeDesc, regex: _winTimeRegex, defaultValue: _winTimeDefaultValue}
+ ]
+ },
+ {
+ title: "System Time Slide",
+ description: "Using System time is used as timestamp for event's timestamp",
+ type: "time",
+ fields:[
+ {title: "Time", description: _winTimeDesc, regex: _winTimeRegex, defaultValue: _winTimeDefaultValue}
+ ]
+ },
+ {
+ title: "System Time Batch",
+ description: "Same as System Time Window except the policy is evaluated at fixed duration",
+ type: "timeBatch",
+ fields:[
+ {title: "Time", description: _winTimeDesc, regex: _winTimeRegex, defaultValue: _winTimeDefaultValue}
+ ]
+ },
+ {
+ title: "Length Slide",
+ description: "The slide window has a fixed length",
+ type: "length",
+ fields:[
+ {title: "Number", description: "Number only. e.g. 1023", regex: /^\d+$/}
+ ]
+ },
+ {
+ title: "Length Batch",
+ description: "Same as Length window except the policy is evaluated in batch mode when fixed event count reached",
+ type: "lengthBatch",
+ fields:[
+ {title: "Number", description: "Number only. e.g. 1023", regex: /^\d+$/}
+ ]
+ }
+ ]
+ };
+
+ $scope.create = create;
+ $scope.encodedRowkey = $wrapState.param.filter;
+
+ $scope.step = 0;
+ $scope.dataSources = {};
+ $scope.policy = {};
+
+ // ==========================================
+ // = Data Preparation =
+ // ==========================================
+ // Steam list
+ var _streamList = Entities.queryEntities("AlertStreamService", {dataSource: Application.current().tags.application});
+ var _executorList = Entities.queryEntities("AlertExecutorService", {dataSource: Application.current().tags.application});
+ $scope.streamList = _streamList;
+ $scope.executorList = _executorList;
+ $scope.streamReady = false;
+
+ $q.all([_streamList._promise, _executorList._promise]).then(function() {
+ // Map executor with stream
+ $.each(_executorList, function(i, executor) {
+ $.each(_streamList, function(j, stream) {
+ if(stream.tags.dataSource === executor.tags.dataSource && stream.tags.streamName === executor.tags.streamName) {
+ stream.alertExecutor = executor;
+ return false;
+ }
+ });
+ });
+
+ // Fill stream list
+ $.each(_streamList, function(i, unit) {
+ var _srcStreamList = $scope.dataSources[unit.tags.dataSource] = $scope.dataSources[unit.tags.dataSource] || [];
+ _srcStreamList.push(unit);
+ });
+
+ $scope.streamReady = true;
+
+ // ==========================================
+ // = Function =
+ // ==========================================
+ function _findStream(dataSource, streamName) {
+ var _streamList = $scope.dataSources[dataSource];
+ if(!_streamList) return null;
+
+ for(var i = 0 ; i < _streamList.length ; i += 1) {
+ if(_streamList[i].tags.streamName === streamName) {
+ return _streamList[i];
+ }
+ }
+ return null;
+ }
+
+ // ==========================================
+ // = Step control =
+ // ==========================================
+ $scope.steps = [
+ // >> Select stream
+ {
+ title: "Select Stream",
+ ready: function() {
+ return $scope.streamReady;
+ },
+ init: function() {
+ $scope.policy.__.streamName = $scope.policy.__.streamName ||
+ common.array.find($scope.policy.tags.dataSource, _streamList, "tags.dataSource").tags.streamName;
+ },
+ nextable: function() {
+ var _streamName = common.getValueByPath($scope.policy, "__.streamName");
+ if(!_streamName) return false;
+
+ // Detect stream in current data source list
+ return !!common.array.find(_streamName, $scope.dataSources[$scope.policy.tags.dataSource], "tags.streamName");
+ }
+ },
+
+ // >> Define Alert Policy
+ {
+ title: "Define Alert Policy",
+ init: function() {
+ // Normal mode will fetch meta list
+ if(!$scope.policy.__.advanced) {
+ var _stream = _findStream($scope.policy.tags.dataSource, $scope.policy.__.streamName);
+ $scope._stream = _stream;
+
+ if(!_stream.metas) {
+ _stream.metas = Entities.queryEntities("AlertStreamSchemaService", {dataSource: $scope.policy.tags.dataSource, streamName: $scope.policy.__.streamName});
+ _stream.metas._promise.then(function() {
+ _stream.metas.sort(function(a, b) {
+ if(a.tags.attrName < b.tags.attrName) {
+ return -1;
+ } else if(a.tags.attrName > b.tags.attrName) {
+ return 1;
+ }
+ return 0;
+ });
+ });
+ }
+ }
+ },
+ ready: function() {
+ if(!$scope.policy.__.advanced) {
+ return $scope._stream.metas._promise.$$state.status === 1;
+ }
+ return true;
+ },
+ nextable: function() {
+ if($scope.policy.__.advanced) {
+ // Check stream source
+ $scope._stream = null;
+ $.each($scope.dataSources[$scope.policy.tags.dataSource], function(i, stream) {
+ if(($scope.policy.__._expression || "").indexOf(stream.tags.streamName) !== -1) {
+ $scope._stream = stream;
+ return false;
+ }
+ });
+ return $scope._stream;
+ } else {
+ // Window
+ if($scope.policy.__.windowConfig) {
+ var _winMatch = true;
+ var _winConds = $scope.getWindow().fields;
+ $.each(_winConds, function(i, cond) {
+ if(!(cond.val || "").match(cond.regex)) {
+ _winMatch = false;
+ return false;
+ }
+ });
+ if(!_winMatch) return false;
+
+ // Aggregation
+ if($scope.policy.__.groupAgg) {
+ if(!$scope.policy.__.groupAggPath ||
+ !$scope.policy.__.groupCondOp ||
+ !$scope.policy.__.groupCondVal) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+ },
+
+ // >> Configuration & Notification
+ {
+ title: "Configuration & Notification",
+ nextable: function() {
+ return !!$scope.policy.tags.policyId;
+ }
+ }
+ ];
+
+ // ==========================================
+ // = Policy Logic =
+ // ==========================================
+ _streamList._promise.then(function() {
+ // Initial policy entity
+ if(create) {
+ $scope.policy = {
+ __: {
+ toJSON: jQuery.noop,
+ conditions: {},
+ notification: [],
+ dedupe: {
+ alertDedupIntervalMin: 10,
+ emailDedupIntervalMin: 10
+ },
+ policy: {},
+ window: "externalTime",
+ group: "",
+ groupAgg: "count",
+ groupAggPath: "timestamp",
+ groupCondOp: ">=",
+ groupCondVal: "2"
+ },
+ desc: "",
+ enabled: true,
+ prefix: "alertdef",
+ remediationDef: "",
+ tags: {
+ dataSource: Application.current().tags.application,
+ policyType: "siddhiCEPEngine"
+ }
+ };
+
+ // If configured data source
+ if($wrapState.param.dataSrc) {
+ $scope.policy.tags.dataSource = $wrapState.param.dataSrc;
+ if(common.array.find($wrapState.param.dataSrc, Site.current().dataSrcList, "tags.dataSource")) {
+ setTimeout(function() {
+ $scope.changeStep(0, 2, false);
+ $scope.$apply();
+ }, 1);
+ }
+ }
+
+ // Start step
+ $scope.changeStep(0, 1, false);
+ console.log($scope.policy);
+ } else {
+ var _policy = Entities.queryEntity("AlertDefinitionService", $scope.encodedRowkey);
+ _policy._promise.then(function() {
+ if(_policy.length) {
+ $scope.policy = _policy[0];
+ $scope.policy.__ = {
+ toJSON: jQuery.noop
+ };
+
+ Site.current(Site.find($scope.policy.tags.site));
+ } else {
+ $.dialog({
+ title: "OPS",
+ content: "Policy not found!"
+ }, function() {
+ $location.path("/common/policyList");
+ $scope.$apply();
+ });
+ return;
+ }
+
+ // === Revert inner data ===
+ // >> De-dupe
+ $scope.policy.__.dedupe = common.parseJSON($scope.policy.dedupeDef, {});
+
+ // >> Notification
+ $scope.policy.__.notification = common.parseJSON($scope.policy.notificationDef, []);
+
+ // >> Policy
+ var _policyUnit = $scope.policy.__.policy = common.parseJSON($scope.policy.policyDef);
+
+ // >> Parse expression
+ $scope.policy.__.conditions = {};
+ var _condition = _policyUnit.expression.match(/from\s+(\w+)(\[(.*)])?(#window[^\)]*\))?\s+(select (\w+, )?(\w+)\((\w+)\) as [\w\d_]+ (group by (\w+) )?having ([\w\d_]+) ([<>=]+) ([^\s]+))?/);
+ var _cond_stream = _condition[1];
+ var _cond_query = _condition[3] || "";
+ var _cond_window = _condition[4];
+ var _cond_group = _condition[5];
+ var _cond_groupUnit = _condition.slice(7,14);
+
+ if(!_condition) {
+ $scope.policy.__.advanced = true;
+ } else {
+ // > StreamName
+ var _streamName = _cond_stream;
+ var _cond = _cond_query;
+
+ $scope.policy.__.streamName = _streamName;
+
+ // > Conditions
+ // Loop condition groups
+ if(_cond.trim() !== "" && /^\(.*\)$/.test(_cond)) {
+ var _condGrps = _cond.substring(1, _cond.length - 1).split(/\)\s+and\s+\(/);
+ $.each(_condGrps, function(i, line) {
+ // Loop condition cells
+ var _condCells = line.split(/\s+or\s+/);
+ $.each(_condCells, function(i, cell) {
+ var _opMatch = cell.match(/(\S*)\s*(==|!=|>|<|>=|<=|contains)\s*('(?:[^'\\]|\\.)*'|[\w\d]+)/);
+ if(!common.isEmpty(_opMatch)) {
+ var _key = _opMatch[1];
+ var _op = _opMatch[2];
+ var _val = _opMatch[3];
+ var _conds = $scope.policy.__.conditions[_key] = $scope.policy.__.conditions[_key] || [];
+ var _type = "";
+ if(_val.match(/'.*'/)) {
+ _val = _val.slice(1, -1);
+ _type = "string";
+ } else if(_val === "true" || _val === "false") {
+ var _regexMatch = _key.match(/^str:regexp\((\w+),'(.*)'\)/);
+ var _containsMatch = _key.match(/^str:contains\((\w+),'(.*)'\)/);
+ var _mathes = _regexMatch || _containsMatch;
+ if(_mathes) {
+ _key = _mathes[1];
+ _val = _mathes[2];
+ _type = "string";
+ _op = _regexMatch ? "regex" : "contains";
+ _conds = $scope.policy.__.conditions[_key] = $scope.policy.__.conditions[_key] || [];
+ } else {
+ _type = "bool";
+ }
+ } else {
+ _type = "number";
+ }
+ _conds.push($scope._CondUnit(_key, _op, _val, _type));
+ }
+ });
+ });
+ } else if(_cond_query !== "") {
+ $scope.policy.__.advanced = true;
+ }
+ }
+
+ if($scope.policy.__.advanced) {
+ $scope.policy.__._expression = _policyUnit.expression;
+ } else {
+ // > window
+ if(!_cond_window) {
+ $scope.policy.__.window = "externalTime";
+ $scope.policy.__.group = "";
+ $scope.policy.__.groupAgg = "count";
+ $scope.policy.__.groupAggPath = "timestamp";
+ $scope.policy.__.groupCondOp = ">=";
+ $scope.policy.__.groupCondVal = "2";
+ } else {
+ try {
+ $scope.policy.__.windowConfig = true;
+
+ var _winCells = _cond_window.match(/\.(\w+)\((.*)\)/);
+ $scope.policy.__.window = _winCells[1];
+ var _winConds = $scope.getWindow().fields;
+ $.each(_winCells[2].split(","), function(i, val) {
+ _winConds[i].val = val;
+ });
+
+ // Group
+ if(_cond_group) {
+ $scope.policy.__.group = _cond_groupUnit[3];
+ $scope.policy.__.groupAgg = _cond_groupUnit[0];
+ $scope.policy.__.groupAggPath = _cond_groupUnit[1];
+ $scope.policy.__.groupAggAlias = _cond_groupUnit[4] === "aggValue" ? "" : _cond_groupUnit[4];
+ $scope.policy.__.groupCondOp = _cond_groupUnit[5];
+ $scope.policy.__.groupCondVal = _cond_groupUnit[6];
+ } else {
+ $scope.policy.__.group = "";
+ $scope.policy.__.groupAgg = "count";
+ $scope.policy.__.groupAggPath = "timestamp";
+ $scope.policy.__.groupCondOp = ">=";
+ $scope.policy.__.groupCondVal = "2";
+ }
+ } catch(err) {
+ $scope.policy.__.window = "externalTime";
+ }
+ }
+ }
+
+ $scope.changeStep(0, 2, false);
+ console.log($scope.policy);
+ });
+ }
+ });
+
+ // ==========================================
+ // = Function =
+ // ==========================================
+ // UI: Highlight select step
+ $scope.stepSelect = function(step) {
+ return step === $scope.step ? "active" : "";
+ };
+
+ // UI: Collapse all
+ $scope.collapse = function(cntr) {
+ var _list = $(cntr).find(".collapse").css("height", "auto");
+ if(_list.hasClass("in")) {
+ _list.removeClass("in");
+ } else {
+ _list.addClass("in");
+ }
+ };
+
+ // Step process. Will fetch target step attribute and return boolean
+ function _check(key, step) {
+ var _step = $scope.steps[step - 1];
+ if(!_step) return;
+
+ var _value = _step[key];
+ if(typeof _value === "function") {
+ return _value();
+ } else if(typeof _value === "boolean") {
+ return _value;
+ }
+ return true;
+ }
+ // Check step is ready. Otherwise will display load animation
+ $scope.stepReady = function(step) {
+ return _check("ready", step);
+ };
+ // Check whether process next step. Otherwise will disable next button
+ $scope.checkNextable = function(step) {
+ return !_check("nextable", step);
+ };
+ // Switch step
+ $scope.changeStep = function(step, targetStep, check) {
+ if(check === false || _check("checkStep", step)) {
+ $scope.step = targetStep;
+
+ _check("init", targetStep);
+ }
+ };
+
+ // Window
+ $scope.getWindow = function() {
+ if(!$scope.policy || !$scope.policy.__) return null;
+ return common.array.find($scope.policy.__.window, $scope.config.window, "type");
+ };
+
+ // Aggregation
+ $scope.groupAggPathList = function() {
+ return $.grep(common.getValueByPath($scope, "_stream.metas", []), function(meta) {
+ return $.inArray(meta.attrType, ['long','integer','number', 'double', 'float']) !== -1;
+ });
+ };
+
+ $scope.updateGroupAgg = function() {
+ $scope.policy.__.groupAggPath = $scope.policy.__.groupAggPath || common.getValueByPath($scope.groupAggPathList()[0], "tags.attrName");
+
+ if($scope.policy.__.groupAgg === 'count') {
+ $scope.policy.__.groupAggPath = 'timestamp';
+ }
+ };
+
+ // Resolver
+ $scope.resolverTypeahead = function(value, resolver) {
+ var _resolverList = Entities.query("stream/attributeresolve", {
+ site: Site.current().tags.site,
+ resolver: resolver,
+ query: value
+ });
+ return _resolverList._promise.then(function() {
+ return _resolverList;
+ });
+ };
+
+ // Used for input box when pressing enter
+ $scope.conditionPress = function(event) {
+ if(event.which == 13) {
+ setTimeout(function() {
+ $(event.currentTarget).closest(".input-group").find("button").click();
+ }, 1);
+ }
+ };
+ // Check whether has condition
+ $scope.hasCondition = function(key, type) {
+ var _list = common.getValueByPath($scope.policy.__.conditions, key, []);
+ if(_list.length === 0) return false;
+
+ if(type === "bool") {
+ return !_list[0].ignored();
+ }
+ return true;
+ };
+ // Condition unit definition
+ $scope._CondUnit = function(key, op, value, type) {
+ return {
+ key: key,
+ op: op,
+ val: value,
+ type: type,
+ ignored: function() {
+ return this.type === "bool" && this.val === "none";
+ },
+ getVal: function() {
+ return this.type === "string" ? "'" + this.val + "'" : this.val;
+ },
+ toString: function() {
+ return this.op + " " + this.getVal();
+ },
+ toCondString: function() {
+ var _op = this.op === "=" ? "==" : this.op;
+ if(_op === "regex") {
+ return "str:regexp(" + this.key + "," + this.getVal() + ")==true";
+ } else if(_op === "contains") {
+ return "str:contains(" + this.key + "," + this.getVal() + ")==true";
+ } else {
+ return this.key + " " + _op + " " + this.getVal();
+ }
+ }
+ };
+ };
+ // Add condition for policy
+ $scope.addCondition = function(key, op, value, type) {
+ if(value === "" || value === undefined) return false;
+
+ var _condList = $scope.policy.__.conditions[key] = $scope.policy.__.conditions[key] || [];
+ _condList.push($scope._CondUnit(key, op, value, type));
+ return true;
+ };
+ // Convert condition list to description string
+ $scope.parseConditionDesc = function(key) {
+ return $.map($scope.policy.__.conditions[key] || [], function(cond) {
+ if(!cond.ignored()) return "[" + cond.toString() + "]";
+ }).join(" or ");
+ };
+
+ // To query
+ $scope.toQuery = function() {
+ if(!$scope.policy.__) return "";
+
+ if($scope.policy.__.advanced) return $scope.policy.__._expression;
+
+ // > Query
+ var _query = $.map(common.getValueByPath($scope.policy, "__.conditions", {}), function(list) {
+ var _conds = $.map(list, function(cond) {
+ if(!cond.ignored()) return cond.toCondString();
+ });
+ if(_conds.length) {
+ return "(" + _conds.join(" or ") + ")";
+ }
+ }).join(" and ");
+ if(_query) {
+ _query = "[" + _query + "]";
+ }
+
+ // > Window
+ var _window = $scope.getWindow();
+ var _windowStr = "";
+ if($scope.policy.__.windowConfig) {
+ _windowStr = $.map(_window.fields, function(field) {
+ return field.val;
+ }).join(",");
+ _windowStr = "#window." + _window.type + "(" + _windowStr + ")";
+
+ // > Group
+ if($scope.policy.__.group) {
+ _windowStr += common.template(" select ${group}, ${groupAgg}(${groupAggPath}) as ${groupAggAlias} group by ${group} having ${groupAggAlias} ${groupCondOp} ${groupCondVal}", {
+ group: $scope.policy.__.group,
+ groupAgg: $scope.policy.__.groupAgg,
+ groupAggPath: $scope.policy.__.groupAggPath,
+ groupCondOp: $scope.policy.__.groupCondOp,
+ groupCondVal: $scope.policy.__.groupCondVal,
+ groupAggAlias: $scope.policy.__.groupAggAlias || "aggValue"
+ });
+ } else {
+ _windowStr += common.template(" select ${groupAgg}(${groupAggPath}) as ${groupAggAlias} having ${groupAggAlias} ${groupCondOp} ${groupCondVal}", {
+ groupAgg: $scope.policy.__.groupAgg,
+ groupAggPath: $scope.policy.__.groupAggPath,
+ groupCondOp: $scope.policy.__.groupCondOp,
+ groupCondVal: $scope.policy.__.groupCondVal,
+ groupAggAlias: $scope.policy.__.groupAggAlias || "aggValue"
+ });
+ }
+ } else {
+ _windowStr = " select *";
+ }
+
+ return common.template("from ${stream}${query}${window} insert into outputStream;", {
+ stream: $scope.policy.__.streamName,
+ query: _query,
+ window: _windowStr
+ });
+ };
+
+ // ==========================================
+ // = Update Policy =
+ // ==========================================
+ // dedupeDef notificationDef policyDef
+ $scope.finishPolicy = function() {
+ $scope.lock = true;
+
+ // dedupeDef
+ $scope.policy.dedupeDef = JSON.stringify($scope.policy.__.dedupe);
+
+ // notificationDef
+ $scope.policy.__.notification = $scope.policy.__.notification || [];
+ var _notificationUnit = $scope.policy.__.notification[0];
+ if(_notificationUnit) {
+ _notificationUnit.flavor = "email";
+ _notificationUnit.id = "email_1";
+ _notificationUnit.tplFileName = "";
+ }
+ $scope.policy.notificationDef = JSON.stringify($scope.policy.__.notification);
+
+ // policyDef
+ $scope.policy.__._dedupTags = $scope.policy.__._dedupTags || {};
+ $scope.policy.__.policy = {
+ expression: $scope.toQuery(),
+ type: "siddhiCEPEngine"
+ };
+ $scope.policy.policyDef = JSON.stringify($scope.policy.__.policy);
+
+ // alertExecutorId
+ if($scope._stream.alertExecutor) {
+ $scope.policy.tags.alertExecutorId = $scope._stream.alertExecutor.tags.alertExecutorId;
+ } else {
+ $scope.lock = false;
+ $.dialog({
+ title: "OPS!",
+ content: "Alert Executor not defined! Please check 'AlertExecutorService'!"
+ });
+ return;
+ }
+
+ // site
+ $scope.policy.tags.site = $scope.policy.tags.site || Site.current().tags.site;
+
+ // owner
+ $scope.policy.owner = Authorization.userProfile.username;
+
+ // Update function
+ function _updatePolicy() {
+ Entities.updateEntity("AlertDefinitionService", $scope.policy)._promise.success(function(data) {
+ $.dialog({
+ title: "Success",
+ content: (create ? "Create" : "Update") + " success!"
+ }, function() {
+ if(data.success) {
+ location.href = "#/common/policyList";
+ } else {
+ $.dialog({
+ title: "OPS",
+ content: (create ? "Create" : "Update") + "failed!" + JSON.stringify(data)
+ });
+ }
+ });
+
+ $scope.create = create = false;
+ $scope.encodedRowkey = data.obj[0];
+ }).error(function(data) {
+ $.dialog({
+ title: "OPS",
+ content: (create ? "Create" : "Update") + "failed!" + JSON.stringify(data)
+ });
+ }).then(function() {
+ $scope.lock = false;
+ });
+ }
+
+ // Check if already exist
+ if($scope.create) {
+ var _checkList = Entities.queryEntities("AlertDefinitionService", {
+ alertExecutorId: $scope.policy.tags.alertExecutorId,
+ policyId: $scope.policy.tags.policyId,
+ policyType: "siddhiCEPEngine",
+ dataSource: $scope.policy.tags.dataSource
+ });
+ _checkList._promise.then(function() {
+ if(_checkList.length) {
+ $.dialog({
+ title: "Override Confirm",
+ content: "Already exists PolicyID '" + $scope.policy.tags.policyId + "'. Do you want to override?",
+ confirm: true
+ }, function(ret) {
+ if(ret) {
+ _updatePolicy();
+ } else {
+ $scope.lock = false;
+ $scope.$apply();
+ }
+ });
+ } else {
+ _updatePolicy();
+ }
+ });
+ } else {
+ _updatePolicy();
+ }
+ };
+ });
+ }
+
+ feature.controller('policyCreate', function(PageConfig, Site, Policy, $scope, $wrapState, $q, Entities, Application, Authorization) {
+ var _args = [true];
+ _args.push.apply(_args, arguments);
+ policyCtrl.apply(this, _args);
+ }, "policyEdit");
+ feature.controller('policyEdit', function(PageConfig, Site, Policy, $scope, $wrapState, $q, Entities, Application, Authorization) {
+ PageConfig.lockSite = true;
+ var _args = [false];
+ _args.push.apply(_args, arguments);
+ policyCtrl.apply(this, _args);
+ });
+
+ // ==============================================================
+ // = Alerts =
+ // ==============================================================
+
+ // ========================= Alert List =========================
+ feature.navItem("alertList", "Alerts", "exclamation-triangle");
+ feature.controller('alertList', function(PageConfig, Site, $scope, $wrapState, $interval, $timeout, Entities, Application) {
+ PageConfig.pageSubTitle = Site.current().tags.site;
+
+ var MAX_PAGESIZE = 10000;
+
+ // Initial load
+ $scope.application = Application.current();
+
+ $scope.alertList = [];
+ $scope.alertList.ready = false;
+
+ // Load data
+ function _loadAlerts() {
+ if($scope.alertList._promise) {
+ $scope.alertList._promise.abort();
+ }
+
+ var _list = Entities.queryEntities("AlertService", {
+ site: Site.current().tags.site,
+ dataSource: $scope.application.tags.application,
+ hostname: null,
+ _pageSize: MAX_PAGESIZE,
+ _duration: 1000 * 60 * 60 * 24 * 30,
+ __ETD: 1000 * 60 * 60 * 24
+ });
+ $scope.alertList._promise = _list._promise;
+ _list._promise.then(function() {
+ var index;
+
+ if($scope.alertList[0]) {
+ // List new alerts
+ for(index = 0 ; index < _list.length ; index += 1) {
+ var _alert = _list[index];
+ _alert.__new = true;
+ if(_alert.encodedRowkey === $scope.alertList[0].encodedRowkey) {
+ break;
+ }
+ }
+
+ if(index > 0) {
+ $scope.alertList.unshift.apply($scope.alertList, _list.slice(0, index));
+
+ // Clean up UI highlight
+ $timeout(function() {
+ $.each(_list, function(i, alert) {
+ delete alert.__new;
+ });
+ }, 100);
+ }
+ } else {
+ // List all alerts
+ $scope.alertList.push.apply($scope.alertList, _list);
+ }
+
+ $scope.alertList.ready = true;
+ });
+ }
+
+ _loadAlerts();
+ var _loadInterval = $interval(_loadAlerts, app.time.refreshInterval);
+ $scope.$on('$destroy',function(){
+ $interval.cancel(_loadInterval);
+ });
+ });
+
+ // ========================= Alert List =========================
+ feature.controller('alertDetail', function(PageConfig, Site, $scope, $wrapState, Entities) {
+ PageConfig.pageTitle = "Alert Detail";
+ PageConfig.lockSite = true;
+ PageConfig
+ .addNavPath("Alert List", "/common/alertList")
+ .addNavPath("Alert Detail");
+
+ $scope.common = common;
+
+ // Query policy
+ $scope.alertList = Entities.queryEntity("AlertService", $wrapState.param.filter);
+ $scope.alertList._promise.then(function() {
+ if($scope.alertList.length === 0) {
+ $.dialog({
+ title: "OPS!",
+ content: "Alert not found!"
+ }, function() {
+ location.href = "#/common/alertList";
+ });
+ } else {
+ $scope.alert = $scope.alertList[0];
+ Site.current(Site.find($scope.alert.tags.site));
+ console.log($scope.alert);
+ }
+ });
+
+ // UI
+ $scope.getMessageTime = function(alert) {
+ var _time = common.getValueByPath(alert, "alertContext.properties.timestamp");
+ return Number(_time);
+ };
+ });
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/common/page/alertDetail.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/common/page/alertDetail.html b/eagle-webservice/src/main/webapp/app/public/feature/common/page/alertDetail.html
new file mode 100644
index 0000000..fee5ab1
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/common/page/alertDetail.html
@@ -0,0 +1,61 @@
+<!--
+ 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-info">
+ <div class="box-header with-border">
+ <h3 class="box-title" id="policyId">
+ {{alert.tags.policyId}}
+ <small>{{common.format.date(alert.timestamp)}}</small>
+ </h3>
+ </div><!-- /.box-header -->
+
+ <div class="box-body">
+ <a class="btn btn-primary pull-right" href="#/common/policyDetail/?policy={{alert.tags.policyId}}&site={{alert.tags.site}}&executor={{alert.tags.alertExecutorId}}">View Policy</a>
+
+ <div class="inline-group">
+ <dl><dt>Site</dt><dd>{{alert.tags.site}}</dd></dl>
+ <dl><dt>Data Source</dt><dd>{{alert.tags.dataSource}}</dd></dl>
+ </div>
+ <div class="inline-group">
+ <dl><dt>Alert Time</dt><dd>{{common.format.date(alert.timestamp)}}</dd></dl>
+ <dl><dt>Message Time</dt><dd>{{common.format.date(alert.alertContext.properties.timestamp)}}</dd></dl>
+ </div>
+ <!--div class="inline-group">
+ <dl><dt>Severity</dt><dd>{{alert.alertContext.properties.severity}}</dd></dl>
+ </div-->
+ <div class="inline-group">
+ <dl><dt>Stream Name</dt><dd>{{alert.tags.sourceStreams}}</dd></dl>
+ </div>
+ <div class="inline-group">
+ <dl><dt>Alert Source</dt><dd>{{alert.tags.alertSource}}</dd></dl>
+ </div>
+ <div class="inline-group">
+ <dl><dt>User</dt><dd>{{alert.alertContext.properties.user}}</dd></dl>
+ <dl><dt>Host</dt><dd>{{alert.alertContext.properties.host}}</dd></dl>
+ </div>
+ <div class="inline-group">
+ <dl><dt>Event</dt><dd>{{alert.alertContext.properties.alertEvent}}</dd></dl>
+ </div>
+ <div class="inline-group">
+ <dl><dt>Message</dt><dd>{{alert.alertContext.properties.alertMessage}}</dd></dl>
+ </div>
+ </div><!-- /.box-body -->
+
+ <div class="overlay" ng-hide="alertList._promise.$$state.status === 1;">
+ <i class="fa fa-refresh fa-spin"></i>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/common/page/alertList.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/common/page/alertList.html b/eagle-webservice/src/main/webapp/app/public/feature/common/page/alertList.html
new file mode 100644
index 0000000..44f5a32
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/common/page/alertList.html
@@ -0,0 +1,69 @@
+<!--
+ 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 with-border">
+ <i class="fa fa-list-alt"> </i>
+ <h3 class="box-title">
+ {{application.displayName}}
+ </h3>
+ </div>
+ <div class="box-body">
+ <p ng-show="!alertList.ready">
+ <span class="fa fa-refresh fa-spin"> </span>
+ Loading...
+ </p>
+
+ <div sorttable source="alertList" sort="-timestamp">
+ <table class="table table-bordered" ng-non-bindable>
+ <thead>
+ <tr>
+ <th width="170" sortpath="timestamp">Alert Time</th>
+ <th width="170" sortpath="alertContext.properties.timestamp">Message Time</th>
+ <th width="105" sortpath="tags.dataSource">Data Source</th>
+ <!--th width="70" sortpath="severity">Type</th-->
+ <th width="150" sortpath="tags.policyId">Policy Name</th>
+ <th width="60" sortpath="alertContext.properties.user">User</th>
+ <th width="150" sortpath="alertContext.properties.host">Host</th>
+ <th sortpath="alertContext.properties.emailMessage">Description</th>
+ <th width="50"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-class="{info : item.__new}">
+ <td>{{common.format.date(item.timestamp)}}</td>
+ <td>{{common.format.date(item.alertContext.properties.timestamp)}}</td>
+ <td>{{item.tags.dataSource}}</td>
+ <!--td>{{item.severity}}</td-->
+ <td class="text-nowrap">
+ <a class="fa fa-share-square-o" ng-show="item.tags.policyId"
+ href="#/common/policyDetail/?policy={{item.tags.policyId}}&site={{item.tags.site}}&executor={{item.tags.alertExecutorId}}"> </a>
+ {{item.tags.policyId}}
+ </td>
+ <td>{{item.alertContext.properties.user}}</td>
+ <td>{{item.alertContext.properties.host}}</td>
+ <td>{{item.alertContext.properties.alertMessage}}</td>
+ <td><a href="#/common/alertDetail/{{item.encodedRowkey}}">Detail</a></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ </div>
+ <!--div class="box-footer clearfix">
+ </div-->
+</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/common/page/dataSrcConfig.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/common/page/dataSrcConfig.html b/eagle-webservice/src/main/webapp/app/public/feature/common/page/dataSrcConfig.html
new file mode 100644
index 0000000..ba4f728
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/common/page/dataSrcConfig.html
@@ -0,0 +1,125 @@
+<div class="box box-primary" ng-repeat="_site in Site.list">
+ <div class="box-header">
+ <h3 class="box-title">{{_site.name}}</h3>
+ <div class="box-tools pull-right">
+ <button class="btn btn-box-tool" data-widget="collapse">
+ <i class="fa fa-minus"></i>
+ </button>
+ <button class="btn btn-box-tool" ng-click="showSiteEditor(_site)">
+ <i class="fa fa-wrench"></i>
+ </button>
+ </div>
+ </div><!-- /.box-header -->
+ <div class="box-body">
+ <div class="row">
+ <div class="col-md-4" ng-repeat="dataSrc in _site.dataSrcList">
+ <div class="info-box" ng-class="dataSrc.enabled !== false ? 'bg-aqua' : 'bg-gray'">
+ <span class="info-box-icon"><i class="fa fa-suitcase"></i></span>
+ <div class="info-box-content">
+ <a class="fa fa-cog config pull-right" ng-click="showDataSourceEditor(dataSrc)"></a>
+ <span class="info-box-text">{{dataSrc.desc || dataSrc.tags.dataSource}}</span>
+
+ <span class="info-box-number" ng-show="dataSrc.hide"><small>-</small></span>
+ <span class="info-box-number" ng-show="!dataSrc.hide">
+ <span class="fa fa-refresh fa-spin" ng-hide="policyStatistic._promise.$$state.status === 1"></span>
+ <span ng-show="policyStatistic._promise.$$state.status === 1">{{getPolicyCount(_site.name, dataSrc.tags.dataSource)}}</span>
+ <small>Policies</small>
+ </span>
+ <div class="progress">
+ <div class="progress-bar"></div>
+ </div>
+ <span class="progress-description" ng-show="dataSrc.hide"><small>-</small></span>
+ <span class="progress-description" ng-show="!dataSrc.hide">
+ <span class="fa fa-refresh fa-spin" ng-hide="alertStatistic._promise.$$state.status === 1"></span>
+ <span ng-show="alertStatistic._promise.$$state.status === 1">{{getAlertCount(_site.name, dataSrc.tags.dataSource)}}</span>
+ alerts in 30 Days
+ </span>
+ </div><!-- /.info-box-content -->
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+
+<!-- Modal: Create / Edit site -->
+<div class="modal fade" id="siteMDL" tabindex="-1" role="dialog">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">×</span>
+ </button>
+ <h4 class="modal-title">{{!_siteEntity.srcSite ? 'Create' : 'Config'}} Site</h4>
+ </div>
+ <div class="modal-body">
+ <div class="form-group">
+ <label>* Site Name</label>
+ <input type="text" class="form-control" placeholder="Site name..." ng-model="_siteEntity.name" ng-disabled="!!_siteEntity.srcSite" id="siteName">
+ </div>
+
+ <label>
+ * Data Source
+ <small class="text-muted">at least select 1 source</small>
+ </label>
+ <div class="checkbox" ng-repeat="item in _siteEntity.dataSrcList">
+ <label>
+ <input type="checkbox" value="{{item.name}}"
+ ng-checked="item.enabled"
+ ng-click="item.enabled = !item.enabled">
+ {{item.name}}
+ </label>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">
+ Close
+ </button>
+ <button type="button" class="btn btn-primary" ng-click="confirmUpateSite()"
+ ng-disabled="!checkUpdateSite()">
+ {{!_siteEntity.srcSite ? 'Create' : 'Update'}}
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<!-- Modal: Edit data source -->
+<div class="modal fade" id="dataSrcMDL" tabindex="-1" role="dialog">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">×</span>
+ </button>
+ <h4 class="modal-title">{{_dataSrcEntity.tags.dataSource}}</h4>
+ </div>
+ <div class="modal-body">
+ <div class="checkbox">
+ <label>
+ <input type="checkbox"
+ ng-checked="_dataSrcEntity.enabled"
+ ng-click="_dataSrcEntity.enabled = !_dataSrcEntity.enabled">
+ Enabled
+ </label>
+ </div>
+
+ <div class="form-group">
+ <label>Configuration</label>
+ <textarea type="text" class="form-control" placeholder="Data source configuration..." ng-model="_dataSrcEntity.config" id="dataSrcConfig" rows="10"></textarea>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger pull-left" ng-click="confirmDeleteDataSource()">
+ Delete Source
+ </button>
+
+ <button type="button" class="btn btn-default" data-dismiss="modal">
+ Close
+ </button>
+ <button type="button" class="btn btn-primary" ng-click="confirmUpateDataSource()" ng-disabled="_dataSrcEntityLock">
+ Update
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyDetail.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyDetail.html b/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyDetail.html
new file mode 100644
index 0000000..8670839
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyDetail.html
@@ -0,0 +1,172 @@
+<!--
+ 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-info">
+ <div class="box-header with-border">
+ <h3 class="box-title">
+ {{policy.tags.policyId}}
+ <small>{{policy.tags.site}}</small>
+ </h3>
+ </div>
+
+ <div class="box-body">
+ <div class="row">
+ <div class="col-xs-8">
+ <div class="inline-group">
+ <dl><dt>Data Source</dt><dd>{{policy.tags.dataSource}}</dd></dl>
+ <dl><dt>Status</dt><dd>
+ <span ng-show="policy.enabled" class="text-muted"><i class="fa fa-square text-green"></i> Enabled</span>
+ <span ng-show="!policy.enabled" class="text-muted"><i class="fa fa-square text-muted"></i> Disabled</span>
+ </dd></dl>
+ </div>
+ <div class="inline-group">
+ <dl><dt>Description</dt><dd>{{policy.desc}}</dd></dl>
+ </div>
+ <div class="inline-group">
+ <dl><dt>Alert</dt><dd>
+ <a href="mailto:{{mail}}" ng-repeat="mail in policy.__mailList track by $index" style="margin-right: 10px;">{{mail}}</a>
+ </dd></dl>
+ </div>
+ </div>
+ <div class="col-xs-4 text-right" ng-show="Auth.isRole('ROLE_ADMIN')">
+ <a class="btn btn-primary" href="#/common/policyEdit/{{policy.encodedRowkey}}">Edit</a>
+ <button class="btn btn-warning" ng-show="!policy.enabled" ng-click="updatePolicyStatus(policy, true)">Enable</button>
+ <button class="btn btn-warning" ng-show="policy.enabled" ng-click="updatePolicyStatus(policy, false)">Disable</button>
+ <button class="btn btn-danger" ng-click="deletePolicy(policy)">Delete</button>
+ </div>
+ </div>
+ </div>
+
+ <div class="overlay" ng-hide="policyList._promise.$$state.status === 1;">
+ <i class="fa fa-refresh fa-spin"></i>
+ </div>
+
+ <div class="box-footer clearfix">
+ <a data-toggle="collapse" href="[data-id='query']">
+ View Query
+ </a>
+ <div data-id="query" class="collapse in">
+ <pre>{{policy.__expression}}</pre>
+ </div>
+ </div>
+</div>
+
+<div class="nav-tabs-custom">
+ <ul class="nav nav-tabs">
+ <li class="active">
+ <a href="[data-id='visualization']" data-toggle="tab">Visualization</a>
+ </li>
+ <li>
+ <a href="[data-id='statistics']" data-toggle="tab">Statistics</a>
+ </li>
+ <li>
+ <a href="[data-id='alerts']" data-toggle="tab">Alerts</a>
+ </li>
+ </ul>
+ <div class="tab-content">
+ <div class="tab-pane active" data-id="visualization">
+ <div class="row">
+ <div class="col-xs-6">
+ <div nvd3="policyEvalSeries" data-title="Policy Eval Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
+ </div>
+ <div class="col-xs-6">
+ <div nvd3="policyEvalFailSeries" data-title="Policy Eval Fail Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
+ </div>
+ <div class="col-xs-6">
+ <div nvd3="alertSeries" data-title="Alert Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
+ </div>
+ <div class="col-xs-6">
+ <div nvd3="alertFailSeries" data-title="Alert Fail Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
+ </div>
+ </div>
+ </div>
+
+ <div class="tab-pane" data-id="statistics">
+ <div class="row">
+ <div class="col-xs-3">
+ <div class="info-box bg-aqua">
+ <span class="info-box-icon"><i class="fa fa-bookmark-o"></i></span>
+ <div class="info-box-content">
+ <span class="info-box-text">Policy Eval Count</span>
+ <span class="info-box-number">{{common.array.sum(policyEvalSeries, "1")}} <small>(Monthly)</small></span>
+ <span class="info-box-number">{{policyEvalSeries[policyEvalSeries.length - 1][1]}} <small>(Daily)</small></span>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-3">
+ <div class="info-box bg-red">
+ <span class="info-box-icon"><i class="fa fa-bookmark-o"></i></span>
+ <div class="info-box-content">
+ <span class="info-box-text">Policy Eval Fail Count</span>
+ <span class="info-box-number">{{common.array.sum(policyEvalFailSeries, "1")}} <small>(Monthly)</small></span>
+ <span class="info-box-number">{{policyEvalFailSeries[policyEvalFailSeries.length - 1][1]}} <small>(Daily)</small></span>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-3">
+ <div class="info-box bg-aqua">
+ <span class="info-box-icon"><i class="fa fa-bookmark-o"></i></span>
+ <div class="info-box-content">
+ <span class="info-box-text">Alert Count</span>
+ <span class="info-box-number">{{common.array.sum(alertSeries, "1")}} <small>(Monthly)</small></span>
+ <span class="info-box-number">{{alertSeries[alertSeries.length - 1][1]}} <small>(Daily)</small></span>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-3">
+ <div class="info-box bg-red">
+ <span class="info-box-icon"><i class="fa fa-bookmark-o"></i></span>
+ <div class="info-box-content">
+ <span class="info-box-text">Alert Fail Count</span>
+ <span class="info-box-number">{{common.array.sum(alertFailSeries, "1")}} <small>(Monthly)</small></span>
+ <span class="info-box-number">{{alertFailSeries[alertFailSeries.length - 1][1]}} <small>(Daily)</small></span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="tab-pane" data-id="alerts">
+ <div sorttable source="alertList" sort="-timestamp">
+ <table class="table table-bordered" ng-non-bindable>
+ <thead>
+ <tr>
+ <th width="170" sortpath="timestamp">Alert Time</th>
+ <th width="170" sortpath="alertContext.properties.timestamp">Message Time</th>
+ <th width="60" sortpath="alertContext.properties.user">User</th>
+ <th width="150" sortpath="alertContext.properties.host">Host</th>
+ <th sortpath="alertContext.properties.emailMessage">Description</th>
+ <th width="50"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-class="{info : item.__new}">
+ <td>{{common.format.date(item.timestamp)}}</td>
+ <td>{{common.format.date(item.alertContext.properties.timestamp)}}</td>
+ <td>{{item.alertContext.properties.user}}</td>
+ <td>{{item.alertContext.properties.host}}</td>
+ <td>{{item.alertContext.properties.alertMessage}}</td>
+ <td><a href="#/common/alertDetail/{{item.encodedRowkey}}">Detail</a></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyEdit.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyEdit.html b/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyEdit.html
new file mode 100644
index 0000000..e07cb0c
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyEdit.html
@@ -0,0 +1,359 @@
+<!--
+ 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="progress active" ng-show="!streamReady">
+ <div class="progress-bar progress-bar-primary progress-bar-striped" style="width: 100%">
+ </div>
+</div>
+
+<!-- Step navigation -->
+<div ng-show="streamReady">
+ <div class="row step-cntr">
+ <div class="col-sm-4" ng-repeat="step in steps">
+ <div class="step" ng-class="stepSelect($index + 1)">
+ <h1>{{$index + 1}}</h1>
+ <h2>Step {{$index + 1}}</h2>
+ <p title="{{step.title}}">{{step.title}}</p>
+ </div>
+ </div>
+ </div>
+
+ <!-- Step container -->
+ <div class="box box-info">
+ <div class="box-header with-border">
+ <h3 class="box-title">Step {{step}} - {{steps[step - 1].title}}</h3>
+ </div><!-- /.box-header -->
+
+ <div class="box-body">
+ <!-- ---------------------- Step Body Start ---------------------- -->
+
+ <!-- Step 1: Data Source -->
+ <!--div ng-show="step === 1">
+ <div class="form-group">
+ <label>Select Data Source</label>
+ <select class="form-control" ng-model="policy.tags.dataSource">
+ <option ng-repeat="dataSource in Site.current().dataSrcList" ng-hide="dataSource.hide" value="{{dataSource.tags.dataSource}}">{{dataSource.desc || dataSource.tags.dataSource}}</option>
+ </select>
+ </div>
+ </div-->
+
+ <!-- Step 1: Stream -->
+ <div ng-show="step === 1">
+ <div class="pull-right" ng-show="policy.__.advanced === undefined">
+ <span class="text-muted">or</span>
+ <a ng-click="policy.__.advanced = true;">Advanced</a>
+ </div>
+
+ <div class="form-group">
+ <label>Select Stream</label>
+ <select class="form-control" ng-model="policy.__.streamName" ng-show="!policy.__.advanced">
+ <option ng-repeat="stream in dataSources[policy.tags.dataSource]">{{stream.tags.streamName}}</option>
+ </select>
+ <select class="form-control" ng-show="policy.__.advanced" disabled="disabled">
+ <option>[Advanced Mode]</option>
+ </select>
+ </div>
+
+ <div class="checkbox" ng-show="policy.__.advanced !== undefined">
+ <label>
+ <input type="checkbox" ng-model="policy.__.advanced">
+ Advanced Mode
+ </label>
+ </div>
+ </div>
+
+ <!-- Step 2: Define Alert Policy -->
+ <div ng-show="step === 2 && !policy.__.advanced">
+ <!-- Criteria -->
+ <div>
+ <label>Match Criteria</label>
+ <a ng-click="collapse('.panel-group')">expand / collapse all</a>
+
+ <div class="panel-group panel-group-sm" role="tablist">
+ <div class="panel panel-default"
+ ng-repeat="meta in _stream.metas"
+ ng-init="op = '=='; val = null; type = (meta.attrType || '').toLowerCase();">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <span class="bg-navy disabled color-palette pull-right">
+ {{parseConditionDesc(meta.tags.attrName)}}
+ </span>
+
+ <a role="button" data-toggle="collapse" href="[data-name='{{meta.tags.attrName}}']" class="collapsed">
+ <span class="fa fa-square" ng-class="hasCondition(meta.tags.attrName, type) ? 'text-green' : 'text-muted'"> </span>
+ {{meta.attrDisplayName || meta.tags.attrName}}
+ <span class="fa fa-question-circle" ng-show="meta.attrDescription"
+ uib-tooltip="{{meta.attrDescription}}" tooltip-placement="right" tooltip-animation="false"> </span>
+ </a>
+ </h4>
+ </div>
+ <div data-name="{{meta.tags.attrName}}" data-type="{{meta.attrType}}" role="tabpanel" class="collapse">
+ <div class="panel-body">
+ <ul ng-show="type !== 'bool'">
+ <li ng-repeat="cond in policy.__.conditions[meta.tags.attrName]">
+ [<a ng-click="policy.__.conditions[meta.tags.attrName].splice($index, 1)">X</a>]
+ {{cond.toString()}}
+ </li>
+ </ul>
+
+ <!-- String -->
+ <div ng-if="type == 'string'">
+ <div class="input-group" style="max-width: 450px;">
+ <div class="input-group-btn">
+ <select class="form-control" ng-model="op">
+ <option ng-repeat="mark in ['==','!=','contains','regex']">{{mark}}</option>
+ </select>
+ </div>
+
+ <!-- With resolver -->
+ <input type="text" class="form-control" autocomplete="off" ng-model="val" ng-show="meta.attrValueResolver"
+ ng-keypress="conditionPress($event, meta.tags.attrName, op, val, type)"
+ uib-typeahead="item for item in resolverTypeahead($viewValue, meta.attrValueResolver)">
+ <!-- Without resolver -->
+ <input type="text" class="form-control" autocomplete="off" ng-model="val" ng-show="!meta.attrValueResolver"
+ ng-keypress="conditionPress($event, meta.tags.attrName, op, val, type)">
+
+ <span class="input-group-btn">
+ <button class="btn btn-info btn-flat" type="button" ng-click="addCondition(meta.tags.attrName, op, val, type);val=null;">Add</button>
+ </span>
+ </div>
+ </div>
+
+ <!-- Number -->
+ <div ng-if="type == 'long' || type == 'integer' || type == 'number' || type == 'double' || type == 'float'">
+ <div class="input-group" style="max-width: 450px;">
+ <div class="input-group-btn">
+ <select class="form-control" ng-model="op">
+ <option ng-repeat="mark in ['==','!=','>','>=','<','<=']">{{mark}}</option>
+ </select>
+ </div>
+
+ <input type="number" class="form-control" autocomplete="off" placeholder="Number Only..." ng-model="val" ng-keypress="conditionPress($event, meta.tags.attrName, op, val, type)">
+ <span class="input-group-btn">
+ <button class="btn btn-info btn-flat" type="button" ng-click="addCondition(meta.tags.attrName, op, val, type) ? val=null : void(0);">Add</button>
+ </span>
+ </div>
+ </div>
+
+ <!-- Boolean -->
+ <div ng-if="type == 'bool'" ng-init="policy.__.conditions[meta.tags.attrName] = policy.__.conditions[meta.tags.attrName] || [_CondUnit(meta.tags.attrName, '==', 'none', 'bool')]">
+ <select class="form-control" ng-model="policy.__.conditions[meta.tags.attrName][0].val" style="max-width: 100px;">
+ <option ng-repeat="bool in ['none','true','false']">{{bool}}</option>
+ </select>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Window -->
+ <div class="checkbox">
+ <label>
+ <input type="checkbox" ng-checked="policy.__.windowConfig" ng-click="policy.__.windowConfig = !policy.__.windowConfig"> Slide Window
+ </label>
+ </div>
+ <div ng-show="policy.__.windowConfig">
+ <div class="row">
+ <div class="col-md-4">
+ <div class="form-group">
+ <label>Window</label>
+ <select class="form-control" ng-model="policy.__.window"
+ uib-tooltip="{{getWindow().description}}" tooltip-animation="false">
+ <option ng-repeat="item in config.window" value="{{item.type}}">{{item.title}}</option>
+ </select>
+ </div>
+ </div>
+
+ <!-- fields -->
+ <div class="col-md-4" ng-repeat="field in getWindow().fields" ng-init="field.val = field.val || (field.defaultValue || '');" ng-hide="field.hide">
+ <div class="form-group" ng-class="{'has-warning' : !field.val || !field.val.match(field.regex)}">
+ <label>Window - {{field.title}}</label>
+ <input type="text" class="form-control" autocomplete="off" placeholder="{{field.description}}" ng-model="field.val" title="{{field.description}}">
+ </div>
+ </div>
+ </div>
+
+ <!-- Aggregation -->
+ <div class="row">
+ <div class="col-md-4">
+ <div class="form-group" ng-class="{'text-yellow' : (policy.__.groupAgg && !policy.__.groupAggPath)}">
+ <label>Aggregation</label>
+ <div class="input-group">
+ <div class="input-group-btn">
+ <select class="form-control" ng-model="policy.__.groupAgg" ng-change="updateGroupAgg()">
+ <option ng-repeat="op in ['max','min','avg','count', 'sum']">{{op}}</option>
+ </select>
+ </div>
+ <select class="form-control" ng-model="policy.__.groupAggPath" ng-class="{'has-warning' : !policy.__.groupAggPath}" id="groupAggPath"
+ ng-show="policy.__.groupAgg" ng-disabled="policy.__.groupAgg === 'count'">
+ <option ng-repeat="meta in groupAggPathList()">{{meta.tags.attrName}}</option>
+ </select>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-md-4">
+ <div class="form-group" ng-class="{'text-yellow' : (!policy.__.groupCondOp || !policy.__.groupCondVal)}">
+ <label>Condition</label>
+ <div class="input-group">
+ <div class="input-group-btn">
+ <select class="form-control" ng-model="policy.__.groupCondOp" ng-class="{'has-warning' : !policy.__.groupCondOp}">
+ <option ng-repeat="op in ['>','<','>=','<=','==']">{{op}}</option>
+ </select>
+ </div>
+ <input type="text" class="form-control" ng-model="policy.__.groupCondVal" ng-class="{'has-warning' : !policy.__.groupCondVal}" />
+ </div>
+ </div>
+ </div>
+
+ <div class="col-md-4">
+ <div class="form-group">
+ <label>Alias (Optional)</label>
+ <input type="text" class="form-control" ng-model="policy.__.groupAggAlias" placeholder="Default: aggValue" />
+ </div>
+ </div>
+ </div>
+
+ <!-- Group -->
+ <div class="row">
+ <div class="col-md-4">
+ <div class="form-group">
+ <label>Group By</label>
+ <select class="form-control" ng-model="policy.__.group">
+ <option value="">None</option>
+ <option ng-repeat="meta in _stream.metas">{{meta.tags.attrName}}</option>
+ </select>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Step 2: Define Alert Policy -->
+ <div ng-show="step === 2 && policy.__.advanced">
+ <div class="form-group">
+ <label>Query Expression</label>
+ <textarea class="form-control" ng-model="policy.__._expression"
+ placeholder="Query expression. e.g. from hdfsAuditLogEventStream[(cmd=='open') and (host=='localhost' or host=='127.0.0.1')]#window.time(2 sec) select * insert into outputStream;" rows="5"></textarea>
+ </div>
+ </div>
+
+ <!-- Step 3: Email Notification -->
+ <div ng-show="step === 3">
+ <div class="row">
+ <div class="col-xs-4">
+ <div class="form-group" ng-class="{'has-warning' : !policy.tags.policyId}">
+ <label>Policy Name</label>
+ <input type="text" class="form-control" placeholder="" ng-model="policy.tags.policyId" ng-disabled="!create">
+ </div>
+ </div>
+ <div class="col-xs-3">
+ <div class="form-group">
+ <label>
+ Alert De-Dup Interval(min)
+ <span class="fa fa-question-circle" uib-tooltip="Same type alert will be De-dup in configured interval"> </span>
+ </label>
+ <input type="number" class="form-control" ng-model="policy.__.dedupe.alertDedupIntervalMin" placeholder="[Minute] Number only. Suggestion: 720">
+ </div>
+ </div>
+ <div class="col-xs-3">
+ <div class="form-group">
+ <label>
+ Email De-Dup Interval(min)
+ <span class="fa fa-question-circle" uib-tooltip="The minimun time interval of email"> </span>
+ </label>
+ <input type="number" class="form-control" ng-model="policy.__.dedupe.emailDedupIntervalMin" placeholder="[Minute] Number only. Suggestion: 1440">
+ </div>
+ </div>
+ <div class="col-xs-2">
+ <div class="form-group">
+ <label>
+ Enabled
+ </label>
+ <p>
+ <input type="checkbox" checked="checked" ng-model="policy.enabled">
+ </p>
+ </div>
+ </div>
+ </div>
+
+ <div>
+ <a data-toggle="collapse" href="[data-id='advancedDeDup']">Advanced De-Dup</a>
+ <div data-id='advancedDeDup' class="collapse">
+ <label>
+ De-Dup Key
+ <span class="fa fa-question-circle" uib-tooltip="Type of grouping alerts. If you don't know how to config, leave it default."> </span>
+ </label>
+ <div class="form-group">
+ <div class="checkbox" ng-repeat="meta in _stream.metas" ng-init="create ? policy.__._dedupTags[meta.tags.attrName] = !!meta.usedAsTag : void(0);">
+ <label>
+ <input type="checkbox" ng-model="policy.__._dedupTags[meta.tags.attrName]">
+ {{meta.tags.attrName}}
+ </label>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <hr/>
+
+ <div class="form-group">
+ <label>Sender</label>
+ <input type="text" class="form-control" value="noreply-hadoop-eagle@company1.com" placeholder="Enter Sender. e.g. sender@eaxmple.com" ng-model="policy.__.notification[0].sender">
+ </div>
+ <div class="form-group">
+ <label>Recipients</label>
+ <input type="text" class="form-control" placeholder="Enter Recipients. Split with ','. e.g. usera@example.com, userb@example.com" ng-model="policy.__.notification[0].recipients">
+ </div>
+ <div class="form-group">
+ <label>Subject</label>
+ <input type="text" class="form-control" placeholder="Enter Subject" ng-model="policy.__.notification[0].subject">
+ </div>
+ <div class="form-group">
+ <label>Description</label>
+ <textarea class="form-control" placeholder="Policy description" ng-model="policy.desc"></textarea>
+ </div>
+
+ <a data-toggle="collapse" href="[data-id='policyQuery']">
+ View Query
+ </a>
+ <div class="collapse in" data-id="policyQuery">
+ <pre>{{toQuery()}}</pre>
+ </div>
+ </div>
+
+ <!-- ----------------------- Step Body End ----------------------- -->
+ </div><!-- /.box-body -->
+
+ <div class="overlay" ng-hide="stepReady(step)">
+ <span class="fa fa-refresh fa-spin"> </span>
+ </div>
+
+ <div class="box-footer text-right">
+ <button class="btn btn-info" ng-show="step > 1" ng-click="changeStep(step, step - 1, false)" ng-disabled="lock">
+ Prev <span class="fa fa-arrow-circle-o-left"> </span>
+ </button>
+ <button class="btn btn-info" ng-show="step < steps.length" ng-click="changeStep(step, step + 1)" ng-disabled="checkNextable(step) || lock">
+ Next <span class="fa fa-arrow-circle-o-right"> </span>
+ </button>
+ <button class="btn btn-info" ng-show="step === steps.length" ng-click="finishPolicy()" ng-disabled="checkNextable(step) || lock">
+ Done <span class="fa fa-check-circle-o"> </span>
+ </button>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyList.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyList.html b/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyList.html
new file mode 100644
index 0000000..d7141a6
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/common/page/policyList.html
@@ -0,0 +1,84 @@
+<!--
+ 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 with-border">
+ <i class="fa fa-list-alt"> </i>
+ <h3 class="box-title">
+ {{application.displayName}}
+ </h3>
+ </div>
+ <div class="box-body">
+ <div class="row">
+ <div class="col-xs-3">
+ <div class="search-box">
+ <input type="search" class="form-control input-sm" placeholder="Search" ng-model="search" />
+ <span class="fa fa-search"> </span>
+ </div>
+ </div>
+ <div class="col-xs-6">
+ <div class="inline-group form-inline text-muted">
+ <dl><dt><i class="fa fa-square text-green"> </i></dt><dd>Enabled</dd></dl>
+ <dl><dt><i class="fa fa-square text-muted"> </i></dt><dd>Disabled</dd></dl>
+ </div>
+ </div>
+ <div class="col-xs-3 text-right">
+ <a class="btn btn-primary" href="#/common/policyCreate/{{!dataSource ? '' : '?dataSrc=' + dataSource.tags.dataSource}}" ng-show="Auth.isRole('ROLE_ADMIN')">
+ New Policy
+ <i class="fa fa-plus-circle"> </i>
+ </a>
+ </div>
+ </div>
+
+ <p ng-show="policyList._promise.$$state.status !== 1">
+ <span class="fa fa-refresh fa-spin"> </span>
+ Loading...
+ </p>
+
+ <div sorttable source="policyList" ng-show="policyList._promise.$$state.status === 1" search="false" searchfunc="searchFunc">
+ <table class="table table-bordered" ng-non-bindable>
+ <thead>
+ <tr>
+ <th width="30" sortpath="enabled"> </th>
+ <th width="200" sortpath="tags.policyId">Policy Name</th>
+ <th sortpath="desc">Description</th>
+ <th width="150" sortpath="owner">Owner</th>
+ <th width="170" sortpath="lastModifiedDate">Last Modified</th>
+ <th width="95" ng-show="_parent.Auth.isRole('ROLE_ADMIN')">Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><span class='fa fa-square' ng-class="item.enabled ? 'text-green' : 'text-muted'"> </span></td>
+ <td><a href="#/common/policyDetail/{{item.encodedRowkey}}">{{item.tags.policyId}}</a></td>
+ <td>{{item.desc}}</td>
+ <td>{{item.owner}}</td>
+ <td>{{common.format.date(item.lastModifiedDate) || "-"}}</td>
+ <td ng-show="_parent.Auth.isRole('ROLE_ADMIN')">
+ <a class="fa fa-pencil btn btn-default btn-xs" uib-tooltip="Edit" tooltip-animation="false" href="#/common/policyEdit/{{item.encodedRowkey}}"> </a>
+ <button class="fa fa-play sm btn btn-default btn-xs" uib-tooltip="Enable" tooltip-animation="false" ng-show="!item.enabled" ng-click="_parent.updatePolicyStatus(item, true)"> </button>
+ <button class="fa fa-pause sm btn btn-default btn-xs" uib-tooltip="Disable" tooltip-animation="false" ng-show="item.enabled" ng-click="_parent.updatePolicyStatus(item, false)"> </button>
+ <button class="rm fa fa-trash-o btn btn-danger btn-xs" uib-tooltip="Delete" tooltip-animation="false" ng-click="_parent.deletePolicy(item)"> </button>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <!--div class="box-footer clearfix">
+ </div-->
+</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/metadata/controller.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/metadata/controller.js b/eagle-webservice/src/main/webapp/app/public/feature/metadata/controller.js
new file mode 100644
index 0000000..2797223
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/metadata/controller.js
@@ -0,0 +1,66 @@
+/*
+ * 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 featureControllers = angular.module('featureControllers');
+ var feature = featureControllers.register("metadata");
+
+ // ==============================================================
+ // = Function =
+ // ==============================================================
+
+ // ==============================================================
+ // = Metadata =
+ // ==============================================================
+
+ // ======================= Policy Summary =======================
+ feature.navItem("streamList", "Metadata", "bullseye");
+ feature.controller('streamList', function(PageConfig, Site, $scope, $q, Application, Entities) {
+ PageConfig.hideSite = true;
+
+ $scope.streams = {};
+ $scope._streamEntity = null;
+ $scope._streamEntityLock = false;
+
+ // =========================================== List ===========================================
+ var _streamList = Entities.queryEntities("AlertStreamService", {dataSource: Application.current().tags.application});
+ var _streamSchemaList = Entities.queryEntities("AlertStreamSchemaService", {dataSource: Application.current().tags.application});
+ $scope.streamList = _streamList;
+ $scope.streamSchemaList = _streamSchemaList;
+
+ _streamList._promise.then(function() {
+ $.each(_streamList, function(i, stream) {
+ stream.metaList = [];
+ $scope.streams[stream.tags.dataSource + "_" + stream.tags.streamName] = stream;
+ });
+ });
+
+ $q.all([_streamList._promise, _streamSchemaList._promise]).then(function() {
+ $.each(_streamSchemaList, function(i, meta) {
+ var _stream = $scope.streams[meta.tags.dataSource + "_" + meta.tags.streamName];
+ if(_stream) {
+ _stream.metaList.push(meta);
+ } else {
+ console.warn("[Meta] Stream not match:", meta.tags.dataSource + "_" + meta.tags.streamName);
+ }
+ });
+ });
+ });
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/metadata/page/streamList.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/metadata/page/streamList.html b/eagle-webservice/src/main/webapp/app/public/feature/metadata/page/streamList.html
new file mode 100644
index 0000000..9218d8d
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/metadata/page/streamList.html
@@ -0,0 +1,84 @@
+<!--
+ 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.
+ -->
+<p ng-show="streamList._promise.$$state.status !== 1">
+ <span class="fa fa-refresh fa-spin"> </span>
+ Loading...
+</p>
+
+<div class="box box-primary" ng-repeat="stream in streams">
+ <div class="box-header with-border">
+ <h3 class="box-title">{{stream.tags.streamName}}</h3>
+ </div>
+ <div class="box-body">
+ <div class="inline-group">
+ <dl>
+ <dt>
+ Data Source
+ </dt>
+ <dd>
+ {{stream.tags.dataSource}}
+ </dd>
+ </dl>
+ <dl>
+ <dt>
+ Stream Name
+ </dt>
+ <dd>
+ {{stream.tags.streamName}}
+ </dd>
+ </dl>
+ </div>
+ <div>
+ <dl>
+ <dt>
+ Description
+ </dt>
+ <dd>
+ {{stream.desc}}
+ </dd>
+ </dl>
+ </div>
+
+ <p ng-show="streamSchemaList._promise.$$state.status !== 1">
+ <span class="fa fa-refresh fa-spin"> </span>
+ Loading...
+ </p>
+
+ <div class="list" ng-show="streamSchemaList._promise.$$state.status === 1">
+ <table class="table table-bordered">
+ <thead>
+ <tr>
+ <th width="10%">Attribute Name</th>
+ <th width="12%">Display Name</th>
+ <th width="8%">Type</th>
+ <th>Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="meta in stream.metaList">
+ <td>{{meta.tags.attrName}}</td>
+ <td>{{meta.attrDisplayName}}</td>
+ <td><span class="label label-warning">{{meta.attrType}}</span></td>
+ <td>{{meta.attrDescription}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div><!-- /.box-body -->
+ <!-- Loading (remove the following to stop the loading)-->
+</div>
\ No newline at end of file
[2/9] incubator-eagle git commit: EAGLE-139 EAGLE-163 Eagle UI
Modularization and fix bugs in policy extensions
Posted by hd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/srv/applicationSrv.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/srv/applicationSrv.js b/eagle-webservice/src/main/webapp/app/public/js/srv/applicationSrv.js
new file mode 100644
index 0000000..67d714f
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/js/srv/applicationSrv.js
@@ -0,0 +1,168 @@
+/*
+ * 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 serviceModule = angular.module('eagle.service');
+ serviceModule.service('Application', function($q, $location, $wrapState, Entities) {
+ var Application = {};
+ var _current;
+ var _featureCache = {};// After loading feature will be in cache. Which will not load twice.
+ var _deferred;
+
+ Application.list = [];
+ Application.list.set = {};
+ Application.featureList = [];
+ Application.featureList.set = {};
+
+ // Set current application
+ Application.current = function(app) {
+ if(arguments.length && _current !== app) {
+ var _prev = _current;
+ _current = app;
+
+ if(sessionStorage && _current) {
+ sessionStorage.setItem("application", _current.tags.application);
+ }
+
+ if(_prev) {
+ console.log("[Application] Switch. Redirect to landing page.");
+ $wrapState.go('landing', true);
+ }
+ }
+ return _current;
+ };
+ Application.find = function(appName) {
+ return common.array.find(appName, Application.list, "tags.application");
+ };
+
+ Application.reload = function() {
+ _deferred = $q.defer();
+
+ if(Application.list && Application.list._promise) Application.list._promise.abort();
+ if(Application.featureList && Application.featureList._promise) Application.featureList._promise.abort();
+
+ Application.list = Entities.queryEntities("ApplicationDescService", '');
+ Application.list.set = {};
+ Application.featureList = Entities.queryEntities("FeatureDescService", '');
+ Application.featureList.set = {};
+
+ Application.featureList._promise.then(function() {
+ var _promiseList;
+ // Load feature script
+ _promiseList = $.map(Application.featureList, function(feature) {
+ var _ajax_deferred, _script;
+ if(_featureCache[feature.tags.feature]) return;
+
+ _featureCache[feature.tags.feature] = true;
+ _ajax_deferred = $q.defer();
+ _script = document.createElement('script');
+ _script.type = 'text/javascript';
+ _script.src = "public/feature/" + feature.tags.feature + "/controller.js?_=" + Math.random();
+ document.head.appendChild(_script);
+ _script.onload = function() {
+ feature._loaded = true;
+ _ajax_deferred.resolve();
+ };
+ _script.onerror = function() {
+ feature._loaded = false;
+ _featureCache[feature.tags.feature] = false;
+ _ajax_deferred.reject();
+ };
+ return _ajax_deferred.promise;
+ });
+
+ // Merge application & feature
+ Application.list._promise.then(function() {
+ // Fill feature set
+ $.each(Application.featureList, function(i, feature) {
+ Application.featureList.set[feature.tags.feature] = feature;
+ });
+
+ // Fill application set
+ $.each(Application.list, function(i, application) {
+ Application.list.set[application.tags.application] = application;
+ application.features = application.features || [];
+ var _configObj = common.parseJSON(application.config, {});
+ var _appFeatureList = $.map(application.features, function(featureName) {
+ var _feature = Application.featureList.set[featureName];
+ if(!_feature) {
+ console.warn("[Application] Feature not mapping:", application.tags.application, "-", featureName);
+ } else {
+ return _feature;
+ }
+ });
+
+ // Find feature
+ _appFeatureList.find = function(featureName) {
+ return common.array.find(featureName, _appFeatureList, "tags.feature");
+ };
+
+ Object.defineProperties(application, {
+ featureList: {
+ get: function () {
+ return _appFeatureList;
+ }
+ },
+ // Get format group name. Will mark as 'Others' if no group defined
+ groupName: {
+ get: function () {
+ return this.group || "Others";
+ }
+ },
+ configObj: {
+ get: function() {
+ return _configObj;
+ }
+ },
+ displayName: {
+ get: function() {
+ return this.alias || this.tags.application;
+ }
+ }
+ });
+ });
+
+ // Set current application
+ if(!Application.current() && sessionStorage && Application.find(sessionStorage.getItem("application"))) {
+ Application.current(Application.find(sessionStorage.getItem("application")));
+ }
+ });
+
+ // Process all promise
+ $q.all(_promiseList.concat(Application.list._promise)).finally(function() {
+ _deferred.resolve(Application);
+ });
+ }, function() {
+ _deferred.reject(Application);
+ });
+
+ return _deferred.promise;
+ };
+
+ Application._promise = function() {
+ if(!_deferred) {
+ Application.reload();
+ }
+ return _deferred.promise;
+ };
+
+ return Application;
+ });
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/srv/authorizationSrv.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/srv/authorizationSrv.js b/eagle-webservice/src/main/webapp/app/public/js/srv/authorizationSrv.js
new file mode 100644
index 0000000..337b567
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/js/srv/authorizationSrv.js
@@ -0,0 +1,131 @@
+/*
+ * 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 serviceModule = angular.module('eagle.service');
+ serviceModule.service('Authorization', function ($rootScope, $http, $wrapState, $q) {
+ $http.defaults.withCredentials = true;
+
+ var _promise;
+ var _path = "";
+
+ var content = {
+ isLogin: true, // Status mark. Work for UI status check, changed when eagle api return 403 authorization failure.
+ needLogin: function () {
+ console.log("[Authorization] Need Login!");
+ if(content.isLogin) {
+ _path = _path || $wrapState.path();
+ content.isLogin = false;
+ console.log("[Authorization] Call need login. Redirect...");
+ $wrapState.go("login", 99);
+ } else {
+ console.log("[Authorization] Already login state...");
+ }
+ },
+ login: function (username, password) {
+ var _hash = btoa(username + ':' + password);
+ return $http({
+ url: app.getURL('userProfile'),
+ method: "GET",
+ headers: {
+ 'Authorization': "Basic " + _hash
+ }
+ }).then(function () {
+ content.isLogin = true;
+ return true;
+ }, function () {
+ return false;
+ });
+ },
+ logout: function () {
+ $http({
+ url: app.getURL('logout'),
+ method: "GET"
+ });
+ },
+ path: function (path) {
+ if (typeof path === "string") {
+ _path = path;
+ } else if (path === true) {
+ $wrapState.path(_path || "");
+ _path = "";
+ }
+ }
+ };
+
+ content.userProfile = {};
+ content.isRole = function (role) {
+ if (!content.userProfile.roles) return null;
+
+ return content.userProfile.roles[role] === true;
+ };
+
+ content.reload = function () {
+ _promise = $http({
+ url: app.getURL('userProfile'),
+ method: "GET"
+ }).then(function (data) {
+ content.userProfile = data.data;
+
+ // Role
+ content.userProfile.roles = {};
+ $.each(content.userProfile.authorities, function (i, role) {
+ content.userProfile.roles[role.authority] = true;
+ });
+
+ return content;
+ }, function(data) {
+ if(data.status === 403) {
+ content.needLogin();
+ }
+ });
+ return _promise;
+ };
+
+ content._promise = function () {
+ if (!_promise) {
+ content.reload();
+ }
+ return _promise;
+ };
+
+ content.rolePromise = function(role, rejectState) {
+ var _deferred = $q.defer();
+ var _oriPromise = content._promise();
+ _oriPromise.then(function() {
+ if(content.isRole(role)) {
+ _deferred.resolve(content);
+ } else if(content.isLogin) {
+ _deferred.resolve(content);
+ console.log("[Authorization] go landing...");
+ $wrapState.go(rejectState || "landing");
+ } else {
+ _deferred.reject(content);
+ }
+
+ return content;
+ });
+
+ return _deferred.promise;
+ };
+
+ return content;
+ });
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/srv/entitiesSrv.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/srv/entitiesSrv.js b/eagle-webservice/src/main/webapp/app/public/js/srv/entitiesSrv.js
new file mode 100644
index 0000000..b580f92
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/js/srv/entitiesSrv.js
@@ -0,0 +1,281 @@
+/*
+ * 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 serviceModule = angular.module('eagle.service');
+ serviceModule.service('Entities', function($http, $q, $rootScope, $location, Authorization) {
+ var pkg;
+
+ // Query
+ function _query(name, kvs) {
+ kvs = kvs || {};
+ var _list = [];
+ var _condition = kvs._condition || {};
+ var _addtionalCondition = _condition.additionalCondition || {};
+ var _startTime, _endTime;
+ var _startTimeStr, _endTimeStr;
+
+ // Initial
+ // > Condition
+ delete kvs._condition;
+ if(_condition) {
+ kvs.condition = _condition.condition;
+ }
+
+ // > Values
+ if(!kvs.values) {
+ kvs.values = "*";
+ } else if($.isArray(kvs.values)) {
+ kvs.values = $.map(kvs.values, function(field) {
+ return (field[0] === "@" ? '' : '@') + field;
+ }).join(",");
+ }
+
+ var _url = app.getURL(name, kvs);
+
+ // Fill special parameters
+ // > Query by time duration
+ if(_addtionalCondition._duration) {
+ _endTime = app.time.now();
+ _startTime = _endTime.clone().subtract(_addtionalCondition._duration, "ms");
+
+ // Debug usage. Extend more time duration for end time
+ if(_addtionalCondition.__ETD) {
+ _endTime.add(_addtionalCondition.__ETD, "ms");
+ }
+
+ _addtionalCondition._startTime = _startTime;
+ _addtionalCondition._endTime = _endTime;
+
+ _startTimeStr = _startTime.format("YYYY-MM-DD HH:mm:ss");
+ _endTimeStr = _endTime.clone().add(1, "s").format("YYYY-MM-DD HH:mm:ss");
+
+ _url += "&startTime=" + _startTimeStr + "&endTime=" + _endTimeStr;
+ } else if(_addtionalCondition._startTime && _addtionalCondition._endTime) {
+ _startTimeStr = _addtionalCondition._startTime.format("YYYY-MM-DD HH:mm:ss");
+ _endTimeStr = _addtionalCondition._endTime.clone().add(1, "s").format("YYYY-MM-DD HH:mm:ss");
+
+ _url += "&startTime=" + _startTimeStr + "&endTime=" + _endTimeStr;
+ }
+
+ // > Query contains metric name
+ if(_addtionalCondition._metricName) {
+ _url += "&metricName=" + _addtionalCondition._metricName;
+ }
+
+ // > Customize page size
+ if(_addtionalCondition._pageSize) {
+ _url = _url.replace(/pageSize=\d+/, "pageSize=" + _addtionalCondition._pageSize);
+ }
+
+ // AJAX
+ var canceler = $q.defer();
+ _list._promise = $http.get(_url, {timeout: canceler.promise}).then(function(status) {
+ _list.push.apply(_list, status.data.obj);
+ return _list;
+ });
+ _list._promise.abort = function() {
+ canceler.resolve();
+ };
+
+ _list._promise.then(function() {}, function(data) {
+ if(data.status === 403) {
+ Authorization.needLogin();
+ }
+ });
+
+ return _list;
+ }
+ function _post(url, entities) {
+ var _list = [];
+ _list._promise = $http({
+ method: 'POST',
+ url: url,
+ headers: {
+ "Content-Type": "application/json"
+ },
+ data: entities
+ }).success(function(data) {
+ _list.push.apply(_list, data.obj);
+ });
+ return _list;
+ }
+ function _delete(url) {
+ var _list = [];
+ _list._promise = $http({
+ method: 'DELETE',
+ url: url,
+ headers: {
+ "Content-Type": "application/json"
+ }
+ }).success(function(data) {
+ _list.push.apply(_list, data.obj);
+ });
+ return _list;
+ }
+ function ParseCondition(condition) {
+ var _this = this;
+ _this.condition = "";
+ _this.additionalCondition = {};
+
+ if(typeof condition === "string") {
+ _this.condition = condition;
+ } else {
+ _this.condition = $.map(condition, function(value, key) {
+ if(!key.match(/^_/)) {
+ if(value === undefined || value === null) {
+ return '@' + key + '=~".*"';
+ } else {
+ return '@' + key + '="' + value + '"';
+ }
+ } else {
+ _this.additionalCondition[key] = value;
+ return null;
+ }
+ }).join(" AND ");
+ }
+ return _this;
+ }
+
+ pkg = {
+ _query: _query,
+ _post: _post,
+
+ updateEntity: function(serviceName, entities, config) {
+ var _url;
+ config = config || {};
+ if(!$.isArray(entities)) entities = [entities];
+
+ // Post clone entities
+ var _entities = $.map(entities, function(entity) {
+ var _entity = {};
+
+ // Clone variables
+ $.each(entity, function(key) {
+ // Skip inner variables
+ if(!key.match(/^__/)) {
+ _entity[key] = entity[key];
+ }
+ });
+
+ // Add timestamp
+ if(config.timestamp !== false) {
+ if(config.createTime !== false && !_entity.createdTime) {
+ _entity.createdTime = new moment().valueOf();
+ }
+ if(config.lastModifiedDate !== false) {
+ _entity.lastModifiedDate = new moment().valueOf();
+ }
+ }
+
+ return _entity;
+ });
+
+ // Check for url hook
+ if(config.hook) {
+ _url = app.getUpdateURL(serviceName);
+ } else {
+ _url = app.getURL("updateEntity", {serviceName: serviceName});
+ }
+
+ return _post(_url, _entities);
+ },
+
+ deleteEntity: function(serviceName, entities) {
+ if (!$.isArray(entities)) entities = [entities];
+
+ var _entities = $.map(entities, function (entity) {
+ return typeof entity === "object" ? entity.encodedRowkey : entity;
+ });
+ return _post(app.getURL("deleteEntity", {serviceName: serviceName}), _entities);
+ },
+ deleteEntities: function(serviceName, condition) {
+ return _delete(app.getURL("deleteEntities", {serviceName: serviceName, condition: new ParseCondition(condition).condition}));
+ },
+ delete: function(serviceName, kvs) {
+ var _deleteURL = app.getDeleteURL(serviceName);
+ return _delete(common.template(_deleteURL, kvs));
+ },
+
+ queryEntity: function(serviceName, encodedRowkey) {
+ return _query("queryEntity", {serviceName: serviceName, encodedRowkey: encodedRowkey});
+ },
+ queryEntities: function(serviceName, condition, fields) {
+ return _query("queryEntities", {serviceName: serviceName, _condition: new ParseCondition(condition), values: fields});
+ },
+ queryGroup: function(serviceName, condition, groupBy, fields) {
+ return _query("queryGroup", {serviceName: serviceName, _condition: new ParseCondition(condition), groupBy: groupBy, values: fields});
+ },
+ querySeries: function(serviceName, condition, groupBy, fields, intervalmin) {
+ var _cond = new ParseCondition(condition);
+ var _list = _query("querySeries", {serviceName: serviceName, _condition: _cond, groupBy: groupBy, values: fields, intervalmin: intervalmin});
+ _list._promise.then(function() {
+ if(_list.length === 0) {
+ _list._empty = true;
+ _list._convert = true;
+
+ for(var i = 0; i <= (_cond.additionalCondition._endTime.valueOf() - _cond.additionalCondition._startTime.valueOf()) / (1000 * 60 * intervalmin); i += 1) {
+ _list.push(0);
+ }
+ } else if(_list.length === 1) {
+ _list._convert = true;
+ var _unit = _list.pop();
+ _list.push.apply(_list, _unit.value[0]);
+ }
+
+ if(_list._convert) {
+ var _current = _cond.additionalCondition._startTime.clone();
+ $.each(_list, function(i, value) {
+ _list[i] = {
+ x: _current.valueOf(),
+ y: value
+ };
+ _current.add(intervalmin, "m");
+ });
+ }
+ });
+ return _list;
+ },
+
+ query: function(path, params) {
+ var _list = [];
+ _list._promise = $http({
+ method: 'GET',
+ url: app.getURL("query") + path,
+ params: params
+ }).success(function(data) {
+ _list.push.apply(_list, data.obj);
+ });
+ return _list;
+ },
+
+ dialog: function(data, callback) {
+ if(data.success === false || (data.exception || "").trim()) {
+ return $.dialog({
+ title: "OPS",
+ content: $("<pre>").html(data.exception)
+ }, callback);
+ }
+ return false;
+ }
+ };
+ return pkg;
+ });
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/srv/main.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/srv/main.js b/eagle-webservice/src/main/webapp/app/public/js/srv/main.js
new file mode 100644
index 0000000..82765b8
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/js/srv/main.js
@@ -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.
+ */
+
+angular.module('eagle.service', []);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/srv/pageSrv.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/srv/pageSrv.js b/eagle-webservice/src/main/webapp/app/public/js/srv/pageSrv.js
new file mode 100644
index 0000000..e59d8a3
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/js/srv/pageSrv.js
@@ -0,0 +1,131 @@
+/*
+ * 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 serviceModule = angular.module('eagle.service');
+
+ // ===========================================================
+ // = Service =
+ // ===========================================================
+ // Feature page
+ serviceModule.service('PageConfig', function() {
+ var _tmplConfig = {
+ pageTitle: "",
+ pageSubTitle: "",
+
+ hideSite: false,
+ lockSite: false,
+ hideApplication: false,
+ hideSidebar: false,
+ hideUser: false,
+
+ // Current page navigation path
+ navPath: [],
+
+ navConfig: {}
+ };
+
+ var PageConfig = {};
+
+ // Reset
+ PageConfig.reset = function() {
+ $.extend(PageConfig, _tmplConfig);
+ PageConfig.navPath = [];
+ };
+ PageConfig.reset();
+
+ // Create navigation path
+ PageConfig.addNavPath = function(title, path) {
+ PageConfig.navPath.push({
+ title: title,
+ path: path
+ });
+ return PageConfig;
+ };
+
+ return PageConfig;
+ });
+
+ // Feature page
+ serviceModule.service('FeaturePageConfig', function(Application) {
+ var config = {
+ // Feature mapping pages
+ _navItemMapping: {}
+ };
+
+ // Register feature controller
+ config.addNavItem = function(feature, item) {
+ var _navItemList = config._navItemMapping[feature] = config._navItemMapping[feature] || [];
+ _navItemList.push(item);
+ };
+
+ // Page list
+ Object.defineProperty(config, "pageList", {
+ get: function() {
+ var _app = Application.current();
+ var _list = [];
+
+ if(_app && _app.features) {
+ $.each(_app.features, function(i, featureName) {
+ _list = _list.concat(config._navItemMapping[featureName] || []);
+ });
+ }
+
+ return _list;
+ }
+ });
+
+ return config;
+ });
+
+ // Configuration page
+ serviceModule.service('ConfigPageConfig', function(Application) {
+ var _originPageList = [
+ {icon: "server", title: "Sites", url: "#/config/site"},
+ {icon: "cubes", title: "Applications", url: "#/config/application"},
+ {icon: "leaf", title: "Features", url: "#/config/feature"}
+ ];
+
+ var config = {
+ _navItemMapping: {}
+ };
+
+ // Register feature controller
+ config.addNavItem = function(feature, item) {
+ var _navItemList = config._navItemMapping[feature] = config._navItemMapping[feature] || [];
+ _navItemList.push(item);
+ };
+
+ // Page list
+ Object.defineProperty(config, "pageList", {
+ get: function() {
+ var _list = _originPageList;
+
+ $.each(Application.featureList, function(i, feature) {
+ _list = _list.concat(config._navItemMapping[feature.tags.feature] || []);
+ });
+
+ return _list;
+ }
+ });
+
+ return config;
+ });
+})();
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/srv/siteSrv.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/srv/siteSrv.js b/eagle-webservice/src/main/webapp/app/public/js/srv/siteSrv.js
new file mode 100644
index 0000000..907915d
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/js/srv/siteSrv.js
@@ -0,0 +1,193 @@
+/*
+ * 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 serviceModule = angular.module('eagle.service');
+ serviceModule.service('Site', function($rootScope, $wrapState, $location, $q, Entities, Application) {
+ var _currentSite;
+ var Site = {};
+ var _promise;
+
+ Site.list = [];
+ Site.list.set = {};
+
+ Site.current = function(site) {
+ if(site) {
+ var _prev = _currentSite;
+ _currentSite = site;
+
+ // Keep current site and reload page
+ if(!_prev || _prev.tags.site !== _currentSite.tags.site) {
+ if(sessionStorage) {
+ sessionStorage.setItem("site", _currentSite.tags.site);
+ }
+
+ if(!$wrapState.current.abstract && $wrapState.current.name !== "login") {
+ console.log("[Site]", "Switch. Reload.");
+ $wrapState.reload();
+ }
+ }
+ }
+ return _currentSite;
+ };
+ Site.find = function(siteName) {
+ return common.array.find(siteName, Site.list, "tags.site");
+ };
+ Site.url = function(site, url) {
+ console.warn("[Site] Site.url is a deprecated function.");
+ if(arguments.length == 1) {
+ url = site;
+ } else {
+ Site.current(site);
+ }
+ $wrapState.url(url);
+
+ if ($rootScope.$$phase != '$apply' && $rootScope.$$phase != '$digest') {
+ $rootScope.$apply();
+ }
+ };
+
+ Site.currentSiteApplication = function() {
+ var _app = Application.current();
+ if(!_app) return null;
+
+ return _currentSite.applicationList.set[_app.tags.application];
+ };
+
+ Site.reload = function() {
+ var _applicationList;
+
+ if(Site.list && Site.list._promise) Site.list._promise.abort();
+
+ Site.list = Entities.queryEntities("SiteDescService", '');
+ Site.list.set = {};
+ _applicationList = Entities.queryEntities("SiteApplicationService", '');
+
+ _promise = $q.all([Site.list._promise, _applicationList._promise, Application._promise()]).then(function() {
+ // Fill site set
+ $.each(Site.list, function(i, site) {
+ var _list = [];
+ var _appGrp = {};
+ var _appGrpList = [];
+ _list.set = {};
+ Site.list.set[site.tags.site] = site;
+
+ // Find application
+ _list.find = function(applicationName) {
+ return common.array.find(applicationName, _list, "tags.application");
+ };
+
+ // Define properties
+ Object.defineProperties(site, {
+ applicationList: {
+ get: function() {
+ return _list;
+ }
+ },
+ applicationGroup: {
+ get: function() {
+ return _appGrp;
+ }
+ },
+ applicationGroupList: {
+ get: function() {
+ return _appGrpList;
+ }
+ }
+ });
+ });
+
+ // Fill site application mapping
+ $.each(_applicationList, function(i, siteApplication) {
+ var _site = Site.list.set[siteApplication.tags.site];
+ var _application = Application.find(siteApplication.tags.application);
+ var _appGroup, _configObj;
+
+ if(!_site) {
+ console.warn("[Site] Application not match site:", siteApplication.tags.site, "-", siteApplication.tags.application);
+ } else if(!_application) {
+ console.warn("[Site] Application not found:", siteApplication.tags.site, "-", siteApplication.tags.application);
+ } else {
+ _configObj = common.parseJSON(siteApplication.config, {});
+ Object.defineProperties(siteApplication, {
+ application: {
+ get: function () {
+ return _application;
+ }
+ },
+ configObj: {
+ get: function () {
+ return _configObj;
+ }
+ }
+ });
+
+ _site.applicationList.push(siteApplication);
+ _site.applicationList.set[siteApplication.tags.application] = siteApplication;
+
+ _appGroup = _site.applicationGroup[_application.groupName] = _site.applicationGroup[_application.groupName] || [];
+ _appGroup.push(_application);
+ }
+ });
+
+ // Fill site application group attributes
+ $.each(Site.list, function(i, site) {
+ $.each(site.applicationGroup, function(grpName, grpList) {
+ var grp = {
+ name: grpName,
+ list: grpList,
+ enabledList: $.grep(grpList, function(application) {return site.applicationList.set[application.tags.application].enabled;}),
+ disabledList: $.grep(grpList, function(application) {return !site.applicationList.set[application.tags.application].enabled;})
+ };
+
+ site.applicationGroupList.push(grp);
+ });
+
+ site.applicationGroupList.sort(function(a, b) {
+ if(a.name === b.name) return 0;
+ if(a.name === "Others") return 1;
+ if(b.name === "Others") return -1;
+ return a.name < b.name ? -1 : 1;
+ });
+ });
+
+ // Set current site
+ if(sessionStorage && Site.find(sessionStorage.getItem("site"))) {
+ Site.current(Site.find(sessionStorage.getItem("site")));
+ } else {
+ Site.current(Site.list[0]);
+ }
+
+ return Site;
+ });
+
+ return _promise;
+ };
+
+ Site._promise = function() {
+ if(!_promise) {
+ Site.reload();
+ }
+ return _promise;
+ };
+
+ return Site;
+ });
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/srv/uiSrv.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/srv/uiSrv.js b/eagle-webservice/src/main/webapp/app/public/js/srv/uiSrv.js
new file mode 100644
index 0000000..f82c838
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/js/srv/uiSrv.js
@@ -0,0 +1,218 @@
+/*
+ * 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 serviceModule = angular.module('eagle.service');
+
+ // ===========================================================
+ // = Service =
+ // ===========================================================
+ // Feature page
+ serviceModule.service('UI', function($rootScope, $q, $compile) {
+ var UI = {};
+
+ function _fieldDialog(create, name, entity, fieldList, checkFunc) {
+ var _deferred, $mdl, $scope;
+
+ _deferred = $q.defer();
+ $scope = $rootScope.$new(true);
+ $scope.name = name;
+ $scope.entity = entity;
+ $scope.fieldList = fieldList;
+ $scope.checkFunc = checkFunc;
+ $scope.lock = false;
+ $scope.create = create;
+
+ $scope.config = typeof name === "object" ? name : {};
+
+ // Modal
+ $mdl = $(TMPL_FIELDS).appendTo('body');
+ $compile($mdl)($scope);
+ $mdl.modal();
+
+ $mdl.on("hide.bs.modal", function() {
+ _deferred.reject();
+ });
+ $mdl.on("hidden.bs.modal", function() {
+ _deferred.resolve({
+ entity: entity
+ });
+ $mdl.remove();
+ });
+
+ // Function
+ $scope.emptyFieldList = function() {
+ return $.map(fieldList, function(field) {
+ if(!field.optional && !entity[field.field]) {
+ return field.field;
+ }
+ });
+ };
+
+ $scope.confirm = function() {
+ $scope.lock = true;
+ _deferred.notify({
+ entity: entity,
+ closeFunc: function() {
+ $mdl.modal('hide');
+ },
+ unlock: function() {
+ $scope.lock = false;
+ }
+ });
+ };
+
+ return _deferred.promise;
+ }
+
+ /***
+ * Create a creation confirm modal.
+ * @param name Name title
+ * @param entity bind entity
+ * @param fieldList Array. Format: {name, field, type(optional: blob), rows(optional: number), description(optional), optional(optional), readonly(optional)}
+ * @param checkFunc Check logic function. Return string will prevent access
+ */
+ UI.createConfirm = function(name, entity, fieldList, checkFunc) {
+ return _fieldDialog(true, name, entity, fieldList, checkFunc);
+ };
+
+ /***
+ * Create a update confirm modal.
+ * @param name Name title
+ * @param entity bind entity
+ * @param fieldList Array. Format: {name, field, type(optional: blob), rows(optional: number), description(optional), optional(optional), readonly(optional)}
+ * @param checkFunc Check logic function. Return string will prevent access
+ */
+ UI.updateConfirm = function(name, entity, fieldList, checkFunc) {
+ return _fieldDialog(false, name, entity, fieldList, checkFunc);
+ };
+
+ /***
+ * Create a customize field confirm modal.
+ * @param config Configuration object
+ * @param config.title Title of dialog box
+ * @param config.size "large". Set dialog size
+ * @param config.confirm Boolean. Display or not confirm button
+ * @param config.confirmDesc Confirm button display description
+ * @param entity bind entity
+ * @param fieldList Array. Format: {name, field, type(optional: blob), rows(optional: number), description(optional), optional(optional), readonly(optional)}
+ * @param checkFunc Check logic function. Return string will prevent access
+ */
+ UI.fieldConfirm = function(config, entity, fieldList, checkFunc) {
+ return _fieldDialog("field", config, entity, fieldList, checkFunc);
+ };
+
+ UI.deleteConfirm = function(name) {
+ var _deferred, $mdl, $scope;
+
+ _deferred = $q.defer();
+ $scope = $rootScope.$new(true);
+ $scope.name = name;
+ $scope.lock = false;
+
+ // Modal
+ $mdl = $(TMPL_DELETE).appendTo('body');
+ $compile($mdl)($scope);
+ $mdl.modal();
+
+ $mdl.on("hide.bs.modal", function() {
+ _deferred.reject();
+ });
+ $mdl.on("hidden.bs.modal", function() {
+ _deferred.resolve({
+ name: name
+ });
+ $mdl.remove();
+ });
+
+ // Function
+ $scope.delete = function() {
+ $scope.lock = true;
+ _deferred.notify({
+ name: name,
+ closeFunc: function() {
+ $mdl.modal('hide');
+ },
+ unlock: function() {
+ $scope.lock = false;
+ }
+ });
+ };
+
+ return _deferred.promise;
+ };
+
+ return UI;
+ });
+
+ // ===========================================================
+ // = Template =
+ // ===========================================================
+ var TMPL_FIELDS =
+ '<div class="modal fade" tabindex="-1" role="dialog">' +
+ '<div class="modal-dialog" ng-class="{\'modal-lg\': config.size === \'large\'}" role="document">' +
+ '<div class="modal-content">' +
+ '<div class="modal-header">' +
+ '<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
+ '<span aria-hidden="true">×</span>' +
+ '</button>' +
+ '<h4 class="modal-title">{{config.title || (create ? "New" : "Update") + " " + name}}</h4>' +
+ '</div>' +
+ '<div class="modal-body">' +
+ '<div class="form-group" ng-repeat="field in fieldList" ng-switch="field.type">' +
+ '<label for="featureName">' +
+ '<span ng-if="!field.optional">*</span> ' +
+ '{{field.name || field.field}}' +
+ '</label>' +
+ '<textarea class="form-control" placeholder="{{field.description || field.name || field.field + \'...\'}}" ng-model="entity[field.field]" rows="{{ field.rows || 10 }}" ng-readonly="field.readonly" ng-disabled="lock" ng-switch-when="blob"></textarea>' +
+ '<input type="text" class="form-control" placeholder="{{field.description || field.name || field.field + \'...\'}}" ng-model="entity[field.field]" ng-readonly="field.readonly" ng-disabled="lock" ng-switch-default>' +
+ '</div>' +
+ '</div>' +
+ '<div class="modal-footer">' +
+ '<p class="pull-left text-danger">{{checkFunc(entity)}}</p>' +
+ '<button type="button" class="btn btn-default" data-dismiss="modal" ng-disabled="lock">Close</button>' +
+ '<button type="button" class="btn btn-primary" ng-click="confirm()" ng-disabled="checkFunc(entity) || emptyFieldList().length || lock" ng-if="config.confirm !== false">' +
+ '{{config.confirmDesc || (create ? "Create" : "Update")}}' +
+ '</button>' +
+ '</div>' +
+ '</div>' +
+ '</div>' +
+ '</div>';
+
+ var TMPL_DELETE =
+ '<div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">' +
+ '<div class="modal-dialog">' +
+ '<div class="modal-content">' +
+ '<div class="modal-header">' +
+ '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>' +
+ '<h4 class="modal-title">Delete Confirm</h4></div>' +
+ '<div class="modal-body">' +
+ '<span class="text-red fa fa-exclamation-triangle pull-left" style="font-size: 50px;"></span>' +
+ '<p>You are <strong class="text-red">DELETING</strong> \'{{name}}\'!</p>' +
+ '<p>Proceed to delete?</p>' +
+ '</div>' +
+ '<div class="modal-footer">' +
+ '<button type="button" class="btn btn-danger" ng-click="delete()" ng-disabled="lock">Delete</button>' +
+ '<button type="button" class="btn btn-default" data-dismiss="modal" ng-disabled="lock">Cancel</button>' +
+ '</div>' +
+ '</div>' +
+ '</div>' +
+ '</div>';
+})();
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/srv/wrapStateSrv.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/srv/wrapStateSrv.js b/eagle-webservice/src/main/webapp/app/public/js/srv/wrapStateSrv.js
new file mode 100644
index 0000000..57872b2
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/js/srv/wrapStateSrv.js
@@ -0,0 +1,109 @@
+/*
+ * 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 serviceModule = angular.module('eagle.service');
+ serviceModule.service('$wrapState', function($state, $location, $stateParams) {
+ var $wrapState = {};
+ var _targetState = null;
+ var _targetPriority = 0;
+
+ // Go
+ $wrapState.go = function(state, param, priority) {
+ setTimeout(function() {
+ _targetState = null;
+ _targetPriority = 0;
+ });
+
+ if(typeof param !== "object") {
+ param = {};
+ priority = param;
+ }
+
+ priority = priority === true ? 1 : (priority || 0);
+ if(_targetPriority > priority) {
+ console.log("[Wrap State] Go - low priority:", state, "(Skip)");
+ return false;
+ }
+
+ if(_targetState !== state || priority) {
+ if($state.current && $state.current.name === state && angular.equals($state.params, param)) {
+ console.log($state);
+ console.log("[Wrap State] Go reload.");
+ $state.reload();
+ } else {
+ console.log("[Wrap State] Go:", state, param, priority);
+ $state.go(state, param);
+ }
+ _targetState = state;
+ _targetPriority = priority;
+ return true;
+ } else {
+ console.log("[Wrap State] Go:", state, "(Ignored)");
+ }
+ return false;
+ };
+
+ // Reload
+ $wrapState.reload = function() {
+ console.log("[Wrap State] Do reload.");
+ $state.reload();
+ };
+
+ // Path
+ $wrapState.path = function(path) {
+ if(path !== undefined) {
+ console.log("[Wrap State][Deprecated] Switch path:", path);
+ }
+ return $location.path(path);
+ };
+
+ // URL
+ $wrapState.url = function(url) {
+ if(url !== undefined) console.log("[Wrap State] Switch url:", url);
+ return $location.url(url);
+ };
+
+ Object.defineProperties($wrapState, {
+ // Origin $state
+ origin: {
+ get: function() {
+ return $state;
+ }
+ },
+
+ // Current
+ current: {
+ get: function() {
+ return $state.current;
+ }
+ },
+
+ // Parameter
+ param: {
+ get: function() {
+ return $.extend({}, $location.search(), $stateParams);
+ }
+ }
+ });
+
+ return $wrapState;
+ });
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/grunt.json
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/grunt.json b/eagle-webservice/src/main/webapp/grunt.json
index 0b8ad5a..c921862 100644
--- a/eagle-webservice/src/main/webapp/grunt.json
+++ b/eagle-webservice/src/main/webapp/grunt.json
@@ -15,8 +15,9 @@
"node_modules/angular/angular.min.js",
"node_modules/angular-resource/angular-resource.min.js",
"node_modules/angular-route/angular-route.min.js",
- "node_modules/angular-cookies/angular-cookies.min.js",
+ "node_modules/angular-animate/angular-animate.min.js",
"node_modules/angular-ui-bootstrap/ui-bootstrap-tpls.min.js",
+ "node_modules/angular-ui-router/release/angular-ui-router.min.js",
"node_modules/d3/d3.min.js",
"node_modules/zombiej-nvd3/build/nv.d3.min.js",
@@ -28,8 +29,8 @@
"src": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"node_modules/zombiej-bootstrap-components/bootstrap-components/css/bootstrap-components.min.css",
- "node_modules/font-awesome/css/font-awesome.min.css",
"node_modules/zombiej-nvd3/build/nv.d3.min.css",
+ "node_modules/font-awesome/css/font-awesome.min.css",
"node_modules/admin-lte/dist/css/AdminLTE.min.css",
"node_modules/admin-lte/dist/css/skins/skin-blue.min.css",
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/package.json
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/package.json b/eagle-webservice/src/main/webapp/package.json
index 713b93c..1e6f8d4 100644
--- a/eagle-webservice/src/main/webapp/package.json
+++ b/eagle-webservice/src/main/webapp/package.json
@@ -20,10 +20,11 @@
"angular-cookies" : "1.4.7",
"angular-animate" : "1.4.7",
"angular-ui-bootstrap" : "0.14.3",
- "d3" : "~3.5.10",
- "zombiej-nvd3" : "~1.8.1-1",
- "jquery-slimscroll": "1.3.6",
- "zombiej-bootstrap-components" : "~1.1.1"
+ "angular-ui-router" : "~0.2.17",
+ "d3" : "3.5.14",
+ "zombiej-nvd3" : "1.8.1-1",
+ "jquery-slimscroll" :"1.3.6",
+ "zombiej-bootstrap-components" : "1.1.1"
},
"devDependencies": {
[3/9] incubator-eagle git commit: EAGLE-139 EAGLE-163 Eagle UI
Modularization and fix bugs in policy extensions
Posted by hd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/ctrl/configurationController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/configurationController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/configurationController.js
new file mode 100644
index 0000000..c17cdf3
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/js/ctrl/configurationController.js
@@ -0,0 +1,332 @@
+/*
+ * 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');
+ // =============================================================
+ // = Configuration =
+ // =============================================================
+ // ========================== Feature ==========================
+ eagleControllers.controller('configFeatureCtrl', function ($scope, PageConfig, Application, Entities, UI) {
+ PageConfig.hideApplication = true;
+ PageConfig.hideSite = true;
+ $scope._pageLock = false;
+
+ // ================== Feature ==================
+ // Current feature
+ $scope.feature = Application.featureList[0];
+ $scope.setFeature = function (feature) {
+ $scope.feature = feature;
+ };
+
+ // Feature list
+ $scope.features = {};
+ $.each(Application.featureList, function(i, feature) {
+ $scope.features[feature.tags.feature] = $.extend({}, feature, true);
+ });
+
+ // Create feature
+ $scope.newFeature = function() {
+ UI.createConfirm("Feature", {}, [
+ {name: "Feature Name", field: "name"}
+ ], function(entity) {
+ if(entity.name && $.map($scope.features, function(feature, name) {
+ return name.toUpperCase() === entity.name.toUpperCase() ? true : null;
+ }).length) {
+ return "Feature name conflict!";
+ }
+ }).then(null, null, function(holder) {
+ Entities.updateEntity(
+ "FeatureDescService",
+ {tags: {feature: holder.entity.name}},
+ {timestamp: false}
+ )._promise.then(function() {
+ holder.closeFunc();
+ location.reload();
+ });
+ });
+ };
+
+ // Delete feature
+ $scope.deleteFeature = function(feature) {
+ UI.deleteConfirm(feature.tags.feature).then(null, null, function(holder) {
+ Entities.delete("FeatureDescService", {feature: feature.tags.feature})._promise.then(function() {
+ holder.closeFunc();
+ location.reload();
+ });
+ });
+ };
+
+ // Save feature
+ $scope.saveAll = function() {
+ $scope._pageLock = true;
+ var _list = $.map($scope.features, function(feature) {
+ return feature;
+ });
+ Entities.updateEntity("FeatureDescService", _list, {timestamp: false})._promise.success(function() {
+ location.reload();
+ }).finally(function() {
+ $scope._pageLock = false;
+ });
+ };
+ });
+
+ // ======================== Application ========================
+ eagleControllers.controller('configApplicationCtrl', function ($scope, $timeout, PageConfig, Application, Entities, UI) {
+ PageConfig.hideApplication = true;
+ PageConfig.hideSite = true;
+ $scope._pageLock = false;
+
+ // ================ Application ================
+ // Current application
+ $scope.application = Application.list[0];
+ $scope.setApplication = function (application) {
+ $scope.application = application;
+ };
+
+ // Application list
+ $scope.applications = {};
+ $.each(Application.list, function(i, application) {
+ var _application = $scope.applications[application.tags.application] = $.extend({}, application, {features: application.features.slice()}, true);
+ _application.optionalFeatures = $.map(Application.featureList, function(feature) {
+ if(!common.array.find(feature.tags.feature, _application.features)) {
+ return feature.tags.feature;
+ }
+ });
+ });
+
+ // Create application
+ $scope.newApplication = function() {
+ UI.createConfirm("Application", {}, [
+ {name: "Application Name", field: "name"}
+ ], function(entity) {
+ if(entity.name && $.map($scope.applications, function(application, name) {
+ return name.toUpperCase() === entity.name.toUpperCase() ? true : null;
+ }).length) {
+ return "Application name conflict!";
+ }
+ }).then(null, null, function(holder) {
+ Entities.updateEntity(
+ "ApplicationDescService",
+ {tags: {application: holder.entity.name}},
+ {timestamp: false}
+ )._promise.then(function() {
+ holder.closeFunc();
+ location.reload();
+ });
+ });
+ };
+
+ // Delete application
+ $scope.deleteApplication = function(application) {
+ UI.deleteConfirm(application.tags.application).then(null, null, function(holder) {
+ Entities.delete("ApplicationDescService", {application: application.tags.application})._promise.then(function() {
+ holder.closeFunc();
+ location.reload();
+ });
+ });
+ };
+
+ // ================= Function ==================
+ // Configuration check
+ $scope.configCheck = function(config) {
+ if(config && !common.parseJSON(config, false)) {
+ return "Invalid JSON format";
+ }
+ };
+
+ // Feature
+ $scope._feature = "";
+ function highlightFeature(feature) {
+ $scope._feature = feature;
+
+ $timeout(function() {
+ $scope._feature = "";
+ }, 100);
+ }
+
+ $scope.addFeature = function(feature, application) {
+ application.features.push(feature);
+ common.array.remove(feature, application.optionalFeatures);
+ highlightFeature(feature);
+ };
+
+ $scope.removeFeature = function(feature, application) {
+ application.optionalFeatures.push(feature);
+ common.array.remove(feature, application.features);
+ };
+
+ $scope.moveFeature = function(feature, list, offset) {
+ common.array.moveOffset(feature, list, offset);
+ highlightFeature(feature);
+ };
+
+ // Save feature
+ $scope.saveAll = function() {
+ $scope._pageLock = true;
+
+ var _list = $.map($scope.applications, function(application) {
+ return application;
+ });
+ Entities.updateEntity("ApplicationDescService", _list, {timestamp: false})._promise.success(function() {
+ location.reload();
+ }).finally(function() {
+ $scope._pageLock = false;
+ });
+ };
+ });
+
+ // ============================ Site ===========================
+ eagleControllers.controller('configSiteCtrl', function ($scope, $timeout, PageConfig, Site, Application, Entities, UI) {
+ PageConfig.hideApplication = true;
+ PageConfig.hideSite = true;
+ $scope._pageLock = false;
+
+ // =================== Site ====================
+ // Current site
+ $scope.site = Site.list[0];
+ $scope.setSite = function (site) {
+ $scope.site = site;
+ };
+
+
+ // Site list
+ $scope.sites = {};
+ $.each(Site.list, function(i, site) {
+ var _site = $scope.sites[site.tags.site] = $.extend({}, site, true);
+ var _applications = [];
+ var _optionalApplications = [];
+
+ Object.defineProperties(_site, {
+ applications: {
+ get: function() {return _applications;}
+ },
+ optionalApplications: {
+ get: function() {return _optionalApplications;}
+ }
+ });
+
+ $.each(Application.list, function(i, application) {
+ var _application = site.applicationList.set[application.tags.application];
+ if(_application && _application.enabled) {
+ _site.applications.push(_application);
+ } else {
+ if(_application) {
+ _site.optionalApplications.push(_application);
+ } else {
+ _site.optionalApplications.push({
+ prefix: "eagleSiteApplication",
+ config: "",
+ enabled: false,
+ tags: {
+ application: application.tags.application,
+ site: site.tags.site
+ }
+ });
+ }
+ }
+ });
+ });
+
+ // Create site
+ $scope.newSite = function() {
+ UI.createConfirm("Site", {}, [
+ {name: "Site Name", field: "name"}
+ ], function(entity) {
+ if(entity.name && $.map($scope.sites, function(site, name) {
+ return name.toUpperCase() === entity.name.toUpperCase() ? true : null;
+ }).length) {
+ return "Site name conflict!";
+ }
+ }).then(null, null, function(holder) {
+ Entities.updateEntity(
+ "SiteDescService",
+ {enabled: true, tags: {site: holder.entity.name}},
+ {timestamp: false}
+ )._promise.then(function() {
+ holder.closeFunc();
+ location.reload();
+ });
+ });
+ };
+
+ // Delete site
+ $scope.deleteSite = function(site) {
+ UI.deleteConfirm(site.tags.site).then(null, null, function(holder) {
+ Entities.delete("SiteDescService", {site: site.tags.site})._promise.then(function() {
+ holder.closeFunc();
+ location.reload();
+ });
+ });
+ };
+
+ // ================= Function ==================
+ $scope._application = "";
+ function highlightApplication(application) {
+ $scope._application = application;
+
+ $timeout(function() {
+ $scope._application = "";
+ }, 100);
+ }
+
+ $scope.addApplication = function(application, site) {
+ site.applications.push(application);
+ common.array.remove(application, site.optionalApplications);
+ application.enabled = true;
+ highlightApplication(application);
+ };
+
+ $scope.removeApplication = function(application, site) {
+ site.optionalApplications.push(application);
+ common.array.remove(application, site.applications);
+ application.enabled = false;
+ };
+
+ $scope.setApplication = function(application) {
+ UI.updateConfirm("Application", {config: application.config}, [
+ {name: "Configuration", field: "config", type: "blob"}
+ ], function(entity) {
+ if(entity.config !== "" && !common.parseJSON(entity.config, false)) {
+ return "Invalid JSON format";
+ }
+ }).then(null, null, function(holder) {
+ application.config = holder.entity.config;
+ holder.closeFunc();
+ });
+ };
+
+ // Save feature
+ $scope.saveAll = function() {
+ $scope._pageLock = true;
+
+ var _list = $.map($scope.sites, function(site) {
+ var _clone = $.extend({applications: site.applications.concat(site.optionalApplications)}, site);
+ return _clone;
+ });
+
+ Entities.updateEntity("SiteDescService", _list, {timestamp: false, hook: true})._promise.success(function() {
+ location.reload();
+ }).finally(function() {
+ $scope._pageLock = false;
+ });
+ };
+ });
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/ctrl/damController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/damController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/damController.js
deleted file mode 100644
index f630fb2..0000000
--- a/eagle-webservice/src/main/webapp/app/public/js/ctrl/damController.js
+++ /dev/null
@@ -1,111 +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.
- */
-
-/* Controllers */
-var damControllers = angular.module('damControllers', ['ui.bootstrap', 'eagle.components']);
-
-damControllers.service('damContent', function(Entities) {
- 'use strict';
-
- var content = {
- config: {
- pageList: [
- {icon: "list", title: "Policies", url: "#/dam/summary"},
- {icon: "exclamation-triangle", title: "Alerts", url: "#/dam/alertList"},
- {icon: "user-secret", title: "Classification", url: "#/dam/sensitivitySummary"},
- {icon: "graduation-cap", title: "User Profiles", url: "#/dam/userProfileList"},
- {icon: "bullseye", title: "Metadata", url: "#/dam/streamList"},
- {icon: "server", title: "Setup", url: "#/dam/siteList", roles: ["ROLE_ADMIN"]},
- ],
- navMapping: {
- "Policy View": "#/dam/summary",
- "Polict List": "#/dam/policyList",
- "Alert List": "#/dam/alertList",
- "User Profile": "#/dam/userProfileList",
- },
- },
- updatePolicyStatus: function(policy, status) {
- $.dialog({
- title: "Confirm",
- content: "Do you want to " + (status ? "enable" : "disable") + " policy[" + policy.tags.policyId + "]?",
- confirm: true,
- }, function(ret) {
- if(ret) {
- policy.enabled = status;
- Entities.updateEntity("AlertDefinitionService", policy);
- }
- });
- },
- deletePolicy: function(policy, callback) {
- $.dialog({
- title: "Confirm",
- content: "Do you want to delete policy[" + policy.tags.policyId + "]?",
- confirm: true,
- }, function(ret) {
- if(ret) {
- policy.enabled = status;
- Entities.deleteEntity("AlertDefinitionService", policy)._promise.finally(function() {
- if(callback) {
- callback(policy);
- }
- });
- }
- });
- },
- };
- return content;
-});
-
-// =============================================================
-// = Summary =
-// =============================================================
-damControllers.controller('summaryCtrl', function(globalContent, Site, damContent, $scope, $q, Entities, $route) {
- 'use strict';
-
- globalContent.setConfig(damContent.config);
- globalContent.pageSubTitle = Site.current().name;
-
- $scope.dataSources = {};
- $scope.dataReady = false;
-
- var _policyList = Entities.queryGroup("AlertDefinitionService", {dataSource:null, site: Site.current().name}, "@dataSource", "count");
-
- _policyList._promise.then(function() {
- // List programs
- $.each(_policyList, function(i, unit) {
- var _dataSrc = Site.current().dataSrcList.find(unit.key[0]);
- if(_dataSrc) {
- _dataSrc.count = unit.value[0];
- } else {
- var _siteHref = $("<a href='#/dam/siteList'>").text("Setup");
- var _dlg = $.dialog({
- title: "Data Source Not Found",
- content: $("<div>")
- .append("Data Source [" + unit.key[0] + "] not found. Please check your configuration in ")
- .append(_siteHref)
- .append(" page.")
- });
- _siteHref.click(function() {
- _dlg.modal('hide');
- });
- }
- });
-
- $scope.dataReady = true;
- });
-});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/ctrl/main.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/main.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/main.js
new file mode 100644
index 0000000..5064a1d
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/js/ctrl/main.js
@@ -0,0 +1,42 @@
+/*
+ * 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', ['ui.bootstrap', 'eagle.components', 'eagle.service']);
+
+ // ===========================================================
+ // = Controller =
+ // ===========================================================
+ eagleControllers.controller('landingCtrl', function($scope, $wrapState, Site, Application, PageConfig, FeaturePageConfig, Feature) {
+ var _app = Application.current();
+
+ PageConfig.pageTitle = _app ? _app.displayName : 'OPS';
+ PageConfig.pageSubTitle = Site.current().tags.site;
+
+ $scope.Application = Application;
+
+ var _navItemList = FeaturePageConfig.pageList;
+ if(_navItemList.length) {
+ console.log("[Landing] Auto redirect.", FeaturePageConfig);
+ var _match = _navItemList[0].url.match(/#\/([^\/]+)\/([^\/]+)/);
+ Feature.go(_match[1], _match[2]);
+ }
+ });
+})();
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/ctrl/policyController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/policyController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/policyController.js
deleted file mode 100644
index 1ca741c..0000000
--- a/eagle-webservice/src/main/webapp/app/public/js/ctrl/policyController.js
+++ /dev/null
@@ -1,898 +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.
- */
-
-// =============================================================
-// = Policy List =
-// =============================================================
-damControllers.controller('policyListCtrl', function(globalContent, Site, damContent, $scope, $routeParams, Entities) {
- 'use strict';
-
- globalContent.setConfig(damContent.config);
- globalContent.pageTitle = "Policy List";
- globalContent.pageSubTitle = Site.current().name;
- globalContent.navPath = ["Policy View", "Polict List"];
-
- // Initial load
- $scope.policyList = [];
- if($routeParams.dataSource) {
- $scope.dataSource = Site.current().dataSrcList.find($routeParams.dataSource);
- }
-
- // List policies
- var _policyList = Entities.queryEntities("AlertDefinitionService", {site: Site.current().name, dataSource: $routeParams.dataSource});
- _policyList._promise.then(function() {
- $.each(_policyList, function(i, policy) {
- if($.inArray(policy.tags.dataSource, app.config.dataSource.uiInvisibleList) === -1) {
- policy.__mailStr = common.getValueByPath(common.parseJSON(policy.notificationDef, {}), "0.recipients", "");
- policy.__mailList = policy.__mailStr.trim() === "" ? [] : policy.__mailStr.split(/[\,\;]/);
- policy.__expression = common.parseJSON(policy.policyDef, {}).expression;
-
- $scope.policyList.push(policy);
- }
- });
- });
- $scope.policyList._promise = _policyList._promise;
-
- // Function
- $scope.searchFunc = function(item) {
- var key = $scope.search;
- if(!key) return true;
-
- var _key = key.toLowerCase();
- function _hasKey(item, path) {
- var _value = common.getValueByPath(item, path, "").toLowerCase();
- return _value.indexOf(_key) !== -1;
- }
- return _hasKey(item, "tags.policyId") || _hasKey(item, "__expression") || _hasKey(item, "desc") || _hasKey(item, "owner") || _hasKey(item, "__mailStr");
- };
-
- $scope.updatePolicyStatus = damContent.updatePolicyStatus;
- $scope.deletePolicy = function(policy) {
- damContent.deletePolicy(policy, function(policy) {
- var _index = $scope.policyList.indexOf(policy);
- $scope.policyList.splice(_index, 1);
- });
- };
-});
-
-// =============================================================
-// = Policy Detail =
-// =============================================================
-damControllers.controller('policyDetailCtrl', function(globalContent, Site, damContent, $scope, $routeParams, Entities, nvd3) {
- 'use strict';
-
- var MAX_PAGESIZE = 10000;
-
- globalContent.setConfig(damContent.config);
- globalContent.pageTitle = "Policy Detail";
- globalContent.navPath = ["Policy View", "Polict List", "Polict Detail"];
- globalContent.lockSite = true;
-
- $scope.common = common;
- $scope.chartConfig = {
- chart: "line",
- xType: "time"
- };
-
- // Query policy
- if($routeParams.encodedRowkey) {
- $scope.policyList = Entities.queryEntity("AlertDefinitionService", $routeParams.encodedRowkey);
- } else {
- $scope.policyList = Entities.queryEntities("AlertDefinitionService", {
- policyId: $routeParams.policy,
- site: $routeParams.site,
- alertExecutorId: $routeParams.executor
- });
- }
- $scope.policyList._promise.then(function() {
- var policy = null;
-
- if($scope.policyList.length === 0) {
- $.dialog({
- title: "OPS!",
- content: "Policy not found!",
- }, function() {
- location.href = "#/dam/policyList";
- });
- return;
- } else {
- policy = $scope.policyList[0];
-
- policy.__mailStr = common.getValueByPath(common.parseJSON(policy.notificationDef, {}), "0.recipients", "");
- policy.__mailList = policy.__mailStr.trim() === "" ? [] : policy.__mailStr.split(/[\,\;]/);
- policy.__expression = common.parseJSON(policy.policyDef, {}).expression;
-
- $scope.policy = policy;
- Site.current(Site.find($scope.policy.tags.site));
- console.log($scope.policy);
- }
-
- // Visualization
- var _endTime = app.time.now().hour(23).minute(59).second(59).millisecond(0);
- var _startTime = _endTime.clone().subtract(1, "month").hour(0).minute(0).second(0).millisecond(0);
- var _cond = {
- dataSource: policy.tags.dataSource,
- policyId: policy.tags.policyId,
- _startTime: _startTime,
- _endTime: _endTime
- };
-
- // > eagle.policy.eval.count
- $scope.policyEvalSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.policy.eval.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
-
- // > eagle.policy.eval.fail.count
- $scope.policyEvalFailSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.policy.eval.fail.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
-
- // > eagle.alert.count
- $scope.alertSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.alert.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
-
- // > eagle.alert.fail.count
- $scope.alertFailSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.alert.fail.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
-
- // Alert list
- $scope.alertList = Entities.queryEntities("AlertService", {
- site: Site.current().name,
- dataSource: policy.tags.dataSource,
- policyId: policy.tags.policyId,
- _pageSize: MAX_PAGESIZE,
- _duration: 1000 * 60 * 60 * 24 * 30,
- __ETD: 1000 * 60 * 60 * 24
- });
- });
-
- // Function
- $scope.updatePolicyStatus = damContent.updatePolicyStatus;
- $scope.deletePolicy = function(policy) {
- damContent.deletePolicy(policy, function(policy) {
- location.href = "#/dam/policyList";
- });
- };
-});
-
-// =============================================================
-// = Policy Edit =
-// =============================================================
-(function() {
- 'use strict';
-
- function policyCtrl(create, globalContent, Site, damContent, $scope, $routeParams, $location, $q, Entities) {
- globalContent.setConfig(damContent.config);
- globalContent.pageTitle = "Policy Edit";
- globalContent.pageSubTitle = Site.current().name;
- globalContent.navPath = ["Policy View", "Polict List", "Polict Edit"];
-
- var _winTimeDesc = "Number unit[millisecond, sec, min, hour, day, month, year]. e.g. 23 sec";
- var _winTimeRegex = /^\d+\s+(millisecond|milliseconds|second|seconds|sec|minute|minutes|min|hour|hours|day|days|week|weeks|month|months|year|years)$/;
- var _winTimeDefaultValue = '10 min';
- $scope.config = {
- window: [
- // Display name, window type, required columns[Title, Description || "LONG_FIELD", Regex check, default value]
- {
- title: "Message Time Slide",
- description: "Using timestamp filed from input is used as event's timestamp",
- type: "externalTime",
- fields:[
- {title: "Field", defaultValue: "timestamp", hide: true},
- {title: "Time", description: _winTimeDesc, regex: _winTimeRegex, defaultValue: _winTimeDefaultValue},
- ]
- },
- {
- title: "System Time Slide",
- description: "Using System time is used as timestamp for event's timestamp",
- type: "time",
- fields:[
- {title: "Time", description: _winTimeDesc, regex: _winTimeRegex, defaultValue: _winTimeDefaultValue},
- ]
- },
- {
- title: "System Time Batch",
- description: "Same as System Time Window except the policy is evaluated at fixed duration",
- type: "timeBatch",
- fields:[
- {title: "Time", description: _winTimeDesc, regex: _winTimeRegex, defaultValue: _winTimeDefaultValue},
- ]
- },
- {
- title: "Length Slide",
- description: "The slide window has a fixed length",
- type: "length",
- fields:[
- {title: "Number", description: "Number only. e.g. 1023", regex: /^\d+$/},
- ]
- },
- {
- title: "Length Batch",
- description: "Same as Length window except the policy is evaluated in batch mode when fixed event count reached",
- type: "lengthBatch",
- fields:[
- {title: "Number", description: "Number only. e.g. 1023", regex: /^\d+$/},
- ]
- },
- ],
- };
-
- $scope.create = create;
- $scope.encodedRowkey = $routeParams.encodedRowkey;
-
- $scope.step = 0;
- $scope.dataSources = {};
- $scope.policy = {};
-
- // ==========================================
- // = Data Preparation =
- // ==========================================
- // Steam list
- var _streamList = Entities.queryEntities("AlertStreamService", '@streamName=~".*"');
- var _executorList = Entities.queryEntities("AlertExecutorService", '@streamName=~".*"');
- $scope.streamList = _streamList;
- $scope.executorList = _executorList;
- $scope.streamReady = false;
-
- $q.all([_streamList._promise, _executorList._promise]).then(function() {
- // Map executor with stream
- $.each(_executorList, function(i, executor) {
- $.each(_streamList, function(j, stream) {
- if(stream.tags.dataSource === executor.tags.dataSource && stream.tags.streamName === executor.tags.streamName) {
- stream.alertExecutor = executor;
- return false;
- }
- });
- });
-
- // Fill stream list
- $.each(_streamList, function(i, unit) {
- var _srcStreamList = $scope.dataSources[unit.tags.dataSource] = $scope.dataSources[unit.tags.dataSource] || [];
- _srcStreamList.push(unit);
- });
-
- $scope.streamReady = true;
-
- // ==========================================
- // = Function =
- // ==========================================
- function _findStream(dataSource, streamName) {
- var _streamList = $scope.dataSources[dataSource];
- if(!_streamList) return null;
-
- for(var i = 0 ; i < _streamList.length ; i += 1) {
- if(_streamList[i].tags.streamName === streamName) {
- return _streamList[i];
- }
- }
- return null;
- }
-
- // ==========================================
- // = Step control =
- // ==========================================
- $scope.steps = [
- // >> Select data source
- {
- title: "Select Data Source",
- ready: function() {
- return $scope.streamReady;
- },
- init: function() {
- if(create) $scope.policy.tags.dataSource = $scope.policy.tags.dataSource || Site.current().dataSrcList[0].tags.dataSource;
- },
- nextable: function() {
- return common.getValueByPath($scope.policy, "tags.dataSource");
- },
- },
-
- // >> Select stream
- {
- title: "Select Stream",
- ready: function() {
- return $scope.streamReady;
- },
- init: function() {
- $scope.policy.__.streamName = $scope.policy.__.streamName ||
- common.array.find($scope.policy.tags.dataSource, _streamList, "tags.dataSource").tags.streamName;
- },
- nextable: function() {
- var _streamName = common.getValueByPath($scope.policy, "__.streamName");
- if(!_streamName) return false;
-
- // Detect stream in current data source list
- return !!common.array.find(_streamName, $scope.dataSources[$scope.policy.tags.dataSource], "tags.streamName");
- },
- },
-
- // >> Define Alert Policy
- {
- title: "Define Alert Policy",
- init: function() {
- // Normal mode will fetch meta list
- if(!$scope.policy.__.advanced) {
- var _stream = _findStream($scope.policy.tags.dataSource, $scope.policy.__.streamName);
- $scope._stream = _stream;
-
- if(!_stream.metas) {
- _stream.metas = Entities.queryEntities("AlertStreamSchemaService", {dataSource: $scope.policy.tags.dataSource, streamName: $scope.policy.__.streamName});
- _stream.metas._promise.then(function() {
- _stream.metas.sort(function(a, b) {
- if(a.tags.attrName < b.tags.attrName) {
- return -1;
- } else if(a.tags.attrName > b.tags.attrName) {
- return 1;
- }
- return 0;
- });
- });
- }
- }
- },
- ready: function() {
- if(!$scope.policy.__.advanced) {
- return $scope._stream.metas._promise.$$state.status === 1;
- }
- return true;
- },
- nextable: function() {
- if($scope.policy.__.advanced) {
- // Check stream source
- $scope._stream = null;
- $.each($scope.dataSources[$scope.policy.tags.dataSource], function(i, stream) {
- if(($scope.policy.__._expression || "").indexOf(stream.tags.streamName) !== -1) {
- $scope._stream = stream;
- return false;
- }
- });
- return $scope._stream;
- } else {
- // Window
- if($scope.policy.__.windowConfig) {
- var _winMatch = true;
- var _winConds = $scope.getWindow().fields;
- $.each(_winConds, function(i, cond) {
- if(!(cond.val || "").match(cond.regex)) {
- _winMatch = false;
- return false;
- }
- });
- if(!_winMatch) return false;
-
- // Aggregation
- if($scope.policy.__.groupAgg) {
- if(!$scope.policy.__.groupAggPath ||
- !$scope.policy.__.groupCondOp ||
- !$scope.policy.__.groupCondVal) {
- return false;
- }
- }
- }
- }
- return true;
- },
- },
-
- // >> Configuration & Notification
- {
- title: "Configuration & Notification",
- nextable: function() {
- return !!$scope.policy.tags.policyId;
- },
- }
- ];
-
- // ==========================================
- // = Policy Logic =
- // ==========================================
- _streamList._promise.then(function() {
- // Initial policy entity
- if(create) {
- $scope.policy = {
- __: {
- toJSON: jQuery.noop,
- conditions: {},
- notification: [],
- dedupe: {
- alertDedupIntervalMin: 10,
- emailDedupIntervalMin: 10,
- },
- policy: {},
- window: "externalTime",
- group: "",
- groupAgg: "count",
- groupAggPath: "timestamp",
- groupCondOp: ">=",
- groupCondVal: "2",
- },
- desc: "",
- enabled: true,
- prefix: "alertdef",
- remediationDef: "",
- tags: {
- policyType: "siddhiCEPEngine",
- }
- };
-
- // If configured data source
- if($routeParams.dataSrc) {
- $scope.policy.tags.dataSource = $routeParams.dataSrc;
- if(common.array.find($routeParams.dataSrc, Site.current().dataSrcList, "tags.dataSource")) {
- setTimeout(function() {
- $scope.changeStep(0, 2, false);
- $scope.$apply();
- }, 1);
- }
- }
- } else {
- var _policy = Entities.queryEntity("AlertDefinitionService", $scope.encodedRowkey);
- _policy._promise.then(function() {
- if(_policy.length) {
- $scope.policy = _policy[0];
- $scope.policy.__ = {
- toJSON: jQuery.noop,
- };
-
- Site.current(Site.find($scope.policy.tags.site));
- } else {
- $.dialog({
- title: "OPS",
- content: "Policy not found!",
- }, function() {
- $location.path("/dam/policyList");
- $scope.$apply();
- });
- return;
- }
-
- // === Revert inner data ===
- // >> De-dupe
- $scope.policy.__.dedupe = common.parseJSON($scope.policy.dedupeDef, {});
-
- // >> Notification
- $scope.policy.__.notification = common.parseJSON($scope.policy.notificationDef, []);
-
- // >> Policy
- var _policyUnit = $scope.policy.__.policy = common.parseJSON($scope.policy.policyDef);
-
- // >> Parse expression
- $scope.policy.__.conditions = {};
- var _condition = _policyUnit.expression.match(/from\s+(\w+)(\[(.*)\])?(#window[^\)]*\))?\s+(select (\w+\, )?(\w+)\((\w+)\) as [\w\d_]+ (group by (\w+) )?having ([\w\d_]+) ([<>=]+) ([^\s]+))?/);
- var _cond_stream = _condition[1];
- var _cond_query = _condition[3] || "";
- var _cond_window = _condition[4];
- var _cond_group = _condition[5];
- var _cond_groupUnit = _condition.slice(7,14);
-
- if(!_condition) {
- $scope.policy.__.advanced = true;
- } else {
- // > StreamName
- var _streamName = _cond_stream;
- var _cond = _cond_query;
-
- $scope.policy.__.streamName = _streamName;
-
- // > Conditions
- // Loop condition groups
- if(_cond.trim() !== "" && /^\(.*\)$/.test(_cond)) {
- var _condGrps = _cond.substring(1, _cond.length - 1).split(/\)\s+and\s+\(/);
- $.each(_condGrps, function(i, line) {
- // Loop condition cells
- var _condCells = line.split(/\s+or\s+/);
- $.each(_condCells, function(i, cell) {
- var _opMatch = cell.match(/(\S*)\s*(==|!=|>|<|>=|<=|contains)\s*('(?:[^'\\]|\\.)*'|[\w\d]+)/);
- if(!common.isEmpty(_opMatch)) {
- var _key = _opMatch[1];
- var _op = _opMatch[2];
- var _val = _opMatch[3];
- var _conds = $scope.policy.__.conditions[_key] = $scope.policy.__.conditions[_key] || [];
- var _type = "";
- if(_val.match(/\'.*\'/)) {
- _val = _val.slice(1, -1);
- _type = "string";
- } else if(_val === "true" || _val === "false") {
- var _regexMatch = _key.match(/^str:regexp\((\w+),'(.*)'\)/);
- var _containsMatch = _key.match(/^str:contains\((\w+),'(.*)'\)/);
- var _mathes = _regexMatch || _containsMatch;
- if(_mathes) {
- _key = _mathes[1];
- _val = _mathes[2];
- _type = "string";
- _op = _regexMatch ? "regex" : "contains";
- _conds = $scope.policy.__.conditions[_key] = $scope.policy.__.conditions[_key] || [];
- } else {
- _type = "bool";
- }
- } else {
- _type = "number";
- }
- _conds.push($scope._CondUnit(_key, _op, _val, _type));
- }
- });
- });
- } else if(_cond_query !== "") {
- $scope.policy.__.advanced = true;
- }
- }
-
- if($scope.policy.__.advanced) {
- $scope.policy.__._expression = _policyUnit.expression;
- } else {
- // > window
- if(!_cond_window) {
- $scope.policy.__.window = "externalTime";
- $scope.policy.__.group = "";
- $scope.policy.__.groupAgg = "count";
- $scope.policy.__.groupAggPath = "timestamp";
- $scope.policy.__.groupCondOp = ">=";
- $scope.policy.__.groupCondVal = "2";
- } else {
- try {
- $scope.policy.__.windowConfig = true;
-
- var _winCells = _cond_window.match(/\.(\w+)\((.*)\)/);
- $scope.policy.__.window = _winCells[1];
- var _winConds = $scope.getWindow().fields;
- $.each(_winCells[2].split(","), function(i, val) {
- _winConds[i].val = val;
- });
-
- // Group
- if(_cond_group) {
- $scope.policy.__.group = _cond_groupUnit[3];
- $scope.policy.__.groupAgg = _cond_groupUnit[0];
- $scope.policy.__.groupAggPath = _cond_groupUnit[1];
- $scope.policy.__.groupAggAlias = _cond_groupUnit[4] === "aggValue" ? "" : _cond_groupUnit[4];
- $scope.policy.__.groupCondOp = _cond_groupUnit[5];
- $scope.policy.__.groupCondVal = _cond_groupUnit[6];
- } else {
- $scope.policy.__.group = "";
- $scope.policy.__.groupAgg = "count";
- $scope.policy.__.groupAggPath = "timestamp";
- $scope.policy.__.groupCondOp = ">=";
- $scope.policy.__.groupCondVal = "2";
- }
- } catch(err) {
- $scope.policy.__.window = "externalTime";
- }
- }
- }
-
- $scope.changeStep(0, 3, false);
- });
- }
-
- // Start step
- $scope.changeStep(0, 1, false);
-
- console.log($scope.policy, $scope);
- });
-
- // ==========================================
- // = Function =
- // ==========================================
- // UI: Highlight select step
- $scope.stepSelect = function(step) {
- return step === $scope.step ? "active" : "";
- };
-
- // UI: Collapse all
- $scope.collapse = function(cntr) {
- var _list = $(cntr).find(".collapse").css("height", "auto");
- if(_list.hasClass("in")) {
- _list.removeClass("in");
- } else {
- _list.addClass("in");
- }
- };
-
- // Step process. Will fetch target step attribute and return boolean
- function _check(key, step) {
- var _step = $scope.steps[step - 1];
- if(!_step) return;
-
- var _value = _step[key];
- if(typeof _value === "function") {
- return _value();
- } else if(typeof _value === "boolean") {
- return _value;
- }
- return true;
- }
- // Check step is ready. Otherwise will display load animation
- $scope.stepReady = function(step) {
- return _check("ready", step);
- };
- // Check whether process next step. Otherwise will disable next button
- $scope.checkNextable = function(step) {
- return !_check("nextable", step);
- };
- // Switch step
- $scope.changeStep = function(step, targetStep, check) {
- if(check === false || _check("checkStep", step)) {
- $scope.step = targetStep;
-
- _check("init", targetStep);
- }
- };
-
- // Window
- $scope.getWindow = function() {
- if(!$scope.policy || !$scope.policy.__) return null;
- var _window = common.array.find($scope.policy.__.window, $scope.config.window, "type");
- return _window;
- };
-
- // Aggregation
- $scope.groupAggPathList = function() {
- return $.grep(common.getValueByPath($scope, "_stream.metas", []), function(meta) {
- return $.inArray(meta.attrType, ['long','integer','number', 'double', 'float']) !== -1;
- });
- };
-
- $scope.updateGroupAgg = function() {
- $scope.policy.__.groupAggPath = $scope.policy.__.groupAggPath || common.getValueByPath($scope.groupAggPathList()[0], "tags.attrName");
-
- if($scope.policy.__.groupAgg === 'count') {
- $scope.policy.__.groupAggPath = 'timestamp';
- }
- };
-
- // Resolver
- $scope.resolverTypeahead = function(value, resolver) {
- var _resolverList = Entities.query("stream/attributeresolve", {
- site: Site.current().name,
- resolver: resolver,
- query: value
- });
- return _resolverList._promise.then(function() {
- return _resolverList;
- });
- };
-
- // Used for input box when pressing enter
- $scope.conditionPress = function(event, key, operation, value, type) {
- if(event.which == 13) {
- setTimeout(function() {
- $(event.currentTarget).closest(".input-group").find("button").click();
- }, 1);
- }
- };
- // Check whether has condition
- $scope.hasCondition = function(key, type) {
- var _list = common.getValueByPath($scope.policy.__.conditions, key, []);
- if(_list.length === 0) return false;
-
- if(type === "bool") {
- return !_list[0].ignored();
- }
- return true;
- };
- // Condition unit definition
- $scope._CondUnit = function(key, op, value, type) {
- var _obj = {
- key: key,
- op: op,
- val: value,
- type: type,
- ignored: function() {
- if(this.type === "bool" && this.val === "none") {
- return true;
- }
- return false;
- },
- getVal: function() {
- return this.type === "string" ? "'" + this.val + "'" : this.val;
- },
- toString: function() {
- return this.op + " " + this.getVal();
- },
- toCondString: function() {
- var _op = this.op === "=" ? "==" : this.op;
- if(_op === "regex") {
- return "str:regexp(" + this.key + "," + this.getVal() + ")==true";
- } else if(_op === "contains") {
- return "str:contains(" + this.key + "," + this.getVal() + ")==true";
- } else {
- return this.key + " " + _op + " " + this.getVal();
- }
- },
- };
- return _obj;
- };
- // Add condition for policy
- $scope.addCondition = function(key, op, value, type) {
- if(value === "" || value === undefined) return false;
-
- var _condList = $scope.policy.__.conditions[key] = $scope.policy.__.conditions[key] || [];
- _condList.push($scope._CondUnit(key, op, value, type));
- return true;
- };
- // Convert condition list to description string
- $scope.parseConditionDesc = function(key) {
- return $.map($scope.policy.__.conditions[key] || [], function(cond) {
- if(!cond.ignored()) return "[" + cond.toString() + "]";
- }).join(" or ");
- };
-
- // To query
- $scope.toQuery = function() {
- if(!$scope.policy.__) return "";
-
- if($scope.policy.__.advanced) return $scope.policy.__._expression;
-
- // > Query
- var _query = $.map(common.getValueByPath($scope.policy, "__.conditions", {}), function(list, key) {
- var _conds = $.map(list, function(cond) {
- if(!cond.ignored()) return cond.toCondString();
- });
- if(_conds.length) {
- return "(" + _conds.join(" or ") + ")";
- }
- }).join(" and ");
- if(_query) {
- _query = "[" + _query + "]";
- }
-
- // > Window
- var _window = $scope.getWindow();
- var _windowStr = "";
- if($scope.policy.__.windowConfig) {
- _windowStr = $.map(_window.fields, function(field) {
- return field.val;
- }).join(",");
- _windowStr = "#window." + _window.type + "(" + _windowStr + ")";
-
- // > Group
- if($scope.policy.__.group) {
- _windowStr += common.template(" select ${group}, ${groupAgg}(${groupAggPath}) as ${groupAggAlias} group by ${group} having ${groupAggAlias} ${groupCondOp} ${groupCondVal}", {
- group: $scope.policy.__.group,
- groupAgg: $scope.policy.__.groupAgg,
- groupAggPath: $scope.policy.__.groupAggPath,
- groupCondOp: $scope.policy.__.groupCondOp,
- groupCondVal: $scope.policy.__.groupCondVal,
- groupAggAlias: $scope.policy.__.groupAggAlias || "aggValue"
- });
- } else {
- _windowStr += common.template(" select ${groupAgg}(${groupAggPath}) as ${groupAggAlias} having ${groupAggAlias} ${groupCondOp} ${groupCondVal}", {
- groupAgg: $scope.policy.__.groupAgg,
- groupAggPath: $scope.policy.__.groupAggPath,
- groupCondOp: $scope.policy.__.groupCondOp,
- groupCondVal: $scope.policy.__.groupCondVal,
- groupAggAlias: $scope.policy.__.groupAggAlias || "aggValue"
- });
- }
- } else {
- _windowStr = " select *";
- }
-
- return common.template("from ${stream}${query}${window} insert into outputStream;", {
- stream: $scope.policy.__.streamName,
- query: _query,
- window: _windowStr,
- });
- };
-
- // ==========================================
- // = Update Policy =
- // ==========================================
- // dedupeDef notificationDef policyDef
- $scope.finishPolicy = function() {
- $scope.lock = true;
-
- // dedupeDef
- $scope.policy.dedupeDef = JSON.stringify($scope.policy.__.dedupe);
-
- // notificationDef
- $scope.policy.__.notification = $scope.policy.__.notification || [];
- var _notificationUnit = $scope.policy.__.notification[0];
- if(_notificationUnit) {
- _notificationUnit.flavor = "email";
- _notificationUnit.id = "email_1";
- _notificationUnit.tplFileName = "";
- }
- $scope.policy.notificationDef = JSON.stringify($scope.policy.__.notification);
-
- // policyDef
- $scope.policy.__._dedupTags = $scope.policy.__._dedupTags || {};
- $scope.policy.__.policy = {
- expression: $scope.toQuery(),
- type: "siddhiCEPEngine"
- };
- $scope.policy.policyDef = JSON.stringify($scope.policy.__.policy);
-
- // alertExecutorId
- if($scope._stream.alertExecutor) {
- $scope.policy.tags.alertExecutorId = $scope._stream.alertExecutor.tags.alertExecutorId;
- } else {
- $scope.lock = false;
- $.dialog({
- title: "OPS!",
- content: "Alert Executor not defined! Please check 'AlertExecutorService'!"
- });
- return;
- }
-
- // site
- $scope.policy.tags.site = $scope.policy.tags.site || Site.current().name;
-
- // Update function
- function _updatePolicy() {
- Entities.updateEntity("AlertDefinitionService", $scope.policy)._promise.success(function(data) {
- $scope.create = create = false;
- $scope.encodedRowkey = data.obj[0];
-
- $.dialog({
- title: "Success",
- content: (create ? "Create" : "Update") + " success!",
- }, function() {
- if(data.success) {
- Site.url(Site.find($scope.policy.tags.site), "/dam/policyList");
- } else {
- $.dialog({
- title: "OPS",
- content: (create ? "Create" : "Update") + "failed!" + JSON.stringify(data),
- });
- }
- });
- }).error(function(data) {
- $.dialog({
- title: "OPS",
- content: (create ? "Create" : "Update") + "failed!" + JSON.stringify(data),
- });
- }).then(function() {
- $scope.lock = false;
- });
- }
-
- // Check if already exist
- if($scope.create) {
- var _checkList = Entities.queryEntities("AlertDefinitionService", {
- alertExecutorId: $scope.policy.tags.alertExecutorId,
- policyId: $scope.policy.tags.policyId,
- policyType: "siddhiCEPEngine",
- dataSource: $scope.policy.tags.dataSource,
- });
- _checkList._promise.then(function() {
- if(_checkList.length) {
- $.dialog({
- title: "Override Confirm",
- content: "Already exists PolicyID '" + $scope.policy.tags.policyId + "'. Do you want to override?",
- confirm: true
- }, function(ret) {
- if(ret) {
- _updatePolicy();
- } else {
- $scope.lock = false;
- $scope.$apply();
- }
- });
- } else {
- _updatePolicy();
- }
- });
- } else {
- _updatePolicy();
- }
- };
- });
- }
-
- damControllers.controller('policyCreateCtrl', function(globalContent, Site, damContent, $scope, $routeParams, $location, $q, Entities) {
- policyCtrl(true, globalContent, Site, damContent, $scope, $routeParams, $location, $q, Entities);
- });
- damControllers.controller('policyEditCtrl', function(globalContent, Site, damContent, $scope, $routeParams, $location, $q, Entities) {
- globalContent.lockSite = true;
- policyCtrl(false, globalContent, Site, damContent, $scope, $routeParams, $location, $q, Entities);
- });
-})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/ctrl/sensitivityController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/sensitivityController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/sensitivityController.js
deleted file mode 100644
index 3a68f10..0000000
--- a/eagle-webservice/src/main/webapp/app/public/js/ctrl/sensitivityController.js
+++ /dev/null
@@ -1,454 +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.
- */
-
-damControllers.service('SensitivityConfig', function(Site) {
- 'use strict';
-
- var config = {
- list: [
- {
- name: "HDFS",
- dataSrc: common.array.find("hdfsAuditLog", Site.current().dataSrcList, "tags.dataSource"),
- service: "FileSensitivityService",
- keys: ["filedir", "sensitivityType"],
-
- type: "folder",
- prefix: "fileSensitivity",
- api: "hdfsResource",
- },
- {
- name: "Hive",
- dataSrc: common.array.find("hiveQueryLog", Site.current().dataSrcList, "tags.dataSource"),
- service: "HiveResourceSensitivityService",
- keys: ["hiveResource", "sensitivityType"],
-
- type: "table",
- prefix: "hiveResourceSensitivity",
- api: {
- database: "hiveResource/databases",
- table: "hiveResource/tables",
- column: "hiveResource/columns",
- },
- mapping: {
- database: "database",
- table: "table",
- column: "column",
- },
- },
- {
- name: "HBase",
- dataSrc: common.array.find("hbaseSecurityLog", Site.current().dataSrcList, "tags.dataSource"),
- service: "HbaseResourceSensitivityService",
- keys: ["hbaseResource", "sensitivityType"],
- type: "table",
- prefix: "hbaseResourceSensitivity",
- api: {
- database: "hbaseResource/namespaces",
- table: "hbaseResource/tables",
- column: "hbaseResource/columns",
- },
- mapping: {
- database: "namespace",
- table: "table",
- column: "columnFamily",
- },
- },
- ],
- };
-
- return config;
-});
-
-// =============================================================
-// = Sensitivity Summary =
-// =============================================================
-damControllers.controller('sensitivitySummaryCtrl', function(globalContent, Site, damContent, $scope, Entities, SensitivityConfig) {
- 'use strict';
-
- globalContent.setConfig(damContent.config);
- globalContent.pageTitle = "Data Classification";
- globalContent.pageSubTitle = Site.current().name;
- $scope.config = SensitivityConfig;
-
- $scope._sensitivitySource = null;
- $scope._sensitivityLock = false;
- $scope._sensitivityImportType = "By Text";
- $scope._sensitivityFile = "";
- $scope._sensitivityData = "";
- $scope._sensitivityError = "";
-
- // ==================== Statistic ====================
- var _refreshStatistic = function(entity) {
- if(entity) {
- entity.statisitc = Entities.queryGroup(entity.service, {site: Site.current().name}, "@site", "count");
- } else {
- $.each($scope.config.list, function(i, entity) {
- entity.statisitc = Entities.queryGroup(entity.service, {site: Site.current().name}, "@site", "count");
- });
- }
- };
- _refreshStatistic();
-
- // ================== Configuration ==================
- // Import sensitivity data
- $scope.showImportEditor = function(entity) {
- $scope._sensitivitySource = entity;
-
- $("#sensitivityMDL").modal('show');
- setTimeout(function() {
- $("#sensitivityData").focus();
- }, 500);
- };
-
- $scope.confirmImport = function() {
- if(!$scope._sensitivitySource) return;
-
- $scope._sensitivityLock = true;
-
- // Post data
- switch($scope._sensitivityImportType) {
- case "By Text":
- // > By Text
- Entities.updateEntity($scope._sensitivitySource.service,
- common.parseJSON($scope._sensitivityData, null),
- {timestamp: false})._promise.success(function(data) {
- if(!Entities.dialog(data)) {
- $("#sensitivityMDL").modal('hide');
- $scope._sensitivityData = "";
-
- _refreshStatistic($scope._sensitivitySource);
- }
- }).finally(function() {
- $scope._sensitivityLock = false;
- });
- break;
-
- case "By File":
- // > By File
- var formData = new FormData();
- formData.append("file", $("#sensitivityFile")[0].files[0]);
- formData.append("site", Site.current().name);
-
- $.ajax({
- url : app.getURL("updateEntity", {serviceName: $scope._sensitivitySource.service}),
- data : formData,
- cache : false,
- contentType : false,
- processData : false,
- type : 'POST',
- }).done(function(data) {
- if(!Entities.dialog(data)) {
- $("#sensitivityMDL").modal('hide');
- $scope._sensitivityFile = "";
-
- _refreshStatistic($scope._sensitivitySource);
- }
- }).always(function() {
- $scope._sensitivityLock = false;
- $scope.$apply();
- });
- }
- };
-
- $scope.importCheck = function() {
- if($scope._sensitivityLock) return false;
- $scope._sensitivityError = "";
-
- switch($scope._sensitivityImportType) {
- case "By Text":
- if(!$scope._sensitivityData) return false;
-
- var _list = common.parseJSON($scope._sensitivityData, null);
- if(!_list) {
- $scope._sensitivityError = "Can't parse json";
- } else if(!$.isArray(_list)) {
- $scope._sensitivityError = "Must be array";
- } else if(_list.length === 0) {
- $scope._sensitivityError = "Please provide at least one sensitivity item";
- }
- break;
- case "By File":
- if(!$scope._sensitivityFile) return false;
- break;
- }
- return !$scope._sensitivityError;
- };
-
- // Manage sensitivity data
- $scope.showManagementEditor = function(entity) {
- $scope._sensitivitySource = entity;
- $("#sensitivityListMDL").modal('show');
-
- entity.list = Entities.queryEntities(entity.service, {site: Site.current().name});
- };
-
- $scope.deleteItem = function(item) {
- $.dialog({
- title: "Delete Confirm",
- content: "Do you want to delete '" + item.tags[$scope._sensitivitySource.keys[0]] + "'?",
- buttons: [
- {name: "Delete", class: "btn btn-danger", value: true},
- {name: "Cancel", class: "btn btn-default", value: false},
- ]
- }, function(ret) {
- if(!ret) return;
-
- common.array.remove(item, $scope._sensitivitySource.list);
- Entities.deleteEntity($scope._sensitivitySource.service, item)._promise.then(function() {
- _refreshStatistic($scope._sensitivitySource);
- });
-
-
- $scope.$apply();
- });
- };
-
- $scope.deleteAll = function(entity) {
- $.dialog({
- title: "Delete Confirm",
- content: "<span class='text-red fa fa-exclamation-triangle pull-left' style='font-size: 50px;'></span>" +
- "<p>You are <strong class='text-red'>DELETING</strong> all the sensitivity data from '" + entity.name + "'!</p>" +
- "<p>Proceed to delete?</p>",
- buttons: [
- {name: "Delete", class: "btn btn-danger", value: true},
- {name: "Cancel", class: "btn btn-default", value: false},
- ]
- }, function(ret) {
- if(!ret) return;
-
- Entities.deleteEntities(entity.service, {
- site: Site.current().name
- })._promise.then(function() {
- _refreshStatistic(entity);
- });
-
- entity.list.splice(0);
- $scope.$apply();
- });
- };
-});
-
-// =============================================================
-// = Sensitivity =
-// =============================================================
-damControllers.controller('sensitivityCtrl', function(globalContent, Site, damContent, $scope, $routeParams, SensitivityConfig) {
- 'use strict';
-
- globalContent.setConfig(damContent.config);
- globalContent.pageTitle = "Data Classification";
- globalContent.pageSubTitle = Site.current().name;
- $scope.config = SensitivityConfig;
- $scope.ajaxId = Math.random();
-
- // Check data source
- $scope.dataSrc = common.array.find($routeParams.dataSrc, $scope.config.list, "name");
- if(!$scope.dataSrc) {
- $.dialog({
- title: "OPS",
- content: "Data Source '" + $routeParams.dataSrc + "' not found!"
- }, function() {
- Site.url('/dam/sensitivitySummary');
- });
- }
-});
-
-// ==============================================================
-// = Sensitivity - Folder =
-// ==============================================================
-damControllers.controller('sensitivityViewFolderCtrl', function(globalContent, Site, damContent, $scope, $location, Entities, SensitivityConfig) {
- 'use strict';
-
- $scope.path = $location.search().path || "/";
- $scope.pathUnitList = [];
- $scope.items = [];
-
- // Mark sensitivity
- $scope._oriItem = {};
- $scope._markItem = {};
-
- // ======================= View =======================
- // Path
- function _refreshPathUnitList(_path) {
- var _start,_current, _unitList = [];
- _path = _path + (_path.match(/\/$/) ? "" : "/");
- for(_current = _start = 0 ; _current < _path.length ; _current += 1) {
- if(_path[_current] === "/") {
- _unitList.push({
- name: _path.substring(_start, _current + (_current === 0 ? 1 : 0)),
- path: _path.substring(0, _current === 0 ? 1 : _current),
- });
- _start = _current + 1;
- }
- }
- $scope.pathUnitList = _unitList;
- }
-
- // Item
- $scope.updateItems = function(path) {
- if(path) $scope.path = path;
-
- $scope.items = Entities.query($scope.dataSrc.api, {site: Site.current().name, path: $scope.path});
- $scope.items._promise.success(function(data) {
- var $dlg = Entities.dialog(data, function() {
- if($scope.path !== "/") $scope.updateItems("/");
- });
- });
- _refreshPathUnitList($scope.path);
- };
-
- $scope.getFileName = function(item) {
- return (item.resource + "").replace(/^.*\//, "");
- };
-
- $scope.updateItems($scope.path);
-
- // =================== Sensitivity ===================
- $scope.markSensitivity = function(item) {
- $scope._oriItem = item;
- $scope._markItem = {
- prefix: $scope.dataSrc.prefix,
- tags: {
- site: Site.current().name,
- },
- sensitivityType: ""
- };
- $scope._markItem.tags[$scope.dataSrc.keys[0]] = item.resource;
- $("#sensitivityMDL").modal();
- setTimeout(function() {
- $("#sensitiveType").focus();
- }, 500);
- };
- $scope.confirmUpateSensitivity = function() {
- $scope._oriItem.sensitiveType = $scope._markItem.sensitivityType;
- var _promise = Entities.updateEntity($scope.dataSrc.service, $scope._markItem, {timestamp: false})._promise.success(function(data) {
- Entities.dialog(data);
- });
- $("#sensitivityMDL").modal('hide');
- };
- $scope.unmarkSensitivity = function(item) {
- $.dialog({
- title: "Unmark Confirm",
- content: "Do you want to remove the sensitivity mark on '" + item.resource + "'?",
- confirm: true
- }, function(ret) {
- if(!ret) return;
-
- var _cond = {site: Site.current().name};
- _cond[$scope.dataSrc.keys[0]] = item.resource;
- Entities.deleteEntities($scope.dataSrc.service, _cond);
-
- item.sensitiveType = null;
- $scope.$apply();
- });
- };
-});
-
-// =============================================================
-// = Sensitivity - Table =
-// =============================================================
-damControllers.controller('sensitivityViewTableCtrl', function(globalContent, Site, damContent, $scope, $location, Entities, SensitivityConfig) {
- 'use strict';
-
- $scope.table = null;
-
- // Mark sensitivity
- $scope._oriItem = {};
- $scope._markItem = {};
-
- // ======================= View =======================
- var _fillAttr = function(list, key, target) {
- list._promise.then(function() {
- $.each(list, function(i, unit) {
- unit[key] = unit[target];
- });
- });
- };
-
- $scope.databases = Entities.query($scope.dataSrc.api.database, {site: Site.current().name});
- _fillAttr($scope.databases, "database", $scope.dataSrc.mapping.database);
-
- $scope.loadTables = function(database) {
- if(database.tables) return;
- var _qry = {
- site: Site.current().name
- };
- _qry[$scope.dataSrc.mapping.database] = database[$scope.dataSrc.mapping.database];
- database.tables = Entities.query($scope.dataSrc.api.table, _qry);
- _fillAttr(database.tables, "table", $scope.dataSrc.mapping.table);
- _fillAttr(database.tables, "database", $scope.dataSrc.mapping.database);
- };
-
- $scope.loadColumns = function(database, table) {
- $scope.table = table;
-
- if(table.columns) return;
- var _qry = {
- site: Site.current().name
- };
- _qry[$scope.dataSrc.mapping.database] = database[$scope.dataSrc.mapping.database];
- _qry[$scope.dataSrc.mapping.table] = table[$scope.dataSrc.mapping.table];
- table.columns = Entities.query($scope.dataSrc.api.column, _qry);
- _fillAttr(table.columns, "column", $scope.dataSrc.mapping.column);
- };
-
- // =================== Sensitivity ===================
- $scope.markSensitivity = function(item, event) {
- if(event) event.stopPropagation();
-
- $scope._oriItem = item;
- $scope._markItem = {
- prefix: $scope.dataSrc.prefix,
- tags: {
- site: Site.current().name,
- },
- sensitivityType: ""
- };
- $scope._markItem.tags[$scope.dataSrc.keys[0]] = item.resource;
- $("#sensitivityMDL").modal();
- setTimeout(function() {
- $("#sensitiveType").focus();
- }, 500);
- };
- $scope.confirmUpateSensitivity = function() {
- $scope._oriItem.sensitiveType = $scope._markItem.sensitivityType;
- var _promise = Entities.updateEntity($scope.dataSrc.service, $scope._markItem, {timestamp: false})._promise.success(function(data) {
- Entities.dialog(data);
- });
- $("#sensitivityMDL").modal('hide');
- };
- $scope.unmarkSensitivity = function(item, event) {
- if(event) event.stopPropagation();
-
- $.dialog({
- title: "Unmark Confirm",
- content: "Do you want to remove the sensitivity mark on '" + item.resource + "'?",
- confirm: true
- }, function(ret) {
- if(!ret) return;
-
- var _qry = {
- site: Site.current().name,
- };
- _qry[$scope.dataSrc.keys[0]] = item.resource;
- Entities.deleteEntities($scope.dataSrc.service, _qry);
-
- item.sensitiveType = null;
- $scope.$apply();
- });
- };
-});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/ctrl/siteController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/siteController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/siteController.js
deleted file mode 100644
index c54e99d..0000000
--- a/eagle-webservice/src/main/webapp/app/public/js/ctrl/siteController.js
+++ /dev/null
@@ -1,209 +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.
- */
-
-// =============================================================
-// = Site List =
-// =============================================================
-damControllers.controller('siteListCtrl', function(globalContent, Site, damContent, $scope, $q, Entities) {
- 'use strict';
-
- globalContent.setConfig(damContent.config);
- globalContent.hideSite = true;
-
- $scope._siteEntity = null;
- $scope._siteEntityLock = false;
-
- $scope._dataSrcEntity = null;
- $scope._dataSrcEntityLock = false;
-
- $scope.dataSrcList = Entities.queryGroup("AlertStreamService", '@dataSource=~".*"', "@dataSource", "count");
-
- // Policy statistic
- $scope.policyStatistic = Entities.queryGroup("AlertDefinitionService", '@dataSource=~".*"', "@site,@dataSource", "count");
- $scope.getPolicyCount = function(site, dataSource) {
- for(var i = 0 ; i < $scope.policyStatistic.length ; i += 1) {
- var _cur = $scope.policyStatistic[i];
- if(_cur.key[0] === site && _cur.key[1] === dataSource) {
- return _cur.value[0];
- }
- }
- return 0;
- };
-
- // Alert statistic
- $scope.alertStatistic = Entities.queryGroup("AlertService", {_duration: 1000 * 60 * 60 * 24 * 30}, "@site,@dataSource", "count");
- $scope.getAlertCount = function(site, dataSource) {
- for(var i = 0 ; i < $scope.alertStatistic.length ; i += 1) {
- var _cur = $scope.alertStatistic[i];
- if(_cur.key[0] === site && _cur.key[1] === dataSource) {
- return _cur.value[0];
- }
- }
- return 0;
- };
-
- // =========================================== Site ===========================================
- $scope.showSiteEditor = function(site) {
- $("#siteMDL").modal("show");
- setTimeout(function() {
- $("#siteName").focus();
- }, 500);
-
- $scope._siteEntity = {
- dataSrcList: {}
- };
- $.each($scope.dataSrcList, function(i, item) {
- $scope._siteEntity.dataSrcList[item.key[0]] = {
- name: item.key[0],
- enabled: false
- };
- });
-
- if(site) {
- $scope._siteEntity.srcSite = site;
- $scope._siteEntity.name = site.name;
-
- $.each(site.dataSrcList, function(i, dataSrc) {
- $scope._siteEntity.dataSrcList[dataSrc.tags.dataSource].enabled = dataSrc.enabled === undefined ? true : dataSrc.enabled;
- });
- }
- };
- $scope.checkUpdateSite = function() {
- if(!$scope._siteEntity || !$scope._siteEntity.dataSrcList) return false;
-
- var _hasDataSrc = !!common.array.find(true, common.map.toArray($scope._siteEntity.dataSrcList), "enabled");
- return $scope._siteEntity.name && _hasDataSrc && !$scope._siteEntityLock;
- };
- $scope.confirmUpateSite = function() {
- var promiseList = [];
- $scope._siteEntityLock = true;
-
- if($scope._siteEntity.srcSite) {
- promiseList = [];
- $.each($scope._siteEntity.dataSrcList, function(name, dataSrc) {
- var _entity = {
- enabled: dataSrc.enabled,
- tags: {
- site: $scope._siteEntity.name,
- dataSource: name,
- },
- };
-
- if(dataSrc.enabled) {
- promiseList.push(Entities.updateEntity("AlertDataSourceService", _entity)._promise);
- } else {
- var _dataSrc = common.array.find(name, $scope._siteEntity.srcSite.dataSrcList, "tags.dataSource");
- if(_dataSrc) {
- _dataSrc.enabled = false;
- promiseList.push(Entities.updateEntity("AlertDataSourceService", _entity)._promise);
- }
- }
- });
- } else {
- $.each($scope._siteEntity.dataSrcList, function(name, dataSrc) {
- if(!dataSrc.enabled) return;
-
- var _entity = {
- enabled: true,
- tags: {
- site: $scope._siteEntity.name,
- dataSource: name,
- },
- };
- promiseList.push(Entities.updateEntity("AlertDataSourceService", _entity)._promise);
- });
- }
-
- $q.all(promiseList).then(function() {
- $("#siteMDL").modal("hide")
- .on("hidden.bs.modal", function() {
- $("#siteMDL").off("hidden.bs.modal");
- Site.refresh();
- });
- }).finally(function() {
- $scope._siteEntityLock = false;
- });
- };
-
- $scope.deleteSite = function(site) {
- $.dialog({
- title: "Delete Confirm",
- content: "<span class='text-red fa fa-exclamation-triangle pull-left' style='font-size: 50px;'></span>" +
- "<p>You are <strong class='text-red'>DELETING</strong> the site '<strong>" + site.name + "</strong>'!</p>" +
- "<p>Proceed to delete?</p>",
- buttons: [
- {name: "Delete", class: "btn btn-danger", value: true},
- {name: "Cancel", class: "btn btn-default", value: false},
- ]
- }, function(ret) {
- if(!ret) return;
-
- Entities.deleteEntities("AlertDataSourceService", {
- site: site.name
- })._promise.then(function() {
- Site.refresh();
- });
- });
- };
-
- // ======================================= Data Source ========================================
- $scope.showDataSourceEditor = function(dataSrc) {
- $("#dataSrcMDL").modal("show");
- setTimeout(function() {
- $("#dataSrcConfig").focus();
- }, 500);
-
- $scope._dataSrcEntity = dataSrc;
- };
-
- $scope.confirmUpateDataSource = function() {
- $scope._dataSrcEntityLock = true;
- Entities.updateEntity("AlertDataSourceService", $scope._dataSrcEntity)._promise.then(function() {
- $("#dataSrcMDL").modal("hide");
- }).finally(function() {
- $scope._dataSrcEntityLock = false;
- });
- };
-
- $scope.confirmDeleteDataSource = function() {
- console.log($scope._dataSrcEntity);
- $("#dataSrcMDL").modal("hide")
- .on('hidden.bs.modal', function (e) {
- $("#dataSrcMDL").off('hidden.bs.modal');
-
- var _additionalContent = Site.find($scope._dataSrcEntity.tags.site).dataSrcList.length > 1 ? "" : "<p class='text-muted' style='margin-left: 60px;'>(This site has only one source. Delete will remove site either.)</p>";
-
- $.dialog({
- title: "Delete Confirm",
- content: "<span class='text-red fa fa-exclamation-triangle pull-left' style='font-size: 50px;'></span>" +
- "<p>You are <strong class='text-red'>DELETING</strong> the data source '<strong>" + $scope._dataSrcEntity.tags.dataSource + "</strong>' of '" + $scope._dataSrcEntity.tags.site + "'!</p>" +
- "<p>Proceed to delete?</p>" + _additionalContent,
- buttons: [
- {name: "Delete", class: "btn btn-danger", value: true},
- {name: "Cancel", class: "btn btn-default", value: false},
- ]
- }, function(ret) {
- if(!ret) return;
-
- Entities.deleteEntity("AlertDataSourceService", $scope._dataSrcEntity)._promise.then(function() {
- Site.refresh();
- });
- });
- });
- };
-});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/ctrl/streamController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/streamController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/streamController.js
deleted file mode 100644
index 8d7347d..0000000
--- a/eagle-webservice/src/main/webapp/app/public/js/ctrl/streamController.js
+++ /dev/null
@@ -1,207 +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.
- */
-
-// =============================================================
-// = Stream List =
-// =============================================================
-damControllers.controller('streamListCtrl', function(globalContent, damContent, $scope, $route, $routeParams, $q, Entities) {
- 'use strict';
-
- globalContent.setConfig(damContent.config);
- globalContent.hideSite = true;
-
- $scope.streams = {};
- $scope._streamEntity = null;
- $scope._streamEntityLock = false;
-
- // =========================================== List ===========================================
- var _streamList = Entities.queryEntities("AlertStreamService", '@streamName=~".*"');
- var _streamSchemaList = Entities.queryEntities("AlertStreamSchemaService", '@streamName=~".*"');
- $scope.streamList = _streamList;
- $scope.streamSchemaList = _streamSchemaList;
-
- _streamList._promise.then(function() {
- $.each(_streamList, function(i, stream) {
- stream.metaList = [];
- $scope.streams[stream.tags.dataSource + "_" + stream.tags.streamName] = stream;
- });
- });
-
- $q.all([_streamList._promise, _streamSchemaList._promise]).then(function(res) {
- $.each(_streamSchemaList, function(i, meta) {
- var _stream = $scope.streams[meta.tags.dataSource + "_" + meta.tags.streamName];
- if(_stream) {
- _stream.metaList.push(meta);
- } else {
- console.warn("[Meta] Stream not match:", meta.tags.dataSource + "_" + meta.tags.streamName);
- }
- });
- });
-
- // =========================================== Edit ===========================================
- $scope.showStreamEditor = function(stream) {
- $("#streamMDL").modal("show");
- setTimeout(function() {
- $("#dataSource").focus();
- }, 500);
-
- $scope._streamEntity = {
- dataSource: "",
- streamName: "",
- description: "",
- metaList: [],
- };
- if(stream) {
- $scope._streamEntity.srcStream = stream;
- $scope._streamEntity.dataSource = stream.tags.dataSource;
- $scope._streamEntity.streamName = stream.tags.streamName;
- $scope._streamEntity.desc = stream.desc;
-
- $scope._streamEntity.metaList = $.map(stream.metaList, function(meta) {
- return {
- srcMeta: meta,
- attrName: meta.tags.attrName,
- attrDisplayName: meta.attrDisplayName,
- attrType: meta.attrType,
- attrDescription: meta.attrDescription,
- };
- });
- }
- };
-
- $scope.deleteMeta = function(meta) {
- $.dialog({
- title: "Delete confirm",
- content: "<p>You are <strong class='text-red'>DELETING</strong> the meta '<strong>" + meta.attrName + "</strong>'!</p>" +
- "<p>Proceed to delete?</p>",
- buttons: [
- {name: "Delete", class: "btn btn-danger", value: true},
- {name: "Cancel", class: "btn btn-default", value: false},
- ]
- }, function(ret) {
- if(!ret) return;
-
- common.array.remove(meta, $scope._streamEntity.metaList);
- $scope.$apply();
- });
- };
-
- $scope.checkUpdateStream = function() {
- if(!$scope._streamEntity || $scope._streamEntityLock) return false;
-
- var _pass = true;
-
- if(!$scope._streamEntity.dataSource) _pass = false;
- if(!$scope._streamEntity.streamName) _pass = false;
-
- $.each($scope._streamEntity.metaList, function(i, meta) {
- if(!meta.attrName || !meta.attrType) {
- _pass = false;
- return false;
- }
- });
-
- return _pass;
- };
-
- $scope.confirmDeleteStream = function() {
- $.dialog({
- title: "Delete Confirm",
- content: "<span class='text-red fa fa-exclamation-triangle pull-left' style='font-size: 50px;'></span>" +
- "<p>You are <strong class='text-red'>DELETING</strong> the stream '<strong>" + $scope._streamEntity.streamName + "</strong>'!</p>" +
- "<p>Proceed to delete?</p>",
- buttons: [
- {name: "Delete", class: "btn btn-danger", value: true},
- {name: "Cancel", class: "btn btn-default", value: false},
- ]
- }, function(ret) {
- if(!ret) return;
-
- var _promiseStream = Entities.deleteEntities("AlertStreamService", {
- dataSource: $scope._streamEntity.dataSource,
- streamName: $scope._streamEntity.streamName,
- })._promise;
- var _promiseStreamSchema = Entities.deleteEntities("AlertStreamSchemaService", {
- dataSource: $scope._streamEntity.dataSource,
- streamName: $scope._streamEntity.streamName,
- })._promise;
-
- $q.all(_promiseStream, _promiseStreamSchema).then(function() {
- $("#streamMDL").modal("hide");
-
- setTimeout(function() {
- $route.reload();
- }, 500);
- });
- });
- };
-
- $scope.confirmUpateStream = function() {
- $scope._streamEntityLock = true;
-
- // Stream entity
- var _entity = {
- prefix: "alertStream",
- tags: {
- dataSource: $scope._streamEntity.dataSource,
- streamName: $scope._streamEntity.streamName,
- },
- desc: $scope._streamEntity.desc
- };
-
- // Merge original stream
- if($scope._streamEntity.srcStream) {
- $.extend(_entity, $scope._streamEntity.srcStream);
- }
-
- // Meta entities
- var _metaList = $.map($scope._streamEntity.metaList, function(meta) {
- return {
- prefix: "alertStreamSchema",
- attrType: meta.attrType,
- attrDisplayName: meta.attrDisplayName,
- attrDescription: meta.attrDescription,
- tags: {
- dataSource: _entity.tags.dataSource,
- streamName: _entity.tags.streamName,
- attrName: meta.attrName,
- },
- };
- });
-
- Entities.updateEntity("AlertStreamService", _entity)._promise.then(function() {
- Entities.deleteEntities("AlertStreamSchemaService", {
- dataSource: _entity.tags.dataSource,
- streamName: _entity.tags.streamName,
- })._promise.then(function() {
- Entities.updateEntity("AlertStreamSchemaService", _metaList)._promise.finally(function() {
- Site.refresh();
- });
- }).finally(function() {
- $("#streamMDL").modal("hide");
- $scope._streamEntityLock = false;
-
- setTimeout(function() {
- $route.reload();
- }, 500);
- });
- }, function() {
- $scope._streamEntityLock = false;
- });
- };
-});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/ctrl/userProfileController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/userProfileController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/userProfileController.js
deleted file mode 100644
index 2d182b0..0000000
--- a/eagle-webservice/src/main/webapp/app/public/js/ctrl/userProfileController.js
+++ /dev/null
@@ -1,261 +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.
- */
-
-// =============================================================
-// = User Profile List =
-// =============================================================
-damControllers.controller('userProfileListCtrl', function(globalContent, Site, damContent, $scope, $interval, Entities) {
- 'use strict';
-
- globalContent.setConfig(damContent.config);
- globalContent.pageSubTitle = Site.current().name;
-
- $scope.common = common;
- $scope.algorithms = [];
-
- // ======================================== Algorithms ========================================
- $scope.algorithmEntity = {};
- Entities.queryEntities("AlertDefinitionService", {site: Site.current().name, dataSource: "userProfile"})._promise.then(function(data) {
- $scope.algorithmEntity = common.getValueByPath(data, "data.obj[0]");
- $scope.algorithmEntity.policy = common.parseJSON($scope.algorithmEntity.policyDef);
- });
-
- // ======================================= User profile =======================================
- $scope.profileList = Entities.queryEntities("MLModelService", {site: Site.current().name}, ["user", "algorithm", "content", "version"]);
- $scope.profileList._promise.then(function() {
- var _algorithms = {};
- var _users = {};
-
- // Map user
- $.each($scope.profileList, function(i, unit) {
- _algorithms[unit.tags.algorithm] = unit.tags.algorithm;
- var _user = _users[unit.tags.user] = _users[unit.tags.user] || {user: unit.tags.user};
- _user[unit.tags.algorithm] = {
- version: unit.version
- };
-
- // DE
- if(unit.tags.algorithm === "DE") {
- var _statistics = common.parseJSON(unit.content);
- _statistics = common.getValueByPath(_statistics, "statistics", []);
- _user[unit.tags.algorithm].topCommands = $.map(common.array.top(_statistics, "mean"), function(command) {
- return command.commandName;
- });
- }
- });
-
- // Map algorithms
- $scope.algorithms = $.map(_algorithms, function(algorithm) {
- return algorithm;
- }).sort();
-
- $scope.profileList.splice(0);
- $scope.profileList.push.apply($scope.profileList, common.map.toArray(_users));
- });
-
- // =========================================== Task ===========================================
- $scope.tasks = [];
- function _loadTasks() {
- var _tasks = Entities.queryEntities("ScheduleTaskService", {
- site: Site.current().name,
- _pageSize: 100,
- _duration: 1000 * 60 * 60 * 24 * 14,
- __ETD: 1000 * 60 * 60 * 24
- });
- _tasks._promise.then(function() {
- $scope.tasks.splice(0);
- $scope.tasks.push.apply($scope.tasks, _tasks);
-
- // Duration
- $.each($scope.tasks, function(i, data) {
- if(data.timestamp && data.updateTime) {
- var _ms = (new moment(data.updateTime)).diff(new moment(data.timestamp));
- var _d = moment.duration(_ms);
- data._duration = Math.floor(_d.asHours()) + moment.utc(_ms).format(":mm:ss");
- data.duration = _ms;
- } else {
- data._duration = "--";
- }
- });
- });
- }
-
- $scope.runningTaskCount = function () {
- return common.array.count($scope.tasks, "INITIALIZED", "status") +
- common.array.count($scope.tasks, "PENDING", "status") +
- common.array.count($scope.tasks, "EXECUTING", "status");
- };
-
- // Create task
- $scope.updateTask = function() {
- $.dialog({
- title: "Confirm",
- content: "Do you want to update now?",
- confirm: true
- }, function(ret) {
- if(!ret) return;
-
- var _entity = {
- status: "INITIALIZED",
- detail: "Newly created command",
- tags: {
- site: Site.current().name,
- type: "USER_PROFILE_TRAINING"
- },
- timestamp: +new Date()
- };
- Entities.updateEntity("ScheduleTaskService", _entity, {timestamp: false})._promise.success(function(data) {
- if(!Entities.dialog(data)) {
- _loadTasks();
- }
- });
- });
- };
-
- // Show detail
- $scope.showTaskDetail = function(task) {
- var _content = $("<pre>").text(task.detail);
-
- var $mdl = $.dialog({
- title: "Detail",
- content: _content
- });
-
- // TODO: Remove task
- _content.click(function(e) {
- if(!e.ctrlKey) return;
-
- $.dialog({
- title: "Confirm",
- content: "Remove this task?",
- confirm: true
- }, function(ret) {
- if(!ret) return;
-
- $mdl.modal('hide');
- Entities.deleteEntity("ScheduleTaskService", task)._promise.then(function(data) {
- _loadTasks();
- });
- });
- });
- };
-
- _loadTasks();
- var _loadInterval = $interval(_loadTasks, app.time.refreshInterval);
- $scope.$on('$destroy',function(){
- $interval.cancel(_loadInterval);
- });
-});
-
-// =============================================================
-// = User Profile Detail =
-// =============================================================
-damControllers.controller('userProfileDetailCtrl', function(globalContent, Site, damContent, $scope, $routeParams, Entities) {
- 'use strict';
-
- globalContent.setConfig(damContent.config);
- globalContent.pageTitle = "User Profile";
- globalContent.pageSubTitle = Site.current().name;
- globalContent.navPath = ["User Profile", "Detail"];
-
- $scope.user = $routeParams.user;
-
- // User profile
- $scope.profiles = {};
- $scope.profileList = Entities.queryEntities("MLModelService", {site: Site.current().name, user: $scope.user});
- $scope.profileList._promise.then(function() {
- $.each($scope.profileList, function(i, unit) {
- unit._content = common.parseJSON(unit.content);
- $scope.profiles[unit.tags.algorithm] = unit;
- });
-
- // DE
- if($scope.profiles.DE) {
- console.log($scope.profiles.DE);
-
- $scope.profiles.DE._chart = {};
-
- $scope.profiles.DE.estimates = {};
- $.each($scope.profiles.DE._content, function(key, value) {
- if(key !== "statistics") {
- $scope.profiles.DE.estimates[key] = value;
- }
- });
-
- var _meanList = [];
- var _stddevList = [];
-
- $.each($scope.profiles.DE._content.statistics, function(i, unit) {
- _meanList[i] = {
- x: unit.commandName,
- y: unit.mean
- };
- _stddevList[i] = {
- x: unit.commandName,
- y: unit.stddev
- };
- });
- $scope.profiles.DE._chart.series = [
- {
- key: "mean",
- values: _meanList
- },
- {
- key: "stddev",
- values: _stddevList
- }
- ];
-
- // Percentage table list
- $scope.profiles.DE.meanList = [];
- var _total = common.array.sum($scope.profiles.DE._content.statistics, "mean");
- $.each($scope.profiles.DE._content.statistics, function(i, unit) {
- $scope.profiles.DE.meanList.push({
- command: unit.commandName,
- percentage: unit.mean / _total
- });
- });
- }
-
- // EigenDecomposition
- if($scope.profiles.EigenDecomposition && $scope.profiles.EigenDecomposition._content.principalComponents) {
- $scope.profiles.EigenDecomposition._chart = {
- series: [],
- };
-
- $.each($scope.profiles.EigenDecomposition._content.principalComponents, function(z, grp) {
- var _line = [];
- $.each(grp, function(x, y) {
- _line.push([x,y,z]);
- });
-
- $scope.profiles.EigenDecomposition._chart.series.push({
- data: _line
- });
- });
- }
- });
-
- // UI
- $scope.showRawData = function(content) {
- $.dialog({
- title: "Raw Data",
- content: $("<pre>").text(content)
- });
- };
-});
\ No newline at end of file
[7/9] incubator-eagle git commit: EAGLE-139 EAGLE-163 Eagle UI
Modularization and fix bugs in policy extensions
Posted by hd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/resources/eagleSecurity.xml
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/resources/eagleSecurity.xml b/eagle-webservice/src/main/resources/eagleSecurity.xml
index 2b106b3..b8683dc 100644
--- a/eagle-webservice/src/main/resources/eagleSecurity.xml
+++ b/eagle-webservice/src/main/resources/eagleSecurity.xml
@@ -28,6 +28,8 @@
<scr:http-basic entry-point-ref="unauthorisedEntryPoint"/>
<scr:intercept-url pattern="/rest/entities" method="POST" access="hasRole('ROLE_ADMIN')" />
<scr:intercept-url pattern="/rest/entities/delete" method="POST" access="hasRole('ROLE_ADMIN')" />
+ <scr:intercept-url pattern="/rest/module/*" method="DELETE" access="hasRole('ROLE_ADMIN')" />
+ <scr:intercept-url pattern="/rest/module/*" method="POST" access="hasRole('ROLE_ADMIN')" />
<scr:intercept-url pattern="/rest/list" method="POST" access="hasRole('ROLE_ADMIN')" />
<scr:intercept-url pattern="/rest/status" method="GET" access="permitAll" />
<scr:intercept-url pattern="/rest/*" access="isAuthenticated()" />
@@ -82,7 +84,7 @@
<scr:user-service>
<!-- user admin has role ADMIN, user eagle has role USER, both have password "secret" -->
<scr:user name="eagle" password="$2a$10$TwALMRHpSetDaeTurg9rj.DnIdOde4fkQGBSPG3fVqtH.G5ZH8sQK" authorities="ROLE_USER" />
- <scr:user name="admin" password="$2a$10$TwALMRHpSetDaeTurg9rj.DnIdOde4fkQGBSPG3fVqtH.G5ZH8sQK" authorities="ROLE_ADMIN, ROLE_USER" />
+ <scr:user name="admin" password="$2a$10$TwALMRHpSetDaeTurg9rj.DnIdOde4fkQGBSPG3fVqtH.G5ZH8sQK" authorities="ROLE_ADMIN" />
</scr:user-service>
<scr:password-encoder ref="passwordEncoder" />
</scr:authentication-provider>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/Gruntfile.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/Gruntfile.js b/eagle-webservice/src/main/webapp/Gruntfile.js
index a32b1da..d547ad6 100644
--- a/eagle-webservice/src/main/webapp/Gruntfile.js
+++ b/eagle-webservice/src/main/webapp/Gruntfile.js
@@ -45,6 +45,9 @@ module.exports = function (grunt) {
concat: {
app: {
src: [
+ 'app/public/js/srv/main.js',
+ 'app/public/js/srv/**.js',
+
'app/public/js/app.js',
'app/public/js/app.*.js',
@@ -54,7 +57,7 @@ module.exports = function (grunt) {
'app/public/js/components/**.js',
'app/public/js/components/**/**.js',
- 'app/public/js/ctrl/damController.js',
+ 'app/public/js/ctrl/main.js',
'app/public/js/ctrl/*.js',
],
dest: 'tmp/public/js/scripts.js'
@@ -89,14 +92,24 @@ module.exports = function (grunt) {
options: {
mangle: false
},
- src: 'tmp/public/js/scripts.js',
- dest: 'tmp/public/js/scripts.min.js'
- }
+ files: [
+ {
+ src: 'tmp/public/js/scripts.js',
+ dest: 'tmp/public/js/scripts.min.js'
+ },
+ {
+ expand: true,
+ src: '**/*.js',
+ dest: 'tmp/feature',
+ cwd: 'app/public/feature'
+ }
+ ]
+ },
},
cssmin: {
ui: {
files: {
- 'tmp/public/css/styles.css': ['app/public/css/main.css']
+ 'tmp/public/css/styles.css': ['app/public/css/main.css', 'app/public/css/animation.css']
}
}
},
@@ -107,6 +120,11 @@ module.exports = function (grunt) {
}
},
copy: {
+ feature: {
+ files: [
+ {expand: true, cwd: 'app/', src: ['public/feature/**'], dest: 'tmp'}
+ ]
+ },
ui: {
files: [
{expand: true, cwd: 'tmp/', src: ['**'], dest: 'ui'},
@@ -133,6 +151,7 @@ module.exports = function (grunt) {
// Clean Env
'clean:build',
// Compress JS
+ 'copy:feature',
'concat:app',
'regex-replace:strict',
'uglify',
@@ -142,7 +161,7 @@ module.exports = function (grunt) {
'concat:css',
// Pass HTML Resources
'htmlrefs',
- 'copy',
+ 'copy:ui',
// Clean Env
'clean:tmp',
]);
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/index.html b/eagle-webservice/src/main/webapp/app/index.html
index 82b543f..f3d61a4 100644
--- a/eagle-webservice/src/main/webapp/app/index.html
+++ b/eagle-webservice/src/main/webapp/app/index.html
@@ -30,72 +30,63 @@
<!-- ref:css public/css/styles.min.css -->
<link href="public/css/main.css" rel="stylesheet" type="text/css" media="screen">
- <link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css" media="screen">
- <link href="../node_modules/zombiej-bootstrap-components/bootstrap-components/css/bootstrap-components.min.css" rel="stylesheet" type="text/css" media="screen">
- <link href="../node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
- <link href="../node_modules/zombiej-nvd3/build/nv.d3.min.css" rel="stylesheet" type="text/css" />
- <link href="../node_modules/admin-lte/dist/css/AdminLTE.min.css" rel="stylesheet" type="text/css" />
- <link href="../node_modules/admin-lte/dist/css/skins/skin-blue.min.css" rel="stylesheet" type="text/css" />
+ <link href="public/css/animation.css" rel="stylesheet" type="text/css" media="screen">
+ <link href="../node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet" type="text/css" media="screen">
+ <link href="../node_modules/zombiej-bootstrap-components/bootstrap-components/css/bootstrap-components.css" rel="stylesheet" type="text/css" media="screen">
+ <link href="../node_modules/zombiej-nvd3/build/nv.d3.css" rel="stylesheet" type="text/css" />
+ <link href="../node_modules/font-awesome/css/font-awesome.css" rel="stylesheet" type="text/css" />
+ <link href="../node_modules/admin-lte/dist/css/AdminLTE.css" rel="stylesheet" type="text/css" />
+ <link href="../node_modules/admin-lte/dist/css/skins/skin-blue.css" rel="stylesheet" type="text/css" />
<!-- endref -->
</head>
- <body class="skin-blue sidebar-mini" ng-class="{'no-sidebar' : globalContent.hideSidebar}">
+ <body class="skin-blue sidebar-mini" ng-class="{'no-sidebar' : PageConfig.hideSidebar}">
<!-- Site wrapper -->
<div class="wrapper">
<header class="main-header">
<a href="#/" class="logo">
- <span class="logo-mini">DAM</span>
- <span class="logo-lg">Eagle <small>Data Activity Monitoring</small></span>
+ <span class="logo-mini"><img src="public/images/favicon_white.png" /></span>
+ <span class="logo-lg">Apache Eagle</span>
</a>
<!-- Header Navbar: style can be found in header.less -->
<nav class="navbar navbar-static-top" role="navigation">
<!-- Sidebar toggle button-->
- <a ng-hide="globalContent.hideSidebar" class="sidebar-toggle" data-toggle="offcanvas" role="button">
+ <a ng-hide="PageConfig.hideSidebar" class="sidebar-toggle" data-toggle="offcanvas" role="button">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
+
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<!-- Site -->
- <li class="dropdown" ng-show="!globalContent.hideSite && !globalContent.lockSite">
+ <li class="dropdown" ng-show="!PageConfig.hideSite && !PageConfig.lockSite">
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-server"></i>
- {{site.current().name}}
+ {{Site.current().tags.site}}
<i class="fa fa-caret-down"></i>
</a>
<ul class="dropdown-menu">
- <li ng-repeat="sites in site.list">
- <a ng-click="site.current(sites);">
- <span class="fa fa-database"></span> {{sites.name}}
+ <li ng-repeat="_site in Site.list" ng-if="_site.enabled">
+ <a ng-click="Site.current(_site);">
+ <span class="fa fa-database"></span> {{_site.tags.site}}
</a>
</li>
- <!--li role="separator" class="divider"></li>
- <li>
- <a href="#/dam/siteList"><span class="fa fa-cog"></span>Config Sites</a>
- </li-->
</ul>
</li>
- <li class="dropdown" ng-show="globalContent.lockSite">
+ <li class="dropdown" ng-show="PageConfig.lockSite">
<a>
<i class="fa fa-server"></i>
- {{site.current().name}}
+ {{Site.current().tags.site}}
</a>
</li>
<!-- User -->
- <li class="dropdown user user-menu" ng-hide="globalContent.hideUser">
+ <li class="dropdown user user-menu" ng-hide="PageConfig.hideUser">
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-user"></i>
- {{auth.userProfile.username}}
+ {{Auth.userProfile.username}}
</a>
- <!--ul class="dropdown-menu">
- <li>
- <a ng-click="logout();">
- <span class="fa fa-sign-out"></span> Logout
- </a>
- </li>
- </ul-->
<ul class="dropdown-menu">
<!-- User image -->
<li class="user-header">
@@ -103,14 +94,17 @@
<span class="fa fa-user" alt="User Image"></span>
</span>
<p>
- {{auth.userProfile.username}}
+ {{Auth.userProfile.username}}
<small>
- <span ng-repeat="role in auth.userProfile.authorities">{{role.authority}} </span>
+ <span ng-repeat="role in Auth.userProfile.authorities">{{role.authority}} </span>
</small>
</p>
</li>
<!-- Menu Footer-->
<li class="user-footer">
+ <div class="pull-left" ng-if="Auth.isRole('ROLE_ADMIN')">
+ <a href="#/config/site" class="btn btn-default btn-flat">Configuration</a>
+ </div>
<div class="pull-right">
<a ng-click="logout();" class="btn btn-default btn-flat">Sign out</a>
</div>
@@ -119,16 +113,45 @@
</li>
</ul>
</div>
+
+ <!-- Applications -->
+ <div ng-hide="PageConfig.hideApplication">
+ <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#moduleMenu">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="fa fa-map"></span>
+ </button>
+ <div class="collapse navbar-collapse" id="moduleMenu">
+ <ul class="nav navbar-nav">
+ <li ng-repeat="_grp in Site.current().applicationGroupList" ng-if="_grp.enabledList.length"
+ class="dropdown" ng-class="{active: Application.current().groupName === _grp.name}">
+ <a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
+ {{_grp.name}}
+ </a>
+ <ul class="dropdown-menu">
+ <li ng-repeat="_app in _grp.enabledList">
+ <a ng-click="Application.current(_app);">
+ <span class="fa fa-cubes"></span> {{_app.displayName}}
+ </a>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ </div>
</nav>
</header>
<!-- =============================================== -->
<!-- Left side column. contains the side bar -->
- <aside class="main-sidebar" ng-hide="globalContent.hideSidebar">
+ <aside class="main-sidebar" ng-hide="PageConfig.hideSidebar">
<!-- side bar: style can be found in sidebar.less -->
<section class="sidebar">
<ul class="sidebar-menu">
- <li ng-repeat="page in globalContent.pageList" ng-class="getNavClass(page)" ng-show="getNavVisible(page)">
+ <li class="header">
+ {{Application.current().groupName || 'Application'}} >
+ {{Application.current().displayName || 'Features'}}
+ </li>
+ <li ng-repeat="page in PageConfig.navConfig.pageList track by $index" ng-class="getNavClass(page)" ng-show="getNavVisible(page)">
<a href="{{page.url}}">
<i class="fa fa-{{page.icon}}"></i> <span>{{page.title}}</span>
</a>
@@ -142,17 +165,18 @@
<!-- Right side column. Contains the navbar and content of the page -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
- <section class="content-header" ng-hide="globalContent.hideSidebar">
+ <section class="content-header" ng-hide="PageConfig.hideSidebar">
<h1>
- <span class="pageTitle">{{globalContent.pageTitle}}</span>
- <small class="pageSubTitle">{{globalContent.pageSubTitle}}</small>
+ <span class="pageTitle">{{PageConfig.pageTitle}}</span>
+ <small class="pageSubTitle">{{PageConfig.pageSubTitle}}</small>
</h1>
+
<ol class="breadcrumb">
- <li ng-repeat="nav in globalContent.navPath">
- <a ng-href="{{$last ? '' : globalContent.navMapping[nav]}}">
- <span class="fa fa-home" ng-show="$first"></span>
- {{nav}}
+ <li ng-repeat="navPath in PageConfig.navPath">
+ <a ng-href="#{{navPath.path}}">
+ <span class="fa fa-home" ng-if="$first"></span>
+ {{navPath.title || navPath.path}}
</a>
</li>
</ol>
@@ -160,7 +184,9 @@
<!-- Main content -->
<section class="content">
- <div id="content" ng-view></div>
+ <div id="content">
+ <div ui-view></div>
+ </div>
</section><!-- /.content -->
</div><!-- /.content-wrapper -->
</div><!-- ./wrapper -->
@@ -176,12 +202,23 @@
<script src="../node_modules/angular/angular.js"></script>
<script src="../node_modules/angular-resource/angular-resource.js"></script>
<script src="../node_modules/angular-route/angular-route.js"></script>
- <script src="../node_modules/angular-cookies/angular-cookies.js"></script>
+ <script src="../node_modules/angular-animate/angular-animate.js"></script>
<script src="../node_modules/angular-ui-bootstrap/ui-bootstrap-tpls.js"></script>
+ <script src="../node_modules/angular-ui-router/release/angular-ui-router.js"></script>
<script src="../node_modules/d3/d3.js"></script>
<script src="../node_modules/zombiej-nvd3/build/nv.d3.js"></script>
-
+ <!-- Service -->
+ <script src="public/js/srv/main.js" type="text/javascript" charset="utf-8"></script>
+ <script src="public/js/srv/applicationSrv.js" type="text/javascript" charset="utf-8"></script>
+ <script src="public/js/srv/authorizationSrv.js" type="text/javascript" charset="utf-8"></script>
+ <script src="public/js/srv/entitiesSrv.js" type="text/javascript" charset="utf-8"></script>
+ <script src="public/js/srv/siteSrv.js" type="text/javascript" charset="utf-8"></script>
+ <script src="public/js/srv/pageSrv.js" type="text/javascript" charset="utf-8"></script>
+ <script src="public/js/srv/wrapStateSrv.js" type="text/javascript" charset="utf-8"></script>
+ <script src="public/js/srv/uiSrv.js" type="text/javascript" charset="utf-8"></script>
+
+ <!-- Application -->
<script src="public/js/app.js" type="text/javascript" charset="utf-8"></script>
<script src="public/js/app.ui.js" type="text/javascript" charset="utf-8"></script>
<script src="public/js/app.time.js" type="text/javascript" charset="utf-8"></script>
@@ -189,6 +226,7 @@
<script src="public/js/common.js" type="text/javascript" charset="utf-8"></script>
+ <!-- Components -->
<script src="public/js/components/main.js" type="text/javascript" charset="utf-8"></script>
<script src="public/js/components/sortTable.js" type="text/javascript" charset="utf-8"></script>
<script src="public/js/components/tabs.js" type="text/javascript" charset="utf-8"></script>
@@ -196,15 +234,10 @@
<script src="public/js/components/charts/line3d.js" type="text/javascript" charset="utf-8"></script>
<script src="public/js/components/nvd3.js" type="text/javascript" charset="utf-8"></script>
-
- <script src="public/js/ctrl/damController.js" type="text/javascript" charset="utf-8"></script>
- <script src="public/js/ctrl/policyController.js" type="text/javascript" charset="utf-8"></script>
- <script src="public/js/ctrl/siteController.js" type="text/javascript" charset="utf-8"></script>
- <script src="public/js/ctrl/streamController.js" type="text/javascript" charset="utf-8"></script>
- <script src="public/js/ctrl/alertController.js" type="text/javascript" charset="utf-8"></script>
- <script src="public/js/ctrl/sensitivityController.js" type="text/javascript" charset="utf-8"></script>
- <script src="public/js/ctrl/userProfileController.js" type="text/javascript" charset="utf-8"></script>
+ <!-- Controllers -->
+ <script src="public/js/ctrl/main.js" type="text/javascript" charset="utf-8"></script>
<script src="public/js/ctrl/authController.js" type="text/javascript" charset="utf-8"></script>
+ <script src="public/js/ctrl/configurationController.js" type="text/javascript" charset="utf-8"></script>
<!-- endref -->
</body>
</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/config/application.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/config/application.html b/eagle-webservice/src/main/webapp/app/partials/config/application.html
new file mode 100644
index 0000000..5c5b09e
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/partials/config/application.html
@@ -0,0 +1,103 @@
+<div class="box box-info">
+ <div class="box-header with-border">
+ <h3 class="box-title">
+ <span class="fa fa-cogs"></span>
+ Configuration
+ </h3>
+ </div><!-- /.box-header -->
+
+ <div class="box-body">
+ <div class="row">
+ <div class="col-md-3">
+ <ul class="nav nav-pills nav-stacked">
+ <li class="disabled"><a>Application</a></li>
+ <li role="presentation" ng-repeat="_application in Application.list track by $index" ng-class="{active: application === _application}">
+ <a ng-click="setApplication(_application)">
+ <span class="fa fa-server"></span>
+ {{_application.tags.application}}
+ <span ng-if="_application.alias">({{_application.alias}})</span>
+ </a>
+ </li>
+
+ <li>
+ <a class="text-light-blue" ng-click="newApplication()" ng-disabled="_pageLock">
+ <span class="fa fa-plus-square"></span>
+ New Application
+ </a>
+ </li>
+ </ul>
+ </div>
+
+ <div class="col-md-9">
+ <a class="pull-right btn btn-danger btn-xs" ng-click="deleteApplication(application)" ng-disabled="_pageLock">
+ <span class="fa fa-trash-o"></span>
+ Delete Application
+ </a>
+
+ <!-- Title -->
+ <h3 class="guideline">
+ Application
+ <small>{{application.tags.application}}</small>
+ </h3>
+ <hr/>
+
+ <!-- Config -->
+ <div class="form-group">
+ <label for="displayName">Display Name</label>
+ <input type="text" class="form-control" id="displayName" placeholder="(Optional) Display name." ng-model="applications[application.tags.application].alias">
+ </div>
+ <div class="form-group">
+ <label for="applicationGroup">Group</label>
+ <input type="text" class="form-control" id="applicationGroup" placeholder="(Optional) Group name" ng-model="applications[application.tags.application].group">
+ </div>
+ <div class="form-group">
+ <label for="applicationDescription">Description</label>
+ <textarea id="applicationDescription" class="form-control" placeholder="(Optional) Application description" rows="2" ng-model="applications[application.tags.application].desc"></textarea>
+ </div>
+ <div class="form-group">
+ <label for="applicationConfiguration">Configuration</label>
+ <span class="text-danger">{{configCheck(applications[application.tags.application].config)}}</span>
+ <textarea id="applicationConfiguration" class="form-control" placeholder="Application configuration. Feature can read this " rows="5" ng-model="applications[application.tags.application].config"></textarea>
+ </div>
+
+ <!-- Feature -->
+ <label>* Feature</label>
+ <div class="row">
+ <div class="col-sm-6">
+ <h1 class="text-muted text-center" ng-show="applications[application.tags.application].features.length === 0">No feature in using</h1>
+ <ul class="products-list product-list-in-box fixed-height" ng-show="applications[application.tags.application].features.length !== 0">
+ <li class="item" ng-repeat="feature in applications[application.tags.application].features track by $index" ng-class="{active: _feature === feature}">
+ <div class="product-operation">
+ <a class="fa fa-chevron-up" ng-click="moveFeature(feature, applications[application.tags.application].features, -1)"></a>
+ <a class="fa fa-chevron-down" ng-click="moveFeature(feature, applications[application.tags.application].features, 1)"></a>
+ </div>
+ <div class="product-info">
+ <a class="fa fa-times pull-right" ng-click="removeFeature(feature, applications[application.tags.application])"></a>
+ <span class="product-title">{{feature}}</span>
+ <span class="product-description">{{Application.featureList.set[feature].desc}}</span>
+ </div>
+ </li>
+ </ul>
+ </div>
+ <div class="col-sm-6">
+ <ul class="products-list product-list-in-box fixed-height">
+ <li class="item" ng-repeat="feature in applications[application.tags.application].optionalFeatures track by $index">
+ <button class="btn btn-lg btn-primary pull-left" ng-click="addFeature(feature, applications[application.tags.application])" ng-disabled="_pageLock">
+ <span class="fa fa-star-o"></span>
+ </button>
+ <div class="product-info">
+ <span class="product-title">{{feature}}</span>
+ <span class="product-description">{{Application.featureList.set[feature].desc}}</span>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div><!-- /.box-body -->
+
+ <div class="box-footer clearfix">
+ <button class="btn btn-primary" ng-click="saveAll()" ng-disabled="_pageLock">Save All</button>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/config/feature.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/config/feature.html b/eagle-webservice/src/main/webapp/app/partials/config/feature.html
new file mode 100644
index 0000000..3088883
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/partials/config/feature.html
@@ -0,0 +1,64 @@
+<div class="box box-info">
+ <div class="box-header with-border">
+ <h3 class="box-title">
+ <span class="fa fa-cogs"></span>
+ Configuration
+ </h3>
+ </div><!-- /.box-header -->
+
+ <div class="box-body">
+ <div class="row">
+ <div class="col-md-3">
+ <ul class="nav nav-pills nav-stacked">
+ <li class="disabled">
+ <a>Feature</a>
+ </li>
+ <li role="presentation" ng-repeat="_feature in Application.featureList" ng-class="{active: feature === _feature}">
+ <a ng-click="setFeature(_feature)">
+ <span class="fa fa-leaf" ng-class="{'text-danger': _feature._loaded === false}" uib-tooltip="Module load failed!" tooltip-enable="_feature._loaded === false"></span>
+ {{_feature.tags.feature}}
+ </a>
+ </li>
+ <li>
+ <a class="text-light-blue" ng-click="newFeature()" ng-disabled="_pageLock">
+ <span class="fa fa-plus-square"></span>
+ New Feature
+ </a>
+ </li>
+ </ul>
+ </div>
+
+ <div class="col-md-9">
+ <a class="pull-right btn btn-danger btn-xs" ng-click="deleteFeature(feature)" ng-disabled="_pageLock">
+ <span class="fa fa-trash-o"></span>
+ Delete Feature
+ </a>
+
+ <h3 class="guideline">
+ <span class="fa fa-exclamation-triangle text-danger" uib-tooltip="Module load failed!" ng-show="feature._loaded === false"></span>
+ {{feature.tags.feature}}
+ </h3>
+ <hr/>
+
+ <p class="text text-muted">
+ Will load the start up file <code>controller.js</code> from <code>public/feature/{{feature.tags.feature}}</code>.
+ If you are developing customized feature, please reference provided feature.
+ </p>
+
+ <!-- Config -->
+ <div class="form-group">
+ <label for="featureVersion">Version</label>
+ <input id="featureVersion" type="text" class="form-control" placeholder="(Optional) Feature version." ng-model="features[feature.tags.feature].version">
+ </div>
+ <div class="form-group">
+ <label for="featureDescription">Description</label>
+ <textarea id="featureDescription" class="form-control" placeholder="(Optional) Feature description." rows="10" ng-model="features[feature.tags.feature].desc"></textarea>
+ </div>
+ </div>
+ </div>
+ </div><!-- /.box-body -->
+
+ <div class="box-footer clearfix">
+ <button class="btn btn-primary" ng-click="saveAll()" ng-disabled="_pageLock">Save All</button>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/config/site.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/config/site.html b/eagle-webservice/src/main/webapp/app/partials/config/site.html
new file mode 100644
index 0000000..1d792d9
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/partials/config/site.html
@@ -0,0 +1,94 @@
+<div class="box box-info">
+ <div class="box-header with-border">
+ <h3 class="box-title">
+ <span class="fa fa-cogs"></span>
+ Configuration
+ </h3>
+ </div><!-- /.box-header -->
+
+ <div class="box-body">
+ <div class="row">
+ <div class="col-md-3">
+ <ul class="nav nav-pills nav-stacked">
+ <li class="disabled"><a>Site</a></li>
+ <li role="presentation" ng-repeat="_site in Site.list track by $index" ng-class="{active: site === _site}">
+ <a ng-click="setSite(_site)">
+ <span class="fa fa-server"></span>
+ {{_site.tags.site}}
+ </a>
+ </li>
+
+ <li>
+ <a class="text-light-blue" ng-click="newSite()" ng-disabled="_pageLock">
+ <span class="fa fa-plus-square"></span>
+ New Site
+ </a>
+ </li>
+ </ul>
+ </div>
+
+ <div class="col-md-9">
+ <a class="pull-right btn btn-danger btn-xs" ng-click="deleteSite(site)" ng-disabled="_pageLock">
+ <span class="fa fa-trash-o"></span>
+ Delete Site
+ </a>
+
+ <!-- Title -->
+ <h3 class="guideline">
+ Site
+ <small>{{site.tags.site}}</small>
+ </h3>
+ <hr/>
+
+ <!-- Config -->
+ <div class="checkbox">
+ <label>
+ <input type="checkbox" ng-checked="sites[site.tags.site].enabled" ng-click="sites[site.tags.site].enabled = !sites[site.tags.site].enabled">
+ <strong>Enabled</strong>
+ </label>
+ </div>
+ <hr/>
+
+ <!-- Application -->
+ <label>* Application</label>
+ <div class="row">
+ <div class="col-sm-6">
+ <h1 class="text-muted text-center" ng-show="sites[site.tags.site].applications.length === 0">No application in using</h1>
+ <ul class="products-list product-list-in-box fixed-height" ng-show="sites[site.tags.site].applications.length !== 0">
+ <li class="item" ng-repeat="application in sites[site.tags.site].applications track by $index" ng-class="{active: _application === application}">
+ <div class="product-operation single">
+ <span class="fa fa-cubes"></span>
+ </div>
+ <div class="product-info">
+ <a class="fa fa-times pull-right" ng-click="removeApplication(application, sites[site.tags.site])"></a>
+ <span class="product-title">
+ <a class="fa fa-cog" ng-click="setApplication(application)"></a>
+ {{application.tags.application}}
+ </span>
+ <span class="product-description">{{Application.list.set[application.tags.application].desc}}</span>
+ </div>
+ </li>
+ </ul>
+ </div>
+ <div class="col-sm-6">
+ <ul class="products-list product-list-in-box fixed-height">
+ <li class="item" ng-repeat="application in sites[site.tags.site].optionalApplications track by $index">
+ <button class="btn btn-lg btn-primary pull-left" ng-click="addApplication(application, sites[site.tags.site])" ng-disabled="_pageLock">
+ <span class="fa fa-star-o"></span>
+ </button>
+ <div class="product-info">
+ <span class="product-title">{{application.tags.application}}</span>
+ <span class="product-description">{{Application.list.set[application.tags.application].desc}}</span>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div><!-- /.box-body -->
+
+ <div class="box-footer clearfix">
+ <button class="btn btn-primary" ng-click="saveAll()" ng-disabled="_pageLock">Save All</button>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/alertDetail.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/alertDetail.html b/eagle-webservice/src/main/webapp/app/partials/dam/alertDetail.html
deleted file mode 100644
index 9b0ec01..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/alertDetail.html
+++ /dev/null
@@ -1,61 +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 box-info">
- <div class="box-header with-border">
- <h3 class="box-title" id="policyId">
- {{alert.tags.policyId}}
- <small>{{common.format.date(alert.timestamp)}}</small>
- </h3>
- </div><!-- /.box-header -->
-
- <div class="box-body">
- <a class="btn btn-primary pull-right" href="#/dam/policyDetail/?policy={{alert.tags.policyId}}&site={{alert.tags.site}}&executor={{alert.tags.alertExecutorId}}">View Policy</a>
-
- <div class="inline-group">
- <dl><dt>Site</dt><dd>{{alert.tags.site}}</dd></dl>
- <dl><dt>Data Source</dt><dd>{{alert.tags.dataSource}}</dd></dl>
- </div>
- <div class="inline-group">
- <dl><dt>Alert Time</dt><dd>{{common.format.date(alert.timestamp)}}</dd></dl>
- <dl><dt>Message Time</dt><dd>{{common.format.date(alert.alertContext.properties.timestamp)}}</dd></dl>
- </div>
- <!--div class="inline-group">
- <dl><dt>Severity</dt><dd>{{alert.alertContext.properties.severity}}</dd></dl>
- </div-->
- <div class="inline-group">
- <dl><dt>Stream Name</dt><dd>{{alert.tags.sourceStreams}}</dd></dl>
- </div>
- <div class="inline-group">
- <dl><dt>Alert Source</dt><dd>{{alert.tags.alertSource}}</dd></dl>
- </div>
- <div class="inline-group">
- <dl><dt>User</dt><dd>{{alert.alertContext.properties.user}}</dd></dl>
- <dl><dt>Host</dt><dd>{{alert.alertContext.properties.host}}</dd></dl>
- </div>
- <div class="inline-group">
- <dl><dt>Event</dt><dd>{{alert.alertContext.properties.alertEvent}}</dd></dl>
- </div>
- <div class="inline-group">
- <dl><dt>Message</dt><dd>{{alert.alertContext.properties.alertMessage}}</dd></dl>
- </div>
- </div><!-- /.box-body -->
-
- <div class="overlay" ng-hide="alertList._promise.$$state.status === 1;">
- <i class="fa fa-refresh fa-spin"></i>
- </div>
-</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/alertList.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/alertList.html b/eagle-webservice/src/main/webapp/app/partials/dam/alertList.html
deleted file mode 100644
index d5492ca..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/alertList.html
+++ /dev/null
@@ -1,83 +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 box-primary">
- <div class="box-header with-border">
- <i class="fa fa-list-alt"> </i>
- <h3 class="box-title">
- {{dataSource || "All Alerts"}}
- <div class="btn-group">
- <button class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
- <i class="fa fa-caret-down"></i>
- </button>
- <ul id="programList" class="dropdown-menu" role="menu">
- <li ng-repeat="dataSrc in site.current().dataSrcList">
- <a href="#/dam/alertList/{{dataSrc.tags.dataSource}}">{{dataSrc.tags.dataSource}}</a>
- </li>
- <li class="divider"></li>
- <li>
- <a href="#/dam/alertList">All Policy List</a>
- </li>
- </ul>
- </div>
- </h3>
- </div>
- <div class="box-body">
- <p ng-show="!alertList.ready">
- <span class="fa fa-refresh fa-spin"> </span>
- Loading...
- </p>
-
- <div sorttable source="alertList" sort="-timestamp">
- <table class="table table-bordered" ng-non-bindable>
- <thead>
- <tr>
- <th width="170" sortpath="timestamp">Alert Time</th>
- <th width="170" sortpath="alertContext.properties.timestamp">Message Time</th>
- <th width="105" sortpath="tags.dataSource">Data Source</th>
- <!--th width="70" sortpath="severity">Type</th-->
- <th width="150" sortpath="tags.policyId">Policy Name</th>
- <th width="60" sortpath="alertContext.properties.user">User</th>
- <th width="150" sortpath="alertContext.properties.host">Host</th>
- <th sortpath="alertContext.properties.emailMessage">Description</th>
- <th width="50"> </th>
- </tr>
- </thead>
- <tbody>
- <tr ng-class="{info : item.__new}">
- <td>{{common.format.date(item.timestamp)}}</td>
- <td>{{common.format.date(item.alertContext.properties.timestamp)}}</td>
- <td>{{item.tags.dataSource}}</td>
- <!--td>{{item.severity}}</td-->
- <td class="text-nowrap">
- <a class="fa fa-share-square-o" ng-show="item.tags.policyId"
- href="#/dam/policyDetail/?policy={{item.tags.policyId}}&site={{item.tags.site}}&executor={{item.tags.alertExecutorId}}"> </a>
- {{item.tags.policyId}}
- </td>
- <td>{{item.alertContext.properties.user}}</td>
- <td>{{item.alertContext.properties.host}}</td>
- <td>{{item.alertContext.properties.alertMessage}}</td>
- <td><a href="#/dam/alertDetail/{{item.encodedRowkey}}">Detail</a></td>
- </tr>
- </tbody>
- </table>
- </div>
-
- </div>
- <!--div class="box-footer clearfix">
- </div-->
-</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/login.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/login.html b/eagle-webservice/src/main/webapp/app/partials/dam/login.html
deleted file mode 100644
index 0e2287c..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/login.html
+++ /dev/null
@@ -1,49 +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="login-box">
- <div class="login-logo">
- <a href="#/"> Data Activity Monitoring </a>
- </div>
- <!-- /.login-logo -->
- <div class="login-box-body">
- <p class="login-box-msg">Sign in to start your session</p>
- <div class="form-group has-feedback">
- <input type="text" class="form-control" placeholder="User Name" ng-model="username" ng-keypress="login($event)" autocomplete="off" id="username">
- <span class="glyphicon glyphicon-user form-control-feedback"></span>
- </div>
- <div class="form-group has-feedback">
- <input type="password" class="form-control" placeholder="Password" ng-model="password" ng-keypress="login($event)">
- <span class="glyphicon glyphicon-lock form-control-feedback"></span>
- </div>
- <div class="row">
- <div class="col-xs-8">
- <!--div class="checkbox">
- <label> <input type="checkbox" /> Remember Me
- </label>
- </div-->
- </div>
- <!-- /.col -->
- <div class="col-xs-4">
- <button class="btn btn-primary btn-block btn-flat" ng-click="login($event, true)" ng-disabled="lock">Sign In</button>
- </div>
- <!-- /.col -->
- </div>
- </div>
- <!-- /.login-box-body -->
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/nvd3.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/nvd3.html b/eagle-webservice/src/main/webapp/app/partials/dam/nvd3.html
deleted file mode 100644
index 1a0196d..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/nvd3.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<style>
- .nvd3-chart-cntr > h3 {
- text-align: center;
- }
-
- .nvd3-chart-cntr > svg {
- height: 300px;
- }
-</style>
-
-<button class="btn btn-primary" ng-click="randomChartData()">Random</button>
-<button class="btn btn-primary" ng-click="chart = 'column'">To Column</button>
-<button class="btn btn-primary" ng-click="chart = 'line'">To Line</button>
-<button class="btn btn-primary" ng-click="chart = 'area'">To Area</button>
-<button class="btn btn-primary" ng-click="chart = 'pie'">To Pie</button>
-<button class="btn btn-warning" ng-click="chartConfig.xType = 'number'">Number</button>
-<button class="btn btn-warning" ng-click="chartConfig.xType = 'time'">Time</button>
-
-<div nvd3="data" data-title="Test" data-chart="{{chart}}" data-watching="true" data-config="chartConfig" class="nvd3-chart-cntr"></div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/policyDetail.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/policyDetail.html b/eagle-webservice/src/main/webapp/app/partials/dam/policyDetail.html
deleted file mode 100644
index 9540ac6..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/policyDetail.html
+++ /dev/null
@@ -1,171 +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 box-info">
- <div class="box-header with-border">
- <h3 class="box-title">
- {{policy.tags.policyId}}
- <small>{{policy.tags.site}}</small>
- </h3>
- </div><!-- /.box-header -->
-
- <div class="box-body">
- <div class="row">
- <div class="col-xs-8">
- <div class="inline-group">
- <dl><dt>Data Source</dt><dd>{{policy.tags.dataSource}}</dd></dl>
- <dl><dt>Status</dt><dd>
- <span ng-show="policy.enabled" class="text-muted"><i class="fa fa-square text-green"></i> Enabled</span>
- <span ng-show="!policy.enabled" class="text-muted"><i class="fa fa-square text-muted"></i> Disabled</span>
- </dd></dl>
- </div>
- <div class="inline-group">
- <dl><dt>Description</dt><dd>{{policy.desc}}</dd></dl>
- </div>
- <div class="inline-group">
- <dl><dt>Alert</dt><dd>
- <a href="mailto:{{mail}}" ng-repeat="mail in policy.__mailList track by $index" style="margin-right: 10px;">{{mail}}</a>
- </dd></dl>
- </div>
- </div>
- <div class="col-xs-4 text-right" ng-show="auth.isRole('ROLE_ADMIN')">
- <a class="btn btn-primary" href="#/dam/policyEdit/{{policy.encodedRowkey}}">Edit</a>
- <button class="btn btn-warning" ng-show="!policy.enabled" ng-click="updatePolicyStatus(policy, true)">Enable</button>
- <button class="btn btn-warning" ng-show="policy.enabled" ng-click="updatePolicyStatus(policy, false)">Disable</button>
- <button class="btn btn-danger" ng-click="deletePolicy(policy)">Delete</button>
- </div>
- </div>
- </div><!-- /.box-body -->
-
- <div class="overlay" ng-hide="policyList._promise.$$state.status === 1;">
- <i class="fa fa-refresh fa-spin"></i>
- </div>
-
- <div class="box-footer clearfix">
- <a data-toggle="collapse" href="[data-id='query']">
- View Query
- </a>
- <div data-id="query" class="collapse in">
- <pre>{{policy.__expression}}</pre>
- </div>
- </div>
-</div>
-
-<div class="nav-tabs-custom">
- <ul class="nav nav-tabs">
- <li class="active">
- <a href="[data-id='visualization']" data-toggle="tab">Visualization</a>
- </li>
- <li>
- <a href="[data-id='statistics']" data-toggle="tab">Statistics</a>
- </li>
- <li>
- <a href="[data-id='alerts']" data-toggle="tab">Alerts</a>
- </li>
- </ul>
- <div class="tab-content">
- <div class="tab-pane active" data-id="visualization">
- <div class="row">
- <div class="col-xs-6">
- <div nvd3="policyEvalSeries" data-title="Policy Eval Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
- </div>
- <div class="col-xs-6">
- <div nvd3="policyEvalFailSeries" data-title="Policy Eval Fail Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
- </div>
- <div class="col-xs-6">
- <div nvd3="alertSeries" data-title="Alert Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
- </div>
- <div class="col-xs-6">
- <div nvd3="alertFailSeries" data-title="Alert Fail Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
- </div>
- </div>
- </div><!-- /.tab-pane -->
-
- <div class="tab-pane" data-id="statistics">
- <div class="row">
- <div class="col-xs-3">
- <div class="info-box bg-aqua">
- <span class="info-box-icon"><i class="fa fa-bookmark-o"></i></span>
- <div class="info-box-content">
- <span class="info-box-text">Policy Eval Count</span>
- <span class="info-box-number">{{common.array.sum(policyEvalSeries, "1")}} <small>(Monthly)</small></span>
- <span class="info-box-number">{{policyEvalSeries[policyEvalSeries.length - 1][1]}} <small>(Daily)</small></span>
- </div><!-- /.info-box-content -->
- </div>
- </div>
- <div class="col-xs-3">
- <div class="info-box bg-red">
- <span class="info-box-icon"><i class="fa fa-bookmark-o"></i></span>
- <div class="info-box-content">
- <span class="info-box-text">Policy Eval Fail Count</span>
- <span class="info-box-number">{{common.array.sum(policyEvalFailSeries, "1")}} <small>(Monthly)</small></span>
- <span class="info-box-number">{{policyEvalFailSeries[policyEvalFailSeries.length - 1][1]}} <small>(Daily)</small></span>
- </div><!-- /.info-box-content -->
- </div>
- </div>
- <div class="col-xs-3">
- <div class="info-box bg-aqua">
- <span class="info-box-icon"><i class="fa fa-bookmark-o"></i></span>
- <div class="info-box-content">
- <span class="info-box-text">Alert Count</span>
- <span class="info-box-number">{{common.array.sum(alertSeries, "1")}} <small>(Monthly)</small></span>
- <span class="info-box-number">{{alertSeries[alertSeries.length - 1][1]}} <small>(Daily)</small></span>
- </div><!-- /.info-box-content -->
- </div>
- </div>
- <div class="col-xs-3">
- <div class="info-box bg-red">
- <span class="info-box-icon"><i class="fa fa-bookmark-o"></i></span>
- <div class="info-box-content">
- <span class="info-box-text">Alert Fail Count</span>
- <span class="info-box-number">{{common.array.sum(alertFailSeries, "1")}} <small>(Monthly)</small></span>
- <span class="info-box-number">{{alertFailSeries[alertFailSeries.length - 1][1]}} <small>(Daily)</small></span>
- </div><!-- /.info-box-content -->
- </div>
- </div>
- </div>
- </div><!-- /.tab-pane -->
-
- <div class="tab-pane" data-id="alerts">
- <div sorttable source="alertList" sort="-timestamp">
- <table class="table table-bordered" ng-non-bindable>
- <thead>
- <tr>
- <th width="170" sortpath="timestamp">Alert Time</th>
- <th width="170" sortpath="alertContext.properties.timestamp">Message Time</th>
- <th width="60" sortpath="alertContext.properties.user">User</th>
- <th width="150" sortpath="alertContext.properties.host">Host</th>
- <th sortpath="alertContext.properties.emailMessage">Description</th>
- <th width="50"> </th>
- </tr>
- </thead>
- <tbody>
- <tr ng-class="{info : item.__new}">
- <td>{{common.format.date(item.timestamp)}}</td>
- <td>{{common.format.date(item.alertContext.properties.timestamp)}}</td>
- <td>{{item.alertContext.properties.user}}</td>
- <td>{{item.alertContext.properties.host}}</td>
- <td>{{item.alertContext.properties.alertMessage}}</td>
- <td><a href="#/dam/alertDetail/{{item.encodedRowkey}}">Detail</a></td>
- </tr>
- </tbody>
- </table>
- </div>
- </div><!-- /.tab-pane -->
-
- </div><!-- /.tab-content -->
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/policyEdit.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/policyEdit.html b/eagle-webservice/src/main/webapp/app/partials/dam/policyEdit.html
deleted file mode 100644
index 038a590..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/policyEdit.html
+++ /dev/null
@@ -1,359 +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="progress active" ng-show="!streamReady">
- <div class="progress-bar progress-bar-primary progress-bar-striped" style="width: 100%">
- </div>
-</div>
-
-<!-- Step navigation -->
-<div ng-show="streamReady">
- <div class="row step-cntr">
- <div class="col-md-3" ng-repeat="step in steps">
- <div class="step" ng-class="stepSelect($index + 1)">
- <h1>{{$index + 1}}</h1>
- <h2>Step {{$index + 1}}</h2>
- <p title="{{step.title}}">{{step.title}}</p>
- </div>
- </div>
- </div>
-
- <!-- Step container -->
- <div class="box box-info">
- <div class="box-header with-border">
- <h3 class="box-title">Step {{step}} - {{steps[step - 1].title}}</h3>
- </div><!-- /.box-header -->
-
- <div class="box-body">
- <!-- ---------------------- Step Body Start ---------------------- -->
-
- <!-- Step 1: Data Source -->
- <div ng-show="step === 1">
- <div class="form-group">
- <label>Select Data Source</label>
- <select class="form-control" ng-model="policy.tags.dataSource">
- <option ng-repeat="dataSource in site.current().dataSrcList" ng-hide="dataSource.hide" value="{{dataSource.tags.dataSource}}">{{dataSource.desc || dataSource.tags.dataSource}}</option>
- </select>
- </div>
- </div>
-
- <!-- Step 2: Stream -->
- <div ng-show="step === 2">
- <div class="pull-right" ng-show="policy.__.advanced === undefined">
- <span class="text-muted">or</span>
- <a ng-click="policy.__.advanced = true;">Advanced</a>
- </div>
-
- <div class="form-group">
- <label>Select Stream</label>
- <select class="form-control" ng-model="policy.__.streamName" ng-show="!policy.__.advanced">
- <option ng-repeat="stream in dataSources[policy.tags.dataSource]">{{stream.tags.streamName}}</option>
- </select>
- <select class="form-control" ng-show="policy.__.advanced" disabled="disabled">
- <option>[Advanced Mode]</option>
- </select>
- </div>
-
- <div class="checkbox" ng-show="policy.__.advanced !== undefined">
- <label>
- <input type="checkbox" ng-model="policy.__.advanced">
- Advanced Mode
- </label>
- </div>
- </div>
-
- <!-- Step 3: Define Alert Policy -->
- <div ng-show="step === 3 && !policy.__.advanced">
- <!-- Criteria -->
- <div>
- <label>Match Criteria</label>
- <a ng-click="collapse('.panel-group')">expand / collapse all</a>
-
- <div class="panel-group panel-group-sm" role="tablist">
- <div class="panel panel-default"
- ng-repeat="meta in _stream.metas"
- ng-init="op = '=='; val = null; type = (meta.attrType || '').toLowerCase();">
- <div class="panel-heading" role="tab">
- <h4 class="panel-title">
- <span class="bg-navy disabled color-palette pull-right">
- {{parseConditionDesc(meta.tags.attrName)}}
- </span>
-
- <a role="button" data-toggle="collapse" href="[data-name='{{meta.tags.attrName}}']" class="collapsed">
- <span class="fa fa-square" ng-class="hasCondition(meta.tags.attrName, type) ? 'text-green' : 'text-muted'"> </span>
- {{meta.attrDisplayName || meta.tags.attrName}}
- <span class="fa fa-question-circle" ng-show="meta.attrDescription"
- uib-tooltip="{{meta.attrDescription}}" tooltip-placement="right" tooltip-animation="false"> </span>
- </a>
- </h4>
- </div>
- <div data-name="{{meta.tags.attrName}}" data-type="{{meta.attrType}}" role="tabpanel" class="collapse">
- <div class="panel-body">
- <ul ng-show="type !== 'bool'">
- <li ng-repeat="cond in policy.__.conditions[meta.tags.attrName]">
- [<a ng-click="policy.__.conditions[meta.tags.attrName].splice($index, 1)">X</a>]
- {{cond.toString()}}
- </li>
- </ul>
-
- <!-- String -->
- <div ng-if="type == 'string'">
- <div class="input-group" style="max-width: 450px;">
- <div class="input-group-btn">
- <select class="form-control" ng-model="op">
- <option ng-repeat="mark in ['==','!=','contains','regex']">{{mark}}</option>
- </select>
- </div>
-
- <!-- With resolver -->
- <input type="text" class="form-control" autocomplete="off" ng-model="val" ng-show="meta.attrValueResolver"
- ng-keypress="conditionPress($event, meta.tags.attrName, op, val, type)"
- uib-typeahead="item for item in resolverTypeahead($viewValue, meta.attrValueResolver)">
- <!-- Without resolver -->
- <input type="text" class="form-control" autocomplete="off" ng-model="val" ng-show="!meta.attrValueResolver"
- ng-keypress="conditionPress($event, meta.tags.attrName, op, val, type)">
-
- <span class="input-group-btn">
- <button class="btn btn-info btn-flat" type="button" ng-click="addCondition(meta.tags.attrName, op, val, type);val=null;">Add</button>
- </span>
- </div>
- </div>
-
- <!-- Number -->
- <div ng-if="type == 'long' || type == 'integer' || type == 'number' || type == 'double' || type == 'float'">
- <div class="input-group" style="max-width: 450px;">
- <div class="input-group-btn">
- <select class="form-control" ng-model="op">
- <option ng-repeat="mark in ['==','!=','>','>=','<','<=']">{{mark}}</option>
- </select>
- </div>
-
- <input type="number" class="form-control" autocomplete="off" placeholder="Number Only..." ng-model="val" ng-keypress="conditionPress($event, meta.tags.attrName, op, val, type)">
- <span class="input-group-btn">
- <button class="btn btn-info btn-flat" type="button" ng-click="addCondition(meta.tags.attrName, op, val, type) ? val=null : void(0);">Add</button>
- </span>
- </div>
- </div>
-
- <!-- Boolean -->
- <div ng-if="type == 'bool'" ng-init="policy.__.conditions[meta.tags.attrName] = policy.__.conditions[meta.tags.attrName] || [_CondUnit(meta.tags.attrName, '==', 'none', 'bool')]">
- <select class="form-control" ng-model="policy.__.conditions[meta.tags.attrName][0].val" style="max-width: 100px;">
- <option ng-repeat="bool in ['none','true','false']">{{bool}}</option>
- </select>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- <!-- Window -->
- <div class="checkbox">
- <label>
- <input type="checkbox" ng-checked="policy.__.windowConfig" ng-click="policy.__.windowConfig = !policy.__.windowConfig"> Slide Window
- </label>
- </div>
- <div ng-show="policy.__.windowConfig">
- <div class="row">
- <div class="col-md-4">
- <div class="form-group">
- <label for="window">Window</label>
- <select class="form-control" ng-model="policy.__.window"
- uib-tooltip="{{getWindow().description}}" tooltip-animation="false">
- <option ng-repeat="item in config.window" value="{{item.type}}">{{item.title}}</option>
- </select>
- </div>
- </div>
-
- <!-- fields -->
- <div class="col-md-4" ng-repeat="field in getWindow().fields" ng-init="field.val = field.val || (field.defaultValue || '');" ng-hide="field.hide">
- <div class="form-group" ng-class="{'has-warning' : !field.val || !field.val.match(field.regex)}">
- <label for="window">Window - {{field.title}}</label>
- <input type="text" class="form-control" autocomplete="off" placeholder="{{field.description}}" ng-model="field.val" title="{{field.description}}">
- </div>
- </div>
- </div>
-
- <!-- Aggregation -->
- <div class="row">
- <div class="col-md-4">
- <div class="form-group" ng-class="{'text-yellow' : (policy.__.groupAgg && !policy.__.groupAggPath)}">
- <label for="window">Aggregation</label>
- <div class="input-group">
- <div class="input-group-btn">
- <select class="form-control" ng-model="policy.__.groupAgg" ng-change="updateGroupAgg()">
- <option ng-repeat="op in ['max','min','avg','count', 'sum']">{{op}}</option>
- </select>
- </div>
- <select class="form-control" ng-model="policy.__.groupAggPath" ng-class="{'has-warning' : !policy.__.groupAggPath}" id="groupAggPath"
- ng-show="policy.__.groupAgg" ng-disabled="policy.__.groupAgg === 'count'">
- <option ng-repeat="meta in groupAggPathList()">{{meta.tags.attrName}}</option>
- </select>
- </div>
- </div>
- </div>
-
- <div class="col-md-4">
- <div class="form-group" ng-class="{'text-yellow' : (!policy.__.groupCondOp || !policy.__.groupCondVal)}">
- <label for="window">Condition</label>
- <div class="input-group">
- <div class="input-group-btn">
- <select class="form-control" ng-model="policy.__.groupCondOp" ng-class="{'has-warning' : !policy.__.groupCondOp}">
- <option ng-repeat="op in ['>','<','>=','<=','==']">{{op}}</option>
- </select>
- </div>
- <input type="text" class="form-control" ng-model="policy.__.groupCondVal" ng-class="{'has-warning' : !policy.__.groupCondVal}" />
- </div>
- </div>
- </div>
-
- <div class="col-md-4">
- <div class="form-group">
- <label for="window">Alias (Optional)</label>
- <input type="text" class="form-control" ng-model="policy.__.groupAggAlias" placeholder="Default: aggValue" />
- </div>
- </div>
- </div>
-
- <!-- Group -->
- <div class="row">
- <div class="col-md-4">
- <div class="form-group">
- <label for="window">Group By</label>
- <select class="form-control" ng-model="policy.__.group">
- <option value="">None</option>
- <option ng-repeat="meta in _stream.metas">{{meta.tags.attrName}}</option>
- </select>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- <!-- Step 3: Define Alert Policy -->
- <div ng-show="step === 3 && policy.__.advanced">
- <div class="form-group">
- <label>Query Expression</label>
- <textarea class="form-control" ng-model="policy.__._expression"
- placeholder="Query expression. e.g. from hdfsAuditLogEventStream[(cmd=='open') and (host=='localhost' or host=='127.0.0.1')]#window.time(2 sec) select * insert into outputStream;" rows="5"></textarea>
- </div>
- </div>
-
- <!-- Step 4: Email Notification -->
- <div ng-show="step === 4">
- <div class="row">
- <div class="col-xs-4">
- <div class="form-group" ng-class="{'has-warning' : !policy.tags.policyId}">
- <label>Policy Name</label>
- <input type="text" class="form-control" placeholder="" ng-model="policy.tags.policyId" ng-disabled="!create">
- </div>
- </div>
- <div class="col-xs-3">
- <div class="form-group">
- <label>
- Alert De-Dup Interval(min)
- <span class="fa fa-question-circle" uib-tooltip="Same type alert will be De-dup in configured interval"> </span>
- </label>
- <input type="number" class="form-control" ng-model="policy.__.dedupe.alertDedupIntervalMin" placeholder="[Minute] Number only. Suggestion: 720">
- </div>
- </div>
- <div class="col-xs-3">
- <div class="form-group">
- <label>
- Email De-Dup Interval(min)
- <span class="fa fa-question-circle" uib-tooltip="The minimun time interval of email"> </span>
- </label>
- <input type="number" class="form-control" ng-model="policy.__.dedupe.emailDedupIntervalMin" placeholder="[Minute] Number only. Suggestion: 1440">
- </div>
- </div>
- <div class="col-xs-2">
- <div class="form-group">
- <label>
- Enabled
- </label>
- <p>
- <input type="checkbox" checked="checked" ng-model="policy.enabled">
- </p>
- </div>
- </div>
- </div>
-
- <div>
- <a data-toggle="collapse" href="[data-id='advancedDeDup']">Advanced De-Dup</a>
- <div data-id='advancedDeDup' class="collapse">
- <label>
- De-Dup Key
- <span class="fa fa-question-circle" uib-tooltip="Type of grouping alerts. If you don't know how to config, leave it default."> </span>
- </label>
- <div class="form-group">
- <div class="checkbox" ng-repeat="meta in _stream.metas" ng-init="create ? policy.__._dedupTags[meta.tags.attrName] = !!meta.usedAsTag : void(0);">
- <label>
- <input type="checkbox" ng-model="policy.__._dedupTags[meta.tags.attrName]">
- {{meta.tags.attrName}}
- </label>
- </div>
- </div>
- </div>
- </div>
-
- <hr/>
-
- <div class="form-group">
- <label>Sender</label>
- <input type="text" class="form-control" value="noreply-hadoop-eagle@company1.com" placeholder="Enter Sender. e.g. sender@eaxmple.com" ng-model="policy.__.notification[0].sender">
- </div>
- <div class="form-group">
- <label>Recipients</label>
- <input type="text" class="form-control" placeholder="Enter Recipients. Split with ','. e.g. usera@example.com, userb@example.com" ng-model="policy.__.notification[0].recipients">
- </div>
- <div class="form-group">
- <label>Subject</label>
- <input type="text" class="form-control" placeholder="Enter Subject" ng-model="policy.__.notification[0].subject">
- </div>
- <div class="form-group">
- <label>Description</label>
- <textarea class="form-control" placeholder="Policy description" ng-model="policy.desc"></textarea>
- </div>
-
- <a data-toggle="collapse" href="[data-id='policyQuery']">
- View Query
- </a>
- <div class="collapse in" data-id="policyQuery">
- <pre>{{toQuery()}}</pre>
- </div>
- </div>
-
- <!-- ----------------------- Step Body End ----------------------- -->
- </div><!-- /.box-body -->
-
- <div class="overlay" ng-hide="stepReady(step)">
- <span class="fa fa-refresh fa-spin"> </span>
- </div>
-
- <div class="box-footer text-right">
- <button class="btn btn-info" ng-show="step > 1" ng-click="changeStep(step, step - 1, false)" ng-disabled="lock">
- Prev <span class="fa fa-arrow-circle-o-left"> </span>
- </button>
- <button class="btn btn-info" ng-show="step < steps.length" ng-click="changeStep(step, step + 1)" ng-disabled="checkNextable(step) || lock">
- Next <span class="fa fa-arrow-circle-o-right"> </span>
- </button>
- <button class="btn btn-info" ng-show="step === steps.length" ng-click="finishPolicy()" ng-disabled="checkNextable(step) || lock">
- Done <span class="fa fa-check-circle-o"> </span>
- </button>
- </div>
- </div>
-</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/policyList.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/policyList.html b/eagle-webservice/src/main/webapp/app/partials/dam/policyList.html
deleted file mode 100644
index 376a513..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/policyList.html
+++ /dev/null
@@ -1,98 +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 box-primary">
- <div class="box-header with-border">
- <i class="fa fa-list-alt"> </i>
- <h3 class="box-title">
- {{dataSource.desc || dataSource.tags.dataSource || "All Policies"}}
- <div class="btn-group">
- <button class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
- <i class="fa fa-caret-down"></i>
- </button>
- <ul id="programList" class="dropdown-menu" role="menu">
- <li ng-repeat="dataSrc in site.current().dataSrcList" ng-hide="dataSrc.hide">
- <a href="#/dam/policyList/{{dataSrc.tags.dataSource}}">{{dataSrc.desc || dataSrc.tags.dataSource}}</a>
- </li>
- <li class="divider"></li>
- <li>
- <a href="#/dam/policyList">All Policy List</a>
- </li>
- </ul>
- </div>
- </h3>
- </div>
- <div class="box-body">
- <div class="row">
- <div class="col-xs-3">
- <div class="search-box">
- <input type="search" class="form-control input-sm" placeholder="Search" ng-model="search" />
- <span class="fa fa-search"> </span>
- </div>
- </div>
- <div class="col-xs-6">
- <div class="inline-group form-inline text-muted">
- <dl><dt><i class="fa fa-square text-green"> </i></dt><dd>Enabled</dd></dl>
- <dl><dt><i class="fa fa-square text-muted"> </i></dt><dd>Disabled</dd></dl>
- </div>
- </div>
- <div class="col-xs-3 text-right">
- <a class="btn btn-primary" href="#/dam/policyCreate/{{!dataSource ? '' : '?dataSrc=' + dataSource.tags.dataSource}}" ng-show="auth.isRole('ROLE_ADMIN')">
- New Policy
- <i class="fa fa-plus-circle"> </i>
- </a>
- </div>
- </div>
-
- <p ng-show="policyList._promise.$$state.status !== 1">
- <span class="fa fa-refresh fa-spin"> </span>
- Loading...
- </p>
-
- <div sorttable source="policyList" ng-show="policyList._promise.$$state.status === 1" search="false" searchfunc="searchFunc">
- <table class="table table-bordered" ng-non-bindable>
- <thead>
- <tr>
- <th width="30" sortpath="enabled"> </th>
- <th width="200" sortpath="tags.policyId">Policy Name</th>
- <th sortpath="desc">Description</th>
- <th width="150" sortpath="owner">Owner</th>
- <th width="170" sortpath="lastModifiedDate">Last Modified</th>
- <th width="95" ng-show="_parent.auth.isRole('ROLE_ADMIN')">Action</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td><span class='fa fa-square' ng-class="item.enabled ? 'text-green' : 'text-muted'"> </span></td>
- <td><a href="#/dam/policyDetail/{{item.encodedRowkey}}">{{item.tags.policyId}}</a></td>
- <td>{{item.desc}}</td>
- <td>{{item.owner}}</td>
- <td>{{common.format.date(item.lastModifiedDate) || "-"}}</td>
- <td ng-show="_parent.auth.isRole('ROLE_ADMIN')">
- <a class="fa fa-pencil btn btn-default btn-xs" uib-tooltip="Edit" tooltip-animation="false" href="#/dam/policyEdit/{{item.encodedRowkey}}"> </a>
- <button class="fa fa-play sm btn btn-default btn-xs" uib-tooltip="Enable" tooltip-animation="false" ng-show="!item.enabled" ng-click="_parent.updatePolicyStatus(item, true)"> </button>
- <button class="fa fa-pause sm btn btn-default btn-xs" uib-tooltip="Disable" tooltip-animation="false" ng-show="item.enabled" ng-click="_parent.updatePolicyStatus(item, false)"> </button>
- <button class="rm fa fa-trash-o btn btn-danger btn-xs" uib-tooltip="Delete" tooltip-animation="false" ng-click="_parent.deletePolicy(item)"> </button>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- <!--div class="box-footer clearfix">
- </div-->
-</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity.html b/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity.html
deleted file mode 100644
index b00bbaf..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity.html
+++ /dev/null
@@ -1,32 +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="nav-tabs-custom">
- <!-- Tabs within a box -->
- <ul class="nav nav-tabs pull-right ui-sortable-handle">
- <li ng-repeat="entity in config.list" ng-class="{active: dataSrc.name === entity.name}">
- <a ng-click="site.url('/dam/sensitivity/' + entity.name)">{{entity.name}}</a>
- </li>
- <li class="pull-left header"><i class="fa fa-folder-open"></i> Sensitivity Broswer</li>
- </ul>
- <div class="tab-content">
- <!-- Morris chart - Sales -->
- <div class="tab-pane active">
- <ng-include src="'partials/dam/sensitivity/' + dataSrc.type + '.html?_=' + ajaxId"></ng-include>
- </div>
- </div>
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity/folder.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity/folder.html b/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity/folder.html
deleted file mode 100644
index 1827eac..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity/folder.html
+++ /dev/null
@@ -1,110 +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 ng-controller="sensitivityViewFolderCtrl">
- <ul class="list-inline path">
- <li>Path:</li>
- <li ng-repeat="unit in pathUnitList">
- <a ng-click="updateItems(unit.path)" class="label bg-black">{{unit.name}}</a>
- </li>
- </ul>
-
- <table class="table table-bordered">
- <thead>
- <tr>
- <th width="15%">File Name</th>
- <th width="10%">Owner</th>
- <th width="10%">Group</th>
- <th>Sensitivity Type</th>
- <th width="10" ng-show="auth.isRole('ROLE_ADMIN')"> </th>
- </tr>
- </thead>
- <tbody>
- <tr ng-show="items._promise.$$state.status !== 1">
- <td colspan="5">
- <span class="fa fa-refresh fa-spin"> </span>
- Loading...
- </td>
- </tr>
- <tr ng-show="items._promise.$$state.status === 1 && !items.length">
- <td colspan="5">
- <span class="fa fa-exclamation-triangle"> </span>
- Empty Folder
- </td>
- </tr>
- <tr ng-repeat="item in items" ng-class="{warning : item.sensitiveType}">
- <td>
- <span ng-show="!item.isdir">
- <span class="fa fa-file"> </span>
- {{getFileName(item)}}
- </span>
- <a ng-show="item.isdir" ng-click="updateItems(item.resource)">
- <span class="fa fa-folder"> </span>
- {{getFileName(item)}}
- </a>
-
- <span class="pull-right" ng-show="item.childSensitiveTypes.length">
- <span class="fa fa-dot-circle-o text-muted" uib-tooltip="Contain child sensitivity defination"> </span>
- </span>
- </td>
- <td>{{item.owner}}</td>
- <td>{{item.group}}</td>
- <td>{{item.sensitiveType}}</td>
- <td ng-show="auth.isRole('ROLE_ADMIN')">
- <button class="fa fa-eye btn btn-primary btn-xs" ng-click="markSensitivity(item)" ng-show="!item.sensitiveType"
- uib-tooltip="Mark as sensitivity data" tooltip-animation="false" tooltip-placement="left"> </button>
- <button class="fa fa-eye-slash btn btn-warning btn-xs" ng-click="unmarkSensitivity(item)" ng-show="item.sensitiveType"
- uib-tooltip="Remove the sensitivity mark" tooltip-animation="false" tooltip-placement="left"> </button>
- </td>
- </tr>
- </tbody>
- </table>
-
-
- <!-- Modal: Create / Edit site -->
- <div class="modal fade" id="sensitivityMDL" tabindex="-1" role="dialog">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="modal-title">Mark Sensitivity Data</h4>
- </div>
- <div class="modal-body">
- <div class="form-group">
- <label>Resource</label>
- <input type="text" readonly="readonly" class="form-control" ng-model="_markItem.tags.filedir" />
- </div>
- <div class="form-group">
- <label>* Sensitivity Type</label>
- <input type="text" class="form-control" ng-model="_markItem.sensitivityType" id="sensitiveType" />
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">
- Close
- </button>
- <button type="button" class="btn btn-primary" ng-click="confirmUpateSensitivity()" ng-disabled="!_markItem.sensitivityType">
- Update
- </button>
- </div>
- </div>
- </div>
- </div>
-
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity/table.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity/table.html b/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity/table.html
deleted file mode 100644
index baa824c..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/sensitivity/table.html
+++ /dev/null
@@ -1,150 +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 ng-controller="sensitivityViewTableCtrl">
- <p ng-show="databases._promise.$$state.status !== 1">
- <span class="fa fa-refresh fa-spin"> </span>
- Loading...
- </p>
-
- <div ng-show="databases._promise.$$state.status === 1" class="row">
- <div class="col-md-4">
- <label>
- Databases
- ({{databases.length}})
- </label>
- <ul class="tree tree-bordered" style="max-height: 500px; overflow-y: auto;">
- <li ng-repeat="db in databases">
- <span class="tree-item box-clickable text-primary" ng-click="db.show = !db.show; loadTables(db);">
- <span ng-class="{'text-warning' : db.sensitiveType}">
- <span class="fa fa-database"> </span>
- {{db.database}}
- <span ng-show="db.tables._promise.$$state.status === 1">({{db.tables.length}})</span>
-
- <span ng-show="auth.isRole('ROLE_ADMIN')">
- <a class="fa fa-eye text-muted hover" ng-click="markSensitivity(db, $event)" ng-show="!db.sensitiveType"
- uib-tooltip="Mark as sensitivity data" tooltip-animation="false" tooltip-placement="right"></a>
- <a class="fa fa-eye-slash text-muted hover" ng-click="unmarkSensitivity(db, $event)" ng-show="db.sensitiveType"
- uib-tooltip="Remove the sensitivity mark" tooltip-animation="false" tooltip-placement="right"></a>
- </span>
-
- <span class="pull-right" ng-show="db.childSensitiveTypes.length">
- <span class="fa fa-dot-circle-o" uib-tooltip="Contain child sensitivity defination" tooltip-placement="right" tooltip-append-to-body="true"> </span>
- </span>
- <span ng-show="db.sensitiveType" class="pull-right">[{{db.sensitiveType}}]</span>
- </span>
- </span>
- <ul ng-show="db.show">
- <li ng-show="db.tables._promise.$$state.status !== 1">
- <span>
- <span class="fa fa-refresh fa-spin"> </span>
- Loading...
- </span>
- </li>
- <li ng-repeat="tb in db.tables" ng-class="{active : tb === table}">
- <span class="tree-item box-clickable text-primary" ng-click="loadColumns(db, tb)">
- <span ng-class="{'text-warning' : tb.sensitiveType}">
- <span class="fa fa-table"> </span>
- {{tb.table}}
-
- <span ng-show="auth.isRole('ROLE_ADMIN')">
- <a class="fa fa-eye text-muted hover" ng-click="markSensitivity(tb, $event)" ng-show="!tb.sensitiveType"
- uib-tooltip="Mark as sensitivity data" tooltip-animation="false" tooltip-placement="right"></a>
- <a class="fa fa-eye-slash text-muted hover" ng-click="unmarkSensitivity(tb, $event)" ng-show="tb.sensitiveType"
- uib-tooltip="Remove the sensitivity mark" tooltip-animation="false" tooltip-placement="right"></a>
- </span>
-
- <span class="pull-right" ng-show="tb.childSensitiveTypes.length">
- <span class="fa fa-dot-circle-o" uib-tooltip="Contain child sensitivity defination" tooltip-placement="right" tooltip-append-to-body="true"> </span>
- </span>
- <span ng-show="tb.sensitiveType" class="pull-right">[{{tb.sensitiveType}}]</span>
- </span>
- </span>
- </li>
- </ul>
- </li>
- </ul>
- </div>
- <div class="col-md-8">
- <label ng-show="table">Route: {{table.database}} > {{table.table}}</label>
- <p ng-show="table && table.columns._promise.$$state.status !== 1">
- <span class="fa fa-refresh fa-spin"> </span>
- Loading...
- </p>
- <div ng-show="table && table.columns._promise.$$state.status === 1">
- <table class="table table-bordered">
- <thead>
- <tr>
- <th width="40%">Column Name</th>
- <th>Sensitivity Type</th>
- <th width="10" ng-show="auth.isRole('ROLE_ADMIN')"> </th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="col in table.columns" ng-class="{warning : col.sensitiveType}">
- <td>{{col.column}}</td>
- <td>{{col.sensitiveType}}</td>
- <td ng-show="auth.isRole('ROLE_ADMIN')">
- <button class="fa fa-eye btn btn-primary btn-xs" ng-click="markSensitivity(col)" ng-show="!col.sensitiveType"
- uib-tooltip="Mark as sensitivity data" tooltip-animation="false" tooltip-placement="left"> </button>
- <button class="fa fa-eye-slash btn btn-warning btn-xs" ng-click="unmarkSensitivity(col)" ng-show="col.sensitiveType"
- uib-tooltip="Remove the sensitivity mark" tooltip-animation="false" tooltip-placement="left"> </button>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- </div>
-
-
-
-
-
-
- <!-- Modal: Create / Edit site -->
- <div class="modal fade" id="sensitivityMDL" tabindex="-1" role="dialog">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="modal-title">Mark Sensitivity Data</h4>
- </div>
- <div class="modal-body">
- <div class="form-group">
- <label>Resource</label>
- <input type="text" readonly="readonly" class="form-control" ng-model="_markItem.tags[dataSrc.keys[0]]" />
- </div>
- <div class="form-group">
- <label>* Sensitivity Type</label>
- <input type="text" class="form-control" ng-model="_markItem.sensitivityType" id="sensitiveType" />
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">
- Close
- </button>
- <button type="button" class="btn btn-primary" ng-click="confirmUpateSensitivity()" ng-disabled="!_markItem.sensitivityType">
- Update
- </button>
- </div>
- </div>
- </div>
- </div>
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/sensitivitySummary.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/sensitivitySummary.html b/eagle-webservice/src/main/webapp/app/partials/dam/sensitivitySummary.html
deleted file mode 100644
index 3dfe103..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/sensitivitySummary.html
+++ /dev/null
@@ -1,143 +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="row">
- <div class="col-md-4" ng-repeat="entity in config.list">
- <div class="info-box bg-aqua box-clickable">
- <span class="info-box-icon" ng-click="site.url('/dam/sensitivity/' + entity.name)"><i class="fa fa-suitcase"></i></span>
- <div class="info-box-content">
- <div class="pull-right btn-group" ng-show="auth.isRole('ROLE_ADMIN')">
- <a class="fa fa-cog config" data-toggle="dropdown"></a>
- <ul class="dropdown-menu" role="menu">
- <li>
- <a ng-click="showImportEditor(entity);"><span class="fa fa-cloud-upload"></span>Import</a>
- </li>
- <li class="divider"></li>
- <li>
- <a ng-click="showManagementEditor(entity);"><span class="fa fa-list"></span>Management</a>
- </li>
- </ul>
- </div>
-
- <div ng-click="site.url('/dam/sensitivity/' + entity.name)">
- <span class="info-box-text text-large">{{entity.name}}</span>
- <!--span class="info-box-number">
- <small>Connected</small>
- </span-->
- <div class="progress">
- <div class="progress-bar"></div>
- </div>
- <span class="progress-description">
- <span class="fa fa-refresh fa-spin" ng-hide="entity.statisitc._promise.$$state.status === 1"></span>
- <span ng-show="entity.statisitc._promise.$$state.status === 1">{{entity.statisitc[0].value[0] || 0}}</span>
- sensitivity items
- </span>
- </div>
- </div><!-- /.info-box-content -->
- </div>
- </div>
-</div>
-
-<!-- Modal: Create sensitivity -->
-<div class="modal fade" id="sensitivityMDL" tabindex="-1" role="dialog">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close" ng-disabled="_sensitivityLock">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="modal-title">Import Sensitivity Data</h4>
- </div>
- <div class="modal-body">
- <div tabs data-inner="true" selected="_sensitivityImportType">
- <div pane data-title="By Text">
- <div class="form-group">
- <label>* Sensitivity Data</label>
- <textarea class="form-control" placeholder="Json format here..." rows="10" id="sensitivityData" ng-model="_parent._sensitivityData" ng-disabled="_parent._sensitivityLock"></textarea>
- </div>
- </div>
- <div pane data-title="By File">
- <input type="file" file filepath="_parent._sensitivityFile" id="sensitivityFile" ng-disabled="_parent._sensitivityLock" />
- </div>
- </div>
-
- </div>
- <div class="modal-footer">
- <p class="text-danger pull-left">{{_sensitivityError}}</p>
-
- <button type="button" class="btn btn-default" data-dismiss="modal" ng-disabled="_sensitivityLock">
- Close
- </button>
- <button type="button" class="btn btn-primary" ng-click="confirmImport()"
- ng-disabled="!importCheck()">
- Import
- </button>
- </div>
- </div>
- </div>
-</div>
-
-<!-- Modal: Manage sensitivity -->
-<div class="modal fade" id="sensitivityListMDL" tabindex="-1" role="dialog">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close" ng-disabled="_sensitivityLock">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="modal-title">Sensitivity List</h4>
- </div>
- <div class="modal-body">
- <p ng-show="_sensitivitySource.list._promise.$$state.status !== 1">
- <span class="fa fa-refresh fa-spin"> </span>
- Loading...
- </p>
-
- <div sorttable source="_sensitivitySource.list" ng-show="_sensitivitySource.list._promise.$$state.status === 1">
- <table class="table table-bordered" ng-non-bindable>
- <thead>
- <tr>
- <!--th width="10"></th-->
- <th ng-repeat="key in _parent._sensitivitySource.keys">{{key}}</th>
- <th width="10"> </th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <!--td>
- <input type="checkbox" ng-checked="item.selected" ng-click="item.selected = !item.selected">
- </td-->
- <td ng-repeat="key in _parent._sensitivitySource.keys">{{item.tags[key] || item[key]}}</td>
- <td>
- <a ng-click="_parent.deleteItem(item)">Delete</a>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-danger pull-left" ng-click="deleteAll(_sensitivitySource)">
- Delete All
- </button>
- <button type="button" class="btn btn-default" data-dismiss="modal">
- Close
- </button>
- </div>
- </div>
- </div>
-</div>
\ No newline at end of file
[6/9] incubator-eagle git commit: EAGLE-139 EAGLE-163 Eagle UI
Modularization and fix bugs in policy extensions
Posted by hd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/siteList.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/siteList.html b/eagle-webservice/src/main/webapp/app/partials/dam/siteList.html
deleted file mode 100644
index 44fad6f..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/siteList.html
+++ /dev/null
@@ -1,162 +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="page-fixed">
- <button class="btn btn-primary"
- ng-disabled="dataSrcList._promise.$$state.status !== 1"
- ng-click="showSiteEditor()"
- >+ New Site</button>
-</div>
-
-<div class="box box-primary" ng-repeat="_site in site.list">
- <div class="box-header">
- <h3 class="box-title">{{_site.name}}</h3>
- <div class="box-tools pull-right">
- <button class="btn btn-box-tool" data-widget="collapse">
- <i class="fa fa-minus"></i>
- </button>
- <div class="btn-group">
- <button class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown">
- <i class="fa fa-wrench"></i>
- </button>
- <ul class="dropdown-menu" role="menu">
- <li>
- <a ng-click="showSiteEditor(_site)"><span class="fa fa-cog"></span> Config</a>
- </li>
- <li class="divider"></li>
- <li class="danger">
- <a ng-click="deleteSite(_site)"><span class="fa fa-trash-o"></span> Delete Site</a>
- </li>
- </ul>
- </div>
- </div>
- </div><!-- /.box-header -->
- <div class="box-body">
- <div class="row">
- <div class="col-md-4" ng-repeat="dataSrc in _site.dataSrcList">
- <div class="info-box" ng-class="dataSrc.enabled !== false ? 'bg-aqua' : 'bg-gray'">
- <span class="info-box-icon"><i class="fa fa-suitcase"></i></span>
- <div class="info-box-content">
- <a class="fa fa-cog config pull-right" ng-click="showDataSourceEditor(dataSrc)"></a>
- <span class="info-box-text">{{dataSrc.desc || dataSrc.tags.dataSource}}</span>
-
- <span class="info-box-number" ng-show="dataSrc.hide"><small>-</small></span>
- <a class="info-box-number" ng-show="!dataSrc.hide" ng-click="site.url(_site, '/dam/policyList/' + dataSrc.tags.dataSource);">
- <span class="fa fa-refresh fa-spin" ng-hide="policyStatistic._promise.$$state.status === 1"></span>
- <span ng-show="policyStatistic._promise.$$state.status === 1">{{getPolicyCount(_site.name, dataSrc.tags.dataSource)}}</span>
- <small>Policies</small>
- </a>
- <div class="progress">
- <div class="progress-bar"></div>
- </div>
- <span class="progress-description" ng-show="dataSrc.hide"><small>-</small></span>
- <a class="progress-description" ng-show="!dataSrc.hide" ng-click="site.url(_site, '/dam/alertList/' + dataSrc.tags.dataSource);">
- <span class="fa fa-refresh fa-spin" ng-hide="alertStatistic._promise.$$state.status === 1"></span>
- <span ng-show="alertStatistic._promise.$$state.status === 1">{{getAlertCount(_site.name, dataSrc.tags.dataSource)}}</span>
- alerts in 30 Days
- </a>
- </div><!-- /.info-box-content -->
- </div>
- </div>
- </div>
- </div>
-</div>
-
-
-
-<!-- Modal: Create / Edit site -->
-<div class="modal fade" id="siteMDL" tabindex="-1" role="dialog">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="modal-title">{{!_siteEntity.srcSite ? 'Create' : 'Config'}} Site</h4>
- </div>
- <div class="modal-body">
- <div class="form-group">
- <label>* Site Name</label>
- <input type="text" class="form-control" placeholder="Site name..." ng-model="_siteEntity.name" ng-disabled="!!_siteEntity.srcSite" id="siteName">
- </div>
-
- <label>
- * Data Source
- <small class="text-muted">at least select 1 source</small>
- </label>
- <div class="checkbox" ng-repeat="item in _siteEntity.dataSrcList">
- <label>
- <input type="checkbox" value="{{item.name}}"
- ng-checked="item.enabled"
- ng-click="item.enabled = !item.enabled">
- {{item.name}}
- </label>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">
- Close
- </button>
- <button type="button" class="btn btn-primary" ng-click="confirmUpateSite()"
- ng-disabled="!checkUpdateSite()">
- {{!_siteEntity.srcSite ? 'Create' : 'Update'}}
- </button>
- </div>
- </div>
- </div>
-</div>
-
-<!-- Modal: Edit data source -->
-<div class="modal fade" id="dataSrcMDL" tabindex="-1" role="dialog">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="modal-title">{{_dataSrcEntity.tags.dataSource}}</h4>
- </div>
- <div class="modal-body">
- <div class="checkbox">
- <label>
- <input type="checkbox"
- ng-checked="_dataSrcEntity.enabled"
- ng-click="_dataSrcEntity.enabled = !_dataSrcEntity.enabled">
- Enabled
- </label>
- </div>
-
- <div class="form-group">
- <label>Configuration</label>
- <textarea type="text" class="form-control" placeholder="Data source configuration..." ng-model="_dataSrcEntity.config" id="dataSrcConfig" rows="10"></textarea>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-danger pull-left" ng-click="confirmDeleteDataSource()">
- Delete Source
- </button>
-
- <button type="button" class="btn btn-default" data-dismiss="modal">
- Close
- </button>
- <button type="button" class="btn btn-primary" ng-click="confirmUpateDataSource()" ng-disabled="_dataSrcEntityLock">
- Update
- </button>
- </div>
- </div>
- </div>
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/streamList.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/streamList.html b/eagle-webservice/src/main/webapp/app/partials/dam/streamList.html
deleted file mode 100644
index 251bc46..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/streamList.html
+++ /dev/null
@@ -1,179 +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="page-fixed">
- <button class="btn btn-primary"
- ng-if="auth.isRole('ROLE_ADMIN')"
- ng-click="showStreamEditor()"
- >+ New Stream</button>
-</div>
-
-<p ng-show="streamList._promise.$$state.status !== 1">
- <span class="fa fa-refresh fa-spin"> </span>
- Loading...
-</p>
-
-<div class="box box-primary" ng-repeat="stream in streams">
- <div class="box-header with-border">
- <h3 class="box-title">{{stream.tags.streamName}}</h3>
- <div class="box-tools pull-right">
- <button class="btn btn-box-tool" data-widget="collapse">
- <i class="fa fa-minus"></i>
- </button>
- <button class="btn btn-box-tool" ng-click="showStreamEditor(stream)" ng-if="auth.isRole('ROLE_ADMIN')">
- <i class="fa fa-wrench"></i>
- </button>
- </div>
- </div>
- <div class="box-body">
- <div class="inline-group">
- <dl>
- <dt>
- Data Source
- </dt>
- <dd>
- {{stream.tags.dataSource}}
- </dd>
- </dl>
- <dl>
- <dt>
- Stream Name
- </dt>
- <dd>
- {{stream.tags.streamName}}
- </dd>
- </dl>
- </div>
- <div>
- <dl>
- <dt>
- Description
- </dt>
- <dd>
- {{stream.desc}}
- </dd>
- </dl>
- </div>
-
- <p ng-show="streamSchemaList._promise.$$state.status !== 1">
- <span class="fa fa-refresh fa-spin"> </span>
- Loading...
- </p>
-
- <div class="list" ng-show="streamSchemaList._promise.$$state.status === 1">
- <table class="table table-bordered">
- <thead>
- <tr>
- <th width="10%">Attribute Name</th>
- <th width="12%">Display Name</th>
- <th width="8%">Type</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="meta in stream.metaList">
- <td>{{meta.tags.attrName}}</td>
- <td>{{meta.attrDisplayName}}</td>
- <td><span class="label label-warning">{{meta.attrType}}</span></td>
- <td>{{meta.attrDescription}}</td>
- </tr>
- </tbody>
- </table>
- </div>
- </div><!-- /.box-body -->
- <!-- Loading (remove the following to stop the loading)-->
-</div>
-
-
-
-
-
-
-<!-- Modal: Create / Edit stream -->
-<div class="modal fade" id="streamMDL" tabindex="-1" role="dialog">
- <div class="modal-dialog modal-lg" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="modal-title">{{!_streamEntity.srcStream ? 'Create' : 'Config'}} Stream</h4>
- </div>
- <div class="modal-body">
- <div class="form-group">
- <label>* Data Source</label>
- <input type="text" class="form-control" placeholder="Data source..." ng-model="_streamEntity.dataSource"
- ng-class="{'has-warning': !_streamEntity.dataSource}" ng-disabled="!!_streamEntity.srcStream" id="dataSource">
- </div>
-
- <div class="form-group">
- <label>* Stream Name</label>
- <input type="text" class="form-control" placeholder="Stream name..." ng-model="_streamEntity.streamName"
- ng-class="{'has-warning': !_streamEntity.streamName}" ng-disabled="!!_streamEntity.srcStream">
- </div>
-
- <div class="form-group">
- <label>Description</label>
- <textarea class="form-control" placeholder="Description..." ng-model="_streamEntity.desc"></textarea>
- </div>
-
- <label>
- * Data Source Schema
- </label>
- <table class="table table-bordered">
- <thead>
- <tr>
- <th width="26"> </th>
- <th width="15%">Attribute Name</th>
- <th width="15%">Display Name</th>
- <th width="15%">Type</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="meta in _streamEntity.metaList">
- <td class="input-field text-center">
- <a class="fa fa-trash-o text-danger" ng-click="deleteMeta(meta)"></a>
- </td>
- <td class="input-field"><input type="text" class="form-control" ng-class="{'has-warning': !meta.attrName}" ng-model="meta.attrName" /></td>
- <td class="input-field"><input type="text" class="form-control" ng-model="meta.attrDisplayName" /></td>
- <td class="input-field">
- <select class="form-control" ng-model="meta.attrType">
- <option ng-repeat="type in ['string','bool','long','integer','double','float']">{{type}}</option>
- </select>
- </td>
- <td class="input-field"><input type="text" class="form-control" ng-model="meta.attrDescription" /></td>
- </tr>
- </tbody>
- </table>
- <a ng-click="_streamEntity.metaList.push({attrName: '', attrType: 'string'})">+ Add Schema Item</a>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-danger pull-left" ng-show="_streamEntity.srcStream" ng-click="confirmDeleteStream()" ng-disabled="!checkUpdateStream()">
- Delete
- </button>
-
- <button type="button" class="btn btn-default" data-dismiss="modal">
- Close
- </button>
- <button type="button" class="btn btn-primary" ng-click="confirmUpateStream()" ng-disabled="!checkUpdateStream()">
- {{!_streamEntity.srcStream ? 'Create' : 'Update'}}
- </button>
- </div>
- </div>
- </div>
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/summary.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/summary.html b/eagle-webservice/src/main/webapp/app/partials/dam/summary.html
deleted file mode 100644
index 5a44551..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/summary.html
+++ /dev/null
@@ -1,45 +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.
- -->
-<p ng-show="!dataReady">
- <span class="fa fa-refresh fa-spin"> </span>
- Loading...
-</p>
-
-<div class="row">
- <div class="col-md-4" ng-repeat="dataSrc in site.current().dataSrcList" ng-hide="dataSrc.hide">
- <div class="small-box bg-aqua box-clickable" ng-click="site.url('/dam/policyList/' + dataSrc.tags.dataSource)">
- <div class="inner">
- <h3>
- {{dataSrc.desc || dataSrc.tags.dataSource}}
- </h3>
- <p>
- {{dataSrc.count || 0}} Policies
- </p>
- </div>
- <div class="icon">
- <i class="fa fa-arrow-circle-right"></i>
- </div>
- <span class="small-box-footer">
- <i class="fa fa-arrow-circle-right"></i>
- View Policy List
- </span>
- </div>
- </div>
-</div>
-
-<a class="btn btn-primary" href="#/dam/policyCreate" ng-show="auth.isRole('ROLE_ADMIN')">+ New Policy</a>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/userProfileDetail.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/userProfileDetail.html b/eagle-webservice/src/main/webapp/app/partials/dam/userProfileDetail.html
deleted file mode 100644
index 7c6e19a..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/userProfileDetail.html
+++ /dev/null
@@ -1,87 +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 box-primary">
- <div class="box-header with-border">
- <i class="fa fa-user"> </i>
- <h3 class="box-title">
- {{user}}
- </h3>
- </div>
- <div class="box-body">
- <div>
- <div class="inline-group">
- <dl><dt>User</dt><dd>{{user}}</dd></dl>
- <dl><dt>Site</dt><dd>{{site.current().name}}</dd></dl>
- </div>
- <div class="inline-group">
- <dl><dt>Other Info</dt><dd class="text-muted">N/A</dd></dl>
- </div>
- </div>
-
- <div class="overlay" ng-hide="profileList._promise.$$state.status === 1;">
- <span class="fa fa-refresh fa-spin"></span>
- </div>
- </div>
-</div>
-
-<!-- Analysis -->
-<div class="nav-tabs-custom">
- <ul class="nav nav-tabs">
- <li class="active">
- <a href="[data-id='DE']" data-toggle="tab" ng-click=" currentTab='DE'">DE</a>
- </li>
- <li>
- <a href="[data-id='EigenDecomposition']" data-toggle="tab" ng-click=" currentTab='EigenDecomposition'">EigenDecomposition</a>
- </li>
- <li class="pull-right">
- <button class="btn btn-primary" ng-click="showRawData(currentTab === 'EigenDecomposition' ? profiles.EigenDecomposition.content : profiles.DE.content)">Raw Data</button>
- </li>
- </ul>
- <div class="tab-content">
- <div class="tab-pane active" data-id="DE">
- <div class="row">
- <div class="col-md-9">
- <div nvd3="profiles.DE._chart.series" data-config="{chart: 'column', xType: 'text', height: 400}" class="nvd3-chart-cntr" height="400"></div>
- <div class="inline-group text-center">
- <dl ng-repeat="(key, value) in profiles.DE.estimates"><dt>{{key}}</dt><dd>{{value}}</dd></dl>
- </div>
- </div>
-
- <div class="col-md-3">
- <table class="table table-bordered">
- <thead>
- <tr>
- <th>Command</th>
- <th>Percentage</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="unit in profiles.DE.meanList">
- <td>{{unit.command}}</td>
- <td class="text-right">{{(unit.percentage*100).toFixed(2)}}%</td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- </div><!-- /.tab-pane -->
- <div class="tab-pane" data-id="EigenDecomposition">
- <div line3d-chart height="400" data="profiles.EigenDecomposition._chart.series"> </div>
- </div><!-- /.tab-pane -->
- </div><!-- /.tab-content -->
-</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/dam/userProfileList.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/userProfileList.html b/eagle-webservice/src/main/webapp/app/partials/dam/userProfileList.html
deleted file mode 100644
index 8c0021a..0000000
--- a/eagle-webservice/src/main/webapp/app/partials/dam/userProfileList.html
+++ /dev/null
@@ -1,138 +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 box-primary">
- <div class="box-header with-border">
- <i class="fa fa-list-alt"> </i>
- <h3 class="box-title">
- User Profiles
- <small><a data-toggle="collapse" href="[data-id='algorithms']">Detail</a></small>
- </h3>
- <div class="pull-right">
- <a class="label label-primary" ng-class="runningTaskCount() ? 'label-primary' : 'label-default'" data-toggle="modal" data-target="#taskMDL">Update</a>
- </div>
- </div>
- <div class="box-body">
- <!-- Algorithms -->
- <div data-id="algorithms" class="collapse">
- <table class="table table-bordered">
- <thead>
- <tr>
- <th>Name</th>
- <td>Feature</td>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="algorithm in algorithmEntity.policy.algorithms">
- <td>{{algorithm.name}}</td>
- <td>{{algorithm.features}}</td>
- </tr>
- </tbody>
- </table>
- <hr/>
- </div>
-
- <!-- User Profile List -->
- <p ng-show="profileList._promise.$$state.status !== 1">
- <span class="fa fa-refresh fa-spin"> </span>
- Loading...
- </p>
-
- <div sorttable source="profileList" ng-show="profileList._promise.$$state.status === 1">
- <table class="table table-bordered" ng-non-bindable>
- <thead>
- <tr>
- <th width="10%" sortpath="user">User</th>
- <th>Most Predominat Feature</th>
- <th width="10"></th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>
- <a href="#/dam/userProfileDetail/{{item.user}}">{{item.user}}</a>
- </td>
- <td>
- {{item.DE.topCommands.slice(0,3).join(", ")}}
- </td>
- <td>
- <a href="#/dam/userProfileDetail/{{item.user}}">Detail</a>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
-</div>
-
-<!-- Modal: User profile Schedule Task -->
-<div class="modal fade" id="taskMDL" tabindex="-1" role="dialog">
- <div class="modal-dialog modal-lg" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="modal-title">Training History</h4>
- </div>
- <div class="modal-body">
- <div sorttable source="tasks">
- <table class="table table-bordered" ng-non-bindable>
- <thead>
- <tr>
- <th sortpath="tags.type">Command</th>
- <th sortpath="timestamp">Start Time</th>
- <th sortpath="updateTime">Update Time</th>
- <th sortpath="duration">Duration</th>
- <th sortpath="status">Status</th>
- <th width="10"> </th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>{{item.tags.type}}</td>
- <td>{{common.format.date(item.timestamp) || "--"}}</td>
- <td>{{common.format.date(item.updateTime) || "--"}}</td>
- <td>{{item._duration}}</td>
- <td class="text-nowrap">
- <span class="fa fa-hourglass-start text-muted" ng-show="item.status === 'INITIALIZED'"></span>
- <span class="fa fa-hourglass-half text-info" ng-show="item.status === 'PENDING'"></span>
- <span class="fa fa-circle-o-notch text-primary" ng-show="item.status === 'EXECUTING'"></span>
- <span class="fa fa-check-circle text-success" ng-show="item.status === 'SUCCEEDED'"></span>
- <span class="fa fa-exclamation-circle text-danger" ng-show="item.status === 'FAILED'"></span>
- <span class="fa fa-ban text-muted" ng-show="item.status === 'CANCELED'"></span>
- {{item.status}}
- </td>
- <td>
- <a ng-click="_parent.showTaskDetail(item)">Detail</a>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-primary pull-left" ng-click="updateTask()" ng-show="auth.isRole('ROLE_ADMIN')">
- Update Now
- </button>
- <button type="button" class="btn btn-default" data-dismiss="modal">
- Close
- </button>
- </div>
- </div>
- </div>
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/landing.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/landing.html b/eagle-webservice/src/main/webapp/app/partials/landing.html
new file mode 100644
index 0000000..c90d97c
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/partials/landing.html
@@ -0,0 +1,12 @@
+<p class="lead">
+ <span ng-if="!Application.current()">Current site do not use any application.</span>
+ <span ng-if="Application.current()">Current application do not install any feature.</span>
+
+ <span ng-if="Auth.isRole('ROLE_ADMIN')">
+ Click
+ <a href="#/config/site" ng-if="!Application.current()">here</a>
+ <a href="#/config/application" ng-if="Application.current()">here</a>
+ to configure.
+ </span>
+ <span ng-if="!Auth.isRole('ROLE_ADMIN')">Please contact your admin.</span>
+</p>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/partials/login.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/login.html b/eagle-webservice/src/main/webapp/app/partials/login.html
new file mode 100644
index 0000000..112a76c
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/partials/login.html
@@ -0,0 +1,49 @@
+<!--
+ 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="login-box">
+ <div class="login-logo">
+ <a href="#/">Apache Eagle</a>
+ </div>
+ <!-- /.login-logo -->
+ <div class="login-box-body">
+ <p class="login-box-msg">Sign in to start your session</p>
+ <div class="form-group has-feedback">
+ <input type="text" class="form-control" placeholder="User Name" ng-model="username" ng-keypress="login($event)" autocomplete="off" id="username">
+ <span class="glyphicon glyphicon-user form-control-feedback"></span>
+ </div>
+ <div class="form-group has-feedback">
+ <input type="password" class="form-control" placeholder="Password" ng-model="password" ng-keypress="login($event)">
+ <span class="glyphicon glyphicon-lock form-control-feedback"></span>
+ </div>
+ <div class="row">
+ <div class="col-xs-8">
+ <!--div class="checkbox">
+ <label> <input type="checkbox" /> Remember Me
+ </label>
+ </div-->
+ </div>
+ <!-- /.col -->
+ <div class="col-xs-4">
+ <button class="btn btn-primary btn-block btn-flat" ng-click="login($event, true)" ng-disabled="lock">Sign In</button>
+ </div>
+ <!-- /.col -->
+ </div>
+ </div>
+ <!-- /.login-box-body -->
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/css/animation.css
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/css/animation.css b/eagle-webservice/src/main/webapp/app/public/css/animation.css
new file mode 100644
index 0000000..954bd29
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/css/animation.css
@@ -0,0 +1,46 @@
+@CHARSET "UTF-8";
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+[ui-view].ng-enter, [ui-view].ng-leave {
+ position: absolute;
+ left: 0;
+ right: 0;
+ -webkit-transition: all .5s ease-in-out;
+ -moz-transition: all .5s ease-in-out;
+ -o-transition: all .5s ease-in-out;
+ transition: all .3s ease-in-out;
+}
+
+[ui-view].ng-enter {
+ opacity: 0;
+}
+
+[ui-view].ng-enter-active {
+ opacity: 1;
+}
+
+[ui-view].ng-leave {
+ opacity: 1;
+ transform:translate3d(0, 0, 0);
+}
+
+[ui-view].ng-leave-active {
+ opacity: 0;
+ transform:translate3d(20%, 0, 0);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/css/main.css
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/css/main.css b/eagle-webservice/src/main/webapp/app/public/css/main.css
index 5e80728..2e951f2 100644
--- a/eagle-webservice/src/main/webapp/app/public/css/main.css
+++ b/eagle-webservice/src/main/webapp/app/public/css/main.css
@@ -43,11 +43,12 @@ body.no-sidebar .content-wrapper {
margin-top: 10px;
}
-/* Common */
+ /* Common */
a {
cursor: pointer;
}
+/* Table */
.table.table-sm>tbody>tr>td,
.table.table-sm>tbody>tr>th,
.table.table-sm>tfoot>tr>td,
@@ -148,41 +149,7 @@ a {
margin: 5px 0 10px 0;
}
-
-body .tooltip-inner {
- max-width: 500px;
-}
-
-.text-nowrap {
- white-space: nowrap;
-}
-
-.text-ellipsis,
-.label.text-ellipsis {
- overflow:hidden;
- text-overflow:ellipsis;
- display: inline-block;
- white-space: nowrap;
- max-width: 100%;
-}
-td.text-ellipsis {
- display: table-cell;
-}
-
-.btn.btn-xs.sm {
- font-size: 12px;
- padding: 2px 6px;
-}
-
-.noSelect {
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- -webkit-touch-callout: none;
- -webkit-user-select: none;
-}
-
+/* inline group */
.inline-group dl,
.inline-group dl dt,
.inline-group dl dd {
@@ -206,6 +173,7 @@ td.text-ellipsis {
margin-right: 5px;
}
+/* Search box */
.search-box {
position: relative;
margin-bottom: 15px;
@@ -327,6 +295,13 @@ ul.nav.nav-tabs li .btn {
background: #dd4b39;
}
+.dropdown-submenu{position:relative;}
+.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px;}
+.dropdown-submenu:hover>.dropdown-menu{display:block;}
+.dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#cccccc;margin-top:5px;margin-right:-10px;}
+.dropdown-submenu:hover>a:after{border-left-color:#ffffff;}
+.dropdown-submenu.pull-left{float:none;}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px;}
+
/* Input Group */
.input-group .input-group-btn select {
width: auto;
@@ -405,6 +380,55 @@ ul.tree.tree-bordered > li > ul > li > a {
padding: 8px 8px 8px 30px;
}
+.product-list-in-box > .item {
+ -webkit-transition: background .5s linear;
+ -o-transition: background .5s linear;
+ transition: background .5s linear;
+}
+.product-list-in-box > .item.ng-animate {
+ transition: 0s;
+}
+.product-list-in-box > .item.active {
+ background: #F5FAFC;
+ -webkit-transition: none;
+ -o-transition: none;
+ transition: none;
+}
+
+.products-list.fixed-height {
+ height: 402px;
+ overflow-y: auto;
+}
+
+.products-list .product-operation {
+ float: left;
+ border: 1px solid #9EC8E0;
+ border-radius: 5px;
+ overflow: hidden;
+}
+
+.products-list .product-operation .fa {
+ display: block;
+ padding: 4px 16px;
+ color: #3c8dbc;
+}
+.products-list .product-operation a.fa:hover {
+ color: #FFFFFF;
+ background: #337ab7;
+}
+
+.products-list .product-operation.single .fa {
+ padding: 12px 12px;
+ font-size: 20px;
+}
+
+.products-list .item .product-info a.fa.fa-times {
+ display: none;
+}
+.products-list .item:hover .product-info a.fa.fa-times {
+ display: block;
+}
+
/* Label */
.label.label-default {
color: #FFFFFF;
@@ -421,24 +445,6 @@ ul.tree.tree-bordered > li > ul > li > a {
height: 200px;
}
-/*.chart .chart-header h3 {
- text-align: center;
- margin: 10px 0 5px 0;
-}
-.chart .chart-body {
- height: 200px;
-}
-
-.chart .chart-body .axis path, .axis line {
- fill: none;
- stroke: #000;
- shape-rendering: crispEdges;
-}
-
-.chart .chart-body .bar {
- fill: steelblue;
-}*/
-
/* Tab */
body .tab-content>.tab-pane {
display: block;
@@ -448,7 +454,18 @@ body .tab-content>.tab-pane {
}
body .tab-content>.tab-pane.active {
height: auto;
- overflow-y: auto;
+ overflow-x: visible;
+ overflow-y: visible;
+}
+
+body .box-body .nav-pills > li > a {
+ padding: 5px 15px;
+ border: none;
+}
+
+/* Box */
+.box .guideline {
+ margin-top: 0;
}
/* Customize */
@@ -474,8 +491,36 @@ body .tab-content>.tab-pane.active {
z-index: 3;
}
-.main-header .logo .logo-lg small {
- font-size: 12px;
+.main-header .logo img {
+ height: 34px;
+}
+
+.main-header .navbar-toggle {
+ float: none;
+ border-radius: 0;
+}
+.main-header .navbar-toggle:hover {
+ background: rgba(0, 0, 0, 0.1);
+}
+
+#moduleMenu > ul > li.active > a {
+ border-top: 3px solid rgba(255,255,255,0.8);
+ padding-top: 12px;
+}
+
+@media (max-width: 767px) {
+ #moduleMenu > ul > li.active > a {
+ padding: 10px 15px;
+ border-top: none;
+ border-left: 3px solid rgba(255,255,255,0.8);
+ }
+
+ .main-header .navbar .navbar-custom-menu .nav .dropdown-menu li a {
+ color: #333;
+ }
+ .main-header .navbar .navbar-custom-menu .nav .dropdown-menu li a:hover {
+ color: #FFF;
+ }
}
#timeRangePickerCntr .navbar-form {
@@ -534,34 +579,37 @@ body .login-box, body .register-box {
}
-.content .miao-chart {
- border: none;
- margin: 0;
+/* Misc */
+body .tooltip-inner {
+ max-width: 500px;
}
-.content .miao-chart .box .chart-entity-title {
- height: auto;
- margin: 0;
+.text-nowrap {
+ white-space: nowrap;
}
-.content .miao-chart .chart-entity-menu {
- display: block;
- top: 5px;
- right: 25px;
+.text-ellipsis,
+.label.text-ellipsis {
+ overflow:hidden;
+ text-overflow:ellipsis;
+ display: inline-block;
+ white-space: nowrap;
+ max-width: 100%;
}
-
-.content .miao-chart .box .chart-entity-menu {
- display: block;
- top: 5px;
- right: 25px;
- padding-right: 10px;
- border-right: 1px solid #f4f4f4;
+td.text-ellipsis {
+ display: table-cell;
}
-.content .miao-chart .box .chart-entity-drillDownPath .drillDownPath {
- position: static;
+.btn.btn-xs.sm {
+ font-size: 12px;
+ padding: 2px 6px;
}
-.content .miao-chart[data-miao-drilldown-depth='0'] .box .box-footer {
- display: none;
-}
+.noSelect {
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/classification/controller.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/classification/controller.js b/eagle-webservice/src/main/webapp/app/public/feature/classification/controller.js
new file mode 100644
index 0000000..ffb8c92
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/classification/controller.js
@@ -0,0 +1,269 @@
+/*
+ * 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 featureControllers = angular.module('featureControllers');
+ var feature = featureControllers.register("classification");
+
+ // ==============================================================
+ // = Function =
+ // ==============================================================
+
+ // =============================================================
+ // = Sensitivity =
+ // =============================================================
+ feature.navItem("sensitivity", "Classification", "user-secret");
+ feature.controller('sensitivity', function(PageConfig, Site, $scope, Application, Entities, UI) {
+ PageConfig.pageTitle = "Data Classification";
+ PageConfig.pageSubTitle = Site.current().tags.site;
+ $scope.ajaxId = Math.random();
+ $scope.viewConfig = Application.current().configObj.view;
+
+ if(!$scope.viewConfig) {
+ $.dialog({
+ title: "OPS",
+ content: "View configuration not defined in Application."
+ });
+ return;
+ }
+
+ // ===================== Function =====================
+ $scope.export = function() {
+ var _data = {};
+ UI.fieldConfirm({title: "Export Classification", confirm: false, size: "large"}, _data, [
+ {name: "Data", field: "data", type: "blob", rows: 20, optional: true, readonly: true}]
+ );
+
+ Entities.queryEntities($scope.viewConfig.service, {site: Site.current().tags.site})._promise.then(function(data) {
+ _data.data = JSON.stringify(data, null, "\t");
+ });
+ };
+
+ $scope.import = function() {
+ UI.fieldConfirm({title: "Import Classification", size: "large"}, {}, [
+ {name: "Data", field: "data", type: "blob", rows: 20, optional: true}
+ ], function(entity) {
+ var _list = common.parseJSON(entity.data, false);
+ if(!_list) {
+ return "Invalid JSON format";
+ }
+ if(!$.isArray(_list)) {
+ return "Not an array";
+ }
+ }).then(null, null, function(holder) {
+ Entities.updateEntity($scope.viewConfig.service, common.parseJSON(holder.entity.data, []), {timestamp: false})._promise.then(function() {
+ holder.closeFunc();
+ location.reload();
+ });
+ });
+ };
+
+ $scope.deleteAll = function() {
+ UI.deleteConfirm("All the Classification Data").then(null, null, function(holder) {
+ Entities.deleteEntities($scope.viewConfig.service, {site: Site.current().tags.site})._promise.then(function() {
+ holder.closeFunc();
+ location.reload();
+ });
+ });
+ };
+ });
+
+ // =============================================================
+ // = Sensitivity - Folder =
+ // =============================================================
+ feature.controller('sensitivityViewFolder', function(Site, $scope, $wrapState, Entities) {
+ $scope.path = $wrapState.param.path || "/";
+ $scope.pathUnitList = [];
+ $scope.items = [];
+
+ // Mark sensitivity
+ $scope._oriItem = {};
+ $scope._markItem = {};
+
+ // ======================= View =======================
+ // Path
+ function _refreshPathUnitList(_path) {
+ var _start,_current, _unitList = [];
+ _path = _path + (_path.match(/\/$/) ? "" : "/");
+ for(_current = _start = 0 ; _current < _path.length ; _current += 1) {
+ if(_path[_current] === "/") {
+ _unitList.push({
+ name: _path.substring(_start, _current + (_current === 0 ? 1 : 0)),
+ path: _path.substring(0, _current === 0 ? 1 : _current)
+ });
+ _start = _current + 1;
+ }
+ }
+ $scope.pathUnitList = _unitList;
+ }
+
+ // Item
+ $scope.updateItems = function(path) {
+ if(path) $scope.path = path;
+
+ $scope.items = Entities.query($scope.viewConfig.api, {site: Site.current().tags.site, path: $scope.path});
+ $scope.items._promise.success(function(data) {
+ Entities.dialog(data, function() {
+ if($scope.path !== "/") $scope.updateItems("/");
+ });
+ });
+ _refreshPathUnitList($scope.path);
+ };
+
+ $scope.getFileName = function(item) {
+ return (item.resource + "").replace(/^.*\//, "");
+ };
+
+ $scope.updateItems($scope.path);
+
+ // =================== Sensitivity ===================
+ $scope.markSensitivity = function(item) {
+ $scope._oriItem = item;
+ $scope._markItem = {
+ prefix: $scope.viewConfig.prefix,
+ tags: {
+ site: Site.current().tags.site
+ },
+ sensitivityType: ""
+ };
+ $scope._markItem.tags[$scope.viewConfig.keys[0]] = item.resource;
+ $("#sensitivityMDL").modal();
+ setTimeout(function() {
+ $("#sensitiveType").focus();
+ }, 500);
+ };
+ $scope.confirmUpateSensitivity = function() {
+ $scope._oriItem.sensitiveType = $scope._markItem.sensitivityType;
+ Entities.updateEntity($scope.viewConfig.service, $scope._markItem, {timestamp: false})._promise.success(function(data) {
+ Entities.dialog(data);
+ });
+ $("#sensitivityMDL").modal('hide');
+ };
+ $scope.unmarkSensitivity = function(item) {
+ $.dialog({
+ title: "Unmark Confirm",
+ content: "Do you want to remove the sensitivity mark on '" + item.resource + "'?",
+ confirm: true
+ }, function(ret) {
+ if(!ret) return;
+
+ var _cond = {site: Site.current().tags.site};
+ _cond[$scope.viewConfig.keys[0]] = item.resource;
+ Entities.deleteEntities($scope.viewConfig.service, _cond);
+
+ item.sensitiveType = null;
+ $scope.$apply();
+ });
+ };
+ });
+
+ // =============================================================
+ // = Sensitivity - Table =
+ // =============================================================
+ feature.controller('sensitivityViewTable', function(Site, $scope, Entities) {
+ $scope.table = null;
+
+ // Mark sensitivity
+ $scope._oriItem = {};
+ $scope._markItem = {};
+
+ // ======================= View =======================
+ var _fillAttr = function(list, key, target) {
+ list._promise.then(function() {
+ $.each(list, function(i, unit) {
+ unit[key] = unit[target];
+ });
+ });
+ };
+
+ $scope.databases = Entities.query($scope.viewConfig.api.database, {site: Site.current().tags.site});
+ _fillAttr($scope.databases, "database", $scope.viewConfig.mapping.database);
+
+ $scope.loadTables = function(database) {
+ if(database.tables) return;
+ var _qry = {
+ site: Site.current().tags.site
+ };
+ _qry[$scope.viewConfig.mapping.database] = database[$scope.viewConfig.mapping.database];
+ database.tables = Entities.query($scope.viewConfig.api.table, _qry);
+ _fillAttr(database.tables, "table", $scope.viewConfig.mapping.table);
+ _fillAttr(database.tables, "database", $scope.viewConfig.mapping.database);
+ };
+
+ $scope.loadColumns = function(database, table) {
+ $scope.table = table;
+
+ if(table.columns) return;
+ var _qry = {
+ site: Site.current().tags.site
+ };
+ _qry[$scope.viewConfig.mapping.database] = database[$scope.viewConfig.mapping.database];
+ _qry[$scope.viewConfig.mapping.table] = table[$scope.viewConfig.mapping.table];
+ table.columns = Entities.query($scope.viewConfig.api.column, _qry);
+ _fillAttr(table.columns, "column", $scope.viewConfig.mapping.column);
+ };
+
+ // =================== Sensitivity ===================
+ $scope.markSensitivity = function(item, event) {
+ if(event) event.stopPropagation();
+
+ $scope._oriItem = item;
+ $scope._markItem = {
+ prefix: $scope.viewConfig.prefix,
+ tags: {
+ site: Site.current().tags.site
+ },
+ sensitivityType: ""
+ };
+ $scope._markItem.tags[$scope.viewConfig.keys[0]] = item.resource;
+ $("#sensitivityMDL").modal();
+ setTimeout(function() {
+ $("#sensitiveType").focus();
+ }, 500);
+ };
+ $scope.confirmUpateSensitivity = function() {
+ $scope._oriItem.sensitiveType = $scope._markItem.sensitivityType;
+ Entities.updateEntity($scope.viewConfig.service, $scope._markItem, {timestamp: false})._promise.success(function(data) {
+ Entities.dialog(data);
+ });
+ $("#sensitivityMDL").modal('hide');
+ };
+ $scope.unmarkSensitivity = function(item, event) {
+ if(event) event.stopPropagation();
+
+ $.dialog({
+ title: "Unmark Confirm",
+ content: "Do you want to remove the sensitivity mark on '" + item.resource + "'?",
+ confirm: true
+ }, function(ret) {
+ if(!ret) return;
+
+ var _qry = {
+ site: Site.current().tags.site
+ };
+ _qry[$scope.viewConfig.keys[0]] = item.resource;
+ Entities.deleteEntities($scope.viewConfig.service, _qry);
+
+ item.sensitiveType = null;
+ $scope.$apply();
+ });
+ };
+ });
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity.html b/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity.html
new file mode 100644
index 0000000..41fb291
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity.html
@@ -0,0 +1,40 @@
+<!--
+ 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 with-border">
+ <i class="fa fa-folder-open"></i>
+ <h3 class="box-title ng-binding">{{Application.current().displayName}}</h3>
+ <div class="box-tools pull-right" ng-if="viewConfig">
+ <div class="btn-group">
+ <button type="button" class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown">
+ <span class="fa fa-wrench"></span>
+ </button>
+ <ul class="dropdown-menu" role="menu">
+ <li><a ng-click="import()"><span class="fa fa-cloud-upload"></span> Import</a></li>
+ <li><a ng-click="export()"><span class="fa fa-cloud-download"></span> Export</a></li>
+ <li class="divider"></li>
+ <li class="danger"><a ng-click="deleteAll()"><span class="fa fa-trash"></span> Delete All</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ <div class="box-body">
+ <ng-include ng-if="viewConfig" src="'public/feature/classification/page/sensitivity/' + viewConfig.type + '.html?_=' + ajaxId"></ng-include>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity/folder.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity/folder.html b/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity/folder.html
new file mode 100644
index 0000000..e7abd4f
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity/folder.html
@@ -0,0 +1,110 @@
+<!--
+ 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="classification_sensitivityViewFolder">
+ <ul class="list-inline path">
+ <li>Path:</li>
+ <li ng-repeat="unit in pathUnitList">
+ <a ng-click="updateItems(unit.path)" class="label bg-black">{{unit.name}}</a>
+ </li>
+ </ul>
+
+ <table class="table table-bordered">
+ <thead>
+ <tr>
+ <th width="15%">File Name</th>
+ <th width="10%">Owner</th>
+ <th width="10%">Group</th>
+ <th>Sensitivity Type</th>
+ <th width="10" ng-show="Auth.isRole('ROLE_ADMIN')"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-show="items._promise.$$state.status !== 1">
+ <td colspan="5">
+ <span class="fa fa-refresh fa-spin"> </span>
+ Loading...
+ </td>
+ </tr>
+ <tr ng-show="items._promise.$$state.status === 1 && !items.length">
+ <td colspan="5">
+ <span class="fa fa-exclamation-triangle"> </span>
+ Empty Folder
+ </td>
+ </tr>
+ <tr ng-repeat="item in items" ng-class="{warning : item.sensitiveType}">
+ <td>
+ <span ng-show="!item.isdir">
+ <span class="fa fa-file"> </span>
+ {{getFileName(item)}}
+ </span>
+ <a ng-show="item.isdir" ng-click="updateItems(item.resource)">
+ <span class="fa fa-folder"> </span>
+ {{getFileName(item)}}
+ </a>
+
+ <span class="pull-right" ng-show="item.childSensitiveTypes.length">
+ <span class="fa fa-dot-circle-o text-muted" uib-tooltip="Contain child sensitivity defination"> </span>
+ </span>
+ </td>
+ <td>{{item.owner}}</td>
+ <td>{{item.group}}</td>
+ <td>{{item.sensitiveType}}</td>
+ <td ng-show="Auth.isRole('ROLE_ADMIN')">
+ <button class="fa fa-eye btn btn-primary btn-xs" ng-click="markSensitivity(item)" ng-show="!item.sensitiveType"
+ uib-tooltip="Mark as sensitivity data" tooltip-animation="false" tooltip-placement="left"> </button>
+ <button class="fa fa-eye-slash btn btn-warning btn-xs" ng-click="unmarkSensitivity(item)" ng-show="item.sensitiveType"
+ uib-tooltip="Remove the sensitivity mark" tooltip-animation="false" tooltip-placement="left"> </button>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+
+ <!-- Modal: Create / Edit site -->
+ <div class="modal fade" id="sensitivityMDL" tabindex="-1" role="dialog">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">×</span>
+ </button>
+ <h4 class="modal-title">Mark Sensitivity Data</h4>
+ </div>
+ <div class="modal-body">
+ <div class="form-group">
+ <label>Resource</label>
+ <input type="text" readonly="readonly" class="form-control" ng-model="_markItem.tags.filedir" />
+ </div>
+ <div class="form-group">
+ <label>* Sensitivity Type</label>
+ <input type="text" class="form-control" ng-model="_markItem.sensitivityType" id="sensitiveType" />
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">
+ Close
+ </button>
+ <button type="button" class="btn btn-primary" ng-click="confirmUpateSensitivity()" ng-disabled="!_markItem.sensitivityType">
+ Update
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity/table.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity/table.html b/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity/table.html
new file mode 100644
index 0000000..13d5807
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/classification/page/sensitivity/table.html
@@ -0,0 +1,150 @@
+<!--
+ 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="classification_sensitivityViewTable">
+ <p ng-show="databases._promise.$$state.status !== 1">
+ <span class="fa fa-refresh fa-spin"> </span>
+ Loading...
+ </p>
+
+ <div ng-show="databases._promise.$$state.status === 1" class="row">
+ <div class="col-md-4">
+ <label>
+ Databases
+ ({{databases.length}})
+ </label>
+ <ul class="tree tree-bordered" style="max-height: 500px; overflow-y: auto;">
+ <li ng-repeat="db in databases">
+ <span class="tree-item box-clickable text-primary" ng-click="db.show = !db.show; loadTables(db);">
+ <span ng-class="{'text-warning' : db.sensitiveType}">
+ <span class="fa fa-database"> </span>
+ {{db.database}}
+ <span ng-show="db.tables._promise.$$state.status === 1">({{db.tables.length}})</span>
+
+ <span ng-show="Auth.isRole('ROLE_ADMIN')">
+ <a class="fa fa-eye text-muted hover" ng-click="markSensitivity(db, $event)" ng-show="!db.sensitiveType"
+ uib-tooltip="Mark as sensitivity data" tooltip-animation="false" tooltip-placement="right"></a>
+ <a class="fa fa-eye-slash text-muted hover" ng-click="unmarkSensitivity(db, $event)" ng-show="db.sensitiveType"
+ uib-tooltip="Remove the sensitivity mark" tooltip-animation="false" tooltip-placement="right"></a>
+ </span>
+
+ <span class="pull-right" ng-show="db.childSensitiveTypes.length">
+ <span class="fa fa-dot-circle-o" uib-tooltip="Contain child sensitivity defination" tooltip-placement="right" tooltip-append-to-body="true"> </span>
+ </span>
+ <span ng-show="db.sensitiveType" class="pull-right">[{{db.sensitiveType}}]</span>
+ </span>
+ </span>
+ <ul ng-show="db.show">
+ <li ng-show="db.tables._promise.$$state.status !== 1">
+ <span>
+ <span class="fa fa-refresh fa-spin"> </span>
+ Loading...
+ </span>
+ </li>
+ <li ng-repeat="tb in db.tables" ng-class="{active : tb === table}">
+ <span class="tree-item box-clickable text-primary" ng-click="loadColumns(db, tb)">
+ <span ng-class="{'text-warning' : tb.sensitiveType}">
+ <span class="fa fa-table"> </span>
+ {{tb.table}}
+
+ <span ng-show="Auth.isRole('ROLE_ADMIN')">
+ <a class="fa fa-eye text-muted hover" ng-click="markSensitivity(tb, $event)" ng-show="!tb.sensitiveType"
+ uib-tooltip="Mark as sensitivity data" tooltip-animation="false" tooltip-placement="right"></a>
+ <a class="fa fa-eye-slash text-muted hover" ng-click="unmarkSensitivity(tb, $event)" ng-show="tb.sensitiveType"
+ uib-tooltip="Remove the sensitivity mark" tooltip-animation="false" tooltip-placement="right"></a>
+ </span>
+
+ <span class="pull-right" ng-show="tb.childSensitiveTypes.length">
+ <span class="fa fa-dot-circle-o" uib-tooltip="Contain child sensitivity defination" tooltip-placement="right" tooltip-append-to-body="true"> </span>
+ </span>
+ <span ng-show="tb.sensitiveType" class="pull-right">[{{tb.sensitiveType}}]</span>
+ </span>
+ </span>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <div class="col-md-8">
+ <label ng-show="table">Route: {{table.database}} > {{table.table}}</label>
+ <p ng-show="table && table.columns._promise.$$state.status !== 1">
+ <span class="fa fa-refresh fa-spin"> </span>
+ Loading...
+ </p>
+ <div ng-show="table && table.columns._promise.$$state.status === 1">
+ <table class="table table-bordered">
+ <thead>
+ <tr>
+ <th width="40%">Column Name</th>
+ <th>Sensitivity Type</th>
+ <th width="10" ng-show="Auth.isRole('ROLE_ADMIN')"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="col in table.columns" ng-class="{warning : col.sensitiveType}">
+ <td>{{col.column}}</td>
+ <td>{{col.sensitiveType}}</td>
+ <td ng-show="Auth.isRole('ROLE_ADMIN')">
+ <button class="fa fa-eye btn btn-primary btn-xs" ng-click="markSensitivity(col)" ng-show="!col.sensitiveType"
+ uib-tooltip="Mark as sensitivity data" tooltip-animation="false" tooltip-placement="left"> </button>
+ <button class="fa fa-eye-slash btn btn-warning btn-xs" ng-click="unmarkSensitivity(col)" ng-show="col.sensitiveType"
+ uib-tooltip="Remove the sensitivity mark" tooltip-animation="false" tooltip-placement="left"> </button>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+
+
+
+
+
+
+ <!-- Modal: Create / Edit site -->
+ <div class="modal fade" id="sensitivityMDL" tabindex="-1" role="dialog">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">×</span>
+ </button>
+ <h4 class="modal-title">Mark Sensitivity Data</h4>
+ </div>
+ <div class="modal-body">
+ <div class="form-group">
+ <label>Resource</label>
+ <input type="text" readonly="readonly" class="form-control" ng-model="_markItem.tags[viewConfig.keys[0]]" />
+ </div>
+ <div class="form-group">
+ <label>* Sensitivity Type</label>
+ <input type="text" class="form-control" ng-model="_markItem.sensitivityType" id="sensitiveType" />
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">
+ Close
+ </button>
+ <button type="button" class="btn btn-primary" ng-click="confirmUpateSensitivity()" ng-disabled="!_markItem.sensitivityType">
+ Update
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
\ No newline at end of file
[4/9] incubator-eagle git commit: EAGLE-139 EAGLE-163 Eagle UI
Modularization and fix bugs in policy extensions
Posted by hd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/userProfile/controller.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/userProfile/controller.js b/eagle-webservice/src/main/webapp/app/public/feature/userProfile/controller.js
new file mode 100644
index 0000000..f048a85
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/userProfile/controller.js
@@ -0,0 +1,268 @@
+/*
+ * 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 featureControllers = angular.module('featureControllers');
+ var feature = featureControllers.register("userProfile");
+
+ // ==============================================================
+ // = Function =
+ // ==============================================================
+
+ // ==============================================================
+ // = User Profile =
+ // ==============================================================
+
+ // ======================== Profile List ========================
+ //feature.navItem("list", "User Profiles", "graduation-cap");
+ feature.controller('list', function(PageConfig, Site, $scope, $interval, Entities) {
+ PageConfig.pageSubTitle = Site.current().tags.site;
+
+ $scope.common = common;
+ $scope.algorithms = [];
+
+ // ======================================== Algorithms ========================================
+ $scope.algorithmEntity = {};
+ Entities.queryEntities("AlertDefinitionService", {site: Site.current().tags.site, dataSource: "userProfile"})._promise.then(function(data) {
+ $scope.algorithmEntity = common.getValueByPath(data, "obj[0]");
+ $scope.algorithmEntity.policy = common.parseJSON($scope.algorithmEntity.policyDef);
+ });
+
+ // ======================================= User profile =======================================
+ $scope.profileList = Entities.queryEntities("MLModelService", {site: Site.current().tags.site}, ["user", "algorithm", "content", "version"]);
+ $scope.profileList._promise.then(function() {
+ var _algorithms = {};
+ var _users = {};
+
+ // Map user
+ $.each($scope.profileList, function(i, unit) {
+ _algorithms[unit.tags.algorithm] = unit.tags.algorithm;
+ var _user = _users[unit.tags.user] = _users[unit.tags.user] || {user: unit.tags.user};
+ _user[unit.tags.algorithm] = {
+ version: unit.version
+ };
+
+ // DE
+ if(unit.tags.algorithm === "DE") {
+ var _statistics = common.parseJSON(unit.content);
+ _statistics = common.getValueByPath(_statistics, "statistics", []);
+ _user[unit.tags.algorithm].topCommands = $.map(common.array.top(_statistics, "mean"), function(command) {
+ return command.commandName;
+ });
+ }
+ });
+
+ // Map algorithms
+ $scope.algorithms = $.map(_algorithms, function(algorithm) {
+ return algorithm;
+ }).sort();
+
+ $scope.profileList.splice(0);
+ $scope.profileList.push.apply($scope.profileList, common.map.toArray(_users));
+ });
+
+ // =========================================== Task ===========================================
+ $scope.tasks = [];
+ function _loadTasks() {
+ var _tasks = Entities.queryEntities("ScheduleTaskService", {
+ site: Site.current().tags.site,
+ _pageSize: 100,
+ _duration: 1000 * 60 * 60 * 24 * 14,
+ __ETD: 1000 * 60 * 60 * 24
+ });
+ _tasks._promise.then(function() {
+ $scope.tasks.splice(0);
+ $scope.tasks.push.apply($scope.tasks, _tasks);
+
+ // Duration
+ $.each($scope.tasks, function(i, data) {
+ if(data.timestamp && data.updateTime) {
+ var _ms = (new moment(data.updateTime)).diff(new moment(data.timestamp));
+ var _d = moment.duration(_ms);
+ data._duration = Math.floor(_d.asHours()) + moment.utc(_ms).format(":mm:ss");
+ data.duration = _ms;
+ } else {
+ data._duration = "--";
+ }
+ });
+ });
+ }
+
+ $scope.runningTaskCount = function () {
+ return common.array.count($scope.tasks, "INITIALIZED", "status") +
+ common.array.count($scope.tasks, "PENDING", "status") +
+ common.array.count($scope.tasks, "EXECUTING", "status");
+ };
+
+ // Create task
+ $scope.updateTask = function() {
+ $.dialog({
+ title: "Confirm",
+ content: "Do you want to update now?",
+ confirm: true
+ }, function(ret) {
+ if(!ret) return;
+
+ var _entity = {
+ status: "INITIALIZED",
+ detail: "Newly created command",
+ tags: {
+ site: Site.current().tags.site,
+ type: "USER_PROFILE_TRAINING"
+ },
+ timestamp: +new Date()
+ };
+ Entities.updateEntity("ScheduleTaskService", _entity, {timestamp: false})._promise.success(function(data) {
+ if(!Entities.dialog(data)) {
+ _loadTasks();
+ }
+ });
+ });
+ };
+
+ // Show detail
+ $scope.showTaskDetail = function(task) {
+ var _content = $("<pre>").text(task.detail);
+
+ var $mdl = $.dialog({
+ title: "Detail",
+ content: _content
+ });
+
+ _content.click(function(e) {
+ if(!e.ctrlKey) return;
+
+ $.dialog({
+ title: "Confirm",
+ content: "Remove this task?",
+ confirm: true
+ }, function(ret) {
+ if(!ret) return;
+
+ $mdl.modal('hide');
+ Entities.deleteEntity("ScheduleTaskService", task)._promise.then(function() {
+ _loadTasks();
+ });
+ });
+ });
+ };
+
+ _loadTasks();
+ var _loadInterval = $interval(_loadTasks, app.time.refreshInterval);
+ $scope.$on('$destroy',function(){
+ $interval.cancel(_loadInterval);
+ });
+ });
+
+ // ======================= Profile Detail =======================
+ feature.controller('detail', function(PageConfig, Site, $scope, $wrapState, Entities) {
+ PageConfig.pageTitle = "User Profile";
+ PageConfig.pageSubTitle = Site.current().tags.site;
+ PageConfig
+ .addNavPath("User Profile", "/userProfile/list")
+ .addNavPath("Detail");
+
+ $scope.user = $wrapState.param.filter;
+
+ // User profile
+ $scope.profiles = {};
+ $scope.profileList = Entities.queryEntities("MLModelService", {site: Site.current().tags.site, user: $scope.user});
+ $scope.profileList._promise.then(function() {
+ $.each($scope.profileList, function(i, unit) {
+ unit._content = common.parseJSON(unit.content);
+ $scope.profiles[unit.tags.algorithm] = unit;
+ });
+
+ // DE
+ if($scope.profiles.DE) {
+ console.log($scope.profiles.DE);
+
+ $scope.profiles.DE._chart = {};
+
+ $scope.profiles.DE.estimates = {};
+ $.each($scope.profiles.DE._content, function(key, value) {
+ if(key !== "statistics") {
+ $scope.profiles.DE.estimates[key] = value;
+ }
+ });
+
+ var _meanList = [];
+ var _stddevList = [];
+
+ $.each($scope.profiles.DE._content.statistics, function(i, unit) {
+ _meanList[i] = {
+ x: unit.commandName,
+ y: unit.mean
+ };
+ _stddevList[i] = {
+ x: unit.commandName,
+ y: unit.stddev
+ };
+ });
+ $scope.profiles.DE._chart.series = [
+ {
+ key: "mean",
+ values: _meanList
+ },
+ {
+ key: "stddev",
+ values: _stddevList
+ }
+ ];
+
+ // Percentage table list
+ $scope.profiles.DE.meanList = [];
+ var _total = common.array.sum($scope.profiles.DE._content.statistics, "mean");
+ $.each($scope.profiles.DE._content.statistics, function(i, unit) {
+ $scope.profiles.DE.meanList.push({
+ command: unit.commandName,
+ percentage: unit.mean / _total
+ });
+ });
+ }
+
+ // EigenDecomposition
+ if($scope.profiles.EigenDecomposition && $scope.profiles.EigenDecomposition._content.principalComponents) {
+ $scope.profiles.EigenDecomposition._chart = {
+ series: [],
+ };
+
+ $.each($scope.profiles.EigenDecomposition._content.principalComponents, function(z, grp) {
+ var _line = [];
+ $.each(grp, function(x, y) {
+ _line.push([x,y,z]);
+ });
+
+ $scope.profiles.EigenDecomposition._chart.series.push({
+ data: _line
+ });
+ });
+ }
+ });
+
+ // UI
+ $scope.showRawData = function(content) {
+ $.dialog({
+ title: "Raw Data",
+ content: $("<pre>").text(content)
+ });
+ };
+ });
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/userProfile/page/detail.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/userProfile/page/detail.html b/eagle-webservice/src/main/webapp/app/public/feature/userProfile/page/detail.html
new file mode 100644
index 0000000..0f94e03
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/userProfile/page/detail.html
@@ -0,0 +1,87 @@
+<!--
+ 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 with-border">
+ <i class="fa fa-user"> </i>
+ <h3 class="box-title">
+ {{user}}
+ </h3>
+ </div>
+ <div class="box-body">
+ <div>
+ <div class="inline-group">
+ <dl><dt>User</dt><dd>{{user}}</dd></dl>
+ <dl><dt>Site</dt><dd>{{Site.current().tags.site}}</dd></dl>
+ </div>
+ <div class="inline-group">
+ <dl><dt>Other Info</dt><dd class="text-muted">N/A</dd></dl>
+ </div>
+ </div>
+
+ <div class="overlay" ng-hide="profileList._promise.$$state.status === 1;">
+ <span class="fa fa-refresh fa-spin"></span>
+ </div>
+ </div>
+</div>
+
+<!-- Analysis -->
+<div class="nav-tabs-custom">
+ <ul class="nav nav-tabs">
+ <li class="active">
+ <a href="[data-id='DE']" data-toggle="tab" ng-click=" currentTab='DE'">DE</a>
+ </li>
+ <li>
+ <a href="[data-id='EigenDecomposition']" data-toggle="tab" ng-click=" currentTab='EigenDecomposition'">EigenDecomposition</a>
+ </li>
+ <li class="pull-right">
+ <button class="btn btn-primary" ng-click="showRawData(currentTab === 'EigenDecomposition' ? profiles.EigenDecomposition.content : profiles.DE.content)">Raw Data</button>
+ </li>
+ </ul>
+ <div class="tab-content">
+ <div class="tab-pane active" data-id="DE">
+ <div class="row">
+ <div class="col-md-9">
+ <div nvd3="profiles.DE._chart.series" data-config="{chart: 'column', xType: 'text', height: 400}" class="nvd3-chart-cntr" height="400"></div>
+ <div class="inline-group text-center">
+ <dl ng-repeat="(key, value) in profiles.DE.estimates"><dt>{{key}}</dt><dd>{{value}}</dd></dl>
+ </div>
+ </div>
+
+ <div class="col-md-3">
+ <table class="table table-bordered">
+ <thead>
+ <tr>
+ <th>Command</th>
+ <th>Percentage</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="unit in profiles.DE.meanList">
+ <td>{{unit.command}}</td>
+ <td class="text-right">{{(unit.percentage*100).toFixed(2)}}%</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div><!-- /.tab-pane -->
+ <div class="tab-pane" data-id="EigenDecomposition">
+ <div line3d-chart height="400" data="profiles.EigenDecomposition._chart.series"> </div>
+ </div><!-- /.tab-pane -->
+ </div><!-- /.tab-content -->
+</div>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/feature/userProfile/page/list.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/feature/userProfile/page/list.html b/eagle-webservice/src/main/webapp/app/public/feature/userProfile/page/list.html
new file mode 100644
index 0000000..2f14479
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/feature/userProfile/page/list.html
@@ -0,0 +1,138 @@
+<!--
+ 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 with-border">
+ <i class="fa fa-list-alt"> </i>
+ <h3 class="box-title">
+ User Profiles
+ <small><a data-toggle="collapse" href="[data-id='algorithms']">Detail</a></small>
+ </h3>
+ <div class="pull-right">
+ <a class="label label-primary" ng-class="runningTaskCount() ? 'label-primary' : 'label-default'" data-toggle="modal" data-target="#taskMDL">Update</a>
+ </div>
+ </div>
+ <div class="box-body">
+ <!-- Algorithms -->
+ <div data-id="algorithms" class="collapse">
+ <table class="table table-bordered">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <td>Feature</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="algorithm in algorithmEntity.policy.algorithms">
+ <td>{{algorithm.name}}</td>
+ <td>{{algorithm.features}}</td>
+ </tr>
+ </tbody>
+ </table>
+ <hr/>
+ </div>
+
+ <!-- User Profile List -->
+ <p ng-show="profileList._promise.$$state.status !== 1">
+ <span class="fa fa-refresh fa-spin"> </span>
+ Loading...
+ </p>
+
+ <div sorttable source="profileList" ng-show="profileList._promise.$$state.status === 1">
+ <table class="table table-bordered" ng-non-bindable>
+ <thead>
+ <tr>
+ <th width="10%" sortpath="user">User</th>
+ <th>Most Predominat Feature</th>
+ <th width="10"></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <a href="#/userProfile/detail/{{item.user}}">{{item.user}}</a>
+ </td>
+ <td>
+ {{item.DE.topCommands.slice(0,3).join(", ")}}
+ </td>
+ <td>
+ <a href="#/userProfile/detail/{{item.user}}">Detail</a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+</div>
+
+<!-- Modal: User profile Schedule Task -->
+<div class="modal fade" id="taskMDL" tabindex="-1" role="dialog">
+ <div class="modal-dialog modal-lg" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">×</span>
+ </button>
+ <h4 class="modal-title">Training History</h4>
+ </div>
+ <div class="modal-body">
+ <div sorttable source="tasks">
+ <table class="table table-bordered" ng-non-bindable>
+ <thead>
+ <tr>
+ <th sortpath="tags.type">Command</th>
+ <th sortpath="timestamp">Start Time</th>
+ <th sortpath="updateTime">Update Time</th>
+ <th sortpath="duration">Duration</th>
+ <th sortpath="status">Status</th>
+ <th width="10"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{{item.tags.type}}</td>
+ <td>{{common.format.date(item.timestamp) || "--"}}</td>
+ <td>{{common.format.date(item.updateTime) || "--"}}</td>
+ <td>{{item._duration}}</td>
+ <td class="text-nowrap">
+ <span class="fa fa-hourglass-start text-muted" ng-show="item.status === 'INITIALIZED'"></span>
+ <span class="fa fa-hourglass-half text-info" ng-show="item.status === 'PENDING'"></span>
+ <span class="fa fa-circle-o-notch text-primary" ng-show="item.status === 'EXECUTING'"></span>
+ <span class="fa fa-check-circle text-success" ng-show="item.status === 'SUCCEEDED'"></span>
+ <span class="fa fa-exclamation-circle text-danger" ng-show="item.status === 'FAILED'"></span>
+ <span class="fa fa-ban text-muted" ng-show="item.status === 'CANCELED'"></span>
+ {{item.status}}
+ </td>
+ <td>
+ <a ng-click="_parent.showTaskDetail(item)">Detail</a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-primary pull-left" ng-click="updateTask()" ng-show="Auth.isRole('ROLE_ADMIN')">
+ Update Now
+ </button>
+ <button type="button" class="btn btn-default" data-dismiss="modal">
+ Close
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/images/favicon_white.png
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/images/favicon_white.png b/eagle-webservice/src/main/webapp/app/public/images/favicon_white.png
new file mode 100644
index 0000000..9879e92
Binary files /dev/null and b/eagle-webservice/src/main/webapp/app/public/images/favicon_white.png differ
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/app.config.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/app.config.js b/eagle-webservice/src/main/webapp/app/public/js/app.config.js
index f18b846..1e6fd79 100644
--- a/eagle-webservice/src/main/webapp/app/public/js/app.config.js
+++ b/eagle-webservice/src/main/webapp/app/public/js/app.config.js
@@ -1,77 +1,104 @@
-/*
- * 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';
-
- app.config = {
- // ============================================================================
- // = URLs =
- // ============================================================================
- urls: {
- HOST: '..',
-
- updateEntity: 'rest/entities?serviceName=${serviceName}',
- queryEntity: 'rest/entities/rowkey?serviceName=${serviceName}&value=${encodedRowkey}',
- queryEntities: 'rest/list?query=${serviceName}[${condition}]{${values}}&pageSize=100000',
- deleteEntity: 'rest/entities/delete?serviceName=${serviceName}&byId=true',
- deleteEntities: 'rest/entities?query=${serviceName}[${condition}]{*}&pageSize=100000',
-
- queryGroup: 'rest/list?query=${serviceName}[${condition}]<${groupBy}>{${values}}&pageSize=100000',
- querySeries: 'rest/list?query=${serviceName}[${condition}]<${groupBy}>{${values}}&pageSize=100000&timeSeries=true&intervalmin=${intervalmin}',
-
- query: 'rest/',
-
- userProfile: 'rest/authentication',
- logout: 'logout',
- },
-
- // ============================================================================
- // = Data Sources =
- // ============================================================================
- dataSource: {
- uiInvisibleList: ["userProfile"],
- },
- };
-
- // ============================================================================
- // = URLs =
- // ============================================================================
- app.getURL = function(name, kvs) {
- var _host = localStorage.getItem("HOST") || app.config.urls.HOST;
- var _path = app.config.urls[name];
- if(!_path) throw "URL:'" + name + "' not exist!";
- var _url = (_host ? _host + "/" : '') + _path;
- if(kvs !== undefined) {
- _url = common.template(_url, kvs);
- }
- return _url;
- };
-
- app._Host = function(host) {
- if(host) {
- localStorage.setItem("HOST", host);
- return app;
- }
- return localStorage.getItem("HOST");
- };
- app._Host.clear = function() {
- localStorage.removeItem("HOST");
- };
- app._Host.sample = "http://localhost:9099/eagle-service";
+/*
+ * 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';
+
+ app.config = {
+ // ============================================================================
+ // = URLs =
+ // ============================================================================
+ urls: {
+ HOST: '..',
+
+ updateEntity: 'rest/entities?serviceName=${serviceName}',
+ queryEntity: 'rest/entities/rowkey?serviceName=${serviceName}&value=${encodedRowkey}',
+ queryEntities: 'rest/list?query=${serviceName}[${condition}]{${values}}&pageSize=100000',
+ deleteEntity: 'rest/entities/delete?serviceName=${serviceName}&byId=true',
+ deleteEntities: 'rest/entities?query=${serviceName}[${condition}]{*}&pageSize=100000',
+
+ queryGroup: 'rest/list?query=${serviceName}[${condition}]<${groupBy}>{${values}}&pageSize=100000',
+ querySeries: 'rest/list?query=${serviceName}[${condition}]<${groupBy}>{${values}}&pageSize=100000&timeSeries=true&intervalmin=${intervalmin}',
+
+ query: 'rest/',
+
+ userProfile: 'rest/authentication',
+ logout: 'logout',
+
+ DELETE_HOOK: {
+ FeatureDescService: 'rest/module/feature?feature=${feature}',
+ ApplicationDescService: 'rest/module/application?application=${application}',
+ SiteDescService: 'rest/module/site?site=${site}'
+ },
+ UPDATE_HOOK: {
+ SiteDescService: 'rest/module/siteApplication'
+ }
+ },
+ };
+
+ // ============================================================================
+ // = URLs =
+ // ============================================================================
+ app.getURL = function(name, kvs) {
+ var _host = localStorage.getItem("HOST") || app.config.urls.HOST;
+ var _path = app.config.urls[name];
+ if(!_path) throw "URL:'" + name + "' not exist!";
+ var _url = (_host ? _host + "/" : '') + _path;
+ if(kvs !== undefined) {
+ _url = common.template(_url, kvs);
+ }
+ return _url;
+ };
+
+ function getHookURL(hookType, serviceName) {
+ var _path = app.config.urls[hookType][serviceName];
+ if(!_path) return null;
+
+ var _host = localStorage.getItem("HOST") || app.config.urls.HOST;
+ var _url = (_host ? _host + "/" : '') + _path;
+ return _url;
+ }
+
+ /***
+ * Eagle support delete function to process special entity delete. Which will delete all the relative entity.
+ * @param serviceName
+ */
+ app.getDeleteURL = function(serviceName) {
+ return getHookURL('DELETE_HOOK', serviceName);
+ };
+
+ /***
+ * Eagle support update function to process special entity update. Which will update all the relative entity.
+ * @param serviceName
+ */
+ app.getUpdateURL = function(serviceName) {
+ return getHookURL('UPDATE_HOOK', serviceName);
+ };
+
+ app._Host = function(host) {
+ if(host) {
+ localStorage.setItem("HOST", host);
+ return app;
+ }
+ return localStorage.getItem("HOST");
+ };
+ app._Host.clear = function() {
+ localStorage.removeItem("HOST");
+ };
+ app._Host.sample = "http://localhost:9099/eagle-service";
})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/app.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/app.js b/eagle-webservice/src/main/webapp/app/public/js/app.js
index 777844d..e9dfb2a 100644
--- a/eagle-webservice/src/main/webapp/app/public/js/app.js
+++ b/eagle-webservice/src/main/webapp/app/public/js/app.js
@@ -18,693 +18,467 @@
var app = {};
-/* App Module */
-var eagleApp = angular.module('eagleApp', ['ngRoute', 'ngCookies', 'damControllers']);
-
-eagleApp.config(function($routeProvider) {
+(function() {
'use strict';
- $routeProvider.when('/dam/summary', {
- templateUrl : 'partials/dam/summary.html',
- controller : 'summaryCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
-
- // Authorization
- }).when('/dam/login', {
- templateUrl : 'partials/dam/login.html',
- controller : 'authLoginCtrl',
- access: {skipCheck: true},
-
- // Policy
- }).when('/dam/policyList', {
- templateUrl : 'partials/dam/policyList.html',
- controller : 'policyListCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
- }).when('/dam/policyList/:dataSource', {
- templateUrl : 'partials/dam/policyList.html',
- controller : 'policyListCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
- }).when('/dam/policyDetail/', {
- templateUrl : 'partials/dam/policyDetail.html',
- controller : 'policyDetailCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
- }).when('/dam/policyDetail/:encodedRowkey', {
- templateUrl : 'partials/dam/policyDetail.html',
- controller : 'policyDetailCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
- }).when('/dam/policyEdit/:encodedRowkey', {
- templateUrl : 'partials/dam/policyEdit.html',
- controller : 'policyEditCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
- }).when('/dam/policyCreate/', {
- templateUrl : 'partials/dam/policyEdit.html',
- controller : 'policyCreateCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
-
- // Alert
- }).when('/dam/alertList', {
- templateUrl : 'partials/dam/alertList.html',
- controller : 'alertListCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
- }).when('/dam/alertList/:dataSource', {
- templateUrl : 'partials/dam/alertList.html',
- controller : 'alertListCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
- }).when('/dam/alertDetail/:encodedRowkey', {
- templateUrl : 'partials/dam/alertDetail.html',
- controller : 'alertDetailCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
-
- // Stream
- }).when('/dam/streamList', {
- templateUrl : 'partials/dam/streamList.html',
- controller : 'streamListCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
-
- // Site
- }).when('/dam/siteList', {
- templateUrl : 'partials/dam/siteList.html',
- controller : 'siteListCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
- access: {roles: ["ROLE_ADMIN"]},
-
- // Sensitivity
- }).when('/dam/sensitivitySummary', {
- templateUrl : 'partials/dam/sensitivitySummary.html',
- controller : 'sensitivitySummaryCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
- }).when('/dam/sensitivity/:dataSrc', {
- templateUrl : 'partials/dam/sensitivity.html',
- controller : 'sensitivityCtrl',
- reloadOnSearch: false,
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
-
- // User Profile
- }).when('/dam/userProfileList', {
- templateUrl : 'partials/dam/userProfileList.html',
- controller : 'userProfileListCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
- }).when('/dam/userProfileDetail/:user', {
- templateUrl : 'partials/dam/userProfileDetail.html',
- controller : 'userProfileDetailCtrl',
- resolve: {
- site: function(Site) {return Site._promise();},
- auth: function(Authorization) {return Authorization._promise();},
- },
-
- }).otherwise({
- redirectTo : '/dam/summary'
+ /* App Module */
+ var eagleApp = angular.module('eagleApp', ['ngRoute', 'ngAnimate', 'ui.router', 'eagleControllers', 'featureControllers', 'eagle.service']);
+
+ // ======================================================================================
+ // = Feature Module =
+ // ======================================================================================
+ var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
+ var FN_ARG_SPLIT = /,/;
+ var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
+ var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
+
+ var featureControllers = angular.module('featureControllers', ['ui.bootstrap', 'eagle.components']);
+ var featureControllerCustomizeHtmlTemplate = {};
+ var featureControllerProvider;
+ var featureProvider;
+
+ featureControllers.config(function ($controllerProvider, $provide) {
+ featureControllerProvider = $controllerProvider;
+ featureProvider = $provide;
});
-});
-
-eagleApp.service('globalContent', function(Entities, $rootScope, $route, $location) {
- 'use strict';
-
- var content = {
- pageTitle: "",
- pageSubTitle: "",
- pageList: [],
- navPath: [],
- navMapping: {},
-
- hideSite: false,
- lockSite: false,
- dataSrcList: [],
+ featureControllers.service("Feature", function($wrapState, PageConfig, ConfigPageConfig, FeaturePageConfig) {
+ var _features = {};
+ var _services = {};
- setConfig: function(config) {
- // Clean up
- content.navPath = [];
-
- // Fill configuration
- $.extend(content, config);
- },
- };
-
- return content;
-});
-
-// Site
-eagleApp.service('Site', function(Authorization, Entities, $rootScope, $route, $location, $q) {
- 'use strict';
-
- var _currentSite;
- var content = {};
-
- content.list = [];
- content.list.set = {};
- content.dataSrcList = [];
-
- content.current = function(site) {
- if(site) {
- var _prev = _currentSite;
- _currentSite = site;
-
- // Broadcast if site update
- if(!_prev || _prev.name !== _currentSite.name) {
- if(sessionStorage) {
- sessionStorage.setItem("site", _currentSite.name);
- }
+ var Feature = function(name, version) {
+ this.name = name;
+ this.version = version;
+ this.features = {};
+ };
- if(!content.hideSite) $route.reload();
+ /***
+ * Inner function. Replace the dependency of constructor.
+ * @param constructor
+ * @private
+ */
+ Feature.prototype._replaceDependencies = function(constructor) {
+ var i, srvName;
+ var _constructor, _$inject;
+ var fnText, argDecl;
+
+ if($.isArray(constructor)) {
+ _constructor = constructor[constructor.length - 1];
+ _$inject = constructor.slice(0, -1);
+ } else if(constructor.$inject) {
+ _constructor = constructor;
+ _$inject = constructor.$inject;
+ } else {
+ _$inject = [];
+ _constructor = constructor;
+ fnText = constructor.toString().replace(STRIP_COMMENTS, '');
+ argDecl = fnText.match(FN_ARGS);
+ $.each(argDecl[1].split(FN_ARG_SPLIT), function(i, arg) {
+ arg.replace(FN_ARG, function(all, underscore, name) {
+ _$inject.push(name);
+ });
+ });
}
- }
- return _currentSite;
- };
- content.find = function(siteName) {
- return common.array.find(siteName, content.list, "name");
- };
- content.url = function(site, url) {
- if(arguments.length == 1) {
- url = site;
- } else {
- content.current(site);
- }
- $location.url(url);
+ _constructor.$inject = _$inject;
- if ($rootScope.$$phase != '$apply' && $rootScope.$$phase != '$digest') {
- $rootScope.$apply();
- }
- };
-
- var _promise;
- content.refresh = function() {
- content.list = [];
- content.list.set = {};
-
- content.dataSrcList = Entities.queryEntities("AlertDataSourceService", '');
- content.dataSrcList._promise.success(function() {
- $.each(content.dataSrcList, function(i, dataSrc) {
- var _site = content.list.set[dataSrc.tags.site];
- if(!_site) {
- _site = content.list.set[dataSrc.tags.site] = {
- name: dataSrc.tags.site,
- dataSrcList: []
- };
- _site.dataSrcList.find = function(dataSrcName) {
- return common.array.find(dataSrcName, _site.dataSrcList, "tags.dataSource");
- };
- content.list.push(_site);
- }
- _site.dataSrcList.push(dataSrc);
+ for(i = 0 ; i < _$inject.length ; i += 1) {
+ srvName = _$inject[i];
+ _$inject[i] = this.features[srvName] || _$inject[i];
+ }
- // UI visible check
- if($.inArray(dataSrc.tags.dataSource, app.config.dataSource.uiInvisibleList) !== -1) {
- dataSrc.hide = true;
- }
- });
+ return _constructor;
+ };
- if(sessionStorage && content.find(sessionStorage.getItem("site"))) {
- content.current(content.find(sessionStorage.getItem("site")));
+ /***
+ * Register a common service for feature usage. Common service will share between the feature. If you are coding customize feature, use 'Feature.service' is the better way.
+ * @param name
+ * @param constructor
+ */
+ Feature.prototype.commonService = function(name, constructor) {
+ if(!_services[name]) {
+ featureProvider.service(name, constructor);
+ _services[name] = this.name;
} else {
- content.current(content.list[0]);
+ throw "Service '" + name + "' has already be registered by feature '" + _services[name] + "'";
}
- });
+ };
- _promise = content.dataSrcList._promise;
- return _promise;
- };
+ /***
+ * Register a service for feature usage.
+ * @param name
+ * @param constructor
+ */
+ Feature.prototype.service = function(name, constructor) {
+ var _serviceName;
+ if(!this.features[name]) {
+ _serviceName = "__FEATURE_" + this.name + "_" + name;
+ featureProvider.service(_serviceName, this._replaceDependencies(constructor));
+ this.features[name] = _serviceName;
+ } else {
+ console.warn("Service '" + name + "' has already be registered.");
+ }
+ };
- content._promise = function() {
- if(!_promise) {
- content.refresh();
- }
- return _promise;
- };
+ /***
+ * Create an navigation item in left navigation bar
+ * @param path
+ * @param title
+ * @param icon use Font Awesome. Needn't with 'fa fa-'.
+ */
+ Feature.prototype.navItem = function(path, title, icon) {
+ title = title || path;
+ icon = icon || "question";
+
+ FeaturePageConfig.addNavItem(this.name, {
+ icon: icon,
+ title: title,
+ url: "#/" + this.name + "/" + path
+ });
+ };
- return content;
-});
+ /***
+ * Register a controller.
+ * @param name
+ * @param constructor
+ */
+ Feature.prototype.controller = function(name, constructor, htmlTemplatePath) {
+ var _name = this.name + "_" + name;
+
+ // Replace feature registered service
+ constructor = this._replaceDependencies(constructor);
+
+ // Register controller
+ featureControllerProvider.register(_name, constructor);
+ if(htmlTemplatePath) {
+ featureControllerCustomizeHtmlTemplate[_name] = htmlTemplatePath;
+ }
-// Authorization
-eagleApp.service('Authorization', function($http, $location, $cookies) {
- 'use strict';
+ return _name;
+ };
- $http.defaults.withCredentials = true;
-
- var _path = "";
- var _userProfile = null;
-
- var content = {
- isLogin: true, // Status mark. Work for UI status check, changed when eagle api return 403 authorization failure.
- needLogin: function() {
- _path = _path || $location.path();
- content.isLogin = false;
- $location.path("/dam/login");
- },
- login: function(username, password) {
- var _hash = btoa(username + ':' + password);
- return $http({
- url : app.getURL('userProfile'),
- method : "GET",
- headers: {
- 'Authorization': "Basic " + _hash
- }
- }).then(function() {
- content.isLogin = true;
- return true;
- }, function() {
- return false;
- });
- },
- logout: function() {
- $http({
- url : app.getURL('logout'),
- method : "GET",
- });
- },
- path: function(path) {
- if(typeof path === "string") {
- _path = path;
- } else if(path === true) {
- $location.path(_path || "");
- _path = "";
+ /***
+ * Register a configuration controller for admin usage.
+ * @param name
+ * @param constructor
+ */
+ Feature.prototype.configController = function(name, constructor, htmlTemplatePath) {
+ var _name = "config_" + this.name + "_" + name;
+
+ // Replace feature registered service
+ constructor = this._replaceDependencies(constructor);
+
+ // Register controller
+ featureControllerProvider.register(_name, constructor);
+ if(htmlTemplatePath) {
+ featureControllerCustomizeHtmlTemplate[_name] = htmlTemplatePath;
}
- },
- };
-
- var _promise;
- content.userProfile = {};
- content.isRole = function(role) {
- if(!content.userProfile.roles) return null;
-
- return content.userProfile.roles[role] === true;
- };
-
- content.refresh = function() {
- _promise = $http({
- url : app.getURL('userProfile'),
- method : "GET",
- }).then(function(data) {
- content.userProfile = data.data;
-
- // Role
- content.userProfile.roles = {};
- $.each(content.userProfile.authorities, function(i, role) {
- content.userProfile.roles[role.authority] = true;
- });
- });
- return _promise;
- };
- content._promise = function() {
- if(!_promise) {
- content.refresh();
- }
- return _promise;
- };
+ return _name;
+ };
- return content;
-});
+ /***
+ * Create an navigation item in left navigation bar for admin configuraion page
+ * @param path
+ * @param title
+ * @param icon use Font Awesome. Needn't with 'fa fa-'.
+ */
+ Feature.prototype.configNavItem = function(path, title, icon) {
+ title = title || path;
+ icon = icon || "question";
+
+ ConfigPageConfig.addNavItem(this.name, {
+ icon: icon,
+ title: title,
+ url: "#/config/" + this.name + "/" + path
+ });
+ };
-eagleApp.service('Entities', function($http, $q, $rootScope, $location, Authorization) {
- 'use strict';
+ // Register
+ featureControllers.register = Feature.register = function(featureName) {
+ _features[featureName] = _features[featureName] || new Feature(featureName);
+ return _features[featureName];
+ };
- // Query
- function _query(name, kvs) {
- kvs = kvs || {};
- var _list = [];
- var _condition = kvs._condition || {};
- var _addtionalCondition = _condition.additionalCondition || {};
- var _startTime, _endTime;
- var _startTimeStr, _endTimeStr;
-
- // Initial
- // > Condition
- delete kvs._condition;
- if(_condition) {
- kvs.condition = _condition.condition;
- }
+ // Page go
+ Feature.go = function(feature, page, filter) {
+ if(!filter) {
+ $wrapState.go("page", {
+ feature: feature,
+ page: page
+ }, 2);
+ } else {
+ $wrapState.go("pageFilter", {
+ feature: feature,
+ page: page,
+ filter: filter
+ }, 2);
+ }
+ };
- // > Values
- if(!kvs.values) {
- kvs.values = "*";
- } else if($.isArray(kvs.values)) {
- kvs.values = $.map(kvs.values, function(field) {
- return (field[0] === "@" ? '' : '@') + field;
- }).join(",");
- }
+ return Feature;
+ });
- var _url = app.getURL(name, kvs);
+ // ======================================================================================
+ // = Router config =
+ // ======================================================================================
+ eagleApp.config(function ($stateProvider, $urlRouterProvider) {
+ // Resolve
+ function _resolve(config) {
+ config = config || {};
- // Fill special parameters
- // > Query by time duration
- if(_addtionalCondition._duration) {
- _endTime = app.time.now();
- _startTime = _endTime.clone().subtract(_addtionalCondition._duration, "ms");
+ var resolve = {
+ Site: function (Site) {
+ return Site._promise();
+ },
+ Authorization: function (Authorization) {
+ if(!config.roleType) {
+ return Authorization._promise();
+ } else {
+ return Authorization.rolePromise(config.roleType);
+ }
+ },
+ Application: function (Application) {
+ return Application._promise();
+ }
+ };
+
+ if(config.featureCheck) {
+ resolve._navigationCheck = function($q, $wrapState, Site, Application) {
+ var _deferred = $q.defer();
+
+ $q.all(Site._promise(), Application._promise()).then(function() {
+ var _match, i, tmpApp;
+ var _site = Site.current();
+ var _app = Application.current();
+
+ // Check application
+ if(_site && (
+ !_app ||
+ !_site.applicationList.set[_app.tags.application] ||
+ !_site.applicationList.set[_app.tags.application].enabled
+ )
+ ) {
+ _match = false;
+
+ for(i = 0 ; i < _site.applicationGroupList.length ; i += 1) {
+ tmpApp = _site.applicationGroupList[i].enabledList[0];
+ if(tmpApp) {
+ _app = Application.current(tmpApp);
+ _match = true;
+ break;
+ }
+ }
+
+ if(!_match) {
+ _app = null;
+ Application.current(null);
+ }
+ }
+ }).finally(function() {
+ _deferred.resolve();
+ });
- // Debug usage. Extend more time duration for end time
- if(_addtionalCondition.__ETD) {
- _endTime.add(_addtionalCondition.__ETD, "ms");
+ return _deferred.promise;
+ };
}
- _addtionalCondition._startTime = _startTime;
- _addtionalCondition._endTime = _endTime;
-
- _startTimeStr = _startTime.format("YYYY-MM-DD HH:mm:ss");
- _endTimeStr = _endTime.clone().add(1, "s").format("YYYY-MM-DD HH:mm:ss");
+ return resolve;
+ }
- _url += "&startTime=" + _startTimeStr + "&endTime=" + _endTimeStr;
- } else if(_addtionalCondition._startTime && _addtionalCondition._endTime) {
- _startTimeStr = _addtionalCondition._startTime.format("YYYY-MM-DD HH:mm:ss");
- _endTimeStr = _addtionalCondition._endTime.clone().add(1, "s").format("YYYY-MM-DD HH:mm:ss");
+ // Router
+ var _featureBase = {
+ templateUrl: function ($stateParams) {
+ var _htmlTemplate = featureControllerCustomizeHtmlTemplate[$stateParams.feature + "_" + $stateParams.page];
+ return "public/feature/" + $stateParams.feature + "/page/" + (_htmlTemplate || $stateParams.page) + ".html?_=" + Math.random();
+ },
+ controllerProvider: function ($stateParams) {
+ return $stateParams.feature + "_" + $stateParams.page;
+ },
+ resolve: _resolve({featureCheck: true}),
+ pageConfig: "FeaturePageConfig"
+ };
- _url += "&startTime=" + _startTimeStr + "&endTime=" + _endTimeStr;
- }
+ $urlRouterProvider.otherwise("/landing");
+ $stateProvider
+ // =================== Landing ===================
+ .state('landing', {
+ url: "/landing",
+ templateUrl: "partials/landing.html?_=" + Math.random(),
+ controller: "landingCtrl",
+ resolve: _resolve({featureCheck: true})
+ })
+
+ // ================ Authorization ================
+ .state('login', {
+ url: "/login",
+ templateUrl: "partials/login.html?_=" + Math.random(),
+ controller: "authLoginCtrl",
+ access: {skipCheck: true}
+ })
+
+ // ================ Configuration ================
+ // Site
+ .state('configSite', {
+ url: "/config/site",
+ templateUrl: "partials/config/site.html?_=" + Math.random(),
+ controller: "configSiteCtrl",
+ pageConfig: "ConfigPageConfig",
+ resolve: _resolve({roleType: 'ROLE_ADMIN'})
+ })
+
+ // Application
+ .state('configApplication', {
+ url: "/config/application",
+ templateUrl: "partials/config/application.html?_=" + Math.random(),
+ controller: "configApplicationCtrl",
+ pageConfig: "ConfigPageConfig",
+ resolve: _resolve({roleType: 'ROLE_ADMIN'})
+ })
+
+ // Feature
+ .state('configFeature', {
+ url: "/config/feature",
+ templateUrl: "partials/config/feature.html?_=" + Math.random(),
+ controller: "configFeatureCtrl",
+ pageConfig: "ConfigPageConfig",
+ resolve: _resolve({roleType: 'ROLE_ADMIN'})
+ })
+
+ // Feature configuration page
+ .state('configFeatureDetail', $.extend({url: "/config/:feature/:page"}, {
+ templateUrl: function ($stateParams) {
+ var _htmlTemplate = featureControllerCustomizeHtmlTemplate[$stateParams.feature + "_" + $stateParams.page];
+ return "public/feature/" + $stateParams.feature + "/page/" + (_htmlTemplate || $stateParams.page) + ".html?_=" + Math.random();
+ },
+ controllerProvider: function ($stateParams) {
+ return "config_" + $stateParams.feature + "_" + $stateParams.page;
+ },
+ pageConfig: "ConfigPageConfig",
+ resolve: _resolve({roleType: 'ROLE_ADMIN'})
+ }))
+
+ // =================== Feature ===================
+ // Dynamic feature page
+ .state('page', $.extend({url: "/:feature/:page"}, _featureBase))
+ .state('pageFilter', $.extend({url: "/:feature/:page/:filter"}, _featureBase))
+ ;
+ });
- // > Query contains metric name
- if(_addtionalCondition._metricName) {
- _url += "&metricName=" + _addtionalCondition._metricName;
- }
+ eagleApp.filter('parseJSON', function () {
+ return function (input, defaultVal) {
+ return common.parseJSON(input, defaultVal);
+ };
+ });
- // > Customize page size
- if(_addtionalCondition._pageSize) {
- _url = _url.replace(/pageSize=\d+/, "pageSize=" + _addtionalCondition._pageSize);
- }
+ eagleApp.filter('split', function () {
+ return function (input, regex) {
+ return input.split(regex);
+ };
+ });
- // AJAX
- var canceler = $q.defer();
- _list._promise = $http.get(_url, {timeout: canceler.promise}).success(function(data) {
- _list.push.apply(_list, data.obj);
- });
- _list._promise.abort = function() {
- canceler.resolve();
+ eagleApp.filter('reverse', function () {
+ return function (items) {
+ return items.slice().reverse();
};
+ });
- _list._promise.then(function() {}, function(data) {
- if(data.status === 403) {
- Authorization.needLogin();
+ // ======================================================================================
+ // = Main Controller =
+ // ======================================================================================
+ eagleApp.controller('MainCtrl', function ($scope, $wrapState, $http, $injector, PageConfig, FeaturePageConfig, Site, Authorization, Entities, nvd3, Application, Feature, UI) {
+ window.site = $scope.Site = Site;
+ window.auth = $scope.Auth = Authorization;
+ window.entities = $scope.Entities = Entities;
+ window.application = $scope.Application = Application;
+ window.pageConfig = $scope.PageConfig = PageConfig;
+ window.featurePageConfig = $scope.FeaturePageConfig = FeaturePageConfig;
+ window.feature = $scope.Feature = Feature;
+ window.ui = $scope.UI = UI;
+ window.nvd3 = nvd3;
+ $scope.app = app;
+ $scope.common = common;
+
+ Object.defineProperty(window, "scope",{
+ get: function() {
+ return angular.element("[ui-view]").scope();
}
});
- return _list;
- }
- function _post(url, entities) {
- var _list = [];
- _list._promise = $http({
- method: 'POST',
- url: url,
- headers: {
- "Content-Type": "application/json"
- },
- data: entities
- }).success(function(data) {
- _list.push.apply(_list, data.obj);
- });
- return _list;
- }
- function _delete(url) {
- var _list = [];
- _list._promise = $http({
- method: 'DELETE',
- url: url,
- headers: {
- "Content-Type": "application/json"
- },
- }).success(function(data) {
- _list.push.apply(_list, data.obj);
- });
- return _list;
- }
- function ParseCondition(condition) {
- var _this = this;
- _this.condition = "";
- _this.additionalCondition = {};
-
- if(typeof condition === "string") {
- _this.condition = condition;
- } else {
- _this.condition = $.map(condition, function(value, key) {
- if(!key.match(/^_/)) {
- if(value === undefined || value === null) {
- return '@' + key + '=~".*"';
- } else {
- return '@' + key + '="' + value + '"';
- }
- } else {
- _this.additionalCondition[key] = value;
- return null;
- }
- }).join(" AND ");
- }
- return _this;
- }
+ // Clean up
+ $scope.$on('$stateChangeStart', function (event, next, nextParam, current, currentParam) {
+ console.log("[Switch] current ->", current, currentParam);
+ console.log("[Switch] next ->", next, nextParam);
+ // Page initialization
+ PageConfig.reset();
- var pkg = {
- _query: _query,
- _post: _post,
-
- updateEntity: function(serviceName, entities, config) {
- config = config || {};
- if(!$.isArray(entities)) entities = [entities];
+ // Dynamic navigation list
+ if(next.pageConfig) {
+ $scope.PageConfig.navConfig = $injector.get(next.pageConfig);
+ } else {
+ $scope.PageConfig.navConfig = {};
+ }
- // Post clone entities
- var _entities = $.map(entities, function(entity) {
- var _entity = {};
+ // Authorization
+ // > Login check
+ if (!common.getValueByPath(next, "access.skipCheck", false)) {
+ if (!Authorization.isLogin) {
+ console.log("[Authorization] Need access. Redirect...");
+ $wrapState.go("login");
+ }
+ }
- // Clone variables
- $.each(entity, function(key, value) {
- // Skip inner variables
- if(!key.match(/^__/)) {
- _entity[key] = entity[key];
+ // > Role control
+ /*var _roles = common.getValueByPath(next, "access.roles", []);
+ if (_roles.length && Authorization.userProfile.roles) {
+ var _roleMatch = false;
+ $.each(_roles, function (i, roleName) {
+ if (Authorization.isRole(roleName)) {
+ _roleMatch = true;
+ return false;
}
});
- // Add timestamp
- if(config.timestamp !== false) {
- if(config.createTime !== false && !_entity.createdTime) {
- _entity.createdTime = new moment().valueOf();
- }
- if(config.lastModifiedDate !== false) {
- _entity.lastModifiedDate = new moment().valueOf();
- }
+ if (!_roleMatch) {
+ $wrapState.path("/dam");
}
+ }*/
+ });
- return _entity;
- });
+ $scope.$on('$stateChangeError', function (event, next, nextParam, current, currentParam, error) {
+ console.error("[Switch] Error", arguments);
+ });
- return _post(app.getURL("updateEntity", {serviceName: serviceName}), _entities);
- },
+ // Get side bar navigation item class
+ $scope.getNavClass = function (page) {
+ var path = page.url.replace(/^#/, '');
- deleteEntity: function(serviceName, entities) {
- if(!$.isArray(entities)) entities = [entities];
+ if ($wrapState.path() === path) {
+ PageConfig.pageTitle = PageConfig.pageTitle || page.title;
+ return "active";
+ } else {
+ return "";
+ }
+ };
- var _entities = $.map(entities, function(entity) {
- return typeof entity === "object" ? entity.encodedRowkey : entity;
- });
- return _post(app.getURL("deleteEntity", {serviceName: serviceName}), _entities);
- },
- deleteEntities: function(serviceName, condition) {
- return _delete(app.getURL("deleteEntities", {serviceName: serviceName, condition: new ParseCondition(condition).condition}));
- },
-
- queryEntity: function(serviceName, encodedRowkey) {
- return _query("queryEntity", {serviceName: serviceName, encodedRowkey: encodedRowkey});
- },
- queryEntities: function(serviceName, condition, fields) {
- return _query("queryEntities", {serviceName: serviceName, _condition: new ParseCondition(condition), values: fields});
- },
- queryGroup: function(serviceName, condition, groupBy, fields) {
- return _query("queryGroup", {serviceName: serviceName, _condition: new ParseCondition(condition), groupBy: groupBy, values: fields});
- },
- querySeries: function(serviceName, condition, groupBy, fields, intervalmin) {
- var _cond = new ParseCondition(condition);
- var _list = _query("querySeries", {serviceName: serviceName, _condition: _cond, groupBy: groupBy, values: fields, intervalmin: intervalmin});
- _list._promise.success(function() {
- if(_list.length === 0) {
- _list._empty = true;
- _list._convert = true;
-
- for(var i = 0; i <= (_cond.additionalCondition._endTime.valueOf() - _cond.additionalCondition._startTime.valueOf()) / (1000 * 60 * intervalmin); i += 1) {
- _list.push(0);
- }
- } else if(_list.length === 1) {
- _list._convert = true;
- var _unit = _list.pop();
- _list.push.apply(_list, _unit.value[0]);
- }
+ // Get side bar navigation item class visible
+ $scope.getNavVisible = function (page) {
+ if (!page.roles) return true;
- if(_list._convert) {
- var _current = _cond.additionalCondition._startTime.clone();
- $.each(_list, function(i, value) {
- _list[i] = {
- x: _current.valueOf(),
- y: value
- };
- _current.add(intervalmin, "m");
- });
+ for (var i = 0; i < page.roles.length; i += 1) {
+ var roleName = page.roles[i];
+ if (Authorization.isRole(roleName)) {
+ return true;
}
- });
- return _list;
- },
-
- query: function(path, params) {
- var _list = [];
- _list._promise = $http({
- method: 'GET',
- url: app.getURL("query") + path,
- params: params
- }).success(function(data) {
- _list.push.apply(_list, data.obj);
- });
- return _list;
- },
-
- dialog: function(data, callback) {
- if(data.success === false || (data.exception || "").trim()) {
- return $.dialog({
- title: "OPS",
- content: $("<pre>").html(data.exception)
- }, callback);
}
- return false;
- },
- };
- return pkg;
-});
-
-eagleApp.filter('parseJSON', function() {
- 'use strict';
-
- return function(input, defaultVal) {
- return common.parseJSON(input, defaultVal);
- };
-});
-eagleApp.filter('split', function() {
- 'use strict';
-
- return function(input, regex) {
- return input.split(regex);
- };
-});
-
-eagleApp.filter('reverse', function() {
- 'use strict';
-
- return function(items) {
- return items.slice().reverse();
- };
-});
-
-eagleApp.controller('MainCtrl', function($scope, $location, $http, globalContent, Site, Authorization, Entities, nvd3) {
- 'use strict';
-
- window.globalContent = $scope.globalContent = globalContent;
- window.site = $scope.site = Site;
- window.auth = $scope.auth = Authorization;
- window.entities = $scope.entities = Entities;
- window.nvd3 = nvd3;
- $scope.app = app;
-
- // Clean up
- $scope.$on('$routeChangeStart', function(event, next, current) {
- // Page initialization
- globalContent.pageTitle = "";
- globalContent.pageSubTitle = "";
- globalContent.hideSite = false;
- globalContent.lockSite = false;
- globalContent.hideSidebar = false;
- globalContent.hideUser = false;
+ return false;
+ };
// Authorization
- // > Login check
- if(!common.getValueByPath(next, "access.skipCheck", false)) {
- if(!Authorization.isLogin) {
- $location.path("/dam/login");
- }
- }
-
- // > Role control
- var _roles = common.getValueByPath(next, "access.roles", []);
- if(_roles.length && Authorization.userProfile.roles) {
- var _roleMatch = false;
- $.each(_roles, function(i, roleName) {
- if(Authorization.isRole(roleName)) {
- _roleMatch = true;
- return false;
- }
- });
-
- if(!_roleMatch) {
- $location.path("/dam");
- }
- }
+ $scope.logout = function () {
+ console.log("[Authorization] Logout. Redirect...");
+ Authorization.logout();
+ $wrapState.go("login");
+ };
});
-
- // Get side bar navigation item class
- $scope.getNavClass = function(page) {
- var path = page.url.replace(/^#/, '');
-
- if ($location.path() == path) {
- globalContent.pageTitle = globalContent.pageTitle || page.title;
- return "active";
- } else {
- return "";
- }
- };
-
- // Get side bar navigation item class visible
- $scope.getNavVisible = function(page) {
- if(!page.roles) return true;
-
- for(var i = 0 ; i < page.roles.length ; i += 1) {
- var roleName = page.roles[i];
- if(Authorization.isRole(roleName)) {
- return true;
- }
- }
-
- return false;
- };
-
- // Authorization
- $scope.logout = function() {
- Authorization.logout();
- $location.path("/dam/login");
- };
-});
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/app.ui.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/app.ui.js b/eagle-webservice/src/main/webapp/app/public/js/app.ui.js
index 4e0ee6e..28727ba 100644
--- a/eagle-webservice/src/main/webapp/app/public/js/app.ui.js
+++ b/eagle-webservice/src/main/webapp/app/public/js/app.ui.js
@@ -1,66 +1,76 @@
-/*
- * 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() {
- // ================== AdminLTE Update ==================
- var _boxSelect = $.AdminLTE.options.boxWidgetOptions.boxWidgetSelectors;
-
- // Box collapse
- $(document).on("click", _boxSelect.collapse, function(e) {
- if(common.getValueByPath($._data(this), "events.click")) return;
-
- e.preventDefault();
- $.AdminLTE.boxWidget.collapse($(this));
- });
-
- // Box remove
- $(document).on("click", _boxSelect.remove, function(e) {
- if(common.getValueByPath($._data(this), "events.click")) return;
-
- e.preventDefault();
- $.AdminLTE.boxWidget.remove($(this));
- });
-
- // =================== jQuery Update ===================
- // Slide Toggle
- var _slideToggle = $.fn.slideToggle;
- $.fn.slideToggle = function(showOrHide) {
- if(arguments.length === 1 && typeof showOrHide === "boolean") {
- if(showOrHide) {
- this.slideDown();
- } else {
- this.slideUp();
- }
- } else {
- _slideToggle.apply(this, arguments);
- }
- };
-
- // Fade Toggle
- var _fadeToggle = $.fn.fadeToggle;
- $.fn.fadeToggle = function(showOrHide) {
- if(arguments.length === 1 && typeof showOrHide === "boolean") {
- if(showOrHide) {
- this.fadeIn();
- } else {
- this.fadeOut();
- }
- } else {
- _fadeToggle.apply(this, arguments);
- }
- };
+/*
+ * 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() {
+ // ================== AdminLTE Update ==================
+ var _boxSelect = $.AdminLTE.options.boxWidgetOptions.boxWidgetSelectors;
+
+ // Box collapse
+ $(document).on("click", _boxSelect.collapse, function(e) {
+ if(common.getValueByPath($._data(this), "events.click")) return;
+
+ e.preventDefault();
+ $.AdminLTE.boxWidget.collapse($(this));
+ });
+
+ // Box remove
+ $(document).on("click", _boxSelect.remove, function(e) {
+ if(common.getValueByPath($._data(this), "events.click")) return;
+
+ e.preventDefault();
+ $.AdminLTE.boxWidget.remove($(this));
+ });
+
+ // =================== jQuery Update ===================
+ // Slide Toggle
+ var _slideToggle = $.fn.slideToggle;
+ $.fn.slideToggle = function(showOrHide) {
+ if(arguments.length === 1 && typeof showOrHide === "boolean") {
+ if(showOrHide) {
+ this.slideDown();
+ } else {
+ this.slideUp();
+ }
+ } else {
+ _slideToggle.apply(this, arguments);
+ }
+ };
+
+ // Fade Toggle
+ var _fadeToggle = $.fn.fadeToggle;
+ $.fn.fadeToggle = function(showOrHide) {
+ if(arguments.length === 1 && typeof showOrHide === "boolean") {
+ if(showOrHide) {
+ this.fadeIn();
+ } else {
+ this.fadeOut();
+ }
+ } else {
+ _fadeToggle.apply(this, arguments);
+ }
+ };
+
+ // Modal
+ var _modal = $.fn.modal;
+ $.fn.modal = function() {
+ setTimeout(function() {
+ $(this).find("input, textarea").filter(':visible:first').focus();
+ }.bind(this), 500);
+ _modal.apply(this, arguments);
+ return this;
+ };
})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/common.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/common.js b/eagle-webservice/src/main/webapp/app/public/js/common.js
index c5b385f..706eeec 100644
--- a/eagle-webservice/src/main/webapp/app/public/js/common.js
+++ b/eagle-webservice/src/main/webapp/app/public/js/common.js
@@ -1,211 +1,226 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var common = {};
-
-common.template = function (str, list) {
- $.each(list, function(key, value) {
- var _regex = new RegExp("\\$\\{" + key + "\\}", "g");
- str = str.replace(_regex, value);
- });
- return str;
-};
-
-common.getValueByPath = function (unit, path, defaultValue) {
- if(unit === null || unit === undefined) throw "Unit or path can't be empty!";
- if(path === "" || path === null || path === undefined) return unit;
-
- path = path.replace(/\[(\d+)\]/g, ".$1").replace(/^\./, "").split(/\./);
- $.each(path, function(i, path) {
- unit = unit[path];
- if(unit === null || unit === undefined) {
- unit = null;
- return false;
- }
- });
- if(unit === null && defaultValue !== undefined) {
- unit = defaultValue;
- }
- return unit;
-};
-
-common.setValueByPath = function(unit, path, value) {
- if(!unit || typeof path !== "string" || path === "") throw "Unit or path can't be empty!";
-
- var _inArray = false;
- var _end = 0;
- var _start = 0;
- var _unit = unit;
-
- function _nextPath(array) {
- var _key = path.slice(_start, _end);
- if(_inArray) {
- _key = _key.slice(0, -1);
- }
- if(!_unit[_key]) {
- if(array) {
- _unit[_key] = [];
- } else {
- _unit[_key] = {};
- }
- }
- _unit = _unit[_key];
- }
-
- for(; _end < path.length ; _end += 1) {
- if(path[_end] === ".") {
- _nextPath(false);
- _start = _end + 1;
- _inArray = false;
- } else if(path[_end] === "[") {
- _nextPath(true);
- _start = _end + 1;
- _inArray = true;
- }
- }
-
- _unit[path.slice(_start, _inArray ? -1 : _end)] = value;
-
- return unit;
-};
-
-common.parseJSON = function (str, defaultVal) {
- try {
- return JSON.parse(str);
- } catch(err) {
- if(defaultVal === undefined) {
- console.warn("Can't parse JSON: " + str);
- }
- }
- return defaultVal === undefined ? null : defaultVal;
-};
-
-common.isEmpty = function(val) {
- if($.isArray(val)) {
- return val.length === 0;
- } else {
- return val === null || val === undefined;
- }
-};
-
-// ====================== Format ======================
-common.format = {};
-
-/*
- * Format date to string. Support number, string, Date instance. Will auto convert time zone offset(Moment instance will keep time zone).
- */
-common.format.date = function(val, type) {
- if(val === undefined || val === null) return "";
-
- if(typeof val === "number" || typeof val === "string" || val instanceof Date) {
- val = app.time.offset(val);
- }
- switch(type) {
- default:
- return val.format("YYYY-MM-DD HH:mm:ss") + (val.utcOffset() === 0 ? '[UTC]' : '');
- }
-};
-
-// ====================== Array =======================
-common.array = {};
-
-common.array.sum = function(list, path) {
- var _sum = 0;
- if(list) {
- $.each(list, function(i, unit) {
- var _val = common.getValueByPath(unit, path);
- if(typeof _val === "number") {
- _sum += _val;
- }
- });
- }
- return _sum;
-};
-
-common.array.max = function(list, path) {
- var _max = null;
- if(list) {
- $.each(list, function(i, unit) {
- var _val = common.getValueByPath(unit, path);
- if(typeof _val === "number" && (_max === null || _max < _val)) {
- _max = _val;
- }
- });
- }
- return _max;
-};
-
-common.array.bottom = function(list, path, count) {
- var _list = list.slice();
-
- _list.sort(function(a, b) {
- var _a = common.getValueByPath(a, path, null);
- var _b = common.getValueByPath(b, path, null);
-
- if(_a === _b) return 0;
- if(_a < _b || _a === null) {
- return -1;
- } else {
- return 1;
- }
- });
- return !count ? _list : _list.slice(0, count);
-};
-common.array.top = function(list, path, count) {
- var _list = common.array.bottom(list, path);
- _list.reverse();
- return !count ? _list : _list.slice(0, count);
-};
-
-common.array.find = function(val, list, path, findAll) {
- path = path || "";
- var _list = $.grep(list, function(unit) {
- return val === common.getValueByPath(unit, path);
- });
- return findAll ? _list : (_list.length === 0 ? null : _list[0]);
-};
-
-common.array.filter = function(val, list, path) {
- return common.array.find(val, list, path, true);
-};
-
-common.array.count = function(list, val, path) {
- if(arguments.length === 1) {
- return list.length;
- } else {
- return common.array.find(val, list, path, true).length;
- }
-};
-
-common.array.remove = function(val, list) {
- for(var i = 0 ; i < list.length ; i += 1) {
- if(list[i] === val) {
- list.splice(i, 1);
- i -= 1;
- }
- }
-};
-
-// ======================= Map ========================
-common.map = {};
-
-common.map.toArray = function(map) {
- return $.map(map, function(unit) {
- return unit;
- });
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var common = {};
+
+common.template = function (str, list) {
+ $.each(list, function(key, value) {
+ var _regex = new RegExp("\\$\\{" + key + "\\}", "g");
+ str = str.replace(_regex, value);
+ });
+ return str;
+};
+
+common.getValueByPath = function (unit, path, defaultValue) {
+ if(unit === null || unit === undefined) throw "Unit or path can't be empty!";
+ if(path === "" || path === null || path === undefined) return unit;
+
+ path = path.replace(/\[(\d+)\]/g, ".$1").replace(/^\./, "").split(/\./);
+ $.each(path, function(i, path) {
+ unit = unit[path];
+ if(unit === null || unit === undefined) {
+ unit = null;
+ return false;
+ }
+ });
+ if(unit === null && defaultValue !== undefined) {
+ unit = defaultValue;
+ }
+ return unit;
+};
+
+common.setValueByPath = function(unit, path, value) {
+ if(!unit || typeof path !== "string" || path === "") throw "Unit or path can't be empty!";
+
+ var _inArray = false;
+ var _end = 0;
+ var _start = 0;
+ var _unit = unit;
+
+ function _nextPath(array) {
+ var _key = path.slice(_start, _end);
+ if(_inArray) {
+ _key = _key.slice(0, -1);
+ }
+ if(!_unit[_key]) {
+ if(array) {
+ _unit[_key] = [];
+ } else {
+ _unit[_key] = {};
+ }
+ }
+ _unit = _unit[_key];
+ }
+
+ for(; _end < path.length ; _end += 1) {
+ if(path[_end] === ".") {
+ _nextPath(false);
+ _start = _end + 1;
+ _inArray = false;
+ } else if(path[_end] === "[") {
+ _nextPath(true);
+ _start = _end + 1;
+ _inArray = true;
+ }
+ }
+
+ _unit[path.slice(_start, _inArray ? -1 : _end)] = value;
+
+ return unit;
+};
+
+common.parseJSON = function (str, defaultVal) {
+ try {
+ str = (str + "").trim();
+ if(Number(str).toString() === str) throw "Number format";
+ return JSON.parse(str);
+ } catch(err) {
+ if(defaultVal === undefined) {
+ console.warn("Can't parse JSON: " + str);
+ }
+ }
+ return defaultVal === undefined ? null : defaultVal;
+};
+
+common.isEmpty = function(val) {
+ if($.isArray(val)) {
+ return val.length === 0;
+ } else {
+ return val === null || val === undefined;
+ }
+};
+
+// ====================== Format ======================
+common.format = {};
+
+/*
+ * Format date to string. Support number, string, Date instance. Will auto convert time zone offset(Moment instance will keep time zone).
+ */
+common.format.date = function(val, type) {
+ if(val === undefined || val === null) return "";
+
+ if(typeof val === "number" || typeof val === "string" || val instanceof Date) {
+ val = app.time.offset(val);
+ }
+ switch(type) {
+ default:
+ return val.format("YYYY-MM-DD HH:mm:ss") + (val.utcOffset() === 0 ? '[UTC]' : '');
+ }
+};
+
+// ====================== Array =======================
+common.array = {};
+
+common.array.sum = function(list, path) {
+ var _sum = 0;
+ if(list) {
+ $.each(list, function(i, unit) {
+ var _val = common.getValueByPath(unit, path);
+ if(typeof _val === "number") {
+ _sum += _val;
+ }
+ });
+ }
+ return _sum;
+};
+
+common.array.max = function(list, path) {
+ var _max = null;
+ if(list) {
+ $.each(list, function(i, unit) {
+ var _val = common.getValueByPath(unit, path);
+ if(typeof _val === "number" && (_max === null || _max < _val)) {
+ _max = _val;
+ }
+ });
+ }
+ return _max;
+};
+
+common.array.bottom = function(list, path, count) {
+ var _list = list.slice();
+
+ _list.sort(function(a, b) {
+ var _a = common.getValueByPath(a, path, null);
+ var _b = common.getValueByPath(b, path, null);
+
+ if(_a === _b) return 0;
+ if(_a < _b || _a === null) {
+ return -1;
+ } else {
+ return 1;
+ }
+ });
+ return !count ? _list : _list.slice(0, count);
+};
+common.array.top = function(list, path, count) {
+ var _list = common.array.bottom(list, path);
+ _list.reverse();
+ return !count ? _list : _list.slice(0, count);
+};
+
+common.array.find = function(val, list, path, findAll) {
+ path = path || "";
+ var _list = $.grep(list, function(unit) {
+ return val === common.getValueByPath(unit, path);
+ });
+ return findAll ? _list : (_list.length === 0 ? null : _list[0]);
+};
+
+common.array.filter = function(val, list, path) {
+ return common.array.find(val, list, path, true);
+};
+
+common.array.count = function(list, val, path) {
+ if(arguments.length === 1) {
+ return list.length;
+ } else {
+ return common.array.find(val, list, path, true).length;
+ }
+};
+
+common.array.remove = function(val, list) {
+ for(var i = 0 ; i < list.length ; i += 1) {
+ if(list[i] === val) {
+ list.splice(i, 1);
+ i -= 1;
+ }
+ }
+};
+
+common.array.insert = function(val, list, index) {
+ list.splice(index, 0, val);
+};
+
+common.array.moveOffset = function(item, list, offset) {
+ var _index = $.inArray(item, list);
+ var _tgtPos = _index + offset;
+ if(_tgtPos < 0 || _tgtPos >= list.length) return;
+
+ common.array.remove(item, list);
+ common.array.insert(item, list, _index + offset);
+};
+
+// ======================= Map ========================
+common.map = {};
+
+common.map.toArray = function(map) {
+ return $.map(map, function(unit) {
+ return unit;
+ });
};
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/ctrl/alertController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/alertController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/alertController.js
deleted file mode 100644
index 2399234..0000000
--- a/eagle-webservice/src/main/webapp/app/public/js/ctrl/alertController.js
+++ /dev/null
@@ -1,128 +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.
- */
-
-// =============================================================
-// = Alert List =
-// =============================================================
-damControllers.controller('alertListCtrl', function(globalContent, Site, damContent, $scope, $routeParams, $interval, $timeout, Entities) {
- 'use strict';
-
- globalContent.setConfig(damContent.config);
- globalContent.pageSubTitle = Site.current().name;
-
- var MAX_PAGESIZE = 10000;
-
- // Initial load
- $scope.dataSource = $routeParams.dataSource;
-
- $scope.alertList = [];
- $scope.alertList.ready = false;
-
- // Load data
- function _loadAlerts() {
- if($scope.alertList._promise) {
- $scope.alertList._promise.abort();
- }
-
- var _list = Entities.queryEntities("AlertService", {
- site: Site.current().name,
- dataSource: $scope.dataSource,
- hostname: null,
- _pageSize: MAX_PAGESIZE,
- _duration: 1000 * 60 * 60 * 24 * 30,
- __ETD: 1000 * 60 * 60 * 24
- });
- $scope.alertList._promise = _list._promise;
- _list._promise.then(function() {
- var index;
-
- if($scope.alertList[0]) {
- // List new alerts
- for(index = 0 ; index < _list.length ; index += 1) {
- var _alert = _list[index];
- _alert.__new = true;
- if(_alert.encodedRowkey === $scope.alertList[0].encodedRowkey) {
- break;
- }
- }
-
- if(index > 0) {
- $scope.alertList.unshift.apply($scope.alertList, _list.slice(0, index));
-
- // Clean up UI highlight
- $timeout(function() {
- $.each(_list, function(i, alert) {
- delete alert.__new;
- });
- }, 100);
- }
- } else {
- // List all alerts
- $scope.alertList.push.apply($scope.alertList, _list);
- }
-
- $scope.alertList.ready = true;
- });
- }
-
- _loadAlerts();
- var _loadInterval = $interval(_loadAlerts, app.time.refreshInterval);
- $scope.$on('$destroy',function(){
- $interval.cancel(_loadInterval);
- });
-});
-
-// =============================================================
-// = Alert Detail =
-// =============================================================
-damControllers.controller('alertDetailCtrl', function(globalContent, Site, damContent, $scope, $routeParams, Entities) {
- 'use strict';
-
- globalContent.setConfig(damContent.config);
- globalContent.pageTitle = "Alert Detail";
- globalContent.navPath = ["Alert List", "Alert Detail"];
- globalContent.lockSite = true;
-
- $scope.common = common;
-
- // Query policy
- $scope.alertList = Entities.queryEntity("AlertService", $routeParams.encodedRowkey);
- $scope.alertList._promise.then(function() {
- if($scope.alertList.length === 0) {
- $.dialog({
- title: "OPS!",
- content: "Alert not found!",
- }, function() {
- location.href = "#/dam/alertList";
- });
- return;
- } else {
- var alert = $scope.alertList[0];
-
- $scope.alert = alert;
- Site.current(Site.find($scope.alert.tags.site));
- console.log($scope.alert);
- }
- });
-
- // UI
- $scope.getMessageTime = function(alert) {
- var _time = common.getValueByPath(alert, "alertContext.properties.timestamp");
- return Number(_time);
- };
-});
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/d37643b0/eagle-webservice/src/main/webapp/app/public/js/ctrl/authController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/authController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/authController.js
index 1131ca5..1b4f602 100644
--- a/eagle-webservice/src/main/webapp/app/public/js/ctrl/authController.js
+++ b/eagle-webservice/src/main/webapp/app/public/js/ctrl/authController.js
@@ -16,48 +16,54 @@
* limitations under the License.
*/
-// =============================================================
-// = User Profile List =
-// =============================================================
-damControllers.controller('authLoginCtrl', function(globalContent, Site, Authorization, $scope) {
+(function() {
'use strict';
- globalContent.hideSidebar = true;
- globalContent.hideSite = true;
- globalContent.hideUser = true;
+ var eagleControllers = angular.module('eagleControllers');
+ // =============================================================
+ // = User Profile List =
+ // =============================================================
+ eagleControllers.controller('authLoginCtrl', function (PageConfig, Site, Authorization, Application, $scope) {
+ PageConfig.hideSidebar = true;
+ PageConfig.hideApplication = true;
+ PageConfig.hideSite = true;
+ PageConfig.hideUser = true;
- $scope.username = "";
- $scope.password = "";
- $scope.lock = false;
+ $scope.username = "";
+ $scope.password = "";
+ $scope.lock = false;
- // UI
- setTimeout(function() {
- $("#username").focus();
- });
+ // UI
+ setTimeout(function () {
+ $("#username").focus();
+ });
- // Login
- $scope.login = function(event, forceSubmit) {
- if($scope.lock) return;
+ // Login
+ $scope.login = function (event, forceSubmit) {
+ if ($scope.lock) return;
- if(event.which === 13 || forceSubmit) {
- $scope.lock = true;
+ if (event.which === 13 || forceSubmit) {
+ $scope.lock = true;
- Authorization.login($scope.username, $scope.password).then(function(success) {
- if(success) {
- Site.refresh();
- Authorization.refresh();
- Authorization.path(true);
- } else {
- $.dialog({
- title: "OPS",
- content: "User name or password not correct."
- }).on("hidden.bs.modal", function() {
- $("#username").focus();
- });
- }
- }).finally(function() {
- $scope.lock = false;
- });
- }
- };
-});
\ No newline at end of file
+ Authorization.login($scope.username, $scope.password).then(function (success) {
+ if (success) {
+ console.log("[Login] Login success! Reload data...");
+ Authorization.reload().then(function() {}, function() {console.warn("Site error!");});
+ Application.reload().then(function() {}, function() {console.warn("Site error!");});
+ Site.reload().then(function() {}, function() {console.warn("Site error!");});
+ Authorization.path(true);
+ } else {
+ $.dialog({
+ title: "OPS",
+ content: "User name or password not correct."
+ }).on("hidden.bs.modal", function () {
+ $("#username").focus();
+ });
+ }
+ }).finally(function () {
+ $scope.lock = false;
+ });
+ }
+ };
+ });
+})();
\ No newline at end of file