Commit 51e0b5ca authored by StreatCodes's avatar StreatCodes
Browse files

Convert all prop params to object param things,

initial work adding statics
parent 3d4eb706
......@@ -13,7 +13,7 @@ function sortService(a, b) {
return a.hostName.toLowerCase() > b.hostName.toLowerCase() ? 1 : 0;
}
function IcingaCheckList(props) {
function IcingaCheckList({check, updateCheckID}) {
const [hosts, setHosts] = useState(null);
const [services, setServices] = useState(null);
......@@ -49,7 +49,7 @@ function IcingaCheckList(props) {
options.push(<option value={service.id}>{service.hostName} - {service.displayName}</option>)
}
return <select value={props.check.checkID} onInput={e => props.updateCheckID(e.currentTarget.value)}>
return <select value={check.checkID} onInput={e => updateCheckID(e.currentTarget.value)}>
{options}
</select>
}
......
......@@ -37,6 +37,25 @@ const dashboardReducer = (state, action) => {
const newState = {...state};
newState.checks[action.checkIndex] = action.check;
return newState;
case 'addStatic':
console.log('Adding new static')
const newStatic = {
type: 'text',
title: 'New text',
rect:{ x: 0, y: 0, w: 15, h: 15},
options: {
fontSize: 40
}
};
return {
...state,
statics: state.statics.concat(newCheck)
};
case 'updateStatic':
console.log('Updating static')
const ns = {...state};
ns.statics[action.staticIndex] = action.static;
return ns;
default: throw new Error(`Unexpected action`);
}
};
......@@ -232,7 +251,7 @@ function DashboardView({dashboard, dashboardDispatch, selectedCheckId, slug}) {
}
//Settings view for the sidebar
function SidePanelSettings(props) {
function SidePanelSettings({dashboardDispatch, dashboard}) {
const handleBackgroundImg = async e => {
try {
const data = await fetch('/upload', {
......@@ -243,7 +262,7 @@ function SidePanelSettings(props) {
body: e.target.files[0]
}).then(res => res.json());
props.dashboardDispatch({
dashboardDispatch({
type: 'setBackground',
background: '/' + data.url
});
......@@ -256,8 +275,8 @@ function SidePanelSettings(props) {
return <Fragment>
<label for="title">Title</label>
<input type="text" id="title" placeholder="Network Overview" value={props.dashboard.title}
onInput={e => props.dashboardDispatch({type: 'setTitle', title: e.currentTarget.value})} />
<input type="text" id="title" placeholder="Network Overview" value={dashboard.title}
onInput={e => dashboardDispatch({type: 'setTitle', title: e.currentTarget.value})} />
<label for="background-image">Background Image</label>
<input id="background-image" type="file" placeholder="Upload a background image"
......
......@@ -26,12 +26,12 @@ const states = {
const checkType = (checkID) => checkID.includes('!') ? 'service' : 'host';
//The rendered view (in the actual dashboard) of the Card Element
export function CardElement(props) {
export function CardElement({check}) {
const [checkState, setCheckState] = useState(null);
//Handle state update
const updateState = () => {
const id = props.check.checkID;
const id = check.checkID;
const t = checkType(id);
fetch(`/icinga/${t}s/${encodeURIComponent(id)}`)
......@@ -44,32 +44,32 @@ export function CardElement(props) {
//Setup check refresher
useEffect(() => {
if(props.check.checkID !== null) {
if(check.checkID !== null) {
updateState();
const intervalID = window.setInterval(updateState, 30*1000)
return () => window.clearInterval(intervalID);
}
}, [props.check.checkID]);
}, [check.checkID]);
return <div class={"check-content card " + checkState}>
<p style={`font-size: ${props.check.options.nameFontSize}px`}>{props.check.title}</p>
<div class="check-state" style={`font-size: ${props.check.options.statusFontSize}px`}>
<p style={`font-size: ${check.options.nameFontSize}px`}>{check.title}</p>
<div class="check-state" style={`font-size: ${check.options.statusFontSize}px`}>
{checkState === null ? 'Unconfigured' : checkState}
</div>
</div>
}
//Card options, displayed in the sidebar
export function CardOptionFields(props) {
export function CardOptionFields({check, updateOptions}) {
return <div class="card-options">
<label for="name-font-size">Name Font Size</label>
<input id="name-font-size" name="name-font-size" type="number" min="0"
value={props.check.options.nameFontSize}
onInput={e => props.updateOptions({nameFontSize: e.currentTarget.value})}/>
value={check.options.nameFontSize}
onInput={e => updateOptions({nameFontSize: e.currentTarget.value})}/>
<label for="status-font-size">Status Font Size</label>
<input id="status-font-size" name="status-font-size" type="number" min="0"
value={props.check.options.statusFontSize}
onInput={e => props.updateOptions({statusFontSize: e.currentTarget.value})}/>
value={check.options.statusFontSize}
onInput={e => updateOptions({statusFontSize: e.currentTarget.value})}/>
</div>
}
\ No newline at end of file
......@@ -30,7 +30,7 @@ const titleToSlug = (title) => {
return result;
}
function CreateDashboardModal(props) {
function CreateDashboardModal({hide}) {
const [title, setTitle] = useState('');
const createDashboard = async e => {
......@@ -40,7 +40,8 @@ function CreateDashboardModal(props) {
const newDashboard = {
title: title,
background: null,
checks: []
checks: [],
statics: []
}
const data = await fetch(`/dashboard`, {
......@@ -56,7 +57,7 @@ function CreateDashboardModal(props) {
}
}
return <div class="modal-wrap" onMouseDown={props.hide}>
return <div class="modal-wrap" onMouseDown={hide}>
<div class="modal" onMouseDown={e => e.stopPropagation()}>
<h3>Create Dashboard</h3>
......@@ -74,22 +75,22 @@ function CreateDashboardModal(props) {
</div>
}
function DashboardList(props) {
function DashboardList({dashboards, loadDashboards, filter}) {
const deleteDashboard = (slug) => {
fetch(`/dashboard/${slug}`, {
method: 'DELETE'
}).then(props.loadDashboards)
}).then(loadDashboards)
}
if(props.dashboards === null) {
if(dashboards === null) {
return <div class="subtle loading">Loading Dashboards</div>
}
const filteredDashboards = props.dashboards.filter((dashboard) => {
if(props.filter === '') {
const filteredDashboards = dashboards.filter((dashboard) => {
if(filter === '') {
return true;
} else {
return dashboard.title.toLowerCase().includes(props.filter.toLowerCase());
return dashboard.title.toLowerCase().includes(filter.toLowerCase());
}
})
......
import { h, Fragment } from 'preact';
import { useState, useEffect } from 'preact/hooks';
import { routeParam, removeParam } from './util';
import { route } from 'preact-router';
function StaticListPanel({statics, addStatic}) {
if(statics.length < 1) {
return <div class="subtle" style="flex-direction: column; font-size: 16px;">
<div>No static content added.</div>
<a onClick={addStatic}>Create static content</a>
</div>
}
const staticList = statics.map((static, index) => (
<div class="static-item" onClick={ e => routeParam('selectedStaticId', index.toString()) }>
<div>{static.title}</div>
</div>
));
return <div class="static-list">
{staticList}
</div>
}
// export function CheckSettings({selectedCheck, updateCheck}) {
// if(selectedCheck === null) {
// return null;
// }
// const updateCheckOptions = (options) => {
// const newOptions = Object.assign(selectedCheck.options, options)
// updateCheck({...selectedCheck, options: newOptions})
// }
// const checkTypeOptions = {
// 'card': <CardOptionFields updateOptions={updateCheckOptions} check={selectedCheck} />,
// 'svg': <div>svg options</div>,
// 'image': <div>image options</div>
// }
// return <div class="editor settings-overlay">
// <div class="options">
// <div class="left">
// <svg class="feather" onClick={e => removeParam('selectedCheckId')}>
// <use xlinkHref={`/res/svgs/feather-sprite.svg#chevron-left`}/>
// </svg>
// <h3 class="no-margin">{selectedCheck.title}</h3>
// </div>
// <div class="asd">
// <label for="name">Name</label>
// <input id="name" type="text" placeholder="Cool check" value={selectedCheck.title}
// onInput={e => updateCheck({...selectedCheck, title: e.currentTarget.value})} />
// <label>Visual Type</label>
// <select name="item-type" value={selectedCheck.type}
// onInput={e => updateCheck({...selectedCheck, type: e.currentTarget.value})}>
// <option value="card">Card</option>
// <option value="svg">SVG</option>
// <option value="image">Image</option>
// </select>
// <label>Icinga Host or Service</label>
// <IcingaCheckList check={selectedCheck}
// updateCheckID={checkID => updateCheck({...selectedCheck, checkID: checkID})} />
// {checkTypeOptions[selectedCheck.type]}
// </div>
// </div>
// </div>
// }
//Statics view for the sidebar
export function SidePanelStatics({dashboard, dashboardDispatch}) {
const addStatic = e => {
const newId = dashboard.statics.length;
dashboardDispatch({type: 'addStatic'});
routeParam('selectedStaticId', newId);
}
return <Fragment>
<div class="lefty-righty" style="margin-bottom: 20px;">
<h3>Static Content</h3>
<button class="small" onClick={addStatic}>New</button>
</div>
<StaticListPanel statics={dashboard.statics} addStatic={addStatic} />
</Fragment>
}
\ No newline at end of file
......@@ -5,14 +5,14 @@ import { useState, useEffect } from 'preact/hooks';
import { CardElement } from './elements/card';
//Read only page
export function Viewer(props) {
export function Viewer({slug}) {
const [dashboard, setDashboard] = useState(null);
useEffect(() => {
fetch(`/dashboard/${props.slug}`)
fetch(`/dashboard/${slug}`)
.then(res => res.json())
.then(res => setDashboard(res));
}, [props.slug]);
}, [slug]);
if(dashboard === null) {
return <div class="loading center subtle">Loading dashboard</div>
......
......@@ -407,6 +407,7 @@ div.editor {
min-width: 380px;
display: flex;
justify-content: space-between;
overflow-y: auto;
}
.editor .options {
......
Markdown is supported
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