Skip to content

Commit 6bc955e

Browse files
committed
gci/: Redesign gci students web-page
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
1 parent 8323939 commit 6bc955e

File tree

8 files changed

+252
-109
lines changed

8 files changed

+252
-109
lines changed

community/urls.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from django.conf import settings
88

99
from community.views import HomePageView
10-
from gci.views import index as gci_index
10+
from gci.views import GCIStudentsList
1111
from gci.feeds import LatestTasksFeed as gci_tasks_rss
1212
from ci_build.view_log import BuildLogsView
1313
from data.views import index as contributors_index
@@ -85,7 +85,7 @@ def get_organization():
8585
distill_file='gci/tasks/rss.xml',
8686
),
8787
distill_url(
88-
r'gci/', gci_index,
88+
r'gci/', GCIStudentsList.as_view(),
8989
name='community-gci',
9090
distill_func=get_index,
9191
distill_file='gci/index.html',

gci/urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
from . import views
44

55
urlpatterns = [
6-
url(r'^$', views.index, name='index'),
6+
url(r'^$', views.GCIStudentsList.as_view(), name='index'),
77
]

gci/views.py

Lines changed: 80 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
from django.http import HttpResponse
21
from datetime import datetime
32
from calendar import timegm
3+
44
import logging
5-
import requests
65

6+
from django.views.generic import TemplateView
7+
8+
from community.views import get_header_and_footer
9+
from data.models import Contributor
710
from .students import get_linked_students
8-
from .gitorg import get_logo
911
from .task import get_tasks
1012

1113
STUDENT_URL = (
@@ -15,75 +17,78 @@
1517
)
1618

1719

18-
def index(request):
19-
logger = logging.getLogger(__name__ + '.index')
20-
try:
21-
get_tasks()
22-
except FileNotFoundError:
23-
logger.info('GCI data not available')
24-
s = ['GCI data not available']
25-
else:
26-
s = gci_overview()
27-
28-
return HttpResponse('\n'.join(s))
29-
30-
31-
def gci_overview():
32-
logger = logging.getLogger(__name__ + '.gci_overview')
33-
linked_students = list(get_linked_students())
34-
if not linked_students:
35-
logger.info('No GCI students are linked')
36-
return ['No GCI students are linked']
37-
38-
org_id = linked_students[0]['organization_id']
39-
org_name = linked_students[0]['organization_name']
40-
s = []
41-
s.append('<link rel="stylesheet" href="static/main.css">')
42-
43-
favicon = get_logo(org_name, 16)
44-
with open('_site/favicon.png', 'wb') as favicon_file:
45-
favicon_file.write(favicon)
46-
47-
org_logo = get_logo(org_name)
48-
with open('_site/org_logo.png', 'wb') as org_logo_file:
49-
org_logo_file.write(org_logo)
50-
51-
s.append('<link rel="shortcut icon" type="image/png" '
52-
'href="static/favicon.png"/>')
53-
s.append('<img src="static/org_logo.png" alt="'+org_name+'">')
54-
s.append('<h2>Welcome</h2>')
55-
s.append('Hello, world. You are at the {org_name} community GCI website.'
56-
.format(org_name=org_name))
57-
s.append('Students linked to %s issues:<ul class="students">' % org_name)
58-
for student in linked_students:
59-
student_id = student['id']
60-
username = student['username']
61-
62-
r = requests.get('https://api.github.com/users/{}'.format(username))
63-
64-
if r.status_code == 404:
65-
continue
66-
67-
student_url = STUDENT_URL.format(org_id=org_id,
68-
student_id=student_id,
69-
)
70-
s.append('<li class="student">'
71-
'STUDENT ID: <a href="{student_url}">{student_id}</a><br />'
72-
'<div class="github-card" data-github="{username}" '
73-
'data-width="400" data-theme="default"></div>'
74-
.format(student_url=student_url, student_id=student_id,
75-
username=username))
76-
77-
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
78-
s.append('</ul><i id="time" class="timestamp" data-time="{unix}">'
79-
'Last updated: {timestamp} '
80-
'(<span id="ago" class="timeago"></span>)</i>'
81-
.format(unix=timegm(datetime.utcnow().utctimetuple()),
82-
timestamp=timestamp))
83-
84-
s.append('<script src="//cdn.jsdelivr.net/gh/lepture/[email protected]'
85-
'/jsdelivr/widget.js"></script>')
86-
s.append('<script src="static/timeago.js"></script>')
87-
s.append('<script>loadTimeElements()</script>')
88-
89-
return s
20+
class GCIStudentsList(TemplateView):
21+
template_name = 'gci_students.html'
22+
23+
def get_data_updated_time(self):
24+
return timegm(datetime.utcnow().utctimetuple())
25+
26+
def get_all_students(self):
27+
"""
28+
Get all GCI students by filtering the tasks that are valid
29+
:return: A List of all students dict having necessary information
30+
about the student
31+
"""
32+
logger = logging.getLogger(__name__ + '.gci_overview')
33+
linked_students = list(get_linked_students())
34+
data = {
35+
'students': list(),
36+
'error': None
37+
}
38+
if not linked_students:
39+
error_message = 'No GCI students are linked'
40+
logger.info(error_message)
41+
data['error'] = error_message
42+
return data
43+
org_id = linked_students[0]['organization_id']
44+
for student in linked_students:
45+
student_id = student['id']
46+
username = student['username']
47+
contributors = Contributor.objects.filter(login=username)
48+
if contributors:
49+
contrib = contributors.first()
50+
student['url'] = STUDENT_URL.format(org_id=org_id,
51+
student_id=student_id)
52+
student['name'] = contrib.name
53+
student['bio'] = contrib.bio
54+
student['public_repos'] = contrib.public_repos
55+
student['public_gists'] = contrib.public_gists
56+
student['followers'] = contrib.followers
57+
data['students'].append(student)
58+
else:
59+
logger.warning(f"GCI Student {username} doesn't exists!"
60+
f' Please check the username.')
61+
return data
62+
63+
def get_gci_tasks_and_students(self):
64+
"""
65+
Get all GCI students by fetching the GCI tasks and the students
66+
:return: A list of all GCI Students
67+
"""
68+
logger = logging.getLogger(__name__ + '.index')
69+
gci_students = {
70+
'data': {},
71+
'error': None
72+
}
73+
try:
74+
get_tasks()
75+
except FileNotFoundError:
76+
logger.info('GCI data not available')
77+
error_message = ('No GCI data is available. Please create a'
78+
' tasks.yaml file having GCI tasks related'
79+
' data in it.')
80+
gci_students['error'] = error_message
81+
else:
82+
data = self.get_all_students()
83+
if data['error']:
84+
gci_students['error'] = data['error']
85+
else:
86+
gci_students['data'] = data['students']
87+
return gci_students
88+
89+
def get_context_data(self, **kwargs):
90+
context = super().get_context_data(**kwargs)
91+
context = get_header_and_footer(context)
92+
context['gci_students'] = self.get_gci_tasks_and_students()
93+
context['updated_time'] = self.get_data_updated_time()
94+
return context

static/css/gci_students.css

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
.data-fetch-error {
2+
padding: 20px 20px 0 20px;
3+
}
4+
5+
.gci-students {
6+
padding: 2% 2%;
7+
}
8+
9+
.gci-students .student-card {
10+
box-shadow: 0 0 25px 2px black;
11+
background-color: #c7da99;
12+
font-size: large;
13+
border: 4px #6c9a55 solid;
14+
}
15+
16+
17+
.gci-students .student-image {
18+
align-items: normal;
19+
}
20+
21+
.gci-students .student-details {
22+
width: 100%;
23+
}
24+
25+
@media only screen and (min-width: 768px) {
26+
.gci-students .student-card {
27+
width: 45%;
28+
height: 300px;
29+
overflow-y: auto;
30+
}
31+
}
32+
33+
.participated-year,
34+
.gci-student-id,
35+
.public-repos,
36+
.public-gists,
37+
.followers {
38+
color: #37474f;
39+
font-weight: bold;
40+
padding-right: 3px;
41+
}
42+
43+
.web-page-details {
44+
width: 100%;
45+
}
46+
47+
.web-page-description,
48+
.data-updated-time,
49+
.data-fetch-error {
50+
text-align: center;
51+
font-size: large;
52+
}

static/js/timeago.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
$(document).ready(function(){
2+
function generateTimeString(timestamp) {
3+
var sec = ((new Date()).getTime() / 1000) - parseInt(timestamp);
4+
var min = sec / 60;
5+
var hour = min / 60;
6+
var day = hour / 24;
7+
8+
var timeString = '';
9+
if (day >= 1) {
10+
timeString = Math.round(day) + ' days ago';
11+
} else if (hour >= 1) {
12+
timeString = Math.round(hour) + ' hours ago';
13+
} else if (min >= 1) {
14+
timeString = Math.round(min) + ' minutes ago';
15+
} else {
16+
timeString = Math.round(sec) + ' seconds ago';
17+
}
18+
19+
return timeString;
20+
}
21+
22+
function updateTimeAgo(time) {
23+
time.text(" " + generateTimeString(time.attr('data-time')));
24+
}
25+
26+
function loadTimeElements() {
27+
updateTimeAgo($('#time'));
28+
}
29+
30+
loadTimeElements();
31+
});

static/timeago.js

Lines changed: 0 additions & 30 deletions
This file was deleted.

templates/base.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
<li><a href="{% url 'community-gci' %}">Google Code-in Students</a></li>
6565
<li><a href="{% url 'inactive_issues_json' %}" title="List of all the issues on organization's main repository on which assignee has not shown any activity for more than 2 months.">Inactive issues</a></li>
6666
<li><a href="{% url 'unassigned_issues_activity_json' %}" title="List of all the issues on organization main repository on which someone has opened a pull request without getting assigned to it.">Unassigned issues activity</a></li>
67-
<li><a href="#">Newcomer issues</a></li>
6867
<li><a href="{% url 'ci_build' %}">Project CI Build</a></li>
6968
{% if isTravis %}
7069
<li><a href="{{ travisLink }}" title="This website was built automatically using Travis CI.">TravisCI build info</a></li>

0 commit comments

Comments
 (0)