Skip to content

Commit

Permalink
ui: Alert Refactoring, remove most Banner Alerts
Browse files Browse the repository at this point in the history
This is a significant refactoring of the systems previously used to display
banner-type notifications.

+ All logic on whether or not to display alerts has been moved to a series of
selectors in `redux/alerts.ts`. After many factoring attempts, using a selector
for each alert seemed like the appropriate design based on current requirements.
+ A new sync service has been added in `alerts.ts`, which is responsible for
loading data from the server which is needed to display alerts. This was chosen
because loading this data using the same method as other components (e.g. how
metric data is loaded) was proving tedious given the nature of alert-relevant
information (only needs to be loaded once, a variety of different settings).
+ Most alerts have been moved from Banners into a dismissable panel which is
displayed on the cluster page. This makes them significantly less disruptive.
+ Significant testing has been added for the alert display logic and the alert
sync service.

Not in this issue:

+ The "cluster disconnected" banner has not been modified, it still displays at
its previous position. The styling of this banner will be changed in a
subsequent pull request, but it will remain visible across all pages because it
is relevant to all pages.

Additional Refactoring changes:

+ Renamed `AdminUIState.ui` -> `AdminUIState.localSettings` to make its purpose
more clear.

Resolves cockroachdb#12890
Resolves cockroachdb#12590
  • Loading branch information
Matt Tracy committed Apr 13, 2017
1 parent f73bd7e commit 1f9a1cc
Show file tree
Hide file tree
Showing 28 changed files with 919 additions and 276 deletions.
Empty file removed pkg/ui/build/.gitkeep
Empty file.
2 changes: 1 addition & 1 deletion pkg/ui/embedded.go

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions pkg/ui/src/components/alertBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as React from "react";
import classNames from "classnames";

import { AlertInfo, AlertLevel } from "../redux/alerts";
import { warningIcon, notificationIcon, criticalIcon } from "../components/icons";
import { trustIcon } from "../util/trust";

function alertIcon (level: AlertLevel) {
switch (level) {
case AlertLevel.CRITICAL:
return trustIcon(criticalIcon);
case AlertLevel.WARNING:
return trustIcon(warningIcon);
default:
return trustIcon(notificationIcon);
}
}

export interface AlertBoxProps extends AlertInfo {
dismiss(): void;
}

export class AlertBox extends React.Component<AlertBoxProps, {}> {
render() {
// build up content element, which has a wrapping anchor element that is
// conditionally present.
let content = <div>
<div className="alert-box__title">{this.props.title}</div>
<div className="alert-box__text">{this.props.text}</div>
</div>;

if (this.props.link) {
content = <a className="alert-box__link" href={this.props.link}>
{ content }
</a>;
}

content = <div className="alert-box__content">
{ content }
</div>;

return <div className={classNames("alert-box", `alert-box--${AlertLevel[this.props.level].toLowerCase()}`)}>
<div className="alert-box__icon" dangerouslySetInnerHTML={alertIcon(this.props.level)} />
{ content }
<div className="alert-box__dismiss">
<a className="alert-box__link" onClick={this.props.dismiss}></a>
</div>
</div>;
}
}
61 changes: 61 additions & 0 deletions pkg/ui/src/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,64 @@ export const rightArrow: string = `<svg width="7px" height="10px" viewBox="0 0 7
</g>
</g>
</svg>`;

export let criticalIcon: string = `<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>Group 3</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Warning---Connection-Lost" transform="translate(-25.000000, -19.000000)">
<g id="Group-3">
<g transform="translate(25.000000, 19.000000)">
<path d="M8.75139389,1.26729609 C9.24631171,0.277343549 10.0519669,0.283622947 10.5438615,1.26729609 L19.1995435,18.5766161 C19.4476073,19.0726851 19.1933971,19.4748284 18.6568996,19.4748284 L0.640505826,19.4748284 C0.092748094,19.4748284 -0.15156708,19.0753209 0.0977558747,18.5766161 L8.75139389,1.26729609 Z" id="Rectangle-4" fill="#F26969"></path>
<g id="Group-2" transform="translate(8.000000, 3.000000)" font-size="14" font-family="Lato-Bold, Lato" fill="#FFFFFF" font-weight="bold">
<text id="!">
<tspan x="0" y="14">!</tspan>
</text>
</g>
</g>
</g>
</g>
</g>
</svg>`;

export let warningIcon: string = `<svg width="21px" height="21px" viewBox="0 0 21 21" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 41.2 (35397) - http://www.bohemiancoding.com/sketch -->
<title>Group 2</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Alert" transform="translate(-18.000000, -20.000000)">
<g id="Group-4">
<g id="Group-2" transform="translate(18.000000, 20.000000)">
<circle id="Oval-5" fill="#F2BE2C" cx="10.5" cy="10.5" r="10.5"></circle>
<text id="!" font-family="Lato-Bold, Lato" font-size="14" font-weight="bold" fill="#FFFFFF">
<tspan x="8" y="16">!</tspan>
</text>
</g>
</g>
</g>
</g>
</svg>`;

export let notificationIcon: string = `
<svg width="22px" height="22px" viewBox="0 0 38 38" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.3.3 (12081) - http://www.bohemiancoding.com/sketch -->
<title>CL Mark</title>
<desc>Created with Sketch.</desc>
<g id="Update-6" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage" >
<g id="Line-Chart-(v4)" sketch:type="MSArtboardGroup" transform="translate(-20.000000, -29.000000)">
<g id="Header" sketch:type="MSLayerGroup" transform="translate(-15.000000, -47.000000)">
<g id="CL-Mark" transform="translate(35.000000, 76.000000)">
<g id="Group-3">
<g id="Clip-2"></g>
<path d="M23.0622,10.88928 C21.72574,11.2024 20.3281,11.36466 18.89664,11.36466 C17.46518,11.36466 16.06754,11.2024 14.72538,10.88928 C15.84372,9.11696 17.25846,7.53996 18.89664,6.24302 C20.5352,7.54566 21.94386,9.11696 23.0622,10.88928 L23.0622,10.88928 Z M35.66034,0.68134 C33.97998,0.23294 32.2088,0 30.3867,0 C26.14058,0 22.18972,1.27718 18.89132,3.47396 C15.599,1.27718 11.64814,0 7.39632,0 C5.57384,0 3.80266,0.23294 2.1223,0.68134 C1.41322,0.86108 0.72504,1.08832 0.05244,1.34292 C0.00874,1.35926 -0.01216,1.41094 0.00722,1.4535 C0.30134,2.0919 0.62928,2.71054 0.98192,3.30942 C1.0013,3.34248 1.04158,3.35692 1.07768,3.344 C1.77878,3.09244 2.49622,2.87888 3.22962,2.70788 C4.56912,2.39552 5.96562,2.23668 7.39632,2.23668 C10.90448,2.23668 14.1854,3.2186 16.9898,4.91036 C15.21292,6.41478 13.69178,8.21408 12.50504,10.2296 C12.27248,10.6153 12.06234,11.00708 11.8579,11.40456 C11.72186,11.67132 11.59114,11.94378 11.4608,12.22764 C11.27346,12.65324 11.09182,13.07922 10.9326,13.51622 C10.09242,15.77 9.63262,18.21074 9.63262,20.74838 C9.63262,26.62356 12.09084,31.9371 16.0303,35.71772 C16.33696,36.01868 16.65502,36.30254 16.9898,36.5807 C17.25086,36.80756 17.51192,37.0177 17.78438,37.22214 C18.12752,37.4946 18.48662,37.74578 18.8461,37.98632 C18.87346,38.00494 18.90956,38.00456 18.93692,37.98594 C19.29602,37.74008 19.64942,37.4889 19.99256,37.22214 C20.27072,37.0177 20.53216,36.80756 20.79322,36.5807 C21.1223,36.30254 21.45176,36.01298 21.75804,35.71772 C25.69218,31.9371 28.15002,26.61786 28.15002,20.74838 C28.15002,18.21074 27.69022,15.7757 26.85004,13.52192 C26.6855,13.08492 26.50956,12.65324 26.31652,12.22764 C26.19188,11.94378 26.06116,11.67132 25.93044,11.40456 C25.72068,11.00708 25.51054,10.6153 25.2776,10.2296 C24.08554,8.21408 22.5701,6.41478 20.79322,4.91036 C23.59762,3.2186 26.87854,2.23668 30.3867,2.23668 C31.8174,2.23668 33.2139,2.39552 34.5534,2.70788 C35.28642,2.87888 36.00918,3.09244 36.70534,3.34362 C36.74144,3.35692 36.78172,3.34248 36.8011,3.30942 C37.15336,2.71054 37.47636,2.0919 37.77466,1.45388 C37.7948,1.41094 37.7739,1.35926 37.72944,1.34254 C37.05228,1.08832 36.3641,0.86108 35.66034,0.68134 L35.66034,0.68134 Z" id="Fill-1" fill="#152849" sketch:type="MSShapeGroup"></path>
</g>
<path d="M25.91372,20.7499 C25.91372,25.65912 23.99396,30.12526 20.86086,33.4419 C20.31024,31.68174 20.0108,29.81404 20.0108,27.88212 C20.0108,22.97328 21.93056,18.49916 25.06366,15.1905 C25.61428,16.94648 25.91372,18.81418 25.91372,20.7499" id="Fill-6" fill="#348540" sketch:type="MSShapeGroup"></path>
<path d="M17.77184,27.88212 C17.77184,29.81404 17.4762,31.68174 16.9214,33.4419 C13.7883,30.12526 11.86854,25.65912 11.86854,20.7499 C11.86854,18.81418 12.17216,16.94648 12.72696,15.1905 C15.86006,18.49916 17.77184,22.97328 17.77184,27.88212" id="Fill-7" fill="#7DBC42" sketch:type="MSShapeGroup"></path>
</g>
</g>
</g>
</g>
</svg>`;
50 changes: 50 additions & 0 deletions pkg/ui/src/containers/alerts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as React from "react";
import _ from "lodash";
import { Dispatch, bindActionCreators } from "redux";
import { connect } from "react-redux";

import { AlertBox } from "../components/alertBox";
import { AdminUIState } from "../redux/state";
import { Alert, allAlertsSelector } from "../redux/alerts";

interface AlertSectionProps {
/**
* List of alerts to display in the alert secion.
*/
alerts: Alert[];
/**
* Raw dispatch method for the current store, will be used to dispatch
* alert dismissal callbacks.
*/
dispatch: Dispatch<AdminUIState>;
}

class AlertSection extends React.Component<AlertSectionProps, {}> {
render() {
let { alerts, dispatch } = this.props;
return <div>
{
_.map(alerts, (a, i) => {
const { dismiss, ...alertProps } = a;
const boundDismiss = bindActionCreators(() => a.dismiss, dispatch);
return <AlertBox key={i} dismiss={ boundDismiss } {...alertProps} />;
})
}
</div>;
}
}

const alertSectionConnected = connect(
(state: AdminUIState) => {
return {
alerts: allAlertsSelector(state),
};
},
(dispatch) => {
return {
dispatch: dispatch,
};
},
)(AlertSection);

export default alertSectionConnected;
4 changes: 0 additions & 4 deletions pkg/ui/src/containers/banner/bannerContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import * as React from "react";
import DisconnectedBanner from "./disconnectedBanner";
import HelpusBanner from "./helpusBanner";
import OutdatedBanner from "./outdatedBanner";

/**
* This is the outer component for all banners
Expand All @@ -11,8 +9,6 @@ export default class extends React.Component<{}, {}> {
// Note: The order the banners appear here dictates their precedence.
return <div id="banner">
<DisconnectedBanner />
<OutdatedBanner />
<HelpusBanner />
</div>;
}
}
93 changes: 0 additions & 93 deletions pkg/ui/src/containers/banner/helpusBanner.tsx

This file was deleted.

Loading

0 comments on commit 1f9a1cc

Please sign in to comment.