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:
@@ -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">
|
||||

|
||||
<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">
|
||||

|
||||
</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}` : ""}`
|
||||
|
||||
@@ -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()}"`)
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user