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`: `
<% } else if (plugins.habits.facts) { %>
-
+
<% if (plugins.habits.indents.style) { %>
- Uses <%= plugins.habits.indents.style %> for indentation
<% } %>
@@ -37,58 +37,78 @@
<% if (plugins.habits.charts) { %>
- <% if (!Number.isNaN(plugins.habits.commits.hour)) { %>
-
- Commit activity per hour of day
-
- <% 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]]) } %>
+
+ <% if (!Number.isNaN(plugins.habits.commits.hour)) { %>
+
+
Commit activity per hour of day
+ <% if (Array.isArray(plugins.habits.charts)) { %>
+
+ <%- plugins.habits.charts[0] %>
+
+ <% } else { %>
+
+ <% 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]]) } %>
- <% if (plugins.habits.trim) { %>
- <% while (displayedValues[0][1] === 0) { displayedValues.shift(); } %>
- <% while (displayedValues[displayedValues.length-1][1] === 0){ displayedValues.pop(); } %>
- <% } %>
+ <% if (plugins.habits.trim) { %>
+ <% while (displayedValues[0][1] === 0) { displayedValues.shift(); } %>
+ <% while (displayedValues[displayedValues.length-1][1] === 0){ displayedValues.pop(); } %>
+ <% } %>
- <% for(let i = 0; i < displayedValues.length; i++) { %>
-
-
<%= displayedValues[i][2] %>
-
- <%= `${displayedValues[i][0]}`.padStart(2, 0) %>
+ <% for(let i = 0; i < displayedValues.length; i++) { %>
+
+
<%= displayedValues[i][2] %>
+
+ <%= `${displayedValues[i][0]}`.padStart(2, 0) %>
+
+ <% } %>
<% } %>
-
- <% } %>
+ <% } %>
-
- <% if (!Number.isNaN(plugins.habits.commits.day)) { %>
-
- Commit activity per day of week
-
- <% for (let d = 0; d < 7; d++) { const p = (plugins.habits.commits.days[d]??0)/(plugins.habits.commits.days.max??1); %>
-
-
<%= plugins.habits.commits.days[d] %>
-
- <%= ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][d] %>
+
+ <% if (!Number.isNaN(plugins.habits.commits.day)) { %>
+
+ Commit activity per day of week
+ <% if (Array.isArray(plugins.habits.charts)) { %>
+
+ <%- plugins.habits.charts[1] %>
+
+ <% } else { %>
+
+ <% for (let d = 0; d < 7; d++) { const p = (plugins.habits.commits.days[d]??0)/(plugins.habits.commits.days.max??1); %>
+
+
<%= plugins.habits.commits.days[d] %>
+
+ <%= ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][d] %>
+
+ <% } %>
<% } %>
-
-
- <% } %>
- <% if (plugins.habits.linguist.available) { %>
-
- Language activity
-
- <% for (const [language, p] of plugins.habits.linguist.ordered) { %>
-
-
<%= language %>
-
-
<%= Math.round(100*p) %>%
+
+ <% } %>
+ <% if (plugins.habits.linguist.available) { %>
+
+ Language activity
+ <% if (Array.isArray(plugins.habits.charts)) { %>
+
+ <%- plugins.habits.charts[2] %>
+
+ <% } else { %>
+
+ <% for (const [language, p] of plugins.habits.linguist.ordered) { %>
+
+
<%= language %>
+
+
<%= Math.round(100*p) %>%
+
+ <% } %>
<% } %>
-
-
- <% } %>
-
+
+ <% } %>
+
+
<% } %>
<% } %>
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;