Version 2.1

- No plugins are enabled by default
- Logs from setup can be hidden
- Number of repositories to inspect can be configured (default to 100)
- Default events for habits plugin is now 100
- Number of events for habits can be overriden in query
- Server app improvments
- Test improvements
- Better test
This commit is contained in:
lowlighter
2020-10-23 13:56:15 +02:00
parent 543c6f8f98
commit 2cf152d7d1
16 changed files with 311 additions and 200 deletions

View File

@@ -13,66 +13,70 @@
<h1><a href="https://github.com/lowlighter/metrics">Generate your metrics !</a></h1>
<div class="step">
<h2>1. Enter your GitHub username</h2>
<label>
<input type="text" v-model="user" maxlength="39" placeholder="GitHub username" :disabled="generated.pending">
</label>
</div>
<template>
<div class="step">
<h2>2. Select a template and enable additional plugins</h2>
<div class="templates">
<label v-for="template in templates.list" :key="template">
<input type="radio" v-model="templates.selected" :value="template" @change="load" :disabled="generated.pending">
{{ templates.descriptions[template] || template }}
<div class="step">
<h2>1. Enter your GitHub username</h2>
<label>
<input type="text" v-model="user" maxlength="39" placeholder="GitHub username" :disabled="generated.pending">
</label>
</div>
<div class="plugins">
<label v-for="plugin in plugins.list" :key="plugin">
<input type="checkbox" v-model="plugins.enabled[plugin]" @change="load" :disabled="generated.pending">
{{ plugins.descriptions[plugin] || plugin }}
</label>
</div>
<div class="cache-notice">
*To reduce server overhead, metrics are cached. Changes may not be reflected until cache expiration.
</div>
<div class="palette">
Generated metrics use transparency and colors which matches both light and dark modes
<div class="palettes">
<label>
<input type="radio" v-model="palette" value="light">
☀️ Light mode
</label>
<label>
<input type="radio" v-model="palette" value="dark">
🌙 Night mode
<div class="step">
<h2>2. Select a template {{ plugins.list.length ? "and enable additional plugins" : "" }}</h2>
<div class="templates">
<label v-for="template in templates.list" :key="template">
<input type="radio" v-model="templates.selected" :value="template" @change="load" :disabled="generated.pending">
{{ templates.descriptions[template] || template }}
</label>
</div>
</div>
</div>
<div class="step">
<h2>3. Generate your metrics</h2>
<template v-if="generated.content">
<img class="metrics" :src="generated.content" alt="metrics">
</template>
<template v-else>
<img class="metrics" :src="templates.placeholder" alt="metrics">
<button @click="generate" :disabled="(!user)||(generated.pending)">{{ generated.pending ? "Generating your metrics..." : user ? "Generate your metrics" : "Enter your GitHub username first" }}</button>
</template>
</div>
<div class="step">
<h2>4. Embed these metrics on your GitHub profile</h2>
<template v-if="user">
Add the markdown below in your <i>README.md</i> at <a :href="repo">{{ user }}/{{ user }}</a>
<div class="code">
![<span class="md-alt">GitHub metrics</span>]({{ url }})
<div class="plugins">
<label v-for="plugin in plugins.list" :key="plugin">
<input type="checkbox" v-model="plugins.enabled[plugin]" @change="load" :disabled="generated.pending">
{{ plugins.descriptions[plugin] || plugin }}
</label>
</div>
</template>
For even more features, setup <a href="https://github.com/lowlighter/metrics">lowlighter/metrics</a> as a <a href="https://github.com/marketplace/actions/github-metrics-as-svg-image">GitHub action</a> !
</div>
<div class="cache-notice" v-if="plugins.list.length">
*To reduce server overhead, metrics are cached. Changes may not be reflected until cache expiration.
</div>
<div class="palette">
Generated metrics use transparency and colors which matches both light and dark modes
<div class="palettes">
<label>
<input type="radio" v-model="palette" value="light">
☀️ Light mode
</label>
<label>
<input type="radio" v-model="palette" value="dark">
🌙 Night mode
</label>
</div>
</div>
</div>
<div class="step">
<h2>3. Generate your metrics</h2>
<template v-if="generated.content">
<img class="metrics" :src="generated.content" alt="metrics">
</template>
<template v-else>
<img class="metrics" :src="templates.placeholder" alt="metrics">
<button @click="generate" :disabled="(!user)||(generated.pending)">{{ generated.pending ? "Generating your metrics..." : user ? "Generate your metrics" : "Enter your GitHub username first" }}</button>
</template>
</div>
<div class="step">
<h2>4. Embed these metrics on your GitHub profile</h2>
<template v-if="user">
Add the markdown below in your <i>README.md</i> at <a :href="repo">{{ user }}/{{ user }}</a>
<div class="code">
![<span class="md-alt">GitHub metrics</span>]({{ url }})
</div>
</template>
For even more features, setup <a href="https://github.com/lowlighter/metrics">lowlighter/metrics</a> as a <a href="https://github.com/marketplace/actions/github-metrics-as-svg-image">GitHub action</a> !
</div>
</template>
</main>
@@ -91,7 +95,7 @@
palette:"light",
plugins:{
list:(await axios.get("/plugins.list")).data,
enabled:{languages:true, followup:true},
enabled:{},
descriptions:{
pagespeed:"Website performances",
languages:"Most used languages",
@@ -122,7 +126,7 @@
},
url() {
const plugins = Object.entries(this.plugins.enabled)
.filter(([key, value]) => /^(?:languages|followup)$/.test(key) ? !value : value)
.filter(([key, value]) => value)
.map(([key, value]) => `${key}=${+value}`)
.join("&")
return `${window.location.href}${this.user}${plugins.length ? `?${plugins}` : ""}`

View File

@@ -14,6 +14,7 @@
console.debug(`metrics/compute/${login} > start`)
console.debug(JSON.stringify(q))
const template = q.template || conf.settings.templates.default
const repositories = Math.max(0, Number(q.repositories)) || conf.settings.repositories || 100
const pending = []
const s = (value, end = "") => value > 1 ? {y:"ies", "":"s"}[end] : end
if ((!(template in Templates))||(!(template in conf.templates))||((conf.settings.templates.enabled.length)&&(!conf.settings.templates.enabled.includes(template))))
@@ -24,6 +25,7 @@
console.debug(`metrics/compute/${login} > query`)
const data = await graphql(query
.replace(/[$]login/, `"${login}"`)
.replace(/[$]repositories/, `${repositories}`)
.replace(/[$]calendar.to/, `"${(new Date()).toISOString()}"`)
.replace(/[$]calendar.from/, `"${(new Date(Date.now()-14*24*60*60*1000)).toISOString()}"`)
)

View File

@@ -1,5 +1,5 @@
//Setup
export default function ({login, data, computed, pending, q}, {enabled = true} = {}) {
export default function ({login, data, computed, pending, q}, {enabled = false} = {}) {
//Check if plugin is enabled and requirements are met
if (!enabled)
return computed.plugins.followup = null

View File

@@ -1,5 +1,5 @@
//Setup
export default function ({login, rest, computed, pending, q}, {enabled = false, from = 50} = {}) {
export default function ({login, rest, computed, pending, q}, {enabled = false, from = 100} = {}) {
//Check if plugin is enabled and requirements are met
if (!enabled)
return computed.plugins.habits = null
@@ -8,6 +8,12 @@
console.debug(`metrics/compute/${login}/plugins > habits`)
computed.svg.height += 70
//Parameter override
if (typeof q["habits.from"] === "number") {
from = Math.max(0, Math.min(from, q["habits.from"]))
console.debug(`metrics/compute/${login}/plugins > habits > events = ${from}`)
}
//Plugin execution
pending.push(new Promise(async solve => {
try {

View File

@@ -1,5 +1,5 @@
//Setup
export default function ({login, data, computed, pending, q}, {enabled = true} = {}) {
export default function ({login, data, computed, pending, q}, {enabled = false} = {}) {
//Check if plugin is enabled and requirements are met
if (!enabled)
return computed.plugins.languages = null

View File

@@ -3,10 +3,11 @@
import path from "path"
/** Setup */
export default async function () {
export default async function ({log = true} = {}) {
//Init
console.debug(`metrics/setup > setup`)
const logger = log ? console.debug : () => null
logger(`metrics/setup > setup`)
const templates = "src/templates"
const conf = {
templates:{},
@@ -16,17 +17,19 @@
}
//Load settings
console.debug(`metrics/setup > load settings.json`)
logger(`metrics/setup > load settings.json`)
if (fs.existsSync(path.resolve("settings.json"))) {
conf.settings = JSON.parse(`${await fs.promises.readFile(path.resolve("settings.json"))}`)
console.debug(`metrics/setup > load settings.json > success`)
logger(`metrics/setup > load settings.json > success`)
}
else
console.debug(`metrics/setup > load settings.json > (missing)`)
logger(`metrics/setup > load settings.json > (missing)`)
if (!conf.settings.templates)
conf.settings.templates = {default:"classic", enabled:[]}
if (!conf.settings.plugins)
conf.settings.plugins = {}
if (conf.settings.debug)
console.debug(conf.settings)
logger(conf.settings)
//Load templates
if (fs.existsSync(path.resolve(templates))) {
@@ -34,7 +37,7 @@
//Cache templates
if (/^index.mjs$/.test(name))
continue
console.debug(`metrics/setup > load template [${name}]`)
logger(`metrics/setup > load template [${name}]`)
const files = [
`${templates}/${name}/query.graphql`,
`${templates}/${name}/image.svg`,
@@ -43,14 +46,14 @@
]
const [query, image, placeholder, style] = await Promise.all(files.map(async file => `${await fs.promises.readFile(path.resolve(file))}`))
conf.templates[name] = {query, image, placeholder, style}
console.debug(`metrics/setup > load template [${name}] > success`)
logger(`metrics/setup > load template [${name}] > success`)
//Debug
if (conf.settings.debug) {
Object.defineProperty(conf.templates, name, {
get() {
console.debug(`metrics/setup > reload template [${name}]`)
logger(`metrics/setup > reload template [${name}]`)
const [query, image, placeholder, style] = files.map(file => `${fs.readFileSync(path.resolve(file))}`)
console.debug(`metrics/setup > reload template [${name}] > success`)
logger(`metrics/setup > reload template [${name}] > success`)
return {query, image, placeholder, style}
}
})
@@ -58,12 +61,12 @@
}
}
else {
console.debug(`metrics/setup > load templates from build`)
logger(`metrics/setup > load templates from build`)
conf.templates = JSON.parse(Buffer.from(`<#assets>`, "base64").toString("utf8"))
}
//Conf
console.debug(`metrics/setup > setup > success`)
logger(`metrics/setup > setup > success`)
return conf
}

View File

@@ -8,7 +8,7 @@ query Metrics {
gists {
totalCount
}
repositories(last: 100, isFork: false, ownerAffiliations: OWNER) {
repositories(last: $repositories, isFork: false, ownerAffiliations: OWNER) {
totalCount
nodes {
name