From 10f83339bd4d4257eadf50b836b4a658a8149c7b Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Tue, 22 Mar 2022 05:22:18 +0100 Subject: [PATCH] feat(plugins/habits): add `plugin_habits_charts_type` (#938) --- source/plugins/habits/index.mjs | 53 ++++++++- source/plugins/habits/metadata.yml | 11 ++ source/templates/classic/partials/habits.ejs | 110 +++++++++++-------- source/templates/classic/style.css | 10 +- 4 files changed, 135 insertions(+), 49 deletions(-) diff --git a/source/plugins/habits/index.mjs b/source/plugins/habits/index.mjs index 259dec3e..63b75812 100644 --- a/source/plugins/habits/index.mjs +++ b/source/plugins/habits/index.mjs @@ -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])) +} \ No newline at end of file diff --git a/source/plugins/habits/metadata.yml b/source/plugins/habits/metadata.yml index e3d9de74..cf09459f 100644 --- a/source/plugins/habits/metadata.yml +++ b/source/plugins/habits/metadata.yml @@ -52,6 +52,17 @@ inputs: type: boolean default: no + plugin_habits_charts_type: + description: | + Charts display type + - `classic`: `
` based charts, simple and lightweight + - `chartist`: `` based charts, smooth + type: string + default: classic + values: + - classic + - chartist + plugin_habits_trim: description: Trim unused hours on charts type: boolean diff --git a/source/templates/classic/partials/habits.ejs b/source/templates/classic/partials/habits.ejs index 6f00fcf1..1ae66d8a 100644 --- a/source/templates/classic/partials/habits.ejs +++ b/source/templates/classic/partials/habits.ejs @@ -1,5 +1,5 @@ <% if (plugins.habits) { %> -
+

Recent coding habits @@ -18,7 +18,7 @@

<% } else if (plugins.habits.facts) { %>
-
+ + <% } %> + + <% } %> <% } %> diff --git a/source/templates/classic/style.css b/source/templates/classic/style.css index e61c8caf..9d165267 100644 --- a/source/templates/classic/style.css +++ b/source/templates/classic/style.css @@ -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;