diff --git a/pom.xml b/pom.xml index 2b61bfc3..a89cb185 100644 --- a/pom.xml +++ b/pom.xml @@ -163,6 +163,21 @@ + + org.apache.rocketmq + rocketmq-proxy + ${rocketmq.version} + + + ch.qos.logback + logback-classic + + + ch.qos.logback + logback-core + + + org.apache.rocketmq rocketmq-namesrv diff --git a/src/main/java/org/apache/rocketmq/dashboard/config/RMQConfigure.java b/src/main/java/org/apache/rocketmq/dashboard/config/RMQConfigure.java index 991a2d8e..bffd1c45 100644 --- a/src/main/java/org/apache/rocketmq/dashboard/config/RMQConfigure.java +++ b/src/main/java/org/apache/rocketmq/dashboard/config/RMQConfigure.java @@ -62,6 +62,10 @@ public class RMQConfigure { private List namesrvAddrs = new ArrayList<>(); + private volatile String proxyAddr; + + private List proxyAddrs = new ArrayList<>(); + public String getAccessKey() { return accessKey; } @@ -86,6 +90,25 @@ public List getNamesrvAddrs() { return namesrvAddrs; } + public List getProxyAddrs() { + return this.proxyAddrs; + } + + public void setProxyAddrs(List proxyAddrs) { + this.proxyAddrs = proxyAddrs; + if (CollectionUtils.isNotEmpty(proxyAddrs)) { + this.setProxyAddr(proxyAddrs.get(0)); + } + } + + public String getProxyAddr() { + return proxyAddr; + } + + public void setProxyAddr(String proxyAddr) { + this.proxyAddr = proxyAddr; + } + public void setNamesrvAddrs(List namesrvAddrs) { this.namesrvAddrs = namesrvAddrs; if (CollectionUtils.isNotEmpty(namesrvAddrs)) { diff --git a/src/main/java/org/apache/rocketmq/dashboard/controller/ProxyController.java b/src/main/java/org/apache/rocketmq/dashboard/controller/ProxyController.java new file mode 100644 index 00000000..cdef150d --- /dev/null +++ b/src/main/java/org/apache/rocketmq/dashboard/controller/ProxyController.java @@ -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. + */ +package org.apache.rocketmq.dashboard.controller; + +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.dashboard.permisssion.Permission; +import org.apache.rocketmq.dashboard.service.ProxyService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; + +@Controller +@RequestMapping("/proxy") +@Permission +public class ProxyController { + @Resource + private ProxyService proxyService; + @RequestMapping(value = "/homePage.query", method = RequestMethod.GET) + @ResponseBody + public Object homePage() { + return proxyService.getProxyHomePage(); + } + + @RequestMapping(value = "/proxyDetailConfig.query", method = RequestMethod.GET) + @ResponseBody + public Object queryProxyDetailConfig(@RequestParam String proxyAddress) throws MQBrokerException { + return proxyService.getProxyDetailConfig(proxyAddress); + } + + @RequestMapping(value = "/addProxyAddr.do", method = RequestMethod.POST) + @ResponseBody + public Object addProxyAddr(@RequestParam String newProxyAddr) { + proxyService.addProxyAddrList(newProxyAddr); + return true; + } + + @RequestMapping(value = "/updateProxyAddr.do", method = RequestMethod.POST) + @ResponseBody + public Object updateProxyAddr(@RequestParam String proxyAddr) { + proxyService.updateProxyAddrList(proxyAddr); + return true; + } +} diff --git a/src/main/java/org/apache/rocketmq/dashboard/controller/TopicController.java b/src/main/java/org/apache/rocketmq/dashboard/controller/TopicController.java index ebed69e1..467c18e4 100644 --- a/src/main/java/org/apache/rocketmq/dashboard/controller/TopicController.java +++ b/src/main/java/org/apache/rocketmq/dashboard/controller/TopicController.java @@ -56,6 +56,12 @@ public Object list(@RequestParam(value = "skipSysProcess", required = false) boo return topicService.fetchAllTopicList(skipSysProcess, skipRetryAndDlq); } + @RequestMapping(value = "/list.queryTopicType", method = RequestMethod.GET) + @ResponseBody + public Object listTopicType() { + return topicService.examineAllTopicType(); + } + @RequestMapping(value = "/stats.query", method = RequestMethod.GET) @ResponseBody public Object stats(@RequestParam String topic) { diff --git a/src/main/java/org/apache/rocketmq/dashboard/model/request/TopicTypeList.java b/src/main/java/org/apache/rocketmq/dashboard/model/request/TopicTypeList.java new file mode 100644 index 00000000..e7b8148f --- /dev/null +++ b/src/main/java/org/apache/rocketmq/dashboard/model/request/TopicTypeList.java @@ -0,0 +1,45 @@ +/* + * 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.dashboard.model.request; + +import java.util.List; + +public class TopicTypeList { + private List topicNameList; + private List messageTypeList; + + public List getTopicNameList() { + return topicNameList; + } + + public void setTopicNameList(List topicNameList) { + this.topicNameList = topicNameList; + } + + public List getMessageTypeList() { + return messageTypeList; + } + + public void setMessageTypeList(List messageTypeList) { + this.messageTypeList = messageTypeList; + } + + public TopicTypeList(List topicNameList, List messageTypeList) { + this.topicNameList = topicNameList; + this.messageTypeList = messageTypeList; + } +} diff --git a/src/main/java/org/apache/rocketmq/dashboard/model/request/TopicTypeMeta.java b/src/main/java/org/apache/rocketmq/dashboard/model/request/TopicTypeMeta.java new file mode 100644 index 00000000..a1fe9350 --- /dev/null +++ b/src/main/java/org/apache/rocketmq/dashboard/model/request/TopicTypeMeta.java @@ -0,0 +1,38 @@ +/* + * 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.dashboard.model.request; + +public class TopicTypeMeta { + private String topicName; + private String messageType; + + public String getTopicName() { + return topicName; + } + + public void setTopicName(String topicName) { + this.topicName = topicName; + } + + public String getMessageType() { + return messageType; + } + + public void setMessageType(String messageType) { + this.messageType = messageType; + } +} diff --git a/src/main/java/org/apache/rocketmq/dashboard/service/ProxyService.java b/src/main/java/org/apache/rocketmq/dashboard/service/ProxyService.java new file mode 100644 index 00000000..68ba8f9a --- /dev/null +++ b/src/main/java/org/apache/rocketmq/dashboard/service/ProxyService.java @@ -0,0 +1,32 @@ +/* + * 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.dashboard.service; + +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.proxy.config.ProxyConfig; + +import java.util.Map; + +public interface ProxyService { + ProxyConfig getProxyDetailConfig(String proxyAddr) throws MQBrokerException; + + void addProxyAddrList(String proxyAddr); + + void updateProxyAddrList(String proxyAddr); + + Map getProxyHomePage(); +} diff --git a/src/main/java/org/apache/rocketmq/dashboard/service/TopicService.java b/src/main/java/org/apache/rocketmq/dashboard/service/TopicService.java index 3a28444f..9ff0bf0c 100644 --- a/src/main/java/org/apache/rocketmq/dashboard/service/TopicService.java +++ b/src/main/java/org/apache/rocketmq/dashboard/service/TopicService.java @@ -19,6 +19,7 @@ import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.common.TopicConfig; +import org.apache.rocketmq.dashboard.model.request.TopicTypeList; import org.apache.rocketmq.remoting.protocol.admin.TopicStatsTable; import org.apache.rocketmq.remoting.protocol.body.GroupList; import org.apache.rocketmq.remoting.protocol.body.TopicList; @@ -31,6 +32,8 @@ public interface TopicService { TopicList fetchAllTopicList(boolean skipSysProcess, boolean skipRetryAndDlq); + TopicTypeList examineAllTopicType(); + TopicStatsTable stats(String topic); TopicRouteData route(String topic); diff --git a/src/main/java/org/apache/rocketmq/dashboard/service/client/ProxyAdmin.java b/src/main/java/org/apache/rocketmq/dashboard/service/client/ProxyAdmin.java new file mode 100644 index 00000000..a4b84d9a --- /dev/null +++ b/src/main/java/org/apache/rocketmq/dashboard/service/client/ProxyAdmin.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.dashboard.service.client; + +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.proxy.config.ProxyConfig; + +public interface ProxyAdmin { + ProxyConfig examineProxyConfig(String addr) throws MQBrokerException; +} diff --git a/src/main/java/org/apache/rocketmq/dashboard/service/client/ProxyAdminImpl.java b/src/main/java/org/apache/rocketmq/dashboard/service/client/ProxyAdminImpl.java new file mode 100644 index 00000000..120e4539 --- /dev/null +++ b/src/main/java/org/apache/rocketmq/dashboard/service/client/ProxyAdminImpl.java @@ -0,0 +1,65 @@ +/* + * 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.dashboard.service.client; + +import com.google.common.base.Throwables; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.proxy.config.ProxyConfig; +import org.apache.rocketmq.remoting.RemotingClient; +import org.apache.rocketmq.remoting.protocol.RemotingCommand; +import org.apache.rocketmq.remoting.protocol.RemotingSerializable; +import org.apache.rocketmq.remoting.protocol.ResponseCode; +import org.apache.rocketmq.tools.admin.MQAdminExt; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class ProxyAdminImpl implements ProxyAdmin { + @Autowired + private GenericObjectPool mqAdminExtPool; + + @Override + public ProxyConfig examineProxyConfig(String addr) throws MQBrokerException { + try { + MQAdminInstance.createMQAdmin(mqAdminExtPool); + RemotingClient remotingClient = MQAdminInstance.threadLocalRemotingClient(); + RemotingCommand request = RemotingCommand.createRequestCommand(514, null); + RemotingCommand response = null; + try { + response = remotingClient.invokeSync(addr, request, 3000); + } catch (Exception err) { + Throwables.throwIfUnchecked(err); + throw new RuntimeException(err); + } + switch (response.getCode()) { + case ResponseCode.SUCCESS: { + ProxyConfig proxyConfig = RemotingSerializable.decode(response.getBody(), ProxyConfig.class); + log.info("addr=" + addr + ",proxyConfig=" + proxyConfig); + return proxyConfig; + } + default: + throw new MQBrokerException(response.getCode(), response.getRemark()); + } + } finally { + MQAdminInstance.returnMQAdmin(mqAdminExtPool); + } + } + +} diff --git a/src/main/java/org/apache/rocketmq/dashboard/service/impl/ProxyServiceImpl.java b/src/main/java/org/apache/rocketmq/dashboard/service/impl/ProxyServiceImpl.java new file mode 100644 index 00000000..1941f5c7 --- /dev/null +++ b/src/main/java/org/apache/rocketmq/dashboard/service/impl/ProxyServiceImpl.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.dashboard.service.impl; + +import com.google.common.collect.Maps; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.dashboard.config.RMQConfigure; +import org.apache.rocketmq.dashboard.service.ProxyService; +import org.apache.rocketmq.dashboard.service.client.ProxyAdmin; +import org.apache.rocketmq.proxy.config.ProxyConfig; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +@Slf4j +@Service +public class ProxyServiceImpl implements ProxyService { + @Resource + protected ProxyAdmin proxyAdmin; + @Resource + private RMQConfigure configure; + + @Override + public ProxyConfig getProxyDetailConfig(String proxyAddr) throws MQBrokerException { + ProxyConfig proxyConfig = proxyAdmin.examineProxyConfig(proxyAddr); + return proxyConfig; + } + + + @Override + public void addProxyAddrList(String proxyAddr) { + List proxyAddrs = configure.getProxyAddrs(); + if (proxyAddrs != null && !proxyAddrs.contains(proxyAddr)) { + proxyAddrs.add(proxyAddr); + } + configure.setProxyAddrs(proxyAddrs); + } + + @Override + public void updateProxyAddrList(String proxyAddr) { + configure.setProxyAddr(proxyAddr); + } + + @Override + public Map getProxyHomePage() { + Map homePageInfoMap = Maps.newHashMap(); + homePageInfoMap.put("currentProxyAddr", configure.getProxyAddr()); + homePageInfoMap.put("proxyAddrList", configure.getProxyAddrs()); + return homePageInfoMap; + } +} diff --git a/src/main/java/org/apache/rocketmq/dashboard/service/impl/TopicServiceImpl.java b/src/main/java/org/apache/rocketmq/dashboard/service/impl/TopicServiceImpl.java index ecd08de2..4f34fc64 100644 --- a/src/main/java/org/apache/rocketmq/dashboard/service/impl/TopicServiceImpl.java +++ b/src/main/java/org/apache/rocketmq/dashboard/service/impl/TopicServiceImpl.java @@ -40,6 +40,8 @@ import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.model.request.SendTopicMessageRequest; import org.apache.rocketmq.dashboard.model.request.TopicConfigInfo; +import org.apache.rocketmq.dashboard.model.request.TopicTypeList; +import org.apache.rocketmq.dashboard.model.request.TopicTypeMeta; import org.apache.rocketmq.dashboard.service.AbstractCommonService; import org.apache.rocketmq.dashboard.service.TopicService; import org.apache.rocketmq.remoting.RPCHook; @@ -54,7 +56,9 @@ import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -99,6 +103,41 @@ public TopicList fetchAllTopicList(boolean skipSysProcess, boolean skipRetryAndD } } + @Override + public TopicTypeList examineAllTopicType() { + ArrayList topicTypes = new ArrayList<>(); + ArrayList names = new ArrayList<>(); + ArrayList messageTypes = new ArrayList<>(); + TopicList topicList = fetchAllTopicList(false, false); + checkTopicType(topicList, topicTypes); + topicTypes.sort((t1, t2) -> t1.getTopicName().compareTo(t2.getTopicName())); + for (TopicTypeMeta topicTypeMeta : topicTypes) { + names.add(topicTypeMeta.getTopicName()); + messageTypes.add(topicTypeMeta.getMessageType()); + } + return new TopicTypeList(names, messageTypes); + } + + private void checkTopicType(TopicList topicList, ArrayList topicTypes) { + for (String topicName : topicList.getTopicList()) { + TopicTypeMeta topicType = new TopicTypeMeta(); + topicType.setTopicName(topicName); + if (topicName.startsWith("%R")) { + topicType.setMessageType("RETRY"); + } else if (topicName.startsWith("%D")) { + topicType.setMessageType("DELAY"); + } else if (topicName.startsWith("%S")) { + topicType.setMessageType("SYSTEM"); + } else { + List topicConfigInfos = examineTopicConfig(topicName); + if (!CollectionUtils.isEmpty(topicConfigInfos)) { + topicType.setMessageType(topicConfigInfos.get(0).getMessageType()); + } + } + topicTypes.add(topicType); + } + } + @Override public TopicStatsTable stats(String topic) { try { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 090e4216..62225b58 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -62,6 +62,9 @@ rocketmq: # set the accessKey and secretKey if you used acl # accessKey: rocketmq2 # secretKey: 12345678 + proxyAddr: 127.0.0.1:8080 + proxyAddrs: + - 127.0.0.1:8080 threadpool: config: diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index c2bf349c..7928ac60 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -109,6 +109,7 @@ + diff --git a/src/main/resources/static/src/app.js b/src/main/resources/static/src/app.js index a7ca1bef..ec4e96d4 100644 --- a/src/main/resources/static/src/app.js +++ b/src/main/resources/static/src/app.js @@ -192,6 +192,9 @@ app.config(['$routeProvider', '$httpProvider','$cookiesProvider','getDictNamePro }).when('/cluster', { templateUrl: 'view/pages/cluster.html', controller:'clusterController' + }).when('/proxy', { + templateUrl: 'view/pages/proxy.html', + controller:'proxyController' }).when('/topic', { templateUrl: 'view/pages/topic.html', controller:'topicController' diff --git a/src/main/resources/static/src/controller.js b/src/main/resources/static/src/controller.js index cdcced59..65d7937c 100644 --- a/src/main/resources/static/src/controller.js +++ b/src/main/resources/static/src/controller.js @@ -15,10 +15,31 @@ * limitations under the License. */ app.controller('AppCtrl', ['$scope','$window','$translate','$http','Notification', function ($scope,$window,$translate, $http, Notification) { + $scope.rmqVersion = localStorage.getItem("isV5") === "true" ? true : false; + $scope.changeTranslate = function(langKey){ $translate.use(langKey); } + $scope.changeRMQVersion = function (version) { + $scope.rmqVersion = version === 5; + localStorage.setItem("isV5", $scope.rmqVersion); + } + + $http({ + method: "GET", + url: "proxy/homePage.query" + }).success(function (resp) { + if (resp.status == 0) { + $scope.proxyAddrList = resp.data.proxyAddrList; + $scope.selectedProxy = resp.data.currentProxyAddr; + $scope.showProxyDetailConfig($scope.selectedProxy); + localStorage.setItem('proxyAddr', $scope.selectedProxy); + } else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + $scope.logout = function(){ $http({ method: "POST", diff --git a/src/main/resources/static/src/i18n/en.js b/src/main/resources/static/src/i18n/en.js index 943ce482..7ce08db0 100644 --- a/src/main/resources/static/src/i18n/en.js +++ b/src/main/resources/static/src/i18n/en.js @@ -54,9 +54,12 @@ var en = { "RESET_CUS_OFFSET": "Reset Consumer Offset", "DELETE": "Delete", "CHANGE_LANG": "ChangeLanguage", + "CHANGE_VERSION": "ChangeVersion", "BROKER": "Broker", "NORMAL": "NORMAL", "RETRY": "RETRY", + "FIFO": "FIFO", + "TRANSACTION": "TRANSACTION", "DLQ": "DLQ", "QUANTITY":"Quantity", "TYPE":"Type", @@ -130,4 +133,11 @@ var en = { "MESSAGE_TYPE_FIFO": "FIFO", "MESSAGE_TYPE_DELAY": "DELAY", "MESSAGE_TYPE_TRANSACTION": "TRANSACTION", + "PROXY":"Proxy", + "PROXY_NAME": "Proxy Name", + "PROXY_CLUSTER_NAME":"Proxy Cluster Name", + "ROCKETMQ_CLUSTER_NAME":"RMQ Cluster Name", + "PROXY_ADDR": "Proxy Address", + "PROXY_MODE": "Proxy Mode", + "DETAIL": "Detail" } diff --git a/src/main/resources/static/src/i18n/zh.js b/src/main/resources/static/src/i18n/zh.js index 8a3b3ff0..764a6f7d 100644 --- a/src/main/resources/static/src/i18n/zh.js +++ b/src/main/resources/static/src/i18n/zh.js @@ -55,9 +55,12 @@ var zh = { "SKIP_MESSAGE_ACCUMULATE":"跳过堆积", "DELETE": "删除", "CHANGE_LANG": "更换语言", + "CHANGE_VERSION": "更换版本", "BROKER": "Broker", "NORMAL": "普通", "RETRY": "重试", + "FIFO": "顺序", + "TRANSACTION": "事务", "DLQ": "死信", "QUANTITY":"数量", "TYPE":"类型", @@ -131,4 +134,11 @@ var zh = { "MESSAGE_TYPE_FIFO": "顺序消息", "MESSAGE_TYPE_DELAY": "定时/延时消息", "MESSAGE_TYPE_TRANSACTION": "事务消息", + "PROXY":"代理", + "PROXY_NAME": "代理名称", + "PROXY_CLUSTER_NAME":"代理集群名称", + "ROCKETMQ_CLUSTER_NAME":"RMQ集群名称", + "PROXY_ADDR": "代理地址", + "PROXY_MODE": "代理模式", + "DETAIL": "详情" } \ No newline at end of file diff --git a/src/main/resources/static/src/proxy.js b/src/main/resources/static/src/proxy.js new file mode 100644 index 00000000..4461b09a --- /dev/null +++ b/src/main/resources/static/src/proxy.js @@ -0,0 +1,97 @@ +/* + * 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('proxyController', ['$scope', '$location', '$http', 'Notification', 'remoteApi', 'tools', '$window', + function ($scope, $location, $http, Notification, remoteApi, tools, $window) { + $scope.proxyAddrList = []; + $scope.userRole = $window.sessionStorage.getItem("userrole"); + $scope.writeOperationEnabled = $scope.userRole == null ? true : ($scope.userRole == 1 ? true : false); + $scope.inputReadonly = !$scope.writeOperationEnabled; + $scope.newProxyAddr = ""; + $scope.allProxyConfig = {}; + + $http({ + method: "GET", + url: "proxy/homePage.query" + }).success(function (resp) { + if (resp.status == 0) { + $scope.proxyAddrList = resp.data.proxyAddrList; + $scope.selectedProxy = resp.data.currentProxyAddr; + $scope.showProxyDetailConfig($scope.selectedProxy); + localStorage.setItem('proxyAddr',$scope.selectedProxy); + } else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + + $scope.eleChange = function (data) { + $scope.proxyAddrList = data; + } + $scope.showDetailConf = function () { + $(".proxyModal").modal(); + } + + + $scope.showProxyDetailConfig = function (proxyAddr) { + $http({ + method: "GET", + url: "proxy/proxyDetailConfig.query", + params: {proxyAddress: proxyAddr} + }).success(function (resp) { + if (resp.status == 0) { + $scope.allProxyConfig = resp.data; + } else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + + $scope.updateProxyAddr = function () { + $http({ + method: "POST", + url: "proxy/updateProxyAddr.do", + params: {proxyAddr: $scope.selectedProxy} + }).success(function (resp) { + if (resp.status == 0) { + localStorage.setItem('proxyAddr', $scope.selectedProxy); + Notification.info({message: "SUCCESS", delay: 2000}); + } else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + $scope.showProxyDetailConfig($scope.selectedProxy); + }; + + $scope.addProxyAddr = function () { + $http({ + method: "POST", + url: "proxy/addProxyAddr.do", + params: {newProxyAddr: $scope.newProxyAddr} + }).success(function (resp) { + if (resp.status == 0) { + if ($scope.proxyAddrList.indexOf($scope.newProxyAddr) == -1) { + $scope.proxyAddrList.push($scope.newProxyAddr); + } + $("#proxyAddr").val(""); + $scope.newProxyAddr = ""; + Notification.info({message: "SUCCESS", delay: 2000}); + } else { + Notification.error({message: resp.errMsg, delay: 2000}); + } + }); + }; + }]) diff --git a/src/main/resources/static/src/topic.js b/src/main/resources/static/src/topic.js index bce0df87..a4555723 100644 --- a/src/main/resources/static/src/topic.js +++ b/src/main/resources/static/src/topic.js @@ -45,24 +45,30 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati } }; $scope.filterNormal = true + $scope.filterDelay = false + $scope.filterFifo = false + $scope.filterTransaction = false $scope.filterRetry = false $scope.filterDLQ = false $scope.filterSystem = false $scope.allTopicList = []; + $scope.allTopicNameList = []; + $scope.allMessageTypeList = []; $scope.topicShowList = []; $scope.userRole = $window.sessionStorage.getItem("userrole"); - $scope.writeOperationEnabled = $scope.userRole == null ? true : ($scope.userRole == 1 ? true : false); + $scope.writeOperationEnabled = $scope.userRole == null ? true : ($scope.userRole == 1 ? true : false); $scope.refreshTopicList = function () { $http({ method: "GET", - url: "topic/list.query" + url: "topic/list.queryTopicType" }).success(function (resp) { if (resp.status == 0) { - $scope.allTopicList = resp.data.topicList.sort(); - console.log($scope.allTopicList); + $scope.allTopicNameList = resp.data.topicNameList; + $scope.allMessageTypeList = resp.data.messageTypeList; + console.log($scope.allTopicNameList); console.log(JSON.stringify(resp)); - $scope.showTopicList(1, $scope.allTopicList.length); + $scope.showTopicList(1, $scope.allTopicNameList.length); } else { Notification.error({message: resp.errMsg, delay: 5000}); @@ -79,6 +85,15 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati $scope.$watch('filterNormal', function () { $scope.filterList(1); }); + $scope.$watch('filterFifo', function () { + $scope.filterList(1); + }); + $scope.$watch('filterTransaction', function () { + $scope.filterList(1); + }); + $scope.$watch('filterDelay', function () { + $scope.filterList(1); + }); $scope.$watch('filterRetry', function () { $scope.filterList(1); }); @@ -92,13 +107,13 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati var lowExceptStr = $scope.filterStr.toLowerCase(); var canShowList = []; - $scope.allTopicList.forEach(function (element) { - if ($scope.filterByType(element)) { - if (element.toLowerCase().indexOf(lowExceptStr) != -1) { - canShowList.push(element); + for (let i = 0; i < $scope.allTopicNameList.length; ++i) { + if ($scope.filterByType($scope.allTopicNameList[i], $scope.allMessageTypeList[i])) { + if ($scope.allTopicNameList[i].toLowerCase().indexOf(lowExceptStr) != -1) { + canShowList.push($scope.allTopicNameList[i]); } } - }); + } $scope.paginationConf.totalItems = canShowList.length; var perPage = $scope.paginationConf.itemsPerPage; var from = (currentPage - 1) * perPage; @@ -106,7 +121,7 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati $scope.topicShowList = canShowList.slice(from, to); }; - $scope.filterByType = function (str) { + $scope.filterByType = function (str, type) { if ($scope.filterRetry) { if (str.startsWith("%R")) { return true @@ -123,7 +138,22 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati } } if ($scope.filterNormal) { - if (str.startsWith("%") == false) { + if (type.includes("NORMAL")) { + return true + } + } + if ($scope.filterDelay) { + if (type.includes("DELAY")) { + return true + } + } + if ($scope.filterFifo) { + if (type.includes("FIFO")) { + return true + } + } + if ($scope.filterTransaction) { + if (type.includes("TRANSACTION")) { return true } } @@ -138,10 +168,10 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati var perPage = $scope.paginationConf.itemsPerPage; var from = (currentPage - 1) * perPage; var to = (from + perPage) > totalItem ? totalItem : from + perPage; - console.log($scope.allTopicList); + console.log($scope.allTopicNameList); console.log(from) console.log(to) - $scope.topicShowList = $scope.allTopicList.slice(from, to); + $scope.topicShowList = $scope.allTopicNameList.slice(from, to); $scope.paginationConf.totalItems = totalItem; console.log($scope.topicShowList) console.log($scope.paginationConf.totalItems) diff --git a/src/main/resources/static/view/layout/_header.html b/src/main/resources/static/view/layout/_header.html index f4485418..c33ae607 100644 --- a/src/main/resources/static/view/layout/_header.html +++ b/src/main/resources/static/view/layout/_header.html @@ -28,6 +28,7 @@ {{'NORMAL' | translate}} + {{'DELAY' | translate}} + + {{'FIFO' | translate}} + + {{'TRANSACTION' | translate}} + {{'RETRY' | translate}} {{'DLQ' | translate}}