feat(plugins/habits): add plugin_habits_charts_type (#938)

This commit is contained in:
Simon Lecoq
2022-03-22 05:22:18 +01:00
committed by GitHub
parent 6e41591d95
commit 10f83339bd
4 changed files with 135 additions and 49 deletions

View File

@@ -10,7 +10,7 @@ export default async function({login, data, rest, imports, q, account}, {enabled
return null
//Load inputs
let {from, days, facts, charts, trim} = imports.metadata.plugins.habits.inputs({data, account, q}, defaults)
let {from, days, facts, charts, "charts.type":_charts, trim} = imports.metadata.plugins.habits.inputs({data, account, q}, defaults)
//Initialization
const habits = {facts, charts, trim, lines:{average:{chars:0}}, commits:{fetched:0, hour:NaN, hours:{}, day:NaN, days:{}}, indents:{style:"", spaces:0, tabs:0}, linguist:{available:false, ordered:[], languages:{}}}
@@ -109,7 +109,53 @@ export default async function({login, data, rest, imports, q, account}, {enabled
}
else
console.debug(`metrics/compute/${login}/plugins > habits > linguist not available`)
}
//Generating charts with chartist
if (_charts === "chartist") {
console.debug(`metrics/compute/${login}/plugins > habits > generating charts`)
habits.charts = await Promise.all([
{type:"line", data:{...empty(24), ...Object.fromEntries(Object.entries(habits.commits.hours).filter(([k]) => !Number.isNaN(+k)))}, low:0, high:habits.commits.hours.max},
{type:"line", data:{...empty(7), ...Object.fromEntries(Object.entries(habits.commits.days).filter(([k]) => !Number.isNaN(+k)))}, low:0, high:habits.commits.days.max, labels:["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], half:true},
{type:"pie", data:habits.linguist.languages, half:true},
].map(({type, data, high, low, ref, labels = {}, half = false}) => {
const options = {
width:480 * (half ? 0.45 : 1),
height:160,
fullWidth:true,
}
const values = {
labels:Object.keys(data).map(key => labels[key] ?? key),
series:Object.values(data)
}
if (type === "line") {
Object.assign(options, {
showPoint:true,
axisX:{showGrid:false},
axisY:{showLabel:false, offset:20, labelInterpolationFnc:value => imports.format(value), high, low, referenceValue:ref},
showArea:true,
})
Object.assign(values, {
series:[Object.values(data)]
})
}
return imports.chartist(type, options, values)
}))
data.postscripts.push(`(${function(format) {
document.querySelectorAll(".habits .chartist").forEach(chart => {
chart.querySelectorAll(".habits .chartist .ct-point").forEach(node => {
const [x, y, value] = ["x1", "y1", "ct:value"].map(attribute => node.getAttribute(attribute))
if (Number(value)) {
const text = document.createElementNS("http://www.w3.org/2000/svg", "text")
text.setAttributeNS(null, "x", x)
text.setAttributeNS(null, "y", y - 5)
text.setAttributeNS(null, "class", "ct-post")
text.appendChild(document.createTextNode(format(value)))
node.parentNode.append(text)
}
})
})
}})(${imports.format.toString()})`)
}
//Results
@@ -122,3 +168,8 @@ export default async function({login, data, rest, imports, q, account}, {enabled
throw {error:{message:"An error occured", instance:error}}
}
}
/**Initialize an empty object with values from 0 to n */
function empty(n) {
return Object.fromEntries(new Array(n).fill(0).map((_, i) => [i, 0]))
}

View File

@@ -52,6 +52,17 @@ inputs:
type: boolean
default: no
plugin_habits_charts_type:
description: |
Charts display type
- `classic`: `<div>` based charts, simple and lightweight
- `chartist`: `<svg>` based charts, smooth
type: string
default: classic
values:
- classic
- chartist
plugin_habits_trim:
description: Trim unused hours on charts
type: boolean

View File

@@ -1,5 +1,5 @@
<% if (plugins.habits) { %>
<section>
<section class="habits">
<h2 class="field wrap">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 01-1.484.211c-.04-.282-.163-.547-.37-.847a8.695 8.695 0 00-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.75.75 0 01-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75zM6 15.25a.75.75 0 01.75-.75h2.5a.75.75 0 010 1.5h-2.5a.75.75 0 01-.75-.75zM5.75 12a.75.75 0 000 1.5h4.5a.75.75 0 000-1.5h-4.5z"></path></svg>
Recent coding habits
@@ -18,7 +18,7 @@
</div>
<% } else if (plugins.habits.facts) { %>
<div class="row">
<ul class="habits">
<ul class="facts">
<% if (plugins.habits.indents.style) { %>
<li>Uses <%= plugins.habits.indents.style %> for indentation</li>
<% } %>
@@ -37,9 +37,15 @@
</section>
<% if (plugins.habits.charts) { %>
<section class="habits">
<% if (!Number.isNaN(plugins.habits.commits.hour)) { %>
<section class="column chart largeable">
<div class="column chart largeable">
<h3>Commit activity per hour of day</h3>
<% if (Array.isArray(plugins.habits.charts)) { %>
<div class="row margin-bottom chartist">
<%- plugins.habits.charts[0] %>
</div>
<% } else { %>
<div class="chart-bars">
<% var displayedValues = []; %>
<% for (let h = 0; h < 24; h++) { displayedValues.push([h, (plugins.habits.commits.hours[h]??0)/(plugins.habits.commits.hours.max??1), plugins.habits.commits.hours[h]]) } %>
@@ -57,13 +63,19 @@
</div>
<% } %>
</div>
</section>
<% } %>
</div>
<% } %>
<div class="row largeable">
<% if (!Number.isNaN(plugins.habits.commits.day)) { %>
<section class="column chart">
<h3>Commit activity per day of week</h3>
<% if (Array.isArray(plugins.habits.charts)) { %>
<div class="margin-bottom chartist">
<%- plugins.habits.charts[1] %>
</div>
<% } else { %>
<div class="chart-bars">
<% for (let d = 0; d < 7; d++) { const p = (plugins.habits.commits.days[d]??0)/(plugins.habits.commits.days.max??1); %>
<div class="entry">
@@ -73,11 +85,17 @@
</div>
<% } %>
</div>
<% } %>
</section>
<% } %>
<% if (plugins.habits.linguist.available) { %>
<section class="column chart">
<h3>Language activity</h3>
<% if (Array.isArray(plugins.habits.charts)) { %>
<div class="margin-bottom chartist">
<%- plugins.habits.charts[2] %>
</div>
<% } else { %>
<div class="chart-bars horizontal">
<% for (const [language, p] of plugins.habits.linguist.ordered) { %>
<div class="entry">
@@ -87,8 +105,10 @@
</div>
<% } %>
</div>
<% } %>
</section>
<% } %>
</div>
</section>
<% } %>
<% } %>

View File

@@ -335,15 +335,15 @@
}
/* Habits */
.habits {
.habits .facts {
margin: 0;
list-style-type: none;
padding-left: 37px;
}
/* Stargazers */
/* Chartist */
/* purgecss ignore */
.stargazers .chartist .ct-post {
.chartist .ct-post {
fill: rgba(127, 127, 127, 0.8) !important;
color: rgba(127, 127, 127, 0.8) !important;
font-size: 9px;
@@ -1365,6 +1365,10 @@
display: flex;
margin-left: -12px;
}
.ct-chart-pie .ct-label {
fill: rgba(255, 255, 255, 0.8) !important;
color: rgba(255, 255, 255, 0.8) !important;
}
.ct-line {
stroke-width: 2px !important;
stroke: #58A6FF !important;