Achievements plugin: add option to change display style (#473)

This commit is contained in:
Simon Lecoq
2021-08-12 19:09:13 +02:00
committed by GitHub
parent 2429c60723
commit 8c241b81cd
7 changed files with 89 additions and 11 deletions

View File

@@ -81,7 +81,7 @@
</section> </section>
<div class="rankeds"> <div class="rankeds">
<div v-for="{icon, title, text, rank, progress, value, leaderboard = null} in ranked" class="ranked" :class="{[rank.charAt(0).toLocaleLowerCase()]:rank !== '$', secret:rank === '$'}"> <div v-for="{icon, prefix, title, text, rank, progress, value, leaderboard = null} in ranked" class="ranked" :class="{[rank.charAt(0).toLocaleLowerCase()]:rank !== '$', secret:rank === '$'}">
<div class="icon"> <div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" height="44" width="44"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" height="44" width="44">
<defs> <defs>
@@ -99,7 +99,7 @@
<div class="info"> <div class="info">
<div class="user-rank">{{ format("number", leaderboard.user) }}<sup>{{ {1:"st", 2:"nd", 3:"rd"}[leaderboard.user%10] ?? "th" }}</sup></div> <div class="user-rank">{{ format("number", leaderboard.user) }}<sup>{{ {1:"st", 2:"nd", 3:"rd"}[leaderboard.user%10] ?? "th" }}</sup></div>
<div class="total-rank">/ {{ format("number", leaderboard.total, {notation:"compact", compactDisplay:"long"}) }} {{ leaderboard.type }}</div> <div class="total-rank">/ {{ format("number", leaderboard.total, {notation:"compact", compactDisplay:"long"}) }} {{ leaderboard.type }}</div>
<div class="title">{{ title }}</div> <div class="title">{{ prefix }} {{ prefix.length ? title.toLocaleLowerCase() : title }}</div>
<div class="text">{{ text }}</div> <div class="text">{{ text }}</div>
</div> </div>
</div> </div>
@@ -124,7 +124,7 @@
Highlights Highlights
</h2> </h2>
<div class="achievements"> <div class="achievements">
<div v-for="{icon, title, text, rank, progress, value, leaderboard = null} in achievements" class="achievement" :class="{[rank.charAt(0).toLocaleLowerCase()]:rank !== '$', secret:rank === '$'}"> <div v-for="{icon, prefix, title, text, rank, progress, value, leaderboard = null} in achievements" class="achievement" :class="{[rank.charAt(0).toLocaleLowerCase()]:rank !== '$', secret:rank === '$'}">
<div class="icon"> <div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" height="44" width="44"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" height="44" width="44">
<defs> <defs>
@@ -140,7 +140,7 @@
</svg> </svg>
</div> </div>
<div class="info"> <div class="info">
<div class="title">{{ title }}</div> <div class="title">{{ prefix }} {{ prefix.length ? title.toLocaleLowerCase() : title }}</div>
<div class="text">{{ text }}</div> <div class="text">{{ text }}</div>
</div> </div>
</div> </div>

View File

@@ -304,6 +304,7 @@
? ({ ? ({
achievements: { achievements: {
list: new Array(8).fill(null).map(_ => ({ list: new Array(8).fill(null).map(_ => ({
prefix: "",
title: faker.lorem.word(), title: faker.lorem.word(),
unlock: null, unlock: null,
text: faker.lorem.sentence(), text: faker.lorem.sentence(),

View File

@@ -5,6 +5,9 @@ The *achievements* plugin displays several highlights about what you achieved on
<table> <table>
<td align="center"> <td align="center">
<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.achievements.svg"> <img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.achievements.svg">
<details><summary>Compact display</summary>
<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.achievements.compact.svg">
</details>
<img width="900" height="1" alt=""> <img width="900" height="1" alt="">
</td> </td>
</table> </table>
@@ -35,4 +38,5 @@ It also lets you quickly see at a glance what this user primarly use GitHub for,
plugin_achievements_secrets: yes # Display unlocked secrets achievements plugin_achievements_secrets: yes # Display unlocked secrets achievements
plugin_achievements_ignored: octonaut # Hide octonaut achievement plugin_achievements_ignored: octonaut # Hide octonaut achievement
plugin_achievements_limit: 0 # Display all unlocked achievement matching threshold and secrets params plugin_achievements_limit: 0 # Display all unlocked achievement matching threshold and secrets params
plugin_achievements_display: compact # Use compact display
``` ```

View File

@@ -10,7 +10,7 @@ export default async function({login, q, imports, data, computed, graphql, queri
return null return null
//Load inputs //Load inputs
let {threshold, secrets, only, ignored, limit} = imports.metadata.plugins.achievements.inputs({data, q, account}) let {threshold, secrets, only, ignored, limit, display} = imports.metadata.plugins.achievements.inputs({data, q, account})
//Initialization //Initialization
const list = [] const list = []
@@ -26,13 +26,14 @@ export default async function({login, q, imports, data, computed, graphql, queri
.filter(a => !ignored.includes(a.title.toLocaleLowerCase())) .filter(a => !ignored.includes(a.title.toLocaleLowerCase()))
.sort((a, b) => (order[b.rank] + b.progress * 0.99) - (order[a.rank] + a.progress * 0.99)) .sort((a, b) => (order[b.rank] + b.progress * 0.99) - (order[a.rank] + a.progress * 0.99))
.map(({title, unlock, ...achievement}) => ({ .map(({title, unlock, ...achievement}) => ({
title:({S:`Master ${title.toLocaleLowerCase()}`, A:`Super ${title.toLocaleLowerCase()}`, B:`Great ${title.toLocaleLowerCase()}`}[achievement.rank] ?? title), prefix:({S:"Master", A:"Super", B:"Great"}[achievement.rank] ?? ""),
title,
unlock:!/invalid date/i.test(unlock) ? `${imports.format.date(unlock, {timeStyle:"short"})} on ${imports.format.date(unlock, {dateStyle:"short"})}` : null, unlock:!/invalid date/i.test(unlock) ? `${imports.format.date(unlock, {timeStyle:"short"})} on ${imports.format.date(unlock, {dateStyle:"short"})}` : null,
...achievement, ...achievement,
})) }))
.map(({icon, ...achievement}) => ({icon:icon.replace(/#primary/g, colors[achievement.rank][0]).replace(/#secondary/g, colors[achievement.rank][1]), ...achievement})) .map(({icon, ...achievement}) => ({icon:icon.replace(/#primary/g, colors[achievement.rank][0]).replace(/#secondary/g, colors[achievement.rank][1]), ...achievement}))
.slice(0, limit || Infinity) .slice(0, limit || Infinity)
return {list:achievements} return {list:achievements, display}
} }
//Handle errors //Handle errors
catch (error) { catch (error) {

View File

@@ -31,6 +31,15 @@ inputs:
type: boolean type: boolean
default: yes default: yes
# Achievements display style
plugin_achievements_display:
description: Achievements display style
type: string
default: normal
values:
- normal # Normal display
- compact # Compact display (only icon, name and value are displayed)
# Number of achievements events to display # Number of achievements events to display
# Set to 0 to disable limitations # Set to 0 to disable limitations
plugin_achievements_limit: plugin_achievements_limit:

View File

@@ -5,14 +5,14 @@
Achievements Achievements
</h2> </h2>
<div class="row"> <div class="row">
<section class="largeable-flex-wrap"> <section class="achievements <%= plugins.achievements?.display ?? "" %> largeable-flex-wrap">
<% if (plugins.achievements.error) { %> <% if (plugins.achievements.error) { %>
<div class="field 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="M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z"></path></svg>
<%= plugins.achievements.error.message %> <%= plugins.achievements.error.message %>
</div> </div>
<% } else { %> <% } else { %>
<% for (const {title, text, icon, rank, leaderboard = null, progress = 0, unlock = null} of plugins.achievements.list) { %> <% for (const {prefix, title, text, icon, rank, value, leaderboard = null, progress = 0, unlock = null} of plugins.achievements.list) { %>
<div class="achievement <%= rank === "$" ? "secret" : rank.charAt(0).toLocaleLowerCase() %> largeable-width-half"> <div class="achievement <%= rank === "$" ? "secret" : rank.charAt(0).toLocaleLowerCase() %> largeable-width-half">
<div class="icon"> <div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" height="44" width="44"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" height="44" width="44">
@@ -32,12 +32,19 @@
</div> </div>
<div class="info"> <div class="info">
<div class="title"> <div class="title">
<%= title %> <span class="prefix"><%= prefix %></span> <%= prefix.length ? title.toLocaleLowerCase() : title %>
<% if (leaderboard) { %> <% if (leaderboard) { %>
<span class="gh"> <span class="gh">
ranked <%= f(leaderboard.user) %> out of <%= f(leaderboard.total) %> <%= leaderboard.type %> ranked <%= f(leaderboard.user) %> out of <%= f(leaderboard.total) %> <%= leaderboard.type %>
</span> </span>
<% } %> <% } %>
<% if (plugins.achievements.display === "compact") { %>
<div class="value-wrapper">
<div class="value">
<%= typeof value === "number" ? Math.floor(value) : value ? "☆" : "?" %>
</div>
</div>
<% } %>
</div> </div>
<div class="text"><%= text %></div> <div class="text"><%= text %></div>
</div> </div>

View File

@@ -1004,37 +1004,55 @@
.achievement .gauge.info { .achievement .gauge.info {
color: #58A6FF; color: #58A6FF;
} }
.achievement .value {
background-color: #58A6FF26;
}
.achievement.x .title { .achievement.x .title {
color: #666666; color: #666666;
} }
.achievement.x .gauge.info { .achievement.x .gauge.info {
color: #B0B0B0; color: #B0B0B0;
} }
.achievement.x .value {
background-color: #B0B0B026;
}
.achievement.b .title { .achievement.b .title {
color: #9D8FFF; color: #9D8FFF;
} }
.achievement.b .gauge.info { .achievement.b .gauge.info {
color: #9E91FF; color: #9E91FF;
} }
.achievement.b .value {
background-color: #9E91FF26;
}
.achievement.a .title { .achievement.a .title {
color: #D79533; color: #D79533;
} }
.achievement.a .gauge.info { .achievement.a .gauge.info {
color: #E7BD69; color: #E7BD69;
} }
.achievement.a .value {
background-color: #E7BD6926;
}
.achievement.s .title { .achievement.s .title {
color: #EB355E; color: #EB355E;
} }
.achievement.s .gauge.info { .achievement.s .gauge.info {
color: #EB355E; color: #EB355E;
} }
.achievement.s .value {
background-color: #EB355E26;
}
.achievement.secret .title{ .achievement.secret .title{
color: #FF76CD; color: #FF76CD;
} }
.achievement.secret .gauge.info { .achievement.secret .gauge.info {
color: #FF79D1; color: #FF79D1;
} }
.achievement .gh { .achievement.secret .value {
background-color: #FF79D126;
}
.achievement .gh, .achievement .value {
border: 1px solid currentColor; border: 1px solid currentColor;
border-radius: 16px; border-radius: 16px;
font-size: 10px; font-size: 10px;
@@ -1044,6 +1062,44 @@
.achievement .gauge-base, .achievement .gauge-arc { .achievement .gauge-base, .achievement .gauge-arc {
stroke-width: 6; stroke-width: 6;
} }
.achievement .value-wrapper {
margin-bottom: -50px;
margin-top: 36px;
display: none;
position: relative;
}
.achievement .value {
margin-left: 46px;
}
.achievements.compact {
display: flex;
flex-wrap: wrap;
}
.achievements.compact .achievement {
flex-direction: column-reverse;
align-items: center;
width: 80px;
}
.achievements.compact .info {
width: 100%;
}
.achievements.compact .achievement .title {
margin-bottom: 2px;
text-transform: capitalize;
text-align: center;
}
.achievements.compact .achievement .title .prefix {
min-height: 13px;
font-size: 10px;
display: block;
margin-bottom: -.25rem;
}
.achievements.compact .achievement .value-wrapper {
display: flex;
}
.achievements.compact .achievement .text, .achievements.compact .achievement .gh {
display: none;
}
/* RSS feed */ /* RSS feed */
.rss { .rss {