Version 2.3
- Display total repository disk usage instead of gists - (classic) removed gists display - Add new plugins "posts"
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
habits:"Coding habits",
|
||||
selfskip:"Skip metrics commits",
|
||||
music:"Music plugin",
|
||||
posts:"Recent posts",
|
||||
"base.header":"Header",
|
||||
"base.activity":"Account activity",
|
||||
"base.community":"Community stats",
|
||||
@@ -39,6 +40,9 @@
|
||||
"habits.from":100,
|
||||
"music.playlist":"",
|
||||
"music.mode":"playlist",
|
||||
"music.limit":4,
|
||||
"posts.limit":4,
|
||||
"posts.source":"dev.to",
|
||||
},
|
||||
},
|
||||
templates:{
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
{{ plugins.descriptions[plugin] || plugin }}
|
||||
</label>
|
||||
</div>
|
||||
<template v-if="(plugins.enabled.habits)||(plugins.enabled.music)">
|
||||
<template v-if="(plugins.enabled.habits)||(plugins.enabled.music)||(plugins.enabled.posts)">
|
||||
<h3>2.3 Configure additional plugins</h3>
|
||||
<div class="options">
|
||||
<label v-if="(plugins.enabled.music)&&(plugins.options['music.mode'] === 'playlist')">
|
||||
@@ -59,6 +59,10 @@
|
||||
Number of events for habits
|
||||
<input type="number" v-model="plugins.options['habits.from']" min="1" max="100">
|
||||
</label>
|
||||
<label v-if="plugins.enabled.posts">
|
||||
Posts source
|
||||
<input type="text" v-model="plugins.options['posts.source']" disabled>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
data.base[part] = (`base.${part}` in q) ? !!q[`base.${part}`] : true
|
||||
|
||||
//Placeholder
|
||||
if (login === "placeholder")
|
||||
if (login === "placeholder")
|
||||
placeholder({data, conf, q})
|
||||
//Compute
|
||||
else {
|
||||
@@ -48,7 +48,7 @@
|
||||
//Compute metrics
|
||||
console.debug(`metrics/compute/${login} > compute`)
|
||||
const computer = Templates[template].default || Templates[template]
|
||||
await computer({login, q}, {conf, data, rest, graphql, plugins}, {s, pending, imports:{plugins:Plugins, url, imgb64, axios, puppeteer, format, shuffle}})
|
||||
await computer({login, q}, {conf, data, rest, graphql, plugins}, {s, pending, imports:{plugins:Plugins, url, imgb64, axios, puppeteer, format, bytes, shuffle}})
|
||||
const promised = await Promise.all(pending)
|
||||
|
||||
//Check plugins errors
|
||||
@@ -96,6 +96,14 @@
|
||||
return n
|
||||
}
|
||||
|
||||
/** Bytes formatter */
|
||||
function bytes(n) {
|
||||
for (const {u, v} of [{u:"E", v:10**18}, {u:"P", v:10**15}, {u:"T", v:10**12}, {u:"G", v:10**9}, {u:"M", v:10**6}, {u:"k", v:10**3}])
|
||||
if (n/v >= 1)
|
||||
return `${(n/v).toFixed(2).substr(0, 4).replace(/[.]0*$/, "")} ${u}B`
|
||||
return `${n} byte${n > 1 ? "s" : ""}`
|
||||
}
|
||||
|
||||
/** Array shuffler */
|
||||
function shuffle(array) {
|
||||
for (let i = array.length-1; i > 0; i--) {
|
||||
@@ -138,8 +146,9 @@
|
||||
registration:"## years ago",
|
||||
calendar:new Array(14).fill({color:"#ebedf0"}),
|
||||
licenses:{favorite:`########`},
|
||||
plugins:Object.fromEntries(enabled.map(key =>
|
||||
plugins:Object.fromEntries(enabled.map(key =>
|
||||
[key, proxify({
|
||||
posts:{source:"########", posts:new Array("posts.limit" in q ? Math.max(Number(q["posts.limit"])||0, 0) : 2).fill({title:"###### ###### ####### ######", date:"####"})},
|
||||
music:{provider:"########", tracks:new Array("music.limit" in q ? Math.max(Number(q["music.limit"])||0, 0) : 4).fill({name:"##########", artist:"######", artwork:"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mOcOnfpfwAGfgLYttYINwAAAABJRU5ErkJggg=="})},
|
||||
pagespeed:{scores:["Performance", "Accessibility", "Best Practices", "SEO"].map(title => ({title, score:NaN}))},
|
||||
followup:{issues:{count:0}, pr:{count:0}},
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import lines from "./lines/index.mjs"
|
||||
import music from "./music/index.mjs"
|
||||
import pagespeed from "./pagespeed/index.mjs"
|
||||
import posts from "./posts/index.mjs"
|
||||
import selfskip from "./selfskip/index.mjs"
|
||||
import traffic from "./traffic/index.mjs"
|
||||
|
||||
@@ -16,6 +17,7 @@
|
||||
lines,
|
||||
music,
|
||||
pagespeed,
|
||||
posts,
|
||||
selfskip,
|
||||
traffic,
|
||||
}
|
||||
45
src/plugins/posts/index.mjs
Normal file
45
src/plugins/posts/index.mjs
Normal file
@@ -0,0 +1,45 @@
|
||||
//Setup
|
||||
export default async function ({imports, data, q}, {enabled = false} = {}) {
|
||||
//Plugin execution
|
||||
try {
|
||||
//Check if plugin is enabled and requirements are met
|
||||
if ((!enabled)||(!q.posts))
|
||||
return null
|
||||
|
||||
//Parameters override
|
||||
const login = data.user.login
|
||||
let {"posts.source":source = "", "posts.limit":limit = 4} = q
|
||||
//Limit
|
||||
limit = Math.max(1, Math.min(30, Number(limit)))
|
||||
|
||||
//Retrieve posts
|
||||
let posts = null
|
||||
switch (source) {
|
||||
//Dev.to
|
||||
case "dev.to":{
|
||||
posts = (await imports.axios.get(`https://dev.to/api/articles?username=${login}&state=fresh`)).data.map(({title, readable_publish_date:date}) => ({title, date}))
|
||||
break
|
||||
}
|
||||
//Unsupported
|
||||
default:
|
||||
throw {error:{message:`Unsupported source "${source}"`}}
|
||||
}
|
||||
//Format posts
|
||||
if (Array.isArray(posts)) {
|
||||
//Limit tracklist
|
||||
if (limit > 0) {
|
||||
console.debug(`metrics/compute/${login}/plugins > music > keeping only ${limit} posts`)
|
||||
posts = posts.slice(0, limit)
|
||||
}
|
||||
//Results
|
||||
return {source, posts}
|
||||
}
|
||||
//Unhandled error
|
||||
throw {error:{message:`An error occured (could not retrieve posts)`}}
|
||||
}
|
||||
//Handle errors
|
||||
catch (error) {
|
||||
console.debug(error)
|
||||
throw {error:{message:`An error occured`}}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,8 @@
|
||||
+ (!!computed.plugins.habits)*68
|
||||
+ (!!computed.plugins.languages)*96
|
||||
+ (!!computed.plugins.music)*64 + (computed.plugins.music ? computed.plugins.music.tracks ? 14+Math.max(0, computed.plugins.music.tracks.length-1)*36 : 0 : 0)
|
||||
+ Math.max(0, (((!!base.metadata)+(!!base.header)+((!!base.activity)||(!!base.community))+(!!base.repositories)+((!!computed.plugins.habits))+(!!computed.plugins.pagespeed)+(!!computed.plugins.languages)+(!!computed.plugins.music))-1))*4
|
||||
+ (!!computed.plugins.posts)*64 + (computed.plugins.posts ? computed.plugins.posts.posts ? Math.max(0, computed.plugins.posts.posts.length-1)*40 : 0 : 0)
|
||||
+ Math.max(0, (((!!base.metadata)+(!!base.header)+((!!base.activity)||(!!base.community))+(!!base.repositories)+((!!computed.plugins.habits))+(!!computed.plugins.pagespeed)+(!!computed.plugins.languages)+(!!computed.plugins.music)+(!!computed.plugins.posts))-1))*4
|
||||
%>">
|
||||
|
||||
<defs><style><%= fonts %></style></defs>
|
||||
@@ -137,8 +138,8 @@
|
||||
<%= user.packages.totalCount %> Package<%= s(user.packages.totalCount) %>
|
||||
</div>
|
||||
<div class="field">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" ><path fill-rule="evenodd" d="M1.75 1.5a.25.25 0 00-.25.25v12.5c0 .138.112.25.25.25h12.5a.25.25 0 00.25-.25V1.75a.25.25 0 00-.25-.25H1.75zM0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0114.25 16H1.75A1.75 1.75 0 010 14.25V1.75zm9.22 3.72a.75.75 0 000 1.06L10.69 8 9.22 9.47a.75.75 0 101.06 1.06l2-2a.75.75 0 000-1.06l-2-2a.75.75 0 00-1.06 0zM6.78 6.53a.75.75 0 00-1.06-1.06l-2 2a.75.75 0 000 1.06l2 2a.75.75 0 101.06-1.06L5.31 8l1.47-1.47z"></path></svg>
|
||||
<%= user.gists.totalCount %> Gist<%= s(user.gists.totalCount) %>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" d="M2.5 3.5c0-.133.058-.318.282-.55.227-.237.592-.484 1.1-.708C4.899 1.795 6.354 1.5 8 1.5c1.647 0 3.102.295 4.117.742.51.224.874.47 1.101.707.224.233.282.418.282.551 0 .133-.058.318-.282.55-.227.237-.592.484-1.1.708C11.101 5.205 9.646 5.5 8 5.5c-1.647 0-3.102-.295-4.117-.742-.51-.224-.874-.47-1.101-.707-.224-.233-.282-.418-.282-.551zM1 3.5c0-.626.292-1.165.7-1.59.406-.422.956-.767 1.579-1.041C4.525.32 6.195 0 8 0c1.805 0 3.475.32 4.722.869.622.274 1.172.62 1.578 1.04.408.426.7.965.7 1.591v9c0 .626-.292 1.165-.7 1.59-.406.422-.956.767-1.579 1.041C11.476 15.68 9.806 16 8 16c-1.805 0-3.475-.32-4.721-.869-.623-.274-1.173-.62-1.579-1.04-.408-.426-.7-.965-.7-1.591v-9zM2.5 8V5.724c.241.15.503.286.779.407C4.525 6.68 6.195 7 8 7c1.805 0 3.475-.32 4.722-.869.275-.121.537-.257.778-.407V8c0 .133-.058.318-.282.55-.227.237-.592.484-1.1.708C11.101 9.705 9.646 10 8 10c-1.647 0-3.102-.295-4.117-.742-.51-.224-.874-.47-1.101-.707C2.558 8.318 2.5 8.133 2.5 8zm0 2.225V12.5c0 .133.058.318.282.55.227.237.592.484 1.1.708 1.016.447 2.471.742 4.118.742 1.647 0 3.102-.295 4.117-.742.51-.224.874-.47 1.101-.707.224-.233.282-.418.282-.551v-2.275c-.241.15-.503.285-.778.406-1.247.549-2.917.869-4.722.869-1.805 0-3.475-.32-4.721-.869a6.236 6.236 0 01-.779-.406z"/></svg>
|
||||
<%= computed.diskUsage %> used
|
||||
</div>
|
||||
<% if (computed.plugins.lines) { %>
|
||||
<div class="field <%= computed.plugins.lines.error ? 'error' : '' %>">
|
||||
@@ -397,6 +398,46 @@
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
<% if (computed.plugins.posts) { %>
|
||||
<section>
|
||||
<h2 class="field">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M6 2a.75.75 0 01.696.471L10 10.731l1.304-3.26A.75.75 0 0112 7h3.25a.75.75 0 010 1.5h-2.742l-1.812 4.528a.75.75 0 01-1.392 0L6 4.77 4.696 8.03A.75.75 0 014 8.5H.75a.75.75 0 010-1.5h2.742l1.812-4.529A.75.75 0 016 2z"/></svg>
|
||||
Recent articles
|
||||
</h2>
|
||||
<div class="row fill-width">
|
||||
<section>
|
||||
<% if (computed.plugins.posts.error) { %>
|
||||
<div class="field error">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M4.47.22A.75.75 0 015 0h6a.75.75 0 01.53.22l4.25 4.25c.141.14.22.331.22.53v6a.75.75 0 01-.22.53l-4.25 4.25A.75.75 0 0111 16H5a.75.75 0 01-.53-.22L.22 11.53A.75.75 0 010 11V5a.75.75 0 01.22-.53L4.47.22zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5H5.31zM8 4a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 018 4zm0 8a1 1 0 100-2 1 1 0 000 2z"></path></svg>
|
||||
<%= computed.plugins.posts.error.message %>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="field">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2.002 2.725a.75.75 0 01.797-.699C8.79 2.42 13.58 7.21 13.974 13.201a.75.75 0 11-1.497.098 10.502 10.502 0 00-9.776-9.776.75.75 0 01-.7-.798zM2 13a1 1 0 112 0 1 1 0 01-2 0zm.84-5.95a.75.75 0 00-.179 1.489c2.509.3 4.5 2.291 4.8 4.8a.75.75 0 101.49-.178A7.003 7.003 0 002.838 7.05z"></path></svg>
|
||||
From <%= computed.plugins.posts.source %>
|
||||
</div>
|
||||
<% if (computed.plugins.posts.posts.length) { %>
|
||||
<% for (const {title, date} of computed.plugins.posts.posts) { %>
|
||||
<div class="field post">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M4.75 0a.75.75 0 01.75.75V2h5V.75a.75.75 0 011.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0113.25 16H2.75A1.75 1.75 0 011 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 014.75 0zm0 3.5h8.5a.25.25 0 01.25.25V6h-11V3.75a.25.25 0 01.25-.25h2zm-2.25 4v6.75c0 .138.112.25.25.25h10.5a.25.25 0 00.25-.25V7.5h-11z"/></svg>
|
||||
<div class="infos">
|
||||
<div class="date"><%= date %></div>
|
||||
<div class="title"><%= title %></div>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
<% } else { %>
|
||||
<div class="field">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.75 1.5a.25.25 0 00-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 01.75.75v2.19l2.72-2.72a.75.75 0 01.53-.22h6.5a.25.25 0 00.25-.25v-9.5a.25.25 0 00-.25-.25H1.75zM0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0114.25 13H8.06l-2.573 2.573A1.457 1.457 0 013 14.543V13H1.75A1.75 1.75 0 010 11.25v-9.5zM9 9a1 1 0 11-2 0 1 1 0 012 0zm-.25-5.25a.75.75 0 00-1.5 0v2.5a.75.75 0 001.5 0v-2.5z"></path></svg>
|
||||
No recent posts
|
||||
</div>
|
||||
<% } %>
|
||||
<% } %>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
<% if (base.metadata) { %>
|
||||
<footer>
|
||||
<span>These metrics <%= !computed.token.scopes.includes("repo") ? "does not include" : "includes" %> private contributions</span>
|
||||
|
||||
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 42 KiB |
@@ -11,6 +11,7 @@ query Metrics {
|
||||
}
|
||||
repositories(last: $repositories, isFork: false, ownerAffiliations: OWNER) {
|
||||
totalCount
|
||||
totalDiskUsage
|
||||
nodes {
|
||||
name
|
||||
watchers {
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
.field svg {
|
||||
margin: 0 8px;
|
||||
fill: #959da5;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.field.error {
|
||||
color: #cb2431;
|
||||
@@ -217,6 +218,29 @@
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
/* Posts plugin */
|
||||
.post {
|
||||
align-items: flex-start;
|
||||
}
|
||||
.post .infos {
|
||||
display: flex;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.post .infos .title {
|
||||
font-size: 14px;
|
||||
width: 400px;
|
||||
white-space: normal;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-height: 40px;;
|
||||
}
|
||||
.post .infos .date {
|
||||
flex-shrink: 0;
|
||||
font-size: 12px;
|
||||
opacity: .7;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
/* Fade animation */
|
||||
.af {
|
||||
opacity: 0;
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
computed.licenses.used[repository.licenseInfo.spdxId] = (computed.licenses.used[repository.licenseInfo.spdxId] || 0) + 1
|
||||
}
|
||||
|
||||
//Total disk usage
|
||||
computed.diskUsage = `${imports.bytes(data.user.repositories.totalDiskUsage*1000)}`
|
||||
|
||||
//Compute licenses stats
|
||||
computed.licenses.favorite = Object.entries(computed.licenses.used).sort(([an, a], [bn, b]) => b - a).slice(0, 1).map(([name, value]) => name) || ""
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ Last generated: <%= new Date().toGMTString() %>
|
||||
<% if (base.repositories) { %>
|
||||
<div class="stdin"><%- meta.$ %> ls -lh github/repositories</div><%# -%>
|
||||
<div class="stdout"><%# -%>
|
||||
Total <%= user.repositories.totalCount %> repositor<%= s(user.repositories.totalCount, "y") %>
|
||||
Total <%= user.repositories.totalCount %> repositor<%= s(user.repositories.totalCount, "y") %> - <%= computed.diskUsage %>
|
||||
<% if (computed.plugins.traffic) { if (computed.plugins.traffic.error) { -%>
|
||||
---- <b> </b> views <span class="error">(<%= computed.plugins.traffic.error.message %>)</span>
|
||||
<% } else { -%>
|
||||
|
||||
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.6 KiB |
@@ -11,6 +11,7 @@ query Metrics {
|
||||
}
|
||||
repositories(last: $repositories, isFork: false, ownerAffiliations: OWNER) {
|
||||
totalCount
|
||||
totalDiskUsage
|
||||
nodes {
|
||||
name
|
||||
watchers {
|
||||
|
||||
Reference in New Issue
Block a user