Skip to content

Commit 9395df8

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 coala#257
1 parent 174152a commit 9395df8

File tree

9 files changed

+243
-144
lines changed

9 files changed

+243
-144
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',

data/migrations/0005_contributor_location.py

-18
This file was deleted.

data/migrations/0006_auto_20190615_1331.py

-18
This file was deleted.

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

+71-75
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,69 @@
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_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+
contributors = Contributor.objects.filter(login=username)
40+
if contributors.exists():
41+
contrib = contributors.first()
42+
student['url'] = STUDENT_URL.format(org_id=org_id,
43+
student_id=student_id)
44+
student['name'] = contrib.name
45+
student['bio'] = contrib.bio
46+
student['public_repos'] = contrib.public_repos
47+
student['public_gists'] = contrib.public_gists
48+
student['followers'] = contrib.followers
49+
data['students'].append(student)
50+
else:
51+
logger.warning("GCI Student {} doesn't exists! Please check"
52+
' the username.'.format(username))
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.

0 commit comments

Comments
 (0)