diff --git a/pkg/ui/src/components/core/colors.styl b/pkg/ui/src/components/core/colors.styl index f9876f9348e9..7179bf32a37b 100644 --- a/pkg/ui/src/components/core/colors.styl +++ b/pkg/ui/src/components/core/colors.styl @@ -40,6 +40,7 @@ $colors--primary-blue-3 = #0788ff $colors--primary-blue-4 = #005fb3 $colors--primary-blue-5 = #00294d +$colors--primary-green-0 = #daf8d4 $colors--primary-green-1 = #b4f1aa $colors--primary-green-2 = #76de49 $colors--primary-green-3 = #37a806 diff --git a/pkg/ui/src/util/decorators.tsx b/pkg/ui/src/util/decorators.tsx new file mode 100644 index 000000000000..8849bea30f85 --- /dev/null +++ b/pkg/ui/src/util/decorators.tsx @@ -0,0 +1,35 @@ +// Copyright 2020 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +import React from "react"; +import { RenderFunction } from "storybook__react"; +import { Provider } from "react-redux"; +import { combineReducers, createStore } from "redux"; +import { ConnectedRouter, connectRouter } from "connected-react-router"; +import { createMemoryHistory } from "history"; + +const history = createMemoryHistory(); +const routerReducer = connectRouter(history); + +const store = createStore( + combineReducers({ + router: routerReducer, + }), +); + +export const styledWrapper = (styles: React.CSSProperties) => ( + storyFn: RenderFunction, +) =>
{storyFn()}
; + +export const withRouterDecorator = (storyFn: RenderFunction) => ( + + {storyFn()} + +); diff --git a/pkg/ui/src/views/reports/containers/network/index.tsx b/pkg/ui/src/views/reports/containers/network/index.tsx index 8c217cb873a8..d9f435729526 100644 --- a/pkg/ui/src/views/reports/containers/network/index.tsx +++ b/pkg/ui/src/views/reports/containers/network/index.tsx @@ -41,7 +41,7 @@ interface NetworkOwnProps { export interface Identity { nodeID: number; address: string; - locality: string; + locality?: string; updatedAt: moment.Moment; } @@ -76,6 +76,9 @@ function contentAvailable(nodesSummary: NodesSummary) { } export function getValueFromString(key: string, params: string, fullString?: boolean) { + if (!params) { + return; + } const result = params.match(new RegExp(key + "=([^,#]*)")); if (!result) { return; diff --git a/pkg/ui/src/views/reports/containers/network/latency/index.tsx b/pkg/ui/src/views/reports/containers/network/latency/index.tsx index 3fda574256a0..28e62863b4f4 100644 --- a/pkg/ui/src/views/reports/containers/network/latency/index.tsx +++ b/pkg/ui/src/views/reports/containers/network/latency/index.tsx @@ -28,7 +28,7 @@ interface StdDev { stddevPlus2: number; } -interface ILegendProps { +export interface ILatencyProps { displayIdentities: Identity[]; staleIDs: Set; multipleHeader: boolean; @@ -159,20 +159,6 @@ const getLatencyCell = ({ latency, identityB, identityA }: { latency: number; id /> ); } - if (latency === -2) { - return ( - - - - - - ); - } if (latency === -1) { return ( 0 && latency > std.stddevPlus2, }); const type: any = classNames({ + "yellow": + latency === -2, "green": - std.stddev > 0 && latency < std.stddevMinus2, + latency > 0 && std.stddev > 0 && latency < std.stddevMinus2, "lightgreen": - std.stddev > 0 && latency < std.stddevMinus1 && latency >= std.stddevMinus2, + latency > 0 && std.stddev > 0 && latency < std.stddevMinus1 && latency >= std.stddevMinus2, "grey": - std.stddev > 0 && latency >= std.stddevMinus1 && latency <= std.stddevPlus1, + latency > 0 && std.stddev > 0 && latency >= std.stddevMinus1 && latency <= std.stddevPlus1, "lightblue": - std.stddev > 0 && latency > std.stddevPlus1 && latency <= std.stddevPlus2, + latency > 0 && std.stddev > 0 && latency > std.stddevPlus1 && latency <= std.stddevPlus2, "blue": - std.stddev > 0 && latency > std.stddevPlus2, + latency > 0 && std.stddev > 0 && latency > std.stddevPlus2, }); + const renderDescription = (data: string) => { + if (!data) { + return; + } + return _.map(data.split(","), (identity, index) => ( +

+ {`${identity},`} +

+ )); + }; return ( {collapsed ? ( @@ -225,20 +223,20 @@ const getLatencyCell = ({ latency, identityB, identityA }: { latency: number; id

{`Node ${identityB.nodeID}`}

-

{identityB.locality}

+ {renderDescription(identityB.locality)}

{`Node ${identityA.nodeID}`}

-

{identityA.locality}

+ {renderDescription(identityA.locality)}
-

{`${latency.toFixed(2)}ms roundtrip`}

+ {latency > 0 &&

{`${latency.toFixed(2)}ms roundtrip`}

} )}>
0 ? latency.toFixed(2) + "ms" : "--"} type={type} />
@@ -249,7 +247,7 @@ const getLatencyCell = ({ latency, identityB, identityA }: { latency: number; id }; // tslint:disable-next-line: variable-name -export const Latency: React.SFC = ({ +export const Latency: React.SFC = ({ displayIdentities, staleIDs, multipleHeader, diff --git a/pkg/ui/src/views/reports/containers/network/latency/latency.fixtures.ts b/pkg/ui/src/views/reports/containers/network/latency/latency.fixtures.ts new file mode 100644 index 000000000000..fadea7d529eb --- /dev/null +++ b/pkg/ui/src/views/reports/containers/network/latency/latency.fixtures.ts @@ -0,0 +1,281 @@ +// Copyright 2020 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +import moment from "moment"; +import Long from "long"; +import { ILatencyProps } from "."; + +const node1 = { + desc: { + node_id: 1, + locality: { + tiers: [ + { key: "region", value: "local" }, + { key: "zone", value: "local" }, + ], + }, + }, + activity: { + "1": { incoming: 85125, outgoing: 204928, latency: Long.fromInt(843506) }, + "2": { + incoming: 1641005, + outgoing: 196537462, + latency: Long.fromInt(12141), + }, + "3": { incoming: 27851, outgoing: 15530093 }, + "4": { + incoming: 4346803, + outgoing: 180065134, + latency: Long.fromInt(505076), + }, + }, +}; +const node2 = { + desc: { + node_id: 2, + locality: { + tiers: [ + { key: "region", value: "local" }, + { key: "zone", value: "local" }, + ], + }, + }, + activity: { + "1": { + incoming: 8408467, + outgoing: 97930352, + latency: Long.fromInt(1455817), + }, + "2": {}, + "3": { incoming: 22800, outgoing: 13925347 }, + "4": { + incoming: 1328435, + outgoing: 63271505, + latency: Long.fromInt(766402), + }, + }, +}; +const node3 = { + desc: { + node_id: 3, + locality: { + tiers: [ + { key: "region", value: "local" }, + { key: "zone", value: "local" }, + ], + }, + }, + activity: { + "1": { incoming: 49177, outgoing: 173961 }, + "2": { incoming: 98747, outgoing: 80848 }, + "3": {}, + "4": { incoming: 18239, outgoing: 12407 }, + }, +}; +const node4 = { + desc: { + node_id: 4, + locality: { + tiers: [ + { key: "region", value: "local" }, + { key: "zone", value: "local" }, + ], + }, + }, + + activity: { + "1": { + incoming: 4917367, + outgoing: 51102302, + latency: Long.fromInt(1589900), + }, + "2": { + incoming: 2657214, + outgoing: 24963000, + latency: Long.fromInt(1807269), + }, + "3": { incoming: 26480, outgoing: 251052 }, + "4": {}, + }, +}; + +export const latencyFixture: ILatencyProps = { + displayIdentities: [ + { + nodeID: 1, + address: "127.0.0.1:26257", + locality: "region=local,zone=local", + updatedAt: moment("2020-05-04T16:26:08.122Z"), + }, + { + nodeID: 2, + address: "127.0.0.1:26259", + locality: "region=local,zone=local", + updatedAt: moment("2020-05-04T16:26:08.674Z"), + }, + { + nodeID: 3, + address: "127.0.0.1:26261", + locality: "region=local,zone=local", + updatedAt: moment("2020-05-04T16:25:52.640Z"), + }, + { + nodeID: 4, + address: "127.0.0.1:26263", + locality: "region=local,zone=local", + updatedAt: moment("2020-05-04T16:26:09.871Z"), + }, + ], + staleIDs: new Set([3]), + multipleHeader: true, + collapsed: false, + nodesSummary: { + nodeStatuses: [node1, node2, node3, node4], + nodeIDs: [1, 2, 3, 4], + nodeStatusByID: { + "1": node1, + "2": node2, + "3": node3, + "4": node4, + }, + +}, + std: { + stddev: 0.3755919319616704, + stddevMinus2: 0.29658363607665916, + stddevMinus1: 0.6721755680383296, + stddevPlus1: 1.4233594319616705, + stddevPlus2: 1.798951363923341, + }, + node_id: "region", +}; + +const nodeNoLocality1 = { + desc: { + node_id: 1, + }, + activity: { + "1": { incoming: 85125, outgoing: 204928, latency: Long.fromInt(843506) }, + "2": { + incoming: 1641005, + outgoing: 196537462, + latency: Long.fromInt(12141), + }, + "3": { incoming: 27851, outgoing: 15530093 }, + "4": { + incoming: 4346803, + outgoing: 180065134, + latency: Long.fromInt(505076), + }, + }, +}; +const nodeNoLocality2 = { + desc: { + node_id: 2, + }, + activity: { + "1": { + incoming: 8408467, + outgoing: 97930352, + latency: Long.fromInt(1455817), + }, + "2": {}, + "3": { incoming: 22800, outgoing: 13925347 }, + "4": { + incoming: 1328435, + outgoing: 63271505, + latency: Long.fromInt(766402), + }, + }, +}; +const nodeNoLocality3 = { + desc: { + node_id: 3, + }, + activity: { + "1": { incoming: 49177, outgoing: 173961 }, + "2": { incoming: 98747, outgoing: 80848 }, + "3": {}, + "4": { incoming: 18239, outgoing: 12407 }, + }, +}; +const nodeNoLocality4 = { + desc: { + node_id: 4, + locality: { + tiers: [ + { key: "region", value: "local" }, + { key: "zone", value: "local" }, + ], + }, + }, + + activity: { + "1": { + incoming: 4917367, + outgoing: 51102302, + latency: Long.fromInt(1589900), + }, + "2": { + incoming: 2657214, + outgoing: 24963000, + latency: Long.fromInt(1807269), + }, + "3": { incoming: 26480, outgoing: 251052 }, + "4": {}, + }, +}; + +export const latencyFixtureNoLocality: ILatencyProps = { + displayIdentities: [ + { + nodeID: 1, + address: "127.0.0.1:26257", + updatedAt: moment("2020-05-04T16:26:08.122Z"), + }, + { + nodeID: 2, + address: "127.0.0.1:26259", + updatedAt: moment("2020-05-04T16:26:08.674Z"), + }, + { + nodeID: 3, + address: "127.0.0.1:26261", + updatedAt: moment("2020-05-04T16:25:52.640Z"), + }, + { + nodeID: 4, + address: "127.0.0.1:26263", + updatedAt: moment("2020-05-04T16:26:09.871Z"), + }, + ], + staleIDs: new Set([3]), + multipleHeader: true, + collapsed: false, + nodesSummary: { + nodeStatuses: [nodeNoLocality1, nodeNoLocality2, nodeNoLocality3, nodeNoLocality4], + nodeIDs: [1, 2, 3, 4], + nodeStatusByID: { + "1": nodeNoLocality1, + "2": nodeNoLocality2, + "3": nodeNoLocality3, + "4": nodeNoLocality4, + }, + +}, + std: { + stddev: 0.3755919319616704, + stddevMinus2: 0.29658363607665916, + stddevMinus1: 0.6721755680383296, + stddevPlus1: 1.4233594319616705, + stddevPlus2: 1.798951363923341, + }, + node_id: "region", +}; diff --git a/pkg/ui/src/views/reports/containers/network/latency/latency.stories.tsx b/pkg/ui/src/views/reports/containers/network/latency/latency.stories.tsx new file mode 100644 index 000000000000..45b12953ba1f --- /dev/null +++ b/pkg/ui/src/views/reports/containers/network/latency/latency.stories.tsx @@ -0,0 +1,24 @@ +// Copyright 2020 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +import React from "react"; +import { storiesOf } from "@storybook/react"; +import {Latency} from "./index"; +import { latencyFixture, latencyFixtureNoLocality } from "./latency.fixtures"; +import { withRouterDecorator } from "src/util/decorators"; + +storiesOf("Latency Table", module) + .addDecorator(withRouterDecorator) + .add("Default state", () => ( + + )) + .add("No localites state", () => ( + + )); diff --git a/pkg/ui/src/views/reports/containers/network/latency/latency.styl b/pkg/ui/src/views/reports/containers/network/latency/latency.styl index b87a36164c23..d0c2b330753b 100644 --- a/pkg/ui/src/views/reports/containers/network/latency/latency.styl +++ b/pkg/ui/src/views/reports/containers/network/latency/latency.styl @@ -82,3 +82,50 @@ .latency-table__empty padding: 30px; + + +.ant-tooltip.Chip--tooltip + min-width 384px + .ant-tooltip-inner + background-color black + padding 12px 18px + .ant-tooltip-content + width 100% + span, p + font-family $font-family--base + font-size 14px + line-height 1.71 + letter-spacing 0.1px + color $table-border-color + .Chip--tooltip__latency + margin-top 25px + .Chip--tooltip__nodes + display flex + justify-content space-between + &--item + width 45% + &:first-child + margin-right 8px + &:last-child + margin-left 8px + .ant-divider + background #3b4a60 + margin 0 + &--item-title, &--item-description + font-family $font-family--base + font-size 14px + line-height 1.57 + letter-spacing 0.1px + color $table-border-color + margin 0 + &--item-title + line-height 1.71 + .color + &--green, &--lightgreen + color $colors--primary-green-2 + &--grey + color $colors--neutral-2 + &--blue, &--lightblue + color $colors--primary-blue-2 + &--yellow + color $colors--functional-yellow-3 diff --git a/pkg/ui/styl/base/palette.styl b/pkg/ui/styl/base/palette.styl index f5e75f5904ae..a727eba33ecc 100644 --- a/pkg/ui/styl/base/palette.styl +++ b/pkg/ui/styl/base/palette.styl @@ -69,7 +69,7 @@ $light-blue = $colors--primary-blue-2 $green = $colors--primary-green-3 $grey2 = $colors--neutral-3 $chip-green = $colors--primary-green-1 -$chip-lightgreen = $colors--primary-green-1 +$chip-lightgreen = $colors--primary-green-0 $chip-grey = $colors--neutral-1 $chip-blue = #74bdfd80 // $colors--primary-blue-2 + 0.5 opacity $chip-lightblue = $colors--primary-blue-1 diff --git a/pkg/ui/styl/shame.styl b/pkg/ui/styl/shame.styl index e8c7376537a4..7400a9d066a1 100644 --- a/pkg/ui/styl/shame.styl +++ b/pkg/ui/styl/shame.styl @@ -296,54 +296,6 @@ letter-spacing 0.1px color $popover-color -.Chip--tooltip - width 250px - .ant-tooltip-inner - background-color black - padding 12px 18px - span, p - font-family Lato-Bold - font-size 14px - line-height 1.71 - letter-spacing 0.1px - color $table-border-color - .Chip--tooltip__nodes - margin-bottom 25px - display flex - justify-content space-between - &--item - width 95px - &:first-child - margin-right 8px - &:last-child - margin-left 8px - .ant-divider - background #3b4a60 - margin 0 - &--item-title, &--item-description - font-family Lato-Regular - font-size 14px - line-height 1.57 - letter-spacing 0.1px - color $table-border-color - margin 0 - &--item-title - font-family Lato-Bold - line-height 1.71 - .color - &--green - color $green - &--lightgreen - color $lightgreen - &--grey - color $grey - &--lightblue - color $lightblue - &--blue - color $blue - &--yellow - color $yellow - .ant-pagination display flex justify-content center