Commit 2878efac authored by StreatCodes's avatar StreatCodes
Browse files

Add ImageCheck

Refactor code
Improve naming consistency
Initial work for SVG check
parent 77a5b318
import { h, Fragment } from 'preact'; import { h, Fragment } from 'preact';
import { useState, useEffect } from 'preact/hooks'; import { useState, useEffect } from 'preact/hooks';
import { CardOptionFields } from './elements/card'; import { CheckCardOptions } from './elements/card';
import { CheckImageOptions } from './elements/image';
import { routeParam, removeParam } from './util'; import { routeParam, removeParam } from './util';
import { route } from 'preact-router'; import { route } from 'preact-router';
import * as meerkat from './meerkat'; import * as meerkat from './meerkat';
...@@ -80,11 +81,10 @@ export function CheckSettings({selectedCheck, updateCheck}) { ...@@ -80,11 +81,10 @@ export function CheckSettings({selectedCheck, updateCheck}) {
updateCheck({...selectedCheck, options: newOptions}) updateCheck({...selectedCheck, options: newOptions})
} }
const checkTypeOptions = { let checkOptions = null;
'card': <CardOptionFields updateOptions={updateCheckOptions} check={selectedCheck} />, if(selectedCheck.type === 'card') { checkOptions = <CheckCardOptions updateOptions={updateCheckOptions} check={selectedCheck} /> }
'svg': <div>svg options</div>, // if(selectedCheck.type === 'svg') { checkOptions = <CheckSVGOptions updateOptions={updateCheckOptions} options={check.options}/> }
'image': <div>image options</div> if(selectedCheck.type === 'image') { checkOptions = <CheckImageOptions updateOptions={updateCheckOptions} options={selectedCheck}/> }
}
return <div class="editor settings-overlay"> return <div class="editor settings-overlay">
<div class="options"> <div class="options">
...@@ -111,7 +111,7 @@ export function CheckSettings({selectedCheck, updateCheck}) { ...@@ -111,7 +111,7 @@ export function CheckSettings({selectedCheck, updateCheck}) {
<IcingaCheckList check={selectedCheck} <IcingaCheckList check={selectedCheck}
updateCheckID={checkID => updateCheck({...selectedCheck, checkID: checkID})} /> updateCheckID={checkID => updateCheck({...selectedCheck, checkID: checkID})} />
{checkTypeOptions[selectedCheck.type]} {checkOptions}
</div> </div>
</div> </div>
</div> </div>
......
...@@ -5,7 +5,8 @@ import { useEffect, useReducer } from 'preact/hooks'; ...@@ -5,7 +5,8 @@ import { useEffect, useReducer } from 'preact/hooks';
import * as meerkat from './meerkat' import * as meerkat from './meerkat'
import { SidePanelChecks, CheckSettings } from './check-settings'; import { SidePanelChecks, CheckSettings } from './check-settings';
import { SidePanelStatics, StaticSettings } from './static-settings'; import { SidePanelStatics, StaticSettings } from './static-settings';
import { CardElement } from './elements/card'; import { CheckCard } from './elements/card';
import { CheckImage } from './elements/image';
import { removeParam } from './util'; import { removeParam } from './util';
import { StaticText } from './statics/text'; import { StaticText } from './statics/text';
import { StaticSVG } from './statics/svg'; import { StaticSVG } from './statics/svg';
...@@ -247,13 +248,10 @@ function DashboardChecks({dashboardDispatch, selectedCheckId, checks}) { ...@@ -247,13 +248,10 @@ function DashboardChecks({dashboardDispatch, selectedCheckId, checks}) {
}); });
} }
let element = <CardElement check={check} /> let element = null;
if(check.type === 'svg') { if(check.type === 'card') { element = <CheckCard check={check} /> }
element = <div> todo </div> if(check.type === 'svg') { element = <CheckSVG check={check}/> }
} if(check.type === 'image') { element = <CheckImage check={check}/> }
if(check.type === 'image') {
element = <div> todo </div>
}
return <TransformableElement rect={check.rect} updateRect={updateRect} return <TransformableElement rect={check.rect} updateRect={updateRect}
glow={selectedCheckId === index}> glow={selectedCheckId === index}>
......
...@@ -2,44 +2,18 @@ import { h } from 'preact'; ...@@ -2,44 +2,18 @@ import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks'; import { useState, useEffect } from 'preact/hooks';
import * as meerkat from '../meerkat'; import * as meerkat from '../meerkat';
import { icingaResultCodeToCheckState, icingaCheckTypeFromId } from '../util'
// Value Host State Service State
// 0 Up OK
// 1 Up Warning
// 2 Down Critical
// 3 Down Unknown
//icinga state matrix: states[type][state]
const states = {
service: {
0: 'ok',
1: 'warning',
2: 'critical',
3: 'unknown'
},
host: {
0: 'up',
1: 'up',
2: 'down',
3: 'down'
}
}
const checkType = (checkID) => checkID.includes('!') ? 'service' : 'host';
//The rendered view (in the actual dashboard) of the Card Element //The rendered view (in the actual dashboard) of the Card Element
export function CardElement({check}) { export function CheckCard({check}) {
const [checkState, setCheckState] = useState(null); const [checkState, setCheckState] = useState(null);
//Handle state update //Handle state update
const updateState = () => { const updateState = async () => {
const id = check.checkID; const checkType = icingaCheckTypeFromId(check.checkID);
const t = checkType(id); const res = await meerkat.getIcingaCheckState(check.checkID, checkType);
const state = icingaResultCodeToCheckState(checkType, res.state);
meerkat.getIcingaCheckState(id, t).then(res => { setCheckState(state);
const state = states[t][res[0].state];
setCheckState(state);
});
} }
//Setup check refresher //Setup check refresher
...@@ -60,7 +34,7 @@ export function CardElement({check}) { ...@@ -60,7 +34,7 @@ export function CardElement({check}) {
} }
//Card options, displayed in the sidebar //Card options, displayed in the sidebar
export function CardOptionFields({check, updateOptions}) { export function CheckCardOptions({check, updateOptions}) {
return <div class="card-options"> return <div class="card-options">
<label for="name-font-size">Name Font Size</label> <label for="name-font-size">Name Font Size</label>
<input id="name-font-size" name="name-font-size" type="number" min="0" <input id="name-font-size" name="name-font-size" type="number" min="0"
......
import { h, Fragment } from 'preact';
import { useState, useEffect } from 'preact/hooks';
import * as meerkat from '../meerkat';
import { icingaResultCodeToCheckState, icingaCheckTypeFromId } from '../util'
export function CheckImageOptions({options, updateOptions}) {
const handleImageUpload = async (fieldName, files) => {
const res = await meerkat.uploadFile(files[0]);
const opts = {}
opts[fieldName] = res.url
updateOptions(opts);
}
return <Fragment>
<label for="ok-image">OK State Image</label>
<input id="ok-image" name="ok-image" type="file"
accept="image/*" onInput={e => handleImageUpload('okImage', e.target.files)}/>
<label for="warning-image">Warning State Image</label>
<input id="warning-image" name="warning-image" type="file"
accept="image/*" onInput={e => handleImageUpload('warningImage', e.target.files)}/>
<label for="unknown-image">Unknown State Image</label>
<input id="unknown-image" name="unknown-image" type="file"
accept="image/*" onInput={e => handleImageUpload('unknownImage', e.target.files)}/>
<label for="critical-image">Critical State Image</label>
<input id="critical-image" name="critical-image" type="file"
accept="image/*" onInput={e => handleImageUpload('criticalImage', e.target.files)}/>
</Fragment>
}
//The rendered view (in the actual dashboard) of the Check Image
export function CheckImage({check}) {
const [checkState, setCheckState] = useState(null);
//Handle state update
const updateState = async () => {
const checkType = icingaCheckTypeFromId(check.checkID);
const res = await meerkat.getIcingaCheckState(check.checkID, checkType);
const state = icingaResultCodeToCheckState(checkType, res.state);
setCheckState(state);
}
//Setup check refresher
useEffect(() => {
if(check.checkID !== null) {
updateState();
const intervalID = window.setInterval(updateState, 30*1000)
return () => window.clearInterval(intervalID);
}
}, [check.checkID]);
let source = null;
if(checkState === 'ok' || checkState === 'up') {source = check.options.okImage}
if(checkState === 'warning') {source = check.options.warningImage}
if(checkState === 'unknown') {source = check.options.unknownImage}
if(checkState === 'critical' || checkState === 'down') {source = check.options.criticalImage}
return <div class="check-content image">
<img src={source} />
</div>
}
\ No newline at end of file
import { h, Fragment } from 'preact';
import { useState, useEffect } from 'preact/hooks';
import * as meerkat from '../meerkat';
import { icingaResultCodeToCheckState, icingaCheckTypeFromId } from '../util'
export function CheckSVGOptions({options, updateOptions}) {
return <div>todo</div>
}
//The rendered view (in the actual dashboard) of the Check SVG
export function CheckSVG({check}) {
const [checkState, setCheckState] = useState(null);
//Handle state update
const updateState = async () => {
const checkType = icingaCheckTypeFromId(check.checkID);
const res = await meerkat.getIcingaCheckState(check.checkID, checkType);
const state = icingaResultCodeToCheckState(checkType, res.state);
setCheckState(state);
}
//Setup check refresher
useEffect(() => {
if(check.checkID !== null) {
updateState();
const intervalID = window.setInterval(updateState, 30*1000)
return () => window.clearInterval(intervalID);
}
}, [check.checkID]);
// let source = null;
// if(checkState === 'ok' || checkState === 'up') {source = check.options.okImage}
// if(checkState === 'warning') {source = check.options.warningImage}
// if(checkState === 'unknown') {source = check.options.unknownImage}
// if(checkState === 'critical' || checkState === 'down') {source = check.options.criticalImage}
return <div class="check-content svg">TODO</div>
}
\ No newline at end of file
...@@ -12,7 +12,11 @@ export async function getIcingaServices() { ...@@ -12,7 +12,11 @@ export async function getIcingaServices() {
export async function getIcingaCheckState(checkId, checkType) { export async function getIcingaCheckState(checkId, checkType) {
const res = await fetch(`/icinga/${checkType}s/${encodeURIComponent(checkId)}`); const res = await fetch(`/icinga/${checkType}s/${encodeURIComponent(checkId)}`);
return res.json(); const data = await res.json();
if(data.length < 1) {
throw new Error('Expected atleast one result in icinga check response');
}
return data[0];
} }
export async function getAllDashboards() { export async function getAllDashboards() {
......
...@@ -20,4 +20,32 @@ export function removeParam(name) { ...@@ -20,4 +20,32 @@ export function removeParam(name) {
} else { } else {
route(`${window.location.pathname}?${params}`); route(`${window.location.pathname}?${params}`);
} }
}
export function icingaCheckTypeFromId(checkId) {
if(checkId.includes('!')) {
return 'service';
} else {
return 'host';
}
}
export function icingaResultCodeToCheckState(checkType, resultCode) {
if(checkType === 'service') {
switch(resultCode){
case 0: return 'ok';
case 1: return 'warning';
case 2: return 'critical';
case 3: return 'unknown';
}
} else if(checkType === 'host') {
switch(resultCode){
case 0: return 'up';
case 1: return 'up';
case 2: return 'down';
case 3: return 'down';
}
}
return 'invalid'
} }
\ No newline at end of file
...@@ -3,7 +3,9 @@ import { route } from 'preact-router'; ...@@ -3,7 +3,9 @@ import { route } from 'preact-router';
import { useState, useEffect } from 'preact/hooks'; import { useState, useEffect } from 'preact/hooks';
import * as meerkat from './meerkat'; import * as meerkat from './meerkat';
import { CardElement } from './elements/card'; import { CheckCard } from './elements/card';
import { CheckImage } from './elements/image';
import { CheckSVG } from './elements/svg';
import { StaticText } from './statics/text'; import { StaticText } from './statics/text';
import { StaticSVG } from './statics/svg'; import { StaticSVG } from './statics/svg';
...@@ -27,8 +29,13 @@ export function Viewer({slug}) { ...@@ -27,8 +29,13 @@ export function Viewer({slug}) {
const width = `${check.rect.w}%`; const width = `${check.rect.w}%`;
const height = `${check.rect.h}%`; const height = `${check.rect.h}%`;
let element = null;
if(check.type === 'card') { element = <CheckCard check={check}/> }
if(check.type === 'svg') { element = <CheckSVG check={check}/> }
if(check.type === 'image') { element = <CheckImage check={check}/> }
return <div class="check" style={{left: left, top: top, width: width, height: height}}> return <div class="check" style={{left: left, top: top, width: width, height: height}}>
<CardElement check={check} /> {element}
</div> </div>
}); });
......
...@@ -490,6 +490,7 @@ div.side-bar-footer { ...@@ -490,6 +490,7 @@ div.side-bar-footer {
padding: 20px; padding: 20px;
background-color: var(--color-light-gray); background-color: var(--color-light-gray);
min-width: 380px; min-width: 380px;
border-top: solid 1px #aaa;
} }
/* DASHBOARD ELEMENTS */ /* DASHBOARD ELEMENTS */
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment