Skip to content

Commit fc11659

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.
1 parent 494d4c7 commit fc11659

20 files changed

Lines changed: 812 additions & 185 deletions

.ci/build.sh

Lines changed: 1 addition & 0 deletions
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

Lines changed: 2 additions & 1 deletion
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 3 additions & 2 deletions
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

Lines changed: 0 additions & 14 deletions
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

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,111 @@
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+
<<<<<<< HEAD
35+
'licence_type': 'GNU AGPL v3.0'
36+
=======
37+
'licence_type': 'GNU AGPL v3.0',
38+
'team_details': dict(get_team_details())
39+
>>>>>>> Enhance the community website homepage
40+
}
41+
return org_details
42+
43+
44+
def get_header_and_footer(context):
45+
context['isTravis'] = Travis.TRAVIS
46+
context['travisLink'] = Travis.TRAVIS_BUILD_WEB_URL
47+
context['org'] = initialize_org_context_details()
48+
print('Running on Travis: {}, build link: {}'.format(context['isTravis'],
49+
context['travisLink']
50+
))
51+
return context
1252

1353

1454
class HomePageView(TemplateView):
1555
template_name = 'index.html'
1656

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
57+
def get_team_details(self):
58+
org_name = get_org_name()
59+
teams = [
60+
'{} newcomers'.format(org_name),
61+
'{} developers'.format(org_name),
62+
'{} admins'.format(org_name)
63+
]
64+
team_details = {}
65+
for team in teams:
66+
team_objs = [Team.objects.get(name=team), ]
67+
contributors = Contributor.objects.filter(teams__in=team_objs)
68+
team_details[team] = contributors.count()
69+
return team_details
70+
71+
def get_quote_of_the_day(self):
72+
import requests
73+
qod = requests.get('http://quotes.rest/qod?category=inspire')
74+
qod_data = qod.json()
75+
if qod.status_code == 429:
76+
return None
77+
return {
78+
'quote': qod_data['contents']['quotes'][0]['quote'],
79+
'author': qod_data['contents']['quotes'][0]['author'],
80+
}
81+
82+
def get_top_meta_review_users(self, count):
83+
from meta_review.models import Participant
84+
participants = Participant.objects.all()[:count]
85+
for contrib in participants:
86+
contrib.score = int(contrib.score)
87+
return participants
2188

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

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

28118

Lines changed: 119 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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)