From ea6567163a5deaa6caec11ffcbc225646d561631 Mon Sep 17 00:00:00 2001 From: kvgarg Date: Wed, 12 Jun 2019 16:12:07 +0530 Subject: [PATCH] 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 https://github.com/coala/community/issues/257 --- community/urls.py | 4 +- gci/urls.py | 2 +- gci/views.py | 155 +++++++++++++++++++----------------- static/css/gci_students.css | 52 ++++++++++++ static/js/timeago.js | 31 ++++++++ static/timeago.js | 30 ------- templates/base.html | 1 - templates/gci_students.html | 86 ++++++++++++++++++++ 8 files changed, 252 insertions(+), 109 deletions(-) create mode 100644 static/css/gci_students.css create mode 100644 static/js/timeago.js delete mode 100644 static/timeago.js create mode 100644 templates/gci_students.html diff --git a/community/urls.py b/community/urls.py index a02a1971..9336b685 100644 --- a/community/urls.py +++ b/community/urls.py @@ -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 ci_build.view_log import BuildLogsView from data.views import index as contributors_index @@ -85,7 +85,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', diff --git a/gci/urls.py b/gci/urls.py index a3780aa2..10e10974 100644 --- a/gci/urls.py +++ b/gci/urls.py @@ -3,5 +3,5 @@ from . import views urlpatterns = [ - url(r'^$', views.index, name='index'), + url(r'^$', views.GCIStudentsList.as_view(), name='index'), ] diff --git a/gci/views.py b/gci/views.py index e9c97589..ceed5c12 100644 --- a/gci/views.py +++ b/gci/views.py @@ -1,11 +1,13 @@ -from django.http import HttpResponse from datetime import datetime from calendar import timegm + import logging -import requests +from django.views.generic import TemplateView + +from community.views import get_header_and_footer +from data.models import Contributor from .students import get_linked_students -from .gitorg import get_logo from .task import get_tasks STUDENT_URL = ( @@ -15,75 +17,78 @@ ) -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('') - - 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('') - s.append(''+org_name+'') - s.append('

Welcome

') - 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:' - 'Last updated: {timestamp} ' - '()' - .format(unix=timegm(datetime.utcnow().utctimetuple()), - timestamp=timestamp)) - - s.append('') - s.append('') - s.append('') - - return s +class GCIStudentsList(TemplateView): + template_name = 'gci_students.html' + + def get_data_updated_time(self): + return timegm(datetime.utcnow().utctimetuple()) + + def get_all_students(self): + """ + Get all GCI students by filtering the tasks that are valid + :return: A List of all students dict having necessary information + about the student + """ + 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'] + contributors = Contributor.objects.filter(login=username) + if contributors: + contrib = contributors.first() + student['url'] = STUDENT_URL.format(org_id=org_id, + student_id=student_id) + student['name'] = contrib.name + student['bio'] = contrib.bio + student['public_repos'] = contrib.public_repos + student['public_gists'] = contrib.public_gists + student['followers'] = contrib.followers + data['students'].append(student) + else: + logger.warning(f"GCI Student {username} doesn't exists!" + f' Please check the username.') + return data + + def get_gci_tasks_and_students(self): + """ + Get all GCI students by fetching the GCI tasks and the students + :return: A list of all GCI Students + """ + 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 having 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_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 diff --git a/static/css/gci_students.css b/static/css/gci_students.css new file mode 100644 index 00000000..a1a2c3e0 --- /dev/null +++ b/static/css/gci_students.css @@ -0,0 +1,52 @@ +.data-fetch-error { + padding: 20px 20px 0 20px; +} + +.gci-students { + padding: 2% 2%; +} + +.gci-students .student-card { + box-shadow: 0 0 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; +} diff --git a/static/js/timeago.js b/static/js/timeago.js new file mode 100644 index 00000000..1e214994 --- /dev/null +++ b/static/js/timeago.js @@ -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(); +}); \ No newline at end of file diff --git a/static/timeago.js b/static/timeago.js deleted file mode 100644 index d6285487..00000000 --- a/static/timeago.js +++ /dev/null @@ -1,30 +0,0 @@ -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, ago) { - ago.innerHTML = generateTimeString(time.getAttribute('data-time')); -} - -function loadTimeElements() { - var time = document.getElementById('time'); - var ago = document.getElementById('ago'); - - updateTimeAgo(time, ago); -} diff --git a/templates/base.html b/templates/base.html index 9638dfdc..97059a89 100644 --- a/templates/base.html +++ b/templates/base.html @@ -64,7 +64,6 @@
  • Google Code-in Students
  • Inactive issues
  • Unassigned issues activity
  • -
  • Newcomer issues
  • Project CI Build
  • {% if isTravis %}
  • TravisCI build info
  • diff --git a/templates/gci_students.html b/templates/gci_students.html new file mode 100644 index 00000000..8c969fd7 --- /dev/null +++ b/templates/gci_students.html @@ -0,0 +1,86 @@ +{% extends 'base.html' %} +{% load staticfiles %} +{% block title %} + Community | GCI Students +{% endblock %} + +{% block add_css_files %} + +{% endblock %} + +{% block add_js_files %} + +{% endblock %} + +{% block main-content %} +
    +

    ~

    +

    + {{ org.name }} + GCI Students +

    +

    ~

    +
    + +
    +

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

    +
    + + {% if gci_students.data %} +
    + {% for student in gci_students.data %} +
    +
    + +
    +
    + + {% if student.display_name %} + {{ student.display_name }} + {% else %} + {{ student.username }} + {% endif %} +
    + {% if student.bio %} +

    {{ student.bio }}

    + {% endif %}{# if student.bio #} +
    +
    +

    Participation year: {{ student.program_year }}

    +

    +
    +

    Repos:

    +

    {{ student.public_repos }}

    +
    +
    +

    Gists:

    +

    {{ student.public_gists }}

    +
    +
    +

    Followers:

    +

    {{ student.followers }}

    +

    +
    +
    + {% endfor %} +
    + {% else %} +
    +
    ERROR:
    +
    {{ gci_students.error }}
    +
    + {% endif %}{# if gci_students.data #} + +
    + GCI Students data was updated: +

    +
    + +{% endblock %} \ No newline at end of file