1
0
mirror of https://github.com/ohwgiles/laminar.git synced 2026-10-17 08:40:54 +00:00

3 Commits

Author SHA1 Message Date
Oliver Giles
7ed63abd0d Better average line in Build time graph
The technique to display the average line in the old Chart.js
does not look so great in the new version. Take a different
approach using a plugin instead.
2022-10-26 20:14:21 +13:00
Guilherme Lima
9db4211091 Minor tweaks to charts appearance
Some charts had a more 'curvy' look to it. Adjusted this by using the
'tension' parameter.
Adjusted 'Utilization' pie chart aspect ratio so it is not so big.
2022-10-04 23:36:32 +02:00
Guilherme Lima
b38cbe5827 Update Chart.js to version 3.9
Fixes #175

Following 3.x Migration Guide, here is a list of the changes:

https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#specific-changes
- Chart.scaleService was replaced with Chart.registry. Scale defaults are now in Chart.defaults.scales[type].
- scales.[x/y]Axes arrays were removed. Scales are now configured directly to options.scales object with the object key being the scale Id.
- scales.[x/y]Axes.barPercentage was moved to dataset option barPercentages
- scales.[x/y]Axes.barThickness was moved to dataset option barThickness
- scales.[x/y]Axes.scaleLabel was renamed to scales[id].title
- scales.[x/y]Axes.scaleLabel.labelString was renamed to scales[id].title.text
- scales.[x/y]Axes.ticks.userCallback was renamed to scales[id].ticks.callback
- tooltips namespace was renamed to tooltip to match the plugin name
- legend, title and tooltip namespaces were moved from options to options.plugins

https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#defaults
- legend, title and tooltip namespaces were moved from Chart.defaults to Chart.defaults.plugins.
- elements.line.fill default changed from true to false

https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#chart-types
- horizontalBar chart type was removed. Horizontal bar charts can be configured using the new indexAxis option

https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#tooltip
- xLabel and yLabel were removed. Please use label and formattedValue
- The callbacks no longer are given a data parameter. The tooltip item parameter contains the chart and dataset instead
- The tooltip item's index parameter was renamed to dataIndex and value was renamed to formattedValue

https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#ticks
- options.gridLines was renamed to options.gridLines
2022-09-28 00:22:36 +02:00
5 changed files with 14 additions and 40 deletions

View File

@@ -534,7 +534,7 @@ If `CONTEXTS` is empty or absent (or if `JOB.conf` doesn't exist), laminar will
## Adding environment to a context
Append desired environment variables to `/var/lib/laminar/cfg/contexts/CONTEXT_NAME.env`:
Append desired environment variables to `/var/lib/laminar/cfg/contexts/CONTEXT_NAME.conf`:
```
DUT_IP=192.168.3.2

View File

@@ -7,7 +7,7 @@ Documentation=https://laminar.ohwg.net/docs.html
[Service]
User=laminar
EnvironmentFile=-/etc/laminar.conf
ExecStart=@CMAKE_INSTALL_PREFIX@/sbin/laminard -v
ExecStart=@CMAKE_INSTALL_PREFIX@/sbin/laminard
[Install]
WantedBy=multi-user.target

View File

@@ -131,16 +131,9 @@ kj::Promise<void> Http::cleanupPeers(kj::Timer& timer)
{
return timer.afterDelay(15 * kj::SECONDS).then([&]{
for(EventPeer* p : eventPeers) {
// Even single threaded, if load causes this timeout to be serviced
// before writeEvents has created a fulfiller, or if an exception
// caused the destruction of the promise but attach(peer) hasn't yet
// removed it from the eventPeers list, we will see a null fulfiller
// here
if(p->fulfiller) {
// an empty SSE message is a colon followed by two newlines
p->pendingOutput.push_back(":\n\n");
p->fulfiller->fulfill();
}
// an empty SSE message is a colon followed by two newlines
p->pendingOutput.push_back(":\n\n");
p->fulfiller->fulfill();
}
return cleanupPeers(timer);
}).eagerlyEvaluate(nullptr);

View File

@@ -95,31 +95,11 @@ Laminar::Laminar(Server &server, Settings settings) :
db = new Database((homePath/"laminar.sqlite").toString(true).cStr());
// Prepare database for first use
// TODO: error handling
const char *create_table_stmt =
"CREATE TABLE IF NOT EXISTS builds("
"name TEXT, number INT UNSIGNED, node TEXT, queuedAt INT, "
"startedAt INT, completedAt INT, result INT, output TEXT, "
"outputLen INT, parentJob TEXT, parentBuild INT, reason TEXT, "
"PRIMARY KEY (name, number DESC))";
db->exec(create_table_stmt);
// Migrate from (name, number) primary key to (name, number DESC).
// SQLite does not allow to alter primary key of existing table, so
// we have to create a new table.
db->stmt("SELECT sql LIKE '%, PRIMARY KEY (name, number))' "
"FROM sqlite_master WHERE type = 'table' AND name = 'builds'")
.fetch<int>([&](int has_old_index) {
if (has_old_index) {
LLOG(INFO, "Migrating table to the new primary key");
db->exec("BEGIN TRANSACTION");
db->exec("ALTER TABLE builds RENAME TO builds_old");
db->exec(create_table_stmt);
db->exec("INSERT INTO builds SELECT * FROM builds_old");
db->exec("DROP TABLE builds_old");
db->exec("COMMIT");
}
});
db->exec("CREATE TABLE IF NOT EXISTS builds("
"name TEXT, number INT UNSIGNED, node TEXT, queuedAt INT, "
"startedAt INT, completedAt INT, result INT, output TEXT, "
"outputLen INT, parentJob TEXT, parentBuild INT, reason TEXT, "
"PRIMARY KEY (name, number))");
db->exec("CREATE INDEX IF NOT EXISTS idx_completion_time ON builds("
"completedAt DESC)");
@@ -358,8 +338,9 @@ std::string Laminar::getStatus(MonitorScope scope) {
j.set("description", desc == jobDescriptions.end() ? "" : desc->second);
} else if(scope.type == MonitorScope::ALL) {
j.startArray("jobs");
db->stmt("SELECT name, number, startedAt, completedAt, result, reason "
"FROM builds GROUP BY name HAVING number = MAX(number)")
db->stmt("SELECT name,number,startedAt,completedAt,result,reason FROM builds b "
"JOIN (SELECT name n,MAX(number) latest FROM builds WHERE result IS NOT NULL GROUP BY n) q "
"ON b.name = q.n AND b.number = latest")
.fetch<str,uint,time_t,time_t,int,str>([&](str name,uint number, time_t started, time_t completed, int result, str reason){
j.StartObject();
j.set("name", name);

View File

@@ -158,7 +158,7 @@
<template id="run"><div style="display: grid; grid-template-rows: auto 1fr">
<div style="padding: 15px">
<div style="display: grid; grid-template-columns: auto 25px auto auto 1fr 400px; gap: 5px; align-items: center">
<h2 style="white-space: nowrap"><span v-html="runIcon(job.result)"></span> <router-link :to="'jobs/'+route.params.name">{{route.params.name}}</router-link> #{{route.params.number}}</h2>
<h2 style="white-space: nowrap"><span v-html="runIcon(job.result)"></span> {{route.params.name}} #{{route.params.number}}</h2>
<span></span>
<router-link :disabled="route.params.number == 1" :to="'jobs/'+route.params.name+'/'+(route.params.number-1)" tag="button">&laquo;</router-link>
<router-link :disabled="route.params.number == latestNum" :to="'jobs/'+route.params.name+'/'+(parseInt(route.params.number)+1)" tag="button">&raquo;</router-link>