Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

activity: Make activity page with graphs on issues #27

Merged
merged 3 commits into from
Dec 9, 2017
Merged

activity: Make activity page with graphs on issues #27

merged 3 commits into from
Dec 9, 2017

Conversation

nalinbhardwaj
Copy link
Member

@nalinbhardwaj nalinbhardwaj commented Dec 6, 2017

Build scraper that scrapes issues.json from gh-board and produces a JSON file just containing stats. This JSON file is used for displaying a static page with graphs, which can be toggled from a dropdown to display past year/month or week's data.
Example page:
screen shot 2017-12-07 at 2 59 04 am

I haven't worked with Django before, so please let me know if something is wrong, or there are better ways to do what I do. I've since removed all uses of Django, and am deploying it individually since I couldn't get it to work with the rest of the codebase neatly(getting some errors, although it worked fine individually)

The data is processed in python, and not directly in frontend to prevent browser overload(issues.json is > 27 MB)
Closes #25

TODO: Once all changes are approved, make orderly commits with proper fragmentation, description etc. (done)

import datetime
from dateutil import parser, relativedelta

issuesurl = "https://coala.github.io/gh-board/issues.json"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line contains the keyword 'coala'.

Origin: KeywordBear, Section: generalization.

<html>

<head>
<title>Coala Community Activity</title>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line contains the keyword 'Coala'.

Origin: KeywordBear, Section: generalization.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, should I remove the word 'coala' or what?

Copy link
Member

@blazeu blazeu Dec 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't allow "coala" here, the organization name must be dynamic.

By the way, coala is always written with lower case 'c', but in this repo, it's should be removed altogether.

Copy link
Member

@Monal5031 Monal5031 Dec 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can keep this as Organization Community Activity for now, later after the model patch, this can be made dynamic.
Same for wherever you've used coala

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Monal5031 okay I’ll do that, but I can’t remove it from the issuesurl since that’s a url to fetch data from? Should I add that to ignored files?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# Ignore KeywordBear

</head>

<body>
<h1>Coala Activity</h1>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line contains the keyword 'Coala'.

Origin: KeywordBear, Section: generalization.

responsive: true,
title: {
display: true,
text: 'Coala Community Activity'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line contains the keyword 'Coala'.

Origin: KeywordBear, Section: generalization.

def diff_week(d1, d2):
monday1 = (d1 - datetime.timedelta(days=d1.weekday()))
monday2 = (d2 - datetime.timedelta(days=d2.weekday()))
return (monday1 - monday2).days / 7
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though I am not sure about this. I think this would be rather // 7. We need the floor value for the number of weeks right.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Monday1-monday2 is guaranteed to be a multiple of 7. Since, it’s a difference in Monday’s of different weeks...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then maybe return ((d1-d2).days)//7 would be more simple.

Copy link
Member Author

@nalinbhardwaj nalinbhardwaj Dec 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose behind doing it this way is to make sure weeks are counted starting from Monday. So if the data is scraped on a Thursday, the current week is Monday-Thursday, and not previous Friday-Thursday, since it doesn’t make much sense mentally to have weeks not start from Monday, and also, it maintains consistency with other options(for example, year counts a month partially if it hasn’t ended yet)
What the code does is basically calculate the number of Mondays between the two dates, which is when regular calendar week changes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left a comment in the code now to be clear(er) about this for future readers.

.travis.yml Outdated
@@ -17,4 +17,9 @@ after_success:
- mkdir _site public
- python manage.py collectstatic --noinput
- python manage.py distill-local public --force
- mkdir public/activity
- python activity/scraper.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move all of this before the django stuff.
Then the json could be loaded by djanjo, but more importantly the static components should all be managed by djanjo's asset system. (e.g. there are django addons that do cache busting)

var labels = [];
var myChart;

function updateChart() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should also be in static JS files, so they can be linted.

pass the document elements into the functions.

from dateutil import parser, relativedelta

# URL to grab all issues from
issuesurl = "https://coala.github.io/gh-board/issues.json" # Ignore KeywordBear
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, dont ignore the bears, they will eat you :P
derive the org_name from your working environment.
See #1 and #26

return (d1-d2).days

# Get labels for each option
month_labels = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you want the python std calendar library, which is unfortunately not well known (and will be necessary if we add i18n).

Also move 80% of the remaining code into a class, even if it isnt well designed, because a class will force you to do some basic design, and then the indent levels will be correct , and it is easier to shuffle code around after that has been done.

if issue["state"] == "closed":
data["week"]["closed"][dys] += 1

print(data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Printed for logging purposes currently, the rest of the codebase doesn't appear to use proper logging so I just printed it to console too :P

data["week"]["closed"][dys] += 1

print(data)
with open('activity/data.json', 'w') as fp:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.sep, for proper cross platform support.

@jayvdb
Copy link
Member

jayvdb commented Dec 7, 2017

unack 0f2b4a2

static/charts.js Outdated
function setChart(labels, openedData, closedData, type) {
var ctx = document.getElementById("canvas");

curChart = new Chart(ctx, {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'Chart' is not defined.

Origin: JSHintBear, Section: javascript.

static/charts.js Outdated
function updateChart(type) {
if(curChart){ curChart.destroy(); }

$.getJSON({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'$' is not defined.

Origin: JSHintBear, Section: javascript.

static/charts.js Outdated
function setChart(labels, openedData, closedData, type) {
var ctx = document.getElementById("canvas");

curChart = new Chart(ctx, {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'Chart' is not defined.

Origin: JSHintBear, Section: javascript.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a way to tell JSHintBear (or configure jshint) to ignore Chart.

static/charts.js Outdated
function updateChart(type) {
if(curChart){ curChart.destroy(); }

$.getJSON({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'$' is not defined.

Origin: JSHintBear, Section: javascript.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to configure JSHintBear to accept JQuery's $.

.travis.yml Outdated
@@ -3,6 +3,7 @@ python: 3.6

env:
global:
- ORG_NAME: "coala"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not allowed to put the word coala anywhere in this repo; it must work dynamically; when forked to a different org, it must derive the org. I've also now created #29 for the existing use of coala in this file.

print(real_data)
with open('static' + os.sep + 'activity-data.json', 'w') as fp:
json.dump(real_data, fp)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EOL problem here.

static/charts.js Outdated
function updateChart(type) {
if(curChart){ curChart.destroy(); }

$.getJSON({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to configure JSHintBear to accept JQuery's $.

static/charts.js Outdated
function setChart(labels, openedData, closedData, type) {
var ctx = document.getElementById("canvas");

curChart = new Chart(ctx, {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a way to tell JSHintBear (or configure jshint) to ignore Chart.

@gitmate-bot
Copy link
Collaborator

Comment on ddf9751, file static/charts.js, line 61.

'$' is not defined.

Origin: JSHintBear, Section: javascript.

@gitmate-bot
Copy link
Collaborator

Comment on ddf9751, file static/charts.js, line 6.

'Chart' is not defined.

Origin: JSHintBear, Section: javascript.

@gitmate-bot
Copy link
Collaborator

Comment on ddf9751, file static/charts.js, line 61.

'$' is not defined.

Origin: JSHintBear, Section: javascript.

static/charts.js Outdated
function setChart(labels, openedData, closedData, type) {
var ctx = document.getElementById("canvas");

curChart = new Chart(ctx, { // Ignore JSHintBear
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to add Chart and $ to the globals by adding this to the top of the file:

/* globals $, Chart */

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, worked like a charm. :)

regex="github.com/[a-z0-9A-Z]*"
git config -l | grep -o "$regex" | while read -r line ; do
echo "${line:11}" | xargs echo -n > org_name.txt
done
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newline here please.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.


<body>
<h1>Community Activity</h1>
<script>loadTimeElements()</script>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not put it inside the same script tag below?

Copy link
Member Author

@nalinbhardwaj nalinbhardwaj Dec 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this is a remain of when I was serving the page using django. It's no longer possible to display the time stamp(since it's not generated via django)
I think I'll just remove this for now.

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="/static/timeago.js"></script>
<script src="/static/charts.js"></script>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the <script> tag can be inside the body (below the content) so it doesn't block content.

updateChart() is called after the content anyway, so it doesn't matter.

<head>
<title>Community Activity</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is jquery 3 not compatible with Chart.js?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't using it because it fails silently on getJSON errors(and I need logging), will change.

Copy link
Member

@blazeu blazeu Dec 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's .fail() in jQuery 3

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, changing.

static/charts.js Outdated
},
error: function(error_data) {
console.log("error");
console.log(error_data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

console.error is a bit accurate.

static/charts.js Outdated
if(curChart){ curChart.destroy(); }

$.getJSON({
url: "/static/activity-data.json",
Copy link
Member

@blazeu blazeu Dec 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the url directly $.getJSON("/static/activity-data.json")
and have a callback as the second argument or .done() and .fail()

Read http://api.jquery.com/jquery.getjson/#jqxhr-object

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ But it's optional.


regex="github.com/[a-z0-9A-Z]*"
git config -l | grep -o "$regex" | while read -r line ; do
echo "${line:11}" | xargs echo -n > org_name.txt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we prefer two indents by default for shell. Maybe see what ShellCheckBear says ;-)

Copy link
Member Author

@nalinbhardwaj nalinbhardwaj Dec 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems not, .ci/deploy.sh uses 4 as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that was a horribly rushed script I mostly copied from other sources and fixed up; without code review; naughty me.

https://github.com/coala/coala-bears/blob/master/.ci/deps.sh
https://github.com/coala/coala/blob/master/.misc/deps.sh
(and others in those directories)

We dont run code linting on them yet. I've created coala/coala#4952 for that. (I'll publish a backlog of new tasks tomorrow)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this script is so small it doesnt matter; you are right we dont have a convention yet, so you dont need to update this patch to follow a non-existent coding standard)

@blazeu
Copy link
Member

blazeu commented Dec 8, 2017

This is just a comment.

When I check ChartJS, it does not need jQuery.

You need to stop using jQuery only for fetching things in the future :P
You can use the native Fetch API and there's 500 bytes polyfill for older browsers to support it.

For now I think it's ok since we're probably gonna need it for anything else, esp. DOM modification,
although I still prefer the native DOM API, it's getting better these days.

@nalinbhardwaj
Copy link
Member Author

@blazeu I'm currently also using .on()(although I could just replace that by an event listener). I think it's okay for it to use jQuery ATM. (I'll switch to a minified version for less loading).

static/charts.js Outdated
$.getJSON("/static/activity-data.json",
function(data) {
var labels = data.year.labels;
var openedData = data.year.opened;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

L65 and 66 are not needed right, its getting overwritten later inside if else anyway

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

from dateutil import parser, relativedelta

class Scraper():
'''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

""" for docstrings.

'''

# Count of months/weeks/days respectively to be scraped in past.
month_count = 12
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am 99% sure these constants can be obtained from calendar. If not, they should be CONSTANTS at the top of the module.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, I chose these constants randomly myself. They're not representative of anything, just a number I think is good for display.(so no calendar use here)


# Process labels for each option
for x in range(self.month_count-1, -1, -1):
self.data["year"]["labels"].append(calendar.month_name[(self.date - relativedelta.relativedelta(months=x)).month])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line length; please ensure this is being linted.


# Initialise data dicts
self.data = {
"year" : {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer single quotes in code.


def get_data(self):
"""
Get data
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return type

# URL to grab all issues from
org_name = open('org_name.txt').readline()

issuesurl = "http://" + org_name + ".github.io/gh-board/issues.json"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issues_url

Nalin Bhardwaj added 2 commits December 9, 2017 04:04
Make bash script to automatically determine the org the repo is for.
Uses git config info. Stores org's name to org_name.txt in running folder.

Fixes #29 partially
Makes class Scraper to scrape http://coala.github.io/gh-board/issues.json
or similar file into a JSON containing only the statistics required.
Stores file at "static/activity-data.json"

Closes #25
Copy link
Member

@jayvdb jayvdb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 spaces for JS is the decision

Make activity/index.html to display the data, and static/charts.js
for constructing the charts. Uses scraped file
`static/activity-data.json`.

Closes #25
@jayvdb
Copy link
Member

jayvdb commented Dec 9, 2017

ack 6b69490

@jayvdb jayvdb merged commit 6b69490 into coala:master Dec 9, 2017
@nalinbhardwaj nalinbhardwaj deleted the activity branch December 9, 2017 16:22
jayvdb added a commit to jayvdb/community that referenced this pull request Dec 10, 2017
When the issue data JSON is missing, an exception
should occur then, instead of when failing to load
the JSON.

Related to coala#27
jayvdb added a commit to jayvdb/community that referenced this pull request Dec 10, 2017
Use templates for static content, including
new basic front page.

Also remove unnecessary auth processor.

Related to coala#27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

8 participants