Skip to content

Commit 23442d7

Browse files
committed
gci/: Redesign the 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 #257
1 parent 4c67a2a commit 23442d7

File tree

7 files changed

+245
-110
lines changed

7 files changed

+245
-110
lines changed

community/urls.py

+2-2
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 twitter.view_twitter import index as twitter_index
1313
from ci_build.view_log import BuildLogsView
@@ -86,7 +86,7 @@ def get_organization():
8686
distill_file='gci/tasks/rss.xml',
8787
),
8888
distill_url(
89-
r'gci/', gci_index,
89+
r'gci/', GCIStudentsList.as_view(),
9090
name='community-gci',
9191
distill_func=get_index,
9292
distill_file='gci/index.html',

gci/urls.py

+1-1
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

+73-77
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,85 @@
1-
from django.http import HttpResponse
21
from datetime import datetime
32
from calendar import timegm
43
import logging
5-
import requests
4+
from github import Github
5+
from github.GithubException import UnknownObjectException
6+
from django.views.generic import TemplateView
67

8+
from community.views import get_header_and_footer
79
from .students import get_linked_students
8-
from .gitorg import get_logo
910
from .task import get_tasks
1011

1112
STUDENT_URL = (
1213
'https://codein.withgoogle.com/dashboard/task-instances/?'
1314
'sp-organization={org_id}&sp-claimed_by={student_id}'
1415
'&sp-order=-modified&sp-my_tasks=false&sp-page_size=20'
1516
)
16-
17-
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
17+
GITHUB_OBJ = Github()
18+
19+
20+
class GCIStudentsList(TemplateView):
21+
template_name = 'gci_students.html'
22+
23+
def get_all_students(self):
24+
logger = logging.getLogger(__name__ + '.gci_overview')
25+
linked_students = list(get_linked_students())
26+
data = {
27+
'students': list(),
28+
'error': None
29+
}
30+
if not linked_students:
31+
error_message = 'No GCI students are linked'
32+
logger.info(error_message)
33+
data['error'] = error_message
34+
return data
35+
org_id = linked_students[0]['organization_id']
36+
for student in linked_students:
37+
student_id = student['id']
38+
username = student['username']
39+
try:
40+
user_obj = GITHUB_OBJ.get_user(username)
41+
except UnknownObjectException:
42+
logger.warning('GCI Student {} doesn\'t exists! Please check'
43+
' the username.'.format(username))
44+
else:
45+
student['url'] = STUDENT_URL.format(org_id=org_id,
46+
student_id=student_id)
47+
student['name'] = user_obj.name
48+
student['bio'] = user_obj.bio
49+
student['public_repos'] = user_obj.public_repos
50+
student['public_gists'] = user_obj.public_gists
51+
student['followers'] = user_obj.followers
52+
data['students'].append(student)
53+
return data
54+
55+
def get_gci_tasks_and_students(self):
56+
logger = logging.getLogger(__name__ + '.index')
57+
gci_students = {
58+
'data': {},
59+
'error': None
60+
}
61+
try:
62+
get_tasks()
63+
except FileNotFoundError:
64+
logger.info('GCI data not available')
65+
error_message = ('No GCI data is available. Please create a'
66+
' tasks.yaml file containing GCI tasks related'
67+
' data in it.')
68+
gci_students['error'] = error_message
69+
else:
70+
data = self.get_all_students()
71+
if data['error']:
72+
gci_students['error'] = data['error']
73+
else:
74+
gci_students['data'] = data['students']
75+
return gci_students
76+
77+
def get_data_updated_time(self):
78+
return timegm(datetime.utcnow().utctimetuple())
79+
80+
def get_context_data(self, **kwargs):
81+
context = super().get_context_data(**kwargs)
82+
context = get_header_and_footer(context)
83+
context['gci_students'] = self.get_gci_tasks_and_students()
84+
context['updated_time'] = self.get_data_updated_time()
85+
return context

static/css/gci_students.css

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
.data-fetch-error {
2+
padding: 20px 20px 0px 20px;
3+
}
4+
5+
.gci-students {
6+
padding: 2% 2%;
7+
}
8+
9+
.gci-students .student-card {
10+
box-shadow: 0px 0px 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

+31
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

-30
This file was deleted.

templates/gci_students.html

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
{% extends 'base.html' %}
2+
{% load staticfiles %}
3+
{% block title %}
4+
Community | GCI Students
5+
{% endblock %}
6+
7+
{% block add_css_files %}
8+
<link rel="stylesheet" href="{% static 'css/gci_students.css' %}">
9+
{% endblock %}
10+
11+
{% block add_js_files %}
12+
<script src="{% static 'js/timeago.js' %}"></script>
13+
{% endblock %}
14+
15+
{% block main-content %}
16+
<div class="web-page-details apply-flex center-content">
17+
<h3 style="padding-right: 15px">~</h3>
18+
<h3 class="page-name">
19+
<img src="{{ org.logo_url }}" alt="{{ org.name }}">
20+
GCI Students
21+
</h3>
22+
<h3 style="padding-left: 15px">~</h3>
23+
</div>
24+
25+
<div class="apply-flex-center">
26+
<p class="container web-page-description">
27+
Hello, World! {{ org.name }} has been participating in GCI (Google Code-In) from last few years and will
28+
be participating in coming years too. Following are the GCI students who participated in GCI with {{ org.name }}
29+
organization.
30+
</p>
31+
</div>
32+
33+
{% if gci_students.data %}
34+
<div class="gci-students apply-flex evenly-spread-content custom-green-color-font">
35+
{% for student in gci_students.data %}
36+
<div class="student-card card horizontal">
37+
<div class="student-image card-image apply-flex">
38+
<img src="//github.com/{{ student.username }}.png/">
39+
</div>
40+
<div class="student-details card-content">
41+
<a class="user-name bold-text" href="//github.com/{{ student.username }}" target="_blank">
42+
{% if student.display_name %}
43+
{{ student.display_name }}
44+
{% else %}
45+
{{ student.username }}
46+
{% endif %}
47+
</a><br>
48+
{% if student.bio %}
49+
<p>{{ student.bio }}</p>
50+
{% endif %}{# if student.bio #}
51+
<div class="inline-contents">
52+
<p class="gci-student-id">ID:</p>
53+
<a href="{{ student.url }}" target="_blank"> {{ student.id }}</a>
54+
</div><br>
55+
<div class="inline-contents">
56+
<p class="participated-year">Participation year: {{ student.program_year }}</p>
57+
</div><br>
58+
<div class="inline-contents">
59+
<p class="public-repos">Repos:</p>
60+
<p> {{ student.public_repos }}</p>
61+
</div>
62+
<div class="inline-contents">
63+
<p class="public-gists">Gists:</p>
64+
<p> {{ student.public_gists }}</p>
65+
</div>
66+
<div class="inline-contents">
67+
<p class="followers">Followers:</p>
68+
<p> {{ student.followers }}</p>
69+
</div><br>
70+
</div>
71+
</div>
72+
{% endfor %}
73+
</div>
74+
{% else %}
75+
<div class="apply-flex center-content data-fetch-error">
76+
<h5><b>ERROR:</b></h5>
77+
<h5>{{ gci_students.error }}</h5>
78+
</div>
79+
{% endif %}{# if gci_students.data #}
80+
81+
<div class="apply-flex center-content data-updated-time">
82+
<b>GCI Students data was updated:</b>
83+
<p id="time" data-time="{{ updated_time }}"></p>
84+
</div>
85+
86+
{% endblock %}

0 commit comments

Comments
 (0)