зеркало из https://github.com/golang/build.git
247 строки
6.2 KiB
HTML
247 строки
6.2 KiB
HTML
<!DOCTYPE html>
|
|
<meta charset="utf-8">
|
|
<title>GopherCon 2017 Contribution Dashboard</title>
|
|
<meta name=viewport content="width=device-width,minimum-scale=1,maximum-scale=1">
|
|
<style>
|
|
* {
|
|
box-sizing: border-box;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
a:link,
|
|
a:visited {
|
|
color: #fff;
|
|
}
|
|
.Site {
|
|
background-color: #2a2a2a;
|
|
color: #fff;
|
|
display: flex;
|
|
flex-direction: column;
|
|
font: 14px 'Helvetica-Neue', Helvetica, sans-serif;
|
|
height: 100vh;
|
|
text-rendering: optimizeLegibility;
|
|
}
|
|
.Site-body {
|
|
display: flex;
|
|
flex: 1;
|
|
}
|
|
.Site-content {
|
|
border-right: 1px solid #3a3939;
|
|
overflow: hidden;
|
|
padding: 1.5em;
|
|
width: 60%;
|
|
}
|
|
.Site-activity {
|
|
background-color: #323232;
|
|
flex: 1;
|
|
overflow: scroll;
|
|
}
|
|
.Site-logo {
|
|
height: 60px;
|
|
margin-right: 2em;
|
|
}
|
|
.Site-pointsTitle,
|
|
.Site-points {
|
|
text-align: center;
|
|
}
|
|
.Site-pointsTitle {
|
|
font-size: 4vh;
|
|
letter-spacing: 1px;
|
|
text-transform: uppercase;
|
|
}
|
|
.Site-points {
|
|
font-size: 30vh;
|
|
}
|
|
.u-avatar {
|
|
border-radius: 50%;
|
|
}
|
|
.AvatarGroup {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: center;
|
|
}
|
|
.AvatarGroup-avatar {
|
|
height: 6vh;
|
|
margin: 0 .5em .5em 0;
|
|
width: 6vh;
|
|
}
|
|
.Activity {
|
|
align-items: flex-start;
|
|
background-color: #323232;
|
|
border-bottom: 1px solid #2d2d2d;
|
|
border-top: 1px solid #404040;
|
|
display: flex;
|
|
font-size: 2vw;
|
|
padding: 1em;
|
|
}
|
|
.Activity-avatar {
|
|
height: 2.5em;
|
|
margin-right: .75em;
|
|
width: 2.5em;
|
|
}
|
|
.Activity-main {
|
|
flex: 1;
|
|
margin-right: .15em;
|
|
}
|
|
.Activity-points {
|
|
color: #85ebf9;
|
|
font-size: .85em;
|
|
margin-top: .25em;
|
|
}
|
|
.Activity-icon {
|
|
font-size: 2em;
|
|
}
|
|
.Site-footer {
|
|
align-items: center;
|
|
background: #3a3737;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
padding: 1em 1.5em;
|
|
}
|
|
</style>
|
|
<body class="Site">
|
|
<div class="Site-body">
|
|
<main class="Site-content">
|
|
<div class="Site-pointsTitle">Total points</div>
|
|
<div class="Site-points js-totalPoints">0</div>
|
|
<div class="AvatarGroup js-avatarGroup"></div>
|
|
</main>
|
|
<aside class="Site-activity js-activityList"></aside>
|
|
</div>
|
|
<footer class="Site-footer">
|
|
<img class="Site-logo" src="https://github.com/ashleymcnamara/gophers/raw/master/GoCommunity.png" alt="Go Community">
|
|
<div>
|
|
Gopher artwork by <a href="https://github.com/ashleymcnamara/gophers" target="_blank">Ashley McNamara</a>
|
|
based on the original artwork by the amazing
|
|
<a href="https://reneefrench.blogspot.com/" target="_blank">Renee French</a>.
|
|
Licensed under a <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.</a>
|
|
</div>
|
|
</footer>
|
|
</body>
|
|
|
|
<template class="activityTemplate">
|
|
<div class="Activity">
|
|
<img class="u-avatar Activity-avatar js-avatar">
|
|
<div class="Activity-main">
|
|
<div class="Activity-body js-body"></div>
|
|
<div class="Activity-points js-points"></div>
|
|
</div>
|
|
<div class="Activity-icon js-icon"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
(function() {
|
|
'use strict';
|
|
|
|
const ActivityType = {
|
|
AMEND_CHANGE: 'AMEND_CHANGE',
|
|
CREATE_CHANGE: 'CREATE_CHANGE',
|
|
MERGE_CHANGE: 'MERGE_CHANGE',
|
|
REGISTER: 'REGISTER',
|
|
};
|
|
|
|
const iconMap = {};
|
|
iconMap.AMEND_CHANGE = '👍';
|
|
iconMap.CREATE_CHANGE = '👏';
|
|
iconMap.MERGE_CHANGE = '🤘';
|
|
iconMap.REGISTER = '🎉';
|
|
|
|
let lastUpdateMs = 0;
|
|
getActivities(lastUpdateMs);
|
|
startUpdateLoop();
|
|
|
|
function getActivities(since) {
|
|
const url = `/_/activities?since=${since}`;
|
|
fetch(url).then(resp => {
|
|
resp.json().then(obj => {
|
|
processAll(obj.activities);
|
|
updatePoints(obj.totalPoints);
|
|
});
|
|
}).catch(err => {
|
|
console.error(err);
|
|
});
|
|
}
|
|
|
|
function startUpdateLoop() {
|
|
window.setInterval(() => {
|
|
getActivities(lastUpdateMs);
|
|
}, 5000);
|
|
}
|
|
|
|
// Username => img element.
|
|
let avatarMap = {};
|
|
|
|
function processAll(activities) {
|
|
const activityListEl = document.querySelector('.js-activityList');
|
|
const avatarGroupEl = document.querySelector('.js-avatarGroup');
|
|
activities.forEach(activity => {
|
|
if (!avatarMap[activity.gitHubUser]) {
|
|
const el = createAvatarEl(activity.gitHubUser);
|
|
el.classList.add('AvatarGroup-avatar');
|
|
avatarMap[activity.gitHubUser] = el;
|
|
}
|
|
avatarGroupEl.insertBefore(avatarMap[activity.gitHubUser],
|
|
avatarGroupEl.firstChild);
|
|
const activityEl = createActivityEl(activity);
|
|
activityListEl.insertBefore(activityEl, activityListEl.firstChild);
|
|
});
|
|
if (activities.length > 0) {
|
|
lastUpdateMs = new Date(activities[activities.length - 1].created).getTime();
|
|
}
|
|
}
|
|
|
|
function updatePoints(points) {
|
|
document.querySelector('.js-totalPoints').textContent = points;
|
|
}
|
|
|
|
function createAvatarEl(username) {
|
|
let img = document.createElement('IMG');
|
|
img.classList.add('u-avatar');
|
|
img.src = avatarSrc(username);
|
|
img.alt = avatarAlt(username);
|
|
return img;
|
|
}
|
|
|
|
function avatarSrc(username) {
|
|
return `https://github.com/${encodeURIComponent(username)}.png?size=100`;
|
|
}
|
|
|
|
function avatarAlt(username) {
|
|
return `Avatar for ${username}`;
|
|
}
|
|
|
|
function activityBody(type, username) {
|
|
switch (type) {
|
|
case ActivityType.AMEND_CHANGE:
|
|
return `${username} just amended a change!`;
|
|
|
|
case ActivityType.CREATE_CHANGE:
|
|
return `${username} just created a change!`;
|
|
|
|
case ActivityType.MERGE_CHANGE:
|
|
return `${username} just merged a change!`;
|
|
|
|
case ActivityType.REGISTER:
|
|
return `${username} just registered!`;
|
|
}
|
|
}
|
|
|
|
function pointsStr(points) {
|
|
return `+${points} Point` + (points > 1 ? 's' : '');
|
|
}
|
|
|
|
function createActivityEl(activity) {
|
|
const tmpl = document.querySelector('.activityTemplate');
|
|
const imgEl = tmpl.content.querySelector('.js-avatar');
|
|
imgEl.src = avatarSrc(activity.gitHubUser);
|
|
imgEl.alt = avatarAlt(activity.gitHubUser);
|
|
tmpl.content.querySelector('.js-icon').textContent = iconMap[activity.type];
|
|
tmpl.content.querySelector('.js-body').textContent =
|
|
activityBody(activity.type, activity.gitHubUser);
|
|
tmpl.content.querySelector('.js-points').textContent =
|
|
pointsStr(activity.points);
|
|
return document.importNode(tmpl.content, true);
|
|
}
|
|
})();
|
|
</script> |