Skip to content

Commit

Permalink
gci/: Redesign the GCI Students web-page
Browse files Browse the repository at this point in the history
The redesigned web-page displays the data
in a better UI/UX form with some additional
information to make it more interactive and
attractive.

Closes coala#257
  • Loading branch information
KVGarg committed Jul 31, 2019
1 parent c057999 commit 9020b08
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 110 deletions.
4 changes: 2 additions & 2 deletions community/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from django.conf import settings

from community.views import HomePageView
from gci.views import index as gci_index
from gci.views import GCIStudentsList
from gci.feeds import LatestTasksFeed as gci_tasks_rss
from twitter.view_twitter import index as twitter_index
from ci_build.view_log import BuildLogsView
Expand Down Expand Up @@ -86,7 +86,7 @@ def get_organization():
distill_file='gci/tasks/rss.xml',
),
distill_url(
r'gci/', gci_index,
r'gci/', GCIStudentsList.as_view(),
name='community-gci',
distill_func=get_index,
distill_file='gci/index.html',
Expand Down
2 changes: 1 addition & 1 deletion gci/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
from . import views

urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^$', views.GCIStudentsList.as_view(), name='index'),
]
150 changes: 73 additions & 77 deletions gci/views.py
Original file line number Diff line number Diff line change
@@ -1,89 +1,85 @@
from django.http import HttpResponse
from datetime import datetime
from calendar import timegm
import logging
import requests
from github import Github
from github.GithubException import UnknownObjectException
from django.views.generic import TemplateView

from community.views import get_header_and_footer
from .students import get_linked_students
from .gitorg import get_logo
from .task import get_tasks

STUDENT_URL = (
'https://codein.withgoogle.com/dashboard/task-instances/?'
'sp-organization={org_id}&sp-claimed_by={student_id}'
'&sp-order=-modified&sp-my_tasks=false&sp-page_size=20'
)


def index(request):
logger = logging.getLogger(__name__ + '.index')
try:
get_tasks()
except FileNotFoundError:
logger.info('GCI data not available')
s = ['GCI data not available']
else:
s = gci_overview()

return HttpResponse('\n'.join(s))


def gci_overview():
logger = logging.getLogger(__name__ + '.gci_overview')
linked_students = list(get_linked_students())
if not linked_students:
logger.info('No GCI students are linked')
return ['No GCI students are linked']

org_id = linked_students[0]['organization_id']
org_name = linked_students[0]['organization_name']
s = []
s.append('<link rel="stylesheet" href="static/main.css">')

favicon = get_logo(org_name, 16)
with open('_site/favicon.png', 'wb') as favicon_file:
favicon_file.write(favicon)

org_logo = get_logo(org_name)
with open('_site/org_logo.png', 'wb') as org_logo_file:
org_logo_file.write(org_logo)

s.append('<link rel="shortcut icon" type="image/png" '
'href="static/favicon.png"/>')
s.append('<img src="static/org_logo.png" alt="'+org_name+'">')
s.append('<h2>Welcome</h2>')
s.append('Hello, world. You are at the {org_name} community GCI website.'
.format(org_name=org_name))
s.append('Students linked to %s issues:<ul class="students">' % org_name)
for student in linked_students:
student_id = student['id']
username = student['username']

r = requests.get('https://api.github.com/users/{}'.format(username))

if r.status_code == 404:
continue

student_url = STUDENT_URL.format(org_id=org_id,
student_id=student_id,
)
s.append('<li class="student">'
'STUDENT ID: <a href="{student_url}">{student_id}</a><br />'
'<div class="github-card" data-github="{username}" '
'data-width="400" data-theme="default"></div>'
.format(student_url=student_url, student_id=student_id,
username=username))

timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
s.append('</ul><i id="time" class="timestamp" data-time="{unix}">'
'Last updated: {timestamp} '
'(<span id="ago" class="timeago"></span>)</i>'
.format(unix=timegm(datetime.utcnow().utctimetuple()),
timestamp=timestamp))

s.append('<script src="//cdn.jsdelivr.net/gh/lepture/[email protected]'
'/jsdelivr/widget.js"></script>')
s.append('<script src="static/timeago.js"></script>')
s.append('<script>loadTimeElements()</script>')

return s
GITHUB_OBJ = Github()


class GCIStudentsList(TemplateView):
template_name = 'gci_students.html'

def get_all_students(self):
logger = logging.getLogger(__name__ + '.gci_overview')
linked_students = list(get_linked_students())
data = {
'students': list(),
'error': None
}
if not linked_students:
error_message = 'No GCI students are linked'
logger.info(error_message)
data['error'] = error_message
return data
org_id = linked_students[0]['organization_id']
for student in linked_students:
student_id = student['id']
username = student['username']
try:
user_obj = GITHUB_OBJ.get_user(username)
except UnknownObjectException:
logger.warning('GCI Student {} doesn\'t exists! Please check'
' the username.'.format(username))
else:
student['url'] = STUDENT_URL.format(org_id=org_id,
student_id=student_id)
student['name'] = user_obj.name
student['bio'] = user_obj.bio
student['public_repos'] = user_obj.public_repos
student['public_gists'] = user_obj.public_gists
student['followers'] = user_obj.followers
data['students'].append(student)
return data

def get_gci_tasks_and_students(self):
logger = logging.getLogger(__name__ + '.index')
gci_students = {
'data': {},
'error': None
}
try:
get_tasks()
except FileNotFoundError:
logger.info('GCI data not available')
error_message = ('No GCI data is available. Please create a'
' tasks.yaml file containing GCI tasks related'
' data in it.')
gci_students['error'] = error_message
else:
data = self.get_all_students()
if data['error']:
gci_students['error'] = data['error']
else:
gci_students['data'] = data['students']
return gci_students

def get_data_updated_time(self):
return timegm(datetime.utcnow().utctimetuple())

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context = get_header_and_footer(context)
context['gci_students'] = self.get_gci_tasks_and_students()
context['updated_time'] = self.get_data_updated_time()
return context
52 changes: 52 additions & 0 deletions static/css/gci_students.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.data-fetch-error {
padding: 20px 20px 0px 20px;
}

.gci-students {
padding: 2% 2%;
}

.gci-students .student-card {
box-shadow: 0px 0px 25px 2px black;
background-color: #c7da99;
font-size: large;
border: 4px #6c9a55 solid;
}


.gci-students .student-image {
align-items: normal;
}

.gci-students .student-details {
width: 100%;
}

@media only screen and (min-width: 768px) {
.gci-students .student-card {
width: 45%;
height: 300px;
overflow-y: auto;
}
}

.participated-year,
.gci-student-id,
.public-repos,
.public-gists,
.followers {
color: #37474f;
font-weight: bold;
padding-right: 3px;
}

.web-page-details {
width: 100%;
}

.web-page-description,
.data-updated-time,
.data-fetch-error {
text-align: center;
font-size: large;
}
31 changes: 31 additions & 0 deletions static/js/timeago.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
$(document).ready(function(){
function generateTimeString(timestamp) {
var sec = ((new Date()).getTime() / 1000) - parseInt(timestamp);
var min = sec / 60;
var hour = min / 60;
var day = hour / 24;

var timeString = '';
if (day >= 1) {
timeString = Math.round(day) + ' days ago';
} else if (hour >= 1) {
timeString = Math.round(hour) + ' hours ago';
} else if (min >= 1) {
timeString = Math.round(min) + ' minutes ago';
} else {
timeString = Math.round(sec) + ' seconds ago';
}

return timeString;
}

function updateTimeAgo(time) {
time.text(" " + generateTimeString(time.attr('data-time')));
}

function loadTimeElements() {
updateTimeAgo($('#time'));
}

loadTimeElements();
});
30 changes: 0 additions & 30 deletions static/timeago.js

This file was deleted.

86 changes: 86 additions & 0 deletions templates/gci_students.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}
Community | GCI Students
{% endblock %}

{% block add_css_files %}
<link rel="stylesheet" href="{% static 'css/gci_students.css' %}">
{% endblock %}

{% block add_js_files %}
<script src="{% static 'js/timeago.js' %}"></script>
{% endblock %}

{% block main-content %}
<div class="web-page-details apply-flex center-content">
<h3 style="padding-right: 15px">~</h3>
<h3 class="page-name">
<img src="{{ org.logo_url }}" alt="{{ org.name }}">
GCI Students
</h3>
<h3 style="padding-left: 15px">~</h3>
</div>

<div class="apply-flex-center">
<p class="container web-page-description">
Hello, World! {{ org.name }} has been participating in GCI (Google Code-In) from last few years and will
be participating in coming years too. Following are the GCI students who participated in GCI with {{ org.name }}
organization.
</p>
</div>

{% if gci_students.data %}
<div class="gci-students apply-flex evenly-spread-content custom-green-color-font">
{% for student in gci_students.data %}
<div class="student-card card horizontal">
<div class="student-image card-image apply-flex">
<img src="//github.com/{{ student.username }}.png/">
</div>
<div class="student-details card-content">
<a class="user-name bold-text" href="//github.com/{{ student.username }}" target="_blank">
{% if student.display_name %}
{{ student.display_name }}
{% else %}
{{ student.username }}
{% endif %}
</a><br>
{% if student.bio %}
<p>{{ student.bio }}</p>
{% endif %}{# if student.bio #}
<div class="inline-contents">
<p class="gci-student-id">ID:</p>
<a href="{{ student.url }}" target="_blank"> {{ student.id }}</a>
</div><br>
<div class="inline-contents">
<p class="participated-year">Participation year: {{ student.program_year }}</p>
</div><br>
<div class="inline-contents">
<p class="public-repos">Repos:</p>
<p> {{ student.public_repos }}</p>
</div>
<div class="inline-contents">
<p class="public-gists">Gists:</p>
<p> {{ student.public_gists }}</p>
</div>
<div class="inline-contents">
<p class="followers">Followers:</p>
<p> {{ student.followers }}</p>
</div><br>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="apply-flex center-content data-fetch-error">
<h5><b>ERROR:</b></h5>
<h5>{{ gci_students.error }}</h5>
</div>
{% endif %}{# if gci_students.data #}

<div class="apply-flex center-content data-updated-time">
<b>GCI Students data was updated:</b>
<p id="time" data-time="{{ updated_time }}"></p>
</div>

{% endblock %}

0 comments on commit 9020b08

Please sign in to comment.