Permalink
Browse files

Merge pull request #271 from mozilla/development

Development
  • Loading branch information...
2 parents e970ec0 + 20df0ce commit 7e547abdb5c5b41d72eb47521c9c1dd5ba488731 @ryanpitts ryanpitts committed on GitHub Dec 16, 2016
Showing with 5,371 additions and 1,271 deletions.
  1. +2 −2 .gitmodules
  2. +2 −0 requirements/prod.txt
  3. 0 source/api/__init__.py
  4. +16 −0 source/api/urls.py
  5. +107 −0 source/api/views.py
  6. +1 −0 source/articles/admin.py
  7. +205 −0 ...rticles/migrations/0002_auto__add_field_article_article_js_header__add_field_article_article_j.py
  8. +2 −0 source/articles/models.py
  9. +1 −1 source/articles/search_indexes.py
  10. +96 −0 source/articles/static/articles/css/highlight-theme.css
  11. +0 −23 source/articles/static/articles/js/jquery.syntaxhighlighter.min.js
  12. +2 −0 source/articles/static/articles/js/pym.min.js
  13. +0 −117 source/articles/static/articles/js/resources/core.console.js
  14. +0 −115 source/articles/static/articles/js/resources/jquery.appendscriptstyle.js
  15. +0 −387 source/articles/static/articles/js/resources/jquery.syntaxhighlighter.js
  16. +1 −1 source/articles/templates/articles/_article_list_item.html
  17. +21 −4 source/articles/templates/articles/article_detail.html
  18. +2 −2 source/articles/templates/articles/article_list_with_promos.html
  19. +1 −1 source/base/feeds.py
  20. +17 −4 source/base/static/base/css/app.css
  21. BIN source/base/static/base/img/srccon_flag.png
  22. +2 −1 source/base/templates/base.html
  23. +8 −1 source/base/urls.py
  24. +25 −1 source/base/views.py
  25. +1 −1 source/code/models.py
  26. +8 −1 source/guides/admin.py
  27. +214 −0 .../guides/migrations/0003_auto__add_field_guidearticle_external_url__chg_field_guidearticle_arti.py
  28. +209 −0 source/guides/migrations/0004_auto__add_field_guidearticle_external_title.py
  29. +12 −4 source/guides/models.py
  30. +12 −8 source/guides/templates/guides/_guide_article_list_item.html
  31. +63 −0 source/jobs/management/commands/job_post_reminders.py
  32. +5 −0 source/jobs/models.py
  33. +46 −0 source/jobs/templates/jobs/emails/job_post_reminder.html
  34. +13 −0 source/jobs/templates/jobs/emails/job_post_reminder.txt
  35. +17 −4 source/jobs/templates/jobs/job_list.html
  36. +0 −1 source/jobs/views.py
  37. +3 −3 source/people/models.py
  38. +1 −557 source/people/templates/people/organization_update.html
  39. +11 −0 source/utils/email.py
  40. +4 −1 source/utils/json.py
  41. +10 −0 vendor-local/lib/python/dateutil/__init__.py
  42. +91 −0 vendor-local/lib/python/dateutil/easter.py
  43. +937 −0 vendor-local/lib/python/dateutil/parser.py
  44. +436 −0 vendor-local/lib/python/dateutil/relativedelta.py
  45. +1,112 −0 vendor-local/lib/python/dateutil/rrule.py
  46. +960 −0 vendor-local/lib/python/dateutil/tz.py
  47. +179 −0 vendor-local/lib/python/dateutil/tzwin.py
  48. +109 −0 vendor-local/lib/python/dateutil/zoneinfo/__init__.py
  49. BIN vendor-local/lib/python/dateutil/zoneinfo/zoneinfo--latest.tar.gz
  50. +24 −0 vendor-local/lib/python/python_dateutil-2.2-py2.7.egg-info/PKG-INFO
  51. +26 −0 vendor-local/lib/python/python_dateutil-2.2-py2.7.egg-info/SOURCES.txt
  52. +1 −0 vendor-local/lib/python/python_dateutil-2.2-py2.7.egg-info/dependency_links.txt
  53. +24 −0 vendor-local/lib/python/python_dateutil-2.2-py2.7.egg-info/installed-files.txt
  54. +1 −0 vendor-local/lib/python/python_dateutil-2.2-py2.7.egg-info/not-zip-safe
  55. +1 −0 vendor-local/lib/python/python_dateutil-2.2-py2.7.egg-info/requires.txt
  56. +1 −0 vendor-local/lib/python/python_dateutil-2.2-py2.7.egg-info/top_level.txt
  57. +32 −0 vendor-local/lib/python/six-1.6.1-py2.7.egg-info/PKG-INFO
  58. +15 −0 vendor-local/lib/python/six-1.6.1-py2.7.egg-info/SOURCES.txt
  59. +1 −0 vendor-local/lib/python/six-1.6.1-py2.7.egg-info/dependency_links.txt
  60. +7 −0 vendor-local/lib/python/six-1.6.1-py2.7.egg-info/installed-files.txt
  61. +1 −0 vendor-local/lib/python/six-1.6.1-py2.7.egg-info/top_level.txt
  62. +272 −30 vendor-local/lib/python/six.py
  63. +1 −1 vendor-local/src/django-south
View
@@ -9,7 +9,7 @@
url = https://github.com/kennethreitz/requests.git
[submodule "vendor-local/src/django-south"]
path = vendor-local/src/django-south
- url = git://github.com/lambdafu/django-south.git
+ url = git://github.com/dmishe/django-south.git
[submodule "vendor-local/src/django-cache-machine"]
path = vendor-local/src/django-cache-machine
url = git://github.com/jbalogh/django-cache-machine.git
@@ -21,7 +21,7 @@
url = git://github.com/toastdriven/pyelasticsearch.git
[submodule "vendor-local/src/sorl-thumbnail"]
path = vendor-local/src/sorl-thumbnail
- url = git://github.com/sorl/sorl-thumbnail.git
+ url = git://github.com/mariocesar/sorl-thumbnail.git
[submodule "vendor-local/src/django-taggit"]
path = vendor-local/src/django-taggit
url = https://github.com/ryanpitts/django-taggit.git
View
@@ -2,3 +2,5 @@
django_browserid
requests
newrelic==1.11.0.55
+python-dateutil==2.2
+six==1.6.1
View
No changes.
View
@@ -0,0 +1,16 @@
+from django.conf import settings
+from django.conf.urls.defaults import *
+from django.views.decorators.cache import cache_page
+
+from .views import ContributorCount
+
+FEED_CACHE_TIME = getattr(settings, 'FEED_CACHE_SECONDS', 60*15)
+
+urlpatterns = patterns('',
+ url(
+ regex = '^contributor-count/$',
+ view = cache_page(ContributorCount.as_view(), FEED_CACHE_TIME),
+ kwargs = {},
+ name = 'api_v1_contributor_count',
+ ),
+)
View
@@ -0,0 +1,107 @@
+from datetime import datetime, timedelta
+from dateutil import parser
+
+from django.conf import settings
+from django.views.generic import View
+
+from source.articles.models import Article
+from source.utils.json import render_json_to_response
+
+USER_DEBUG = getattr(settings, 'USER_DEBUG', False)
+
+
+class ContributorCount(View):
+ def get(self, request, *args, **kwargs):
+ '''
+ Returns the following counts for Mozilla contributors dashboard:
+
+ * Distinct authors who published articles in the previous year
+ * New authors who published articles in the previous week, where "new"
+ means they have not published in the previous year
+ * Distinct people associated with articles published in the previous year
+ * New people associated with articles published in the previous week,
+ where "new" means they have not been mentioned in the previous year
+
+ These counts reflect the way Source articles can be associated
+ with individuals:
+
+ * Authors: The person or people who wrote the article
+ * People: A person or people whose work is being covered by the article.
+ These people may or may not also be listed as article Authors.
+
+ A date may be passed as a querystring parameter to provide a starting
+ point for calculations. If no date is passed, `today` will be assumed.
+
+ * /api/1.0/contributor-count/
+ * /api/1.0/contributor-count/?date=2014-04-12
+
+ Date ranges will be calculated from midnight of the starting date, so
+ records won't be missed based on the time of day when the query is run.
+ '''
+
+ # set up the date parameters
+ requested_date = request.GET.get('date', None)
+ if requested_date:
+ start_date = parser.parse(requested_date)
+ else:
+ today = datetime.today()
+ midnight = datetime.min.time()
+ start_date = datetime.combine(today, midnight)
+
+ previous_year = start_date - timedelta(days=365)
+ previous_7_days = start_date - timedelta(days=7)
+
+ # set up the necessary article querysets
+ articles_year = Article.live_objects.filter(pubdate__lt=start_date, pubdate__gte=previous_year)
+ articles_7_days = Article.live_objects.filter(pubdate__lt=start_date, pubdate__gte=previous_7_days)
+ articles_year_exclude_7_days = Article.live_objects.filter(pubdate__lt=previous_7_days, pubdate__gte=previous_year)
+
+ # get down to counting some authors
+ # first, take all the articles published in the previous year, fetch
+ # the pk values for their `authors` m2m relationship
+ authors_previous_year = articles_year.values_list('authors', flat=True)
+ # filter out `none` values, use set() to remove dupes, count members
+ authors_previous_year_count = len(set(filter(None, authors_previous_year)))
+
+ # repeat process for articles published in the previous week, but only
+ # to the point where we're creating the set of unique author values
+ authors_previous_7_days = articles_7_days.values_list('authors', flat=True)
+ authors_previous_7_days_set = set(filter(None, authors_previous_7_days))
+
+ # do the same for articles published during previous year but NOT
+ # during the previous week
+ authors_previous_year_exclude_7_days = articles_year_exclude_7_days.values_list('authors', flat=True)
+ authors_previous_year_exclude_7_days_set = set(filter(None, authors_previous_year_exclude_7_days))
+
+ # then use set difference to find author values from previous 7 days
+ # that do NOT appear elsewhere in the previous year
+ authors_new_previous_7_days_count = len(
+ authors_previous_7_days_set.difference(authors_previous_year_exclude_7_days_set)
+ )
+
+ # now repeat all of that for people associated with published articles
+ people_previous_year = articles_year.values_list('people', flat=True)
+ people_previous_year_count = len(set(filter(None, people_previous_year)))
+
+ people_previous_7_days = articles_7_days.values_list('people', flat=True)
+ people_previous_7_days_set = set(filter(None, people_previous_7_days))
+
+ people_previous_year_exclude_7_days = articles_year_exclude_7_days.values_list('people', flat=True)
+ people_previous_year_exclude_7_days_set = set(filter(None, people_previous_year_exclude_7_days))
+
+ people_new_previous_7_days_count = len(
+ people_previous_7_days_set.difference(people_previous_year_exclude_7_days_set)
+ )
+
+ result = {
+ 'start_date': datetime.strftime(start_date, '%Y-%m-%d'),
+ 'previous_year': datetime.strftime(previous_year, '%Y-%m-%d'),
+ 'previous_7_days': datetime.strftime(previous_7_days, '%Y-%m-%d'),
+ 'authors_previous_year': authors_previous_year_count,
+ 'authors_new_previous_7_days': authors_new_previous_7_days_count,
+ 'people_previous_year': people_previous_year_count,
+ 'people_new_previous_7_days': people_new_previous_7_days_count
+ }
+
+ return render_json_to_response(result)
+
View
@@ -32,6 +32,7 @@ class ArticleAdmin(AdminImageMixin, admin.ModelAdmin):
('', {'fields': (('pubdate', 'is_live', 'show_in_lists', 'allow_comments'), ('title', 'slug'), 'subhead', ('category', 'tags'), 'technology_tags', 'concept_tags',)}),
('Article relationships', {'fields': ('authors', 'people', 'organizations', 'code',)}),
('Article body', {'fields': ('image', 'image_caption', 'image_credit', 'summary', 'body', 'disable_auto_linebreaks')}),
+ ('Article javascript', {'classes': ('collapse',), 'fields': ('article_js_header', 'article_js_footer')}),
)
inlines = [ArticleBlockInline,]
readonly_fields = ('tags',)
Oops, something went wrong.

0 comments on commit 7e547ab

Please sign in to comment.