problems: refactor
This commit is contained in:
@@ -90,7 +90,7 @@ interface EventTagProps {
|
|||||||
onClick?: (tag: ZBXTag) => void;
|
onClick?: (tag: ZBXTag) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
class EventTag extends PureComponent<EventTagProps> {
|
export default class EventTag extends PureComponent<EventTagProps> {
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
if (this.props.onClick) {
|
if (this.props.onClick) {
|
||||||
this.props.onClick(this.props.tag);
|
this.props.onClick(this.props.tag);
|
||||||
@@ -113,5 +113,3 @@ class EventTag extends PureComponent<EventTagProps> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default EventTag;
|
|
||||||
|
|||||||
23
src/panel-triggers/components/Problems/AcknowledgesList.tsx
Normal file
23
src/panel-triggers/components/Problems/AcknowledgesList.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { ZBXAcknowledge } from 'panel-triggers/types';
|
||||||
|
|
||||||
|
interface AcknowledgesListProps {
|
||||||
|
acknowledges: ZBXAcknowledge[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AcknowledgesList(props: AcknowledgesListProps) {
|
||||||
|
const { acknowledges } = props;
|
||||||
|
return (
|
||||||
|
<div className="problem-ack-list">
|
||||||
|
<div className="problem-ack-col problem-ack-time">
|
||||||
|
{acknowledges.map(ack => <span key={ack.acknowledgeid} className="problem-ack-time">{ack.time}</span>)}
|
||||||
|
</div>
|
||||||
|
<div className="problem-ack-col problem-ack-user">
|
||||||
|
{acknowledges.map(ack => <span key={ack.acknowledgeid} className="problem-ack-user">{ack.user}</span>)}
|
||||||
|
</div>
|
||||||
|
<div className="problem-ack-col problem-ack-message">
|
||||||
|
{acknowledges.map(ack => <span key={ack.acknowledgeid} className="problem-ack-message">{ack.message}</span>)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import * as utils from '../../datasource-zabbix/utils';
|
import * as utils from '../../../datasource-zabbix/utils';
|
||||||
import { ZBXTrigger, ZBXItem, ZBXAcknowledge, ZBXHost, ZBXGroup, ZBXEvent, GFTimeRange, RTRow, ZBXTag } from '../types';
|
import { ZBXTrigger, ZBXItem, ZBXAcknowledge, ZBXHost, ZBXGroup, ZBXEvent, GFTimeRange, RTRow, ZBXTag } from '../../types';
|
||||||
import { Modal, AckProblemData } from './Modal';
|
import { Modal, AckProblemData } from '../Modal';
|
||||||
import EventTag from './EventTag';
|
import EventTag from '../EventTag';
|
||||||
import Tooltip from './Tooltip/Tooltip';
|
import Tooltip from '../Tooltip/Tooltip';
|
||||||
|
import ProblemStatusBar from './ProblemStatusBar';
|
||||||
|
import AcknowledgesList from './AcknowledgesList';
|
||||||
import ProblemTimeline from './ProblemTimeline';
|
import ProblemTimeline from './ProblemTimeline';
|
||||||
import FAIcon from './FAIcon';
|
import FAIcon from '../FAIcon';
|
||||||
|
|
||||||
interface ProblemDetailsProps extends RTRow<ZBXTrigger> {
|
interface ProblemDetailsProps extends RTRow<ZBXTrigger> {
|
||||||
rootWidth: number;
|
rootWidth: number;
|
||||||
@@ -192,27 +194,6 @@ class ProblemItems extends PureComponent<ProblemItemsProps> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AcknowledgesListProps {
|
|
||||||
acknowledges: ZBXAcknowledge[];
|
|
||||||
}
|
|
||||||
|
|
||||||
function AcknowledgesList(props: AcknowledgesListProps) {
|
|
||||||
const { acknowledges } = props;
|
|
||||||
return (
|
|
||||||
<div className="problem-ack-list">
|
|
||||||
<div className="problem-ack-col problem-ack-time">
|
|
||||||
{acknowledges.map(ack => <span key={ack.acknowledgeid} className="problem-ack-time">{ack.time}</span>)}
|
|
||||||
</div>
|
|
||||||
<div className="problem-ack-col problem-ack-user">
|
|
||||||
{acknowledges.map(ack => <span key={ack.acknowledgeid} className="problem-ack-user">{ack.user}</span>)}
|
|
||||||
</div>
|
|
||||||
<div className="problem-ack-col problem-ack-message">
|
|
||||||
{acknowledges.map(ack => <span key={ack.acknowledgeid} className="problem-ack-message">{ack.message}</span>)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ProblemGroupsProps {
|
interface ProblemGroupsProps {
|
||||||
groups: ZBXGroup[];
|
groups: ZBXGroup[];
|
||||||
className?: string;
|
className?: string;
|
||||||
@@ -245,61 +226,6 @@ class ProblemHosts extends PureComponent<ProblemHostsProps> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ProblemStatusBarProps {
|
|
||||||
problem: ZBXTrigger;
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ProblemStatusBar(props: ProblemStatusBarProps) {
|
|
||||||
const { problem, className } = props;
|
|
||||||
const multiEvent = problem.type === '1';
|
|
||||||
const link = problem.url && problem.url !== '';
|
|
||||||
const maintenance = problem.maintenance;
|
|
||||||
const manualClose = problem.manual_close === '1';
|
|
||||||
const error = problem.error && problem.error !== '';
|
|
||||||
const stateUnknown = problem.state === '1';
|
|
||||||
const closeByTag = problem.correlation_mode === '1';
|
|
||||||
const actions = problem.alerts && problem.alerts.length !== 0;
|
|
||||||
const actionMessage = problem.alerts ? problem.alerts[0].message : '';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={`problem-statusbar ${className || ''}`}>
|
|
||||||
<ProblemStatusBarItem icon="wrench" fired={maintenance} tooltip="Host maintenance" />
|
|
||||||
<ProblemStatusBarItem icon="globe" fired={link} link={link && problem.url} tooltip="External link" />
|
|
||||||
<ProblemStatusBarItem icon="bullhorn" fired={multiEvent} tooltip="Trigger generates multiple problem events" />
|
|
||||||
<ProblemStatusBarItem icon="tag" fired={closeByTag} tooltip={`OK event closes problems matched to tag: ${problem.correlation_tag}`} />
|
|
||||||
<ProblemStatusBarItem icon="circle-o-notch" fired={actions} tooltip={actionMessage} />
|
|
||||||
<ProblemStatusBarItem icon="question-circle" fired={stateUnknown} tooltip="Current trigger state is unknown" />
|
|
||||||
<ProblemStatusBarItem icon="warning" fired={error} tooltip={problem.error} />
|
|
||||||
<ProblemStatusBarItem icon="window-close-o" fired={manualClose} tooltip="Manual close problem" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ProblemStatusBarItemProps {
|
|
||||||
icon: string;
|
|
||||||
fired?: boolean;
|
|
||||||
link?: string;
|
|
||||||
tooltip?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ProblemStatusBarItem(props: ProblemStatusBarItemProps) {
|
|
||||||
const { fired, icon, link, tooltip } = props;
|
|
||||||
let item = (
|
|
||||||
<div className={`problem-statusbar-item ${fired ? 'fired' : 'muted'}`}>
|
|
||||||
<FAIcon icon={icon} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
if (tooltip && fired) {
|
|
||||||
item = (
|
|
||||||
<Tooltip placement="bottom" content={tooltip}>
|
|
||||||
{item}
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return link ? <a href={link} target="_blank">{item}</a> : item;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ProblemActionButtonProps {
|
interface ProblemActionButtonProps {
|
||||||
icon: string;
|
icon: string;
|
||||||
tooltip?: string;
|
tooltip?: string;
|
||||||
59
src/panel-triggers/components/Problems/ProblemStatusBar.tsx
Normal file
59
src/panel-triggers/components/Problems/ProblemStatusBar.tsx
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import FAIcon from '../FAIcon';
|
||||||
|
import Tooltip from '../Tooltip/Tooltip';
|
||||||
|
import { ZBXTrigger } from 'panel-triggers/types';
|
||||||
|
|
||||||
|
export interface ProblemStatusBarProps {
|
||||||
|
problem: ZBXTrigger;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ProblemStatusBar(props: ProblemStatusBarProps) {
|
||||||
|
const { problem, className } = props;
|
||||||
|
const multiEvent = problem.type === '1';
|
||||||
|
const link = problem.url && problem.url !== '';
|
||||||
|
const maintenance = problem.maintenance;
|
||||||
|
const manualClose = problem.manual_close === '1';
|
||||||
|
const error = problem.error && problem.error !== '';
|
||||||
|
const stateUnknown = problem.state === '1';
|
||||||
|
const closeByTag = problem.correlation_mode === '1';
|
||||||
|
const actions = problem.alerts && problem.alerts.length !== 0;
|
||||||
|
const actionMessage = problem.alerts ? problem.alerts[0].message : '';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`problem-statusbar ${className || ''}`}>
|
||||||
|
<ProblemStatusBarItem icon="wrench" fired={maintenance} tooltip="Host maintenance" />
|
||||||
|
<ProblemStatusBarItem icon="globe" fired={link} link={link && problem.url} tooltip="External link" />
|
||||||
|
<ProblemStatusBarItem icon="bullhorn" fired={multiEvent} tooltip="Trigger generates multiple problem events" />
|
||||||
|
<ProblemStatusBarItem icon="tag" fired={closeByTag} tooltip={`OK event closes problems matched to tag: ${problem.correlation_tag}`} />
|
||||||
|
<ProblemStatusBarItem icon="circle-o-notch" fired={actions} tooltip={actionMessage} />
|
||||||
|
<ProblemStatusBarItem icon="question-circle" fired={stateUnknown} tooltip="Current trigger state is unknown" />
|
||||||
|
<ProblemStatusBarItem icon="warning" fired={error} tooltip={problem.error} />
|
||||||
|
<ProblemStatusBarItem icon="window-close-o" fired={manualClose} tooltip="Manual close problem" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ProblemStatusBarItemProps {
|
||||||
|
icon: string;
|
||||||
|
fired?: boolean;
|
||||||
|
link?: string;
|
||||||
|
tooltip?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ProblemStatusBarItem(props: ProblemStatusBarItemProps) {
|
||||||
|
const { fired, icon, link, tooltip } = props;
|
||||||
|
let item = (
|
||||||
|
<div className={`problem-statusbar-item ${fired ? 'fired' : 'muted'}`}>
|
||||||
|
<FAIcon icon={icon} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
if (tooltip && fired) {
|
||||||
|
item = (
|
||||||
|
<Tooltip placement="bottom" content={tooltip}>
|
||||||
|
{item}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return link ? <a href={link} target="_blank">{item}</a> : item;
|
||||||
|
}
|
||||||
@@ -3,13 +3,13 @@ import ReactTable from 'react-table';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import * as utils from '../../datasource-zabbix/utils';
|
import * as utils from '../../../datasource-zabbix/utils';
|
||||||
import { isNewProblem } from '../utils';
|
import { isNewProblem } from '../../utils';
|
||||||
import { ProblemsPanelOptions, ZBXTrigger, ZBXEvent, GFTimeRange, RTCell, ZBXTag, TriggerSeverity, RTResized } from '../types';
|
import { ProblemsPanelOptions, ZBXTrigger, ZBXEvent, GFTimeRange, RTCell, ZBXTag, TriggerSeverity, RTResized } from '../../types';
|
||||||
import EventTag from './EventTag';
|
import EventTag from '../EventTag';
|
||||||
import ProblemDetails from './ProblemDetails';
|
import ProblemDetails from './ProblemDetails';
|
||||||
import { AckProblemData } from './Modal';
|
import { AckProblemData } from '../Modal';
|
||||||
import GFHeartIcon from './GFHeartIcon';
|
import GFHeartIcon from '../GFHeartIcon';
|
||||||
|
|
||||||
export interface ProblemListProps {
|
export interface ProblemListProps {
|
||||||
problems: ZBXTrigger[];
|
problems: ZBXTrigger[];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import {DEFAULT_TARGET} from './triggers_panel_ctrl';
|
import { getDefaultTarget } from './triggers_panel_ctrl';
|
||||||
|
|
||||||
// Actual schema version
|
// Actual schema version
|
||||||
export const CURRENT_SCHEMA_VERSION = 6;
|
export const CURRENT_SCHEMA_VERSION = 6;
|
||||||
@@ -34,7 +34,7 @@ export function migratePanelSchema(panel) {
|
|||||||
if (schemaVersion < 5) {
|
if (schemaVersion < 5) {
|
||||||
if (panel.targets && !_.isEmpty(panel.targets)) {
|
if (panel.targets && !_.isEmpty(panel.targets)) {
|
||||||
_.each(panel.targets, (target) => {
|
_.each(panel.targets, (target) => {
|
||||||
_.defaultsDeep(target, DEFAULT_TARGET);
|
_.defaultsDeep(target, getDefaultTarget());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { PanelCtrl } from 'grafana/app/plugins/sdk';
|
|||||||
import { triggerPanelOptionsTab } from './options_tab';
|
import { triggerPanelOptionsTab } from './options_tab';
|
||||||
import { triggerPanelTriggersTab } from './triggers_tab';
|
import { triggerPanelTriggersTab } from './triggers_tab';
|
||||||
import { migratePanelSchema, CURRENT_SCHEMA_VERSION } from './migrations';
|
import { migratePanelSchema, CURRENT_SCHEMA_VERSION } from './migrations';
|
||||||
import ProblemList from './components/Problems';
|
import ProblemList from './components/Problems/Problems';
|
||||||
import AlertList from './components/AlertList/AlertList';
|
import AlertList from './components/AlertList/AlertList';
|
||||||
|
|
||||||
const ZABBIX_DS_ID = 'alexanderzobnin-zabbix-datasource';
|
const ZABBIX_DS_ID = 'alexanderzobnin-zabbix-datasource';
|
||||||
@@ -23,6 +23,8 @@ export const DEFAULT_TARGET = {
|
|||||||
proxy: {filter: ""},
|
proxy: {filter: ""},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getDefaultTarget = () => DEFAULT_TARGET;
|
||||||
|
|
||||||
export const DEFAULT_SEVERITY = [
|
export const DEFAULT_SEVERITY = [
|
||||||
{ priority: 0, severity: 'Not classified', color: 'rgb(108, 108, 108)', show: true},
|
{ priority: 0, severity: 'Not classified', color: 'rgb(108, 108, 108)', show: true},
|
||||||
{ priority: 1, severity: 'Information', color: 'rgb(120, 158, 183)', show: true},
|
{ priority: 1, severity: 'Information', color: 'rgb(120, 158, 183)', show: true},
|
||||||
@@ -32,6 +34,8 @@ export const DEFAULT_SEVERITY = [
|
|||||||
{ priority: 5, severity: 'Disaster', color: 'rgb(215, 0, 0)', show: true},
|
{ priority: 5, severity: 'Disaster', color: 'rgb(215, 0, 0)', show: true},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const getDefaultSeverity = () => DEFAULT_SEVERITY;
|
||||||
|
|
||||||
const DEFAULT_TIME_FORMAT = "DD MMM YYYY HH:mm:ss";
|
const DEFAULT_TIME_FORMAT = "DD MMM YYYY HH:mm:ss";
|
||||||
|
|
||||||
export const PANEL_DEFAULTS = {
|
export const PANEL_DEFAULTS = {
|
||||||
@@ -67,7 +71,7 @@ export const PANEL_DEFAULTS = {
|
|||||||
lastChangeFormat: "",
|
lastChangeFormat: "",
|
||||||
resizedColumns: [],
|
resizedColumns: [],
|
||||||
// Triggers severity and colors
|
// Triggers severity and colors
|
||||||
triggerSeverity: DEFAULT_SEVERITY,
|
triggerSeverity: getDefaultSeverity(),
|
||||||
okEventColor: 'rgb(56, 189, 113)',
|
okEventColor: 'rgb(56, 189, 113)',
|
||||||
ackEventColor: 'rgb(56, 219, 156)',
|
ackEventColor: 'rgb(56, 219, 156)',
|
||||||
markAckEvents: false,
|
markAckEvents: false,
|
||||||
@@ -107,7 +111,7 @@ export class TriggerPanelCtrl extends PanelCtrl {
|
|||||||
this.panel.datasources.push(this.available_datasources[0]);
|
this.panel.datasources.push(this.available_datasources[0]);
|
||||||
}
|
}
|
||||||
if (this.isEmptyTargets()) {
|
if (this.isEmptyTargets()) {
|
||||||
this.panel.targets[this.panel.datasources[0]] = DEFAULT_TARGET;
|
this.panel.targets[this.panel.datasources[0]] = getDefaultTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initDatasources();
|
this.initDatasources();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import * as utils from '../datasource-zabbix/utils';
|
import * as utils from '../datasource-zabbix/utils';
|
||||||
import {DEFAULT_TARGET} from './triggers_panel_ctrl';
|
import { getDefaultTarget } from './triggers_panel_ctrl';
|
||||||
|
|
||||||
class TriggersTabCtrl {
|
class TriggersTabCtrl {
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ class TriggersTabCtrl {
|
|||||||
datasourcesChanged() {
|
datasourcesChanged() {
|
||||||
_.each(this.panel.datasources, (ds) => {
|
_.each(this.panel.datasources, (ds) => {
|
||||||
if (!this.panel.targets[ds]) {
|
if (!this.panel.targets[ds]) {
|
||||||
this.panel.targets[ds] = _.cloneDeep(DEFAULT_TARGET);
|
this.panel.targets[ds] = getDefaultTarget();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.parseTarget();
|
this.parseTarget();
|
||||||
|
|||||||
Reference in New Issue
Block a user