...
 
Commits (5)
.DS_Store
image: alpine:latest
pages:
stage: deploy
script:
- echo 'Nothing to do...'
artifacts:
paths:
- public
only:
- master
# gitlab-stat
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="GitLab activity analysis">
<meta name="author" content="Alexandr Musikhin">
<title>GitLab Stat</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.12.0/css/all.css" crossorigin="anonymous">
<link rel="icon" href="/favicon.png" sizes="32x32">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="GitLab Stat">
<meta name="twitter:description" content="GitLab activity analysis">
<meta name="twitter:image" content="//placehold.it/512?text=GitLab+Stat">
<meta property="og:site_name" content="GitLab Stat">
<meta property="og:title" content="Home">
<meta property="og:description" content="GitLab activity analysis">
<meta property="og:type" content="website">
<meta property="og:url" content="https://gitlab-stat.tophackr.com">
<meta property="og:image" content="//placehold.it/512?text=GitLab+Stat">
</head>
<body>
<div class="container-fluid container-md">
<nav class="navbar navbar-expand navbar-light flex-column flex-md-row my-4 px-0 d-none">
<a class="navbar-brand" href="/">
<i class="fab fa-gitlab fa-fw"></i>
GitLab Stat
</a>
<form onsubmit="isClick(); return false;" class="navbar-nav form-group row mx-auto mx-sm-0 ml-md-auto">
<span class="navbar-text col-form-label">gitlab.com/</span>
<div class="col">
<input id="search_first" class="form-control" type="text" placeholder="Search" aria-label="Search">
</div>
<button class="btn btn-outline-primary" type="button" onclick="isClick();">Search</button>
</form>
</nav><!-- /.navbar -->
<div id="loading" class="row align-items-center h-100">
<div class="col-md-12 text-center">
<i class="fas fa-circle-notch fa-fw fa-3x fa-spin text-primary"></i>
</div>
</div><!-- /#loading -->
<div id="main" class="row justify-content-center align-items-center h-100 d-none">
<div class="col-11 col-md-8 text-center">
<div class="d-none d-sm-block display-4 mb-4">
<i class="fab fa-gitlab fa-fw"></i>
GitLab Stat
</div>
<div class="d-block d-sm-none h2 mb-4">
<i class="fab fa-gitlab fa-fw"></i>
GitLab Stat
</div>
<form onsubmit="isClick(); return false;" class="form-group row">
<span class="col-form-label">gitlab.com/</span>
<div class="col">
<input id="search_second" class="form-control" type="text" placeholder="Search" aria-label="Search">
</div>
<button class="btn btn-outline-primary" type="button" onclick="isClick();">Search</button>
</form>
<div class="fixed-bottom my-5">
<i class="fas fa-code-branch fa-fw"></i>
Code on <a href="https://gitlab.com/tophackr/gitlab-stat">tophackr/gitlab-stat</a>
</div>
</div>
</div><!-- /#main -->
<div id="notfound" class="row align-items-center h-50 d-none">
<div class="col-md-12 text-center">
<div class="display-4">Page not found</div>
</div>
</div><!-- /#notfound -->
<div id="profile" class="row mb-4 d-none">
<div class="col-lg-4 mb-3">
<ul id="more" class="list-group">
<li class="list-group-item py-3">
<div class="row">
<div class="col-3">
<img id="avatar" class="img-fluid rounded">
</div>
<div class="col">
<a id="name" class="text-body h6 m-0">Not found</a>
<a id="blog"></a>
<span id="company"></span>
</div>
</div>
</li>
</ul>
</div><!-- /.col -->
<div class="col-lg-8">
<ul id="activities" class="list-group">
<h5 class="list-group-item m-0">Latest activities</h5>
</ul>
</div><!-- /.col -->
</div><!-- /#profile -->
</div><!-- /.container -->
<script src="js/config.js"></script>
<script async src="js/activities.js"></script>
<script src="js/function.js"></script>
</body>
</html>
\ No newline at end of file
public/favicon.png

236 Bytes

(async () => {
home.select('meta[property="og:url"]').content += `/${username}`;
if (username !== '') {
const response_preuser = await fetch(`https://gitlab.com/api/v4/users/?username=${username}`);
const json_preuser = await response_preuser.json();
if (json_preuser == '') {
home.select('#loading').classList.add('d-none');
home.select('#notfound').classList.remove('d-none');
home.select('.navbar').classList.add('d-flex');
home.select('.navbar').classList.remove('d-none');
return false;
}
let isUser;
json_preuser.forEach(user => {
isUser = user.id;
});
const response_user = await fetch(`https://gitlab.com/api/v4/users/${isUser}`);
const response_rep = await fetch(`https://gitlab.com/api/v4/users/${isUser}/projects?per_page=100`);
const response_event = await fetch(`https://gitlab.com/api/v4/users/${isUser}/events?order_by=created_at`);
const json_user = await response_user.json();
const json_rep = await response_rep.json();
const json_event = await response_event.json();
const gitSearchElement = home.select('#search_first');
const gitAvatarElement = home.select('#avatar');
const gitAvatarTwitter = home.select('meta[name="twitter:image"]');
const gitAvatarOG = home.select('meta[property="og:image"]');
const gitNameElement = home.select('#name');
const gitTitle = home.select('title');
const gitTitleTwitter = home.select('meta[name="twitter:title"]');
const gitTitleOG = home.select('meta[property="og:title"]');
const gitBlogElement = home.select('#blog');
const gitCompanyElement = home.select('#company');
const gitMoreElement = home.select('#more');
const gitDescription = home.select('meta[name="description"]');
const gitDescriptionTwitter = home.select('meta[name="twitter:description"]');
const gitDescriptionOG = home.select('meta[property="og:description"]');
const gitActivitiesElement = home.select('#activities');
let allStars = 0;
let allForks = 0;
json_rep.forEach(repo => {
allStars += repo.star_count;
allForks += repo.forks_count;
});
// username in search bar
gitSearchElement.value = json_user.username;
// avatar
gitAvatarElement.src = json_user.avatar_url;
gitAvatarTwitter.content = json_user.avatar_url;
gitAvatarOG.content = json_user.avatar_url;
gitNameElement.href = json_user.web_url; // url to name
if (json_user.name === '') { // login if name 'null'
gitNameElement.textContent = json_user.username;
gitTitle.textContent = `${json_user.username} | GitLab Stat`;
gitTitleTwitter.content = json_user.username;
gitTitleOG.content = json_user.username;
} else { // name
gitNameElement.textContent = json_user.name;
gitTitle.textContent = `${json_user.name} | GitLab Stat`;
gitTitleTwitter.content = json_user.name;
gitTitleOG.content = json_user.name;
}
// website url
if (json_user.website_url !== '') {
gitNameElement.innerHTML += '<br>';
gitBlogElement.href = json_user.website_url; // todo: fix for non http url
gitBlogElement.textContent = `${json_user.website_url.replace(/^(http:|https:)?\/*/i,"")}`;
}
// organization
if (json_user.organization !== '') {
if (json_user.website_url !== '')
gitBlogElement.innerHTML += '<br>';
else
gitNameElement.innerHTML += '<br>';
gitCompanyElement.className = `badge badge-primary`;
gitCompanyElement.innerHTML = `<i class="fas fa-users fa-fw mr-2"></i>${json_user.organization}`;
}
// bio
if (json_user.bio !== '') {
gitMoreElement.innerHTML += `<li class="list-group-item"><small class="text-muted">Bio:</small><p class="m-0">${json_user.bio}</p></li>`;
gitDescription.content = json_user.bio;
gitDescriptionTwitter.content = json_user.bio;
gitDescriptionOG.content = json_user.bio;
}
// counts
gitMoreElement.innerHTML += `
<li class="list-group-item d-flex flex-column">
<div><div class="float-left text-muted">Stars Received</div><div class="text-monospace float-right">${allStars}</div></div>
<div><div class="float-left text-muted">Forks by users</div><div class="text-monospace float-right">${allForks}</div></div>
</li>`;
// about (join date, location)
let gitAboutElement = `<small class="text-muted">Joined</small><p>${isDate(json_user.created_at)}</p>`;
if (json_user.location !== null)
gitAboutElement += `<small class="text-muted">Location</small><p class="text-primary">${json_user.location}</p>`;
gitMoreElement.innerHTML += `<li class="list-group-item">${gitAboutElement}</li>`;
// activities
let plusIcon, branchIcon, trashIcon, commentIcon;
plusIcon = `<i class="fas fa-plus-circle fa-fw text-success"></i>`;
branchIcon = `<i class="fas fa-code-branch fa-fw text-success"></i>`;
trashIcon = `<i class="fas fa-trash-alt fa-fw text-danger"></i>`;
commentIcon = `<i class="fas fa-comment-dots fa-fw text-muted"></i>`;
let eventid = [];
for (let activities of json_event) {
const response_event_rep = await fetch(`https://gitlab.com/api/v4/projects/${activities.project_id}`);
const json_event_rep = await response_event_rep.json();
repoURL = `<a href="${json_event_rep.web_url}">${json_event_rep.path_with_namespace}</a>`;
switch (activities.action_name) {
case "pushed to":
let commit = `commit`;
if (activities.push_data.commit_count > 1)
commit += "s";
isStr = `${plusIcon} Pushed <a href="https://gitlab.com/${json_event_rep.path_with_namespace}/commits/${activities.push_data.ref}">${activities.push_data.commit_count} ${commit}</a> to ${repoURL}`;
break;
case "created":
isStr = `${plusIcon} Created a repository ${repoURL}`;
break;
case "pushed new":
if (activities.push_data.ref_type === "branch")
isStr = branchIcon;
else
isStr = plusIcon;
isStr += ` Created a ${activities.push_data.ref_type} `;
if (activities.push_data.ref_type === "branch")
isStr += `<a href="${json_event_rep.web_url}/tree/${activities.push_data.ref}">${activities.push_data.ref}</a> in ${repoURL}`;
else
isStr += repoURL;
break;
case "opened":
if (activities.target_type === 'MergeRequest') {
isStr = branchIcon;
url = 'merge_request';
name = 'Merge Request';
} else {
isStr = plusIcon;
url = activities.target_type.toLowerCase();
name = activities.target_type.toLowerCase();
}
isStr += ` Opened an <a href="${json_event_rep.web_url}/${url}/${activities.target_iid}">${name}</a> in ${repoURL}`;
break;
case "closed":
if (activities.target_type === 'MergeRequest') {
url = 'merge_request';
name = 'Merge Request';
} else {
url = activities.target_type.toLowerCase();
name = activities.target_type.toLowerCase();
}
isStr = `${trashIcon} Closed an <a href="${json_event_rep.web_url}/${url}/${activities.target_iid}">${name}</a> in ${repoURL}`;
break;
case "accepted":
if (activities.target_type === 'MergeRequest') {
url = 'merge_request';
name = 'Merge Request';
} else {
url = activities.target_type.toLowerCase();
name = activities.target_type.toLowerCase();
}
isStr = `${plusIcon} Accepted an <a href="${json_event_rep.web_url}/${url}/${activities.target_iid}">${name}</a> in ${repoURL}`;
break;
case "commented on":
isStr = `${commentIcon} Created <a href="${json_event_rep.web_url}/${activities.note.noteable_type.toLowerCase()}/${activities.note.noteable_iid}#note_${activities.note.id}">a comment</a> on an issue in ${repoURL}`;
break;
case "deleted":
isStr = `${trashIcon} Deleted a ${activities.push_data.ref_type} ${activities.push_data.ref} from ${repoURL}`;
break;
default:
console.log(activities.action_name);
return false;
break;
}
gitActivitiesElement.innerHTML += `<li class="list-group-item"><div class="row"><div class="col-9">${isStr}</div><div class="col-3 text-muted text-right">${isTimeAgo(activities.created_at)}</div></div></li>`;
}
home.select('#loading').classList.add('d-none');
home.select('#profile').classList.remove('d-none');
home.select('.navbar').classList.add('d-flex');
home.select('.navbar').classList.remove('d-none');
}
})();
\ No newline at end of file
const home = {
select: document.querySelector.bind(document),
selectAll: document.querySelectorAll.bind(document)
};
const username = location.pathname.replace('/', '');
if (username === '') {
home.select('#loading').classList.add('d-none');
home.select('#main').classList.remove('d-none');
}
\ No newline at end of file
function isClick() {
if (home.select('#search_second').value !== '')
window.location = `/${home.select('#search_second').value}`;
else
window.location = `/${home.select('#search_first').value}`;
}
function isDate(d) {
return new Date(d).toLocaleDateString(['en'], {
month: "long",
day: "numeric",
year: "numeric"
});
}
function isTimeAgo(t) {
let current = new Date();
let previous = new Date(t);
var msPerMinute = 60 * 1000;
var msPerHour = msPerMinute * 60;
var msPerDay = msPerHour * 24;
var msPerMonth = msPerDay * 30;
var elapsed = current - previous;
if (elapsed < msPerMinute) {
return Math.round(elapsed / 1000) + " seconds ago";
} else if (elapsed < msPerHour) {
return Math.round(elapsed / msPerMinute) + " minutes ago";
} else if (elapsed < msPerDay) {
return Math.round(elapsed / msPerHour) + " hours ago";
} else if (elapsed < msPerMonth && Math.round(elapsed / msPerDay) <= 2) {
return Math.round(elapsed / msPerDay) + " days ago";
} else {
return previous.toLocaleDateString(['en'], {
month: "long",
day: "numeric"
});
}
}
\ No newline at end of file