admin: migrate login stats chart to web component

This commit is contained in:
Jens Langhammer 2020-11-20 23:42:14 +01:00
parent 582dfface9
commit a2c7921c1f
10 changed files with 296 additions and 234 deletions

View file

@ -17,8 +17,8 @@
<i class="pf-icon pf-icon-server"></i> {% trans 'Logins over the last 24 hours' %}
</div>
</div>
<div class="pf-c-card__body" style="position: relative; height:100%; width:100%">
<canvas id="logins-last-metrics"></canvas>
<div class="pf-c-card__body">
<pb-admin-logins-chart url="{% url 'passbook_api:admin_metrics-list' %}"></pb-admin-logins-chart>
</div>
</div>
<div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-4-col" style="grid-column-end: span 2;grid-row-end: span 3;">
@ -277,59 +277,4 @@
</div>
</div>
</div>
<script>
var ctx = document.getElementById('logins-last-metrics').getContext('2d');
fetch("{% url 'passbook_api:admin_metrics-list' %}").then(r => r.json()).then(r => {
var myChart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [
{
label: 'Failed Logins',
backgroundColor: "rgba(201, 25, 11, .5)",
spanGaps: true,
data: r.logins_failed_per_1h,
},
{
label: 'Successful Logins',
backgroundColor: "rgba(189, 229, 184, .5)",
spanGaps: true,
data: r.logins_per_1h,
},
]
},
options: {
maintainAspectRatio: false,
spanGaps: true,
scales: {
xAxes: [{
stacked: true,
gridLines: {
color: "rgba(0, 0, 0, 0)",
},
type: 'time',
offset: true,
ticks: {
callback: function (value, index, values) {
const date = new Date();
const delta = (date - values[index].value);
const ago = Math.round(delta / 1000 / 3600);
return `${ago} Hours ago`;
},
autoSkip: true,
maxTicksLimit: 8
}
}],
yAxes: [{
stacked: true,
gridLines: {
color: "rgba(0, 0, 0, 0)",
}
}]
}
}
});
});
</script>
{% endblock %}

View file

@ -15,7 +15,6 @@
<script src="{% static 'node_modules/codemirror/mode/xml/xml.js' %}"></script>
<script src="{% static 'node_modules/codemirror/mode/yaml/yaml.js' %}"></script>
<script src="{% static 'node_modules/codemirror/mode/python/python.js' %}"></script>
<script src="{% static 'node_modules/chart.js/dist/Chart.bundle.min.js' %}"></script>
{% endblock %}
{% block page_content %}

View file

@ -17,7 +17,7 @@
<link rel="stylesheet" type="text/css" href="{% static 'node_modules/@patternfly/patternfly/patternfly-addons.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'passbook/passbook.css' %}">
<script src="{% static 'passbook/main.js' %}" defer></script>
<script src="{% static 'passbook/main.js' %}" type="module"></script>
{% block head %}
{% endblock %}
</head>

View file

@ -73,6 +73,14 @@
}
}
},
"@types/chart.js": {
"version": "2.9.28",
"resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.28.tgz",
"integrity": "sha512-9YYhsxRngRJb0dkuaU5BezkF+zvvVHnwdRw+rtlahtFb4zqNf9YSgWsOq+dLYeh0fqsWmHUYLR64eNigh02F+w==",
"requires": {
"moment": "^2.10.2"
}
},
"@types/clean-css": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.2.tgz",

View file

@ -7,6 +7,7 @@
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.1",
"@patternfly/patternfly": "^4.59.1",
"@types/chart.js": "^2.9.28",
"chart.js": "^2.9.4",
"codemirror": "^5.58.2",
"lit-element": "^2.4.0",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -9,12 +9,11 @@ export default [{
input: './src/main.ts',
output: [
{
format: 'iife',
format: 'es',
dir: 'passbook',
sourcemap: true
}
],
plugins: [
typescript(),
resolve({browser: true}),

View file

@ -0,0 +1,101 @@
import { css, customElement, html, LitElement, property } from "lit-element";
import Chart from "chart.js";
interface TickValue {
value: number;
major: boolean;
}
@customElement("pb-admin-logins-chart")
export class AdminLoginsChart extends LitElement {
@property()
url: string = "";
chart: any;
static get styles() {
return css`
:host {
position: relative;
height: 100%;
width: 100%;
display: block;
min-height: 25rem;
}
canvas {
width: 100px;
height: 100px;
}
`;
}
constructor() {
super();
window.addEventListener('resize', () => {
if (this.chart) {
this.chart.resize();
}
});
}
firstUpdated() {
fetch(this.url).then(r => r.json()).catch(e => console.error(e)).then(r => {
let ctx = (<HTMLCanvasElement>this.shadowRoot?.querySelector("canvas")).getContext('2d')!;
this.chart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [
{
label: 'Failed Logins',
backgroundColor: "rgba(201, 25, 11, .5)",
spanGaps: true,
data: r.logins_failed_per_1h,
},
{
label: 'Successful Logins',
backgroundColor: "rgba(189, 229, 184, .5)",
spanGaps: true,
data: r.logins_per_1h,
},
]
},
options: {
maintainAspectRatio: false,
spanGaps: true,
scales: {
xAxes: [{
stacked: true,
gridLines: {
color: "rgba(0, 0, 0, 0)",
},
type: 'time',
offset: true,
ticks: {
callback: function (value, index: number, values) {
const valueStamp = <TickValue>(<unknown>values[index]);
const delta = (Date.now() - valueStamp.value);
const ago = Math.round(delta / 1000 / 3600);
return `${ago} Hours ago`;
},
autoSkip: true,
maxTicksLimit: 8
}
}],
yAxes: [{
stacked: true,
gridLines: {
color: "rgba(0, 0, 0, 0)",
}
}]
}
}
});
});
}
render() {
return html`<canvas></canvas>`;
}
}

View file

@ -1,5 +1,6 @@
import "./legacy.js";
import "./AdminLoginsChart";
import './ActionButton';
import './Dropdown';
import './FetchFillSlot';