1
0
Fork 0

feat(webui/dashboard): init new dashboard

This commit is contained in:
Antoine Caron 2019-07-18 22:36:04 +02:00 committed by Traefiker Bot
parent 8e97af8dc3
commit 4d8dcdc623
8 changed files with 303 additions and 41 deletions

View file

@ -1,5 +1,17 @@
<template>
<div id="app">
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href="/dashboard">
<img
src="./assets/images/traefik_logo@3x.svg"
alt="Traefik Webui"
width="112"
height="28"
/>
</a>
</div>
</nav>
<router-view />
</div>
</template>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -3,6 +3,8 @@ import App from "./App.vue";
import router from "./router";
import store from "./store";
import "bulma/css/bulma.min.css";
Vue.config.productionTip = false;
new Vue({

View file

@ -1,6 +1,6 @@
import Vue from "vue";
import Router from "vue-router";
import WIP from "./views/WIP.vue";
import Home from "./views/Home.vue";
Vue.use(Router);
@ -9,7 +9,7 @@ export default new Router({
{
path: "/",
name: "home",
component: WIP
component: Home
}
]
});

228
webui/src/views/Home.vue Normal file
View file

@ -0,0 +1,228 @@
<template>
<main class="home section">
<section class="container panel">
<p class="panel-heading ">🚧 Work in progress...</p>
<div class="panel-block">
<div>
<p>
In the meantime, you can review your current configuration by using
the <a href="/api/rawdata">/api/rawdata</a> endpoint.
</p>
<p>
Also, please keep your <i class="fa fa-eye" /> on our
<a href="https://docs.traefik.io/v2.0/operations/dashboard/"
>documentation</a
>
to stay informed
</p>
</div>
</div>
</section>
<section class="container panel" v-if="entrypoints.length">
<p class="panel-heading ">Entrypoints</p>
<div class="panel-block">
<nav class="level" :style="{ flex: '1 1' }">
<div
class="level-item has-text-centered"
v-for="entrypoint in entrypoints"
:key="entrypoint.name"
>
<div>
<p class="heading">{{ entrypoint.name }}</p>
<p class="title">{{ entrypoint.address }}</p>
</div>
</div>
</nav>
</div>
</section>
<section class="container" v-if="overview.http">
<p class="title is-4">HTTP</p>
<div class="tile is-child box columns is-height-limited">
<div class="column is-4">
<canvas id="http-routers" />
</div>
<div class="column is-4">
<canvas id="http-middlewares" />
</div>
<div class="column is-4">
<canvas id="http-services" />
</div>
</div>
</section>
<section class="container" v-if="overview.tcp">
<p class="title is-4">TCP</p>
<div class="tile is-child box columns is-height-limited">
<div class="column is-4">
<canvas id="tcp-routers" />
</div>
<div class="column is-4">
<canvas id="tcp-services" />
</div>
</div>
</section>
<section class="container panel">
<p class="panel-heading">Features</p>
<div class="panel-block">
<div class="tile is-ancestor">
<div
class="tile is-parent"
v-for="(feature, key) of overview.features"
:key="key"
>
<div
class="tile is-child notification"
:class="{ 'is-success': feature, 'is-danger': !feature }"
>
<p class="title">{{ key }}</p>
</div>
</div>
</div>
</div>
</section>
</main>
</template>
<script>
import Chart from "chart.js";
Chart.plugins.register({
afterDraw: function(chart) {
if (chart.data.datasets[0].data.reduce((acc, it) => acc + it, 0) === 0) {
var ctx = chart.chart.ctx;
var width = chart.chart.width;
var height = chart.chart.height
chart.clear();
ctx.save();
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = "16px normal 'Helvetica Nueue'";
ctx.fillText(`No ${chart.options.title.text}`, width / 2, height / 2);
ctx.restore();
}
}
});
export default {
name: "home",
data: () => ({
entrypoints: [],
overview: {
features: []
},
charts: {
http: {
routers: null,
middlewares: null,
services: null
},
tcp: {
routers: null,
services: null
}
},
interval: null
}),
methods: {
buildDoughnutChart(
selector,
entity = { errors: 2, warnings: 2, total: 6 },
name
) {
return new Chart(this.$el.querySelector(selector), {
type: "doughnut",
data: {
datasets: [
{
data: [
entity.errors,
entity.warnings,
entity.total - (entity.errors + entity.warnings)
],
backgroundColor: [
"hsl(348, 100%, 61%)",
"hsl(48, 100%, 67%)",
"hsl(141, 71%, 48%)"
]
}
],
labels: ["errors", "warnings", "success"]
},
options: {
title: {
display: true,
text: name
},
legend: {
display: false
}
}
});
},
fetchOverview() {
return fetch("/api/overview")
.then(response => response.json())
.then(response => (this.overview = response))
.then(() => {
this.charts = {
http: {
routers: this.buildDoughnutChart(
"#http-routers",
this.overview.http.routers,
"Routers"
),
middlewares: this.buildDoughnutChart(
"#http-middlewares",
this.overview.http.middlewares,
"Middlewares"
),
services: this.buildDoughnutChart(
"#http-services",
this.overview.http.services,
"Services"
)
},
tcp: {
routers: this.buildDoughnutChart(
"#tcp-routers",
this.overview.tcp.routers,
"Routers"
),
services: this.buildDoughnutChart(
"#tcp-services",
this.overview.tcp.services,
"Services"
)
}
};
});
},
fetchEntrypoints() {
return fetch("/api/entrypoints")
.then(response => response.json())
.then(response => (this.entrypoints = response));
}
},
async mounted() {
await this.fetchOverview();
await this.fetchEntrypoints();
this.interval = setInterval(() => {
this.fetchOverview();
this.fetchEntrypoints();
}, 60000);
},
beforeDestroy() {
clearInterval(this.interval);
}
};
</script>
<style lang="scss">
.home section {
margin-bottom: 1.5rem;
}
</style>

View file

@ -1,39 +0,0 @@
<template>
<main class="wip">
<img src="../assets/images/traefik.logo.svg" alt="logo" />
<header>
<h1 class="title">
<i class="fa fa-exclamation-triangle"></i>
Work in progress...
</h1>
<p>
In the meantime, you can review your current configuration by using the
<a href="/api/rawdata">/api/rawdata</a> endpoint <br /><br />
Also, please keep your <i class="fa fa-eye"></i> on our
<a href="https://docs.traefik.io/v2.0/operations/dashboard/"
>documentation</a
>
to stay informed
</p>
<p></p>
</header>
</main>
</template>
<script>
export default {
name: "home"
};
</script>
<style lang="sass">
.wip
display: flex
flex-direction: column
align-items: center
justify-content: center
height: 100vh
.title
font-size: 4em
</style>