Skip to content

Commit 2362349

Browse files
committed
Enhance the community website homepage
The enhancement includes addition of materialize css, JQuery, responsiveness, and easy-navigation of website features. The easy-navigatibility is achieved by adding a navbar with display of meta -review and gamification leaderboard on homepage. Apart from this, the activity graph url is omitted from website by displaying the graph itslef on the homepage on large devices. Closes https://gitlab.com/coala/GSoC/gsoc-2019/issues/142
1 parent 610f8d1 commit 2362349

20 files changed

+886
-185
lines changed

.ci/build.sh

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ python manage.py fetch_deployed_data _site $ISSUES_JSON \
2727

2828
python manage.py migrate
2929
python manage.py import_contributors_data
30+
python manage.py create_org_cluster_map_and_activity_graph org_map
3031
python manage.py import_issues_data
3132
python manage.py import_merge_requests_data
3233
python manage.py create_config_data

.coafile

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[all]
22
files = **.py, **.js, **.sh
3-
ignore = .git/**, **/__pycache__/**, gci/client.py, */migrations/**, private/*, openhub/**
3+
ignore = .git/**, **/__pycache__/**, gci/client.py, */migrations/**, private/*, openhub/**, **/leaflet_dist/**
44
max_line_length = 80
55
use_spaces = True
66
preferred_quotation = '
@@ -42,6 +42,7 @@ files = static/**/*.js
4242
bears = JSHintBear
4343
allow_unused_variables = True
4444
javascript_strictness = False
45+
environment_jquery = True
4546

4647
[all.yml]
4748
bears = YAMLLintBear

.moban.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ packages:
1616
- unassigned_issues
1717

1818
dependencies:
19+
- getorg~=0.3.1
1920
- git+https://gitlab.com/coala/coala-utils.git
2021
- git-url-parse
2122
- django>2.1,<2.2

activity/scraper.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def get_data(self):
136136
return self.data
137137

138138

139-
def activity_json(request):
139+
def activity_json(filename):
140140

141141
org_name = get_org_name()
142142

@@ -152,4 +152,5 @@ def activity_json(request):
152152
real_data = Scraper(parsed_json['issues'], datetime.datetime.today())
153153
real_data = real_data.get_data()
154154

155-
return HttpResponse(json.dumps(real_data))
155+
with open(filename, 'w+') as f:
156+
json.dump(real_data, f, indent=4)

community/urls.py

-14
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@
55
from django_distill import distill_url
66
from django.conf.urls.static import static
77
from django.conf import settings
8-
from django.views.generic import TemplateView
98

109
from community.views import HomePageView, info
1110
from gci.views import index as gci_index
1211
from gci.feeds import LatestTasksFeed as gci_tasks_rss
13-
from activity.scraper import activity_json
1412
from twitter.view_twitter import index as twitter_index
1513
from log.view_log import index as log_index
1614
from data.views import index as contributors_index
@@ -87,18 +85,6 @@ def get_organization():
8785
distill_func=get_index,
8886
distill_file='info.txt',
8987
),
90-
distill_url(
91-
r'static/activity-data.json', activity_json,
92-
name='activity_json',
93-
distill_func=get_index,
94-
distill_file='static/activity-data.json',
95-
),
96-
distill_url(
97-
r'activity/', TemplateView.as_view(template_name='activity.html'),
98-
name='activity',
99-
distill_func=get_index,
100-
distill_file='activity/index.html',
101-
),
10288
distill_url(
10389
r'gci/tasks/rss.xml', gci_tasks_rss(),
10490
name='gci-tasks-rss',

community/views.py

+92-7
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,106 @@
88
get_org_name,
99
get_owner,
1010
get_upstream_deploy_url,
11+
get_remote_url
1112
)
13+
from data.models import Team, Contributor
14+
15+
16+
def initialize_org_context_details():
17+
org_name = get_org_name()
18+
org_details = {
19+
'name': org_name,
20+
'blog_url': 'https://blog.{}.io/'.format(org_name),
21+
'twitter_url': 'https://twitter.com/{}_io/'.format(org_name),
22+
'facebook_url': 'https://www.facebook.com/{}Analyzer'.format(
23+
org_name),
24+
'repo_url': get_remote_url().href,
25+
'docs': 'http://{}.io/docs'.format(org_name),
26+
'newcomer_docs': 'http://{}.io/newcomer'.format(org_name),
27+
'coc': 'http://{}.io/coc'.format(org_name),
28+
'logo_url': ('https://api.{}.io/en/latest/_static/images/'
29+
'{}_logo.svg'.format(org_name, org_name)),
30+
'gitter_chat': 'https://gitter.im/{}/{}/'.format(org_name,
31+
org_name),
32+
'github_core_repo': 'https://github.com/{}/{}/'.format(org_name,
33+
org_name),
34+
'licence_type': 'GNU AGPL v3.0'
35+
}
36+
return org_details
37+
38+
39+
def get_header_and_footer(context):
40+
context['isTravis'] = Travis.TRAVIS
41+
context['travisLink'] = Travis.TRAVIS_BUILD_WEB_URL
42+
context['org'] = initialize_org_context_details()
43+
print('Running on Travis: {}, build link: {}'.format(context['isTravis'],
44+
context['travisLink']
45+
))
46+
return context
1247

1348

1449
class HomePageView(TemplateView):
1550
template_name = 'index.html'
1651

17-
def get_context_data(self, **kwargs):
18-
context = super().get_context_data(**kwargs)
19-
context['isTravis'] = Travis.TRAVIS
20-
context['travisLink'] = Travis.TRAVIS_BUILD_WEB_URL
52+
def get_team_details(self):
53+
org_name = get_org_name()
54+
teams = [
55+
'{} newcomers'.format(org_name),
56+
'{} developers'.format(org_name),
57+
'{} admins'.format(org_name)
58+
]
59+
team_details = {}
60+
for team in teams:
61+
team_objs = [Team.objects.get(name=team), ]
62+
contributors = Contributor.objects.filter(teams__in=team_objs)
63+
team_details[team] = contributors.count()
64+
return team_details
65+
66+
def get_quote_of_the_day(self):
67+
import requests
68+
qod = requests.get('http://quotes.rest/qod?category=inspire')
69+
qod_data = qod.json()
70+
if qod.status_code == 429:
71+
return None
72+
return {
73+
'quote': qod_data['contents']['quotes'][0]['quote'],
74+
'author': qod_data['contents']['quotes'][0]['author'],
75+
}
76+
77+
def get_top_meta_review_users(self, count):
78+
from meta_review.models import Participant
79+
participants = Participant.objects.all()[:count]
80+
for contrib in participants:
81+
contrib.score = int(contrib.score)
82+
return participants
2183

22-
print('Running on Travis: {}, build link: {}'.format(
23-
context['isTravis'],
24-
context['travisLink']))
84+
def get_top_gamification_users(self, count):
85+
from gamification.models import Participant
86+
return enumerate(Participant.objects.all()[:count])
2587

88+
def get_context_data(self, **kwargs):
89+
context = super().get_context_data(**kwargs)
90+
context = get_header_and_footer(context)
91+
context['org']['team_details'] = dict(self.get_team_details())
92+
org_name = context['org']['name']
93+
about_org = ('{org_name} (always spelled with a lowercase c!) is one'
94+
' of the welcoming open-source organizations for'
95+
' newcomers. {org_name} stands for “COde AnaLysis'
96+
' Application” as it works well with animals and thus is'
97+
' well visualizable which makes it easy to memorize.'
98+
' {org_name} provides a unified interface for linting'
99+
' and fixing the code with a single configuration file,'
100+
' regardless of the programming languages used. You can'
101+
' use {org_name} from within your favorite editor,'
102+
' integrate it with your CI and, get the results as JSON'
103+
', or customize it to your needs with its flexible'
104+
' configuration syntax.'.format(org_name=org_name))
105+
context['org']['about'] = about_org
106+
context['quote_details'] = self.get_quote_of_the_day()
107+
context['top_meta_review_users'] = self.get_top_meta_review_users(
108+
count=5)
109+
context['top_gamification_users'] = self.get_top_gamification_users(
110+
count=5)
26111
return context
27112

28113

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import logging
2+
import json
3+
import getorg
4+
import os
5+
6+
from django.core.management.base import BaseCommand
7+
8+
from data.models import Contributor
9+
from activity.scraper import activity_json
10+
11+
12+
class Command(BaseCommand):
13+
help = 'Create a cluster map using contributors geolocation'
14+
15+
def add_arguments(self, parser):
16+
parser.add_argument('output_dir', nargs='?', type=str)
17+
18+
def handle(self, *args, **options):
19+
logger = logging.getLogger(__name__)
20+
output_dir = options.get('output_dir')
21+
22+
if not output_dir:
23+
logger.debug('output_dir arg not provided! Setting output_dir'
24+
' to cluster_map/')
25+
output_dir = 'cluster_map'
26+
27+
class Location:
28+
29+
def __init__(self, longitude, latitude):
30+
self.longitude = longitude
31+
self.latitude = latitude
32+
33+
org_location_dict = {}
34+
35+
for contrib in Contributor.objects.all():
36+
if not contrib.login.startswith('testuser') and contrib.location:
37+
user_location = json.loads(contrib.location)
38+
location = Location(user_location['longitude'],
39+
user_location['latitude'])
40+
org_location_dict[contrib.login] = location
41+
logger.debug('{} location {} added on map'.format(
42+
contrib.login, user_location))
43+
getorg.orgmap.output_html_cluster_map(org_location_dict,
44+
folder_name=output_dir)
45+
46+
self.move_and_make_changes_in_files(output_dir)
47+
48+
# Fetch data for activity graph to be displayed on home-page
49+
activity_json('static/activity-data.js')
50+
51+
def move_and_make_changes_in_files(self, output_dir):
52+
# Move leaflet_dist folder to static folder
53+
leaflet_source_path = '{}/{}/leaflet_dist/'.format(os.getcwd(),
54+
output_dir)
55+
leaflet_destination_path = '{}/{}/leaflet_dist/'.format(os.getcwd(),
56+
'static')
57+
os.renames(leaflet_source_path, leaflet_destination_path)
58+
# Move org_locations.js to static folder
59+
locations_source_path = '{}/{}/org-locations.js'.format(os.getcwd(),
60+
output_dir)
61+
locations_destination_path = '{}/{}/org-locations.js'.format(
62+
os.getcwd(), 'static')
63+
os.rename(locations_source_path, locations_destination_path)
64+
# Change map.html to support django
65+
with open('{}/map.html'.format(output_dir)) as f:
66+
django_supported_htmls = []
67+
lines = f.readlines()
68+
for index in range(len(lines)):
69+
line = lines[index].strip()
70+
if line.__contains__('<html>'):
71+
django_supported_htmls.append('{% load staticfiles %}\n')
72+
django_supported_htmls.append(line+'\n')
73+
elif line.__contains__('</head>'):
74+
adjust_prop = '''
75+
<style>
76+
#map {
77+
width: 60%;
78+
height: 300px;
79+
margin: auto;
80+
box-shadow: 0px 0px 25px 2px;
81+
}
82+
@media only screen and (max-width:750px){
83+
#map {
84+
width: 90%
85+
}
86+
}
87+
</style>\n
88+
'''
89+
meta_charset = '<meta charset="utf-8">'
90+
adjust_prop = adjust_prop.strip().replace(' ', '')
91+
django_supported_htmls.insert(6, meta_charset+'\n')
92+
django_supported_htmls.append(adjust_prop+'\n')
93+
django_supported_htmls.append(line+'\n')
94+
elif line.__contains__('https://'):
95+
line = line.replace('https:', '').replace(' />', '>')
96+
django_supported_htmls.append(line.strip()+'\n')
97+
elif line.__contains__('<link '):
98+
line = line.replace('href="', 'href="{% static \'')
99+
line = line.replace('.css', '.css\' %}').replace(' />', '>')
100+
django_supported_htmls.append(line+'\n')
101+
elif line.__contains__('<script '):
102+
line = line.replace('src="', 'src="{% static \'')
103+
line = line.replace('.js', '.js\' %}')
104+
if line.__contains__(' type="text/javascript"'):
105+
line = line.replace(' type="text/javascript"', '')
106+
django_supported_htmls.append(line+'\n')
107+
elif line.__contains__('Mouse over') or len(line) == 0:
108+
pass
109+
else:
110+
django_supported_htmls.append(line+'\n')
111+
# Add map.html to templates folder
112+
html_map_path = '{}/{}/map.html'
113+
html_map_source_path = html_map_path.format(os.getcwd(),
114+
output_dir)
115+
html_map_destination_path = html_map_path.format(os.getcwd(),
116+
'templates')
117+
os.remove(html_map_source_path)
118+
with open(html_map_destination_path, 'w+') as f:
119+
f.writelines(django_supported_htmls)

requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
getorg~=0.3.1
12
git+https://gitlab.com/coala/coala-utils.git
23
git-url-parse
34
django>2.1,<2.2

0 commit comments

Comments
 (0)