added widget layout styling

added basic system to render linear gauges (wip)
This commit is contained in:
Youen Toupin 2022-04-12 23:06:58 +02:00
parent 81c2d82e1d
commit 48fb012e54
10 changed files with 174 additions and 8 deletions

View File

@ -3,6 +3,10 @@ import m from 'mithril';
export abstract class Component {
abstract view(vnode: m.Vnode): m.Children;
constructor(vnode?: m.Vnode) {
}
oninit(vnode: m.Vnode) {}
oncreate(vnode: m.Vnode) {}

View File

@ -1,16 +1,20 @@
import m from 'mithril';
import { Component } from 'components/component'
import { Widget } from 'components/widgets/widget';
require("./clock.css");
export default class Clock extends Component {
export class Clock extends Widget {
constructor(vnode: any) {
super(vnode);
}
view(vnode: m.Vnode<{}, {}>): m.Children {
var now = new Date();
var days = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'];
var nextUpdateDelay = 61 - now.getSeconds();
setTimeout(() => m.redraw(), nextUpdateDelay * 1000);
return <div class="clock">
return <div class="widget clock">
<div class="date">
<p class="day">{days[now.getDay()]}</p>
<p class="date">{('0'+now.getDate()).slice(-2) + '/' + ('0'+now.getMonth()).slice(-2)}</p>

View File

@ -0,0 +1,32 @@
div.gauge-linear {
display: flex;
flex-direction: column;
}
div.gauge-linear p.value {
font-size: 2.3rem;
font-family: monospace;
}
div.gauge-linear span.unit {
font-size: 1.6rem;
font-family: initial;
}
rect.gauge-linear-bg {
fill: rgb(255,255,255);
stroke-width: 2;
stroke: rgb(0,0,0)
}
rect.gauge-linear-bar {
fill: rgb(230,230,230);
stroke-width: 1;
stroke: rgb(180,180,180)
}
rect.gauge-linear-bar.lit {
fill: rgb(180,180,180);
stroke-width: 1;
stroke: rgb(0,0,0)
}

View File

@ -0,0 +1,71 @@
import m from 'mithril';
import { Widget } from 'components/widgets/widget';
require('./gauge-linear.css');
export class GaugeLinear extends Widget {
private bars: SVGRectElement[] = [];
constructor(vnode: any) {
super(vnode);
}
view(vnode: m.Vnode<{}, {}>): m.Children {
return <div class="widget gauge-linear" style={'flex: ' + this.widgetWidth}>
<p class="value">643<span class="unit">W</span></p>
<svg>
</svg>
</div>;
}
createSvg(svgElement: SVGElement) {
let w = Math.round(svgElement.clientWidth);
let h = Math.round(svgElement.clientHeight);
svgElement.setAttribute('viewBox', "0 0 "+w+" "+h);
let bg = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
bg.setAttribute('width', w.toString());
bg.setAttribute('height', h.toString());
bg.classList.add('gauge-linear-bg');
svgElement.append(bg);
let barHeight = 15;
const barGap = barHeight * 0.2;
let numBars = Math.round(h / (barHeight + barGap));
let bh = (h - (numBars+1)*barGap) / numBars;
barHeight = Math.round(bh);
for(let barIdx = 0; barIdx < numBars; ++barIdx) {
let bar = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
bar.setAttribute('width', (w - barGap * 2).toString());
bar.setAttribute('height', barHeight.toString());
bar.classList.add('gauge-linear-bar');
bar.classList.toggle('lit', false);
bar.setAttribute('x', barGap.toString());
bar.setAttribute('y', (h - barIdx * (bh+barGap) - barGap - barHeight).toString());
svgElement.append(bar);
this.bars.push(bar);
}
}
renderGaugeRatio(ratio: number) {
let numBars = this.bars.length;
let litBars = Math.round(ratio * numBars);
console.log(litBars);
for(let barIdx = 0; barIdx < numBars; ++barIdx) {
let bar = this.bars[barIdx];
bar.classList.toggle('lit', barIdx < litBars);
}
}
oncreate(vnode: any) {
let svgElement: SVGElement = vnode.dom.querySelector('svg');
this.createSvg(svgElement);
this.renderGaugeRatio(0.2);
}
}

View File

@ -0,0 +1,3 @@
div.widget svg {
flex: 1;
}

View File

@ -0,0 +1,19 @@
import m from 'mithril';
import { Component } from 'components/component'
require('./widget.css');
interface WidgetAttrs
{
widgetWidth: number;
}
export abstract class Widget extends Component {
public widgetWidth = 1.0;
constructor(vnode?: m.Vnode<WidgetAttrs>) {
super(vnode);
if(vnode.attrs.widgetWidth !== undefined)
this.widgetWidth = vnode.attrs.widgetWidth;
}
};

View File

@ -1,3 +1,13 @@
/*html body {
font-size: 3rem;
}*/
html, html > body {
height: 100%;
width: 100%;
}
html > body {
display: flex;
flex-direction: column;
}
html > body > section {
flex: 1;
}

View File

@ -0,0 +1,13 @@
div.dashboard-page {
width: 100%;
height: 100%;
}
div.widgets-row {
display: flex;
flex-direction: row;
}
div.widget {
flex: 1;
}

View File

@ -1,7 +1,11 @@
import m from 'mithril';
import { Page } from 'components/page';
import { MonitorApi, Status } from 'monitor-api';
import Clock from 'components/widgets/clock';
import { Clock } from 'components/widgets/clock';
import { GaugeLinear } from 'components/widgets/gauge-linear';
require('./dashboard-page.css');
export class DashboardPage extends Page {
status: Status = null;
@ -29,7 +33,12 @@ export class DashboardPage extends Page {
view() {
return this.status
? <div class="dashboard-page">
<Clock/>
<div class="widgets-row">
<Clock/>
</div>
<div class="widgets-row" style="height: 40%">
<GaugeLinear widgetWidth={0.2} />
</div>
</div>
: <p>Chargement...</p>;
}

View File

@ -41,6 +41,7 @@ module.exports = {
}),
new PurgecssPlugin({
paths: glob.sync('./src/**/*', { nodir: true }),
safelist: ['html', 'body']
})
]
};