Repository: provectus/kafka-ui
Issue: Display kafka cluser version 
Labels: type/enhancement
good first issue
scope/frontend

### Describe the solution you'd like

Add kafka cluster version on dashboard and brokers page.
On brokers page we could add it in the box with uptime


Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/model/InternalClusterMetrics.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/model/InternalClusterMetrics.java
index 28717dbcd3a..66bf2ccaa75 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/model/InternalClusterMetrics.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/model/InternalClusterMetrics.java
@@ -27,4 +27,5 @@ public class InternalClusterMetrics {
   private final Map<Integer, InternalBrokerMetrics> internalBrokerMetrics;
   private final List<Metric> metrics;
   private final int zooKeeperStatus;
+  private final String version;
 }
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/KafkaService.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/KafkaService.java
index d61f807c155..cc978d7a376 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/KafkaService.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/KafkaService.java
@@ -159,6 +159,7 @@ private KafkaCluster buildFromData(KafkaCluster currentCluster,
         .onlinePartitionCount(topicsMetrics.getOnlinePartitionCount())
         .offlinePartitionCount(topicsMetrics.getOfflinePartitionCount())
         .zooKeeperStatus(ClusterUtil.convertToIntServerStatus(zookeeperStatus))
+        .version(version)
         .build();
 
     return currentCluster.toBuilder()
diff --git a/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml b/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml
index 488566c166d..2bb431ac6ee 100644
--- a/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml
+++ b/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml
@@ -1417,6 +1417,8 @@ components:
           type: array
           items:
             $ref: '#/components/schemas/BrokerDiskUsage'
+        version:
+          type: string
 
     BrokerDiskUsage:
       type: object
diff --git a/kafka-ui-react-app/src/components/Brokers/Brokers.tsx b/kafka-ui-react-app/src/components/Brokers/Brokers.tsx
index 982cda4568f..9a14fe1cf28 100644
--- a/kafka-ui-react-app/src/components/Brokers/Brokers.tsx
+++ b/kafka-ui-react-app/src/components/Brokers/Brokers.tsx
@@ -27,6 +27,7 @@ const Brokers: React.FC<Props> = ({
   diskUsage,
   fetchClusterStats,
   fetchBrokers,
+  version,
 }) => {
   const { clusterName } = useParams<{ clusterName: ClusterName }>();
 
@@ -56,6 +57,9 @@ const Brokers: React.FC<Props> = ({
             {zkOnline ? 'Online' : 'Offline'}
           </span>
         </Indicator>
+        <Indicator className="is-one-third" label="Version">
+          {version}
+        </Indicator>
       </MetricsWrapper>
       <MetricsWrapper title="Partitions">
         <Indicator label="Online">
diff --git a/kafka-ui-react-app/src/components/Brokers/BrokersContainer.ts b/kafka-ui-react-app/src/components/Brokers/BrokersContainer.ts
index 9dad90a0abf..d61a049f768 100644
--- a/kafka-ui-react-app/src/components/Brokers/BrokersContainer.ts
+++ b/kafka-ui-react-app/src/components/Brokers/BrokersContainer.ts
@@ -12,6 +12,7 @@ import {
   getOutOfSyncReplicasCount,
   getUnderReplicatedPartitionCount,
   getDiskUsage,
+  getVersion,
 } from 'redux/reducers/brokers/selectors';
 import Brokers from 'components/Brokers/Brokers';
 
@@ -26,6 +27,7 @@ const mapStateToProps = (state: RootState) => ({
   outOfSyncReplicasCount: getOutOfSyncReplicasCount(state),
   underReplicatedPartitionCount: getUnderReplicatedPartitionCount(state),
   diskUsage: getDiskUsage(state),
+  version: getVersion(state),
 });
 
 const mapDispatchToProps = {
diff --git a/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx b/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx
index 7aab0fc3e57..2ec1b16f0b0 100644
--- a/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx
+++ b/kafka-ui-react-app/src/components/Brokers/__test__/Brokers.spec.tsx
@@ -26,6 +26,7 @@ describe('Brokers Component', () => {
           inSyncReplicasCount={0}
           outOfSyncReplicasCount={0}
           underReplicatedPartitionCount={0}
+          version="1"
           fetchClusterStats={jest.fn()}
           fetchBrokers={jest.fn()}
           diskUsage={undefined}
@@ -61,6 +62,7 @@ describe('Brokers Component', () => {
           inSyncReplicasCount={64}
           outOfSyncReplicasCount={0}
           underReplicatedPartitionCount={0}
+          version="1"
           fetchClusterStats={jest.fn()}
           fetchBrokers={jest.fn()}
           diskUsage={[
diff --git a/kafka-ui-react-app/src/components/Brokers/__test__/__snapshots__/Brokers.spec.tsx.snap b/kafka-ui-react-app/src/components/Brokers/__test__/__snapshots__/Brokers.spec.tsx.snap
index 24cb30bd533..be83a9ba00f 100644
--- a/kafka-ui-react-app/src/components/Brokers/__test__/__snapshots__/Brokers.spec.tsx.snap
+++ b/kafka-ui-react-app/src/components/Brokers/__test__/__snapshots__/Brokers.spec.tsx.snap
@@ -69,6 +69,7 @@ exports[`Brokers Component Brokers Empty matches Brokers Empty snapshot 1`] = `
       onlinePartitionCount={0}
       outOfSyncReplicasCount={0}
       underReplicatedPartitionCount={0}
+      version="1"
       zooKeeperStatus={0}
     >
       <div
@@ -179,6 +180,29 @@ exports[`Brokers Component Brokers Empty matches Brokers Empty snapshot 1`] = `
                   </div>
                 </div>
               </Indicator>
+              <Indicator
+                className="is-one-third"
+                label="Version"
+              >
+                <div
+                  className="level-item is-one-third"
+                >
+                  <div
+                    title="Version"
+                  >
+                    <p
+                      className="heading"
+                    >
+                      Version
+                    </p>
+                    <p
+                      className="title has-text-centered"
+                    >
+                      1
+                    </p>
+                  </div>
+                </div>
+              </Indicator>
             </div>
           </div>
         </MetricsWrapper>
@@ -400,6 +424,7 @@ exports[`Brokers Component Brokers matches snapshot 1`] = `
       onlinePartitionCount={64}
       outOfSyncReplicasCount={0}
       underReplicatedPartitionCount={0}
+      version="1"
       zooKeeperStatus={1}
     >
       <div
@@ -510,6 +535,29 @@ exports[`Brokers Component Brokers matches snapshot 1`] = `
                   </div>
                 </div>
               </Indicator>
+              <Indicator
+                className="is-one-third"
+                label="Version"
+              >
+                <div
+                  className="level-item is-one-third"
+                >
+                  <div
+                    title="Version"
+                  >
+                    <p
+                      className="heading"
+                    >
+                      Version
+                    </p>
+                    <p
+                      className="title has-text-centered"
+                    >
+                      1
+                    </p>
+                  </div>
+                </div>
+              </Indicator>
             </div>
           </div>
         </MetricsWrapper>
diff --git a/kafka-ui-react-app/src/components/Dashboard/ClustersWidget/ClusterWidget.tsx b/kafka-ui-react-app/src/components/Dashboard/ClustersWidget/ClusterWidget.tsx
index 43d076ae15a..4231e277617 100644
--- a/kafka-ui-react-app/src/components/Dashboard/ClustersWidget/ClusterWidget.tsx
+++ b/kafka-ui-react-app/src/components/Dashboard/ClustersWidget/ClusterWidget.tsx
@@ -18,6 +18,7 @@ const ClusterWidget: React.FC<ClusterWidgetProps> = ({
     bytesOutPerSec,
     onlinePartitionCount,
     readOnly,
+    version,
   },
 }) => (
   <div className="column is-full-modile is-6">
@@ -38,6 +39,10 @@ const ClusterWidget: React.FC<ClusterWidgetProps> = ({
 
       <table className="table is-fullwidth">
         <tbody>
+          <tr>
+            <th>Version</th>
+            <td>{version}</td>
+          </tr>
           <tr>
             <th>Brokers</th>
             <td>
diff --git a/kafka-ui-react-app/src/components/Dashboard/ClustersWidget/__test__/__snapshots__/ClusterWidget.spec.tsx.snap b/kafka-ui-react-app/src/components/Dashboard/ClustersWidget/__test__/__snapshots__/ClusterWidget.spec.tsx.snap
index 8ab8a406d3e..8d6b8173f84 100644
--- a/kafka-ui-react-app/src/components/Dashboard/ClustersWidget/__test__/__snapshots__/ClusterWidget.spec.tsx.snap
+++ b/kafka-ui-react-app/src/components/Dashboard/ClustersWidget/__test__/__snapshots__/ClusterWidget.spec.tsx.snap
@@ -21,6 +21,12 @@ exports[`ClusterWidget when cluster is offline matches snapshot 1`] = `
       className="table is-fullwidth"
     >
       <tbody>
+        <tr>
+          <th>
+            Version
+          </th>
+          <td />
+        </tr>
         <tr>
           <th>
             Brokers
@@ -100,6 +106,12 @@ exports[`ClusterWidget when cluster is online matches snapshot 1`] = `
       className="table is-fullwidth"
     >
       <tbody>
+        <tr>
+          <th>
+            Version
+          </th>
+          <td />
+        </tr>
         <tr>
           <th>
             Brokers
diff --git a/kafka-ui-react-app/src/redux/reducers/brokers/selectors.ts b/kafka-ui-react-app/src/redux/reducers/brokers/selectors.ts
index 3c6ef947dd4..9b841b464b3 100644
--- a/kafka-ui-react-app/src/redux/reducers/brokers/selectors.ts
+++ b/kafka-ui-react-app/src/redux/reducers/brokers/selectors.ts
@@ -48,3 +48,8 @@ export const getDiskUsage = createSelector(
   brokersState,
   ({ diskUsage }) => diskUsage
 );
+
+export const getVersion = createSelector(
+  brokersState,
+  ({ version }) => version
+);


Test patch: