http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/java/org/apache/rocketmq/console/util/JsonUtil.java ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/java/org/apache/rocketmq/console/util/JsonUtil.java b/rocketmq-console-ng/src/main/java/org/apache/rocketmq/console/util/JsonUtil.java new file mode 100644 index 0000000..857a7fa --- /dev/null +++ b/rocketmq-console-ng/src/main/java/org/apache/rocketmq/console/util/JsonUtil.java @@ -0,0 +1,156 @@ +/* + * 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.rocketmq.console.util; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; +import com.google.common.base.Strings; +import com.google.common.base.Throwables; +import java.io.IOException; +import java.io.Writer; +import java.text.SimpleDateFormat; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings("unchecked") +public class JsonUtil { + + private static Logger logger = LoggerFactory.getLogger(JsonUtil.class); + private static ObjectMapper objectMapper = new ObjectMapper(); + + private JsonUtil() { + } + + static { + objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true); + objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + objectMapper.setFilters(new SimpleFilterProvider().setFailOnUnknownId(false)); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); + objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + } + + public static void writeValue(Writer writer, Object obj) { + try { + objectMapper.writeValue(writer, obj); + } + catch (IOException e) { + Throwables.propagateIfPossible(e); + } + } + + public static <T> String obj2String(T src) { + if (src == null) { + return null; + } + + try { + return src instanceof String ? (String)src : objectMapper.writeValueAsString(src); + } + catch (Exception e) { + logger.error("Parse Object to String error src=" + src, e); + return null; + } + } + + public static <T> byte[] obj2Byte(T src) { + if (src == null) { + return null; + } + + try { + return src instanceof byte[] ? (byte[])src : objectMapper.writeValueAsBytes(src); + } + catch (Exception e) { + logger.error("Parse Object to byte[] error", e); + return null; + } + } + + public static <T> T string2Obj(String str, Class<T> clazz) { + if (Strings.isNullOrEmpty(str) || clazz == null) { + return null; + } + str = escapesSpecialChar(str); + try { + return clazz.equals(String.class) ? (T)str : objectMapper.readValue(str, clazz); + } + catch (Exception e) { + logger.error("Parse String to Object error\nString: {}\nClass<T>: {}\nError: {}", str, clazz.getName(), e); + return null; + } + } + + public static <T> T byte2Obj(byte[] bytes, Class<T> clazz) { + if (bytes == null || clazz == null) { + return null; + } + try { + return clazz.equals(byte[].class) ? (T)bytes : objectMapper.readValue(bytes, clazz); + } + catch (Exception e) { + logger.error("Parse byte[] to Object error\nbyte[]: {}\nClass<T>: {}\nError: {}", bytes, clazz.getName(), e); + return null; + } + } + + public static <T> T string2Obj(String str, TypeReference<T> typeReference) { + if (Strings.isNullOrEmpty(str) || typeReference == null) { + return null; + } + str = escapesSpecialChar(str); + try { + return (T)(typeReference.getType().equals(String.class) ? str : objectMapper.readValue(str, typeReference)); + } + catch (Exception e) { + logger.error("Parse String to Object error\nString: {}\nTypeReference<T>: {}\nError: {}", str, + typeReference.getType(), e); + return null; + } + } + + public static <T> T byte2Obj(byte[] bytes, TypeReference<T> typeReference) { + if (bytes == null || typeReference == null) { + return null; + } + try { + return (T)(typeReference.getType().equals(byte[].class) ? bytes : objectMapper.readValue(bytes, + typeReference)); + } + catch (Exception e) { + logger.error("Parse byte[] to Object error\nbyte[]: {}\nTypeReference<T>: {}\nError: {}", bytes, + typeReference.getType(), e); + return null; + } + } + + public static <T> T map2Obj(Map<String, String> map, Class<T> clazz) { + String str = obj2String(map); + return string2Obj(str, clazz); + } + + private static String escapesSpecialChar(String str) { + return str.replace("\n", "\\n").replace("\r", "\\r"); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/application.properties ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/application.properties b/rocketmq-console-ng/src/main/resources/application.properties new file mode 100644 index 0000000..de8eb1b --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/application.properties @@ -0,0 +1,16 @@ +server.contextPath= +server.port=8080 +#spring.application.index=true +spring.application.name=rocketmq-console +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +logging.config=classpath:logback.xml +#if this value is empty,use env value rocketmq.config.namesrvAddr NAMESRV_ADDR | now, you can set it in ops page.default localhost:9876 +rocketmq.config.namesrvAddr= +#if you use rocketmq version < 3.5.8, rocketmq.config.isVIPChannel should be false.default true +rocketmq.config.isVIPChannel= +#rocketmq-console's data path:dashboard/monitor +rocketmq.config.dataPath=/tmp/rocketmq-console/data +#set it false if you don't want use dashboard.default true +rocketmq.config.enableDashBoardCollect=true \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/logback.xml ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/logback.xml b/rocketmq-console-ng/src/main/resources/logback.xml new file mode 100644 index 0000000..c1fc79a --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/logback.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder charset="UTF-8"> + <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %5p %m%n</pattern> + </encoder> + </appender> + + <appender name="FILE" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${user.home}/logs/consolelogs/rocketmq-console.log</file> + <append>true</append> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${user.home}/logs/consolelogs/rocketmq-console-%d{yyyy-MM-dd}.%i.log + </fileNamePattern> + <timeBasedFileNamingAndTriggeringPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> + <maxFileSize>104857600</maxFileSize> + </timeBasedFileNamingAndTriggeringPolicy> + <MaxHistory>10</MaxHistory> + </rollingPolicy> + <encoder> + <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %5p %m%n</pattern> + <charset class="java.nio.charset.Charset">UTF-8</charset> + </encoder> + </appender> + + <root level="INFO"> + <appender-ref ref="STDOUT" /> + <appender-ref ref="FILE" /> + </root> + +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/index.html ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/index.html b/rocketmq-console-ng/src/main/resources/static/index.html new file mode 100644 index 0000000..745b1fa --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/index.html @@ -0,0 +1,117 @@ +<!DOCTYPE html> +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<html lang="en" ng-app="app"> +<head> + <meta charset="UTF-8"> + <title>RocketMq-console-ng</title> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name='description' content=''> + <meta name='keywords' content=''> + <!--iOS --> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + + <!-- preLoading --> + <link rel="stylesheet" href="style/preLoading/normalize.css"> + <link rel="stylesheet" href="style/preLoading/main.css"> + <script src="vendor/preLoading/modernizr-2.6.2.min.js"></script> + <!-- preLoading --> + + <link rel="stylesheet" href="vendor/bootstrap/css/bootstrap.min.css"> + <link rel="stylesheet" href="vendor/bootstrap-material-design/css/bootstrap-material-design.css"> + <link rel="stylesheet" href="vendor/bootstrap-material-design/css/ripples.css"> + <link rel="stylesheet" href="vendor/angular/notification/angular-ui-notification.css"> + <link rel="stylesheet" href="vendor/ng-dialog/ngDialog.min.css"> + <link rel="stylesheet" href="vendor/ng-dialog/ngDialog-theme-default.css"> + <link rel="stylesheet" href="vendor/dropdown/jquery.dropdown.css"> + <link rel="stylesheet" href="vendor/datatimepicker/bootstrap-datetimepicker.min.css"> + <link rel="stylesheet" href="vendor/font-awesome-4.7.0/css/font-awesome.min.css"> + <link rel="stylesheet" href="vendor/font-awesome-4.7.0/fonts/fontawesome-webfont.svg"> + <link rel="stylesheet" type="text/css" href="vendor/chosen/chosen.css"/> + <link rel="stylesheet" type="text/css" href="vendor/chosen/chosen-spinner.css"/> + <link rel="stylesheet" type="text/css" href="vendor/angular-material/angular-material.min.css"/> + <link rel="stylesheet" type="text/css" href="vendor/md-tab/docs.css"/> + <link rel="stylesheet" href="style/animate.css"> + <link rel="stylesheet" href="style/theme.css"> + <link rel="stylesheet" href="style/app.css"> + +</head> +<body ng-controller="AppCtrl"> +<!--[if lte IE 9]> +<script type="text/javascript"> + location.href = 'view/pages/un_support_browser.html'; +</script> +<![endif]--> + +<div id="loader-wrapper"> + <div id="loader"></div> + + <div class="loader-section section-left"></div> + <div class="loader-section section-right"></div> + +</div> +<div ng-include="'view/layout/_header.html'"></div> +<section ng-view></section> +<div ng-include="'view/layout/_footer.html'"></div> +<script type="text/javascript" src="vendor/jquery/jquery1.11.3.min.js"></script> +<script type="text/javascript" src="vendor/bootstrap/js/bootstrap.min.js"></script> +<script type="text/javascript" src="vendor/bootstrap-material-design/js/material.min.js"></script> +<script type="text/javascript" src="vendor/bootstrap-material-design/js/ripples.min.js"></script> +<script type="text/javascript" src="vendor/angular/angular.min.js"></script> +<script type="text/javascript" src="vendor/angular/angular-translate.min.js"></script> +<script type="text/javascript" + src="vendor/angular/angular-translate-storage-cookie/angular-translate-storage-cookie.min.js"></script> +<script type="text/javascript" src="vendor/angular/i18n/angular-locale_zh-cn.js"></script> +<script type="text/javascript" src="src/i18n/en.js"></script> +<script type="text/javascript" src="src/i18n/zh.js"></script> +<script type="text/javascript" src="vendor/angular/angular-cookies.min.js"></script> +<script type="text/javascript" src="vendor/angular/angular-animate.min.js"></script> +<script type="text/javascript" src="vendor/angular/angular-route.min.js"></script> +<script type="text/javascript" src="vendor/angular/angular-ui-router.min.js"></script> +<script type="text/javascript" src="vendor/angular/angular-sanitize.min.js"></script> +<script type="text/javascript" src="vendor/angular/angular-aria.min.js"></script> +<script type="text/javascript" src="vendor/angular/angular-messages.min.js"></script> +<script type="text/javascript" src="vendor/angular/angular-sanitize.min.js"></script> +<script type="text/javascript" src="vendor/angular/notification/angular-ui-notification.js"></script> +<script type="text/javascript" src="vendor/pagination/tm.pagination.js"></script> +<script type="text/javascript" src="vendor/ng-dialog/ngDialog.min.js"></script> +<script type="text/javascript" src="vendor/json-bigint/json-bigint.js"></script> +<script type="text/javascript" src="vendor/dropdown/jquery.dropdown.js"></script> +<script type="text/javascript" src="vendor/datatimepicker/moment.min.js"></script> +<script type="text/javascript" src="vendor/datatimepicker/bootstrap-datetimepicker.min.js"></script> +<script type="text/javascript" src="vendor/datatimepicker/angular-eonasdan-datetimepicker.min.js"></script> +<script type="text/javascript" src="vendor/chosen/angular-chosen.js"></script> +<script type="text/javascript" src="vendor/chosen/chosen.jquery.min.js"></script> +<script type="text/javascript" src='vendor/md-tab/svg-assets-cache.js'></script> +<script type="text/javascript" src='vendor/angular-material/angular-material.min.js'></script> +<script type="text/javascript" src="vendor/echarts/echarts.min.js"></script> +<script type="text/javascript" src="src/app.js"></script> +<script type="text/javascript" src="src/controller.js?v=201702250025"></script> +<script type="text/javascript" src="src/tools/tools.js"></script> +<script type="text/javascript" src="src/cluster.js?timestamp=4"></script> +<script type="text/javascript" src="src/topic.js"></script> +<script type="text/javascript" src="src/consumer.js?timestamp=6"></script> +<script type="text/javascript" src="src/producer.js"></script> +<script type="text/javascript" src="src/message.js"></script> +<script type="text/javascript" src="src/ops.js?timestamp=7"></script> +<script type="text/javascript" src="src/remoteApi/remoteApi.js"></script> +<script type="text/javascript" src="vendor/preLoading/main.js"></script> + +</body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/app.js ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/app.js b/rocketmq-console-ng/src/main/resources/static/src/app.js new file mode 100644 index 0000000..b241010 --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/app.js @@ -0,0 +1,208 @@ +/* + * 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. + */ +'use strict'; +var app = angular.module('app', [ + 'ngAnimate', + 'ngCookies', + 'ngRoute', + 'ngDialog', + 'ngMaterial', + 'ngSanitize', + 'material.svgAssetsCache', + 'ui-notification', + 'tm.pagination', + 'ae-datetimepicker', + 'localytics.directives', + 'pascalprecht.translate' +]).run( + ['$rootScope','$location','$cookies', + function ($rootScope,$location,$cookies) { + // var filter = function(url){ + // var outFilterArrs = [] + // outFilterArrs.push("/login"); + // outFilterArrs.push("/reg"); + // outFilterArrs.push("/logout"); + // outFilterArrs.push("/404"); + // var flag = false; + // $.each(outFilterArrs,function(i,value){ + // if(url.indexOf(value) > -1){ + // flag = true; + // return false; + // } + // }); + // return flag; + // } + + // if(angular.isDefined($cookies.get("isLogin")) && $cookies.get("isLogin") == 'true'){ + // chatApi.login(); + // } + + + $rootScope.$on('$routeChangeSuccess', function() { + var pathArray = $location.url().split("/"); + var index = pathArray.indexOf(""); + if(index >= 0){ + pathArray.remove(index); + } + $rootScope.path = pathArray[0]; + + //åå§åmaterial UIæ§ä»¶ + $.material.init(); + }); + + $rootScope.$on('$routeChangeStart',function (evt, next,current) { + window.clearInterval($rootScope._thread); + }) + } + ] + ).animation('.view', function () { + return { + animate: function (element, className, from, to, done) { + //styles + } + } + }); + +app.provider('getDictName', function () { + + var dictList = []; + + this.init = function () { + var url = "src/data/dict.json";//æ æ³ä½¿ç¨commonæå¡ç±»ï¼å°ååªè½åæ» + var params = {}; + $.get(url, params, function (ret) { + dictList = ret; + }) + } + + this.$get = function () { + return function (dictType, value) { + for (var i = 0; i < dictList.length; i++) { + var dict = dictList[i]; + if (dict.TYPE == dictType && dict.DICT_VALUE == value) { + return dict.DICT_NAME; + } + } + } + } +}) + +app.config(['$routeProvider', '$httpProvider','$cookiesProvider','getDictNameProvider','$sceProvider','$translateProvider','$mdThemingProvider', + function ($routeProvider, $httpProvider ,$cookiesProvider,getDictNameProvider,$sceProvider,$translateProvider,$mdThemingProvider) { + //å ³éhtmlæ ¡éªï¼åå¨å®å ¨éæ£ï¼ä½ç®å没é®é¢ï¼ä½¿ç¨ng-bind-htmléè¦æ³¨æï¼é²æ¢è·¨ç«æ»å» + $sceProvider.enabled(false); + //å端åå ¸é¡¹ç®åå§å + getDictNameProvider.init(); + + //init angular + $mdThemingProvider.theme('default') + .primaryPalette('pink') + .accentPalette('light-blue'); + + + //设置ajaxé»è®¤é ç½® + $.ajaxSetup({ + type: "POST", + contentType: 'application/json', + cache:false, + timeout : 5000, //è¶ æ¶æ¶é´è®¾ç½®ï¼å使¯«ç§ + converters:{ + "text json": JSONbig.parse + } + }); + + $httpProvider.defaults.cache = false; + + $routeProvider.when('/', { + templateUrl: 'view/pages/index.html', + controller:'dashboardCtrl' + }).when('/cluster', { + templateUrl: 'view/pages/cluster.html', + controller:'clusterController' + }).when('/topic', { + templateUrl: 'view/pages/topic.html', + controller:'topicController' + }).when('/consumer', { + templateUrl: 'view/pages/consumer.html', + controller:'consumerController' + }).when('/producer', { + templateUrl: 'view/pages/producer.html', + controller:'producerController' + }).when('/message', { + templateUrl: 'view/pages/message.html', + controller:'messageController' + }).when('/ops', { + templateUrl: 'view/pages/ops.html', + controller:'opsController' + }).when('/404', { + templateUrl: '404' + }).otherwise('404'); + + $translateProvider.translations('en',en); + $translateProvider.translations('zh',zh); + $translateProvider.preferredLanguage('en'); + $translateProvider.useCookieStorage(); +// $translateProvider.useSanitizeValueStrategy('sanitize'); + + }]); + +app.filter('range', function() { + return function(input, range) { + var total = parseInt(range.totalPage) + 1; + var count = 5; + for (var i = range.start; i<total; i++) { + if(count > 0){ + input.push(i); + count -- ; + }else { + break; + } + } + return input; + }; +}); + + +app.filter('dict',['getDictName',function(getDictName){ + return function(value,type){ + return getDictName(type,value); + } +}]) + +/** + * æ°ç»æ©å±æ¹æ³ï¼ç§»é¤æ°ç»ä¸æä¸å ç´ ææä¸æ®µå ç´ + * @param from éè¦ç§»é¤å ç´ çç´¢å¼å¼å§å¼ï¼åªä¼ ä¸ä¸ªåæ°è¡¨ç¤ºåç¬ç§»é¤è¯¥å ç´ ï¼ + * @param to éè¦ç§»é¤å ç´ çç´¢å¼ç»æå¼ + * @returns {*} + */ +Array.prototype.remove = function(from, to) { + var rest = this.slice((to || from) + 1 || this.length); + this.length = from < 0 ? this.length + from : from; + return this.push.apply(this, rest); +}; + +/** + * æ ¹æ®å ç´ å¼æ¥è¯¢æ°ç»ä¸å ç´ çç´¢å¼ + * @param val + * @returns {number} + */ +Array.prototype.indexOf = function(val) { + for (var i = 0; i < this.length; i++) { + if (this[i] == val) return i; + } + return -1; +}; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/cluster.js ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/cluster.js b/rocketmq-console-ng/src/main/resources/static/src/cluster.js new file mode 100644 index 0000000..6f1baee --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/cluster.js @@ -0,0 +1,72 @@ +/* + * 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. + */ + +app.controller('clusterController', ['$scope','$location','$http','Notification','remoteApi','tools', function ($scope,$location,$http,Notification,remoteApi,tools) { + $scope.clusterMap = {};//cluster:brokerNameList + $scope.brokerMap = {};//brokerName:{id:addr} + $scope.brokerDetail = {};//{brokerName,id:detail} + $scope.clusterNames = []; + $scope.selectedCluster = ""; + var callback = function (resp) { + if (resp.status == 0) { + $scope.clusterMap = resp.data.clusterInfo.clusterAddrTable; + $scope.brokerMap = resp.data.clusterInfo.brokerAddrTable; + $scope.brokerDetail = resp.data.brokerServer; + $.each($scope.clusterMap,function(clusterName,clusterBrokersNames){ + $scope.clusterNames.push(clusterName); + }); + if ($scope.clusterNames.length > 0) { + $scope.selectedCluster = $scope.clusterNames[0]; + } + $scope.brokers = tools.generateBrokerMap($scope.brokerDetail,$scope.clusterMap,$scope.brokerMap); + $scope.switchCluster(); + }else{ + Notification.error({message: resp.errMsg, delay: 2000}); + } + } + + remoteApi.queryClusterList(callback); + + $scope.switchCluster = function(){ + $scope.instances = $scope.brokers[$scope.selectedCluster]; + } + + $scope.showDetail = function (brokerName,index) { + $scope.detail = $scope.brokerDetail[brokerName][index]; + $scope.brokerName = brokerName; + $scope.index = index; + $(".brokerModal").modal(); + } + + $scope.showConfig = function (brokerAddr,brokerName,index) { + $scope.brokerAddr = brokerAddr; + $scope.brokerName = brokerName; + $scope.index = index; + $http({ + method: "GET", + url: "cluster/brokerConfig.query", + params:{brokerAddr:brokerAddr} + }).success(function (resp) { + if (resp.status == 0) { + $scope.brokerConfig = resp.data; + $(".configModal").modal(); + }else{ + Notification.error({message: resp.errMsg, delay: 2000}); + } + }) + } +}]) http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/consumer.js ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/consumer.js b/rocketmq-console-ng/src/main/resources/static/src/consumer.js new file mode 100644 index 0000000..cd093d4 --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/consumer.js @@ -0,0 +1,350 @@ +/* + * 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 module = app; + +module.controller('consumerController', ['$scope', 'ngDialog', '$http','Notification',function ($scope, ngDialog, $http,Notification) { + $scope.paginationConf = { + currentPage: 1, + totalItems: 0, + itemsPerPage: 10, + pagesLength: 15, + perPageOptions: [10], + rememberPerPage: 'perPageItems', + onChange: function () { + $scope.showConsumerGroupList(this.currentPage,this.totalItems); + } + }; + $scope.sortKey = null; + $scope.sortOrder=1; + $scope.intervalProcessSwitch = false; + $scope.intervalProcess = null; + $scope.allConsumerGrouopList = []; + $scope.consumerGroupShowList = []; + $scope.sortByKey = function (key) { + $scope.paginationConf.currentPage=1; + $scope.sortOrder = -$scope.sortOrder; + $scope.sortKey = key; + $scope.doSort(); + }; + + $scope.doSort = function (){// todo how to change this fe's code ? (it's dirty) + if($scope.sortKey == 'diffTotal'){ + $scope.allConsumerGrouopList.sort(function(a,b) {return (a.diffTotal > b.diffTotal) ? $scope.sortOrder : ((b.diffTotal > a.diffTotal) ? -$scope.sortOrder : 0);} ); + } + if($scope.sortKey == 'group'){ + $scope.allConsumerGrouopList.sort(function(a,b) {return (a.group > b.group) ? $scope.sortOrder : ((b.group > a.group) ? -$scope.sortOrder : 0);} ); + } + if($scope.sortKey == 'count'){ + $scope.allConsumerGrouopList.sort(function(a,b) {return (a.count > b.count) ? $scope.sortOrder : ((b.count > a.count) ? -$scope.sortOrder : 0);} ); + } + if($scope.sortKey == 'consumeTps'){ + $scope.allConsumerGrouopList.sort(function(a,b) {return (a.consumeTps > b.consumeTps) ? $scope.sortOrder : ((b.consumeTps > a.consumeTps) ? -$scope.sortOrder : 0);} ); + } + $scope.filterList($scope.paginationConf.currentPage) + }; + $scope.refreshConsumerData = function () { + $http({ + method: "GET", + url: "consumer/groupList.query" + }).success(function (resp) { + if(resp.status ==0){ + $scope.allConsumerGrouopList = resp.data; + console.log($scope.allConsumerGrouopList); + console.log(JSON.stringify(resp)); + $scope.showConsumerGroupList($scope.paginationConf.currentPage,$scope.allConsumerGrouopList.length); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + $scope.monitor = function(consumerGroupName){ + $http({ + method: "GET", + url: "monitor/consumerMonitorConfigByGroupName.query", + params:{consumeGroupName:consumerGroupName} + }).success(function (resp) { + // if(resp.status ==0){ + ngDialog.open({ + template: 'consumerMonitorDialog', + controller: 'consumerMonitorDialogController', + data:{consumerGroupName:consumerGroupName,data:resp.data} + }); + // }else { + // Notification.error({message: resp.errMsg, delay: 2000}); + // } + }); + }; + + + $scope.$watch('intervalProcessSwitch', function () { + if ($scope.intervalProcess != null) { + clearInterval($scope.intervalProcess); + $scope.intervalProcess = null; + } + if ($scope.intervalProcessSwitch) { + $scope.intervalProcess = setInterval($scope.refreshConsumerData, 10000); + } + }); + + + $scope.refreshConsumerData(); + $scope.filterStr=""; + $scope.$watch('filterStr', function() { + $scope.paginationConf.currentPage=1; + $scope.filterList(1) + }); + + $scope.filterList = function (currentPage) { + var lowExceptStr = $scope.filterStr.toLowerCase(); + var canShowList = []; + $scope.allConsumerGrouopList.forEach(function(element) { + console.log(element) + if (element.group.toLowerCase().indexOf(lowExceptStr) != -1){ + canShowList.push(element); + } + }); + $scope.paginationConf.totalItems =canShowList.length; + var perPage = $scope.paginationConf.itemsPerPage; + var from = (currentPage - 1) * perPage; + var to = (from + perPage)>canShowList.length?canShowList.length:from + perPage; + $scope.consumerGroupShowList = canShowList.slice(from, to); + }; + + + $scope.showConsumerGroupList = function (currentPage,totalItem) { + var perPage = $scope.paginationConf.itemsPerPage; + var from = (currentPage - 1) * perPage; + var to = (from + perPage)>totalItem?totalItem:from + perPage; + $scope.consumerGroupShowList = $scope.allConsumerGrouopList.slice(from, to); + $scope.paginationConf.totalItems = totalItem ; + console.log($scope.consumerGroupShowList) + console.log($scope.paginationConf.totalItems) + $scope.doSort() + }; + $scope.openAddDialog = function () { + $scope.openCreateOrUpdateDialog(null); + }; + $scope.openCreateOrUpdateDialog = function(request){ + var bIsUpdate = true; + if(request == null){ + request = [{ + brokerNameList: [], + subscriptionGroupConfig: { + groupName: "", + consumeEnable: true, + consumeFromMinEnable: true, + consumeBroadcastEnable: true, + retryQueueNums: 1, + retryMaxTimes: 16, + brokerId: 0, + whichBrokerWhenConsumeSlowly: 1 + } + }]; + bIsUpdate = false; + } + console.log(request); + $http({ + method: "GET", + url: "cluster/list.query" + }).success(function (resp) { + if(resp.status ==0){ + console.log(resp); + ngDialog.open({ + template: 'consumerModifyDialog', + controller: 'consumerModifyDialogController', + data:{ + consumerRequestList:request, + allClusterNameList:Object.keys(resp.data.clusterInfo.clusterAddrTable), + allBrokerNameList:Object.keys(resp.data.brokerServer), + bIsUpdate:bIsUpdate + } + }); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + $scope.detail = function(consumerGroupName){ + $http({ + method: "GET", + url: "consumer/queryTopicByConsumer.query", + params:{consumerGroup:consumerGroupName} + }).success(function (resp) { + if(resp.status ==0){ + console.log(resp); + ngDialog.open({ + template: 'consumerTopicViewDialog', + controller: 'consumerTopicViewDialogController', + data:{consumerGroupName:consumerGroupName,data:resp.data} + }); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + + $scope.client = function(consumerGroupName){ + $http({ + method: "GET", + url: "consumer/consumerConnection.query", + params:{consumerGroup:consumerGroupName} + }).success(function (resp) { + if(resp.status ==0){ + console.log(resp); + ngDialog.open({ + template: 'clientInfoDialog', + // controller: 'addTopicDialogController', + data:{data:resp.data,consumerGroupName:consumerGroupName} + }); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + $scope.updateConfigDialog = function(consumerGroupName){ + $http({ + method: "GET", + url: "consumer/examineSubscriptionGroupConfig.query", + params:{consumerGroup:consumerGroupName} + }).success(function (resp) { + if(resp.status ==0){ + console.log(resp); + $scope.openCreateOrUpdateDialog(resp.data); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + + + }; + $scope.delete = function(consumerGroupName){ + $http({ + method: "GET", + url: "consumer/fetchBrokerNameList.query", + params:{ + consumerGroup:consumerGroupName + } + }).success(function (resp) { + if(resp.status ==0){ + console.log(resp); + + ngDialog.open({ + template: 'deleteConsumerDialog', + controller: 'deleteConsumerDialogController', + data:{ + // allClusterList:Object.keys(resp.data.clusterInfo.clusterAddrTable), + allBrokerNameList:resp.data, + consumerGroupName:consumerGroupName + } + }); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + } + +}]) +module.controller('consumerMonitorDialogController', function ($scope, ngDialog, $http,Notification) { + $scope.createOrUpdateConsumerMonitor = function () { + $http({ + method: "POST", + url: "monitor/createOrUpdateConsumerMonitor.do", + params:{consumeGroupName:$scope.ngDialogData.consumerGroupName, + minCount:$scope.ngDialogData.data.minCount, + maxDiffTotal:$scope.ngDialogData.data.maxDiffTotal} + }).success(function (resp) { + if(resp.status ==0){ + Notification.info({message: "delete success!", delay: 2000}); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + } + } +); + + +module.controller('deleteConsumerDialogController', ['$scope', 'ngDialog', '$http','Notification',function ($scope, ngDialog, $http,Notification) { + $scope.selectedClusterList = []; + $scope.selectedBrokerNameList = []; + $scope.delete = function () { + console.log($scope.selectedClusterList); + console.log($scope.selectedBrokerNameList); + console.log($scope.ngDialogData.consumerGroupName); + $http({ + method: "POST", + url: "consumer/deleteSubGroup.do", + data:{groupName:$scope.ngDialogData.consumerGroupName, + brokerNameList:$scope.selectedBrokerNameList} + }).success(function (resp) { + if(resp.status ==0){ + Notification.info({message: "delete success!", delay: 2000}); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + } + }] +); + +module.controller('consumerModifyDialogController', ['$scope', 'ngDialog', '$http','Notification',function ($scope, ngDialog, $http,Notification) { + $scope.postConsumerRequest = function (consumerRequest) { + var request = JSON.parse(JSON.stringify(consumerRequest)); + console.log(request); + $http({ + method: "POST", + url: "consumer/createOrUpdate.do", + data:request + }).success(function (resp) { + if(resp.status ==0){ + Notification.info({message: "update success!", delay: 2000}); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + } + }] +); + +module.controller('consumerTopicViewDialogController', ['$scope', 'ngDialog', '$http', 'Notification', function ($scope, ngDialog, $http, Notification) { + $scope.consumerRunningInfo = function (consumerGroup, clientId, jstack) { + $http({ + method: "GET", + url: "consumer/consumerRunningInfo.query", + params: { + consumerGroup: consumerGroup, + clientId: clientId, + jstack: jstack + } + }).success(function (resp) { + if (resp.status == 0) { + ngDialog.open({ + template: 'consumerClientDialog', + data:{consumerClientInfo:resp.data, + clientId:clientId} + }); + } else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + }] +); + + + http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/controller.js ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/controller.js b/rocketmq-console-ng/src/main/resources/static/src/controller.js new file mode 100644 index 0000000..fbf041d --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/controller.js @@ -0,0 +1,557 @@ +/* + * 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. + */ +app.controller('AppCtrl', ['$scope','$rootScope','$cookies','$location','$translate', function ($scope,$rootScope,$cookies,$location,$translate) { + $scope.changeTranslate = function(langKey){ + $translate.use(langKey); + } +}]); + +app.controller('dashboardCtrl', ['$scope','$rootScope','$translate','$filter','Notification','remoteApi','tools', function ($scope,$rootScope,$translate,$filter,Notification,remoteApi,tools) { + + $scope.barChart = echarts.init(document.getElementById('main')); + $scope.lineChart = echarts.init(document.getElementById('line')); + $scope.topicBarChart = echarts.init(document.getElementById('topicBar')); + $scope.topicLineChart = echarts.init(document.getElementById('topicLine')); + $scope.timepickerOptions ={format: 'YYYY-MM-DD', showClear: true}; + $scope.topicNames = []; + + $translate('BROKER').then(function (broker) { + $scope.BROKER_TITLE = broker; + initBrokerBarChart(); + initBrokerLineChart(); + }, function (translationId) { + $scope.BROKER_TITLE = translationId; + }); + + $translate('TOPIC').then(function (topic) { + $scope.TOPIC_TITLE = topic; + initTopicBarChart(); + initTopicLineChart(); + }, function (translationId) { + $scope.TOPIC_TITLE = translationId; + }); + + var initBrokerBarChart = function(){ + $scope.barChart.setOption({ + title: { + text:$scope.BROKER_TITLE + ' TOP 10' + }, + tooltip: {}, + legend: { + data:['TotalMsg'] + }, + axisPointer : { + type : 'shadow' + }, + xAxis: { + data: [], + axisLabel: { + inside: false, + textStyle: { + color: '#000000' + }, + rotate: 0, + interval:0 + }, + axisTick: { + show: true + }, + axisLine: { + show: true + }, + z: 10 + }, + yAxis: { + type: 'value', + boundaryGap: [0, '100%'], + axisLabel: { + formatter: function(value){ + return value.toFixed(2); + } + }, + splitLine: { + show: true + } + }, + series: [{ + name: 'TotalMsg', + type: 'bar', + data: [] + }] + }) + } + + var initBrokerLineChart = function(){ + $scope.lineChart.setOption({ + title: { + text: $scope.BROKER_TITLE + ' 5min trend' + }, + toolbox: { + feature: { + dataZoom: { + yAxisIndex: 'none' + }, + restore: {}, + saveAsImage: {} + } + }, + tooltip: { + trigger: 'axis', + axisPointer: { + animation: false + } + }, + yAxis: { + type: 'value', + boundaryGap: [0, '80%'], + axisLabel: { + formatter: function(value){ + return value.toFixed(2); + } + }, + splitLine: { + show: true + } + }, + dataZoom: [{ + type: 'inside', + start: 90, + end: 100 + }, { + start: 0, + end: 10, + handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z', + handleSize: '80%', + handleStyle: { + color: '#fff', + shadowBlur: 3, + shadowColor: 'rgba(0, 0, 0, 0.6)', + shadowOffsetX: 2, + shadowOffsetY: 2 + } + }], + legend: { + data: [], + top:30 + }, + xAxis: { + type: 'time', + boundaryGap: false, + data: [] + }, + series: [] + }) + + } + + var initTopicBarChart = function(){ + $scope.topicBarChart.setOption({ + title: { + text:$scope.TOPIC_TITLE + ' TOP 10' + }, + tooltip: {}, + legend: { + data:['TotalMsg'] + }, + axisPointer : { + type : 'shadow' + }, + xAxis: { + data: [], + axisLabel: { + inside: false, + textStyle: { + color: '#000000' + }, + rotate: 0, + interval:0 + }, + axisTick: { + show: true + }, + axisLine: { + show: true + }, + z: 10 + }, + yAxis: { + type: 'value', + boundaryGap: [0, '100%'], + axisLabel: { + formatter: function(value){ + return value.toFixed(2); + } + }, + splitLine: { + show: true + } + }, + series: [{ + name: 'TotalMsg', + type: 'bar', + data: [] + }] + }) + } + + var initTopicLineChart = function(){ + var _option = { + baseOption:{ + title: { + text: $scope.TOPIC_TITLE + ' 5min trend' + }, + toolbox: { + feature: { + dataZoom: { + yAxisIndex: 'none' + }, + restore: {}, + saveAsImage: {} + } + }, + grid:{ + top:100 + }, + tooltip: { + trigger: 'axis', + axisPointer: { + animation: false + } + }, + yAxis: { + type: 'value', + boundaryGap: [0, '80%'], + axisLabel: { + formatter: function(value){ + return value.toFixed(2); + } + }, + splitLine: { + show: true + } + }, + dataZoom: [{ + type: 'inside', + start: 90, + end: 100 + }, { + start: 0, + end: 10, + handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z', + handleSize: '80%', + handleStyle: { + color: '#fff', + shadowBlur: 3, + shadowColor: 'rgba(0, 0, 0, 0.6)', + shadowOffsetX: 2, + shadowOffsetY: 2 + } + }], + legend:{ + data:[], + top:30 + }, + xAxis: { + type: 'time', + boundaryGap: false, + data: [] + }, + series: [] + } + } + $scope.topicLineChart.setOption(_option) + + } + + var getBrokerBarChartOp = function(xAxisData,data){ + // æå®å¾è¡¨çé ç½®é¡¹åæ°æ® + var option = { + xAxis: { + data: xAxisData, + axisLabel: { + inside: false, + textStyle: { + color: '#000000' + }, + rotate: 0, + interval:0 + }, + axisTick: { + show: true + }, + axisLine: { + show: true + }, + z: 10 + }, + series: [{ + name: 'TotalMsg', + type: 'bar', + data: data + }] + }; + + $scope.barChart.setOption(option); + } + + var callback = function (resp) { + $scope.barChart.hideLoading(); + if (resp.status == 0) { + var clusterMap = resp.data.clusterInfo.clusterAddrTable; + var brokerMap = resp.data.clusterInfo.brokerAddrTable; + var brokerDetail = resp.data.brokerServer; + var clusterMap = tools.generateBrokerMap(brokerDetail,clusterMap,brokerMap); + $scope.brokerArray = []; + $.each(clusterMap,function(clusterName,brokers){ + $.each(brokers,function(i,broker){ + $scope.brokerArray.push(broker) + }) + }) + + //sort the brokerArray + $scope.brokerArray.sort(function(firstBroker,lastBroker){ + var firstTotalMsg = parseFloat(firstBroker.msgGetTotalTodayNow); + var lastTotalMsg = parseFloat(lastBroker.msgGetTotalTodayNow); + return lastTotalMsg-firstTotalMsg; + }); + + var xAxisData = [], + data = []; + + $.each($scope.brokerArray,function(i,broker){ + if(i > 9){ + return false; + } + xAxisData.push(broker.brokerName + ":" + broker.index); + data.push(broker.msgGetTotalTodayNow); + }) + getBrokerBarChartOp(xAxisData,data); + }else{ + Notification.error({message: resp.errMsg, delay: 2000}); + } + } + + $scope.barChart.showLoading(); + remoteApi.queryClusterList(callback); + + $scope.topicBarChart.showLoading(); + remoteApi.queryTopicCurrentData(function(resp){ + $scope.topicBarChart.hideLoading(); + if (resp.status == 0) { + var topicList = resp.data; + topicList.sort(function(first,last){ + var firstTotalMsg = parseFloat(first.split(",")[1]); + var lastTotalMsg = parseFloat(last.split(",")[1]); + return lastTotalMsg-firstTotalMsg; + }) + + var xAxisData = []; + var data = []; + $.each(topicList,function (i,currentData) { + var currentArray = currentData.split(","); + $scope.topicNames.push(currentArray[0]); + if(!angular.isDefined($scope.selectedTopic)){ + $scope.selectedTopic = currentArray[0]; + } + }) + $.each(topicList,function (i, currentData) { + if(i > 9){ + return false; + } + var currentArray = currentData.split(","); + xAxisData.push(currentArray[0]); + data.push(currentArray[1]); + }) + // æå®å¾è¡¨çé ç½®é¡¹åæ°æ® + var option = { + xAxis: { + data: xAxisData, + axisLabel: { + inside: false, + textStyle: { + color: '#000000' + }, + rotate: 60, + interval:0 + }, + axisTick: { + show: true + }, + axisLine: { + show: true + }, + z: 10 + }, + series: [{ + name: 'TotalMsg', + type: 'bar', + data: data + }] + }; + $scope.topicBarChart.setOption(option); + queryLineData(); + }else{ + Notification.error({message: resp.errMsg, delay: 2000}); + } + }) + + + var getBrokerLineChart = function(legend,data){ + var series = []; + var xAxisData = []; + var flag = true; + var i = 0; + $.each(data,function(key,value){ + // if(i > 9 ){ + // return false; + // } + var _tps = []; + $.each(value,function(i,tpsValue){ + var tpsArray = tpsValue.split(","); + if(flag){ + xAxisData.push($filter('date')(tpsArray[0], "HH:mm:ss")); + } + _tps.push(tpsArray[1]); + }) + flag = false; + var _series = { + name:key, + type:'line', + smooth:true, + symbol: 'none', + sampling: 'average', + data: _tps + } + series.push(_series); + i++ + }) + + var option = { + legend: { + data: legend + }, + color: ["#FF0000", "#00BFFF", "#FF00FF", "#1ce322", "#000000", '#EE7942'], + xAxis: { + type: 'category', + boundaryGap: false, + data: xAxisData + }, + series: series + }; + return option; + } + + var getTopicLineChart = function(legend,data){ + var series = []; + var xAxisData = []; + var flag = true; + var i = 0; + $.each(data,function(key,value){ + var _tps = []; + $.each(value,function(i,tpsValue){ + var tpsArray = tpsValue.split(","); + if(flag){ + xAxisData.push($filter('date')(tpsArray[0], "HH:mm:ss")); + } + _tps.push(tpsArray[3]); + }) + flag = false; + var _series = { + name:key, + type:'line', + smooth:true, + symbol: 'none', + sampling: 'average', + data: _tps + } + series.push(_series); + i++ + }) + + var option = { + baseOption:{ + legend: { + data: legend + }, + // color: ["#FF0000", "#00BFFF", "#FF00FF", "#1ce322", "#000000", '#EE7942'], + xAxis: { + type: 'category', + boundaryGap: false, + data: xAxisData + }, + series: series + }, + media:[ + { + query:{}, + option:{ + + } + } + ] + + }; + return option; + } + + + var queryLineData = function () { + var _date; + if($scope.date != null){ + _date = $filter('date')($scope.date.valueOf(), "yyyy-MM-dd"); + }else{ + _date = $filter('date')(new Date(), "yyyy-MM-dd"); + } + // $scope.lineChart.showLoading(); + remoteApi.queryBrokerHisData(_date,function(resp){ + // $scope.lineChart.hideLoading(); + if (resp.status == 0) { + var _data = {} + var _xAxisData = []; + $.each(resp.data,function(address,values){ + _data[address] = values; + _xAxisData.push(address); + }) + $scope.lineChart.setOption(getBrokerLineChart(_xAxisData,_data)); + }else{ + Notification.error({message: "" + resp.errMsg, delay: 2000}); + } + }) + + $scope.topicLineChart.showLoading(); + remoteApi.queryTopicHisData(_date,$scope.selectedTopic,function (resp) { + $scope.topicLineChart.hideLoading(); + if (resp.status == 0) { + var _data = {}; + _data[$scope.selectedTopic] = resp.data; + var _xAxisData = $scope.selectedTopic; + $scope.topicLineChart.setOption(getTopicLineChart(_xAxisData,_data)); + }else{ + Notification.error({message: "" + resp.errMsg, delay: 2000}); + } + + }) + + } + + //router after will clear this thread + $rootScope._thread = setInterval( queryLineData, tools.dashboardRefreshTime); + + +}]); + + http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/data/dict.json ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/data/dict.json b/rocketmq-console-ng/src/main/resources/static/src/data/dict.json new file mode 100644 index 0000000..defdab3 --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/data/dict.json @@ -0,0 +1,4 @@ +[ + {"TYPE":"DEMO_TYPE","DICT_VALUE":"0","DICT_NAME":"test1"}, + {"TYPE":"DEMO_TYPE","DICT_VALUE":"1","DICT_NAME":"test2"} +] \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/i18n/en.js ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/i18n/en.js b/rocketmq-console-ng/src/main/resources/static/src/i18n/en.js new file mode 100644 index 0000000..d0074c2 --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/i18n/en.js @@ -0,0 +1,80 @@ +var en = { + "TITLE": "RocketMq-Console-Ng", + "CLOSE": "Close", + "NO": "NO.", + "ADDRESS": "Address", + "VERSION": "Version", + "PRO_MSG_TPS": "Produce Massage TPS", + "CUS_MSG_TPS": "Consumer Massage TPS", + "YESTERDAY_PRO_COUNT": "Yesterday Produce Count", + "YESTERDAY_CUS_COUNT": "Yesterday Consume Count", + "TODAY_PRO_COUNT": "Today Produce Count", + "TODAY_CUS_COUNT": "Today Ponsume Count", + "INSTANCE": "Instance", + "SPLIT": "Broker", + "CLUSTER": "Cluster", + "CLUSTER_DETAIL": "Cluster Detail", + "TOPIC": "Topic", + "SUBSCRIPTION_GROUP":"SubscriptionGroup", + "PRODUCER_GROUP":"ProducerGroup", + "CONSUMER":"Consumer", + "PRODUCER":"Producer", + "MESSAGE":"Message", + "COMMIT": "Commit", + "OPERATION": "Operation", + "ADD": "Add", + "UPDATE": "Update", + "STATUS": "Status", + "ROUTER": "Router", + "MANAGE": "Manage", + "CONFIG": "Config", + "SEND_MSG": "Send Massage", + "RESET_CUS_OFFSET": "Reset Consumer Offset", + "DELETE": "Delete", + "CHANGE_LANG": "ChangeLanguage", + "BROKER": "Broker", + "NORMAL": "NORMAL", + "RETRY": "RETRY", + "DLQ": "DLQ", + "QUANTITY":"Quantity", + "TYPE":"Type", + "MODE":"Mode", + "DELAY":"Delay", + "DASHBOARD":"Dashboard", + "CONSUME_DETAIL":"CONSUME DETAIL", + "CLIENT":"CLIENT", + "LAST_CONSUME_TIME":"LastConsumeTime", + "TIME":"Time", + "RESET":"RESET", + "DATE":"Date", + "NO_DATA":"NO DATA", + "SEARCH":"Search", + "BEGIN":"Begin", + "END":"End", + "TOPIC_CHANGE":"Topic Change", + "SEND":"Send", + "SUBSCRIPTION_CHANGE":"Subscription Change", + "QUEUE":"Queue", + "MIN_OFFSET":"minOffset", + "MAX_OFFSET":"maxOffset", + "LAST_UPDATE_TIME_STAMP":"lastUpdateTimeStamp", + "QUEUE_DATAS":"queueDatas", + "READ_QUEUE_NUMS":"readQueueNums", + "WRITE_QUEUE_NUMS":"writeQueueNums", + "PERM":"perm", + "TAG":"Tag", + "KEY":"Key", + "MESSAGE_BODY":"Message Body", + "TOPIC_NAME":"topicName", + "ORDER":"order", + "CONSUMER_CLIENT":"consumerClient", + "BROKER_OFFSET":"brokerOffset", + "CONSUMER_OFFSET":"consumerOffset", + "DIFF_TOTAL":"diffTotal", + "LAST_TIME_STAMP":"lastTimeStamp", + "RESET_OFFSET":"resetOffset", + "CLUSTER_NAME":"clusterName", + "OPS":"OPS", + "AUTO_REFRESH":"AUTO_REFRESH", + "REFRESH":"REFRESH" +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/i18n/zh.js ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/i18n/zh.js b/rocketmq-console-ng/src/main/resources/static/src/i18n/zh.js new file mode 100644 index 0000000..6cf39f0 --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/i18n/zh.js @@ -0,0 +1,80 @@ +var zh = { + "TITLE": "RocketMqæ§å¶å°", + "CLOSE": "å ³é", + "NO": "ç¼å·", + "ADDRESS": "å°å", + "VERSION": "çæ¬", + "PRO_MSG_TPS": "çäº§æ¶æ¯TPS", + "CUS_MSG_TPS": "æ¶è´¹æ¶æ¯TPS", + "YESTERDAY_PRO_COUNT": "æ¨æ¥çäº§æ»æ°", + "YESTERDAY_CUS_COUNT": "æ¨æ¥æ¶è´¹æ»æ°", + "TODAY_PRO_COUNT": "ä»å¤©çäº§æ»æ°", + "TODAY_CUS_COUNT": "ä»å¤©æ¶è´¹æ»æ°", + "INSTANCE": "å®ä¾", + "SPLIT": "åç", + "CLUSTER": "é群", + "CLUSTER_DETAIL": "é群详æ ", + "COMMIT": "æäº¤", + "TOPIC": "主é¢", + "SUBSCRIPTION_GROUP":"订é ç»", + "PRODUCER_GROUP":"ç产ç»", + "CONSUMER":"æ¶è´¹è ", + "PRODUCER":"ç产è ", + "MESSAGE":"æ¶æ¯", + "OPERATION": "æä½", + "ADD": "æ°å¢", + "UPDATE": "æ´æ°", + "STATUS": "ç¶æ", + "ROUTER": "è·¯ç±", + "MANAGE": "管ç", + "CONFIG": "é ç½®", + "SEND_MSG": "åéæ¶æ¯", + "RESET_CUS_OFFSET": "éç½®æ¶è´¹ä½ç¹", + "DELETE": "å é¤", + "CHANGE_LANG": "æ´æ¢è¯è¨", + "BROKER": "Broker", + "NORMAL": "æ®é", + "RETRY": "éè¯", + "DLQ": "æ»ä¿¡", + "QUANTITY":"æ°é", + "TYPE":"ç±»å", + "MODE":"模å¼", + "DELAY":"å»¶è¿", + "DASHBOARD":"驾驶è±", + "CONSUME_DETAIL":"æ¶è´¹è¯¦æ ", + "CLIENT":"ç»ç«¯", + "LAST_CONSUME_TIME":"æåæ¶è´¹æ¶é´", + "TIME":"æ¶é´ç¹", + "RESET":"éç½®", + "DATE":"æ¥æ", + "NO_DATA":"ææ æ°æ®", + "SEARCH":"æç´¢", + "BEGIN":"å¼å§", + "END":"ç»æ", + "TOPIC_CHANGE":"ä¿®æ¹ä¸»é¢", + "SEND":"åé", + "SUBSCRIPTION_CHANGE":"ä¿®æ¹è®¢é ", + "QUEUE":"éå", + "MIN_OFFSET":"æå°ä½ç¹", + "MAX_OFFSET":"æå¤§ä½ç¹", + "LAST_UPDATE_TIME_STAMP":"䏿¬¡æ´æ°æ¶é´", + "QUEUE_DATAS":"éåä¿¡æ¯", + "READ_QUEUE_NUMS":"读éåæ°é", + "WRITE_QUEUE_NUMS":"åéåæ°é", + "PERM":"perm", + "TAG":"æ ç¾", + "KEY":"å¼", + "MESSAGE_BODY":"æ¶æ¯ä¸»ä½", + "TOPIC_NAME":"主é¢å", + "ORDER":"顺åº", + "CONSUMER_CLIENT":"æ¶è´¹è ç»ç«¯", + "BROKER_OFFSET":"代çè ä½ç¹", + "CONSUMER_OFFSET":"æ¶è´¹è ä½ç¹", + "DIFF_TOTAL":"å·®å¼", + "LAST_TIME_STAMP":"䏿¬¡æ¶é´", + "RESET_OFFSET":"éç½®ä½ç¹", + "CLUSTER_NAME":"é群å", + "OPS":"è¿ç»´", + "AUTO_REFRESH":"èªå¨å·æ°", + "REFRESH":"å·æ°" +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/message.js ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/message.js b/rocketmq-console-ng/src/main/resources/static/src/message.js new file mode 100644 index 0000000..fca286c --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/message.js @@ -0,0 +1,200 @@ +/* + * 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 module = app; + +module.controller('messageController', ['$scope', 'ngDialog', '$http','Notification',function ($scope, ngDialog, $http,Notification) { + $scope.allTopicList = []; + $scope.selectedTopic =[]; + $scope.key =""; + $scope.messageId =""; + $scope.queryMessageByTopicResult=[]; + $scope.queryMessageByTopicAndKeyResult=[]; + $scope.queryMessageByMessageIdResult={}; + $http({ + method: "GET", + url: "topic/list.query" + }).success(function (resp) { + if(resp.status ==0){ + $scope.allTopicList = resp.data.topicList.sort(); + console.log($scope.allTopicList); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + $scope.timepickerBegin = moment().subtract(1, 'hour').format('YYYY-MM-DD HH:mm'); + $scope.timepickerEnd = moment().add(1,'hour').format('YYYY-MM-DD HH:mm'); + $scope.timepickerOptions ={format: 'YYYY-MM-DD HH:mm', showClear: true}; + + $scope.paginationConf = { + currentPage: 1, + totalItems: 0, + itemsPerPage: 20, + pagesLength: 15, + perPageOptions: [10], + rememberPerPage: 'perPageItems', + onChange: function () { + $scope.changeShowMessageList(this.currentPage,this.totalItems); + } + }; + + + $scope.queryMessageByTopic = function () { + console.log($scope.selectedTopic); + console.log($scope.timepickerBegin) + console.log($scope.timepickerEnd) + $http({ + method: "GET", + url: "message/queryMessageByTopic.query", + params: { + topic: $scope.selectedTopic, + begin: $scope.timepickerBegin.valueOf(), + end: $scope.timepickerEnd.valueOf() + + } + }).success(function (resp) { + if (resp.status == 0) { + console.log(resp); + $scope.queryMessageByTopicResult = resp.data; + $scope.changeShowMessageList(1,$scope.queryMessageByTopicResult.length); + // todo + // console.log($scope.queryMessageByTopicResult); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + + $scope.queryMessageByTopicAndKey = function () { + console.log($scope.selectedTopic); + console.log($scope.key); + $http({ + method: "GET", + url: "message/queryMessageByTopicAndKey.query", + params: { + topic: $scope.selectedTopic, + key:$scope.key + } + }).success(function (resp) { + if (resp.status == 0) { + console.log(resp); + $scope.queryMessageByTopicAndKeyResult = resp.data; + console.log($scope.queryMessageByTopicAndKeyResult); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + + $scope.queryMessageByBrokerAndOffset = function (storeHost,commitLogOffset) { + $http({ + method: "GET", + url: "message/viewMessageByBrokerAndOffset.query", + params: { + brokerHost: storeHost.address, + port:storeHost.port, + offset: commitLogOffset + } + }).success(function (resp) { + if (resp.status == 0) { + console.log(resp); + ngDialog.open({ + template: 'messageDetailViewDialog', + controller: 'messageDetailViewDialogController', + data: resp.data + }); + } else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + + $scope.queryMessageByMessageId = function (messageId,topic) { + $http({ + method: "GET", + url: "message/viewMessage.query", + params: { + msgId: messageId, + topic:topic + } + }).success(function (resp) { + if (resp.status == 0) { + console.log(resp); + ngDialog.open({ + template: 'messageDetailViewDialog', + controller: 'messageDetailViewDialogController', + data:resp.data + }); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + + + $scope.changeShowMessageList = function (currentPage,totalItem) { + var perPage = $scope.paginationConf.itemsPerPage; + var from = (currentPage - 1) * perPage; + var to = (from + perPage)>totalItem?totalItem:from + perPage; + $scope.messageShowList = $scope.queryMessageByTopicResult.slice(from, to); + $scope.paginationConf.totalItems = totalItem ; + }; +}]); + +module.controller('messageDetailViewDialogController',['$scope', 'ngDialog', '$http','Notification', function ($scope, ngDialog, $http,Notification) { + + $scope.resendMessage = function (msgId,topic,consumerGroup) { + $http({ + method: "POST", + url: "message/consumeMessageDirectly.do", + params: { + msgId: msgId, + consumerGroup:consumerGroup, + topic:topic + } + }).success(function (resp) { + if (resp.status == 0) { + ngDialog.open({ + template: 'operationResultDialog', + data:{ + result:resp.data + } + }); + } + else { + ngDialog.open({ + template: 'operationResultDialog', + data:{ + result:resp.errMsg + } + }); + } + }); + }; + $scope.showExceptionDesc = function (errmsg) { + if(errmsg == null){ + errmsg = "Don't have Exception" + } + ngDialog.open({ + template: 'operationResultDialog', + data:{ + result:errmsg + } + }); + }; + }] +); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/ops.js ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/ops.js b/rocketmq-console-ng/src/main/resources/static/src/ops.js new file mode 100644 index 0000000..312e41f --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/ops.js @@ -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. + */ + +app.controller('opsController', ['$scope','$location','$http','Notification','remoteApi','tools', function ($scope,$location,$http,Notification,remoteApi,tools) { + $scope.namesvrAddrList = []; + $scope.useVIPChannel = true; + $http({ + method: "GET", + url: "ops/homePage.query" + }).success(function (resp) { + if (resp.status == 0) { + $scope.namesvrAddrList = resp.data.namesvrAddrList; + $scope.useVIPChannel = resp.data.useVIPChannel + }else{ + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + + $scope.updateNameSvrAddr = function () { + $http({ + method: "POST", + url: "ops/updateNameSvrAddr.do", + params:{nameSvrAddrList:$scope.namesvrAddrList.join(";")} + }).success(function (resp) { + if (resp.status == 0) { + Notification.info({message: "SUCCESS", delay: 2000}); + }else{ + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + $scope.updateIsVIPChannel = function () { + $http({ + method: "POST", + url: "ops/updateIsVIPChannel.do", + params:{useVIPChannel:$scope.useVIPChannel} + }).success(function (resp) { + if (resp.status == 0) { + Notification.info({message: "SUCCESS", delay: 2000}); + }else{ + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + } +}]); http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/producer.js ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/producer.js b/rocketmq-console-ng/src/main/resources/static/src/producer.js new file mode 100644 index 0000000..3c039ad --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/producer.js @@ -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. + */ + +var module = app; +module.controller('producerController', ['$scope', '$http','Notification',function ($scope, $http,Notification) { + $scope.selectedTopic=[]; + $scope.producerGroup=""; + $http({ + method: "GET", + url: "topic/list.query" + }).success(function (resp) { + if(resp.status ==0){ + $scope.allTopicList = resp.data.topicList.sort(); + console.log($scope.allTopicList); + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + $scope.queryClientByTopicAndGroup = function () { + $http({ + method: "GET", + url: "producer/producerConnection.query", + params:{ + topic:$scope.selectedTopic, + producerGroup:$scope.producerGroup + } + }).success(function (resp) { + if(resp.status ==0){ + $scope.connectionList = resp.data.connectionSet; + }else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + } +} ]); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/remoteApi/remoteApi.js ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/remoteApi/remoteApi.js b/rocketmq-console-ng/src/main/resources/static/src/remoteApi/remoteApi.js new file mode 100644 index 0000000..1189771 --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/remoteApi/remoteApi.js @@ -0,0 +1,75 @@ +/* + * 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. + */ +app.service('remoteApi', ['$http','tools', function ($http,tools) { + var queryTopic = function(callback){ + $http({ + method: "GET", + url: "topic/list.query" + }).success(callback); + } + + var queryClusterList = function(callback){ + $http({ + method: "GET", + url: "cluster/list.query" + }).success(callback); + } + + var queryBrokerHisData = function(date,callback){ + var url = 'dashboard/broker.query'; + var data = {date:date}; + var setting = { + type: "GET", + data:data, + timeout:15000,//data is too large,so master set time out is long enough + success:callback + } + $.ajax(url,setting) + } + + var queryTopicHisData = function(date,topicName,callback){ + var url = 'dashboard/topic.query'; + var data = {date:date,topicName:topicName}; + var setting = { + type: "GET", + data:data, + timeout:15000,//data is too large,so master set time out is long enough + success:callback + } + $.ajax(url,setting) + } + + var queryTopicCurrentData = function(callback){ + var url = 'dashboard/topicCurrent'; + var setting = { + type: "GET", + timeout:15000,//data is too large,so master set time out is long enough + success:callback + } + $.ajax(url,setting) + } + + + return { + queryTopic:queryTopic, + queryClusterList:queryClusterList, + queryBrokerHisData:queryBrokerHisData, + queryTopicHisData:queryTopicHisData, + queryTopicCurrentData:queryTopicCurrentData + } +}]) + http://git-wip-us.apache.org/repos/asf/incubator-rocketmq-externals/blob/4b8f1357/rocketmq-console-ng/src/main/resources/static/src/tools/tools.js ---------------------------------------------------------------------- diff --git a/rocketmq-console-ng/src/main/resources/static/src/tools/tools.js b/rocketmq-console-ng/src/main/resources/static/src/tools/tools.js new file mode 100644 index 0000000..780f088 --- /dev/null +++ b/rocketmq-console-ng/src/main/resources/static/src/tools/tools.js @@ -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. + */ + +app.service('tools', ['$http', function ($http) { + + var ctx = ""; + var dashboardRefreshTime = 5000; // todo improve. when data size is large,request is too slow + + var generateBrokerMap = function(brokerDetail,clusterMap,brokerMap){ + var map = {}; + $.each(brokerDetail,function(k,v){ + $.each(clusterMap,function (ck, cv) { + if(angular.isUndefined(map[ck])){ + map[ck] = []; + } + $.each(cv,function(cvi,cvv){ + if(cvv == k){ + var index = 0; + $.each(v,function(vi,vv){ + vv.split = k; + vv.index = index; + vv.address = brokerMap[cvv].brokerAddrs[index]; + vv.brokerName = brokerMap[cvv].brokerName; + map[ck].push(vv); + index++; + }) + } + }) + }) + }) + return map; + } + + var fastSort = function (arrayToSort, propertyToSortWith, sortDirection) { + // temporary holder of position and sort-value + var map = arrayToSort.map(function (e, i) { + if (typeof e[propertyToSortWith] === 'string') { + return { index: i, value: e[propertyToSortWith].toLowerCase() }; + } + else { + return { index: i, value: e[propertyToSortWith] }; + } + + }) + + // sorting the map containing the reduced values + map.sort(function (a, b) { + if (sortDirection === "ascending") { + return +(a.value > b.value) || +(a.value === b.value) - 1; + } + else { + return +(a.value < b.value) || +(a.value === b.value) - 1; + } + + }); + + // container for the resulting order + var result = map.map(function (e) { + return arrayToSort[e.index]; + }); + return result; + }; + + return { + generateBrokerMap:generateBrokerMap, + fastSort:fastSort, + ctx:ctx, + dashboardRefreshTime:dashboardRefreshTime + } +}]) + + +
