Browse Source

[UI] Cleanup

Oleg Shuralev 5 years ago
parent
commit
25a7bf0301

+ 101 - 105
frontend/src/components/Brokers/Brokers.tsx

@@ -1,5 +1,4 @@
 import React from 'react';
 import React from 'react';
-import PageLoader from 'components/common/PageLoader/PageLoader';
 import { ClusterId, BrokerMetrics, ZooKeeperStatus } from 'types';
 import { ClusterId, BrokerMetrics, ZooKeeperStatus } from 'types';
 import useInterval from 'lib/hooks/useInterval';
 import useInterval from 'lib/hooks/useInterval';
 import formatBytes from 'lib/utils/formatBytes';
 import formatBytes from 'lib/utils/formatBytes';
@@ -41,134 +40,131 @@ const Topics: React.FC<Props> = ({
 
 
   useInterval(() => { fetchBrokerMetrics(clusterId); }, 5000);
   useInterval(() => { fetchBrokerMetrics(clusterId); }, 5000);
 
 
-  if (isFetched) {
-    const [minDiskUsageValue, minDiskUsageSize] = formatBytes(minDiskUsage);
-    const [maxDiskUsageValue, maxDiskUsageSize] = formatBytes(maxDiskUsage);
+  const [minDiskUsageValue, minDiskUsageSize] = formatBytes(minDiskUsage);
+  const [maxDiskUsageValue, maxDiskUsageSize] = formatBytes(maxDiskUsage);
 
 
-    return (
-      <div className="section">
-        <div className="box">
-          <h5 className="title is-5">Uptime</h5>
-          <div className="level">
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Total Brokers</p>
-                <p className="title">{brokerCount}</p>
-              </div>
+  return (
+    <div className="section">
+      <div className="box">
+        <h5 className="title is-5">Uptime</h5>
+        <div className="level">
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">Total Brokers</p>
+              <p className="title">{brokerCount}</p>
             </div>
             </div>
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Active Controllers</p>
-                <p className="title">{activeControllers}</p>
-              </div>
+          </div>
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">Active Controllers</p>
+              <p className="title">{activeControllers}</p>
             </div>
             </div>
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Zookeeper Status</p>
-                <p className="title">
-                  {zooKeeperStatus === ZooKeeperStatus.online ? (
-                    <span className="tag is-primary">Online</span>
-                  ) : (
-                    <span className="tag is-danger">Offline</span>
-                  )}
-                </p>
-              </div>
+          </div>
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">Zookeeper Status</p>
+              <p className="title">
+                {zooKeeperStatus === ZooKeeperStatus.online ? (
+                  <span className="tag is-primary">Online</span>
+                ) : (
+                  <span className="tag is-danger">Offline</span>
+                )}
+              </p>
             </div>
             </div>
           </div>
           </div>
         </div>
         </div>
+      </div>
 
 
-        <div className="box">
-          <h5 className="title is-5">Partitions</h5>
-          <div className="level">
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Online</p>
-                <p>
-                  <span className={cx('title', {'has-text-danger': offlinePartitionCount !== 0})}>
-                    {onlinePartitionCount}
-                  </span>
-                  <span className="subtitle"> of {onlinePartitionCount + offlinePartitionCount}</span>
-                </p>
-              </div>
+      <div className="box">
+        <h5 className="title is-5">Partitions</h5>
+        <div className="level">
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">Online</p>
+              <p>
+                <span className={cx('title', {'has-text-danger': offlinePartitionCount !== 0})}>
+                  {onlinePartitionCount}
+                </span>
+                <span className="subtitle"> of {onlinePartitionCount + offlinePartitionCount}</span>
+              </p>
             </div>
             </div>
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Under Replicated</p>
-                <p className="title">{underReplicatedPartitionCount}</p>
-              </div>
+          </div>
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">Under Replicated</p>
+              <p className="title">{underReplicatedPartitionCount}</p>
             </div>
             </div>
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">In Sync Replicas</p>
-                <p className="title has-text-grey-lighter">Soon</p>
-              </div>
+          </div>
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">In Sync Replicas</p>
+              <p className="title has-text-grey-lighter">Soon</p>
             </div>
             </div>
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Out of Sync Replicas</p>
-                <p className="title has-text-grey-lighter">Soon</p>
-              </div>
+          </div>
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">Out of Sync Replicas</p>
+              <p className="title has-text-grey-lighter">Soon</p>
             </div>
             </div>
           </div>
           </div>
         </div>
         </div>
+      </div>
 
 
-        <div className="box">
-          <h5 className="title is-5">Disk</h5>
-          <div className="level">
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Max usage</p>
-                <p>
-                  <span className="title">{maxDiskUsageValue}</span>
-                  <span className="subtitle"> {maxDiskUsageSize}</span>
-                </p>
-              </div>
+      <div className="box">
+        <h5 className="title is-5">Disk</h5>
+        <div className="level">
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">Max usage</p>
+              <p>
+                <span className="title">{maxDiskUsageValue}</span>
+                <span className="subtitle"> {maxDiskUsageSize}</span>
+              </p>
             </div>
             </div>
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Min Usage</p>
-                <p>
-                  <span className="title">{minDiskUsageValue}</span>
-                  <span className="subtitle"> {minDiskUsageSize}</span>
-                </p>
-              </div>
+          </div>
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">Min Usage</p>
+              <p>
+                <span className="title">{minDiskUsageValue}</span>
+                <span className="subtitle"> {minDiskUsageSize}</span>
+              </p>
             </div>
             </div>
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Distribution</p>
-                <p className="title">{diskUsageDistribution}</p>
-              </div>
+          </div>
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">Distribution</p>
+              <p className="title is-capitalized">{diskUsageDistribution}</p>
             </div>
             </div>
           </div>
           </div>
         </div>
         </div>
-        <div className="box">
-          <h5 className="title is-5">System</h5>
-          <div className="level">
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Network pool usage</p>
-                <p className="title">
-                  {Math.round(networkPoolUsage * 10000) / 100}
-                  <span className="subtitle">%</span>
-                </p>
-              </div>
+      </div>
+
+      <div className="box">
+        <h5 className="title is-5">System</h5>
+        <div className="level">
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">Network pool usage</p>
+              <p className="title">
+                {Math.round(networkPoolUsage * 10000) / 100}
+                <span className="subtitle">%</span>
+              </p>
             </div>
             </div>
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Request pool usage</p>
-                <p className="title">
-                  {Math.round(requestPoolUsage * 10000) / 100}
-                  <span className="subtitle">%</span>
-                </p>
-              </div>
+          </div>
+          <div className="level-item level-left">
+            <div>
+              <p className="heading">Request pool usage</p>
+              <p className="title">
+                {Math.round(requestPoolUsage * 10000) / 100}
+                <span className="subtitle">%</span>
+              </p>
             </div>
             </div>
           </div>
           </div>
         </div>
         </div>
       </div>
       </div>
-    );
-  }
-
-  return (<PageLoader />);
+    </div>
+  );
 }
 }
 
 
 export default Topics;
 export default Topics;

+ 13 - 57
frontend/src/components/Topics/Details/Details.tsx

@@ -1,64 +1,20 @@
 import React from 'react';
 import React from 'react';
-import { Topic, TopicConfigs } from 'types';
-import ConfigRow from './ConfigRow';
-import Partition from './Partition';
 
 
-const Details: React.FC<{ topic: Topic }> = ({
-  topic: {
-    name,
-    partitions,
-  }
+const Details: React.FC = ({
 }) => {
 }) => {
-  const configs: TopicConfigs = {[ 'key-config']: '1' };
-  const configKeys = Object.keys(configs);
-
   return (
   return (
-    <>
-      <section className="hero is-info is-bold">
-        <div className="hero-body">
-          <div className="level has-text-white">
-            <div className="level-item level-left">
-              <div>
-                <p className="heading">Name</p>
-                <p className="title has-text-white">{name}</p>
-              </div>
-            </div>
-            <div className="level-item level-left  has-text-centered ">
-              <div>
-                <p className="heading">Partitions</p>
-                <p className="title has-text-white">{partitions.length}</p>
-              </div>
-            </div>
-          </div>
-        </div>
-      </section>
-
-      <section className="container is-fluid">
-        <div className="tile is-parent">
-
-          <div className="tile is-parent is-7 is-vertical is-narrow">
-            {partitions.map((partition) => <Partition {...partition} />)}
-          </div>
-
-          <div className="tile is-parent">
-            <div className="tile is-child box">
-              <h2 className="title is-5">Config</h2>
-              <table className="table is-striped is-fullwidth">
-                <thead>
-                  <tr>
-                    <th>Key</th>
-                    <th>Value</th>
-                  </tr>
-                </thead>
-                <tbody>
-                  {configKeys.map((key) => <ConfigRow name={key} key={key} value={configs[key]} />)}
-                </tbody>
-              </table>
-            </div>
-          </div>
-        </div>
-      </section>
-    </>
+    <div className="section">
+      <div className="tabs">
+        <ul>
+          <li className="is-active">
+            <a>Pictures</a>
+          </li>
+          <li><a>Music</a></li>
+          <li><a>Videos</a></li>
+          <li><a>Documents</a></li>
+        </ul>
+      </div>
+    </div>
   );
   );
 }
 }
 
 

+ 0 - 1
frontend/src/lib/utils/formatBytes.ts

@@ -1,6 +1,5 @@
 function formatBytes(bytes: number, decimals: number = 0) {
 function formatBytes(bytes: number, decimals: number = 0) {
     const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
     const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
-
     if (bytes === 0) return [0, sizes[0]];
     if (bytes === 0) return [0, sizes[0]];
 
 
     const k = 1024;
     const k = 1024;

+ 20 - 5
frontend/src/redux/reducers/brokers/reducer.ts

@@ -1,4 +1,4 @@
-import { Action, BrokersState, ZooKeeperStatus } from 'types';
+import { Action, BrokersState, ZooKeeperStatus, BrokerMetrics } from 'types';
 import actionType from 'redux/reducers/actionType';
 import actionType from 'redux/reducers/actionType';
 
 
 export const initialState: BrokersState =  {
 export const initialState: BrokersState =  {
@@ -12,20 +12,35 @@ export const initialState: BrokersState =  {
   offlinePartitionCount: 0,
   offlinePartitionCount: 0,
   underReplicatedPartitionCount: 0,
   underReplicatedPartitionCount: 0,
   diskUsageDistribution: undefined,
   diskUsageDistribution: undefined,
+  diskUsage: [],
+};
+
+const updateBrokerSegmentSize = (state: BrokersState, payload: BrokerMetrics) => {
+  const brokers = state.items;
+  const { diskUsage } = payload;
+
+  const items = brokers.map((broker) => {
+    const brokerMetrics = diskUsage.find(({ brokerId }) => brokerId === broker.brokerId);
+    if (brokerMetrics !== undefined) {
+      return { ...broker, ...brokerMetrics };
+    }
+    return broker;
+  });
+
+  return { ...state, items, ...payload };
 };
 };
 
 
 const reducer = (state = initialState, action: Action): BrokersState => {
 const reducer = (state = initialState, action: Action): BrokersState => {
   switch (action.type) {
   switch (action.type) {
+    case actionType.GET_BROKERS__REQUEST:
+      return initialState;
     case actionType.GET_BROKERS__SUCCESS:
     case actionType.GET_BROKERS__SUCCESS:
       return {
       return {
         ...state,
         ...state,
         items: action.payload,
         items: action.payload,
       };
       };
     case actionType.GET_BROKER_METRICS__SUCCESS:
     case actionType.GET_BROKER_METRICS__SUCCESS:
-      return {
-        ...state,
-        ...action.payload,
-      };
+      return updateBrokerSegmentSize(state, action.payload);
     default:
     default:
       return state;
       return state;
   }
   }

+ 14 - 2
frontend/src/redux/reducers/brokers/selectors.ts

@@ -25,10 +25,22 @@ export const getUnderReplicatedPartitionCount = createSelector(brokersState, ({
 
 
 export const getMinDiskUsage = createSelector(
 export const getMinDiskUsage = createSelector(
   getBrokerList,
   getBrokerList,
-  (brokers) => Math.min(...brokers.map(({ segmentSize }) => segmentSize)),
+  (brokers) => {
+    if (brokers.length === 0) {
+      return 0;
+    }
+
+    return Math.min(...brokers.map(({ segmentSize }) => segmentSize));
+  },
 );
 );
 
 
 export const getMaxDiskUsage = createSelector(
 export const getMaxDiskUsage = createSelector(
   getBrokerList,
   getBrokerList,
-  (brokers) => Math.max(...brokers.map(({ segmentSize }) => segmentSize)),
+  (brokers) => {
+    if (brokers.length === 0) {
+      return 0;
+    }
+
+    return Math.max(...brokers.map(({ segmentSize }) => segmentSize));
+  },
 );
 );

+ 9 - 0
frontend/src/theme/index.scss

@@ -38,3 +38,12 @@ code {
   text-overflow: ellipsis;
   text-overflow: ellipsis;
   white-space: nowrap;
   white-space: nowrap;
 }
 }
+
+.section {
+  animation: fadein .5s;
+}
+
+@keyframes fadein {
+  from { opacity: 0; }
+  to   { opacity: 1; }
+}

+ 1 - 0
frontend/src/types/broker.ts

@@ -25,6 +25,7 @@ export interface BrokerMetrics {
   offlinePartitionCount: number;
   offlinePartitionCount: number;
   underReplicatedPartitionCount: number;
   underReplicatedPartitionCount: number;
   diskUsageDistribution?: string;
   diskUsageDistribution?: string;
+  diskUsage: BrokerDiskUsage[];
 }
 }
 
 
 export interface BrokersState extends BrokerMetrics {
 export interface BrokersState extends BrokerMetrics {