From daf03c6694bd2701387a2569131fefc573dadc5e Mon Sep 17 00:00:00 2001 From: fu-turer Date: Sat, 11 Dec 2021 18:13:58 +0800 Subject: [PATCH] add topic detail info (#21) --- .../pulsar/pulsar_partitioned_topic_api.dart | 107 ++++++++++++++++++ lib/api/pulsar/pulsar_topic_api.dart | 105 +++++++++++++++++ lib/generated/intl/messages_en.dart | 4 +- lib/generated/intl/messages_zh.dart | 2 +- lib/generated/l10n.dart | 14 ++- lib/l10n/intl_en.arb | 3 +- lib/l10n/intl_zh.arb | 1 + lib/module/pulsar/pulsar_consume.dart | 35 ++++++ .../pulsar/pulsar_partitioned_topic_base.dart | 23 ++++ lib/module/pulsar/pulsar_topic_base.dart | 17 +++ .../screen/pulsar_partitioned_topic.dart | 13 ++- lib/ui/pulsar/screen/pulsar_topic.dart | 16 ++- .../pulsar_partitioned_topic_basic.dart | 65 +++++++++++ .../pulsar_partitioned_topic_consume.dart | 107 ++++++++++++++++++ lib/ui/pulsar/widget/pulsar_topic_basic.dart | 78 ++++++++++++- .../pulsar/widget/pulsar_topic_consume.dart | 105 +++++++++++++++++ ...ar_partitioned_topic_basic_view_model.dart | 14 ++- ..._partitioned_topic_consume_view_model.dart | 68 +++++++++++ .../pulsar/pulsar_topic_basic_view_model.dart | 23 ++++ .../pulsar_topic_consume_view_model.dart | 64 +++++++++++ macos/Podfile.lock | 2 +- pubspec.lock | 4 +- 22 files changed, 850 insertions(+), 20 deletions(-) create mode 100644 lib/module/pulsar/pulsar_consume.dart create mode 100644 lib/module/pulsar/pulsar_partitioned_topic_base.dart create mode 100644 lib/module/pulsar/pulsar_topic_base.dart create mode 100644 lib/ui/pulsar/widget/pulsar_partitioned_topic_consume.dart create mode 100644 lib/ui/pulsar/widget/pulsar_topic_consume.dart create mode 100644 lib/vm/pulsar/pulsar_partitioned_topic_consume_view_model.dart create mode 100644 lib/vm/pulsar/pulsar_topic_consume_view_model.dart diff --git a/lib/api/pulsar/pulsar_partitioned_topic_api.dart b/lib/api/pulsar/pulsar_partitioned_topic_api.dart index 497aa88..675f8ac 100644 --- a/lib/api/pulsar/pulsar_partitioned_topic_api.dart +++ b/lib/api/pulsar/pulsar_partitioned_topic_api.dart @@ -4,6 +4,8 @@ import 'dart:developer'; import 'package:http/http.dart' as http; import 'package:paas_dashboard_flutter/api/http_util.dart'; import 'package:paas_dashboard_flutter/api/pulsar/pulsar_stat_api.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_consume.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_partitioned_topic_base.dart'; import 'package:paas_dashboard_flutter/module/pulsar/pulsar_partitioned_topic_detail.dart'; import 'package:paas_dashboard_flutter/module/pulsar/pulsar_produce.dart'; import 'package:paas_dashboard_flutter/module/pulsar/pulsar_subscription.dart'; @@ -130,6 +132,72 @@ class PulsarPartitionedTopicApi { return ""; } + static Future> getConsumers(String host, int port, + String tenant, String namespace, String topic) async { + String data = ""; + await PulsarStatApi.partitionedTopicStats( + host, port, tenant, namespace, topic) + .then((value) => {data = value}); + List respList = new List.empty(growable: true); + Map statsMap = json.decode(data) as Map; + if (statsMap.containsKey("subscriptions")) { + Map subscriptionsMap = statsMap["subscriptions"] as Map; + subscriptionsMap.forEach((key, value) { + Map subMap = value as Map; + if (subMap.containsKey("consumers")) { + List consumers = subMap["consumers"] as List; + consumers.forEach((element) { + Map consumer = element as Map; + double rateOut = 0; + double throughputOut = 0; + String clientVersion = ""; + String address = ""; + String consumerName = ""; + double availablePermits = 0; + double unackedMessages = 0; + double lastConsumedTimestamp = 0; + if (consumer.containsKey("consumerName")) { + consumerName = consumer["consumerName"]; + } + if (consumer.containsKey("address")) { + address = consumer["address"]; + } + if (consumer.containsKey("clientVersion")) { + clientVersion = consumer["clientVersion"]; + } + if (consumer.containsKey("throughputOut")) { + throughputOut = consumer["throughputOut"]; + } + if (consumer.containsKey("rateOut")) { + rateOut = consumer["rateOut"]; + } + if (consumer.containsKey("availablePermits")) { + availablePermits = consumer["availablePermits"]; + } + if (consumer.containsKey("unackedMessages")) { + unackedMessages = consumer["unackedMessages"]; + } + if (consumer.containsKey("lastConsumedTimestamp")) { + lastConsumedTimestamp = consumer["lastConsumedTimestamp"]; + } + ConsumerResp consumerResp = new ConsumerResp( + consumerName, + key, + rateOut, + throughputOut, + availablePermits, + unackedMessages, + lastConsumedTimestamp, + clientVersion, + address); + respList.add(consumerResp); + }); + } + }); + } + return respList; + } + static Future> getProducers(String host, int port, String tenant, String namespace, String topic) async { String data = ""; @@ -174,4 +242,43 @@ class PulsarPartitionedTopicApi { } return respList; } + + static Future getBase(String host, int port, + String tenant, String namespace, String topic) async { + String data = ""; + await PulsarStatApi.partitionedTopicStats( + host, port, tenant, namespace, topic) + .then((value) => {data = value}); + + Map statsMap = json.decode(data) as Map; + String topicName = topic; + int partitionNum = 0; + double msgRateIn = 0; + double msgRateOut = 0; + double msgInCounter = 0; + double msgOutCounter = 0; + double storageSize = 0; + + if (statsMap.containsKey("metadata")) { + Map metadata = statsMap["metadata"] as Map; + partitionNum = metadata["partitions"]; + } + if (statsMap.containsKey("msgRateIn")) { + msgRateIn = statsMap["msgRateIn"]; + } + if (statsMap.containsKey("msgRateOut")) { + msgRateOut = statsMap["msgRateOut"]; + } + if (statsMap.containsKey("msgInCounter")) { + msgInCounter = statsMap["msgInCounter"]; + } + if (statsMap.containsKey("msgOutCounter")) { + msgOutCounter = statsMap["msgOutCounter"]; + } + if (statsMap.containsKey("storageSize")) { + storageSize = statsMap["storageSize"]; + } + return new PulsarPartitionedTopicBaseResp(topicName, partitionNum, + msgRateIn, msgRateOut, msgInCounter, msgOutCounter, storageSize); + } } diff --git a/lib/api/pulsar/pulsar_topic_api.dart b/lib/api/pulsar/pulsar_topic_api.dart index 392d18d..3f27bb1 100644 --- a/lib/api/pulsar/pulsar_topic_api.dart +++ b/lib/api/pulsar/pulsar_topic_api.dart @@ -4,9 +4,11 @@ import 'dart:developer'; import 'package:http/http.dart' as http; import 'package:paas_dashboard_flutter/api/http_util.dart'; import 'package:paas_dashboard_flutter/api/pulsar/pulsar_stat_api.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_consume.dart'; import 'package:paas_dashboard_flutter/module/pulsar/pulsar_produce.dart'; import 'package:paas_dashboard_flutter/module/pulsar/pulsar_subscription.dart'; import 'package:paas_dashboard_flutter/module/pulsar/pulsar_topic.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_topic_base.dart'; import 'package:paas_dashboard_flutter/ui/util/string_util.dart'; class PulsarTopicApi { @@ -109,6 +111,71 @@ class PulsarTopicApi { return ""; } + static Future> getConsumers(String host, int port, + String tenant, String namespace, String topic) async { + String data = ""; + await PulsarStatApi.topicStats(host, port, tenant, namespace, topic) + .then((value) => {data = value}); + List respList = new List.empty(growable: true); + Map statsMap = json.decode(data) as Map; + if (statsMap.containsKey("subscriptions")) { + Map subscriptionsMap = statsMap["subscriptions"] as Map; + subscriptionsMap.forEach((key, value) { + Map subMap = value as Map; + if (subMap.containsKey("consumers")) { + List consumers = subMap["consumers"] as List; + consumers.forEach((element) { + Map consumer = element as Map; + double rateOut = 0; + double throughputOut = 0; + String clientVersion = ""; + String address = ""; + String consumerName = ""; + double availablePermits = 0; + double unackedMessages = 0; + double lastConsumedTimestamp = 0; + if (consumer.containsKey("consumerName")) { + consumerName = consumer["consumerName"]; + } + if (consumer.containsKey("address")) { + address = consumer["address"]; + } + if (consumer.containsKey("clientVersion")) { + clientVersion = consumer["clientVersion"]; + } + if (consumer.containsKey("throughputOut")) { + throughputOut = consumer["throughputOut"]; + } + if (consumer.containsKey("rateOut")) { + rateOut = consumer["rateOut"]; + } + if (consumer.containsKey("availablePermits")) { + availablePermits = consumer["availablePermits"]; + } + if (consumer.containsKey("unackedMessages")) { + unackedMessages = consumer["unackedMessages"]; + } + if (consumer.containsKey("lastConsumedTimestamp")) { + lastConsumedTimestamp = consumer["lastConsumedTimestamp"]; + } + ConsumerResp consumerResp = new ConsumerResp( + consumerName, + key, + rateOut, + throughputOut, + availablePermits, + unackedMessages, + lastConsumedTimestamp, + clientVersion, + address); + respList.add(consumerResp); + }); + } + }); + } + return respList; + } + static Future> getProducers(String host, int port, String tenant, String namespace, String topic) async { String data = ""; @@ -132,4 +199,42 @@ class PulsarTopicApi { } return respList; } + + static Future getBase(String host, int port, + String tenant, String namespace, String topic) async { + String data = ""; + await PulsarStatApi.topicStats(host, port, tenant, namespace, topic) + .then((value) => {data = value}); + + Map statsMap = json.decode(data) as Map; + String topicName = topic; + int partitionNum = 0; + double msgRateIn = 0; + double msgRateOut = 0; + double msgInCounter = 0; + double msgOutCounter = 0; + double storageSize = 0; + + if (statsMap.containsKey("metadata")) { + Map metadata = statsMap["metadata"] as Map; + partitionNum = metadata["partitions"]; + } + if (statsMap.containsKey("msgRateIn")) { + msgRateIn = statsMap["msgRateIn"]; + } + if (statsMap.containsKey("msgRateOut")) { + msgRateOut = statsMap["msgRateOut"]; + } + if (statsMap.containsKey("msgInCounter")) { + msgInCounter = statsMap["msgInCounter"]; + } + if (statsMap.containsKey("msgOutCounter")) { + msgOutCounter = statsMap["msgOutCounter"]; + } + if (statsMap.containsKey("storageSize")) { + storageSize = statsMap["storageSize"]; + } + return new PulsarTopicBaseResp(topicName, partitionNum, msgRateIn, + msgRateOut, msgInCounter, msgOutCounter, storageSize); + } } diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 391ac20..3b3859a 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -8,7 +8,6 @@ // ignore_for_file:prefer_single_quotes,comment_references, directives_ordering // ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases // ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes -// ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes import 'package:intl/intl.dart'; import 'package:intl/message_lookup_by_library.dart'; @@ -35,7 +34,7 @@ class MessageLookup extends MessageLookupByLibrary { "confirmDeleteQuestion": MessageLookupByLibrary.simpleMessage("ConfirmDelete?"), "consume": MessageLookupByLibrary.simpleMessage("consume"), - "consumer": MessageLookupByLibrary.simpleMessage("consumer"), + "consumer": MessageLookupByLibrary.simpleMessage("Consumer"), "consumerList": MessageLookupByLibrary.simpleMessage("Consumer List"), "delete": MessageLookupByLibrary.simpleMessage("Delete"), "deleteNamespace": @@ -74,6 +73,7 @@ class MessageLookup extends MessageLookupByLibrary { "tenant": MessageLookupByLibrary.simpleMessage("tenant"), "tenantName": MessageLookupByLibrary.simpleMessage("Tenant Name"), "tenants": MessageLookupByLibrary.simpleMessage("Tenants"), + "topicDetail": MessageLookupByLibrary.simpleMessage("topic detail"), "topicName": MessageLookupByLibrary.simpleMessage("Topic Name"), "topics": MessageLookupByLibrary.simpleMessage("Topics"), "unit": MessageLookupByLibrary.simpleMessage("unit"), diff --git a/lib/generated/intl/messages_zh.dart b/lib/generated/intl/messages_zh.dart index f74f3e0..0954806 100644 --- a/lib/generated/intl/messages_zh.dart +++ b/lib/generated/intl/messages_zh.dart @@ -8,7 +8,6 @@ // ignore_for_file:prefer_single_quotes,comment_references, directives_ordering // ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases // ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes -// ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes import 'package:intl/intl.dart'; import 'package:intl/message_lookup_by_library.dart'; @@ -64,6 +63,7 @@ class MessageLookup extends MessageLookupByLibrary { "tenant": MessageLookupByLibrary.simpleMessage("租户"), "tenantName": MessageLookupByLibrary.simpleMessage("租户名称"), "tenants": MessageLookupByLibrary.simpleMessage("租户列表"), + "topicDetail": MessageLookupByLibrary.simpleMessage("主题详情"), "topicName": MessageLookupByLibrary.simpleMessage("Topic 名称"), "topics": MessageLookupByLibrary.simpleMessage("Topic 列表"), "unit": MessageLookupByLibrary.simpleMessage("单位"), diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 5001c36..a469e28 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -160,10 +160,10 @@ class S { ); } - /// `consumer` + /// `Consumer` String get consumer { return Intl.message( - 'consumer', + 'Consumer', name: 'consumer', desc: '', args: [], @@ -470,6 +470,16 @@ class S { ); } + /// `topic detail` + String get topicDetail { + return Intl.message( + 'topic detail', + name: 'topicDetail', + desc: '', + args: [], + ); + } + /// `Topic Name` String get topicName { return Intl.message( diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 40a21d4..910eee4 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -11,7 +11,7 @@ "confirmClearBacklog": "ConfirmClear?", "confirmDeleteQuestion": "ConfirmDelete?", "consume": "consume", - "consumer": "consumer", + "consumer": "Consumer", "consumerList": "Consumer List", "delete": "Delete", "deleteNamespace": "Delete Namespace", @@ -42,6 +42,7 @@ "tenant": "tenant", "tenantName": "Tenant Name", "tenants": "Tenants", + "topicDetail": "topic detail", "topicName": "Topic Name", "topics": "Topics", "unit": "unit", diff --git a/lib/l10n/intl_zh.arb b/lib/l10n/intl_zh.arb index e22a2d9..7a591fb 100644 --- a/lib/l10n/intl_zh.arb +++ b/lib/l10n/intl_zh.arb @@ -42,6 +42,7 @@ "tenant": "租户", "tenantName": "租户名称", "tenants": "租户列表", + "topicDetail": "主题详情", "topicName": "Topic 名称", "topics": "Topic 列表", "unit": "单位", diff --git a/lib/module/pulsar/pulsar_consume.dart b/lib/module/pulsar/pulsar_consume.dart new file mode 100644 index 0000000..b664922 --- /dev/null +++ b/lib/module/pulsar/pulsar_consume.dart @@ -0,0 +1,35 @@ +class ConsumerResp { + final String consumerName; + final String subscriptionName; + final double rateOut; + final double throughputOut; + final double availablePermits; + final double unackedMessages; + final double lastConsumedTimestamp; + final String clientVersion; + final String address; + + ConsumerResp( + this.consumerName, + this.subscriptionName, + this.rateOut, + this.throughputOut, + this.availablePermits, + this.unackedMessages, + this.lastConsumedTimestamp, + this.clientVersion, + this.address); + + ConsumerResp deepCopy() { + return new ConsumerResp( + consumerName, + subscriptionName, + rateOut, + throughputOut, + availablePermits, + unackedMessages, + lastConsumedTimestamp, + clientVersion, + address); + } +} diff --git a/lib/module/pulsar/pulsar_partitioned_topic_base.dart b/lib/module/pulsar/pulsar_partitioned_topic_base.dart new file mode 100644 index 0000000..c738630 --- /dev/null +++ b/lib/module/pulsar/pulsar_partitioned_topic_base.dart @@ -0,0 +1,23 @@ +class PulsarPartitionedTopicBaseResp { + final String topicName; + final int partitionNum; + final double msgRateIn; + final double msgRateOut; + final double msgInCounter; + final double msgOutCounter; + final double storageSize; + + PulsarPartitionedTopicBaseResp( + this.topicName, + this.partitionNum, + this.msgRateIn, + this.msgRateOut, + this.msgInCounter, + this.msgOutCounter, + this.storageSize); + + PulsarPartitionedTopicBaseResp deepCopy() { + return new PulsarPartitionedTopicBaseResp(topicName, partitionNum, + msgRateIn, msgRateOut, msgInCounter, msgOutCounter, storageSize); + } +} diff --git a/lib/module/pulsar/pulsar_topic_base.dart b/lib/module/pulsar/pulsar_topic_base.dart new file mode 100644 index 0000000..824a70b --- /dev/null +++ b/lib/module/pulsar/pulsar_topic_base.dart @@ -0,0 +1,17 @@ +class PulsarTopicBaseResp { + final String topicName; + final int partitionNum; + final double msgRateIn; + final double msgRateOut; + final double msgInCounter; + final double msgOutCounter; + final double storageSize; + + PulsarTopicBaseResp(this.topicName, this.partitionNum, this.msgRateIn, + this.msgRateOut, this.msgInCounter, this.msgOutCounter, this.storageSize); + + PulsarTopicBaseResp deepCopy() { + return new PulsarTopicBaseResp(topicName, partitionNum, msgRateIn, + msgRateOut, msgInCounter, msgOutCounter, storageSize); + } +} diff --git a/lib/ui/pulsar/screen/pulsar_partitioned_topic.dart b/lib/ui/pulsar/screen/pulsar_partitioned_topic.dart index 59f93e5..660f188 100644 --- a/lib/ui/pulsar/screen/pulsar_partitioned_topic.dart +++ b/lib/ui/pulsar/screen/pulsar_partitioned_topic.dart @@ -1,10 +1,12 @@ import 'package:flutter/material.dart'; import 'package:paas_dashboard_flutter/generated/l10n.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_partitioned_topic_basic.dart'; +import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_partitioned_topic_consume.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_partitioned_topic_detail.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_partitioned_topic_produce.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_partitioned_topic_subscription.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_partitioned_topic_basic_view_model.dart'; +import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_partitioned_topic_consume_view_model.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_partitioned_topic_detail_view_model.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_partitioned_topic_produce_view_model.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_partitioned_topic_subscription_view_model.dart'; @@ -27,7 +29,7 @@ class _PulsarPartitionedTopicState extends State { Widget build(BuildContext context) { final vm = Provider.of(context); return DefaultTabController( - length: 4, + length: 5, child: Scaffold( appBar: AppBar( title: Text( @@ -37,6 +39,7 @@ class _PulsarPartitionedTopicState extends State { Tab(text: S.of(context).basic), Tab(text: S.of(context).detail), Tab(text: S.of(context).subscription), + Tab(text: S.of(context).consumer), Tab(text: S.of(context).produce), ], ), @@ -68,6 +71,14 @@ class _PulsarPartitionedTopicState extends State { vm.topicResp), child: PulsarPartitionedTopicSubscriptionWidget(), ).build(context), + ChangeNotifierProvider( + create: (context) => PulsarPartitionedTopicConsumeViewModel( + vm.pulsarInstancePo, + vm.tenantResp, + vm.namespaceResp, + vm.topicResp), + child: PulsarPartitionedTopicConsumeWidget(), + ).build(context), ChangeNotifierProvider( create: (context) => PulsarPartitionedTopicProduceViewModel( vm.pulsarInstancePo, diff --git a/lib/ui/pulsar/screen/pulsar_topic.dart b/lib/ui/pulsar/screen/pulsar_topic.dart index 8724bee..67db90b 100644 --- a/lib/ui/pulsar/screen/pulsar_topic.dart +++ b/lib/ui/pulsar/screen/pulsar_topic.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; import 'package:paas_dashboard_flutter/generated/l10n.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_topic_basic.dart'; +import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_topic_consume.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_topic_produce.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_topic_subscription.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_topic_basic_view_model.dart'; +import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_topic_consume_view_model.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_topic_produce_view_model.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_topic_subscription_view_model.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_topic_view_model.dart'; @@ -25,7 +27,7 @@ class _PulsarTopicState extends State { Widget build(BuildContext context) { final vm = Provider.of(context); return DefaultTabController( - length: 3, + length: 4, child: Scaffold( appBar: AppBar( title: Text( @@ -34,6 +36,7 @@ class _PulsarTopicState extends State { tabs: [ Tab(text: S.of(context).basic), Tab(text: S.of(context).subscription), + Tab(text: S.of(context).consumer), Tab(text: S.of(context).produce), ], ), @@ -49,14 +52,21 @@ class _PulsarTopicState extends State { child: PulsarTopicBasicWidget(), ).build(context), ChangeNotifierProvider( - create: (context) => - new PulsarTopicSubscriptionViewModel( + create: (context) => new PulsarTopicSubscriptionViewModel( vm.pulsarInstancePo, vm.tenantResp, vm.namespaceResp, vm.topicResp), child: PulsarTopicSubscriptionWidget(), ).build(context), + ChangeNotifierProvider( + create: (context) => PulsarTopicConsumeViewModel( + vm.pulsarInstancePo, + vm.tenantResp, + vm.namespaceResp, + vm.topicResp), + child: PulsarTopicConsumeWidget(), + ).build(context), ChangeNotifierProvider( create: (context) => PulsarTopicProduceViewModel( vm.pulsarInstancePo, diff --git a/lib/ui/pulsar/widget/pulsar_partitioned_topic_basic.dart b/lib/ui/pulsar/widget/pulsar_partitioned_topic_basic.dart index d7c167e..1009b3e 100644 --- a/lib/ui/pulsar/widget/pulsar_partitioned_topic_basic.dart +++ b/lib/ui/pulsar/widget/pulsar_partitioned_topic_basic.dart @@ -62,6 +62,71 @@ class PulsarPartitionedTopicBasicWidgetState ], ), ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'storageSize : ${vm.storageSize}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'MsgRateIn : ${vm.msgRateIn}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'MsgRateOut : ${vm.msgRateOut}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'MsgInCounter : ${vm.msgInCounter}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'MsgOutCounter : ${vm.msgOutCounter}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), ], ); return body; diff --git a/lib/ui/pulsar/widget/pulsar_partitioned_topic_consume.dart b/lib/ui/pulsar/widget/pulsar_partitioned_topic_consume.dart new file mode 100644 index 0000000..fc0dec8 --- /dev/null +++ b/lib/ui/pulsar/widget/pulsar_partitioned_topic_consume.dart @@ -0,0 +1,107 @@ +import 'package:flutter/material.dart'; +import 'package:paas_dashboard_flutter/generated/l10n.dart'; +import 'package:paas_dashboard_flutter/ui/util/exception_util.dart'; +import 'package:paas_dashboard_flutter/ui/util/spinner_util.dart'; +import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_partitioned_topic_consume_view_model.dart'; +import 'package:provider/provider.dart'; + +class PulsarPartitionedTopicConsumeWidget extends StatefulWidget { + PulsarPartitionedTopicConsumeWidget(); + + @override + State createState() { + return new PulsarPartitionedTopicConsumeWidgetState(); + } +} + +class PulsarPartitionedTopicConsumeWidgetState + extends State { + @override + void initState() { + super.initState(); + final vm = Provider.of(context, + listen: false); + vm.fetchConsumers(); + } + + @override + Widget build(BuildContext context) { + final vm = Provider.of(context); + if (vm.loading) { + WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { + SpinnerUtil.create(); + }); + } + ExceptionUtil.processLoadException(vm, context); + ExceptionUtil.processOpException(vm, context); + var consumerFuture = SingleChildScrollView( + child: DataTable( + showCheckboxColumn: false, + columns: [ + DataColumn(label: Text('SubscriptionName')), + DataColumn(label: Text('ConsumerName')), + DataColumn(label: Text('MsgRateOut')), + DataColumn(label: Text('MsgThroughputOut')), + DataColumn(label: Text('AvailablePermits')), + DataColumn(label: Text('UnackedMessages')), + DataColumn(label: Text('LastConsumedTimestamp')), + DataColumn(label: Text('ClientVersion')), + DataColumn(label: Text('Address')), + ], + rows: vm.displayList + .map((data) => DataRow(cells: [ + DataCell( + Text(data.subscriptionName), + ), + DataCell( + Text(data.consumerName), + ), + DataCell( + Text(data.rateOut.toString()), + ), + DataCell( + Text(data.throughputOut.toString()), + ), + DataCell( + Text(data.availablePermits.toString()), + ), + DataCell( + Text(data.unackedMessages.toString()), + ), + DataCell( + Text(data.lastConsumedTimestamp.toString()), + ), + DataCell( + Text(data.clientVersion.toString()), + ), + DataCell( + Text(data.address.toString()), + ), + ])) + .toList()), + ); + var refreshButton = TextButton( + onPressed: () { + vm.fetchConsumers(); + }, + child: Text(S.of(context).refresh)); + var body = ListView( + children: [ + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [refreshButton], + ), + ), + Text( + S.of(context).consumerList, + style: TextStyle(fontSize: 22), + ), + consumerFuture, + ], + ); + return body; + } +} diff --git a/lib/ui/pulsar/widget/pulsar_topic_basic.dart b/lib/ui/pulsar/widget/pulsar_topic_basic.dart index e7af0ef..2783c00 100644 --- a/lib/ui/pulsar/widget/pulsar_topic_basic.dart +++ b/lib/ui/pulsar/widget/pulsar_topic_basic.dart @@ -14,11 +14,12 @@ class PulsarTopicBasicWidget extends StatefulWidget { } } -class PulsarTopicBasicWidgetState - extends State { +class PulsarTopicBasicWidgetState extends State { @override void initState() { super.initState(); + final vm = Provider.of(context, listen: false); + vm.fetchPartitions(); } @override @@ -31,8 +32,11 @@ class PulsarTopicBasicWidgetState } ExceptionUtil.processLoadException(vm, context); ExceptionUtil.processOpException(vm, context); - var refreshButton = - TextButton(onPressed: () {}, child: Text(S.of(context).refresh)); + var refreshButton = TextButton( + onPressed: () { + vm.fetchPartitions(); + }, + child: Text(S.of(context).refresh)); var body = ListView( children: [ Container( @@ -43,9 +47,73 @@ class PulsarTopicBasicWidgetState children: [refreshButton], ), ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'StorageSize : ${vm.storageSize}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'MsgRateIn : ${vm.msgRateIn}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'MsgRateOut : ${vm.msgRateOut}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'MsgInCounter : ${vm.msgInCounter}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'MsgOutCounter : ${vm.msgOutCounter}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), ], ); return body; } - } diff --git a/lib/ui/pulsar/widget/pulsar_topic_consume.dart b/lib/ui/pulsar/widget/pulsar_topic_consume.dart new file mode 100644 index 0000000..d809d67 --- /dev/null +++ b/lib/ui/pulsar/widget/pulsar_topic_consume.dart @@ -0,0 +1,105 @@ +import 'package:flutter/material.dart'; +import 'package:paas_dashboard_flutter/generated/l10n.dart'; +import 'package:paas_dashboard_flutter/ui/util/exception_util.dart'; +import 'package:paas_dashboard_flutter/ui/util/spinner_util.dart'; +import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_topic_consume_view_model.dart'; +import 'package:provider/provider.dart'; + +class PulsarTopicConsumeWidget extends StatefulWidget { + PulsarTopicConsumeWidget(); + + @override + State createState() { + return new PulsarTopicConsumeWidgetState(); + } +} + +class PulsarTopicConsumeWidgetState extends State { + @override + void initState() { + super.initState(); + final vm = Provider.of(context, listen: false); + vm.fetchConsumers(); + } + + @override + Widget build(BuildContext context) { + final vm = Provider.of(context); + if (vm.loading) { + WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { + SpinnerUtil.create(); + }); + } + ExceptionUtil.processLoadException(vm, context); + ExceptionUtil.processOpException(vm, context); + var consumerFuture = SingleChildScrollView( + child: DataTable( + showCheckboxColumn: false, + columns: [ + DataColumn(label: Text('SubscriptionName')), + DataColumn(label: Text('ConsumerName')), + DataColumn(label: Text('MsgRateOut')), + DataColumn(label: Text('MsgThroughputOut')), + DataColumn(label: Text('AvailablePermits')), + DataColumn(label: Text('UnackedMessages')), + DataColumn(label: Text('LastConsumedTimestamp')), + DataColumn(label: Text('ClientVersion')), + DataColumn(label: Text('Address')), + ], + rows: vm.displayList + .map((data) => DataRow(cells: [ + DataCell( + Text(data.subscriptionName), + ), + DataCell( + Text(data.consumerName), + ), + DataCell( + Text(data.rateOut.toString()), + ), + DataCell( + Text(data.throughputOut.toString()), + ), + DataCell( + Text(data.availablePermits.toString()), + ), + DataCell( + Text(data.unackedMessages.toString()), + ), + DataCell( + Text(data.lastConsumedTimestamp.toString()), + ), + DataCell( + Text(data.clientVersion.toString()), + ), + DataCell( + Text(data.address.toString()), + ), + ])) + .toList()), + ); + var refreshButton = TextButton( + onPressed: () { + vm.fetchConsumers(); + }, + child: Text(S.of(context).refresh)); + var body = ListView( + children: [ + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [refreshButton], + ), + ), + Text( + S.of(context).consumerList, + style: TextStyle(fontSize: 22), + ), + consumerFuture, + ], + ); + return body; + } +} diff --git a/lib/vm/pulsar/pulsar_partitioned_topic_basic_view_model.dart b/lib/vm/pulsar/pulsar_partitioned_topic_basic_view_model.dart index e19fbdb..aad902d 100644 --- a/lib/vm/pulsar/pulsar_partitioned_topic_basic_view_model.dart +++ b/lib/vm/pulsar/pulsar_partitioned_topic_basic_view_model.dart @@ -11,6 +11,11 @@ class PulsarPartitionedTopicBasicViewModel extends BaseLoadViewModel { final NamespaceResp namespaceResp; final TopicResp topicResp; String partitionNum = ""; + double msgRateIn = 0; + double msgRateOut = 0; + double msgInCounter = 0; + double msgOutCounter = 0; + double storageSize = 0; PulsarPartitionedTopicBasicViewModel(this.pulsarInstancePo, this.tenantResp, this.namespaceResp, this.topicResp); @@ -50,9 +55,14 @@ class PulsarPartitionedTopicBasicViewModel extends BaseLoadViewModel { Future fetchPartitions() async { try { - final results = await PulsarPartitionedTopicApi.getDetails( + final results = await PulsarPartitionedTopicApi.getBase( host, port, tenant, namespace, topic); - partitionNum = results.length.toString(); + partitionNum = results.partitionNum.toString(); + msgRateIn = results.msgRateIn; + msgRateOut = results.msgRateOut; + msgInCounter = results.msgInCounter; + msgOutCounter = results.msgOutCounter; + storageSize = results.storageSize; loadSuccess(); } on Exception catch (e) { loadException = e; diff --git a/lib/vm/pulsar/pulsar_partitioned_topic_consume_view_model.dart b/lib/vm/pulsar/pulsar_partitioned_topic_consume_view_model.dart new file mode 100644 index 0000000..fe52d69 --- /dev/null +++ b/lib/vm/pulsar/pulsar_partitioned_topic_consume_view_model.dart @@ -0,0 +1,68 @@ +import 'package:paas_dashboard_flutter/api/pulsar/pulsar_partitioned_topic_api.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_consume.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_namespace.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_tenant.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_topic.dart'; +import 'package:paas_dashboard_flutter/persistent/po/pulsar_instance_po.dart'; +import 'package:paas_dashboard_flutter/vm/base_load_list_view_model.dart'; + +class PulsarPartitionedTopicConsumeViewModel + extends BaseLoadListViewModel { + final PulsarInstancePo pulsarInstancePo; + final TenantResp tenantResp; + final NamespaceResp namespaceResp; + final TopicResp topicResp; + + PulsarPartitionedTopicConsumeViewModel(this.pulsarInstancePo, this.tenantResp, + this.namespaceResp, this.topicResp); + + PulsarPartitionedTopicConsumeViewModel deepCopy() { + return new PulsarPartitionedTopicConsumeViewModel( + pulsarInstancePo.deepCopy(), + tenantResp.deepCopy(), + namespaceResp.deepCopy(), + topicResp.deepCopy()); + } + + int get id { + return this.pulsarInstancePo.id; + } + + String get name { + return this.pulsarInstancePo.name; + } + + String get host { + return this.pulsarInstancePo.host; + } + + int get port { + return this.pulsarInstancePo.port; + } + + String get tenant { + return this.tenantResp.tenant; + } + + String get namespace { + return this.namespaceResp.namespace; + } + + String get topic { + return this.topicResp.topicName; + } + + Future fetchConsumers() async { + try { + final results = await PulsarPartitionedTopicApi.getConsumers( + host, port, tenant, namespace, topic); + this.fullList = results; + this.displayList = this.fullList; + loadSuccess(); + } on Exception catch (e) { + loadException = e; + loading = false; + } + notifyListeners(); + } +} diff --git a/lib/vm/pulsar/pulsar_topic_basic_view_model.dart b/lib/vm/pulsar/pulsar_topic_basic_view_model.dart index 94b8d3b..f2d542a 100644 --- a/lib/vm/pulsar/pulsar_topic_basic_view_model.dart +++ b/lib/vm/pulsar/pulsar_topic_basic_view_model.dart @@ -1,3 +1,4 @@ +import 'package:paas_dashboard_flutter/api/pulsar/pulsar_topic_api.dart'; import 'package:paas_dashboard_flutter/module/pulsar/pulsar_namespace.dart'; import 'package:paas_dashboard_flutter/module/pulsar/pulsar_tenant.dart'; import 'package:paas_dashboard_flutter/module/pulsar/pulsar_topic.dart'; @@ -9,6 +10,11 @@ class PulsarTopicBasicViewModel extends BaseLoadViewModel { final TenantResp tenantResp; final NamespaceResp namespaceResp; final TopicResp topicResp; + double msgRateIn = 0; + double msgRateOut = 0; + double msgInCounter = 0; + double msgOutCounter = 0; + double storageSize = 0; PulsarTopicBasicViewModel(this.pulsarInstancePo, this.tenantResp, this.namespaceResp, this.topicResp); @@ -45,4 +51,21 @@ class PulsarTopicBasicViewModel extends BaseLoadViewModel { String get topic { return this.topicResp.topicName; } + + Future fetchPartitions() async { + try { + final results = + await PulsarTopicApi.getBase(host, port, tenant, namespace, topic); + msgRateIn = results.msgRateIn; + msgRateOut = results.msgRateOut; + msgInCounter = results.msgInCounter; + msgOutCounter = results.msgOutCounter; + storageSize = results.storageSize; + loadSuccess(); + } on Exception catch (e) { + loadException = e; + loading = false; + } + notifyListeners(); + } } diff --git a/lib/vm/pulsar/pulsar_topic_consume_view_model.dart b/lib/vm/pulsar/pulsar_topic_consume_view_model.dart new file mode 100644 index 0000000..deff67f --- /dev/null +++ b/lib/vm/pulsar/pulsar_topic_consume_view_model.dart @@ -0,0 +1,64 @@ +import 'package:paas_dashboard_flutter/api/pulsar/pulsar_topic_api.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_consume.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_namespace.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_tenant.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_topic.dart'; +import 'package:paas_dashboard_flutter/persistent/po/pulsar_instance_po.dart'; +import 'package:paas_dashboard_flutter/vm/base_load_list_view_model.dart'; + +class PulsarTopicConsumeViewModel extends BaseLoadListViewModel { + final PulsarInstancePo pulsarInstancePo; + final TenantResp tenantResp; + final NamespaceResp namespaceResp; + final TopicResp topicResp; + + PulsarTopicConsumeViewModel(this.pulsarInstancePo, this.tenantResp, + this.namespaceResp, this.topicResp); + + PulsarTopicConsumeViewModel deepCopy() { + return new PulsarTopicConsumeViewModel(pulsarInstancePo.deepCopy(), + tenantResp.deepCopy(), namespaceResp.deepCopy(), topicResp.deepCopy()); + } + + int get id { + return this.pulsarInstancePo.id; + } + + String get name { + return this.pulsarInstancePo.name; + } + + String get host { + return this.pulsarInstancePo.host; + } + + int get port { + return this.pulsarInstancePo.port; + } + + String get tenant { + return this.tenantResp.tenant; + } + + String get namespace { + return this.namespaceResp.namespace; + } + + String get topic { + return this.topicResp.topicName; + } + + Future fetchConsumers() async { + try { + final results = await PulsarTopicApi.getConsumers( + host, port, tenant, namespace, topic); + this.fullList = results; + this.displayList = this.fullList; + loadSuccess(); + } on Exception catch (e) { + loadException = e; + loading = false; + } + notifyListeners(); + } +} diff --git a/macos/Podfile.lock b/macos/Podfile.lock index f968896..2b61683 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -28,4 +28,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c -COCOAPODS: 1.11.2 +COCOAPODS: 1.10.2 diff --git a/pubspec.lock b/pubspec.lock index 588bf71..7765bee 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -160,7 +160,7 @@ packages: name: sqflite url: "https://pub.dartlang.org" source: hosted - version: "2.0.0+4" + version: "2.0.1" sqflite_common: dependency: transitive description: @@ -181,7 +181,7 @@ packages: name: sqlite3 url: "https://pub.dartlang.org" source: hosted - version: "1.3.1" + version: "1.4.0" stack_trace: dependency: transitive description: