From 08297c56ac38c0d853c08e3976fd2ff08ce20455 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sun, 29 Mar 2015 16:28:03 +0530 Subject: [PATCH 001/666] fix(UI/Proposals): fix the edit proposal form as per create proposal form --- junction/static/css/form.css | 5 ---- junction/templates/proposals/create.html | 7 ++--- junction/templates/proposals/update.html | 34 +++++++++++++----------- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/junction/static/css/form.css b/junction/static/css/form.css index 3a853efd..ac1a0fef 100644 --- a/junction/static/css/form.css +++ b/junction/static/css/form.css @@ -16,11 +16,6 @@ width: 76%; } - .edit-proposal-form label.control-label { - width:24%; - padding-right:2%; - } - @media (max-width: 480px) { label.control-label{ display: block; diff --git a/junction/templates/proposals/create.html b/junction/templates/proposals/create.html index d9d4785a..ea3cbe61 100644 --- a/junction/templates/proposals/create.html +++ b/junction/templates/proposals/create.html @@ -22,12 +22,10 @@
-

New Proposal

-

This form supports - markdown for formatting.

+

New Proposal

+

This form supports markdown for formatting.


-
{% csrf_token %} {% bootstrap_form form %} {% buttons %} @@ -39,7 +37,6 @@

New Proposal

{% endbuttons %}
-
diff --git a/junction/templates/proposals/update.html b/junction/templates/proposals/update.html index a3207147..afed8574 100644 --- a/junction/templates/proposals/update.html +++ b/junction/templates/proposals/update.html @@ -20,22 +20,24 @@ {% block content %} {{ form.media }} -
-
-
-

Edit Proposal

-
-
-
{% csrf_token %} - {% bootstrap_form form %} - {% buttons %} - - {% endbuttons %} -
-
- +
+
+
+

Edit Proposal

+

This form supports markdown for formatting.

+
+
+
{% csrf_token %} + {% bootstrap_form form %} + {% buttons %} +
+ +
+ {% endbuttons %} +
+
From 188ee5838a38d54df43e0d6f74a97597ddc8e216 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sun, 29 Mar 2015 17:24:16 +0530 Subject: [PATCH 002/666] refactor(ui/proposals): abstract listitems to a partial items, fix filtering closes #170 --- docs/release_notes.md | 9 + junction/proposals/views.py | 32 +- junction/templates/proposals/list.html | 330 +----------------- .../partials/proposal-list--items.html | 75 ++++ 4 files changed, 120 insertions(+), 326 deletions(-) create mode 100644 junction/templates/proposals/partials/proposal-list--items.html diff --git a/docs/release_notes.md b/docs/release_notes.md index 8cb21c9e..7d227b04 100644 --- a/docs/release_notes.md +++ b/docs/release_notes.md @@ -1,5 +1,13 @@ # Release Notes +## [0.3.0-dev][0.3.0] + +__Date:__ unreleased + +__Fixes__ +- fix the tag filtering for all the proposal sections inside proposal list (#170) + + ## [0.2.0][0.2.0] __Date:__ 29th March 2015 @@ -28,6 +36,7 @@ __Date:__ 8th February 2015 - initial release with core functionality working +[0.3.0]: https://github.com/pythonindia/junction/compare/0.2.0...master [0.2.0]: https://github.com/pythonindia/junction/compare/0.1.0...0.2.0 [0.1.0]: https://github.com/pythonindia/junction/issues?q=milestone%3A%22release+0.1.0+-+initial+release%22 diff --git a/junction/proposals/views.py b/junction/proposals/views.py index fce7c9a6..703437dd 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals +from __future__ import unicode_literals, absolute_import # Third Party Stuff from django.conf import settings @@ -54,8 +54,6 @@ def list_proposals(request, conference_slug): if request.user.is_authenticated(): # Display the proposals by this user user_proposals_list = proposals_qs.filter(author=request.user) - selected_proposals_list = proposals_qs.filter(review_status=PROPOSAL_REVIEW_STATUS_SELECTED) - proposals_to_review = [] if _is_proposal_reviewer(request.user, conference): proposal_reviewer_sections = [p.proposal_section for p in @@ -70,20 +68,25 @@ def list_proposals(request, conference_slug): is_filtered = False if proposal_section_filter: - proposals_qs = proposals_qs.filter(proposal_section__id__in=proposal_section_filter) + proposals_qs = proposals_qs.filter( + proposal_section__id__in=proposal_section_filter) is_filtered = True if proposal_type_filter: - proposals_qs = proposals_qs.filter(proposal_type__id__in=proposal_type_filter) + proposals_qs = proposals_qs.filter( + proposal_type__id__in=proposal_type_filter) is_filtered = True + # make sure it's after the tag filtering is applied + selected_proposals_list = proposals_qs.filter( + review_status=PROPOSAL_REVIEW_STATUS_SELECTED) + # Display proposals which are public & exclude logged in user proposals if request.user.is_authenticated(): proposals_qs = proposals_qs.exclude(author=request.user.id) - public_proposals_list = proposals_qs.exclude( - review_status=PROPOSAL_REVIEW_STATUS_SELECTED).filter( - status=PROPOSAL_STATUS_PUBLIC).order_by('-created_at') + public_proposals_list = proposals_qs.exclude(review_status=PROPOSAL_REVIEW_STATUS_SELECTED).filter( + status=PROPOSAL_STATUS_PUBLIC).order_by('-created_at') proposal_sections = ProposalSection.objects.filter(conferences=conference) proposal_types = ProposalType.objects.filter(conferences=conference) @@ -146,13 +149,15 @@ def create_proposal(request, conference_slug): def detail_proposal(request, conference_slug, slug): conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=slug, conference=conference) - allow_private_comment = _is_proposal_author_or_reviewer(request.user, conference, proposal) + allow_private_comment = _is_proposal_author_or_reviewer( + request.user, conference, proposal) vote_value = 0 try: if request.user.is_authenticated(): - proposal_vote = ProposalVote.objects.get(proposal=proposal, voter=request.user) + proposal_vote = ProposalVote.objects.get( + proposal=proposal, voter=request.user) vote_value = 1 if proposal_vote.up_vote else -1 except ProposalVote.DoesNotExist: pass @@ -311,7 +316,8 @@ def create_proposal_comment(request, conference_slug, proposal_slug): @login_required def proposal_vote(request, conference_slug, proposal_slug, up_vote): conference = get_object_or_404(Conference, slug=conference_slug) - proposal = get_object_or_404(Proposal, slug=proposal_slug, conference=conference) + proposal = get_object_or_404( + Proposal, slug=proposal_slug, conference=conference) proposal_vote, created = ProposalVote.objects.get_or_create( proposal=proposal, voter=request.user) # @UnusedVariable @@ -365,5 +371,5 @@ def proposal_comment_up_vote(request, conference_slug, proposal_slug, @require_http_methods(['POST']) def proposal_comment_down_vote(request, conference_slug, proposal_slug, proposal_comment_id): - return proposal_comment_vote(request, conference_slug, proposal_slug, - proposal_comment_id, False) + return proposal_comment_vote(request, conference_slug, proposal_slug, + proposal_comment_id, False) diff --git a/junction/templates/proposals/list.html b/junction/templates/proposals/list.html index 483d077e..510613a9 100644 --- a/junction/templates/proposals/list.html +++ b/junction/templates/proposals/list.html @@ -73,330 +73,34 @@

Proposal Types


- + {% if is_filtered %} + View all proposals + {% endif %} + {% if conference.status == 1 %} + + New Proposal + + {% endif %} {% if proposals_to_review %} -
-
-
-
-

Proposals To Be Reviewed

-
-
-
-
- - {% for proposal in proposals_to_review %} -
-
-
- -
-

- - {{ proposal.get_comments_count }} - - - {{ proposal.get_votes_count }} - -

-

- {{ forloop.counter}}. {{ proposal.title|capfirst }} -

-
- - - - - {% if proposal.author.get_full_name %} - {{ proposal.author.get_full_name }} (~{{ proposal.author.username }}) - {% else %} - {{ proposal.author.username }} - {% endif %} - |  - {{ proposal.created_at|date:"d M, Y" }} - - -
- -
- - - Review this proposal - -
-
-
-
-
- {% endfor %} + {% include 'proposals/partials/proposal-list--items.html' with proposals=proposals_to_review title="Proposals To Be Reviewed" display_status=False %} {% endif %} {% if selected_proposals_list %} -
-
-
-
-

Selected Proposals

-
-
-
-
+ {% include 'proposals/partials/proposal-list--items.html' with proposals=selected_proposals_list title="Selected Proposals" display_status=False %} {% endif %} - {% for proposal in selected_proposals_list %} -
-
-
- -
-

- - {{ proposal.get_comments_count }} - - - {{ proposal.get_votes_count }} - -

-

- {{ forloop.counter}}. {{ proposal.title|capfirst }} -

-
- - - - - {% if proposal.author.get_full_name %} - {{ proposal.author.get_full_name }} (~{{ proposal.author.username }}) - {% else %} - {{ proposal.author.username }} - {% endif %} - |  - {{ proposal.created_at|date:"d M, Y" }} - -
-
-
-
-
-
- {% endfor %} - - {% if user_proposals_list %} -
-
-
-
-

My Proposals

-
-
-
-
- - {% for proposal in user_proposals_list %} -
-
-
- -
-

- - {{ proposal.get_comments_count }} - - - {{ proposal.get_votes_count }} - -

-

- {{ forloop.counter}}. {{ proposal.title|capfirst }} -

-
- - - - - {% if proposal.author.get_full_name %} - {{ proposal.author.get_full_name }} (~{{ proposal.author.username }}) - {% else %} - {{ proposal.author.username }} - {% endif %} - |  - {{ proposal.created_at|date:"d M, Y" }} - -
-
-
-
-
-
- {% endfor %} + {% include 'proposals/partials/proposal-list--items.html' with proposals=user_proposals_list title="My Proposals" display_status=True %} {% endif %} -
-
- {% if conference.status == 1 %} - - New Proposal - - {% endif %} -
-
-

List of Proposals

- {% if is_filtered %} View All{% endif %} - -
-
-
-
- - {% if not public_proposals_list %} -

No proposals found.

+ {% if public_proposals_list %} + {% include 'proposals/partials/proposal-list--items.html' with proposals=public_proposals_list title="List of Proposals" display_status=False %} + {% else %} +
+

List of Proposals

+

No proposals avaiable yet.

{% endif %} - - {% for proposal in public_proposals_list %} -
-
-
- -
-

- - {{ proposal.get_votes_count }} - - - {{ proposal.get_comments_count }} - -

-

- {{ forloop.counter}}. {{ proposal.title|capfirst }} -

-
- - - - - {% if proposal.author.get_full_name %} - {{ proposal.author.get_full_name }} (~{{ proposal.author.username }}) - {% else %} - {{ proposal.author.username }} - {% endif %} - |  - {{ proposal.created_at|date:"d M, Y" }} - -
-
-
-
-
- {% endfor %}
diff --git a/settings/common.py b/settings/common.py index 3c1fdb9b..ebdded5b 100644 --- a/settings/common.py +++ b/settings/common.py @@ -32,6 +32,7 @@ 'site_description': 'Junction is a software to manage proposals, reviews, schedule, feedback during conference.', 'google_analytics_id': os.environ.get('GOOGLE_ANALYTICS_ID', None), 'site_url': SITE_URL, + 'settings': 'Copyright © 2015. Python Software Society of India.' } MIDDLEWARE_CLASSES = ( From 50c350f7c381ff0e93d6b21e17deffb991dd8c0f Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Wed, 15 Apr 2015 23:48:23 +0530 Subject: [PATCH 017/666] Rename settings to footer --- junction/templates/base.html | 2 +- settings/common.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/junction/templates/base.html b/junction/templates/base.html index a9e14fff..bfc572c4 100644 --- a/junction/templates/base.html +++ b/junction/templates/base.html @@ -147,7 +147,7 @@
-

{{ SITE_INFO.settings }}

+

{{ SITE_INFO.footer }}

diff --git a/settings/common.py b/settings/common.py index ebdded5b..8d8e772a 100644 --- a/settings/common.py +++ b/settings/common.py @@ -32,7 +32,7 @@ 'site_description': 'Junction is a software to manage proposals, reviews, schedule, feedback during conference.', 'google_analytics_id': os.environ.get('GOOGLE_ANALYTICS_ID', None), 'site_url': SITE_URL, - 'settings': 'Copyright © 2015. Python Software Society of India.' + 'footer': 'Copyright © 2015. Python Software Society of India.' } MIDDLEWARE_CLASSES = ( From 08d7ee1940a2b3fccfa8066fb610869162bfa0c3 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Thu, 16 Apr 2015 10:14:14 +0530 Subject: [PATCH 018/666] Fix typo on proposal detail page s/URLS/URLs --- junction/templates/proposals/detail/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index b0fc562a..72af34a6 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -113,7 +113,7 @@

{% if proposal.content_urls %}

- Content URLS : + Content URLs :

{{ proposal.content_urls|markdown }} From 1250377f1a245a8be7a66409265358877b87a62f Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Thu, 16 Apr 2015 10:55:32 +0530 Subject: [PATCH 019/666] Fix SITE_INFO.footer, allow html content to be rendered __why__ strings like `©` will not render properly if the variable is not marked as `safe`. --- junction/templates/base.html | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/junction/templates/base.html b/junction/templates/base.html index bfc572c4..27a89778 100644 --- a/junction/templates/base.html +++ b/junction/templates/base.html @@ -132,14 +132,13 @@ {% render_breadcrumbs "django_bootstrap_breadcrumbs/bootstrap3.html" %} -

+
{% block content %} {% endblock %}
-
@@ -147,7 +146,7 @@
-

{{ SITE_INFO.footer }}

+

{{ SITE_INFO.footer|safe }}

From 15c470c28006a4fe24b385641634ece6ed38ccaf Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Thu, 16 Apr 2015 11:05:36 +0530 Subject: [PATCH 020/666] Update proposal writeup styling closes #180 --- junction/static/css/app.css | 4 + junction/static/css/details.css | 2 +- junction/static/less/proposals.less | 4 + junction/templates/base.html | 1 - junction/templates/proposals/detail/base.html | 73 ++++++++----------- 5 files changed, 40 insertions(+), 44 deletions(-) diff --git a/junction/static/css/app.css b/junction/static/css/app.css index d4127f71..d8c4cd0e 100644 --- a/junction/static/css/app.css +++ b/junction/static/css/app.css @@ -8638,6 +8638,10 @@ a.status:focus { .proposal-meta table td { padding: 3px; } +.proposal-writeup .heading { + border-bottom: 1px solid #eee; + padding-bottom: 5px; +} .comments-and-reviews-panel { margin-bottom: 20px; } diff --git a/junction/static/css/details.css b/junction/static/css/details.css index 90d8eeaa..d6600093 100644 --- a/junction/static/css/details.css +++ b/junction/static/css/details.css @@ -70,4 +70,4 @@ .porsal-title-section .col-sm-12{ height:100px; } -} \ No newline at end of file +} diff --git a/junction/static/less/proposals.less b/junction/static/less/proposals.less index 6601fd59..c0ebe5d7 100644 --- a/junction/static/less/proposals.less +++ b/junction/static/less/proposals.less @@ -43,6 +43,10 @@ } } } +.proposal-writeup .heading { + border-bottom: 1px solid #eee; + padding-bottom: 5px; +} .comments-and-reviews-panel { margin-bottom: 20px; diff --git a/junction/templates/base.html b/junction/templates/base.html index 27a89778..9862a6d1 100644 --- a/junction/templates/base.html +++ b/junction/templates/base.html @@ -172,5 +172,4 @@ {% endif %} - diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index 72af34a6..fc8126c1 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -94,52 +94,41 @@

-
-

- Description : -

-

- {{ proposal.description|markdown }} -

+
+
+

{{ proposal.description|markdown }}

+
- {% if proposal.prerequisites %} -

- Prerequisites : -

-

- {{ proposal.prerequisites|markdown }} -

- {% endif %} + {% if proposal.prerequisites %} +
+

Prerequisites:

+

{{ proposal.prerequisites|markdown }}

+
+ {% endif %} - {% if proposal.content_urls %} -

- Content URLs : -

-

- {{ proposal.content_urls|markdown }} -

- {% endif %} + {% if proposal.content_urls %} +
+

Content URLs:

+

{{ proposal.content_urls|markdown }}

+
+ {% endif %} - {% if proposal.speaker_info %} -

- Speaker Info : -

-

- {{ proposal.speaker_info|markdown }} -

- {% endif %} + {% if proposal.speaker_info %} +
+

Speaker Info:

+

{{ proposal.speaker_info|markdown }}

+
+ {% endif %} - {% if proposal.speaker_links %} -

- Speaker Links : -

-

- {{ proposal.speaker_links|markdown }} -

- {% endif %} -
+ {% if proposal.speaker_links %} +
+

Speaker Links:

+

{{ proposal.speaker_links|markdown }}

+
+ {% endif %} + -
+
@@ -169,7 +158,7 @@

Section:
{% include "social_shares.html" %} -
+
From 34bc1d2c34540ae0a4ef8062f1256389d7213ce9 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Thu, 16 Apr 2015 11:54:55 +0530 Subject: [PATCH 021/666] Change the order of social share button to look better --- junction/static/css/app.css | 2 +- junction/static/less/proposals.less | 2 +- junction/templates/social_shares.html | 48 +++++++++++---------------- 3 files changed, 21 insertions(+), 31 deletions(-) diff --git a/junction/static/css/app.css b/junction/static/css/app.css index d8c4cd0e..3fb539b5 100644 --- a/junction/static/css/app.css +++ b/junction/static/css/app.css @@ -8636,7 +8636,7 @@ a.status:focus { padding: 0; } .proposal-meta table td { - padding: 3px; + padding: 3px !important; } .proposal-writeup .heading { border-bottom: 1px solid #eee; diff --git a/junction/static/less/proposals.less b/junction/static/less/proposals.less index c0ebe5d7..82d594b9 100644 --- a/junction/static/less/proposals.less +++ b/junction/static/less/proposals.less @@ -39,7 +39,7 @@ table { td { - padding: 3px; + padding: 3px !important; } } } diff --git a/junction/templates/social_shares.html b/junction/templates/social_shares.html index 2465b945..aa4283b1 100644 --- a/junction/templates/social_shares.html +++ b/junction/templates/social_shares.html @@ -29,33 +29,23 @@ -
    -
  • -

    - -

    -
  • -
  • -

    -

    -
    -

    -
  • -
  • -

    - -

    -

    -
  • -
+

+

+

+ +
+
+

From fe3c1d0f052b38304bc693a13b4c58b46d721c9b Mon Sep 17 00:00:00 2001 From: Nabeel Valapra Date: Thu, 16 Apr 2015 13:09:30 +0530 Subject: [PATCH 022/666] #203 Fix --- junction/proposals/models.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index d39ed0b9..c2afe3c4 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -71,10 +71,10 @@ class Proposal(TimeAuditModel): description = models.TextField(default="") target_audience = models.PositiveSmallIntegerField( choices=PROPOSAL_TARGET_AUDIENCES, default=1, verbose_name="Target Audience") - prerequisites = models.TextField(default="") - content_urls = models.TextField(default="") - speaker_info = models.TextField(default="") - speaker_links = models.TextField(default="") + prerequisites = models.TextField(blank=True, default="") + content_urls = models.TextField(blank=True, default="") + speaker_info = models.TextField(blank=True, default="") + speaker_links = models.TextField(blank=True, default="") status = models.PositiveSmallIntegerField( choices=PROPOSAL_STATUS_LIST, default=1) review_status = models.PositiveSmallIntegerField( From 0665ba83910f1885d65dd2c36c5f6fbba7c045ba Mon Sep 17 00:00:00 2001 From: Nabeel Valapra Date: Thu, 16 Apr 2015 16:18:25 +0530 Subject: [PATCH 023/666] Adding migration file --- .../migrations/0006_auto_20150416_1612.py | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 junction/proposals/migrations/0006_auto_20150416_1612.py diff --git a/junction/proposals/migrations/0006_auto_20150416_1612.py b/junction/proposals/migrations/0006_auto_20150416_1612.py new file mode 100644 index 00000000..7183d989 --- /dev/null +++ b/junction/proposals/migrations/0006_auto_20150416_1612.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0005_proposalsectionreviewer_active'), + ] + + operations = [ + migrations.AlterField( + model_name='proposal', + name='content_urls', + field=models.TextField(default='', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='proposal', + name='prerequisites', + field=models.TextField(default='', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='proposal', + name='review_status', + field=models.PositiveSmallIntegerField(default=1, verbose_name='Review Status', choices=[(1, 'Yet to be reviewed'), (2, 'Selected'), (3, 'Rejected'), (4, 'On hold'), (5, 'Wait-listed')]), + preserve_default=True, + ), + migrations.AlterField( + model_name='proposal', + name='speaker_info', + field=models.TextField(default='', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='proposal', + name='speaker_links', + field=models.TextField(default='', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='proposal', + name='status', + field=models.PositiveSmallIntegerField(default=1, choices=[(2, 'Public'), (1, 'Draft'), (3, 'Cancelled')]), + preserve_default=True, + ), + ] From 07a6b7cb0af15b8685493bd053738e7f321467b3 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sun, 19 Apr 2015 22:22:10 +0530 Subject: [PATCH 024/666] added license to readme --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 014befdd..a02b2d00 100644 --- a/README.md +++ b/README.md @@ -77,3 +77,11 @@ Contributing [issue-list]: https://github.com/pythonindia/junction/issues/ [new-issue]: https://github.com/pythonindia/junction/issues/new [guidelines]: https://github.com/pythonindia/junction/blob/master/CONTRIBUTING.md + + +License +------- + +This software is licensed under The MIT License(MIT). See the [LICENSE][LICENSE] file in the top distribution directory for the full license text. + +[LICENSE]: https://github.com/pythonindia/junction/blob/master/LICENSE From 120d342b558793774d72495f55d651bbd2a65363 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 20 Apr 2015 21:41:25 +0530 Subject: [PATCH 025/666] fix mixed content --- junction/templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/templates/base.html b/junction/templates/base.html index 27a89778..40f47d50 100644 --- a/junction/templates/base.html +++ b/junction/templates/base.html @@ -51,7 +51,7 @@ - + {% block style_extra %} {% endblock %} From 054003d5f01b4ef7c7d0a3e2afbee289b1d375a9 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Wed, 22 Apr 2015 01:01:40 +0530 Subject: [PATCH 026/666] Add default comment text and fix or in condition proposal detail view --- junction/conferences/management/commands/sample_data.py | 1 + junction/proposals/views.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/junction/conferences/management/commands/sample_data.py b/junction/conferences/management/commands/sample_data.py index a8aeca55..c909482b 100644 --- a/junction/conferences/management/commands/sample_data.py +++ b/junction/conferences/management/commands/sample_data.py @@ -217,6 +217,7 @@ def create_proposal_comment(self, users): comment = ProposalComment.objects.create( proposal=self.sd.choice(self.proposals), private=self.sd.boolean(), + comment='Comment', commenter=commenter) return comment diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 42bd07e4..c7a4f910 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -44,7 +44,7 @@ def _is_proposal_section_reviewer(user, conference, proposal): def _is_proposal_author_or_proposal_section_reviewer(user, conference, proposal): - return _is_proposal_author(user, proposal) and \ + return _is_proposal_author(user, proposal) or \ _is_proposal_section_reviewer(user, conference, proposal) From afa66ceee7763ff5714e3768603e17054de78728 Mon Sep 17 00:00:00 2001 From: Anand Date: Thu, 23 Apr 2015 19:17:49 +0530 Subject: [PATCH 027/666] fix mis aligned header --- junction/templates/proposals/list.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junction/templates/proposals/list.html b/junction/templates/proposals/list.html index 510613a9..e3072372 100644 --- a/junction/templates/proposals/list.html +++ b/junction/templates/proposals/list.html @@ -73,6 +73,8 @@

Proposal Types


+ +
{% if is_filtered %} View all proposals {% endif %} @@ -81,6 +83,7 @@

Proposal Types

New Proposal {% endif %} +
{% if proposals_to_review %} {% include 'proposals/partials/proposal-list--items.html' with proposals=proposals_to_review title="Proposals To Be Reviewed" display_status=False %} From 65d265df1da6322470cf67c8ba0a2be06f1cf1f1 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 27 Apr 2015 19:27:42 +0530 Subject: [PATCH 028/666] only proposal section reviewers can review proposal --- junction/proposals/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index c7a4f910..01e77d9c 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -232,7 +232,7 @@ def review_proposal(request, conference_slug, slug): conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=slug, conference=conference) - if not _is_proposal_reviewer(request.user, conference): + if not _is_proposal_section_reviewer(request.user, conference, proposal): return HttpResponseForbidden() if request.method == 'GET': From 2d75e3ae39dc15df17145d8274f65714c5697953 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 27 Apr 2015 19:28:54 +0530 Subject: [PATCH 029/666] added werkzeug to requirements --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index fc2385b1..a0f2a3cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,7 @@ redis==2.10.3 # Extensions # ------------------------------------------------- django-extensions==1.5.2 +Werkzeug==0.9.4 ipython==3.0.0 pyreadline==2.0 six==1.9.0 From 02cb768b506e6ffffc10aa830cbd51ccb2889b51 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 27 Apr 2015 19:45:47 +0530 Subject: [PATCH 030/666] fix lazy object --- junction/proposals/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 01e77d9c..a49dcb0a 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -36,7 +36,7 @@ def _is_proposal_reviewer(user, conference): def _is_proposal_section_reviewer(user, conference, proposal): - return ProposalSectionReviewer.objects.filter( + return user.is_authenticated() and ProposalSectionReviewer.objects.filter( conference_reviewer__reviewer=user, conference_reviewer__conference=conference, proposal_section=proposal.proposal_section, From 6b7d1f446422a3daa003ac8fd77fe9ffb69adce9 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 27 Apr 2015 20:21:35 +0530 Subject: [PATCH 031/666] add review link --- junction/proposals/views.py | 2 +- junction/templates/proposals/detail/base.html | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index a49dcb0a..0e16020c 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -170,8 +170,8 @@ def detail_proposal(request, conference_slug, slug): 'proposal': proposal, 'allow_private_comment': allow_private_comment, 'vote_value': vote_value, - 'can_delete': request.user == proposal.author, 'is_author': request.user == proposal.author, + 'is_reviewer': _is_proposal_section_reviewer(request.user, conference, proposal) } comments = ProposalComment.objects.filter( diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index fc8126c1..55c1f443 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -53,7 +53,7 @@

- {% if can_delete %} + {% if is_author %} {% endif %} + + {% if is_reviewer %} + Review proposal + {% endif %} From d45dd594d6e4d3b9edb4fa05d402da8eed84d9b9 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Thu, 7 May 2015 23:24:04 +0530 Subject: [PATCH 032/666] provide read access to private comments for all reviewers --- junction/proposals/views.py | 23 ++++++++++++------- junction/templates/proposals/detail/base.html | 6 ++--- .../templates/proposals/detail/comments.html | 6 ++++- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 0e16020c..cee16bf3 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -43,6 +43,11 @@ def _is_proposal_section_reviewer(user, conference, proposal): active=True).exists() +def _is_proposal_author_or_proposal_reviewer(user, conference, proposal): + return _is_proposal_author(user, proposal) or \ + _is_proposal_reviewer(user, conference) + + def _is_proposal_author_or_proposal_section_reviewer(user, conference, proposal): return _is_proposal_author(user, proposal) or \ _is_proposal_section_reviewer(user, conference, proposal) @@ -153,7 +158,8 @@ def create_proposal(request, conference_slug): def detail_proposal(request, conference_slug, slug): conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=slug, conference=conference) - allow_private_comment = _is_proposal_author_or_proposal_section_reviewer(request.user, conference, proposal) + read_private_comment = _is_proposal_author_or_proposal_reviewer(request.user, conference, proposal) + write_private_comment = _is_proposal_author_or_proposal_section_reviewer(request.user, conference, proposal) vote_value = 0 @@ -168,7 +174,8 @@ def detail_proposal(request, conference_slug, slug): ctx = { 'login_url': settings.LOGIN_URL, 'proposal': proposal, - 'allow_private_comment': allow_private_comment, + 'read_private_comment': read_private_comment, + 'write_private_comment': write_private_comment, 'vote_value': vote_value, 'is_author': request.user == proposal.author, 'is_reviewer': _is_proposal_section_reviewer(request.user, conference, proposal) @@ -178,14 +185,14 @@ def detail_proposal(request, conference_slug, slug): proposal=proposal, deleted=False, ) - if allow_private_comment: - ctx.update({ - 'reviewers_comments': comments.filter(private=True), - 'reviewers_proposal_comment_form': ProposalCommentForm( - initial={'private': True}) - }) + if read_private_comment: + ctx['reviewers_comments'] = comments.filter(private=True) + if write_private_comment: + ctx['reviewers_proposal_comment_form'] = ProposalCommentForm(initial={'private': True}) + ctx.update({'comments': comments.filter(private=False), 'proposal_comment_form': ProposalCommentForm()}) + return render(request, 'proposals/detail/base.html', ctx) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index 55c1f443..4a8b47f9 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -178,7 +178,7 @@

Speaker Links:

- {% if allow_private_comment %} + {% if read_private_comment %} - {% if read_private_comment %} {% endif %} + + {% if is_reviewer %} + + {% endif %}
@@ -201,6 +209,14 @@

Speaker Links:

{% endwith %}
{% endif %} + {% if is_reviewer %} +
+ This tab is for reviewers only. + {% with comments=reviewers_only_comments proposal_comment_form=reviewers_only_proposal_comment_form review_comments='1' %} + {% include "proposals/detail/comments.html" %} + {% endwith %} +
+ {% endif %} @@ -220,6 +236,9 @@

Speaker Links:

$('a[href=#reviewers-comments]').click(function(){ $('a[href=#js-reviewers]').parent().addClass('active').siblings().removeClass("active"); }); + $('a[href=#reviewers-only-comments]').click(function(){ + $('a[href=#js-only-reviewers]').parent().addClass('active').siblings().removeClass("active"); + }); }); diff --git a/junction/templates/proposals/detail/comments.html b/junction/templates/proposals/detail/comments.html index 0642b7fa..315c59b8 100644 --- a/junction/templates/proposals/detail/comments.html +++ b/junction/templates/proposals/detail/comments.html @@ -76,6 +76,8 @@
{% bootstrap_field proposal_comment_form.private %} + {% bootstrap_field proposal_comment_form.reviewer %} + {% buttons %} + + + + +
+
+

Review Proposal

+
+
+ {% csrf_token %} +
+ {% for field in proposal_review_form %} + {% if field.errors %} + {{field.errors}} + {% endif %} +
+ {{field}} +
+ {% endfor %} +
-
-
- -
+
+
+ +
+
+ +
- +
- - -
-

Reviewers Comments

-
-
-
-
-
{% endblock %} {% block script_extra %} - + {% endblock script_extra %} From f257fea6f4f32117cb15b794efc74ee8308af50d Mon Sep 17 00:00:00 2001 From: vijay Date: Fri, 29 May 2015 16:15:58 +0530 Subject: [PATCH 061/666] Removed name url to proposal-list Removed name url to proposal-list --- junction/templates/proposals/dashboard.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/junction/templates/proposals/dashboard.html b/junction/templates/proposals/dashboard.html index 76e496d7..d649d26d 100644 --- a/junction/templates/proposals/dashboard.html +++ b/junction/templates/proposals/dashboard.html @@ -94,7 +94,7 @@ {% for group,count in group_by_type.items %} {{count.3}} - {{count.0}} + {{count.0}} {{count.1}} {{count.2}} @@ -121,7 +121,7 @@ {% for group,count in group_by_reviewer_section.items %} {{count.3}} - {{count.0}} + {{count.0}} {{count.1}} {{count.2}} @@ -144,7 +144,7 @@ {% for group, count in group_by_section.items %} {{count.3}} - {{count.0}} + {{count.0}} {{count.1}} {{count.2}} From 00a3882ee91d1f11afaf4c3e63e5c9e8b654e679 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Fri, 29 May 2015 23:13:59 +0530 Subject: [PATCH 062/666] Create new model for reviewer vote values --- junction/proposals/admin.py | 8 +++- .../migrations/0009_auto_20150529_2216.py | 38 +++++++++++++++++++ junction/proposals/models.py | 12 +++++- junction/proposals/views.py | 8 ++-- junction/templates/proposals/review.html | 2 +- 5 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 junction/proposals/migrations/0009_auto_20150529_2216.py diff --git a/junction/proposals/admin.py b/junction/proposals/admin.py index a7e4d099..2edff0db 100644 --- a/junction/proposals/admin.py +++ b/junction/proposals/admin.py @@ -16,7 +16,8 @@ ProposalSectionReviewer, ProposalType, ProposalVote, - ProposalSectionReviewerVote + ProposalSectionReviewerVote, + ProposalSectionReviewerVoteValue ) @@ -46,6 +47,10 @@ class ProposalVoteAdmin(TimeAuditAdmin): TimeAuditAdmin.list_display +class ProposalSectionReviewerVoteValueAdmin(AuditAdmin): + list_display = ('vote_value', 'description') + AuditAdmin.list_display + + class ProposalSectionReviewerVoteAdmin(TimeAuditAdmin): list_display = ('proposal', 'voter', 'role', 'vote_value') + \ TimeAuditAdmin.list_display @@ -66,6 +71,7 @@ class ProposalCommentVoteAdmin(TimeAuditAdmin): admin.site.register(Proposal, ProposalAdmin) admin.site.register(ProposalVote, ProposalVoteAdmin) admin.site.register(ProposalSectionReviewerVote, ProposalSectionReviewerVoteAdmin) +admin.site.register(ProposalSectionReviewerVoteValue, ProposalSectionReviewerVoteValueAdmin) admin.site.register(ProposalComment, ProposalCommentAdmin) admin.site.register(ProposalCommentVote, ProposalCommentVoteAdmin) admin.site.register(ProposalSectionReviewer, ProposalSectionReviewerAdmin) diff --git a/junction/proposals/migrations/0009_auto_20150529_2216.py b/junction/proposals/migrations/0009_auto_20150529_2216.py new file mode 100644 index 00000000..741f0ea7 --- /dev/null +++ b/junction/proposals/migrations/0009_auto_20150529_2216.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('proposals', '0008_auto_20150528_2243'), + ] + + operations = [ + migrations.CreateModel( + name='ProposalSectionReviewerVoteValue', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')), + ('vote_value', models.SmallIntegerField()), + ('description', models.CharField(max_length=255)), + ('created_by', models.ForeignKey(related_name='created_proposalsectionreviewervotevalue_set', verbose_name='Created By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ('modified_by', models.ForeignKey(related_name='updated_proposalsectionreviewervotevalue_set', verbose_name='Modified By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ], + options={ + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.AlterField( + model_name='proposalsectionreviewervote', + name='vote_value', + field=models.ForeignKey(to='proposals.ProposalSectionReviewerVoteValue'), + preserve_default=True, + ), + ] diff --git a/junction/proposals/models.py b/junction/proposals/models.py index f5f7fc44..0005031e 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -143,6 +143,16 @@ class Meta: unique_together = ("proposal", "voter") +@python_2_unicode_compatible +class ProposalSectionReviewerVoteValue(AuditModel): + """ Proposal reviewer vote choices. """ + vote_value = models.SmallIntegerField() + description = models.CharField(max_length=255) + + def __str__(self): + return "[{}] {}".format(self.vote_value, self.description) + + @python_2_unicode_compatible class ProposalSectionReviewerVote(TimeAuditModel): @@ -150,7 +160,7 @@ class ProposalSectionReviewerVote(TimeAuditModel): proposal = models.ForeignKey(Proposal) voter = models.ForeignKey(ProposalSectionReviewer) role = models.PositiveSmallIntegerField(choices=PROPOSAL_USER_VOTE_ROLES, default=2) - vote_value = models.SmallIntegerField(default=True) + vote_value = models.ForeignKey(ProposalSectionReviewerVoteValue) def __str__(self): return "[{}] {}".format(self.vote_value, self.proposal) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 1c713f3e..0748ec54 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -27,7 +27,8 @@ ProposalSectionReviewer, ProposalType, ProposalVote, - ProposalSectionReviewerVote + ProposalSectionReviewerVote, + ProposalSectionReviewerVoteValue ) from .services import send_mail_for_new_comment, send_mail_for_new_proposal @@ -253,7 +254,7 @@ def review_proposal(request, conference_slug, slug): try: vote = ProposalSectionReviewerVote.objects.get(proposal=proposal, voter=request.user) - vote_value = vote.vote_value + vote_value = vote.vote_value.vote_value except ProposalSectionReviewerVote.DoesNotExist: pass @@ -283,7 +284,8 @@ def review_proposal(request, conference_slug, slug): 'proposal': proposal, 'vote_form_errors': vote_form.errors}) else: - vote.vote_value = vote_form.cleaned_data['vote_value'] + vote_value = vote_form.cleaned_data['vote_value'] + vote.vote_value = ProposalSectionReviewerVoteValue.objects.get(vote_value=vote_value) vote.save() if 'review-form' in request.POST: diff --git a/junction/templates/proposals/review.html b/junction/templates/proposals/review.html index f2596254..88bb529a 100644 --- a/junction/templates/proposals/review.html +++ b/junction/templates/proposals/review.html @@ -49,7 +49,7 @@

Proposal Voting

-
From 8e6c1c80d911efe7cdb0bfbf4fc5871c66b2de53 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Fri, 29 May 2015 23:14:20 +0530 Subject: [PATCH 063/666] Create default values for reviewer vote values --- .../conferences/management/commands/sample_data.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/junction/conferences/management/commands/sample_data.py b/junction/conferences/management/commands/sample_data.py index ff6fc901..56ddd2c8 100644 --- a/junction/conferences/management/commands/sample_data.py +++ b/junction/conferences/management/commands/sample_data.py @@ -18,7 +18,13 @@ # Junction Stuff from junction.base import constants from junction.conferences.models import Conference -from junction.proposals.models import Proposal, ProposalComment, ProposalSection, ProposalType +from junction.proposals.models import ( + Proposal, + ProposalComment, + ProposalSection, + ProposalType, + ProposalSectionReviewerVoteValue +) NUM_USERS = getattr(settings, "NUM_USERS", 10) NUM_CONFERENCES = getattr(settings, "NUM_CONFERENCES", 4) @@ -104,6 +110,10 @@ def handle(self, *args, **options): for x in range(NUM_REVIEWER_COMMENTS): self.create_proposal_comment(users=reviewers) + print(' Creating default choices for proposal reviewer vote values.') + for vote in constants.PROPOSAL_REVIEW_VOTES_LIST: + ProposalSectionReviewerVoteValue.objects.create(vote_value=vote[0], description=vote[1]) + def create_proposal_sections(self): sections = [] for count in range(NUM_PROPOSAL_SECTIONS): From 2ae6a0f21880547437f1ecdb58d71745aec9e9dd Mon Sep 17 00:00:00 2001 From: chillaranand Date: Fri, 29 May 2015 23:37:20 +0530 Subject: [PATCH 064/666] Fix bug in proposal review vote --- junction/proposals/views.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 0748ec54..e3016c17 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -253,10 +253,16 @@ def review_proposal(request, conference_slug, slug): vote_value = None try: - vote = ProposalSectionReviewerVote.objects.get(proposal=proposal, voter=request.user) + vote = ProposalSectionReviewerVote.objects.get( + proposal=proposal, + voter=ProposalSectionReviewer.objects.get( + conference_reviewer__reviewer=request.user, + conference_reviewer__conference=conference, + proposal_section=proposal.proposal_section), + ) vote_value = vote.vote_value.vote_value except ProposalSectionReviewerVote.DoesNotExist: - pass + vote = None if request.method == 'GET': @@ -285,8 +291,18 @@ def review_proposal(request, conference_slug, slug): 'vote_form_errors': vote_form.errors}) else: vote_value = vote_form.cleaned_data['vote_value'] - vote.vote_value = ProposalSectionReviewerVoteValue.objects.get(vote_value=vote_value) - vote.save() + if not vote: + vote = ProposalSectionReviewerVote.objects.create( + proposal=proposal, + voter=ProposalSectionReviewer.objects.get( + conference_reviewer__reviewer=request.user, + conference_reviewer__conference=conference, + proposal_section=proposal.proposal_section), + vote_value=ProposalSectionReviewerVoteValue.objects.get(vote_value=vote_value), + ) + else: + vote.vote_value = ProposalSectionReviewerVoteValue.objects.get(vote_value=vote_value) + vote.save() if 'review-form' in request.POST: review_form = ProposalReviewForm(request.POST) From 5e5c3e4ac7e7dda369c168e335dcc6c1cc30daa8 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Fri, 29 May 2015 23:40:15 +0530 Subject: [PATCH 065/666] Align options vertically --- junction/templates/proposals/review.html | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/junction/templates/proposals/review.html b/junction/templates/proposals/review.html index 88bb529a..6bb044df 100644 --- a/junction/templates/proposals/review.html +++ b/junction/templates/proposals/review.html @@ -9,7 +9,6 @@ {% endblock %} @@ -41,7 +40,7 @@

Proposal Voting

{% if field.errors %} {{field.errors}} {% endif %} -
+
{{field}}
{% endfor %} @@ -68,7 +67,7 @@

Review Proposal

{% if field.errors %} {{field.errors}} {% endif %} -
+
{{field}}
{% endfor %} From b36042b1d47522afdcfff40d6b125a055660dd9b Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sat, 30 May 2015 00:22:28 +0530 Subject: [PATCH 066/666] Use vote values from database --- junction/proposals/forms.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index 5ea6ae2e..53dc9602 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -10,10 +10,13 @@ from junction.base.constants import ( PROPOSAL_REVIEW_STATUS_LIST, PROPOSAL_STATUS_LIST, - PROPOSAL_TARGET_AUDIENCES, - PROPOSAL_REVIEW_VOTES_LIST + PROPOSAL_TARGET_AUDIENCES +) +from junction.proposals.models import ( + ProposalSection, + ProposalType, + ProposalSectionReviewerVoteValue ) -from junction.proposals.models import ProposalSection, ProposalType def _get_proposal_section_choices(conference): @@ -124,6 +127,7 @@ class ProposalReviewerVoteForm(forms.Form): Used by ProposalSectionReviewers to vote on proposals. """ vote_value = forms.ChoiceField( - choices=PROPOSAL_REVIEW_VOTES_LIST, + choices=((i.vote_value, i.description) + for i in ProposalSectionReviewerVoteValue.objects.all()), widget=forms.RadioSelect() ) From f9a6f6bb0d1fb4da9758c727e4c2d87e424eaf9c Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sat, 30 May 2015 00:44:59 +0530 Subject: [PATCH 067/666] Show vote value along with description --- junction/proposals/forms.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index 53dc9602..3b04a5c1 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -29,6 +29,11 @@ def _get_proposal_type_choices(conference): for cpt in ProposalType.objects.filter(conferences=conference)] +def _get_proposal_section_reviewer_vote_choices(): + return [(i.vote_value, '{} ({})'.format(i.description, i.vote_value)) + for i in ProposalSectionReviewerVoteValue.objects.all()] + + class HorizRadioRenderer(forms.RadioSelect.renderer): """ @@ -127,7 +132,6 @@ class ProposalReviewerVoteForm(forms.Form): Used by ProposalSectionReviewers to vote on proposals. """ vote_value = forms.ChoiceField( - choices=((i.vote_value, i.description) - for i in ProposalSectionReviewerVoteValue.objects.all()), + choices=_get_proposal_section_reviewer_vote_choices(), widget=forms.RadioSelect() ) From da5fd61b1239a9adfc1f9a056f76da617437e002 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sat, 30 May 2015 00:52:08 +0530 Subject: [PATCH 068/666] Display votes in decreasing order of their value --- junction/proposals/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 0005031e..8ca61967 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -152,6 +152,9 @@ class ProposalSectionReviewerVoteValue(AuditModel): def __str__(self): return "[{}] {}".format(self.vote_value, self.description) + class Meta: + ordering = ('-vote_value',) + @python_2_unicode_compatible class ProposalSectionReviewerVote(TimeAuditModel): From c0d764e098f2d9f5646ac832abe348b3c03f3998 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sat, 30 May 2015 01:25:10 +0530 Subject: [PATCH 069/666] Move voting to seperate end point --- junction/proposals/urls.py | 2 + junction/proposals/views.py | 96 ++++++++++++++++---------- junction/templates/proposals/vote.html | 64 +++++++++++++++++ 3 files changed, 125 insertions(+), 37 deletions(-) create mode 100644 junction/templates/proposals/vote.html diff --git a/junction/proposals/urls.py b/junction/proposals/urls.py index c540e86d..24d1b3d7 100644 --- a/junction/proposals/urls.py +++ b/junction/proposals/urls.py @@ -35,6 +35,8 @@ views.proposal_vote_up, name='proposal-vote-up'), url(r'^(?P[\w-]+)/down-vote/$', views.proposal_vote_down, name='proposal-vote-down'), + url(r'^(?P[\w-]+)/vote/$', + views.proposal_reviewer_vote, name='proposal-reviewer-vote'), ) # random addition to attempt to merge diff --git a/junction/proposals/views.py b/junction/proposals/views.py index e3016c17..9779ca8a 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -247,6 +247,44 @@ def review_proposal(request, conference_slug, slug): conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=slug, conference=conference) + if not _is_proposal_section_reviewer(request.user, conference, proposal): + return HttpResponseForbidden() + + if request.method == 'GET': + + comments = ProposalComment.objects.filter(proposal=proposal, deleted=False,) + + proposal_review_form = ProposalReviewForm(initial={'review_status': proposal.review_status}) + + ctx = { + 'proposal': proposal, + 'proposal_review_form': proposal_review_form, + 'reviewers_comments': comments.filter(private=True), + 'reviewers_proposal_comment_form': ProposalCommentForm(initial={'private': True}), + } + + return render(request, 'proposals/review.html', ctx) + + # POST Workflow + form = ProposalReviewForm(request.POST) + if not form.is_valid(): + return render(request, 'proposals/review.html', {'form': form, + 'proposal': proposal, + 'form_errors': form.errors}) + + # Valid Form + proposal.review_status = form.cleaned_data['review_status'] + proposal.save() + + return HttpResponseRedirect(reverse('proposals-list', args=[conference.slug])) + + +@login_required +@require_http_methods(['GET', 'POST']) +def proposal_reviewer_vote(request, conference_slug, slug): + conference = get_object_or_404(Conference, slug=conference_slug) + proposal = get_object_or_404(Proposal, slug=slug, conference=conference) + if not _is_proposal_section_reviewer(request.user, conference, proposal): return HttpResponseForbidden() @@ -266,53 +304,37 @@ def review_proposal(request, conference_slug, slug): if request.method == 'GET': - comments = ProposalComment.objects.filter(proposal=proposal, deleted=False,) - - proposal_review_form = ProposalReviewForm(initial={'review_status': proposal.review_status}) proposal_vote_form = ProposalReviewerVoteForm(initial={'vote_value': vote_value}) ctx = { 'proposal': proposal, - 'proposal_review_form': proposal_review_form, 'proposal_vote_form': proposal_vote_form, - 'reviewers_comments': comments.filter(private=True), - 'reviewers_proposal_comment_form': ProposalCommentForm(initial={'private': True}), 'vote_value': vote_value, } - return render(request, 'proposals/review.html', ctx) + return render(request, 'proposals/vote.html', ctx) # POST Workflow - if 'vote-form' in request.POST: - vote_form = ProposalReviewerVoteForm(request.POST) - if not vote_form.is_valid(): - return render(request, 'proposals/review.html', {'vote_form': vote_form, - 'proposal': proposal, - 'vote_form_errors': vote_form.errors}) - else: - vote_value = vote_form.cleaned_data['vote_value'] - if not vote: - vote = ProposalSectionReviewerVote.objects.create( - proposal=proposal, - voter=ProposalSectionReviewer.objects.get( - conference_reviewer__reviewer=request.user, - conference_reviewer__conference=conference, - proposal_section=proposal.proposal_section), - vote_value=ProposalSectionReviewerVoteValue.objects.get(vote_value=vote_value), - ) - else: - vote.vote_value = ProposalSectionReviewerVoteValue.objects.get(vote_value=vote_value) - vote.save() - - if 'review-form' in request.POST: - review_form = ProposalReviewForm(request.POST) - if not review_form.is_valid(): - return render(request, 'proposals/review.html', {'review_form': review_form, - 'proposal': proposal, - 'review_form_errors': review_form.errors}) - else: - proposal.review_status = review_form.cleaned_data['review_status'] - proposal.save() + form = ProposalReviewerVoteForm(request.POST) + if not form.is_valid(): + return render(request, 'proposals/vote.html', {'form': form, + 'proposal': proposal, + 'form_errors': form.errors}) + + # Valid Form + vote_value = form.cleaned_data['vote_value'] + if not vote: + vote = ProposalSectionReviewerVote.objects.create( + proposal=proposal, + voter=ProposalSectionReviewer.objects.get( + conference_reviewer__reviewer=request.user, + conference_reviewer__conference=conference, + proposal_section=proposal.proposal_section), + vote_value=ProposalSectionReviewerVoteValue.objects.get(vote_value=vote_value), + ) + else: + vote.vote_value = ProposalSectionReviewerVoteValue.objects.get(vote_value=vote_value) + vote.save() return HttpResponseRedirect(reverse('proposals-list', args=[conference.slug])) diff --git a/junction/templates/proposals/vote.html b/junction/templates/proposals/vote.html new file mode 100644 index 00000000..29440281 --- /dev/null +++ b/junction/templates/proposals/vote.html @@ -0,0 +1,64 @@ +{% extends 'base.html' %} +{% load bootstrap3 %} +{% load static from staticfiles %} +{% load django_bootstrap_breadcrumbs %} + +{% block head_title %} Proposal Voting | {{ block.super }} {% endblock %} + +{% block style_extra %} + +{% endblock %} + +{% block endhead %} + + +{% endblock %} + +{% block breadcrumbs %} + {{ block.super }} + {% breadcrumb proposal.conference.name "conference-detail" proposal.conference.slug %} + {% breadcrumb "Proposals" "proposals-list" proposal.conference.slug %} + {% breadcrumb proposal.title "proposal-detail" proposal.conference.slug proposal.slug %} + {% breadcrumb "Voting" "" %} +{% endblock %} + +{% block content %} +
+
+
+
+
+

Proposal Voting

+
+
+ {% csrf_token %} +
+ {% for field in proposal_vote_form %} + {% if field.errors %} + {{field.errors}} + {% endif %} +
+ {{field}} +
+ {% endfor %} +
+ +
+
+ +
+
+
+
+
+ +
+
+
+{% endblock %} From a20673b94ed22e514669a5ce1baef96389d07cbf Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sat, 30 May 2015 01:30:09 +0530 Subject: [PATCH 070/666] Remove unused function --- junction/proposals/views.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 9779ca8a..101606da 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -417,22 +417,6 @@ def proposal_vote_down(request, conference_slug, proposal_slug): return proposal_vote(request, conference_slug, proposal_slug, False) -@login_required -@require_http_methods(['POST']) -def proposal_section_reviewer_vote(request, conference_slug, proposal_slug, up_vote): - conference = get_object_or_404(Conference, slug=conference_slug) - proposal = get_object_or_404(Proposal, slug=proposal_slug, conference=conference) - - proposal_vote, created = ProposalSectionReviewerVote.objects.get_or_create( - proposal=proposal, voter=request.user) # @UnusedVariable - - proposal_vote.role = 2 - proposal_vote.up_vote = up_vote - proposal_vote.save() - - return HttpResponse(proposal.get_section_reviewer_votes_count()) - - def proposal_comment_vote(request, conference_slug, proposal_slug, comment_id, up_vote): conference = get_object_or_404(Conference, slug=conference_slug) From 15c9cdfb839dbce06c492622ed9fc2102b59bf60 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sat, 30 May 2015 02:25:42 +0530 Subject: [PATCH 071/666] fix flake8 errors --- junction/proposals/admin.py | 1 + junction/proposals/views.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/junction/proposals/admin.py b/junction/proposals/admin.py index 72323f81..2beba8b9 100644 --- a/junction/proposals/admin.py +++ b/junction/proposals/admin.py @@ -61,6 +61,7 @@ class ProposalCommentAdmin(TimeAuditAdmin): 'proposal', 'commenter', 'private', 'comment') + TimeAuditAdmin.list_display list_filter = ['private', 'reviewer'] + class ProposalCommentVoteAdmin(TimeAuditAdmin): list_display = ('proposal_comment', 'voter', 'up_vote') + \ TimeAuditAdmin.list_display diff --git a/junction/proposals/views.py b/junction/proposals/views.py index c991507e..e1bbb5bf 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -200,7 +200,7 @@ def detail_proposal(request, conference_slug, slug): if is_reviewer: ctx['reviewers_only_proposal_comment_form'] = ProposalCommentForm(initial={'reviewer': True}) ctx['reviewers_only_comments'] = comments.filter(reviewer=True) - ctx.update({'comments': comments.filter(private=False,reviewer=False), + ctx.update({'comments': comments.filter(private=False, reviewer=False), 'proposal_comment_form': ProposalCommentForm()}) return render(request, 'proposals/detail/base.html', ctx) @@ -265,7 +265,7 @@ def review_proposal(request, conference_slug, slug): 'reviewers_only_comments': comments.filter(review=True), 'reviewers_proposal_comment_form': ProposalCommentForm( initial={'private': True}), - 'reviewers_only_proposal_comment_form':ProposalCommentForm( + 'reviewers_only_proposal_comment_form': ProposalCommentForm( initial={'review': True}), } From 11af09bc623cd38b30d4a95233f91938cfa7ab54 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sat, 30 May 2015 02:30:34 +0530 Subject: [PATCH 072/666] add migration files --- junction/proposals/migrations/0010_merge.py | 15 +++++++++++++++ .../migrations/0011_auto_20150530_0224.py | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 junction/proposals/migrations/0010_merge.py create mode 100644 junction/proposals/migrations/0011_auto_20150530_0224.py diff --git a/junction/proposals/migrations/0010_merge.py b/junction/proposals/migrations/0010_merge.py new file mode 100644 index 00000000..c33eb3b7 --- /dev/null +++ b/junction/proposals/migrations/0010_merge.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0007_auto_20150522_2358'), + ('proposals', '0009_auto_20150529_2216'), + ] + + operations = [ + ] diff --git a/junction/proposals/migrations/0011_auto_20150530_0224.py b/junction/proposals/migrations/0011_auto_20150530_0224.py new file mode 100644 index 00000000..373dd3e5 --- /dev/null +++ b/junction/proposals/migrations/0011_auto_20150530_0224.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0010_merge'), + ] + + operations = [ + migrations.AlterModelOptions( + name='proposalsectionreviewervotevalue', + options={'ordering': ('-vote_value',)}, + ), + ] From aa37b0b3af6f44441e905a6d015d4b2b044a3378 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 30 May 2015 02:50:00 +0530 Subject: [PATCH 073/666] Remove proposer from reviewers only comment --- junction/proposals/services.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/junction/proposals/services.py b/junction/proposals/services.py index f362017a..4c6ea1f3 100644 --- a/junction/proposals/services.py +++ b/junction/proposals/services.py @@ -35,16 +35,21 @@ def send_mail_for_new_comment(proposal_comment, host, login_url): def comment_recipients(proposal_comment): proposal = proposal_comment.proposal if proposal_comment.private: - proposal_reviewers = set(ProposalSectionReviewer.objects.filter( - proposal_section=proposal.proposal_section)) - recipients = {proposal_reviewer.conference_reviewer.reviewer - for proposal_reviewer in proposal_reviewers} + recipients = _get_proposal_section_reviewers( + proposal=proposal) else: recipients = { comment.commenter for comment in proposal.proposalcomment_set .all().select_related('commenter')} - recipients.add(proposal.author) + if proposal_comment.reviewer: + # Don't add proposer to reviwer only comments + section_reviewers = _get_proposal_section_reviewers( + proposal=proposal) + recipients.union(section_reviewers) + else: + recipients.add(proposal.author) + return recipients @@ -68,3 +73,11 @@ def send_mail_for_new_proposal(proposal, host): 'host': host, 'proposal_url': proposal_url, 'login_url': login_url}) + + +def _get_proposal_section_reviewers(proposal): + proposal_reviewers = set(ProposalSectionReviewer.objects.filter( + proposal_section=proposal.proposal_section)) + recipients = {proposal_reviewer.conference_reviewer.reviewer + for proposal_reviewer in proposal_reviewers} + return recipients From 99867c6e7c415b6dccbc3743221d27a6302ff73c Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 30 May 2015 02:52:12 +0530 Subject: [PATCH 074/666] Fix PEP8 issues in detail proposal --- junction/proposals/views.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index e0f297b5..93ce209b 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -159,8 +159,10 @@ def create_proposal(request, conference_slug): def detail_proposal(request, conference_slug, slug): conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=slug, conference=conference) - read_private_comment = _is_proposal_author_or_proposal_reviewer(request.user, conference, proposal) - write_private_comment = _is_proposal_author_or_proposal_section_reviewer(request.user, conference, proposal) + read_private_comment = _is_proposal_author_or_proposal_reviewer( + request.user, conference, proposal) + write_private_comment = _is_proposal_author_or_proposal_section_reviewer( + request.user, conference, proposal) is_reviewer = _is_proposal_reviewer(request.user, conference) vote_value = 0 @@ -179,7 +181,8 @@ def detail_proposal(request, conference_slug, slug): 'write_private_comment': write_private_comment, 'vote_value': vote_value, 'is_author': request.user == proposal.author, - 'is_reviewer': _is_proposal_section_reviewer(request.user, conference, proposal) + 'is_reviewer': _is_proposal_section_reviewer(request.user, conference, + proposal) } comments = ProposalComment.objects.filter( @@ -189,11 +192,13 @@ def detail_proposal(request, conference_slug, slug): if read_private_comment: ctx['reviewers_comments'] = comments.filter(private=True) if write_private_comment: - ctx['reviewers_proposal_comment_form'] = ProposalCommentForm(initial={'private': True}) + ctx['reviewers_proposal_comment_form'] = ProposalCommentForm( + initial={'private': True}) if is_reviewer: - ctx['reviewers_only_proposal_comment_form'] = ProposalCommentForm(initial={'reviewer': True}) + ctx['reviewers_only_proposal_comment_form'] = ProposalCommentForm( + initial={'reviewer': True}) ctx['reviewers_only_comments'] = comments.filter(reviewer=True) - ctx.update({'comments': comments.filter(private=False,reviewer=False), + ctx.update({'comments': comments.filter(private=False, reviewer=False), 'proposal_comment_form': ProposalCommentForm()}) return render(request, 'proposals/detail/base.html', ctx) From e8e6c5a9eeea23e4c7944a1e153b85060a0d3feb Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 30 May 2015 03:16:08 +0530 Subject: [PATCH 075/666] Add custom queryset and manager for ProposalComment --- junction/proposals/models.py | 27 +++++++++++++++++++++++++++ junction/proposals/views.py | 6 +++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index f6fa0e06..3a28011b 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -143,6 +143,31 @@ class Meta: unique_together = ("proposal", "voter") +class ProposalCommentQuerySet(models.QuerySet): + def get_public_comments(self): + return self.filter(private=False, reviewer=False) + + def get_reviewers_comments(self): + return self.filter(private=True) + + def get_reviewers_only_comments(self): + return self.filter(reviewer=True) + + +class ProposalCommentManager(models.Manager): + def get_queryset(self): + return ProposalCommentQuerySet(self.model, using=self._db) + + def get_public_comments(self): + return self.get_queryset().get_public_comments() + + def get_reviewers_comments(self): + return self.get_queryset().get_reviewers_comments() + + def get_reviewers_only_comments(self): + return self.get_queryset().get_reviewers_only_comments() + + @python_2_unicode_compatible class ProposalComment(TimeAuditModel): @@ -154,6 +179,8 @@ class ProposalComment(TimeAuditModel): comment = models.TextField() deleted = models.BooleanField(default=False, verbose_name="Is Deleted?") + objects = ProposalCommentManager() + def __str__(self): return "[{} by {}] {}".format(self.comment, self.commenter.get_full_name(), diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 93ce209b..968604ca 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -190,15 +190,15 @@ def detail_proposal(request, conference_slug, slug): ) if read_private_comment: - ctx['reviewers_comments'] = comments.filter(private=True) + ctx['reviewers_comments'] = comments.get_reviewers_comments() if write_private_comment: ctx['reviewers_proposal_comment_form'] = ProposalCommentForm( initial={'private': True}) if is_reviewer: ctx['reviewers_only_proposal_comment_form'] = ProposalCommentForm( initial={'reviewer': True}) - ctx['reviewers_only_comments'] = comments.filter(reviewer=True) - ctx.update({'comments': comments.filter(private=False, reviewer=False), + ctx['reviewers_only_comments'] = comments.get_reviewers_only_comments() + ctx.update({'comments': comments.get_public_comments(), 'proposal_comment_form': ProposalCommentForm()}) return render(request, 'proposals/detail/base.html', ctx) From 3c17002cc2b00b2816aad86c2ee185b3881a7f50 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 30 May 2015 03:23:06 +0530 Subject: [PATCH 076/666] PEP8 fixes and use new methods in ProposalComment QS --- junction/proposals/admin.py | 1 + junction/proposals/views.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/junction/proposals/admin.py b/junction/proposals/admin.py index 0c43cb9b..5deeb5e0 100644 --- a/junction/proposals/admin.py +++ b/junction/proposals/admin.py @@ -50,6 +50,7 @@ class ProposalCommentAdmin(TimeAuditAdmin): 'proposal', 'commenter', 'private', 'comment') + TimeAuditAdmin.list_display list_filter = ['private', 'reviewer'] + class ProposalCommentVoteAdmin(TimeAuditAdmin): list_display = ('proposal_comment', 'voter', 'up_vote') + \ TimeAuditAdmin.list_display diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 968604ca..ba87a58c 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -262,11 +262,11 @@ def review_proposal(request, conference_slug, slug): ctx = { 'proposal': proposal, 'proposal_review_form': proposal_review_form, - 'reviewers_comments': comments.filter(private=True), - 'reviewers_only_comments': comments.filter(review=True), + 'reviewers_comments': comments.get_reviewers_comments(), + 'reviewers_only_comments': comments.get_reviewers_only_comments(), 'reviewers_proposal_comment_form': ProposalCommentForm( initial={'private': True}), - 'reviewers_only_proposal_comment_form':ProposalCommentForm( + 'reviewers_only_proposal_comment_form': ProposalCommentForm( initial={'review': True}), } From 0c37eb5b5a842a8cbe846937ee24269283ef1df4 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 30 May 2015 13:55:27 +0530 Subject: [PATCH 077/666] Add max connection timeout --- settings/common.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/settings/common.py b/settings/common.py index 8d8e772a..5768c23d 100644 --- a/settings/common.py +++ b/settings/common.py @@ -213,3 +213,7 @@ TWITTER_CONSUMER_SECRET = os.environ.get('TWITTER_CONSUMER_SECRET', None) TWITTER_ACCESS_TOKEN_KEY = os.environ.get('TWITTER_ACCESS_TOKEN_KEY', None) TWITTER_ACCESS_TOKEN_SECRET = os.environ.get('TWITTER_ACCESS_TOKEN_SECRET', None) + +# Add connection life time +# Make sure DB request held on for minimim 5 minutes +CONN_MAX_AGE = 300 From fdf35956f4f7241fe0b146e9799aba724ae0f256 Mon Sep 17 00:00:00 2001 From: Nabeel Valapra Date: Sat, 30 May 2015 16:54:16 +0530 Subject: [PATCH 078/666] Fixed empty space at bottom --- junction/static/css/app.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/junction/static/css/app.css b/junction/static/css/app.css index 64a0be13..401f996a 100644 --- a/junction/static/css/app.css +++ b/junction/static/css/app.css @@ -8395,10 +8395,6 @@ body { font-family: 'Open Sans', sans-serif; color: #333; } -html, -body { - height: 100%; -} footer { padding: 20px 0; background-color: #fff7f8; From 2ca5e27b8f878aed3e8479882ab2f1f321a0971b Mon Sep 17 00:00:00 2001 From: nabeel07 Date: Sat, 30 May 2015 17:37:08 +0530 Subject: [PATCH 079/666] Revert "Fixed empty space at bottom" --- junction/static/css/app.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/junction/static/css/app.css b/junction/static/css/app.css index 401f996a..64a0be13 100644 --- a/junction/static/css/app.css +++ b/junction/static/css/app.css @@ -8395,6 +8395,10 @@ body { font-family: 'Open Sans', sans-serif; color: #333; } +html, +body { + height: 100%; +} footer { padding: 20px 0; background-color: #fff7f8; From 245b4a88a6946fd623761e0849896a0b20795c7a Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 31 May 2015 16:14:01 +0530 Subject: [PATCH 080/666] Better message for CFP close --- junction/templates/proposals/closed.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/junction/templates/proposals/closed.html b/junction/templates/proposals/closed.html index 74da7717..dd0cb7f3 100644 --- a/junction/templates/proposals/closed.html +++ b/junction/templates/proposals/closed.html @@ -5,7 +5,7 @@ {% load url from future %} {% load i18n %} -{% block head_title %} Proposals are closed | {{ block.super }} {% endblock %} +{% block head_title %} CFP submission is closed | {{ block.super }} {% endblock %} {% block breadcrumbs %} {{ block.super }} @@ -18,9 +18,9 @@
-

{% trans "Proposals are closed" %}

+

{% trans "CFP submission is closed" %}

-

{% trans "We are sorry, but proposals are closed." %}

+

{% trans "We are no longer accepting proposals. You can prepare a session for open spaces or flash talks." %}

From 4bce3ad8b15fa737050791ac913153d56d9907a4 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 31 May 2015 18:41:03 +0530 Subject: [PATCH 081/666] Use select_related and aggregate functions to reduce DB calls --- junction/proposals/models.py | 8 ++++++-- junction/proposals/views.py | 12 ++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 3a28011b..852733ae 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -112,8 +112,12 @@ def get_reviews_comments_count(self): def get_votes_count(self): """ Show only the public comment count """ - up_vote_count = ProposalVote.objects.filter(proposal=self, up_vote=True).count() - down_vote_count = ProposalVote.objects.filter(proposal=self, up_vote=False).count() + votes = ProposalVote.objects.filter( + proposal=self + ).values('up_vote').annotate(counts=models.Count('up_vote')) + votes = {item['up_vote']: item['counts'] for item in votes} + up_vote_count = votes.get(True, 0) + down_vote_count = votes.get(False, 0) return up_vote_count - down_vote_count def status_text(self): diff --git a/junction/proposals/views.py b/junction/proposals/views.py index ba87a58c..632c230a 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -55,9 +55,13 @@ def _is_proposal_author_or_proposal_section_reviewer(user, conference, proposal) @require_http_methods(['GET']) def list_proposals(request, conference_slug): - conference = get_object_or_404(Conference, slug=conference_slug) + conference = get_object_or_404( + Conference, slug=conference_slug) + # .prefetch_related('proposal_types', 'proposal_sections') - proposals_qs = Proposal.objects.filter(conference=conference) + proposals_qs = Proposal.objects.select_related( + 'proposal_type', 'proposal_section', 'conference', 'author', + ).filter(conference=conference) user_proposals_list = [] if request.user.is_authenticated(): # Display the proposals by this user @@ -98,8 +102,8 @@ def list_proposals(request, conference_slug): public_proposals_list = proposals_qs.exclude(review_status=PROPOSAL_REVIEW_STATUS_SELECTED).filter( status=PROPOSAL_STATUS_PUBLIC).order_by('-created_at') - proposal_sections = ProposalSection.objects.filter(conferences=conference) - proposal_types = ProposalType.objects.filter(conferences=conference) + proposal_sections = conference.proposal_types.all() + proposal_types = conference.proposal_sections.all() return render(request, 'proposals/list.html', {'public_proposals_list': public_proposals_list, From 107ecdd3e9a1b17769537dea2892309e9bf24d41 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 31 May 2015 18:47:25 +0530 Subject: [PATCH 082/666] Removed unused imports --- junction/proposals/views.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 632c230a..e91b65fc 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -18,9 +18,7 @@ Proposal, ProposalComment, ProposalCommentVote, - ProposalSection, ProposalSectionReviewer, - ProposalType, ProposalVote ) from .services import send_mail_for_new_comment, send_mail_for_new_proposal From 1eb4f59b604cb3787e4de3d72e2701feca6ddac7 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Mon, 1 Jun 2015 11:32:16 +0530 Subject: [PATCH 083/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e6360614..19bebd93 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ python manage.py sample_data Initial auth data: admin/123123 -If docker and fig are not installed already: +If docker and fig are not installed already (Not mandatory): -------------------------------------------- Refer to (http://docs.docker.com/installation/) for detailed installation instructions. From 9ddb61184739b3a062f7558a14d4c3cf0561d4b7 Mon Sep 17 00:00:00 2001 From: vijay Date: Mon, 1 Jun 2015 12:23:18 +0530 Subject: [PATCH 084/666] Added Reviewers dashboard Added Reviewers dashboard --- junction/proposals/dashboard.py | 171 ++++++++++++++++++ junction/proposals/views.py | 97 ---------- .../proposals/reviewers_dashboard.html | 133 ++++++++++++++ junction/urls.py | 6 +- 4 files changed, 309 insertions(+), 98 deletions(-) create mode 100644 junction/proposals/dashboard.py create mode 100644 junction/templates/proposals/reviewers_dashboard.html diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py new file mode 100644 index 00000000..f4f25d32 --- /dev/null +++ b/junction/proposals/dashboard.py @@ -0,0 +1,171 @@ +from django.contrib.auth.decorators import login_required +from django.shortcuts import get_object_or_404, render +from django.views.decorators.http import require_http_methods +from django.http.response import HttpResponseForbidden + +from junction.base.constants import ( + PROPOSAL_STATUS_PUBLIC) +from junction.conferences.models import Conference + +from .models import ( + Proposal, + ProposalComment, + ProposalSectionReviewer +) +from junction.conferences.models import ( + ConferenceProposalReviewer + ) + + +@login_required +@require_http_methods(['GET']) +def proposal_dashbaord(request, conference_slug): + conference = get_object_or_404(Conference, slug=conference_slug) + + if not request.user.is_superuser: + return HttpResponseForbidden() + + proposals_qs = Proposal.objects.filter( + conference=conference, + status=PROPOSAL_STATUS_PUBLIC) + + by_type = {} + by_section = {} + by_reviewer = {} + by_audience = {} + reviewed_count = 0 + unreviewed_count = 0 + for proposal in proposals_qs: + pro_type = proposal.proposal_type + section = proposal.proposal_section + # dict structure {'id':[total, review, unreview, name]} + by_type.setdefault(pro_type.id, [0, 0, 0, pro_type.name]) + by_type[pro_type.id][0] = by_type[pro_type.id][0] + 1 + + by_section.setdefault(section.id, [0, 0, 0, section.name]) + by_section[section.id][0] = by_section[section.id][0] + 1 + private_comment_count = \ + ProposalComment.objects.filter( + proposal=proposal, + deleted=False, + private=True).count() + if private_comment_count: + reviewed_count = reviewed_count + 1 + by_type[pro_type.id][1] = by_type[pro_type.id][1] + 1 + by_section[section.id][1] = by_section[section.id][1] + 1 + else: + unreviewed_count = unreviewed_count + 1 + by_type[pro_type.id][2] = by_type[pro_type.id][2] + 1 + by_section[section.id][2] = by_section[section.id][2] + 1 + + sections = \ + ProposalSectionReviewer.objects.filter( + conference_reviewer__reviewer=request.user)\ + .distinct('proposal_section__id') + # Hande case if reviewer is added to section twice' + + for section in sections: + proposal_qs = proposals_qs.filter(proposal_section=section.proposal_section) + # due to space and number issue for key used this + key_id = '%s' % section.proposal_section.id + by_reviewer.setdefault( + key_id, + [proposal_qs.count(), 0, 0, section.proposal_section.name]) + for proposal in proposal_qs: + private_comment_count = ProposalComment.objects.filter( + proposal=proposal, deleted=False, private=True).count() + if private_comment_count: + by_reviewer[key_id][1] = by_reviewer[key_id][1] + 1 + else: + by_reviewer[key_id][2] = by_reviewer[key_id][2] + 1 + + audience_dict = { + 1: 'Beginner', + 2: 'Intermediate', + 3: 'Advanced' + } + + for proposal in proposals_qs: + audience = audience_dict[proposal.target_audience] + by_audience.setdefault(audience, [0, 0, 0, audience]) + private_comment_count = \ + ProposalComment.objects.filter( + proposal=proposal, + deleted=False, + private=True).count() + if private_comment_count: + by_audience[audience][1] = by_audience[audience][1] + 1 + by_audience[audience][0] = by_audience[audience][0] + 1 + else: + by_audience[audience][2] = by_audience[audience][2] + 1 + by_audience[audience][0] = by_audience[audience][0] + 1 + + ctx = { + 'conference': conference, + 'total': proposals_qs.count(), + 'reviewed': reviewed_count, + 'unreviewed': unreviewed_count, + 'group_by_type': by_type, + 'group_by_section': by_section, + 'group_by_reviewer_section': by_reviewer, + 'by_target_audience': by_audience + } + + return render(request, 'proposals/dashboard.html', ctx) + + +@login_required +@require_http_methods(['GET']) +def reviewer_dahboard(request, conference_slug): + conference = get_object_or_404(Conference, slug=conference_slug) + + if not request.user.is_superuser: + return HttpResponseForbidden() + conference_reviewers = ConferenceProposalReviewer.objects.filter( + conference=conference, active=True) + proposals_qs = Proposal.objects.filter( + conference=conference, + status=PROPOSAL_STATUS_PUBLIC) + by_conference = {} + by_section = {} + for reviewers in conference_reviewers: + id = reviewers.reviewer.id + by_conference.setdefault(id, [ + reviewers.reviewer.first_name, + reviewers.reviewer.last_name, 0]) + by_conference[id][2] = ProposalComment.objects.filter( + commenter=reviewers.reviewer, + deleted=False, + private=True).count() + # by_section is dict with + # find each reviewers section and their comments + # Need to rework on this code section to make it 1-2 loops + by_section.setdefault(id, { + 'reviewer': reviewers.reviewer, + 'interaction': []}) + reviewers_section = ProposalSectionReviewer.objects.filter( + conference_reviewer=reviewers) + for section in reviewers_section: + proposal_qs = proposals_qs.filter( + proposal_section=section.proposal_section) + commented = 0 + uncommented = 0 + for proposal in proposal_qs: + private_comment_count = ProposalComment.objects.filter( + proposal=proposal, deleted=False, + private=True, commenter=reviewers.reviewer).count() + if private_comment_count: + commented = commented + 1 + else: + uncommented = uncommented + 1 + by_section[id]['interaction'].append([ + proposal_qs.count(), commented, + uncommented, section.proposal_section.name]) + ctx = { + 'conference': conference, + 'conference_reviewers': conference_reviewers, + 'by_conference': by_conference, + 'by_section': by_section + } + + return render(request, 'proposals/reviewers_dashboard.html', ctx) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index e91b65fc..09eff696 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -402,100 +402,3 @@ def proposal_comment_down_vote(request, conference_slug, proposal_slug, proposal_comment_id): return proposal_comment_vote(request, conference_slug, proposal_slug, proposal_comment_id, False) - - -@login_required -@require_http_methods(['GET']) -def dashboard(request, conference_slug): - conference = get_object_or_404(Conference, slug=conference_slug) - - if not request.user.is_superuser: - return HttpResponseForbidden() - - proposals_qs = Proposal.objects.filter( - conference=conference, - status=PROPOSAL_STATUS_PUBLIC) - - by_type = {} - by_section = {} - by_reviewer = {} - by_audience = {} - reviewed_count = 0 - unreviewed_count = 0 - for proposal in proposals_qs: - pro_type = proposal.proposal_type - section = proposal.proposal_section - # dict structure {'id':[total, review, unreview, name]} - by_type.setdefault(pro_type.id, [0, 0, 0, pro_type.name]) - by_type[pro_type.id][0] = by_type[pro_type.id][0] + 1 - - by_section.setdefault(section.id, [0, 0, 0, section.name]) - by_section[section.id][0] = by_section[section.id][0] + 1 - private_comment_count = \ - ProposalComment.objects.filter( - proposal=proposal, - deleted=False, - private=True).count() - if private_comment_count: - reviewed_count = reviewed_count + 1 - by_type[pro_type.id][1] = by_type[pro_type.id][1] + 1 - by_section[section.id][1] = by_section[section.id][1] + 1 - else: - unreviewed_count = unreviewed_count + 1 - by_type[pro_type.id][2] = by_type[pro_type.id][2] + 1 - by_section[section.id][2] = by_section[section.id][2] + 1 - - sections = \ - ProposalSectionReviewer.objects.filter( - conference_reviewer__reviewer=request.user)\ - .distinct('proposal_section__id') - # Hande case if reviewer is added to section twice' - - for section in sections: - proposal_qs = proposals_qs.filter(proposal_section=section.proposal_section) - # due to space and number issue for key used this - key_id = '%s' % section.proposal_section.id - by_reviewer.setdefault( - key_id, - [proposal_qs.count(), 0, 0, section.proposal_section.name]) - for proposal in proposal_qs: - private_comment_count = ProposalComment.objects.filter( - proposal=proposal, deleted=False, private=True).count() - if private_comment_count: - by_reviewer[key_id][1] = by_reviewer[key_id][1] + 1 - else: - by_reviewer[key_id][2] = by_reviewer[key_id][2] + 1 - - audience_dict = { - 1: 'Beginner', - 2: 'Intermediate', - 3: 'Advanced' - } - - for proposal in proposals_qs: - audience = audience_dict[proposal.target_audience] - by_audience.setdefault(audience, [0, 0, 0, audience]) - private_comment_count = \ - ProposalComment.objects.filter( - proposal=proposal, - deleted=False, - private=True).count() - if private_comment_count: - by_audience[audience][1] = by_audience[audience][1] + 1 - by_audience[audience][0] = by_audience[audience][0] + 1 - else: - by_audience[audience][2] = by_audience[audience][2] + 1 - by_audience[audience][0] = by_audience[audience][0] + 1 - - ctx = { - 'conference': conference, - 'total': proposals_qs.count(), - 'reviewed': reviewed_count, - 'unreviewed': unreviewed_count, - 'group_by_type': by_type, - 'group_by_section': by_section, - 'group_by_reviewer_section': by_reviewer, - 'by_target_audience': by_audience - } - - return render(request, 'proposals/dashboard.html', ctx) diff --git a/junction/templates/proposals/reviewers_dashboard.html b/junction/templates/proposals/reviewers_dashboard.html new file mode 100644 index 00000000..81930abd --- /dev/null +++ b/junction/templates/proposals/reviewers_dashboard.html @@ -0,0 +1,133 @@ +{% extends 'base.html' %} + +{% load django_markdown %} +{% load static from staticfiles %} +{% load django_bootstrap_breadcrumbs %} + +{% block head_title %} {{ conference.name }} Reviewers dashbaord {% endblock %} +{% block og_title %} {{ conference.name }} Reviewers dashboard {% endblock %} +{% block og_description %} {{ conference.description|markdown|safe|striptags}} {% endblock %} +{% block page_description %} {{ conference.description|markdown|safe|striptags}} {% endblock %} + +{% block endhead %} + + +{% endblock %} + +{% block breadcrumbs %} + {{ block.super }} + {% breadcrumb conference.name "conference-detail" conference.slug %} + {% breadcrumb "Dashboard" "proposals-dashoboard" conference.slug %} +{% endblock %} + + +{% block navbar_logo %} + {% if conference.logo %} + + + + {% else %} + {{ conference.name }} + {% endif %} +{% endblock navbar_logo %} + +{% block page_classes %}{{ block.super}} page-proposals{% endblock page_classes %} + +{% block content %} +
+
+
+
+

+ + {{ conference.start_date }} – + {{ conference.end_date }} + + {% if is_proposal_reviewer %} + + Reviewer Dashboard + + {% endif %} + + {{ conference.get_status_display }} + +

+
+

{{ conference.description|markdown }}

+
+
+
+ +
+
+
+
By Reviewers
+
+ + + + + + + {% for id, data in by_conference.items %} + + + + + + + {% endfor %} +
ReviewersProposal commented
{{data.0}} {{data.1}}{{data.2}}
+
+
+
+ + +
+
+
+
+
Reviewer/Section
+
+ + + + + + {% for id,section in by_section.items %} + + + + + {% endfor %} +
ReviewersSection Based Stat
+ {{section.reviewer.first_name}} {{section.reviewer.last_name}} + + + + + + + + + {% for values in section.interaction %} + + + + + + + {% endfor %} + +
Section TotalReviewedYet to be reviewed
{{values.3}}{{values.0}}{{values.1}}{{values.2}}
+
+ +
+
+
+
+ + +
+ +{% endblock %} diff --git a/junction/urls.py b/junction/urls.py index e699db91..3234dc94 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -27,7 +27,11 @@ # Proposals related url(r'^(?P[\w-]+)/proposals/', include('junction.proposals.urls')), - url(r'^(?P[\w-]+)/dashboard/', 'junction.proposals.views.dashboard', name='proposal-dashboard'), + url(r'^(?P[\w-]+)/dashboard/reviewers/', + 'junction.proposals.dashboard.reviewer_dahboard', + name='proposal-reviewers-dashboard'), + url(r'^(?P[\w-]+)/dashboard/', + 'junction.proposals.dashboard.proposal_dashbaord', name='proposal-dashboard'), # Static Pages. TODO: to be refactored url(r'^speakers/$', TemplateView.as_view(template_name='static-content/speakers.html',), name='speakers-static'), From 7f0d53fd621b961ff3d28e58e4e71261f6ce75ac Mon Sep 17 00:00:00 2001 From: vijay Date: Mon, 1 Jun 2015 16:18:36 +0530 Subject: [PATCH 085/666] Fix to check if user is conference reviewers Fix to check if user is conference reviewers --- junction/proposals/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index e91b65fc..c8ec5544 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -183,8 +183,7 @@ def detail_proposal(request, conference_slug, slug): 'write_private_comment': write_private_comment, 'vote_value': vote_value, 'is_author': request.user == proposal.author, - 'is_reviewer': _is_proposal_section_reviewer(request.user, conference, - proposal) + 'is_reviewer': is_reviewer, } comments = ProposalComment.objects.filter( From 53364ab166775be2889a21afc395adb0cbb6652e Mon Sep 17 00:00:00 2001 From: "Haris Ibrahim K. V" Date: Mon, 1 Jun 2015 18:48:38 +0530 Subject: [PATCH 086/666] Edits the constants for Conference status acceptance and closure --- junction/base/constants.py | 4 ++-- .../migrations/0008_auto_20150601_1436.py | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 junction/conferences/migrations/0008_auto_20150601_1436.py diff --git a/junction/base/constants.py b/junction/base/constants.py index 58319bdf..715255ce 100644 --- a/junction/base/constants.py +++ b/junction/base/constants.py @@ -2,8 +2,8 @@ from __future__ import absolute_import, unicode_literals # Conference Application Choice Fields -CONFERENCE_STATUS_ACCEPTING_CFP = "Accepting Call for Proposals" -CONFERENCE_STATUS_CLOSED_CFP = "Closed for Proposals" +CONFERENCE_STATUS_ACCEPTING_CFP = "Accepting Proposals" +CONFERENCE_STATUS_CLOSED_CFP = "Proposal submission closed" CONFERENCE_STATUS_ACCEPTING_VOTES = "Accepting Votes" CONFERENCE_STATUS_SCHEDULE_PUBLISHED = "Schedule Published" diff --git a/junction/conferences/migrations/0008_auto_20150601_1436.py b/junction/conferences/migrations/0008_auto_20150601_1436.py new file mode 100644 index 00000000..4dfb357e --- /dev/null +++ b/junction/conferences/migrations/0008_auto_20150601_1436.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('conferences', '0007_auto_20150522_2358'), + ] + + operations = [ + migrations.AlterField( + model_name='conference', + name='status', + field=models.PositiveSmallIntegerField(verbose_name='Current Status', choices=[(1, 'Accepting Proposals'), (2, 'Proposal submission closed'), (3, 'Accepting Votes'), (4, 'Schedule Published')]), + preserve_default=True, + ), + ] From 0d4b9ee98057617bd08b0febabde8b1c512a7cd9 Mon Sep 17 00:00:00 2001 From: "Haris Ibrahim K. V" Date: Mon, 1 Jun 2015 20:41:32 +0530 Subject: [PATCH 087/666] Updates CONTRIBUTORS.txt --- CONTRIBUTORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 540a6ea3..c1119efc 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -12,6 +12,7 @@ Anand Reddy Pandikunta (gh:ChillarAnand) Anuvrat Parashar (gh:bhanuvrat/ @bhanuvrat) Aayush Kasurde Arjoonn Sharma (gh:theSage21) +Haris Ibrahim K V (gh:harisibrahimkv / @harisibrahimkv) * Possesses commit rights From 3d88ba7a728dcdc63477ede94b624a52626350cf Mon Sep 17 00:00:00 2001 From: vijay Date: Tue, 2 Jun 2015 07:31:07 +0530 Subject: [PATCH 088/666] Renamed and removed extra spaces Renamed and removed extra spaces --- junction/proposals/dashboard.py | 8 ++++---- junction/urls.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index f4f25d32..21a72536 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -19,7 +19,7 @@ @login_required @require_http_methods(['GET']) -def proposal_dashbaord(request, conference_slug): +def proposals_dashboard(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) if not request.user.is_superuser: @@ -81,8 +81,8 @@ def proposal_dashbaord(request, conference_slug): audience_dict = { 1: 'Beginner', - 2: 'Intermediate', - 3: 'Advanced' + 2: 'Intermediate', + 3: 'Advanced' } for proposal in proposals_qs: @@ -116,7 +116,7 @@ def proposal_dashbaord(request, conference_slug): @login_required @require_http_methods(['GET']) -def reviewer_dahboard(request, conference_slug): +def reviewer_comments_dashboard(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) if not request.user.is_superuser: diff --git a/junction/urls.py b/junction/urls.py index 3234dc94..2e5e1ea0 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -28,10 +28,10 @@ # Proposals related url(r'^(?P[\w-]+)/proposals/', include('junction.proposals.urls')), url(r'^(?P[\w-]+)/dashboard/reviewers/', - 'junction.proposals.dashboard.reviewer_dahboard', + 'junction.proposals.dashboard.reviewer_comments_dashboard', name='proposal-reviewers-dashboard'), url(r'^(?P[\w-]+)/dashboard/', - 'junction.proposals.dashboard.proposal_dashbaord', name='proposal-dashboard'), + 'junction.proposals.dashboard.proposals_dashboard', name='proposal-dashboard'), # Static Pages. TODO: to be refactored url(r'^speakers/$', TemplateView.as_view(template_name='static-content/speakers.html',), name='speakers-static'), From 8c3a4984b13dd827d592d649b14bc2da2940617a Mon Sep 17 00:00:00 2001 From: vijay Date: Tue, 2 Jun 2015 07:43:17 +0530 Subject: [PATCH 089/666] Made some cleanup --- junction/proposals/dashboard.py | 14 +++++--------- .../templates/proposals/reviewers_dashboard.html | 9 ++++----- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index 21a72536..77682130 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -130,19 +130,15 @@ def reviewer_comments_dashboard(request, conference_slug): by_section = {} for reviewers in conference_reviewers: id = reviewers.reviewer.id - by_conference.setdefault(id, [ - reviewers.reviewer.first_name, - reviewers.reviewer.last_name, 0]) - by_conference[id][2] = ProposalComment.objects.filter( + by_conference.setdefault(id, [reviewers.reviewer, 0]) + by_conference[id][1] = ProposalComment.objects.filter( commenter=reviewers.reviewer, - deleted=False, - private=True).count() + deleted=False, private=True).count() # by_section is dict with # find each reviewers section and their comments # Need to rework on this code section to make it 1-2 loops - by_section.setdefault(id, { - 'reviewer': reviewers.reviewer, - 'interaction': []}) + by_section.setdefault( + id, {'reviewer': reviewers.reviewer, 'interaction': []}) reviewers_section = ProposalSectionReviewer.objects.filter( conference_reviewer=reviewers) for section in reviewers_section: diff --git a/junction/templates/proposals/reviewers_dashboard.html b/junction/templates/proposals/reviewers_dashboard.html index 81930abd..cafa1652 100644 --- a/junction/templates/proposals/reviewers_dashboard.html +++ b/junction/templates/proposals/reviewers_dashboard.html @@ -65,15 +65,14 @@
- - + {% for id, data in by_conference.items %} - - - + + + {% endfor %} From c1051b9b9219704935fccbad765b665cd848318b Mon Sep 17 00:00:00 2001 From: vijay Date: Tue, 2 Jun 2015 07:58:29 +0530 Subject: [PATCH 090/666] Adjustment with flake8 Adjustment with flake8 --- junction/proposals/dashboard.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index 77682130..c6111b9a 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -132,18 +132,19 @@ def reviewer_comments_dashboard(request, conference_slug): id = reviewers.reviewer.id by_conference.setdefault(id, [reviewers.reviewer, 0]) by_conference[id][1] = ProposalComment.objects.filter( - commenter=reviewers.reviewer, - deleted=False, private=True).count() + commenter=reviewers.reviewer, + deleted=False, private=True).count() # by_section is dict with # find each reviewers section and their comments # Need to rework on this code section to make it 1-2 loops by_section.setdefault( - id, {'reviewer': reviewers.reviewer, 'interaction': []}) + id, + {'reviewer': reviewers.reviewer, 'interaction': []}) reviewers_section = ProposalSectionReviewer.objects.filter( - conference_reviewer=reviewers) + conference_reviewer=reviewers) for section in reviewers_section: proposal_qs = proposals_qs.filter( - proposal_section=section.proposal_section) + proposal_section=section.proposal_section) commented = 0 uncommented = 0 for proposal in proposal_qs: @@ -154,14 +155,16 @@ def reviewer_comments_dashboard(request, conference_slug): commented = commented + 1 else: uncommented = uncommented + 1 - by_section[id]['interaction'].append([ - proposal_qs.count(), commented, - uncommented, section.proposal_section.name]) + by_section[id]['interaction'].append( + [ + proposal_qs.count(), commented, + uncommented, section.proposal_section.name] + ) + ctx = { - 'conference': conference, - 'conference_reviewers': conference_reviewers, - 'by_conference': by_conference, - 'by_section': by_section - } + 'conference': conference, + 'conference_reviewers': conference_reviewers, + 'by_conference': by_conference, + 'by_section': by_section} return render(request, 'proposals/reviewers_dashboard.html', ctx) From ee7702f8d3a9bafa24361923ffd8298ae7246e82 Mon Sep 17 00:00:00 2001 From: vijay Date: Wed, 3 Jun 2015 22:12:45 +0530 Subject: [PATCH 091/666] Added myself to contributors Added myself to contributors --- CONTRIBUTORS.txt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index c1119efc..36420fe7 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -4,6 +4,7 @@ Code Contributors Sivasubramaniam Arunachalam (gh:sivaa / @sivaa_in)* Saurabh Kumar (gh:theskumar / @_theskumar)* Kracekumar Ramaraju (gh:kracekumar / @kracetheking)* +Vijay Bung (gh:vnbang2003 / @vnbang2003) * Kishor Bhat (gh:kbhat95) Ganeshkumar S (gh:ganeshks) Mudassir Ali (gh:mudassir0909) @@ -15,11 +16,3 @@ Arjoonn Sharma (gh:theSage21) Haris Ibrahim K V (gh:harisibrahimkv / @harisibrahimkv) * Possesses commit rights - -Special Thanks -============== - -The following haven't provided code directly, but have provided guidance and advice. - -Vijay Bung (gh:vnbang2003 / @vnbang2003) - From 48f79ad09e4f614c56b632ffb1ebc81e5a798076 Mon Sep 17 00:00:00 2001 From: theSage21 Date: Thu, 4 Jun 2015 16:35:43 +0530 Subject: [PATCH 092/666] source of comment mentioned along with (private message) flag in emails when comments by reviewer and by author instead of always saying "comment by reviewer" --- junction/templates/proposals/email/comment/message.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/templates/proposals/email/comment/message.html b/junction/templates/proposals/email/comment/message.html index fc8bdf0a..6c6bf634 100644 --- a/junction/templates/proposals/email/comment/message.html +++ b/junction/templates/proposals/email/comment/message.html @@ -1,7 +1,7 @@ There is a new comment on " {{proposal.title}} {% if comment.private %} -" by one of the reviewer.: +" by {{comment.commenter}}(private comment): {% else %} " by {{comment.commenter}}: {% endif %} From c0d137013f9ea10bb047bd3f6978932659f94534 Mon Sep 17 00:00:00 2001 From: theSage21 Date: Thu, 4 Jun 2015 16:46:12 +0530 Subject: [PATCH 093/666] The previous method leaked which reviewer had commented on the post. This was not desired and so has been fixed by having a condition check. --- junction/proposals/services.py | 3 ++- junction/templates/proposals/email/comment/message.html | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/junction/proposals/services.py b/junction/proposals/services.py index 4c6ea1f3..0de31f01 100644 --- a/junction/proposals/services.py +++ b/junction/proposals/services.py @@ -29,7 +29,8 @@ def send_mail_for_new_comment(proposal_comment, host, login_url): 'comment': proposal_comment, 'commenter': commenter, 'host': host, - 'login_url': login_url}) + 'login_url': login_url, + 'by_author': commenter == proposal.author}) def comment_recipients(proposal_comment): diff --git a/junction/templates/proposals/email/comment/message.html b/junction/templates/proposals/email/comment/message.html index 6c6bf634..d80ef269 100644 --- a/junction/templates/proposals/email/comment/message.html +++ b/junction/templates/proposals/email/comment/message.html @@ -1,7 +1,11 @@ There is a new comment on " {{proposal.title}} {% if comment.private %} -" by {{comment.commenter}}(private comment): + {% if by_author %} +" by by Author.: + {% else %} +" by by a Reviewer.: + {% endif %} {% else %} " by {{comment.commenter}}: {% endif %} From 2e9ee488cf4ba8be8736805fe556e7a7daa92387 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sun, 7 Jun 2015 23:16:35 +0530 Subject: [PATCH 094/666] Update url in proposal comments email message --- junction/proposals/services.py | 3 +-- junction/proposals/views.py | 17 +++++++++-------- .../proposals/email/comment/message.html | 2 +- .../proposals/email/comment/message.txt | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/junction/proposals/services.py b/junction/proposals/services.py index 0de31f01..df4766bb 100644 --- a/junction/proposals/services.py +++ b/junction/proposals/services.py @@ -15,7 +15,7 @@ logger = logging.getLogger(__name__) -def send_mail_for_new_comment(proposal_comment, host, login_url): +def send_mail_for_new_comment(proposal_comment, login_url): proposal = proposal_comment.proposal send_to = comment_recipients(proposal_comment) commenter = proposal_comment.commenter @@ -28,7 +28,6 @@ def send_mail_for_new_comment(proposal_comment, host, login_url): 'proposal': proposal, 'comment': proposal_comment, 'commenter': commenter, - 'host': host, 'login_url': login_url, 'by_author': commenter == proposal.author}) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 915f0a54..1444df7d 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -386,14 +386,15 @@ def create_proposal_comment(request, conference_slug, proposal_slug): proposal_comment = ProposalComment.objects.create( proposal=proposal, comment=comment, - private=private, reviewer=reviewer, commenter=request.user) - send_mail_for_new_comment( - proposal_comment, login_url=settings.LOGIN_URL, - host='{}://{}'.format(settings.SITE_PROTOCOL, - request.META['HTTP_HOST'])) - - redirect_url = reverse('proposal-detail', - args=[conference.slug, proposal.slug]) + private=private, reviewer=reviewer, commenter=request.user + ) + login_url = '{}://{}{}?next={}'.format( + settings.SITE_PROTOCOL, request.META['HTTP_HOST'], + settings.LOGIN_URL, proposal.get_absolute_url() + ) + send_mail_for_new_comment(proposal_comment, login_url=login_url) + + redirect_url = reverse('proposal-detail', args=[conference.slug, proposal.slug]) if private: redirect_url += "#js-reviewers" diff --git a/junction/templates/proposals/email/comment/message.html b/junction/templates/proposals/email/comment/message.html index d80ef269..017ee605 100644 --- a/junction/templates/proposals/email/comment/message.html +++ b/junction/templates/proposals/email/comment/message.html @@ -15,4 +15,4 @@
PS: Please, don't reply to the email. You can - login to and leave a comment + login to and leave a comment diff --git a/junction/templates/proposals/email/comment/message.txt b/junction/templates/proposals/email/comment/message.txt index 05b2b708..f0e1d8fa 100644 --- a/junction/templates/proposals/email/comment/message.txt +++ b/junction/templates/proposals/email/comment/message.txt @@ -2,4 +2,4 @@ There is a new comment on {{host}}{{proposal.get_absolute_url}} by {% if comment "{{comment.comment}}" ------------------------------------------------------------------------------- -PS: Please, don't reply to the email. You can login({{host}}{{login_url}})to and leave a comment +PS: Please, don't reply to the email. You can login({{login_url}})to and leave a comment From d1ac93ac48e7536e3cd66aa6b3d695418e75f38f Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Wed, 10 Jun 2015 00:54:51 +0530 Subject: [PATCH 095/666] Change "Reviewers Only" to "Reviewers Talk" --- junction/templates/proposals/detail/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index ed3e67a9..523e7542 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -194,7 +194,7 @@

Speaker Links:

{% endif %} From 01235b18b2e07615e832e6292efeac5142b7d744 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 13:12:19 +0530 Subject: [PATCH 096/666] modifiction to run heroku --- Procfile | 1 + requirements.txt | 2 +- settings/__init__.py | 6 ++++++ settings/heroku.py | 7 +++++++ uwsgi.ini | 7 +++++++ 5 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 Procfile create mode 100644 settings/heroku.py create mode 100644 uwsgi.ini diff --git a/Procfile b/Procfile new file mode 100644 index 00000000..1693c49a --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: uwsgi uwsgi.ini diff --git a/requirements.txt b/requirements.txt index 6c8aa682..e81786fb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ celery==3.1.18 # ------------------------------------------------- psycopg2==2.6 redis==2.10.3 - +dj-database-url==0.3.* # Extensions # ------------------------------------------------- diff --git a/settings/__init__.py b/settings/__init__.py index 21d5babc..92c54e7f 100644 --- a/settings/__init__.py +++ b/settings/__init__.py @@ -3,6 +3,7 @@ # Standard Library import sys +import os if "test" in sys.argv: print("\033[1;91mNo django tests.\033[0m") @@ -21,3 +22,8 @@ from .prod import * # noqa except ImportError: pass + +# heroku + +if 'DYNO' in os.environ: + from .heroku import * diff --git a/settings/heroku.py b/settings/heroku.py new file mode 100644 index 00000000..00dc45f9 --- /dev/null +++ b/settings/heroku.py @@ -0,0 +1,7 @@ +import dj_database_url + +DATABASES = { + 'default': dj_database_url.config() +} + +ALLOWED_HOSTS = ['*'] diff --git a/uwsgi.ini b/uwsgi.ini new file mode 100644 index 00000000..805f73ef --- /dev/null +++ b/uwsgi.ini @@ -0,0 +1,7 @@ +[uwsgi] +http-socket = :$(PORT) +master = true +processes = 4 +die-on-term = true +module = wsgi +memory-report = true From b36f4533b26886b84c0c5bc1243c49a02ce706f8 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 13:27:47 +0530 Subject: [PATCH 097/666] add uwsgi as part of requirements --- requirements.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/requirements.txt b/requirements.txt index e81786fb..512beaf1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -42,3 +42,7 @@ django-markdown==0.8.4 django-pagedown==0.1.0 mdx-linkify==0.6 Markdown==2.6.2 + +# Server +# ------------------------------------------------ +uwsgi==2.0.* From 608772cb28bdc1ef04f2aa82f94c1746bab4684e Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 13:47:35 +0530 Subject: [PATCH 098/666] set debug to false, serve staticfiles from uwsgi --- settings/heroku.py | 2 ++ uwsgi.ini | 2 ++ 2 files changed, 4 insertions(+) diff --git a/settings/heroku.py b/settings/heroku.py index 00dc45f9..4626efe7 100644 --- a/settings/heroku.py +++ b/settings/heroku.py @@ -5,3 +5,5 @@ } ALLOWED_HOSTS = ['*'] + +DEGUG = False diff --git a/uwsgi.ini b/uwsgi.ini index 805f73ef..38cbdc7a 100644 --- a/uwsgi.ini +++ b/uwsgi.ini @@ -5,3 +5,5 @@ processes = 4 die-on-term = true module = wsgi memory-report = true +check-static = junction/assets/collected-static +offload-threads = 4 From 9aa3b88af57dc35f9800fc28d5bbad271d26a122 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 13:51:23 +0530 Subject: [PATCH 099/666] fix debug spelling in heroku --- settings/heroku.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/heroku.py b/settings/heroku.py index 4626efe7..0195576d 100644 --- a/settings/heroku.py +++ b/settings/heroku.py @@ -6,4 +6,4 @@ ALLOWED_HOSTS = ['*'] -DEGUG = False +DEBUG = False From 479bd29a2be6ff4dedd73ddb5969e1fceb9793d1 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 14:11:30 +0530 Subject: [PATCH 100/666] set static map instead of check static --- uwsgi.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/uwsgi.ini b/uwsgi.ini index 38cbdc7a..d5db0425 100644 --- a/uwsgi.ini +++ b/uwsgi.ini @@ -5,5 +5,6 @@ processes = 4 die-on-term = true module = wsgi memory-report = true -check-static = junction/assets/collected-static offload-threads = 4 +static-map = /static=junction/assets/collected-static +# home = $(VIRTUAL_ENV) From fc79064d87447908296108c9f21c15736b8f2405 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 14:32:31 +0530 Subject: [PATCH 101/666] added noqa --- settings/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/__init__.py b/settings/__init__.py index 92c54e7f..ab7082e3 100644 --- a/settings/__init__.py +++ b/settings/__init__.py @@ -26,4 +26,4 @@ # heroku if 'DYNO' in os.environ: - from .heroku import * + from .heroku import * # noqa From fb02e7eeda8d48ede12a0a1e2a95cd4ff7657697 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 14:48:13 +0530 Subject: [PATCH 102/666] added deploy to heroku button and app.json for heroku --- README.md | 2 +- app.json | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 app.json diff --git a/README.md b/README.md index 19bebd93..908852b4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ junction ======== -[![Build Status](https://travis-ci.org/pythonindia/junction.svg)](https://travis-ci.org/pythonindia/junction) [![Coverage Status](https://coveralls.io/repos/pythonindia/junction/badge.svg?branch=master)](https://coveralls.io/r/pythonindia/junction?branch=master) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pythonindia/junction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy)[![Build Status](https://travis-ci.org/pythonindia/junction.svg)](https://travis-ci.org/pythonindia/junction) [![Coverage Status](https://coveralls.io/repos/pythonindia/junction/badge.svg?branch=master)](https://coveralls.io/r/pythonindia/junction?branch=master) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pythonindia/junction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) **Version**: 0.2.0-dev diff --git a/app.json b/app.json new file mode 100644 index 00000000..07c4a547 --- /dev/null +++ b/app.json @@ -0,0 +1,12 @@ +{ + "name": "Junction", + "description": "Junction is a software to manage proposals, reviews, schedule, feedback during conference.", + "repository": "https://github.com/pythonindia/junction/", + "keywords": ["python", "django", "CFP", "conference"], + "scripts": { + "postdeploy": "python manage.py migrate" + }, + "addons": [ + "heroku-postgresql" + ] +} From de2f3fac191d39ba1184a731d1a6eabd5693c8cf Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 14:50:02 +0530 Subject: [PATCH 103/666] cleanup readme --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 908852b4..fadcff98 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ junction ======== -[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy)[![Build Status](https://travis-ci.org/pythonindia/junction.svg)](https://travis-ci.org/pythonindia/junction) [![Coverage Status](https://coveralls.io/repos/pythonindia/junction/badge.svg?branch=master)](https://coveralls.io/r/pythonindia/junction?branch=master) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pythonindia/junction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy) + +[![Build Status](https://travis-ci.org/pythonindia/junction.svg)](https://travis-ci.org/pythonindia/junction) [![Coverage Status](https://coveralls.io/repos/pythonindia/junction/badge.svg?branch=master)](https://coveralls.io/r/pythonindia/junction?branch=master) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pythonindia/junction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) **Version**: 0.2.0-dev @@ -41,7 +43,7 @@ alias docker='sudo docker' alias fig='sudo fig' ``` -Finally, run +Finally, run ``` fig up ``` @@ -50,7 +52,7 @@ fig up Configuring Django-allauth --------------------------- - - Go to `http://localhost:8000/nimda/sites/site/` + - Go to `http://localhost:8000/nimda/sites/site/` - Change the default site's(the one with ID = 1) name and display to `localhost:8000` - Go to `Social Applications` in admin panel and add [Github](http://django-allauth.readthedocs.org/en/latest/providers.html#github) and [Google](http://django-allauth.readthedocs.org/en/latest/providers.html#google)'s auth details @@ -72,7 +74,7 @@ Contributing 1. Choose an [issue][issue-list] and ask any doubts in the issue thread. 2. Report any bugs/feature request as github [new issue][new-issue], if it's already not present. 3. If you are starting to work on an issue, please leave a comment saying "I am working on it". -4. Once you are done with feature/bug fix, send a pull request according to the [guidelines]. +4. Once you are done with feature/bug fix, send a pull request according to the [guidelines]. [issue-list]: https://github.com/pythonindia/junction/issues/ [new-issue]: https://github.com/pythonindia/junction/issues/new From fdfac1bcc9ec7a1eebe50c0f6bc553e867517b21 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 16:04:05 +0530 Subject: [PATCH 104/666] limit the allowed hosts to herokuapp.com --- settings/heroku.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/heroku.py b/settings/heroku.py index 0195576d..1316c248 100644 --- a/settings/heroku.py +++ b/settings/heroku.py @@ -4,6 +4,6 @@ 'default': dj_database_url.config() } -ALLOWED_HOSTS = ['*'] +ALLOWED_HOSTS = ['*.herokuapp.com'] DEBUG = False From 95ec0633dce48b842e791bb7218d10900ce3db8e Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 16:23:25 +0530 Subject: [PATCH 105/666] fix the allowed_hosts --- settings/heroku.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/heroku.py b/settings/heroku.py index 1316c248..367f7f40 100644 --- a/settings/heroku.py +++ b/settings/heroku.py @@ -4,6 +4,6 @@ 'default': dj_database_url.config() } -ALLOWED_HOSTS = ['*.herokuapp.com'] +ALLOWED_HOSTS = ['.herokuapp.com'] DEBUG = False From e3bb172fc1edd4a0e20a977854c1c9dcc0b86734 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 15 Jun 2015 00:36:00 +0530 Subject: [PATCH 106/666] Convert markdown to html while sending emails Junction comments support markdown. So comments should be converted to html while emailing. --- junction/base/emailer.py | 14 +++++++------- junction/proposals/services.py | 12 ++++++++++++ .../templates/proposals/email/comment/message.html | 2 +- requirements.txt | 1 + 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/junction/base/emailer.py b/junction/base/emailer.py index 86d71f69..2e3c573a 100644 --- a/junction/base/emailer.py +++ b/junction/base/emailer.py @@ -21,15 +21,15 @@ def send_email(to, context, template_dir): :rtype: None """ - expected_templates = {'message': 'message.txt', 'subject': 'subject.txt', - 'html_message': 'message.html'} + to_str = lambda x: render_to_string(path.join(template_dir, x), context).strip() - kwargs = {key: render_to_string(path.join(template_dir, template), - context).strip() - for key, template in expected_templates.items()} + subject = to_str('subject.txt') + text_message = to_str('message.txt') + html_message = to_str('message.html') + from_email = settings.DEFAULT_FROM_EMAIL + recipient_list = [_format_email(to)] - return send_mail(from_email=settings.DEFAULT_FROM_EMAIL, - recipient_list=[_format_email(to)], **kwargs) + return send_mail(subject, text_message, from_email, recipient_list, html_message=html_message) def _format_email(user): diff --git a/junction/proposals/services.py b/junction/proposals/services.py index df4766bb..5ffc1a9e 100644 --- a/junction/proposals/services.py +++ b/junction/proposals/services.py @@ -6,6 +6,8 @@ # Third Party Stuff from django.conf import settings +import pypandoc + # Junction Stuff from junction.base.emailer import send_email @@ -15,10 +17,20 @@ logger = logging.getLogger(__name__) +def markdown_to_html(markdown): + """ + Convert given markdown to html. + :param markdown: string + :return: string - converted html + """ + return pypandoc.convert(markdown, 'html', format='markdown') + + def send_mail_for_new_comment(proposal_comment, login_url): proposal = proposal_comment.proposal send_to = comment_recipients(proposal_comment) commenter = proposal_comment.commenter + proposal_comment.comment = markdown_to_html(proposal_comment.comment) for to in send_to: if to == proposal_comment.commenter: continue diff --git a/junction/templates/proposals/email/comment/message.html b/junction/templates/proposals/email/comment/message.html index 017ee605..fe6ce706 100644 --- a/junction/templates/proposals/email/comment/message.html +++ b/junction/templates/proposals/email/comment/message.html @@ -11,7 +11,7 @@ {% endif %}

-"{{comment.comment}}" +"{{comment.comment | safe}}"
PS: Please, don't reply to the email. You can diff --git a/requirements.txt b/requirements.txt index 6c8aa682..2230057c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -42,3 +42,4 @@ django-markdown==0.8.4 django-pagedown==0.1.0 mdx-linkify==0.6 Markdown==2.6.2 +pypandoc==0.9.8 From 60e2408d69f5af19a4ee94a3cdd406d0fb6f108b Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 15 Jun 2015 00:37:44 +0530 Subject: [PATCH 107/666] Added test for markdown to html conversion --- tests/unit/proposals/test_services.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/unit/proposals/test_services.py diff --git a/tests/unit/proposals/test_services.py b/tests/unit/proposals/test_services.py new file mode 100644 index 00000000..8b350bae --- /dev/null +++ b/tests/unit/proposals/test_services.py @@ -0,0 +1,7 @@ +from junction.proposals.services import markdown_to_html + + +def test_markdown_to_html(): + markdown = '#test' + html = markdown_to_html(markdown) + assert html == '

test

\n' From 850494bae4441d085264d9e31f77cf672a172e8d Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Wed, 10 Jun 2015 00:54:51 +0530 Subject: [PATCH 108/666] Change "Reviewers Only" to "Reviewers Talk" --- junction/templates/proposals/detail/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index ed3e67a9..523e7542 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -194,7 +194,7 @@

Speaker Links:

{% endif %} From 12b4a701893b909e738f07167868304ba9f0a482 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 13:12:19 +0530 Subject: [PATCH 109/666] modifiction to run heroku --- Procfile | 1 + requirements.txt | 2 +- settings/__init__.py | 6 ++++++ settings/heroku.py | 7 +++++++ uwsgi.ini | 7 +++++++ 5 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 Procfile create mode 100644 settings/heroku.py create mode 100644 uwsgi.ini diff --git a/Procfile b/Procfile new file mode 100644 index 00000000..1693c49a --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: uwsgi uwsgi.ini diff --git a/requirements.txt b/requirements.txt index 2230057c..ae1da9ec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ celery==3.1.18 # ------------------------------------------------- psycopg2==2.6 redis==2.10.3 - +dj-database-url==0.3.* # Extensions # ------------------------------------------------- diff --git a/settings/__init__.py b/settings/__init__.py index 21d5babc..92c54e7f 100644 --- a/settings/__init__.py +++ b/settings/__init__.py @@ -3,6 +3,7 @@ # Standard Library import sys +import os if "test" in sys.argv: print("\033[1;91mNo django tests.\033[0m") @@ -21,3 +22,8 @@ from .prod import * # noqa except ImportError: pass + +# heroku + +if 'DYNO' in os.environ: + from .heroku import * diff --git a/settings/heroku.py b/settings/heroku.py new file mode 100644 index 00000000..00dc45f9 --- /dev/null +++ b/settings/heroku.py @@ -0,0 +1,7 @@ +import dj_database_url + +DATABASES = { + 'default': dj_database_url.config() +} + +ALLOWED_HOSTS = ['*'] diff --git a/uwsgi.ini b/uwsgi.ini new file mode 100644 index 00000000..805f73ef --- /dev/null +++ b/uwsgi.ini @@ -0,0 +1,7 @@ +[uwsgi] +http-socket = :$(PORT) +master = true +processes = 4 +die-on-term = true +module = wsgi +memory-report = true From 4e1c116e81feed2f6eb82a39c640770aa5bb5854 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 13:27:47 +0530 Subject: [PATCH 110/666] add uwsgi as part of requirements --- requirements.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/requirements.txt b/requirements.txt index ae1da9ec..bbbcf2dc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -43,3 +43,9 @@ django-pagedown==0.1.0 mdx-linkify==0.6 Markdown==2.6.2 pypandoc==0.9.8 + + +# Server +# ------------------------------------------------ +uwsgi==2.0.* + From 461d95f54f726ca8ecbe8ac45f41914712ac56f7 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 13:47:35 +0530 Subject: [PATCH 111/666] set debug to false, serve staticfiles from uwsgi --- settings/heroku.py | 2 ++ uwsgi.ini | 2 ++ 2 files changed, 4 insertions(+) diff --git a/settings/heroku.py b/settings/heroku.py index 00dc45f9..4626efe7 100644 --- a/settings/heroku.py +++ b/settings/heroku.py @@ -5,3 +5,5 @@ } ALLOWED_HOSTS = ['*'] + +DEGUG = False diff --git a/uwsgi.ini b/uwsgi.ini index 805f73ef..38cbdc7a 100644 --- a/uwsgi.ini +++ b/uwsgi.ini @@ -5,3 +5,5 @@ processes = 4 die-on-term = true module = wsgi memory-report = true +check-static = junction/assets/collected-static +offload-threads = 4 From a0778577cb6bcc77900aeb52f2a35be5c3dea521 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 13:51:23 +0530 Subject: [PATCH 112/666] fix debug spelling in heroku --- settings/heroku.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/heroku.py b/settings/heroku.py index 4626efe7..0195576d 100644 --- a/settings/heroku.py +++ b/settings/heroku.py @@ -6,4 +6,4 @@ ALLOWED_HOSTS = ['*'] -DEGUG = False +DEBUG = False From 1ee5853472a27e5aa5b7c51a2c43906d405cc23c Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 14:11:30 +0530 Subject: [PATCH 113/666] set static map instead of check static --- uwsgi.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/uwsgi.ini b/uwsgi.ini index 38cbdc7a..d5db0425 100644 --- a/uwsgi.ini +++ b/uwsgi.ini @@ -5,5 +5,6 @@ processes = 4 die-on-term = true module = wsgi memory-report = true -check-static = junction/assets/collected-static offload-threads = 4 +static-map = /static=junction/assets/collected-static +# home = $(VIRTUAL_ENV) From f47efe7e25d4310ce9690715b0420cd0ba349ed6 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 14:32:31 +0530 Subject: [PATCH 114/666] added noqa --- settings/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/__init__.py b/settings/__init__.py index 92c54e7f..ab7082e3 100644 --- a/settings/__init__.py +++ b/settings/__init__.py @@ -26,4 +26,4 @@ # heroku if 'DYNO' in os.environ: - from .heroku import * + from .heroku import * # noqa From 5ed38ce0e66632d7b96d40e2d9939ae340ec3388 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 14:48:13 +0530 Subject: [PATCH 115/666] added deploy to heroku button and app.json for heroku --- README.md | 2 +- app.json | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 app.json diff --git a/README.md b/README.md index 19bebd93..908852b4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ junction ======== -[![Build Status](https://travis-ci.org/pythonindia/junction.svg)](https://travis-ci.org/pythonindia/junction) [![Coverage Status](https://coveralls.io/repos/pythonindia/junction/badge.svg?branch=master)](https://coveralls.io/r/pythonindia/junction?branch=master) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pythonindia/junction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy)[![Build Status](https://travis-ci.org/pythonindia/junction.svg)](https://travis-ci.org/pythonindia/junction) [![Coverage Status](https://coveralls.io/repos/pythonindia/junction/badge.svg?branch=master)](https://coveralls.io/r/pythonindia/junction?branch=master) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pythonindia/junction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) **Version**: 0.2.0-dev diff --git a/app.json b/app.json new file mode 100644 index 00000000..07c4a547 --- /dev/null +++ b/app.json @@ -0,0 +1,12 @@ +{ + "name": "Junction", + "description": "Junction is a software to manage proposals, reviews, schedule, feedback during conference.", + "repository": "https://github.com/pythonindia/junction/", + "keywords": ["python", "django", "CFP", "conference"], + "scripts": { + "postdeploy": "python manage.py migrate" + }, + "addons": [ + "heroku-postgresql" + ] +} From 6593f811fb65fbe37c9ac940251027ae8963db36 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 14:50:02 +0530 Subject: [PATCH 116/666] cleanup readme --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 908852b4..fadcff98 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ junction ======== -[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy)[![Build Status](https://travis-ci.org/pythonindia/junction.svg)](https://travis-ci.org/pythonindia/junction) [![Coverage Status](https://coveralls.io/repos/pythonindia/junction/badge.svg?branch=master)](https://coveralls.io/r/pythonindia/junction?branch=master) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pythonindia/junction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy) + +[![Build Status](https://travis-ci.org/pythonindia/junction.svg)](https://travis-ci.org/pythonindia/junction) [![Coverage Status](https://coveralls.io/repos/pythonindia/junction/badge.svg?branch=master)](https://coveralls.io/r/pythonindia/junction?branch=master) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pythonindia/junction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) **Version**: 0.2.0-dev @@ -41,7 +43,7 @@ alias docker='sudo docker' alias fig='sudo fig' ``` -Finally, run +Finally, run ``` fig up ``` @@ -50,7 +52,7 @@ fig up Configuring Django-allauth --------------------------- - - Go to `http://localhost:8000/nimda/sites/site/` + - Go to `http://localhost:8000/nimda/sites/site/` - Change the default site's(the one with ID = 1) name and display to `localhost:8000` - Go to `Social Applications` in admin panel and add [Github](http://django-allauth.readthedocs.org/en/latest/providers.html#github) and [Google](http://django-allauth.readthedocs.org/en/latest/providers.html#google)'s auth details @@ -72,7 +74,7 @@ Contributing 1. Choose an [issue][issue-list] and ask any doubts in the issue thread. 2. Report any bugs/feature request as github [new issue][new-issue], if it's already not present. 3. If you are starting to work on an issue, please leave a comment saying "I am working on it". -4. Once you are done with feature/bug fix, send a pull request according to the [guidelines]. +4. Once you are done with feature/bug fix, send a pull request according to the [guidelines]. [issue-list]: https://github.com/pythonindia/junction/issues/ [new-issue]: https://github.com/pythonindia/junction/issues/new From 8f1d6d7f312db40bffa45b8e1f9f52d69101a2b4 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 16:04:05 +0530 Subject: [PATCH 117/666] limit the allowed hosts to herokuapp.com --- settings/heroku.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/heroku.py b/settings/heroku.py index 0195576d..1316c248 100644 --- a/settings/heroku.py +++ b/settings/heroku.py @@ -4,6 +4,6 @@ 'default': dj_database_url.config() } -ALLOWED_HOSTS = ['*'] +ALLOWED_HOSTS = ['*.herokuapp.com'] DEBUG = False From 814f3eaa57e2d53f9b420b75bc3ceba74789f331 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sun, 14 Jun 2015 16:23:25 +0530 Subject: [PATCH 118/666] fix the allowed_hosts --- settings/heroku.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/heroku.py b/settings/heroku.py index 1316c248..367f7f40 100644 --- a/settings/heroku.py +++ b/settings/heroku.py @@ -4,6 +4,6 @@ 'default': dj_database_url.config() } -ALLOWED_HOSTS = ['*.herokuapp.com'] +ALLOWED_HOSTS = ['.herokuapp.com'] DEBUG = False From 5b3f2dc855b94b13364f31d0e9e94ab38400b549 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Mon, 15 Jun 2015 13:27:18 +0530 Subject: [PATCH 119/666] chore(frontend/proposal-detail): add tooltip for action buttons of proposal. closes #253 --- junction/static/js/main.js | 5 +++++ junction/templates/proposals/detail/base.html | 18 +++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/junction/static/js/main.js b/junction/static/js/main.js index 53cf74ce..9f8448f3 100644 --- a/junction/static/js/main.js +++ b/junction/static/js/main.js @@ -21,3 +21,8 @@ $.ajaxSetup({ } } }); + +// Enable tooltip +$(function () { + $('[data-toggle="tooltip"]').tooltip() +}) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index 523e7542..c6da5238 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -55,21 +55,25 @@

{% if is_author %} {% endif %} From a734be2f476443807dbafc8333dd277cb9baf9b3 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Mon, 15 Jun 2015 13:57:16 +0530 Subject: [PATCH 120/666] fix(proposal/UI): POST create/update should redirect to proposal detail - currently it was going to proposal list --- junction/proposals/views.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 1444df7d..73576e5c 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -160,8 +160,8 @@ def create_proposal(request, conference_slug): host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META['HTTP_HOST']) send_mail_for_new_proposal(proposal, host) - return HttpResponseRedirect(reverse('proposals-list', - args=[conference.slug])) + return HttpResponseRedirect(reverse('proposal-detail', + args=[conference.slug, proposal.slug])) @require_http_methods(['GET']) @@ -245,8 +245,8 @@ def update_proposal(request, conference_slug, slug): proposal.proposal_type_id = form.cleaned_data['proposal_type'] proposal.proposal_section_id = form.cleaned_data['proposal_section'] proposal.save() - return HttpResponseRedirect(reverse('proposals-list', - args=[conference.slug])) + return HttpResponseRedirect(reverse('proposal-detail', + args=[conference.slug, proposal.slug])) @login_required From 367d126d3a0b4f8b8db2911648d6d7edcebf1d11 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 15 Jun 2015 19:43:49 +0530 Subject: [PATCH 121/666] Add pandoc to travis & readme --- .travis.yml | 4 ++++ README.md | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4e747e23..e29cad8f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,10 @@ cache: directories: - $HOME/.pip-cache/ +before_install: + - sudo apt-get update -qq + - sudo apt-get install -qqy pandoc + install: - pip install -r requirements-dev.txt --allow-all-external --download-cache $HOME/.pip-cache - pip install coveralls diff --git a/README.md b/README.md index fadcff98..ec6b28ef 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,13 @@ Junction is a software to manage proposals, reviews, schedule, feedback during c Setup ===== +Junction uses `pandoc` for converting markdown to html. +To install run this command in Your terminal. + +``` +sudo apt-get install pandoc +``` + It is advised to install all the requirements inside [virtualenv], use [virtualenvwrapper] to manage virtualenvs. [virtualenv]: https://virtualenv.pypa.io/en/latest/ From 55dbe404acb4809561fa7318e6dcdcf964921804 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 15 Jun 2015 19:48:04 +0530 Subject: [PATCH 122/666] Update travis config --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e29cad8f..b9f258ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: python -sudo: false +sudo: required python: - '2.7' addons: From bf1a6d538a8fac9036331ac157aac2f0e9a9fe4b Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 15 Jun 2015 21:25:29 +0530 Subject: [PATCH 123/666] Add Pandoc installing guide to readme --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ec6b28ef..332108b9 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,16 @@ Setup ===== Junction uses `pandoc` for converting markdown to html. -To install run this command in Your terminal. +If You are using Ubuntu, You can install it using ``` sudo apt-get install pandoc ``` +For other operating systems & more installing options checkout [Pandoc installation guide]. + +[Pandoc installation guide]: http://pandoc.org/installing.html + It is advised to install all the requirements inside [virtualenv], use [virtualenvwrapper] to manage virtualenvs. [virtualenv]: https://virtualenv.pypa.io/en/latest/ From 4cae8a4e2bbd49b95d9a02ca1e5fa1ad160491a4 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 15 Jun 2015 21:41:47 +0530 Subject: [PATCH 124/666] Use markdown2 instead of pandoc PyPandoc has system dependency pandoc. --- .travis.yml | 6 +----- README.md | 11 ----------- junction/proposals/services.py | 8 ++++---- requirements.txt | 2 +- tests/unit/proposals/test_services.py | 2 +- 5 files changed, 7 insertions(+), 22 deletions(-) diff --git a/.travis.yml b/.travis.yml index b9f258ff..4e747e23 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: python -sudo: required +sudo: false python: - '2.7' addons: @@ -9,10 +9,6 @@ cache: directories: - $HOME/.pip-cache/ -before_install: - - sudo apt-get update -qq - - sudo apt-get install -qqy pandoc - install: - pip install -r requirements-dev.txt --allow-all-external --download-cache $HOME/.pip-cache - pip install coveralls diff --git a/README.md b/README.md index 332108b9..fadcff98 100644 --- a/README.md +++ b/README.md @@ -12,17 +12,6 @@ Junction is a software to manage proposals, reviews, schedule, feedback during c Setup ===== -Junction uses `pandoc` for converting markdown to html. -If You are using Ubuntu, You can install it using - -``` -sudo apt-get install pandoc -``` - -For other operating systems & more installing options checkout [Pandoc installation guide]. - -[Pandoc installation guide]: http://pandoc.org/installing.html - It is advised to install all the requirements inside [virtualenv], use [virtualenvwrapper] to manage virtualenvs. [virtualenv]: https://virtualenv.pypa.io/en/latest/ diff --git a/junction/proposals/services.py b/junction/proposals/services.py index 5ffc1a9e..ec7572bf 100644 --- a/junction/proposals/services.py +++ b/junction/proposals/services.py @@ -6,7 +6,7 @@ # Third Party Stuff from django.conf import settings -import pypandoc +from markdown2 import markdown # Junction Stuff @@ -17,13 +17,13 @@ logger = logging.getLogger(__name__) -def markdown_to_html(markdown): +def markdown_to_html(md): """ Convert given markdown to html. - :param markdown: string + :param md: string :return: string - converted html """ - return pypandoc.convert(markdown, 'html', format='markdown') + return markdown(md) def send_mail_for_new_comment(proposal_comment, login_url): diff --git a/requirements.txt b/requirements.txt index bbbcf2dc..d14827b8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -42,7 +42,7 @@ django-markdown==0.8.4 django-pagedown==0.1.0 mdx-linkify==0.6 Markdown==2.6.2 -pypandoc==0.9.8 +markdown2==2.3.0 # Server diff --git a/tests/unit/proposals/test_services.py b/tests/unit/proposals/test_services.py index 8b350bae..750ac1e1 100644 --- a/tests/unit/proposals/test_services.py +++ b/tests/unit/proposals/test_services.py @@ -4,4 +4,4 @@ def test_markdown_to_html(): markdown = '#test' html = markdown_to_html(markdown) - assert html == '

test

\n' + assert html == '

test

\n' From dc384a13993e3f74944e4e7d767db1cacffa4700 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Wed, 17 Jun 2015 20:13:02 +0530 Subject: [PATCH 125/666] Fix broken link in comment mails --- junction/proposals/services.py | 6 ++++-- junction/proposals/views.py | 7 ++----- junction/templates/proposals/email/comment/message.html | 2 +- junction/templates/proposals/email/comment/message.txt | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/junction/proposals/services.py b/junction/proposals/services.py index ec7572bf..2c1c08e4 100644 --- a/junction/proposals/services.py +++ b/junction/proposals/services.py @@ -26,8 +26,9 @@ def markdown_to_html(md): return markdown(md) -def send_mail_for_new_comment(proposal_comment, login_url): +def send_mail_for_new_comment(proposal_comment, host): proposal = proposal_comment.proposal + login_url = '{}?next={}'.format(settings.LOGIN_URL, proposal.get_absolute_url()) send_to = comment_recipients(proposal_comment) commenter = proposal_comment.commenter proposal_comment.comment = markdown_to_html(proposal_comment.comment) @@ -37,10 +38,11 @@ def send_mail_for_new_comment(proposal_comment, login_url): send_email(to=to, template_dir='proposals/email/comment', context={'to': to, + 'host': host, + 'login_url': login_url, 'proposal': proposal, 'comment': proposal_comment, 'commenter': commenter, - 'login_url': login_url, 'by_author': commenter == proposal.author}) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 73576e5c..8c2ad897 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -388,11 +388,8 @@ def create_proposal_comment(request, conference_slug, proposal_slug): proposal=proposal, comment=comment, private=private, reviewer=reviewer, commenter=request.user ) - login_url = '{}://{}{}?next={}'.format( - settings.SITE_PROTOCOL, request.META['HTTP_HOST'], - settings.LOGIN_URL, proposal.get_absolute_url() - ) - send_mail_for_new_comment(proposal_comment, login_url=login_url) + host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META['HTTP_HOST']) + send_mail_for_new_comment(proposal_comment, host) redirect_url = reverse('proposal-detail', args=[conference.slug, proposal.slug]) diff --git a/junction/templates/proposals/email/comment/message.html b/junction/templates/proposals/email/comment/message.html index fe6ce706..089fd17d 100644 --- a/junction/templates/proposals/email/comment/message.html +++ b/junction/templates/proposals/email/comment/message.html @@ -15,4 +15,4 @@
PS: Please, don't reply to the email. You can - login to and leave a comment + login to and leave a comment diff --git a/junction/templates/proposals/email/comment/message.txt b/junction/templates/proposals/email/comment/message.txt index f0e1d8fa..05b2b708 100644 --- a/junction/templates/proposals/email/comment/message.txt +++ b/junction/templates/proposals/email/comment/message.txt @@ -2,4 +2,4 @@ There is a new comment on {{host}}{{proposal.get_absolute_url}} by {% if comment "{{comment.comment}}" ------------------------------------------------------------------------------- -PS: Please, don't reply to the email. You can login({{login_url}})to and leave a comment +PS: Please, don't reply to the email. You can login({{host}}{{login_url}})to and leave a comment From ea32d267d403b1925f8d39e74df83828e2f16ef2 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Wed, 17 Jun 2015 20:25:33 +0530 Subject: [PATCH 126/666] Fix broken link in comment mails --- 0001-Fix-broken-link-in-comment-mails.patch | 81 +++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 0001-Fix-broken-link-in-comment-mails.patch diff --git a/0001-Fix-broken-link-in-comment-mails.patch b/0001-Fix-broken-link-in-comment-mails.patch new file mode 100644 index 00000000..15a8337c --- /dev/null +++ b/0001-Fix-broken-link-in-comment-mails.patch @@ -0,0 +1,81 @@ +From dc384a13993e3f74944e4e7d767db1cacffa4700 Mon Sep 17 00:00:00 2001 +From: chillaranand +Date: Wed, 17 Jun 2015 20:13:02 +0530 +Subject: [PATCH] Fix broken link in comment mails + +--- + junction/proposals/services.py | 6 ++++-- + junction/proposals/views.py | 7 ++----- + junction/templates/proposals/email/comment/message.html | 2 +- + junction/templates/proposals/email/comment/message.txt | 2 +- + 4 files changed, 8 insertions(+), 9 deletions(-) + +diff --git a/junction/proposals/services.py b/junction/proposals/services.py +index ec7572b..2c1c08e 100644 +--- a/junction/proposals/services.py ++++ b/junction/proposals/services.py +@@ -26,8 +26,9 @@ def markdown_to_html(md): + return markdown(md) + + +-def send_mail_for_new_comment(proposal_comment, login_url): ++def send_mail_for_new_comment(proposal_comment, host): + proposal = proposal_comment.proposal ++ login_url = '{}?next={}'.format(settings.LOGIN_URL, proposal.get_absolute_url()) + send_to = comment_recipients(proposal_comment) + commenter = proposal_comment.commenter + proposal_comment.comment = markdown_to_html(proposal_comment.comment) +@@ -37,10 +38,11 @@ def send_mail_for_new_comment(proposal_comment, login_url): + send_email(to=to, + template_dir='proposals/email/comment', + context={'to': to, ++ 'host': host, ++ 'login_url': login_url, + 'proposal': proposal, + 'comment': proposal_comment, + 'commenter': commenter, +- 'login_url': login_url, + 'by_author': commenter == proposal.author}) + + +diff --git a/junction/proposals/views.py b/junction/proposals/views.py +index 73576e5..8c2ad89 100644 +--- a/junction/proposals/views.py ++++ b/junction/proposals/views.py +@@ -388,11 +388,8 @@ def create_proposal_comment(request, conference_slug, proposal_slug): + proposal=proposal, comment=comment, + private=private, reviewer=reviewer, commenter=request.user + ) +- login_url = '{}://{}{}?next={}'.format( +- settings.SITE_PROTOCOL, request.META['HTTP_HOST'], +- settings.LOGIN_URL, proposal.get_absolute_url() +- ) +- send_mail_for_new_comment(proposal_comment, login_url=login_url) ++ host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META['HTTP_HOST']) ++ send_mail_for_new_comment(proposal_comment, host) + + redirect_url = reverse('proposal-detail', args=[conference.slug, proposal.slug]) + +diff --git a/junction/templates/proposals/email/comment/message.html b/junction/templates/proposals/email/comment/message.html +index fe6ce70..089fd17 100644 +--- a/junction/templates/proposals/email/comment/message.html ++++ b/junction/templates/proposals/email/comment/message.html +@@ -15,4 +15,4 @@ There is a new comment on " + +
+ PS: Please, don't reply to the email. You can +-
login to and leave a comment ++ login to and leave a comment +diff --git a/junction/templates/proposals/email/comment/message.txt b/junction/templates/proposals/email/comment/message.txt +index f0e1d8f..05b2b70 100644 +--- a/junction/templates/proposals/email/comment/message.txt ++++ b/junction/templates/proposals/email/comment/message.txt +@@ -2,4 +2,4 @@ There is a new comment on {{host}}{{proposal.get_absolute_url}} by {% if comment + + "{{comment.comment}}" + ------------------------------------------------------------------------------- +-PS: Please, don't reply to the email. You can login({{login_url}})to and leave a comment ++PS: Please, don't reply to the email. You can login({{host}}{{login_url}})to and leave a comment +-- +1.9.1 + From 86e2f5c2f0f510a17f67148612f365528cd81310 Mon Sep 17 00:00:00 2001 From: dhilipsiva Date: Tue, 23 Jun 2015 00:55:31 +0530 Subject: [PATCH 127/666] Adding a nickname --- .../0009_conferenceproposalreviewer_nick.py | 20 +++++++++++++++++++ junction/conferences/models.py | 1 + junction/proposals/models.py | 7 ++++++- .../templates/proposals/detail/comments.html | 2 +- .../proposals/email/comment/message.html | 2 +- 5 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 junction/conferences/migrations/0009_conferenceproposalreviewer_nick.py diff --git a/junction/conferences/migrations/0009_conferenceproposalreviewer_nick.py b/junction/conferences/migrations/0009_conferenceproposalreviewer_nick.py new file mode 100644 index 00000000..f7cec018 --- /dev/null +++ b/junction/conferences/migrations/0009_conferenceproposalreviewer_nick.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('conferences', '0008_auto_20150601_1436'), + ] + + operations = [ + migrations.AddField( + model_name='conferenceproposalreviewer', + name='nick', + field=models.CharField(max_length=255, null=True, verbose_name='Nick Name', blank=True), + preserve_default=True, + ), + ] diff --git a/junction/conferences/models.py b/junction/conferences/models.py index 26a19dc9..b23400ac 100644 --- a/junction/conferences/models.py +++ b/junction/conferences/models.py @@ -78,6 +78,7 @@ class ConferenceProposalReviewer(AuditModel): conference = models.ForeignKey(Conference, related_name='proposal_reviewers') reviewer = models.ForeignKey(User) active = models.BooleanField(default=True, verbose_name="Is Active?") + nick = models.CharField(max_length=255, verbose_name="Nick Name", null=True, blank=True) class Meta: verbose_name = 'proposals reviewer' diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 76951474..2b5c1d8b 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -16,7 +16,7 @@ PROPOSAL_USER_VOTE_ROLES ) from junction.base.models import AuditModel, TimeAuditModel -from junction.conferences.models import Conference +from junction.conferences.models import Conference, ConferenceProposalReviewer @python_2_unicode_compatible @@ -230,6 +230,11 @@ def get_votes_count(self): down_vote_count = ProposalCommentVote.objects.filter(proposal_comment=self, up_vote=False).count() return up_vote_count - down_vote_count + def get_reviewer_nick(self): + reviewer = ConferenceProposalReviewer.objects.get(conference_id=self.proposal.conference_id, + reviewer_id=self.commenter_id) + return reviewer.nick + @python_2_unicode_compatible class ProposalCommentVote(TimeAuditModel): diff --git a/junction/templates/proposals/detail/comments.html b/junction/templates/proposals/detail/comments.html index 315c59b8..b76a0630 100644 --- a/junction/templates/proposals/detail/comments.html +++ b/junction/templates/proposals/detail/comments.html @@ -44,7 +44,7 @@
{% if comment.commenter == proposal.author %} Comment by proposer. {% else %} - Comment by reviewer. + Comment by {{comment.get_reviewer_nick}}. {% endif %} {% else %} {% if comment.commenter.get_full_name %} diff --git a/junction/templates/proposals/email/comment/message.html b/junction/templates/proposals/email/comment/message.html index 089fd17d..cd5ab359 100644 --- a/junction/templates/proposals/email/comment/message.html +++ b/junction/templates/proposals/email/comment/message.html @@ -4,7 +4,7 @@ {% if by_author %} " by by Author.: {% else %} -" by by a Reviewer.: +" by by {{comment.get_reviewer_nick}}.: {% endif %} {% else %} " by {{comment.commenter}}: From d2167bdc33314d0975a161a19eabba092b6c162f Mon Sep 17 00:00:00 2001 From: dhilipsiva Date: Tue, 23 Jun 2015 09:21:14 +0530 Subject: [PATCH 128/666] Set `Reviewer` for `nick` --- .../migrations/0009_conferenceproposalreviewer_nick.py | 2 +- junction/conferences/models.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/junction/conferences/migrations/0009_conferenceproposalreviewer_nick.py b/junction/conferences/migrations/0009_conferenceproposalreviewer_nick.py index f7cec018..830b5886 100644 --- a/junction/conferences/migrations/0009_conferenceproposalreviewer_nick.py +++ b/junction/conferences/migrations/0009_conferenceproposalreviewer_nick.py @@ -14,7 +14,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='conferenceproposalreviewer', name='nick', - field=models.CharField(max_length=255, null=True, verbose_name='Nick Name', blank=True), + field=models.CharField(default='Reviewer', max_length=255, verbose_name='Nick Name'), preserve_default=True, ), ] diff --git a/junction/conferences/models.py b/junction/conferences/models.py index b23400ac..a04b469f 100644 --- a/junction/conferences/models.py +++ b/junction/conferences/models.py @@ -78,7 +78,7 @@ class ConferenceProposalReviewer(AuditModel): conference = models.ForeignKey(Conference, related_name='proposal_reviewers') reviewer = models.ForeignKey(User) active = models.BooleanField(default=True, verbose_name="Is Active?") - nick = models.CharField(max_length=255, verbose_name="Nick Name", null=True, blank=True) + nick = models.CharField(max_length=255, verbose_name="Nick Name", default="Reviewer") class Meta: verbose_name = 'proposals reviewer' From 94f788dee7c79addf138fe832f0bf2a86a93e3c9 Mon Sep 17 00:00:00 2001 From: dhilipsiva Date: Tue, 23 Jun 2015 09:30:47 +0530 Subject: [PATCH 129/666] Adding `dhilipsiva` to contributors. :smile: http://dhilipsiva.com https://github.com/dhilipsiva https://twitter.com/dhilipsiva --- CONTRIBUTORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 36420fe7..0cd3a52f 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -14,5 +14,6 @@ Anuvrat Parashar (gh:bhanuvrat/ @bhanuvrat) Aayush Kasurde Arjoonn Sharma (gh:theSage21) Haris Ibrahim K V (gh:harisibrahimkv / @harisibrahimkv) +dhilipsiva (gh:dhilipsiva / @dhilipsiva) * Possesses commit rights From da8a3b2114d0800f24a29407742091641ed3596d Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 28 Jun 2015 13:57:49 +0530 Subject: [PATCH 130/666] Add dummy schedule --- junction/schedule/__init__.py | 0 junction/schedule/admin.py | 3 + junction/schedule/migrations/__init__.py | 0 junction/schedule/models.py | 3 + junction/schedule/tests.py | 3 + junction/schedule/urls.py | 13 ++ junction/schedule/views.py | 11 + junction/templates/dummy_schedule.json | 251 +++++++++++++++++++++++ junction/urls.py | 3 + 9 files changed, 287 insertions(+) create mode 100644 junction/schedule/__init__.py create mode 100644 junction/schedule/admin.py create mode 100644 junction/schedule/migrations/__init__.py create mode 100644 junction/schedule/models.py create mode 100644 junction/schedule/tests.py create mode 100644 junction/schedule/urls.py create mode 100644 junction/schedule/views.py create mode 100644 junction/templates/dummy_schedule.json diff --git a/junction/schedule/__init__.py b/junction/schedule/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/junction/schedule/admin.py b/junction/schedule/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/junction/schedule/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/junction/schedule/migrations/__init__.py b/junction/schedule/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/junction/schedule/models.py b/junction/schedule/models.py new file mode 100644 index 00000000..71a83623 --- /dev/null +++ b/junction/schedule/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/junction/schedule/tests.py b/junction/schedule/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/junction/schedule/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/junction/schedule/urls.py b/junction/schedule/urls.py new file mode 100644 index 00000000..c0ca41e2 --- /dev/null +++ b/junction/schedule/urls.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +# Third Party Stuff +from django.conf.urls import include, patterns, url + +from . import views + +urlpatterns = patterns( + '', + # schedule urls + url(r'^dummy_schedule/$', views.dummy_schedule, name='dummy_schedule'), +) diff --git a/junction/schedule/views.py b/junction/schedule/views.py new file mode 100644 index 00000000..9c76e69e --- /dev/null +++ b/junction/schedule/views.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- + +from django.http import HttpResponse +from django.template.loader import render_to_string + +# Create your views here. + + +def dummy_schedule(request, conference_slug): + data = render_to_string('dummy_schedule.json') + return HttpResponse(data, content_type='application/json') diff --git a/junction/templates/dummy_schedule.json b/junction/templates/dummy_schedule.json new file mode 100644 index 00000000..c491d9e1 --- /dev/null +++ b/junction/templates/dummy_schedule.json @@ -0,0 +1,251 @@ +{ + "conference": { + "id": 1, + "name": "PyCon India 2015", + "start_date": "2015-10-02", + "end_date": "2015-10-04", + "timezone": "Asia/Kolkatta", + "venue": { + "name": "Nimhans", + "google_map_url": "https://goo.gl/XITV4W" + }, + "rooms": [ + { + "id": 1, + "name": "Audi 1", + "floor": "Ground", + "note": "Straight from entrance" + }, + { + "id": 2, + "name": "Audi 2", + "floor": "Ground", + "note": "Right side of entrance" + }, + { + "id": 3, + "name": "Audi 3", + "floor": "Ground", + "note": "Right extreme" + }, + { + "id": 4, + "name": "Open Space", + "floor": "First", + "note": "" + }, + { + "id": 5, + "name": "Lunch Hall", + "floor": "Ground", + "note": "Left side of the entrance" + } + ], + "days": [ + { + "name": "Workshop Day", + "slots": [ + { + "start_datetime": "2015-10-02T04:00:00.000000Z", + "end_datetime": "2015-10-02T06:30:00.000000Z", + "sessions": [ + { + "room_id": 1, + "session_id": 1, + "title": "Workshop 1", + "description": "Description will be long and supports markdown.", + "prerequisites": "This is also markdown, text area", + "content_urls": "Again Markdown", + "speaker_info": "Batman", + "speaker_links": "Links in markdown", + "section": "Web development", + "type": "Workshop", + "target_audience": "Beginners", + "feedback_url": "https://in.pycon.org/cfp/2015/sessions/workshop-1/feedback/", + "full_name": "Batman Rises", + "is_break": false, + "is_lunch": false + }, + { + "room_id": 2, + "session_id": 2, + "title": "Workshop 2", + "description": "Description will be long and supports markdown.", + "prerequisites": "This is also markdown, text area", + "content_urls": "Again Markdown", + "speaker_info": "Joker", + "speaker_links": "Links in markdown", + "section": "Infrastructure", + "type": "Workshop", + "target_audience": "Intermediate", + "feedback_url": "https://in.pycon.org/cfp/2015/sessions/workshop-2/feedback/", + "full_name": "Joker", + "is_break": false, + "is_lunch": false + }, + { + "room_id": 3, + "session_id": 3, + "title": "Workshop 3", + "description": "Description will be long and supports markdown.", + "prerequisites": "This is also markdown, text area", + "content_urls": "Again Markdown", + "speaker_info": "Arun", + "speaker_links": "Links in markdown", + "section": "Core Python", + "type": "Workshop", + "target_audience": "Advanced", + "feedback_url": "https://in.pycon.org/cfp/2015/sessions/workshop-3/feedback/", + "full_name": "Arun", + "is_break": false, + "is_lunch": false + } + ] + }, + { + "start_datetime": "2015-10-02T06:30:00.000000Z", + "end_datetime": "2015-10-02T07:30:00.000000Z", + "sessions": [ + { + "room_id": 4, + "session_id": 4, + "title": "Lunch", + "is_break": false, + "is_lunch": true + } + ] + }, + { + "start_datetime": "2015-10-02T07:30:00.000000Z", + "end_datetime": "2015-10-02T10:00:00.000000Z", + "sessions": [ + { + "room_id": 1, + "session_id": 5, + "title": "Workshop 4", + "description": "Description will be long and supports markdown.", + "prerequisites": "This is also markdown, text area", + "content_urls": "Again Markdown", + "speaker_info": "Batman 1", + "speaker_links": "Links in markdown", + "section": "Web development", + "type": "Workshop", + "target_audience": "Beginners", + "feedback_url": "https://in.pycon.org/cfp/2015/sessions/workshop-4/feedback/", + "full_name": "Batman Rises", + "is_break": false, + "is_lunch": false + }, + { + "room_id": 2, + "session_id": 6, + "title": "Workshop 5", + "description": "Description will be long and supports markdown.", + "prerequisites": "This is also markdown, text area", + "content_urls": "Again Markdown", + "speaker_info": "Joker", + "speaker_links": "Links in markdown", + "section": "Infrastructure", + "type": "Workshop", + "target_audience": "Intermediate", + "feedback_url": "https://in.pycon.org/cfp/2015/sessions/workshop-5/feedback/", + "full_name": "Joker", + "is_break": false, + "is_lunch": false + }, + { + "room_id": 3, + "session_id": 7, + "title": "Workshop 6", + "description": "Description will be long and supports markdown.", + "prerequisites": "This is also markdown, text area", + "content_urls": "Again Markdown", + "speaker_info": "Arun", + "speaker_links": "Links in markdown", + "section": "Core Python", + "type": "Workshop", + "target_audience": "Advanced", + "feedback_url": "https://in.pycon.org/cfp/2015/sessions/workshop-6/feedback/", + "full_name": "Arun", + "is_break": false, + "is_lunch": false + } + ] + }, + { + "start_datetime": "2015-10-02T10:00:00.000000Z", + "end_datetime": "2015-10-02T10:30:00.000000Z", + "sessions": [ + { + "room_id": 4, + "session_id": 8, + "title": "Break", + "is_break": true, + "is_lunch": false + } + ] + }, + { + "start_datetime": "2015-10-02T10:30:00.000000Z", + "end_datetime": "2015-10-02T13:00:00.000000Z", + "sessions": [ + { + "room_id": 1, + "session_id": 9, + "title": "Workshop 7", + "description": "Description will be long and supports markdown.", + "prerequisites": "This is also markdown, text area", + "content_urls": "Again Markdown", + "speaker_info": "Batman 1", + "speaker_links": "Links in markdown", + "section": "Web development", + "type": "Workshop", + "target_audience": "Beginners", + "feedback_url": "https://in.pycon.org/cfp/2015/sessions/workshop-7/feedback/", + "full_name": "Batman Rises", + "is_break": false, + "is_lunch": false + }, + { + "room_id": 2, + "session_id": 10, + "title": "Workshop 8", + "description": "Description will be long and supports markdown.", + "prerequisites": "This is also markdown, text area", + "content_urls": "Again Markdown", + "speaker_info": "Joker", + "speaker_links": "Links in markdown", + "section": "Infrastructure", + "type": "Workshop", + "target_audience": "Intermediate", + "feedback_url": "https://in.pycon.org/cfp/2015/sessions/workshop-8/feedback/", + "full_name": "Joker", + "is_break": false, + "is_lunch": false + }, + { + "room_id": 3, + "session_id": 11, + "title": "Workshop 9", + "description": "Description will be long and supports markdown.", + "prerequisites": "This is also markdown, text area", + "content_urls": "Again Markdown", + "speaker_info": "Arun", + "speaker_links": "Links in markdown", + "section": "Core Python", + "type": "Workshop", + "target_audience": "Advanced", + "feedback_url": "https://in.pycon.org/cfp/2015/sessions/workshop-9/feedback/", + "full_name": "Arun", + "is_break": false, + "is_lunch": false + } + ] + } + ] + } + ], + "total": 20, + "count": 20 + } +} diff --git a/junction/urls.py b/junction/urls.py index 2e5e1ea0..c142b56f 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -33,6 +33,9 @@ url(r'^(?P[\w-]+)/dashboard/', 'junction.proposals.dashboard.proposals_dashboard', name='proposal-dashboard'), + # Schedule related + url(r'^(?P[\w-]+)/schedule/', + include('junction.schedule.urls')), # Static Pages. TODO: to be refactored url(r'^speakers/$', TemplateView.as_view(template_name='static-content/speakers.html',), name='speakers-static'), url(r'^schedule/$', TemplateView.as_view(template_name='static-content/schedule.html',), name='schedule-static'), From 5852415d43aa8068902756e71340b4d489c3df88 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 28 Jun 2015 14:02:46 +0530 Subject: [PATCH 131/666] Fix flake8 warnings --- junction/schedule/admin.py | 2 +- junction/schedule/models.py | 2 +- junction/schedule/tests.py | 2 +- junction/schedule/urls.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/junction/schedule/admin.py b/junction/schedule/admin.py index 8c38f3f3..6af52da2 100644 --- a/junction/schedule/admin.py +++ b/junction/schedule/admin.py @@ -1,3 +1,3 @@ -from django.contrib import admin +from django.contrib import admin # noqa # Register your models here. diff --git a/junction/schedule/models.py b/junction/schedule/models.py index 71a83623..9d57c559 100644 --- a/junction/schedule/models.py +++ b/junction/schedule/models.py @@ -1,3 +1,3 @@ -from django.db import models +from django.db import models # noqa # Create your models here. diff --git a/junction/schedule/tests.py b/junction/schedule/tests.py index 7ce503c2..9a30df3b 100644 --- a/junction/schedule/tests.py +++ b/junction/schedule/tests.py @@ -1,3 +1,3 @@ -from django.test import TestCase +from django.test import TestCase # noqa # Create your tests here. diff --git a/junction/schedule/urls.py b/junction/schedule/urls.py index c0ca41e2..49988f7c 100644 --- a/junction/schedule/urls.py +++ b/junction/schedule/urls.py @@ -2,7 +2,7 @@ from __future__ import absolute_import, unicode_literals # Third Party Stuff -from django.conf.urls import include, patterns, url +from django.conf.urls import patterns, url from . import views From 7908e294a50d97231338dbc71f70491eeb9ea448 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 29 Jun 2015 21:46:53 +0530 Subject: [PATCH 132/666] Add anchor tag to jump to proposals --- junction/templates/proposals/list.html | 1 + .../templates/proposals/partials/proposal-list--items.html | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/junction/templates/proposals/list.html b/junction/templates/proposals/list.html index 44d21743..aec25d8f 100644 --- a/junction/templates/proposals/list.html +++ b/junction/templates/proposals/list.html @@ -79,6 +79,7 @@

Proposal Types

+
{% if is_filtered %} View all proposals diff --git a/junction/templates/proposals/partials/proposal-list--items.html b/junction/templates/proposals/partials/proposal-list--items.html index 73b9c94b..5e3a14dc 100644 --- a/junction/templates/proposals/partials/proposal-list--items.html +++ b/junction/templates/proposals/partials/proposal-list--items.html @@ -40,11 +40,11 @@

{% endif %} {{ proposal.proposal_type }} + href="?proposal_type={{proposal.proposal_type.id}}#proposals">{{ proposal.proposal_type }} {{ proposal.proposal_section }} + href="?proposal_section={{proposal.proposal_section.id}}#proposals">{{ proposal.proposal_section }}

From 4d40e1685703daa6cf9213ee79bacdb8cab7183a Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 29 Jun 2015 21:47:16 +0530 Subject: [PATCH 133/666] Remove unused code --- junction/templates/proposals/list.html | 36 +------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/junction/templates/proposals/list.html b/junction/templates/proposals/list.html index aec25d8f..d489efd4 100644 --- a/junction/templates/proposals/list.html +++ b/junction/templates/proposals/list.html @@ -110,41 +110,7 @@

Proposal Types

List of Proposals

No proposals avaiable yet.

{% endif %} - + {% endblock %} From f6417191d203e629161b8b3a98321dff3630317d Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 29 Jun 2015 21:50:22 +0530 Subject: [PATCH 134/666] Remove patch from version control --- 0001-Fix-broken-link-in-comment-mails.patch | 81 --------------------- 1 file changed, 81 deletions(-) delete mode 100644 0001-Fix-broken-link-in-comment-mails.patch diff --git a/0001-Fix-broken-link-in-comment-mails.patch b/0001-Fix-broken-link-in-comment-mails.patch deleted file mode 100644 index 15a8337c..00000000 --- a/0001-Fix-broken-link-in-comment-mails.patch +++ /dev/null @@ -1,81 +0,0 @@ -From dc384a13993e3f74944e4e7d767db1cacffa4700 Mon Sep 17 00:00:00 2001 -From: chillaranand -Date: Wed, 17 Jun 2015 20:13:02 +0530 -Subject: [PATCH] Fix broken link in comment mails - ---- - junction/proposals/services.py | 6 ++++-- - junction/proposals/views.py | 7 ++----- - junction/templates/proposals/email/comment/message.html | 2 +- - junction/templates/proposals/email/comment/message.txt | 2 +- - 4 files changed, 8 insertions(+), 9 deletions(-) - -diff --git a/junction/proposals/services.py b/junction/proposals/services.py -index ec7572b..2c1c08e 100644 ---- a/junction/proposals/services.py -+++ b/junction/proposals/services.py -@@ -26,8 +26,9 @@ def markdown_to_html(md): - return markdown(md) - - --def send_mail_for_new_comment(proposal_comment, login_url): -+def send_mail_for_new_comment(proposal_comment, host): - proposal = proposal_comment.proposal -+ login_url = '{}?next={}'.format(settings.LOGIN_URL, proposal.get_absolute_url()) - send_to = comment_recipients(proposal_comment) - commenter = proposal_comment.commenter - proposal_comment.comment = markdown_to_html(proposal_comment.comment) -@@ -37,10 +38,11 @@ def send_mail_for_new_comment(proposal_comment, login_url): - send_email(to=to, - template_dir='proposals/email/comment', - context={'to': to, -+ 'host': host, -+ 'login_url': login_url, - 'proposal': proposal, - 'comment': proposal_comment, - 'commenter': commenter, -- 'login_url': login_url, - 'by_author': commenter == proposal.author}) - - -diff --git a/junction/proposals/views.py b/junction/proposals/views.py -index 73576e5..8c2ad89 100644 ---- a/junction/proposals/views.py -+++ b/junction/proposals/views.py -@@ -388,11 +388,8 @@ def create_proposal_comment(request, conference_slug, proposal_slug): - proposal=proposal, comment=comment, - private=private, reviewer=reviewer, commenter=request.user - ) -- login_url = '{}://{}{}?next={}'.format( -- settings.SITE_PROTOCOL, request.META['HTTP_HOST'], -- settings.LOGIN_URL, proposal.get_absolute_url() -- ) -- send_mail_for_new_comment(proposal_comment, login_url=login_url) -+ host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META['HTTP_HOST']) -+ send_mail_for_new_comment(proposal_comment, host) - - redirect_url = reverse('proposal-detail', args=[conference.slug, proposal.slug]) - -diff --git a/junction/templates/proposals/email/comment/message.html b/junction/templates/proposals/email/comment/message.html -index fe6ce70..089fd17 100644 ---- a/junction/templates/proposals/email/comment/message.html -+++ b/junction/templates/proposals/email/comment/message.html -@@ -15,4 +15,4 @@ There is a new comment on " - -
- PS: Please, don't reply to the email. You can --
login to and leave a comment -+ login to and leave a comment -diff --git a/junction/templates/proposals/email/comment/message.txt b/junction/templates/proposals/email/comment/message.txt -index f0e1d8f..05b2b70 100644 ---- a/junction/templates/proposals/email/comment/message.txt -+++ b/junction/templates/proposals/email/comment/message.txt -@@ -2,4 +2,4 @@ There is a new comment on {{host}}{{proposal.get_absolute_url}} by {% if comment - - "{{comment.comment}}" - ------------------------------------------------------------------------------- --PS: Please, don't reply to the email. You can login({{login_url}})to and leave a comment -+PS: Please, don't reply to the email. You can login({{host}}{{login_url}})to and leave a comment --- -1.9.1 - From dfe3499454615c562b24d5885dd3568e311a3943 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Tue, 30 Jun 2015 23:44:00 +0530 Subject: [PATCH 135/666] Added proposals to review page --- junction/proposals/models.py | 4 +- junction/proposals/urls.py | 3 +- junction/proposals/views.py | 37 ++++++++++ junction/templates/proposals/list.html | 15 ++-- .../partials/proposal-list--review-items.html | 68 +++++++++++++++++++ 5 files changed, 114 insertions(+), 13 deletions(-) create mode 100644 junction/templates/proposals/partials/proposal-list--review-items.html diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 2b5c1d8b..b39157af 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -103,11 +103,11 @@ def get_down_vote_url(self): return reverse('proposal-vote-down', args=[self.conference.slug, self.slug]) def get_comments_count(self): - """ Show only the public comment count """ + """ Show only public comments count """ return ProposalComment.objects.filter(proposal=self, deleted=False, private=False).count() def get_reviews_comments_count(self): - """ Show only the public comment count """ + """ Show only private comments count """ return ProposalComment.objects.filter(proposal=self, deleted=False, private=True).count() def get_votes_count(self): diff --git a/junction/proposals/urls.py b/junction/proposals/urls.py index 24d1b3d7..4c435bd3 100644 --- a/junction/proposals/urls.py +++ b/junction/proposals/urls.py @@ -21,6 +21,7 @@ # proposal urls url(r'^$', views.list_proposals, name='proposals-list'), url(r'^create/$', views.create_proposal, name='proposal-create'), + url(r'^to_review/$', views.proposals_to_review, name='proposals-to-review'), url(r'^(?P[\w-]+)/update/$', views.update_proposal, name='proposal-update'), url(r'^(?P[\w-]+)/$', views.detail_proposal, name='proposal-detail'), @@ -38,5 +39,3 @@ url(r'^(?P[\w-]+)/vote/$', views.proposal_reviewer_vote, name='proposal-reviewer-vote'), ) - -# random addition to attempt to merge diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 8c2ad897..f11009d8 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals +# Standard Library +import collections + # Third Party Stuff from django.conf import settings from django.contrib.auth.decorators import login_required @@ -249,6 +252,40 @@ def update_proposal(request, conference_slug, slug): args=[conference.slug, proposal.slug])) +@login_required +@require_http_methods(['GET', 'POST']) +def proposals_to_review(request, conference_slug): + conference = get_object_or_404(Conference, slug=conference_slug) + + if not _is_proposal_reviewer(request.user, conference): + return HttpResponseForbidden() + + proposals_qs = Proposal.objects.select_related( + 'proposal_type', 'proposal_section', 'conference', 'author', + ).filter(conference=conference).filter(status=PROPOSAL_STATUS_PUBLIC) + + proposal_reviewer_sections = [p.proposal_section for p in + ProposalSectionReviewer.objects.filter( + conference_reviewer__reviewer=request.user)] + proposals_to_review = [] + s_items = collections.namedtuple('section_items', 'section proposals') + for section in proposal_reviewer_sections: + section_proposals = [p for p in proposals_qs if p.proposal_section == section] + proposals_to_review.append(s_items(section, section_proposals)) + + proposal_sections = conference.proposal_types.all() + proposal_types = conference.proposal_sections.all() + + ctx = { + 'proposals_to_review': proposals_to_review, + 'proposal_sections': proposal_sections, + 'proposal_types': proposal_types, + 'conference': conference + } + + return render(request, 'proposals/to_review.html', ctx) + + @login_required @require_http_methods(['GET', 'POST']) def review_proposal(request, conference_slug, slug): diff --git a/junction/templates/proposals/list.html b/junction/templates/proposals/list.html index d489efd4..ca2d0754 100644 --- a/junction/templates/proposals/list.html +++ b/junction/templates/proposals/list.html @@ -47,13 +47,15 @@ Reviewer Dashboard {% endif %} - {{ conference.get_status_display }}


{{ conference.description|markdown }}

+ {% if proposals_to_review %} + Proposals To Review + {% endif %}
@@ -90,21 +92,16 @@

Proposal Types

{% endif %}
- - {% if proposals_to_review %} - {% include 'proposals/partials/proposal-list--items.html' with proposals=proposals_to_review title="Proposals To Be Reviewed" display_status=False %} - {% endif %} - {% if selected_proposals_list %} - {% include 'proposals/partials/proposal-list--items.html' with proposals=selected_proposals_list title="Selected Proposals" display_status=False %} + {% include 'proposals/partials/proposal-list--items.html' with proposals=selected_proposals_list title="Selected Proposals" display_status=False %} {% endif %} {% if user_proposals_list %} - {% include 'proposals/partials/proposal-list--items.html' with proposals=user_proposals_list title="My Proposals" display_status=True %} + {% include 'proposals/partials/proposal-list--items.html' with proposals=user_proposals_list title="My Proposals" display_status=True %} {% endif %} {% if public_proposals_list %} - {% include 'proposals/partials/proposal-list--items.html' with proposals=public_proposals_list title="List of Proposals" display_status=False %} + {% include 'proposals/partials/proposal-list--items.html' with proposals=public_proposals_list title="List of Proposals" display_status=False %} {% else %}

List of Proposals

diff --git a/junction/templates/proposals/partials/proposal-list--review-items.html b/junction/templates/proposals/partials/proposal-list--review-items.html new file mode 100644 index 00000000..88318d31 --- /dev/null +++ b/junction/templates/proposals/partials/proposal-list--review-items.html @@ -0,0 +1,68 @@ +{% if title %} +

{{ title }}

+{% endif %} + +{% for proposal in proposals %} +
+
+
+ +
+

+ + {{ proposal.get_comments_count }} + + + {{ proposal.get_votes_count }} + +

+

+ {{ forloop.counter}}. {{ proposal.title|capfirst }} +

+
+
+ {% if display_status %} + + {{ proposal.status_text }} + + {% endif %} + {{ proposal.proposal_type }} + {{ proposal.proposal_section }} + {% if proposal.get_reviews_comments_count > 0 %} + + + + {% endif %} + +
+ + + + {% if proposal.author.get_full_name %} + {{ proposal.author.get_full_name }} (~{{ proposal.author.username }}) + {% else %} + {{ proposal.author.username }} + {% endif %} + |  + {{ proposal.created_at|date:"d M, Y" }} + +
+
+
+
+
+
+{% endfor %} From 6d825078f194e656f3411013082cc94addbb1d34 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Tue, 30 Jun 2015 23:48:26 +0530 Subject: [PATCH 136/666] Updated list proposals page Since we moved review proposals to different page, removed those from this page. --- junction/proposals/views.py | 11 ++--------- junction/templates/proposals/list.html | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index f11009d8..25b6dba1 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -75,14 +75,7 @@ def list_proposals(request, conference_slug): if request.user.is_authenticated(): # Display the proposals by this user user_proposals_list = proposals_qs.filter(author=request.user) - proposals_to_review = [] - if _is_proposal_reviewer(request.user, conference): - proposal_reviewer_sections = [p.proposal_section for p in - ProposalSectionReviewer.objects.filter( - conference_reviewer__reviewer=request.user)] - proposals_to_review = [p for p in proposals_qs - if p.proposal_section in proposal_reviewer_sections and - p.status == PROPOSAL_STATUS_PUBLIC] + is_reviewer = _is_proposal_reviewer(request.user, conference) # Filtering proposal_section_filter = request.GET.getlist('proposal_section') @@ -117,10 +110,10 @@ def list_proposals(request, conference_slug): {'public_proposals_list': public_proposals_list, 'user_proposals_list': user_proposals_list, 'selected_proposals_list': selected_proposals_list, - 'proposals_to_review': proposals_to_review, 'proposal_sections': proposal_sections, 'proposal_types': proposal_types, 'is_filtered': is_filtered, + 'is_reviewer': is_reviewer, 'conference': conference}) diff --git a/junction/templates/proposals/list.html b/junction/templates/proposals/list.html index ca2d0754..48352f6b 100644 --- a/junction/templates/proposals/list.html +++ b/junction/templates/proposals/list.html @@ -53,7 +53,7 @@


{{ conference.description|markdown }}

- {% if proposals_to_review %} + {% if is_reviewer %} Proposals To Review {% endif %} From ff2f7edf538bdf99e392e3c79939de5b4a9f1bc0 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Tue, 30 Jun 2015 23:52:31 +0530 Subject: [PATCH 137/666] Added template for proposals to review --- junction/templates/proposals/to_review.html | 53 +++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 junction/templates/proposals/to_review.html diff --git a/junction/templates/proposals/to_review.html b/junction/templates/proposals/to_review.html new file mode 100644 index 00000000..32d89b21 --- /dev/null +++ b/junction/templates/proposals/to_review.html @@ -0,0 +1,53 @@ +{% extends 'base.html' %} + +{% load django_markdown %} +{% load static from staticfiles %} +{% load django_bootstrap_breadcrumbs %} + +{% block head_title %} {{ conference.name }} proposals to review {% endblock %} +{% block og_title %} {{ conference.name }} proposals to review {% endblock %} +{% block og_description %} {{ conference.description|markdown|safe|striptags}} {% endblock %} +{% block page_description %} {{ conference.description|markdown|safe|striptags}} {% endblock %} + +{% block endhead %} + + +{% endblock %} + +{% block breadcrumbs %} + {{ block.super }} + {% breadcrumb conference.name "conference-detail" conference.slug %} + {% breadcrumb "Proposals To Review" "proposals-to-review" conference.slug %} +{% endblock %} + +{% block navbar_logo %} + {% if conference.logo %} + + + + {% else %} + {{ conference.name }} + {% endif %} +{% endblock navbar_logo %} + +{% block page_classes %}{{ block.super}} page-proposals{% endblock page_classes %} + +{% block content %} +
+
+ + {% if proposals_to_review %} +

Proposals To Review

+
+ {% for section_items in proposals_to_review %} + {% include 'proposals/partials/proposal-list--review-items.html' with proposals=section_items.proposals title=section_items.section display_status=False %} + {% endfor %} + + {% else %} +

No proposals to review.

+ {% endif %} +
+
+{% endblock %} + + From 0e3995845a9c6925fba8b4fd9730df4b934d8331 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Wed, 1 Jul 2015 21:48:10 +0530 Subject: [PATCH 138/666] Update urls --- junction/proposals/urls.py | 20 ++++++++------------ junction/proposals/views.py | 4 ++-- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/junction/proposals/urls.py b/junction/proposals/urls.py index 4c435bd3..e2b71326 100644 --- a/junction/proposals/urls.py +++ b/junction/proposals/urls.py @@ -22,20 +22,16 @@ url(r'^$', views.list_proposals, name='proposals-list'), url(r'^create/$', views.create_proposal, name='proposal-create'), url(r'^to_review/$', views.proposals_to_review, name='proposals-to-review'), - url(r'^(?P[\w-]+)/update/$', - views.update_proposal, name='proposal-update'), url(r'^(?P[\w-]+)/$', views.detail_proposal, name='proposal-detail'), - url(r'^(?P[\w-]+)/delete/$', - views.delete_proposal, name='proposal-delete'), - # url(r'^(?P[\w-]+)/review/$', - # views.review_proposal, name='proposal-review'), + url(r'^(?P[\w-]+)/delete/$', views.delete_proposal, name='proposal-delete'), + url(r'^(?P[\w-]+)/update/$', views.update_proposal, name='proposal-update'), + # url(r'^(?P[\w-]+)/review/$', views.review_proposal, name='proposal-review'), + # comment urls url(r'^comment/', include(comment_urls)), + # Voting - url(r'^(?P[\w-]+)/up-vote/$', - views.proposal_vote_up, name='proposal-vote-up'), - url(r'^(?P[\w-]+)/down-vote/$', - views.proposal_vote_down, name='proposal-vote-down'), - url(r'^(?P[\w-]+)/vote/$', - views.proposal_reviewer_vote, name='proposal-reviewer-vote'), + url(r'^(?P[\w-]+)/vote/$', views.proposal_reviewer_vote, name='proposal-reviewer-vote'), + url(r'^(?P[\w-]+)/down-vote/$', views.proposal_vote_down, name='proposal-vote-down'), + url(r'^(?P[\w-]+)/up-vote/$', views.proposal_vote_up, name='proposal-vote-up'), ) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 25b6dba1..a08ebe4b 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -323,9 +323,9 @@ def review_proposal(request, conference_slug, slug): @login_required @require_http_methods(['GET', 'POST']) -def proposal_reviewer_vote(request, conference_slug, slug): +def proposal_reviewer_vote(request, conference_slug, proposal_slug): conference = get_object_or_404(Conference, slug=conference_slug) - proposal = get_object_or_404(Proposal, slug=slug, conference=conference) + proposal = get_object_or_404(Proposal, slug=proposal_slug, conference=conference) if not _is_proposal_section_reviewer(request.user, conference, proposal): return HttpResponseForbidden() From bc2cbae1fa97ed4fdf225988a0f794c446a0bcae Mon Sep 17 00:00:00 2001 From: chillaranand Date: Wed, 1 Jul 2015 23:37:31 +0530 Subject: [PATCH 139/666] Filter proposals in proposals to review page --- junction/proposals/forms.py | 16 +++ junction/proposals/models.py | 4 + junction/proposals/views.py | 5 +- .../partials/proposal-list--review-items.html | 125 +++++++++--------- junction/templates/proposals/to_review.html | 73 +++++++--- 5 files changed, 142 insertions(+), 81 deletions(-) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index 6d82f713..0ac2cea9 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -136,3 +136,19 @@ class ProposalReviewerVoteForm(forms.Form): choices=_get_proposal_section_reviewer_vote_choices(), widget=forms.RadioSelect() ) + + +class ProposalsToReviewForm(forms.Form): + + ''' + Used filter proposals + ''' + proposal_type = forms.ChoiceField(widget=forms.Select(attrs={'class': 'dropdown'})) + proposal_section = forms.ChoiceField(widget=forms.Select(attrs={'class': 'dropdown'})) + reviewer_comment = forms.ChoiceField(widget=forms.Select(attrs={'class': 'dropdown'})) + + def __init__(self, conference, *args, **kwargs): + super(ProposalsToReviewForm, self).__init__(*args, **kwargs) + self.fields['proposal_section'].choices = _get_proposal_section_choices(conference) + self.fields['proposal_type'].choices = _get_proposal_type_choices(conference) + self.fields['reviewer_comment'].choices = [('Yes', 'Yes'), ('No', 'No')] diff --git a/junction/proposals/models.py b/junction/proposals/models.py index b39157af..fc5bebaf 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -110,6 +110,10 @@ def get_reviews_comments_count(self): """ Show only private comments count """ return ProposalComment.objects.filter(proposal=self, deleted=False, private=True).count() + def has_reviewer_comments(self): + """ Proposals has reviewer comments """ + return ProposalComment.objects.filter(proposal=self, deleted=False, private=True).count() > 0 + def get_votes_count(self): """ Show only the public comment count """ votes = ProposalVote.objects.filter( diff --git a/junction/proposals/views.py b/junction/proposals/views.py index a08ebe4b..2c28b56d 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -21,6 +21,7 @@ ProposalForm, ProposalReviewForm, ProposalReviewerVoteForm, + ProposalsToReviewForm ) from .models import ( Proposal, @@ -268,12 +269,14 @@ def proposals_to_review(request, conference_slug): proposal_sections = conference.proposal_types.all() proposal_types = conference.proposal_sections.all() + form = ProposalsToReviewForm(conference=conference) ctx = { 'proposals_to_review': proposals_to_review, 'proposal_sections': proposal_sections, 'proposal_types': proposal_types, - 'conference': conference + 'conference': conference, + 'form': form, } return render(request, 'proposals/to_review.html', ctx) diff --git a/junction/templates/proposals/partials/proposal-list--review-items.html b/junction/templates/proposals/partials/proposal-list--review-items.html index 88318d31..47c8584c 100644 --- a/junction/templates/proposals/partials/proposal-list--review-items.html +++ b/junction/templates/proposals/partials/proposal-list--review-items.html @@ -1,68 +1,71 @@ -{% if title %} -

{{ title }}

-{% endif %} +
+ + {% if title %} +

{{ title }}

+ {% endif %} -{% for proposal in proposals %} -
-
-
- -
-

- - {{ proposal.get_comments_count }} - - - {{ proposal.get_votes_count }} - -

-

- {{ forloop.counter}}. {{ proposal.title|capfirst }} -

-
-
- {% if display_status %} - - {{ proposal.status_text }} - - {% endif %} - {{ proposal.proposal_type }} - {{ proposal.proposal_section }} - {% if proposal.get_reviews_comments_count > 0 %} - - - - {% endif %} - + {% for proposal in proposals %} +
+
+
+ +
+

+ + {{ proposal.get_comments_count }} + + + {{ proposal.get_votes_count }} + +

+

+ {{ forloop.counter}}. {{ proposal.title|capfirst }} +

+
+
+ {% if display_status %} + + {{ proposal.status_text }} + + {% endif %} + {{ proposal.proposal_type }} + {{ proposal.proposal_section }} + {% if proposal.has_reviewer_comments %} + + + + {% endif %} + +
- - - {% if proposal.author.get_full_name %} - {{ proposal.author.get_full_name }} (~{{ proposal.author.username }}) - {% else %} - {{ proposal.author.username }} - {% endif %} - |  - {{ proposal.created_at|date:"d M, Y" }} - + + + {% if proposal.author.get_full_name %} + {{ proposal.author.get_full_name }} (~{{ proposal.author.username }}) + {% else %} + {{ proposal.author.username }} + {% endif %} + |  + {{ proposal.created_at|date:"d M, Y" }} + +
+
-
+
+ {% endfor %}
-
-{% endfor %} diff --git a/junction/templates/proposals/to_review.html b/junction/templates/proposals/to_review.html index 32d89b21..29d51a6a 100644 --- a/junction/templates/proposals/to_review.html +++ b/junction/templates/proposals/to_review.html @@ -1,4 +1,5 @@ {% extends 'base.html' %} +{% load bootstrap3 %} {% load django_markdown %} {% load static from staticfiles %} @@ -22,9 +23,9 @@ {% block navbar_logo %} {% if conference.logo %} - - - + + + {% else %} {{ conference.name }} {% endif %} @@ -33,21 +34,55 @@ {% block page_classes %}{{ block.super}} page-proposals{% endblock page_classes %} {% block content %} -
-
- - {% if proposals_to_review %} -

Proposals To Review

-
- {% for section_items in proposals_to_review %} - {% include 'proposals/partials/proposal-list--review-items.html' with proposals=section_items.proposals title=section_items.section display_status=False %} - {% endfor %} - - {% else %} -

No proposals to review.

- {% endif %} -
-
-{% endblock %} +
+
+ + {% if proposals_to_review %} +

Proposals To Review

+
+

Filter Proposals

+
+ {% csrf_token %} + {% bootstrap_form form %} + {% buttons %} +
+ +
+ {% endbuttons %} + +
+
+ {% for section_items in proposals_to_review %} + {% include 'proposals/partials/proposal-list--review-items.html' with proposals=section_items.proposals title=section_items.section display_status=False %} + {% endfor %} +
+ + {% else %} +

No proposals to review.

+ {% endif %} +
+
+{% endblock %} +{% block script_extra %} + +{% endblock %} From 7dd3db0fa9c5c8082e6b045ed7f523c5495a7ddd Mon Sep 17 00:00:00 2001 From: chillaranand Date: Wed, 1 Jul 2015 23:56:48 +0530 Subject: [PATCH 140/666] Code cleanup for proposals to review page --- junction/base/constants.py | 6 ++++++ junction/proposals/forms.py | 5 +++-- junction/templates/proposals/to_review.html | 8 +------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/junction/base/constants.py b/junction/base/constants.py index 93fd183d..cf6c4f32 100644 --- a/junction/base/constants.py +++ b/junction/base/constants.py @@ -62,3 +62,9 @@ (0, PROPOSAL_REVIEW_VOTE_NOT_BAD), (-1, PROPOSAL_REVIEW_VOTE_NOT_ALLOWED), ) + +REVIEWER_HAS_COMMENTED = 'Yes' +REVIEWER_HAS_NOT_COMMENTED = 'No' +PROPOSAL_REVIEWER_COMMENT_CHOICES = (('True', REVIEWER_HAS_COMMENTED), + ('False', REVIEWER_HAS_NOT_COMMENTED), + ) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index 0ac2cea9..99bb6857 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -10,7 +10,8 @@ from junction.base.constants import ( PROPOSAL_REVIEW_STATUS_LIST, PROPOSAL_STATUS_LIST, - PROPOSAL_TARGET_AUDIENCES + PROPOSAL_TARGET_AUDIENCES, + PROPOSAL_REVIEWER_COMMENT_CHOICES, ) from junction.proposals.models import ( ProposalSection, @@ -151,4 +152,4 @@ def __init__(self, conference, *args, **kwargs): super(ProposalsToReviewForm, self).__init__(*args, **kwargs) self.fields['proposal_section'].choices = _get_proposal_section_choices(conference) self.fields['proposal_type'].choices = _get_proposal_type_choices(conference) - self.fields['reviewer_comment'].choices = [('Yes', 'Yes'), ('No', 'No')] + self.fields['reviewer_comment'].choices = PROPOSAL_REVIEWER_COMMENT_CHOICES diff --git a/junction/templates/proposals/to_review.html b/junction/templates/proposals/to_review.html index 29d51a6a..0dcd295e 100644 --- a/junction/templates/proposals/to_review.html +++ b/junction/templates/proposals/to_review.html @@ -71,17 +71,11 @@

Filter Proposals

From 9c421afbafbdd4feeccc42b71eaf3f51eb4a83f3 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Thu, 2 Jul 2015 00:01:57 +0530 Subject: [PATCH 141/666] Change order of fields in form --- junction/proposals/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index 99bb6857..c18abf46 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -144,8 +144,8 @@ class ProposalsToReviewForm(forms.Form): ''' Used filter proposals ''' - proposal_type = forms.ChoiceField(widget=forms.Select(attrs={'class': 'dropdown'})) proposal_section = forms.ChoiceField(widget=forms.Select(attrs={'class': 'dropdown'})) + proposal_type = forms.ChoiceField(widget=forms.Select(attrs={'class': 'dropdown'})) reviewer_comment = forms.ChoiceField(widget=forms.Select(attrs={'class': 'dropdown'})) def __init__(self, conference, *args, **kwargs): From 87c2ad13bddd9188f33b21aa2b7f919bc811a01f Mon Sep 17 00:00:00 2001 From: chillaranand Date: Thu, 2 Jul 2015 00:12:50 +0530 Subject: [PATCH 142/666] Add missing glyphicons file --- .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 junction/static/fonts/glyphicons-halflings-regular.woff2 diff --git a/junction/static/fonts/glyphicons-halflings-regular.woff2 b/junction/static/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..64539b54c3751a6d9adb44c8e3a45ba5a73b77f0 GIT binary patch literal 18028 zcmV(~K+nH-Pew8T0RR9107h&84*&oF0I^&E07eM_0Rl|`00000000000000000000 z0000#Mn+Uk92y`7U;vDA2m}!b3WBL5f#qcZHUcCAhI9*rFaQJ~1&1OBl~F%;WnyLq z8)b|&?3j;$^FW}&KmNW53flIFARDZ7_Wz%hpoWaWlgHTHEHf()GI0&dMi#DFPaEt6 zCO)z0v0~C~q&0zBj^;=tv8q{$8JxX)>_`b}WQGgXi46R*CHJ}6r+;}OrvwA{_SY+o zK)H-vy{l!P`+NG*`*x6^PGgHH4!dsolgU4RKj@I8Xz~F6o?quCX&=VQ$Q{w01;M0? zKe|5r<_7CD z=eO3*x!r$aX2iFh3;}xNfx0v;SwBfGG+@Z;->HhvqfF4r__4$mU>Dl_1w;-9`~5rF~@!3;r~xP-hZvOfOx)A z#>8O3N{L{naf215f>m=bzbp7_(ssu&cx)Qo-{)!)Yz3A@Z0uZaM2yJ8#OGlzm?JO5gbrj~@)NB4@?>KE(K-$w}{};@dKY#K3+Vi64S<@!Z{(I{7l=!p9 z&kjG^P~0f46i13(w!hEDJga;*Eb z`!n|++@H8VaKG<9>VDh(y89J#=;Z$ei=GnD5TesW#|Wf)^D+9NKN4J3H5PF_t=V+Z zdeo8*h9+8&Zfc?>>1|E4B7MAx)^uy$L>szyXre7W|81fjy+RZ1>Gd}@@${~PCOXo) z$#HZd3)V3@lNGG%(3PyIbvyJTOJAWcN@Uh!FqUkx^&BuAvc)G}0~SKI`8ZZXw$*xP zum-ZdtPciTAUn$XWb6vrS=JX~f5?M%9S(=QsdYP?K%Odn0S0-Ad<-tBtS3W06I^FK z8}d2eR_n!(uK~APZ-#tl@SycxkRJ@5wmypdWV{MFtYBUY#g-Vv?5AEBj1 z`$T^tRKca*sn7gt%s@XUD-t>bij-4q-ilku9^;QJ3Mpc`HJ_EX4TGGQ-Og)`c~qm51<|gp7D@ zp#>Grssv^#A)&M8>ulnDM_5t#Al`#jaFpZ<#YJ@>!a$w@kEZ1<@PGs#L~kxOSz7jj zEhb?;W)eS}0IQQuk4~JT30>4rFJ3!b+77}>$_>v#2FFEnN^%(ls*o80pv0Q>#t#%H z@`Yy-FXQ9ULKh{Up&oA_A4B!(x^9&>i`+T|eD!&QOLVd(_avv-bFX~4^>o{%mzzrg_i~SBnr%DeE|i+^}|8?kaV(Z32{`vA^l!sp15>Z72z52FgXf z^8ZITvJ9eXBT1~iQjW|Q`Fac^ak$^N-vI^*geh5|*CdMz;n16gV_zk|Z7q8tFfCvU zJK^Pptnn0Rc~egGIAK}uv99VZm2WLPezQQ5K<`f zg{8Ll|GioPYfNheMj-7-S87=w4N0WxHP`1V6Y)0M&SkYzVrwp>yfsEF7wj&T0!}dB z)R~gGfP9pOR;GY_e0~K^^oJ-3AT+m~?Al!{>>5gNe17?OWz)$)sMH*xuQiB>FT2{i zQ>6U_8}Ay~r4li;jzG+$&?S12{)+<*k9 z<^SX#xY|jvlvTxt(m~C7{y{3g>7TX#o2q$xQO|fc<%8rE@A3=UW(o?gVg?gDV!0q6O!{MlX$6-Bu_m&0ms66 znWS&zr{O_4O&{2uCLQvA?xC5vGZ}KV1v6)#oTewgIMSnBur0PtM0&{R5t#UEy3I9) z`LVP?3f;o}sz*7g5qdTxJl^gk3>;8%SOPH@B)rmFOJ)m6?PlYa$y=RX%;}KId{m9R#2=LNwosF@OTivgMqxpRGe}5=LtAn?VVl6VWCFLD z7l#^^H8jY~42hR)OoVF#YDW(md!g(&pJ;yMj|UBAQa}UH?ED@%ci=*(q~Opn>kE2Q z_4Kgf|0kEA6ary41A;)^Ku(*nirvP!Y>{FZYBLXLP6QL~vRL+uMlZ?jWukMV*(dsn zL~~KA@jU)(UeoOz^4Gkw{fJsYQ%|UA7i79qO5=DOPBcWlv%pK!A+)*F`3WJ}t9FU3 zXhC4xMV7Z%5RjDs0=&vC4WdvD?Zi5tg4@xg8-GLUI>N$N&3aS4bHrp%3_1u9wqL)i z)XQLsI&{Hd&bQE!3m&D0vd!4D`l1$rt_{3NS?~lj#|$GN5RmvP(j3hzJOk=+0B*2v z)Bw133RMUM%wu_+$vbzOy?yk#kvR?xGsg-ipX4wKyXqd zROKp5))>tNy$HByaEHK%$mqd>-{Yoj`oSBK;w>+eZ&TVcj^DyXjo{DDbZ>vS2cCWB z(6&~GZ}kUdN(*2-nI!hvbnVy@z2E#F394OZD&Jb04}`Tgaj?MoY?1`{ejE2iud51% zQ~J0sijw(hqr_Ckbj@pm$FAVASKY(D4BS0GYPkSMqSDONRaFH+O2+jL{hIltJSJT~e)TNDr(}=Xt7|UhcU9eoXl&QZRR<9WomW%&m)FT~j zTgGd3-j}Uk%CRD;$@X)NNV9+RJbifYu>yr{FkO;p>_&njI> zyBHh_72bW;8}oGeY0gpHOxiV597j7mY<#?WMmkf5x~Kfk*re(&tG_mX<3&2cON*2u%V29tsXUv{#-ijs2>EuNH-x3) zPBpi+V6gI=wn}u164_j8xi-y(B?Au2o;UO=r6&)i5S3Mx*)*{_;u}~i4dh$`VgUS- zMG6t*?DXDYX0D2Oj31MI!HF>|aG8rjrOPnxHu4wZl;!=NGjjDoBpXf?ntrwt^dqxm zs(lE@*QB3NH)!`rH)5kks-D89g@UX&@DU9jvrsY)aI=9b4nPy3bfdX_U;#?zsan{G>DKob2LnhCJv8o}duQK)qP{7iaaf2=K`a-VNcfC582d4a z>sBJA*%S|NEazDxXcGPW_uZ&d7xG`~JB!U>U(}acUSn=FqOA~(pn^!aMXRnqiL0;? zebEZYouRv}-0r;Dq&z9>s#Rt1HL`0p4bB)A&sMyn|rE_9nh z?NO*RrjET8D4s(-`nS{MrdYtv*kyCnJKbsftG2D#ia@;42!8xd?a3P(&Y?vCf9na< zQ&Ni*1Qel&Xq{Z?=%f0SRqQt5m|Myg+8T=GDc)@^};=tM>9IDr7hdvE9-M@@<0pqv45xZTeNecbL- zWFQt4t`9>j8~X%lz}%We>Kzh_=`XO}!;4!OWH?=p*DOs#Nt({k^IvtBEL~Qafn)I^ zm*k{y7_bIs9YE}0B6%r`EIUH8US+MGY!KQA1fi-jCx9*}oz2k1nBsXp;4K<_&SN}}w<)!EylI_)v7}3&c)V;Cfuj*eJ2yc8LK=vugqTL><#65r6%#2e| zdYzZ)9Uq7)A$ol&ynM!|RDHc_7?FlWqjW>8TIHc`jExt)f5W|;D%GC#$u!%B*S%Z0 zsj&;bIU2jrt_7%$=!h4Q29n*A^^AI8R|stsW%O@?i+pN0YOU`z;TVuPy!N#~F8Z29 zzZh1`FU(q31wa>kmw{$q=MY>XBprL<1)Py~5TW4mgY%rg$S=4C^0qr+*A^T)Q)Q-U zGgRb9%MdE-&i#X3xW=I`%xDzAG95!RG9)s?v_5+qx`7NdkQ)If5}BoEp~h}XoeK>kweAMxJ8tehagx~;Nr_WP?jXa zJ&j7%Ef3w*XWf?V*nR)|IOMrX;$*$e23m?QN` zk>sC^GE=h6?*Cr~596s_QE@>Nnr?{EU+_^G=LZr#V&0fEXQ3IWtrM{=t^qJ62Sp=e zrrc>bzX^6yFV!^v7;>J9>j;`qHDQ4uc92eVe6nO@c>H=ouLQot``E~KLNqMqJ7(G+?GWO9Ol+q$w z!^kMv!n{vF?RqLnxVk{a_Ar;^sw0@=+~6!4&;SCh^utT=I zo&$CwvhNOjQpenw2`5*a6Gos6cs~*TD`8H9P4=#jOU_`%L!W;$57NjN%4 z39(61ZC#s7^tv`_4j}wMRT9rgDo*XtZwN-L;Qc$6v8kKkhmRrxSDkUAzGPgJ?}~_t zkwoGS4=6lsD`=RL|8L3O9L()N)lmEn-M15fRC{dhZ}7eYV%O-R^gsAp{q4 z!C1}_T8gy^v@SZ5R&Li5JMJy+K8iZw3LOGA0pN1~y@w7RRl#F()ii6Y5mr~Mdy@Kz z@FT4cm^I&#Fu_9IX(HAFP{XLbRALqm&)>m_we>a`hfv?eE|t z?YdDp2yAhj-~vuw^wzVDuj%w?exOcOT(ls(F*ceCe(C5HlN{lcQ;}|mRPqFDqLEzw zR7ldY+M6xe$$qLwekmk{Z&5cME$gpC?-8)f0m$rqaS|mj9ATNJvvyCgs(f2{r;2E!oy$k5{jik#(;S>do<#m0wVcU<}>)VtYmF9O0%(C>GDzPgh6X z9OkQLMR~y7=|MtaU!LDPPY7O)L{X#SC+M|v^X2CZ?$GS>U_|aC(VA(mIvCNk+biD| zSpj>gd(v>_Cbq>~-x^Y3o|?eHmuC?E&z>;Ij`%{$Pm$hI}bl0Kd`9KD~AchY+goL1?igDxf$qxL9< z4sW@sD)nwWr`T>e2B8MQN|p*DVTT8)3(%AZ&D|@Zh6`cJFT4G^y6`(UdPLY-&bJYJ z*L06f2~BX9qX}u)nrpmHPG#La#tiZ23<>`R@u8k;ueM6 znuSTY7>XEc+I-(VvL?Y>)adHo(cZ;1I7QP^q%hu#M{BEd8&mG_!EWR7ZV_&EGO;d(hGGJzX|tqyYEg2-m0zLT}a{COi$9!?9yK zGN7&yP$a|0gL`dPUt=4d^}?zrLN?HfKP0_gdRvb}1D73Hx!tXq>7{DWPV;^X{-)cm zFa^H5oBDL3uLkaFDWgFF@HL6Bt+_^g~*o*t`Hgy3M?nHhWvTp^|AQDc9_H< zg>IaSMzd7c(Sey;1SespO=8YUUArZaCc~}}tZZX80w%)fNpMExki-qB+;8xVX@dr; z#L52S6*aM-_$P9xFuIui;dN#qZ_MYy^C^hrY;YAMg;K`!ZpKKFc z9feHsool)`tFSS}Su|cL0%F;h!lpR+ym|P>kE-O`3QnHbJ%gJ$dQ_HPTT~>6WNX41 zoDEUpX-g&Hh&GP3koF4##?q*MX1K`@=W6(Gxm1=2Tb{hn8{sJyhQBoq}S>bZT zisRz-xDBYoYxt6--g2M1yh{#QWFCISux}4==r|7+fYdS$%DZ zXVQu{yPO<)Hn=TK`E@;l!09aY{!TMbT)H-l!(l{0j=SEj@JwW0a_h-2F0MZNpyucb zPPb+4&j?a!6ZnPTB>$t`(XSf-}`&+#rI#`GB> zl=$3HORwccTnA2%>$Nmz)u7j%_ywoGri1UXVNRxSf(<@vDLKKxFo;5pTI$R~a|-sQ zd5Rfwj+$k1t0{J`qOL^q>vZUHc7a^`cKKVa{66z?wMuQAfdZBaVVv@-wamPmes$d! z>gv^xx<0jXOz;7HIQS z4RBIFD?7{o^IQ=sNQ-k!ao*+V*|-^I2=UF?{d>bE9avsWbAs{sRE-y`7r zxVAKA9amvo4T}ZAHSF-{y1GqUHlDp4DO9I3mz5h8n|}P-9nKD|$r9AS3gbF1AX=2B zyaK3TbKYqv%~JHKQH8v+%zQ8UVEGDZY|mb>Oe3JD_Z{+Pq%HB+J1s*y6JOlk`6~H) zKt)YMZ*RkbU!GPHzJltmW-=6zqO=5;S)jz{ zFSx?ryqSMxgx|Nhv3z#kFBTuTBHsViaOHs5e&vXZ@l@mVI37<+^KvTE51!pB4Tggq zz!NlRY2ZLno0&6bA|KHPYOMY;;LZG&_lzuLy{@i$&B(}_*~Zk2 z>bkQ7u&Ww%CFh{aqkT{HCbPbRX&EvPRp=}WKmyHc>S_-qbwAr0<20vEoJ(!?-ucjE zKQ+nSlRL^VnOX0h+WcjGb6WI(8;7bsMaHXDb6ynPoOXMlf9nLKre;w*#E_whR#5!! z!^%_+X3eJVKc$fMZP;+xP$~e(CIP1R&{2m+iTQhDoC8Yl@kLM=Wily_cu>7C1wjVU z-^~I0P06ZSNVaN~A`#cSBH2L&tk6R%dU1(u1XdAx;g+5S^Hn9-L$v@p7CCF&PqV{Z?R$}4EJi36+u2JP7l(@fYfP!=e#76LGy^f>~vs0%s*x@X8`|5 zGd6JOHsQ=feES4Vo8%1P_7F5qjiIm#oRT0kO1(?Z_Dk6oX&j=Xd8Klk(;gk3S(ZFnc^8Gc=d;8O-R9tlGyp=2I@1teAZpGWUi;}`n zbJOS_Z2L16nVtDnPpMn{+wR9&yU9~C<-ncppPee`>@1k7hTl5Fn_3_KzQ)u{iJPp3 z)df?Xo%9ta%(dp@DhKuQj4D8=_!*ra#Ib&OXKrsYvAG%H7Kq|43WbayvsbeeimSa= z8~{7ya9ZUAIgLLPeuNmSB&#-`Je0Lja)M$}I41KHb7dQq$wgwX+EElNxBgyyLbA2* z=c1VJR%EPJEw(7!UE?4w@94{pI3E%(acEYd8*Wmr^R7|IM2RZ-RVXSkXy-8$!(iB* zQA`qh2Ze!EY6}Zs7vRz&nr|L60NlIgnO3L*Yz2k2Ivfen?drnVzzu3)1V&-t5S~S? zw#=Sdh>K@2vA25su*@>npw&7A%|Uh9T1jR$mV*H@)pU0&2#Se`7iJlOr$mp79`DKM z5vr*XLrg7w6lc4&S{So1KGKBqcuJ!E|HVFB?vTOjQHi)g+FwJqX@Y3q(qa#6T@3{q zhc@2T-W}XD9x4u+LCdce$*}x!Sc#+rH-sCz6j}0EE`Tk*irUq)y^za`}^1gFnF)C!yf_l_}I<6qfbT$Gc&Eyr?!QwJR~RE4!gKVmqjbI+I^*^ z&hz^7r-dgm@Mbfc#{JTH&^6sJCZt-NTpChB^fzQ}?etydyf~+)!d%V$0faN(f`rJb zm_YaJZ@>Fg>Ay2&bzTx3w^u-lsulc{mX4-nH*A(32O&b^EWmSuk{#HJk}_ULC}SB(L7`YAs>opp9o5UcnB^kVB*rmW6{s0&~_>J!_#+cEWib@v-Ms`?!&=3fDot`oH9v&$f<52>{n2l* z1FRzJ#yQbTHO}}wt0!y8Eh-0*|Um3vjX-nWH>`JN5tWB_gnW%; zUJ0V?_a#+!=>ahhrbGvmvObe8=v1uI8#gNHJ#>RwxL>E^pT05Br8+$@a9aDC1~$@* zicSQCbQcr=DCHM*?G7Hsovk|{$3oIwvymi#YoXeVfWj{Gd#XmnDgzQPRUKNAAI44y z{1WG&rhIR4ipmvBmq$BZ*5tmPIZmhhWgq|TcuR{6lA)+vhj(cH`0;+B^72{&a7ff* zkrIo|pd-Yxm+VVptC@QNCDk0=Re%Sz%ta7y{5Dn9(EapBS0r zLbDKeZepar5%cAcb<^;m>1{QhMzRmRem=+0I3ERot-)gb`i|sII^A#^Gz+x>TW5A& z3PQcpM$lDy`zb%1yf!e8&_>D02RN950KzW>GN6n@2so&Wu09x@PB=&IkIf|zZ1W}P zAKf*&Mo5@@G=w&290aG1@3=IMCB^|G4L7*xn;r3v&HBrD4D)Zg+)f~Ls$7*P-^i#B z4X7ac=0&58j^@2EBZCs}YPe3rqgLAA1L3Y}o?}$%u~)7Rk=LLFbAdSy@-Uw6lv?0K z&P@@M`o2Rll3GoYjotf@WNNjHbe|R?IKVn*?Rzf9v9QoFMq)ODF~>L}26@z`KA82t z43e!^z&WGqAk$Ww8j6bc3$I|;5^BHwt`?e)zf|&+l#!8uJV_Cwy-n1yS0^Q{W*a8B zTzTYL>tt&I&9vzGQUrO?YIm6C1r>eyh|qw~-&;7s7u1achP$K3VnXd8sV8J7ZTxTh z5+^*J5%_#X)XL2@>h(Gmv$@)fZ@ikR$v(2Rax89xscFEi!3_;ORI0dBxw)S{r50qf zg&_a*>2Xe{s@)7OX9O!C?^6fD8tc3bQTq9}fxhbx2@QeaO9Ej+2m!u~+u%Q6?Tgz{ zjYS}bleKcVhW~1$?t*AO^p!=Xkkgwx6OTik*R3~yg^L`wUU9Dq#$Z*iW%?s6pO_f8 zJ8w#u#Eaw7=8n{zJ}C>w{enA6XYHfUf7h)!Qaev)?V=yW{b@-z`hAz;I7^|DoFChP z1aYQnkGauh*ps6x*_S77@z1wwGmF8ky9fMbM$dr*`vsot4uvqWn)0vTRwJqH#&D%g zL3(0dP>%Oj&vm5Re%>*4x|h1J2X*mK5BH1?Nx_#7( zepgF`+n)rHXj!RiipusEq!X81;QQBXlTvLDj=Qub(ha&D=BDx3@-V*d!D9PeXUY?l zwZ0<4=iY!sUj4G>zTS+eYX7knN-8Oynl=NdwHS*nSz_5}*5LQ@=?Yr?uj$`C1m2OR zK`f5SD2|;=BhU#AmaTKe9QaSHQ_DUj1*cUPa*JICFt1<&S3P3zsrs^yUE;tx=x^cmW!Jq!+hohv_B> zPDMT0D&08dC4x@cTD$o1$x%So1Ir(G3_AVQMvQ13un~sP(cEWi$2%5q93E7t{3VJf%K? zuwSyDke~7KuB2?*#DV8YzJw z&}SCDexnUPD!%4|y~7}VzvJ4ch)WT4%sw@ItwoNt(C*RP)h?&~^g##vnhR0!HvIYx z0td2yz9=>t3JNySl*TszmfH6`Ir;ft@RdWs3}!J88UE|gj_GMQ6$ZYphUL2~4OY7} zB*33_bjkRf_@l;Y!7MIdb~bVe;-m78Pz|pdy=O*3kjak63UnLt!{^!!Ljg0rJD3a~ z1Q;y5Z^MF<=Hr}rdoz>yRczx+p3RxxgJE2GX&Si)14B@2t21j4hnnP#U?T3g#+{W+Zb z5s^@>->~-}4|_*!5pIzMCEp|3+i1XKcfUxW`8|ezAh>y{WiRcjSG*asw6;Ef(k#>V ztguN?EGkV_mGFdq!n#W)<7E}1#EZN8O$O|}qdoE|7K?F4zo1jL-v}E8v?9qz(d$&2 zMwyK&xlC9rXo_2xw7Qe0caC?o?Pc*-QAOE!+UvRuKjG+;dk|jQhDDBe?`XT7Y5lte zqSu0t5`;>Wv%|nhj|ZiE^IqA_lZu7OWh!2Y(627zb=r7Ends}wVk7Q5o09a@ojhH7 zU0m&h*8+j4e|OqWyJ&B`V`y=>MVO;K9=hk^6EsmVAGkLT{oUtR{JqSRY{Qi{kKw1k z6s;0SMPJOLp!som|A`*q3t0wIj-=bG8a#MC)MHcMSQU98Juv$?$CvYX)(n`P^!`5| zv3q@@|G@6wMqh;d;m4qvdibx2Yjml}vG9mDv&!0ne02M#D`Bo}xIB0VWh8>>WtNZQ z$&ISlJX;*ORQIO;k62qA{^6P%3!Z=Y1EbmY02{w^yB$`;%!{kur&XTGDiO2cjA)lr zsY^XZWy^DSAaz;kZ_VG?uWnJR7qdN18$~)>(kOoybY0~QYu9||K#|$Mby{3GduV~N zk9H7$7=RSo+?CUYF502`b76ytBy}sFak&|HIwRvB=0D|S`c#QCJPq zP)uOWI)#(n&{6|C4A^G~%B~BY21aOMoz9RuuM`Ip%oBz+NoAlb7?#`E^}7xXo!4S? zFg8I~G%!@nXi8&aJSGFcZAxQf;0m}942=i#p-&teLvE{AKm7Sl2f}Io?!IqbC|J;h z`=5LFOnU5?^w~SV@YwNZx$k_(kLNxZDE z3cf08^-rIT_>A$}B%IJBPcN^)4;90BQtiEi!gT#+EqyAUZ|}*b_}R>SGloq&6?opL zuT_+lwQMgg6!Cso$BwUA;k-1NcrzyE>(_X$B0HocjY~=Pk~Q08+N}(|%HjO_i+*=o z%G6C6A30Ch<0UlG;Zdj@ed!rfUY_i9mYwK8(aYuzcUzlTJ1yPz|Bb-9b33A9zRhGl>Ny-Q#JAq-+qtI@B@&w z$;PJbyiW=!py@g2hAi0)U1v=;avka`gd@8LC4=BEbNqL&K^UAQ5%r95#x%^qRB%KLaqMnG|6xKAm}sx!Qwo}J=2C;NROi$mfADui4)y(3wVA3k~{j^_5%H)C6K zlYAm1eY**HZOj($)xfKIQFtIVw$4&yvz9>(Crs>Gh{ zya6-FG7Dgi92#K)64=9Csj5?Zqe~_9TwSI!2quAwa1w-*uC5!}xY`?tltb0Hq740< zsq2QelPveZ4chr$=~U3!+c&>xyfvA1`)owOqj=i4wjY=A1577Gwg&Ko7;?il9r|_* z8P&IDV_g2D{in5OLFxsO!kx3AhO$5aKeoM|!q|VokqMlYM@HtsRuMtBY%I35#5$+G zpp|JOeoj^U=95HLemB04Yqv{a8X<^K9G2`&ShM_6&Bi1n?o?@MXsDj9Z*A3>#XK%J zRc*&SlFl>l)9DyRQ{*%Z+^e1XpH?0@vhpXrnPPU*d%vOhKkimm-u3c%Q^v3RKp9kx@A2dS?QfS=iigGr7m><)YkV=%LA5h@Uj@9=~ABPMJ z1UE;F&;Ttg5Kc^Qy!1SuvbNEqdgu3*l`=>s5_}dUv$B%BJbMiWrrMm7OXOdi=GOmh zZBvXXK7VqO&zojI2Om9};zCB5i|<210I{iwiGznGCx=FT89=Ef)5!lB1cZ6lbzgDn07*he}G&w7m!;|E(L-?+cz@0<9ZI~LqYQE7>HnPA436}oeN2Y(VfG6 zxNZuMK3Crm^Z_AFeHc~CVRrSl0W^?+Gbteu1g8NGYa3(8f*P{(ZT>%!jtSl6WbYVv zmE(37t0C8vJ6O-5+o*lL9XRcFbd~GSBGbGh3~R!67g&l)7n!kJlWd)~TUyXus#!&G6sR%(l(h1$xyrR5j_jM1zj#giA&@(Xl26@n<9>folx!92bQ z24h570+<)4!$!IQ(5yOU|4_E6aN@4v0+{Kx~Z z;q7fp%0cHziuI%!kB~w}g9@V+1wDz0wFlzX2UOvOy|&;e;t!lAR8tV2KQHgtfk8Uf zw;rs!(4JPODERk4ckd5I2Vq|0rd@@Mwd8MID%0^fITjYIQom^q;qhP8@|eJx{?5xX zc1@Fj*kDknlk{c-rnCloQ3hGh7OU+@efO3>fkRMcM>J?AeVP& zlfzX%cdp=N+4S#E*%^=BQ+N`A7C}|k%$|QUn0yI6S3$MS-NjO!4hm55uyju)Q6e!} z*OVO@A#-mfC9Pha6ng((Xl^V7{d+&u+yx)_B1{~t7d5e8L^i4J>;x<7@5;+l7-Gge zf#9diXJ$&v^rbN5V(ee%q0xBMEgS6%qZm7hNUP%G;^J44I!BmI@M*+FWz0!+s;+iQ zU4CuI+27bvNK8v>?7PZnVxB=heJ&_ymE0nN^W#-rqB%+JXkYGDuRw>JM_LdtLkiq* z6%%3&^BX$jnM@2bjiGc-DymKly)wVkA-pq;jSWL#7_*moZZ4I|-N}o8SK?sIv)p|c zu~9-B%tMc=!)YMFp*SiC0>kfnH8+X5>;+FFVN{~a9YVdIg1uGkZ~kegFy{^PU(4{( z`CbY`XmVA3esai686Yw8djCEyF7`bfB^F1)nwv+AqYLZ&Zy=eFhYT2uMd@{sP_qS4 zbJ&>PxajjZt?&c<1^!T|pLHfX=E^FJ>-l_XCZzvRV%x}@u(FtF(mS+Umw$e+IA74e>gCdTqi;6&=euAIpxd=Y3I5xWR zBhGoT+T`V1@91OlQ}2YO*~P4ukd*TBBdt?Plt)_ou6Y@Db`ss+Q~A-48s>?eaJYA2 zRGOa8^~Em}EFTmKIVVbMb|ob)hJJ7ITg>yHAn2i|{2ZJU!cwt9YNDT0=*WO7Bq#Xj zg@FjEaKoolrF8%c;49|`IT&25?O$dq8kp3#la9&6aH z6G|{>^C(>yP7#Dr$aeFyS0Ai_$ILhL43#*mgEl(c*4?Ae;tRL&S7Vc}Szl>B`mBuI zB9Y%xp%CZwlH!3V(`6W4-ZuETssvI&B~_O;CbULfl)X1V%(H7VSPf`_Ka9ak@8A=z z1l|B1QKT}NLI`WVTRd;2En5u{0CRqy9PTi$ja^inu){LJ&E&6W%JJPw#&PaTxpt?k zpC~gjN*22Q8tpGHR|tg~ye#9a8N<%odhZJnk7Oh=(PKfhYfzLAxdE36r<6a?A;rO&ELp_Y?8Pdw(PT^Fxn!eG_|LEbSYoBrsBA|6Fgr zt5LntyusI{Q2fdy=>ditS;}^B;I2MD4=(>7fWt0Jp~y=?VvfvzHvQhj6dyIef46J$ zl4Xu7U9v_NJV?uBBC0!kcTS0UcrV7+@~is?Fi+jrr@l3XwD|uG zr26jUWiv>Ju48Y^#qn7r9mwIH-Pv6Y|V|V-GZ&+&gQ?S?-`&ts{@5GXPqbmyZjUACC&oVXfNwUX0}ba(v978 zp8z!v9~8Zx8qB@7>oFPDm^iR@+yw`79YF)w^OHB_N;&&x7c3l^3!)IY#)}x)@D(iNaOm9 zC=^*!{`7={3*S=%iU=KsPXh=DDZcc``Ss>057i{pdW8M@4q+Ba@Tt%OytH!4>rbIbQw^-pR zGGYNPzw@n=PV@)b7yVbFr;glF*Qq3>F9oBN5PUXt!?2mdGcpv^o1?Thp`jP10G2Yi z(c93td3F3SW!Le5DUwdub!aDKoVLU6g!O?Ret21l$qOC;kdd@L#M&baVu&JZGt&<6 z!VCkvgRaav6QDW2x}tUy4~Y5(B+#Ej-8vM?DM-1?J_*&PntI3E96M!`WL#<&Z5n2u zo`P!~vBT$YOT~gU9#PB)%JZ zcd_u=m^LYzC!pH#W`yA1!(fA;D~b zG#73@l)NNd;n#XrKXZEfab;@kQRnOFU2Th-1m<4mJzlj9b3pv-GF$elX7ib9!uILM_$ke zHIGB*&=5=;ynQA{y7H93%i^d)T}y@(p>8vVhJ4L)M{0Q*@D^+SPp`EW+G6E%+`Z;u zS3goV@Dic7vc5`?!pCN44Ts@*{)zwy)9?B||AM{zKlN4T}qQRL2 zgv+{K8bv7w)#xge16;kI1fU87!W4pX)N&|cq8&i^1r`W|Hg4366r(?-ecEJ9u&Eaw zrhyikXQB>C9d>cpPGiu=VU3Z-u4|0V_iap!_J3o+K_R5EXk@sfu~zHwwYkpncVh!R zqNe7Cmf_|Wmeq4#(mIO&(wCK@b4(x0?W1Qtk(`$?+$uCJCGZm_%k?l32vuShgDFMa ztc`{$8DhB9)&?~(m&EUc=LzI1=qo#zjy#2{hLT_*aj<618qQ7mD#k2ZFGou&69;=2 z1j7=Su8k}{L*h&mfs7jg^PN&9C1Z@U!p6gXk&-7xM~{X`nqH#aGO`;Xy_zbz^rYacIq0AH%4!Oh93TzJ820%ur)8OyeS@K?sF1V(iFO z37Nnqj1z#1{|v7=_CX`lQA|$<1gtuNMHGNJYp1D_k;WQk-b+T6VmUK(x=bWviOZ~T z|4e%SpuaWLWD?qN2%`S*`P;BQBw(B__wTD6epvGdJ+>DBq2oVlf&F*lz+#avb4)3P1c^Mf#olQheVvZ|Z5 z>xXfgmv!5Z^SYn+_x}K5B%G^sRwiez&z9|f!E!#oJlT2kCOV0000$L_|bHBqAarB4TD{W@grX1CUr72@caw0faEd7-K|4L_|cawbojjHdpd6 zI6~Iv5J?-Q4*&oF000000FV;^004t70Z6Qk1Xl{X9oJ{sRC2(cs?- literal 0 HcmV?d00001 From 06cfb173eaebb8c6dfb88b897068c913d03ff987 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Thu, 2 Jul 2015 19:55:34 +0530 Subject: [PATCH 143/666] Add button to clear filters --- junction/templates/proposals/to_review.html | 58 ++++++++++++++------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/junction/templates/proposals/to_review.html b/junction/templates/proposals/to_review.html index 0dcd295e..5c3c7061 100644 --- a/junction/templates/proposals/to_review.html +++ b/junction/templates/proposals/to_review.html @@ -40,18 +40,20 @@ {% if proposals_to_review %}

Proposals To Review


-

Filter Proposals

-
- {% csrf_token %} - {% bootstrap_form form %} - {% buttons %} -
- -
- {% endbuttons %} - +
+

Filter Proposals

+
+ {% csrf_token %} + {% bootstrap_form form %} + {% buttons %} +
+ +
+ {% endbuttons %} + +

@@ -59,7 +61,7 @@

Filter Proposals

{% include 'proposals/partials/proposal-list--review-items.html' with proposals=section_items.proposals title=section_items.section display_status=False %} {% endfor %}
- + {% else %}

No proposals to review.

{% endif %} @@ -69,14 +71,32 @@

Filter Proposals

{% block script_extra %} {% endblock %} From c2871a20c5ef5ecf0c34ddca7d386ad58278ab1d Mon Sep 17 00:00:00 2001 From: chillaranand Date: Thu, 2 Jul 2015 19:56:13 +0530 Subject: [PATCH 144/666] Add `all` option to existing options in dropdown --- junction/templates/proposals/to_review.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/junction/templates/proposals/to_review.html b/junction/templates/proposals/to_review.html index 5c3c7061..b691eada 100644 --- a/junction/templates/proposals/to_review.html +++ b/junction/templates/proposals/to_review.html @@ -75,6 +75,11 @@

Filter Proposals

$('#filter').append('
'); }; + $.each($('select'), function(val, text) { + $(this).prepend( new Option('All', 'All') ); + $(this).val('All').change(); + }); + is_clicked = false; $( 'button[type="submit"]' ).click(function(e){ e.preventDefault(); From b2e20775f70a1f33bb989cdb5d610ca0e06fd8eb Mon Sep 17 00:00:00 2001 From: chillaranand Date: Thu, 2 Jul 2015 20:12:04 +0530 Subject: [PATCH 145/666] Only logged in reviewer comments should be counted In proposals to review page, only current users comment count should be considered. Other reviewers comments are irrelevant to current reviewer. --- junction/proposals/models.py | 6 +++--- junction/proposals/templatetags/__init__.py | 0 junction/proposals/templatetags/proposal_filters.py | 13 +++++++++++++ .../partials/proposal-list--review-items.html | 7 +++++-- 4 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 junction/proposals/templatetags/__init__.py create mode 100644 junction/proposals/templatetags/proposal_filters.py diff --git a/junction/proposals/models.py b/junction/proposals/models.py index fc5bebaf..647ef2cf 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -110,9 +110,9 @@ def get_reviews_comments_count(self): """ Show only private comments count """ return ProposalComment.objects.filter(proposal=self, deleted=False, private=True).count() - def has_reviewer_comments(self): - """ Proposals has reviewer comments """ - return ProposalComment.objects.filter(proposal=self, deleted=False, private=True).count() > 0 + def get_reviewer_comments_count(self, user): + """ Number of private comments by a reviewer """ + return ProposalComment.objects.filter(proposal=self, deleted=False, private=True, commenter=user).count() def get_votes_count(self): """ Show only the public comment count """ diff --git a/junction/proposals/templatetags/__init__.py b/junction/proposals/templatetags/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py new file mode 100644 index 00000000..dfb685d8 --- /dev/null +++ b/junction/proposals/templatetags/proposal_filters.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +# Third Party Stuff +from django import template + + +register = template.Library() + + +@register.filter(name='reviewer_comments') +def reviewer_comments(proposal, user): + return proposal.get_reviewer_comments_count(user) > 0 diff --git a/junction/templates/proposals/partials/proposal-list--review-items.html b/junction/templates/proposals/partials/proposal-list--review-items.html index 47c8584c..3a590439 100644 --- a/junction/templates/proposals/partials/proposal-list--review-items.html +++ b/junction/templates/proposals/partials/proposal-list--review-items.html @@ -1,3 +1,6 @@ +{% load proposal_filters %} + +
{% if title %} @@ -5,7 +8,7 @@

{{ title }}

{% endif %} {% for proposal in proposals %} -
+
{% endif %} + + {% if proposal.speaker_info %}

Speaker Info:

@@ -233,20 +241,31 @@

Speaker Links:

{% endblock %} {% block script_extra %} - + {% endblock %} diff --git a/junction/templates/proposals/email/upload_content/message.html b/junction/templates/proposals/email/upload_content/message.html new file mode 100644 index 00000000..a8371143 --- /dev/null +++ b/junction/templates/proposals/email/upload_content/message.html @@ -0,0 +1,16 @@ +Hi {{ author_name }}, + + +We are glad with Your proposal {{ proposal.title }} for {{ conference.name }}. As you are aware that reviewers are providing feedback and helping you with the content, we request you to share the draft version of your presentation in junction.

+ +We understand that you might feel that its too early to upload the presentation without knowing about talk selection. But this would help the reviewers understand your content in detail and provide feedback accordingly.

+ +If you have proposed a workshop, do share the draft version of the content you are planning to present in ppt or pdf format, code snippets can be added later.

+ +Looking forward to seeing you in {{ conference.name }}.

+ +Thanks,
+{{ conference.name }} Team

+ +------------------------------------------------------------------------------- +PS: Please, don't reply to the email. You can login ({{host}}{{login_url}}) to add content to proposal. diff --git a/junction/templates/proposals/email/upload_content/message.txt b/junction/templates/proposals/email/upload_content/message.txt new file mode 100644 index 00000000..a4ec871c --- /dev/null +++ b/junction/templates/proposals/email/upload_content/message.txt @@ -0,0 +1,16 @@ +Hi {{ author_name }}, + +We are glad with Your proposal {{ proposal.title }} for {{ conference.name }}. As you are aware that reviewers are providing feedback and helping you with the content, we request you to share the draft version of your presentation in junction. + +We understand that you might feel that its too early to upload the presentation without knowing about talk selection. But this would help the reviewers understand your content in detail and provide feedback accordingly. + +If you have proposed a workshop, do share the draft version of the content you are planning to present in ppt or pdf format, code snippets can be added later. + +Looking forward to seeing you in {{ conference.name }}. + +Thanks,
+{{ conference.name }} Team

+ +------------------------------------------------------------------------------- +PS: Please, don't reply to the email. You can login ({{host}}{{login_url}}) to add content to proposal. + diff --git a/junction/templates/proposals/email/upload_content/subject.txt b/junction/templates/proposals/email/upload_content/subject.txt new file mode 100644 index 00000000..88f2dca9 --- /dev/null +++ b/junction/templates/proposals/email/upload_content/subject.txt @@ -0,0 +1 @@ +Request to upload content for "{{proposal}}" From 4f7ffe647e85c6bead70c41279c63249c8737ed3 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 6 Jul 2015 22:51:06 +0530 Subject: [PATCH 149/666] Add sweetalert static files --- junction/static/css/sweetalert.css | 715 ++++++++++++++++++ junction/static/js/sweetalert.min.js | 1 + junction/templates/proposals/detail/base.html | 4 +- 3 files changed, 718 insertions(+), 2 deletions(-) create mode 100644 junction/static/css/sweetalert.css create mode 100644 junction/static/js/sweetalert.min.js diff --git a/junction/static/css/sweetalert.css b/junction/static/css/sweetalert.css new file mode 100644 index 00000000..4469aea6 --- /dev/null +++ b/junction/static/css/sweetalert.css @@ -0,0 +1,715 @@ +body.stop-scrolling { + height: 100%; + overflow: hidden; } + +.sweet-overlay { + background-color: black; + /* IE8 */ + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)"; + /* IE8 */ + background-color: rgba(0, 0, 0, 0.4); + position: fixed; + left: 0; + right: 0; + top: 0; + bottom: 0; + display: none; + z-index: 10000; } + +.sweet-alert { + background-color: white; + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + width: 478px; + padding: 17px; + border-radius: 5px; + text-align: center; + position: fixed; + left: 50%; + top: 50%; + margin-left: -256px; + margin-top: -200px; + overflow: hidden; + display: none; + z-index: 99999; } + @media all and (max-width: 540px) { + .sweet-alert { + width: auto; + margin-left: 0; + margin-right: 0; + left: 15px; + right: 15px; } } + .sweet-alert h2 { + color: #575757; + font-size: 30px; + text-align: center; + font-weight: 600; + text-transform: none; + position: relative; + margin: 25px 0; + padding: 0; + line-height: 40px; + display: block; } + .sweet-alert p { + color: #797979; + font-size: 16px; + text-align: center; + font-weight: 300; + position: relative; + text-align: inherit; + float: none; + margin: 0; + padding: 0; + line-height: normal; } + .sweet-alert fieldset { + border: none; + position: relative; } + .sweet-alert .sa-error-container { + background-color: #f1f1f1; + margin-left: -17px; + margin-right: -17px; + overflow: hidden; + padding: 0 10px; + max-height: 0; + webkit-transition: padding 0.15s, max-height 0.15s; + transition: padding 0.15s, max-height 0.15s; } + .sweet-alert .sa-error-container.show { + padding: 10px 0; + max-height: 100px; + webkit-transition: padding 0.2s, max-height 0.2s; + transition: padding 0.25s, max-height 0.25s; } + .sweet-alert .sa-error-container .icon { + display: inline-block; + width: 24px; + height: 24px; + border-radius: 50%; + background-color: #ea7d7d; + color: white; + line-height: 24px; + text-align: center; + margin-right: 3px; } + .sweet-alert .sa-error-container p { + display: inline-block; } + .sweet-alert .sa-input-error { + position: absolute; + top: 29px; + right: 26px; + width: 20px; + height: 20px; + opacity: 0; + -webkit-transform: scale(0.5); + transform: scale(0.5); + -webkit-transform-origin: 50% 50%; + transform-origin: 50% 50%; + -webkit-transition: all 0.1s; + transition: all 0.1s; } + .sweet-alert .sa-input-error::before, .sweet-alert .sa-input-error::after { + content: ""; + width: 20px; + height: 6px; + background-color: #f06e57; + border-radius: 3px; + position: absolute; + top: 50%; + margin-top: -4px; + left: 50%; + margin-left: -9px; } + .sweet-alert .sa-input-error::before { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); } + .sweet-alert .sa-input-error::after { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); } + .sweet-alert .sa-input-error.show { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); } + .sweet-alert input { + width: 100%; + box-sizing: border-box; + border-radius: 3px; + border: 1px solid #d7d7d7; + height: 43px; + margin-top: 10px; + margin-bottom: 17px; + font-size: 18px; + box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.06); + padding: 0 12px; + display: none; + -webkit-transition: all 0.3s; + transition: all 0.3s; } + .sweet-alert input:focus { + outline: none; + box-shadow: 0px 0px 3px #c4e6f5; + border: 1px solid #b4dbed; } + .sweet-alert input:focus::-moz-placeholder { + transition: opacity 0.3s 0.03s ease; + opacity: 0.5; } + .sweet-alert input:focus:-ms-input-placeholder { + transition: opacity 0.3s 0.03s ease; + opacity: 0.5; } + .sweet-alert input:focus::-webkit-input-placeholder { + transition: opacity 0.3s 0.03s ease; + opacity: 0.5; } + .sweet-alert input::-moz-placeholder { + color: #bdbdbd; } + .sweet-alert input:-ms-input-placeholder { + color: #bdbdbd; } + .sweet-alert input::-webkit-input-placeholder { + color: #bdbdbd; } + .sweet-alert.show-input input { + display: block; } + .sweet-alert button { + background-color: #AEDEF4; + color: white; + border: none; + box-shadow: none; + font-size: 17px; + font-weight: 500; + -webkit-border-radius: 4px; + border-radius: 5px; + padding: 10px 32px; + margin: 26px 5px 0 5px; + cursor: pointer; } + .sweet-alert button:focus { + outline: none; + box-shadow: 0 0 2px rgba(128, 179, 235, 0.5), inset 0 0 0 1px rgba(0, 0, 0, 0.05); } + .sweet-alert button:hover { + background-color: #a1d9f2; } + .sweet-alert button:active { + background-color: #81ccee; } + .sweet-alert button.cancel { + background-color: #D0D0D0; } + .sweet-alert button.cancel:hover { + background-color: #c8c8c8; } + .sweet-alert button.cancel:active { + background-color: #b6b6b6; } + .sweet-alert button.cancel:focus { + box-shadow: rgba(197, 205, 211, 0.8) 0px 0px 2px, rgba(0, 0, 0, 0.0470588) 0px 0px 0px 1px inset !important; } + .sweet-alert button::-moz-focus-inner { + border: 0; } + .sweet-alert[data-has-cancel-button=false] button { + box-shadow: none !important; } + .sweet-alert[data-has-confirm-button=false][data-has-cancel-button=false] { + padding-bottom: 40px; } + .sweet-alert .sa-icon { + width: 80px; + height: 80px; + border: 4px solid gray; + -webkit-border-radius: 40px; + border-radius: 40px; + border-radius: 50%; + margin: 20px auto; + padding: 0; + position: relative; + box-sizing: content-box; } + .sweet-alert .sa-icon.sa-error { + border-color: #F27474; } + .sweet-alert .sa-icon.sa-error .sa-x-mark { + position: relative; + display: block; } + .sweet-alert .sa-icon.sa-error .sa-line { + position: absolute; + height: 5px; + width: 47px; + background-color: #F27474; + display: block; + top: 37px; + border-radius: 2px; } + .sweet-alert .sa-icon.sa-error .sa-line.sa-left { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + left: 17px; } + .sweet-alert .sa-icon.sa-error .sa-line.sa-right { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + right: 16px; } + .sweet-alert .sa-icon.sa-warning { + border-color: #F8BB86; } + .sweet-alert .sa-icon.sa-warning .sa-body { + position: absolute; + width: 5px; + height: 47px; + left: 50%; + top: 10px; + -webkit-border-radius: 2px; + border-radius: 2px; + margin-left: -2px; + background-color: #F8BB86; } + .sweet-alert .sa-icon.sa-warning .sa-dot { + position: absolute; + width: 7px; + height: 7px; + -webkit-border-radius: 50%; + border-radius: 50%; + margin-left: -3px; + left: 50%; + bottom: 10px; + background-color: #F8BB86; } + .sweet-alert .sa-icon.sa-info { + border-color: #C9DAE1; } + .sweet-alert .sa-icon.sa-info::before { + content: ""; + position: absolute; + width: 5px; + height: 29px; + left: 50%; + bottom: 17px; + border-radius: 2px; + margin-left: -2px; + background-color: #C9DAE1; } + .sweet-alert .sa-icon.sa-info::after { + content: ""; + position: absolute; + width: 7px; + height: 7px; + border-radius: 50%; + margin-left: -3px; + top: 19px; + background-color: #C9DAE1; } + .sweet-alert .sa-icon.sa-success { + border-color: #A5DC86; } + .sweet-alert .sa-icon.sa-success::before, .sweet-alert .sa-icon.sa-success::after { + content: ''; + -webkit-border-radius: 40px; + border-radius: 40px; + border-radius: 50%; + position: absolute; + width: 60px; + height: 120px; + background: white; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); } + .sweet-alert .sa-icon.sa-success::before { + -webkit-border-radius: 120px 0 0 120px; + border-radius: 120px 0 0 120px; + top: -7px; + left: -33px; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + -webkit-transform-origin: 60px 60px; + transform-origin: 60px 60px; } + .sweet-alert .sa-icon.sa-success::after { + -webkit-border-radius: 0 120px 120px 0; + border-radius: 0 120px 120px 0; + top: -11px; + left: 30px; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + -webkit-transform-origin: 0px 60px; + transform-origin: 0px 60px; } + .sweet-alert .sa-icon.sa-success .sa-placeholder { + width: 80px; + height: 80px; + border: 4px solid rgba(165, 220, 134, 0.2); + -webkit-border-radius: 40px; + border-radius: 40px; + border-radius: 50%; + box-sizing: content-box; + position: absolute; + left: -4px; + top: -4px; + z-index: 2; } + .sweet-alert .sa-icon.sa-success .sa-fix { + width: 5px; + height: 90px; + background-color: white; + position: absolute; + left: 28px; + top: 8px; + z-index: 1; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); } + .sweet-alert .sa-icon.sa-success .sa-line { + height: 5px; + background-color: #A5DC86; + display: block; + border-radius: 2px; + position: absolute; + z-index: 2; } + .sweet-alert .sa-icon.sa-success .sa-line.sa-tip { + width: 25px; + left: 14px; + top: 46px; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); } + .sweet-alert .sa-icon.sa-success .sa-line.sa-long { + width: 47px; + right: 8px; + top: 38px; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); } + .sweet-alert .sa-icon.sa-custom { + background-size: contain; + border-radius: 0; + border: none; + background-position: center center; + background-repeat: no-repeat; } + +/* + * Animations + */ +@-webkit-keyframes showSweetAlert { + 0% { + transform: scale(0.7); + -webkit-transform: scale(0.7); } + 45% { + transform: scale(1.05); + -webkit-transform: scale(1.05); } + 80% { + transform: scale(0.95); + -webkit-transform: scale(0.95); } + 100% { + transform: scale(1); + -webkit-transform: scale(1); } } + +@keyframes showSweetAlert { + 0% { + transform: scale(0.7); + -webkit-transform: scale(0.7); } + 45% { + transform: scale(1.05); + -webkit-transform: scale(1.05); } + 80% { + transform: scale(0.95); + -webkit-transform: scale(0.95); } + 100% { + transform: scale(1); + -webkit-transform: scale(1); } } + +@-webkit-keyframes hideSweetAlert { + 0% { + transform: scale(1); + -webkit-transform: scale(1); } + 100% { + transform: scale(0.5); + -webkit-transform: scale(0.5); } } + +@keyframes hideSweetAlert { + 0% { + transform: scale(1); + -webkit-transform: scale(1); } + 100% { + transform: scale(0.5); + -webkit-transform: scale(0.5); } } + +@-webkit-keyframes slideFromTop { + 0% { + top: 0%; } + 100% { + top: 50%; } } + +@keyframes slideFromTop { + 0% { + top: 0%; } + 100% { + top: 50%; } } + +@-webkit-keyframes slideToTop { + 0% { + top: 50%; } + 100% { + top: 0%; } } + +@keyframes slideToTop { + 0% { + top: 50%; } + 100% { + top: 0%; } } + +@-webkit-keyframes slideFromBottom { + 0% { + top: 70%; } + 100% { + top: 50%; } } + +@keyframes slideFromBottom { + 0% { + top: 70%; } + 100% { + top: 50%; } } + +@-webkit-keyframes slideToBottom { + 0% { + top: 50%; } + 100% { + top: 70%; } } + +@keyframes slideToBottom { + 0% { + top: 50%; } + 100% { + top: 70%; } } + +.showSweetAlert[data-animation=pop] { + -webkit-animation: showSweetAlert 0.3s; + animation: showSweetAlert 0.3s; } + +.showSweetAlert[data-animation=none] { + -webkit-animation: none; + animation: none; } + +.showSweetAlert[data-animation=slide-from-top] { + -webkit-animation: slideFromTop 0.3s; + animation: slideFromTop 0.3s; } + +.showSweetAlert[data-animation=slide-from-bottom] { + -webkit-animation: slideFromBottom 0.3s; + animation: slideFromBottom 0.3s; } + +.hideSweetAlert[data-animation=pop] { + -webkit-animation: hideSweetAlert 0.2s; + animation: hideSweetAlert 0.2s; } + +.hideSweetAlert[data-animation=none] { + -webkit-animation: none; + animation: none; } + +.hideSweetAlert[data-animation=slide-from-top] { + -webkit-animation: slideToTop 0.4s; + animation: slideToTop 0.4s; } + +.hideSweetAlert[data-animation=slide-from-bottom] { + -webkit-animation: slideToBottom 0.3s; + animation: slideToBottom 0.3s; } + +@-webkit-keyframes animateSuccessTip { + 0% { + width: 0; + left: 1px; + top: 19px; } + 54% { + width: 0; + left: 1px; + top: 19px; } + 70% { + width: 50px; + left: -8px; + top: 37px; } + 84% { + width: 17px; + left: 21px; + top: 48px; } + 100% { + width: 25px; + left: 14px; + top: 45px; } } + +@keyframes animateSuccessTip { + 0% { + width: 0; + left: 1px; + top: 19px; } + 54% { + width: 0; + left: 1px; + top: 19px; } + 70% { + width: 50px; + left: -8px; + top: 37px; } + 84% { + width: 17px; + left: 21px; + top: 48px; } + 100% { + width: 25px; + left: 14px; + top: 45px; } } + +@-webkit-keyframes animateSuccessLong { + 0% { + width: 0; + right: 46px; + top: 54px; } + 65% { + width: 0; + right: 46px; + top: 54px; } + 84% { + width: 55px; + right: 0px; + top: 35px; } + 100% { + width: 47px; + right: 8px; + top: 38px; } } + +@keyframes animateSuccessLong { + 0% { + width: 0; + right: 46px; + top: 54px; } + 65% { + width: 0; + right: 46px; + top: 54px; } + 84% { + width: 55px; + right: 0px; + top: 35px; } + 100% { + width: 47px; + right: 8px; + top: 38px; } } + +@-webkit-keyframes rotatePlaceholder { + 0% { + transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); } + 5% { + transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); } + 12% { + transform: rotate(-405deg); + -webkit-transform: rotate(-405deg); } + 100% { + transform: rotate(-405deg); + -webkit-transform: rotate(-405deg); } } + +@keyframes rotatePlaceholder { + 0% { + transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); } + 5% { + transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); } + 12% { + transform: rotate(-405deg); + -webkit-transform: rotate(-405deg); } + 100% { + transform: rotate(-405deg); + -webkit-transform: rotate(-405deg); } } + +.animateSuccessTip { + -webkit-animation: animateSuccessTip 0.75s; + animation: animateSuccessTip 0.75s; } + +.animateSuccessLong { + -webkit-animation: animateSuccessLong 0.75s; + animation: animateSuccessLong 0.75s; } + +.sa-icon.sa-success.animate::after { + -webkit-animation: rotatePlaceholder 4.25s ease-in; + animation: rotatePlaceholder 4.25s ease-in; } + +@-webkit-keyframes animateErrorIcon { + 0% { + transform: rotateX(100deg); + -webkit-transform: rotateX(100deg); + opacity: 0; } + 100% { + transform: rotateX(0deg); + -webkit-transform: rotateX(0deg); + opacity: 1; } } + +@keyframes animateErrorIcon { + 0% { + transform: rotateX(100deg); + -webkit-transform: rotateX(100deg); + opacity: 0; } + 100% { + transform: rotateX(0deg); + -webkit-transform: rotateX(0deg); + opacity: 1; } } + +.animateErrorIcon { + -webkit-animation: animateErrorIcon 0.5s; + animation: animateErrorIcon 0.5s; } + +@-webkit-keyframes animateXMark { + 0% { + transform: scale(0.4); + -webkit-transform: scale(0.4); + margin-top: 26px; + opacity: 0; } + 50% { + transform: scale(0.4); + -webkit-transform: scale(0.4); + margin-top: 26px; + opacity: 0; } + 80% { + transform: scale(1.15); + -webkit-transform: scale(1.15); + margin-top: -6px; } + 100% { + transform: scale(1); + -webkit-transform: scale(1); + margin-top: 0; + opacity: 1; } } + +@keyframes animateXMark { + 0% { + transform: scale(0.4); + -webkit-transform: scale(0.4); + margin-top: 26px; + opacity: 0; } + 50% { + transform: scale(0.4); + -webkit-transform: scale(0.4); + margin-top: 26px; + opacity: 0; } + 80% { + transform: scale(1.15); + -webkit-transform: scale(1.15); + margin-top: -6px; } + 100% { + transform: scale(1); + -webkit-transform: scale(1); + margin-top: 0; + opacity: 1; } } + +.animateXMark { + -webkit-animation: animateXMark 0.5s; + animation: animateXMark 0.5s; } + +@-webkit-keyframes pulseWarning { + 0% { + border-color: #F8D486; } + 100% { + border-color: #F8BB86; } } + +@keyframes pulseWarning { + 0% { + border-color: #F8D486; } + 100% { + border-color: #F8BB86; } } + +.pulseWarning { + -webkit-animation: pulseWarning 0.75s infinite alternate; + animation: pulseWarning 0.75s infinite alternate; } + +@-webkit-keyframes pulseWarningIns { + 0% { + background-color: #F8D486; } + 100% { + background-color: #F8BB86; } } + +@keyframes pulseWarningIns { + 0% { + background-color: #F8D486; } + 100% { + background-color: #F8BB86; } } + +.pulseWarningIns { + -webkit-animation: pulseWarningIns 0.75s infinite alternate; + animation: pulseWarningIns 0.75s infinite alternate; } + +/* Internet Explorer 9 has some special quirks that are fixed here */ +/* The icons are not animated. */ +/* This file is automatically merged into sweet-alert.min.js through Gulp */ +/* Error icon */ +.sweet-alert .sa-icon.sa-error .sa-line.sa-left { + -ms-transform: rotate(45deg) \9; } + +.sweet-alert .sa-icon.sa-error .sa-line.sa-right { + -ms-transform: rotate(-45deg) \9; } + +/* Success icon */ +.sweet-alert .sa-icon.sa-success { + border-color: transparent\9; } + +.sweet-alert .sa-icon.sa-success .sa-line.sa-tip { + -ms-transform: rotate(45deg) \9; } + +.sweet-alert .sa-icon.sa-success .sa-line.sa-long { + -ms-transform: rotate(-45deg) \9; } diff --git a/junction/static/js/sweetalert.min.js b/junction/static/js/sweetalert.min.js new file mode 100644 index 00000000..3e4e7ff4 --- /dev/null +++ b/junction/static/js/sweetalert.min.js @@ -0,0 +1 @@ +!function(e,t,n){"use strict";!function o(e,t,n){function a(s,l){if(!t[s]){if(!e[s]){var i="function"==typeof require&&require;if(!l&&i)return i(s,!0);if(r)return r(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var c=t[s]={exports:{}};e[s][0].call(c.exports,function(t){var n=e[s][1][t];return a(n?n:t)},c,c.exports,o,e,t,n)}return t[s].exports}for(var r="function"==typeof require&&require,s=0;s=0;)n=n.replace(" "+t+" "," ");e.className=n.replace(/^\s+|\s+$/g,"")}},i=function(e){var n=t.createElement("div");return n.appendChild(t.createTextNode(e)),n.innerHTML},u=function(e){e.style.opacity="",e.style.display="block"},c=function(e){if(e&&!e.length)return u(e);for(var t=0;t0?setTimeout(o,t):e.style.display="none"});o()},h=function(n){if("function"==typeof MouseEvent){var o=new MouseEvent("click",{view:e,bubbles:!1,cancelable:!0});n.dispatchEvent(o)}else if(t.createEvent){var a=t.createEvent("MouseEvents");a.initEvent("click",!1,!1),n.dispatchEvent(a)}else t.createEventObject?n.fireEvent("onclick"):"function"==typeof n.onclick&&n.onclick()},g=function(t){"function"==typeof t.stopPropagation?(t.stopPropagation(),t.preventDefault()):e.event&&e.event.hasOwnProperty("cancelBubble")&&(e.event.cancelBubble=!0)};a.hasClass=r,a.addClass=s,a.removeClass=l,a.escapeHtml=i,a._show=u,a.show=c,a._hide=d,a.hide=f,a.isDescendant=p,a.getTopMargin=m,a.fadeIn=v,a.fadeOut=y,a.fireClick=h,a.stopEventPropagation=g},{}],5:[function(t,o,a){Object.defineProperty(a,"__esModule",{value:!0});var r=t("./handle-dom"),s=t("./handle-swal-dom"),l=function(t,o,a){var l=t||e.event,i=l.keyCode||l.which,u=a.querySelector("button.confirm"),c=a.querySelector("button.cancel"),d=a.querySelectorAll("button[tabindex]");if(-1!==[9,13,32,27].indexOf(i)){for(var f=l.target||l.srcElement,p=-1,m=0;m"),i.innerHTML=e.html?e.text:s.escapeHtml(e.text||"").split("\n").join("
"),e.text&&s.show(i),e.customClass)s.addClass(t,e.customClass),t.setAttribute("data-custom-class",e.customClass);else{var d=t.getAttribute("data-custom-class");s.removeClass(t,d),t.setAttribute("data-custom-class","")}if(s.hide(t.querySelectorAll(".sa-icon")),e.type&&!a.isIE8()){var f=function(){for(var o=!1,a=0;ao;o++)n=parseInt(e.substr(2*o,2),16),n=Math.round(Math.min(Math.max(0,n+n*t),255)).toString(16),a+=("00"+n).substr(n.length);return a};o.extend=a,o.hexToRgb=r,o.isIE8=s,o.logStr=l,o.colorLuminance=i},{}]},{},[1]),"function"==typeof define&&define.amd?define(function(){return sweetAlert}):"undefined"!=typeof module&&module.exports&&(module.exports=sweetAlert)}(window,document); \ No newline at end of file diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index 06f1bf5d..64ce16bc 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -12,7 +12,7 @@ {% block page_classes %} {{ block.super}} proposal proposal-detail {% endblock page_classes %} {% block endhead %} - {% endblock %} @@ -128,7 +128,7 @@

Content URLs:

{% endif %} From 551680603c171c0caaf7fd839872ad6e1dc7c186 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Wed, 8 Jul 2015 18:04:08 +0530 Subject: [PATCH 150/666] Only reviewers & superuser can access send mail button --- junction/proposals/views.py | 3 ++- junction/templates/proposals/detail/base.html | 12 +++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 49dbdd48..3d6e6974 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -334,7 +334,8 @@ def proposal_upload_content(request, conference_slug, slug): conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=slug, conference=conference) - if not _is_proposal_section_reviewer(request.user, conference, proposal): + if not (_is_proposal_section_reviewer(request.user, conference, proposal) or + request.user.is_superuser): return HttpResponseForbidden() host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META['HTTP_HOST']) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index 64ce16bc..eb5e840a 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -127,11 +127,13 @@

Content URLs:

{% endif %} - + {% if is_reviewer or user.is_authenticated and user.is_superuser %} + + {% endif %} {% if proposal.speaker_info %}
From e26e743c98e844dd34643144a7d090dca21d0581 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Thu, 9 Jul 2015 01:36:41 +0530 Subject: [PATCH 151/666] Fix proposal sections & type swapping --- junction/proposals/views.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 3d6e6974..4a0f28bd 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -108,8 +108,8 @@ def list_proposals(request, conference_slug): public_proposals_list = proposals_qs.exclude(review_status=PROPOSAL_REVIEW_STATUS_SELECTED).filter( status=PROPOSAL_STATUS_PUBLIC).order_by('-created_at') - proposal_sections = conference.proposal_types.all() - proposal_types = conference.proposal_sections.all() + proposal_sections = conference.proposal_sections.all() + proposal_types = conference.proposal_types.all() return render(request, 'proposals/list.html', {'public_proposals_list': public_proposals_list, @@ -271,8 +271,8 @@ def proposals_to_review(request, conference_slug): section_proposals = [p for p in proposals_qs if p.proposal_section == section] proposals_to_review.append(s_items(section, section_proposals)) - proposal_sections = conference.proposal_types.all() - proposal_types = conference.proposal_sections.all() + proposal_sections = conference.proposal_sections.all() + proposal_types = conference.proposal_types.all() form = ProposalsToReviewForm(conference=conference) ctx = { From eb228e9b7bd1500ba36cf22e8919b603156b637b Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Thu, 9 Jul 2015 02:18:51 +0530 Subject: [PATCH 152/666] add post compile for heroku do migration after compilation --- bin/post_compile | 4 ++++ 1 file changed, 4 insertions(+) create mode 100755 bin/post_compile diff --git a/bin/post_compile b/bin/post_compile new file mode 100755 index 00000000..5fd426cf --- /dev/null +++ b/bin/post_compile @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +# Run Django migrations. +./manage.py migrate From 875c972ac7341488f4857ff2ccd8ba87c3686088 Mon Sep 17 00:00:00 2001 From: dhilipsiva Date: Fri, 10 Jul 2015 08:45:30 +0530 Subject: [PATCH 153/666] Time based proposal acceptance --- junction/proposals/forms.py | 4 ++- .../migrations/0012_auto_20150709_0842.py | 27 +++++++++++++++++++ junction/proposals/models.py | 4 +++ junction/proposals/views.py | 3 ++- 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 junction/proposals/migrations/0012_auto_20150709_0842.py diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index c18abf46..d7f7ed9a 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -4,6 +4,7 @@ # Third Party Stuff from django import forms from django.utils.safestring import mark_safe +from django.utils.timezone import now from pagedown.widgets import PagedownWidget # Junction Stuff @@ -22,7 +23,8 @@ def _get_proposal_section_choices(conference): return [(str(cps.id), cps.name) - for cps in ProposalSection.objects.filter(conferences=conference)] + for cps in ProposalSection.objects.filter( + conferences=conference, end_date__gt=now())] def _get_proposal_type_choices(conference): diff --git a/junction/proposals/migrations/0012_auto_20150709_0842.py b/junction/proposals/migrations/0012_auto_20150709_0842.py new file mode 100644 index 00000000..59c7f642 --- /dev/null +++ b/junction/proposals/migrations/0012_auto_20150709_0842.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import datetime + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0011_auto_20150530_0224'), + ] + + operations = [ + migrations.AddField( + model_name='proposalsection', + name='end_date', + field=models.DateField(default=datetime.datetime.now, verbose_name='End Date'), + preserve_default=True, + ), + migrations.AddField( + model_name='proposalsection', + name='start_date', + field=models.DateField(default=datetime.datetime.now, verbose_name='Start Date'), + preserve_default=True, + ), + ] diff --git a/junction/proposals/models.py b/junction/proposals/models.py index cdfe5114..a48d5030 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals +from datetime import datetime + # Third Party Stuff from django.contrib.auth.models import User from django.core.urlresolvers import reverse @@ -27,6 +29,8 @@ class ProposalSection(AuditModel): description = models.TextField(default="") active = models.BooleanField(default=True, verbose_name="Is Active?") conferences = models.ManyToManyField(to=Conference, related_name='proposal_sections') + start_date = models.DateField(default=datetime.now, verbose_name="Start Date") + end_date = models.DateField(default=datetime.now, verbose_name="End Date") def __str__(self): return self.name diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 2c28b56d..3570cb67 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -6,6 +6,7 @@ # Third Party Stuff from django.conf import settings +from django.utils.timezone import now from django.contrib.auth.decorators import login_required from django.core.urlresolvers import reverse from django.http.response import HttpResponse, HttpResponseForbidden, HttpResponseRedirect @@ -123,7 +124,7 @@ def list_proposals(request, conference_slug): def create_proposal(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) if request.method == 'GET': - if conference.status != 1: + if conference.status != 1 and conference.proposal_sections.filter(end_date__gt=now()).count() == 0: return render(request, 'proposals/closed.html', {'conference': conference}) form = ProposalForm(conference) From 6f8578a51358fba09123408c39f63e954fb2a05f Mon Sep 17 00:00:00 2001 From: dhilipsiva Date: Sat, 11 Jul 2015 07:21:17 +0530 Subject: [PATCH 154/666] Remove checks for conference status. --- junction/proposals/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 3570cb67..26ae2a5f 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -124,7 +124,7 @@ def list_proposals(request, conference_slug): def create_proposal(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) if request.method == 'GET': - if conference.status != 1 and conference.proposal_sections.filter(end_date__gt=now()).count() == 0: + if conference.proposal_sections.filter(end_date__gt=now()).count() == 0: return render(request, 'proposals/closed.html', {'conference': conference}) form = ProposalForm(conference) From 1e820eca7d35ed5f27ba01e899d1814448bf2b19 Mon Sep 17 00:00:00 2001 From: dhilipsiva Date: Sat, 11 Jul 2015 07:26:58 +0530 Subject: [PATCH 155/666] Adding 'start_date' and 'end_date' to admin --- junction/proposals/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/proposals/admin.py b/junction/proposals/admin.py index 2beba8b9..352a82de 100644 --- a/junction/proposals/admin.py +++ b/junction/proposals/admin.py @@ -22,7 +22,7 @@ class ProposalSectionAdmin(AuditAdmin): - list_display = ('name', 'active') + AuditAdmin.list_display + list_display = ('name', 'active', 'start_date', 'end_date') + AuditAdmin.list_display class ProposalSectionReviewerAdmin(AuditAdmin): From 2aef24782ab57d2d8f0dc725bdb45bfb735f9eeb Mon Sep 17 00:00:00 2001 From: dhilipsiva Date: Sat, 11 Jul 2015 12:48:38 +0530 Subject: [PATCH 156/666] Refctor conference status as Enum --- junction/base/constants.py | 40 ++++++++++++++----- .../management/commands/sample_data.py | 2 +- junction/conferences/models.py | 4 +- junction/proposals/views.py | 5 ++- junction/templates/proposals/list.html | 2 +- tests/factories.py | 4 +- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/junction/base/constants.py b/junction/base/constants.py index cf6c4f32..3f3ea607 100644 --- a/junction/base/constants.py +++ b/junction/base/constants.py @@ -1,17 +1,35 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals -# Conference Application Choice Fields -CONFERENCE_STATUS_ACCEPTING_CFP = "Accepting Proposals" -CONFERENCE_STATUS_CLOSED_CFP = "Proposal submission closed" -CONFERENCE_STATUS_ACCEPTING_VOTES = "Accepting Votes" -CONFERENCE_STATUS_SCHEDULE_PUBLISHED = "Schedule Published" - -CONFERENCE_STATUS_LIST = ((1, CONFERENCE_STATUS_ACCEPTING_CFP), - (2, CONFERENCE_STATUS_CLOSED_CFP), - (3, CONFERENCE_STATUS_ACCEPTING_VOTES), - (4, CONFERENCE_STATUS_SCHEDULE_PUBLISHED), - ) +import inspect + + +def _user_attributes(cls): + defaults = dir(type(str('defaults'), (object,), {})) # gives all inbuilt attrs + return [ + item[0] for item in inspect.getmembers(cls) if item[0] not in defaults] + + +def choices(cls): + """ + Decorator to set `CHOICES` and other attributes + """ + _choices = [] + for attr in _user_attributes(cls): + val = getattr(cls, attr) + setattr(cls, attr[1:], val[0]) + _choices.append((val[0], val[1])) + setattr(cls, 'CHOICES', tuple(_choices)) + return cls + + +@choices +class ConferenceStatus: + _ACCEPTING_CFP = [1, "Accepting Proposals"] + _CLOSED_CFP = [2, "Proposal submission closed"] + _ACCEPTING_VOTES = [3, "Accepting Votes"] + _SCHEDULE_PUBLISHED = [4, "Schedule Published"] + # Proposal Application Choice Fields PROPOSAL_STATUS_DRAFT = 1 diff --git a/junction/conferences/management/commands/sample_data.py b/junction/conferences/management/commands/sample_data.py index 56ddd2c8..9a4e0c12 100644 --- a/junction/conferences/management/commands/sample_data.py +++ b/junction/conferences/management/commands/sample_data.py @@ -168,7 +168,7 @@ def create_conference(self, counter, start_date=None, end_date=None): conference = Conference.objects.create( name='%s Conference' % self.sd.words(1, 2).title(), description=self.sd.paragraph(), - status=self.sd.choices_key(constants.CONFERENCE_STATUS_LIST), + status=self.sd.choices_key(constants.ConferenceStatus.CHOICES), start_date=start_date, end_date=end_date, created_by=self.sd.choice(self.users), diff --git a/junction/conferences/models.py b/junction/conferences/models.py index a04b469f..98d467a9 100644 --- a/junction/conferences/models.py +++ b/junction/conferences/models.py @@ -13,7 +13,7 @@ from uuid_upload_path import upload_to # Junction Stuff -from junction.base.constants import CONFERENCE_STATUS_LIST +from junction.base.constants import ConferenceStatus from junction.base.models import AuditModel @@ -28,7 +28,7 @@ class Conference(AuditModel): end_date = models.DateField(verbose_name="End Date") logo = models.ImageField(blank=True, null=True, upload_to=upload_to) status = models.PositiveSmallIntegerField( - choices=CONFERENCE_STATUS_LIST, verbose_name="Current Status") + choices=ConferenceStatus.CHOICES, verbose_name="Current Status") deleted = models.BooleanField(default=False, verbose_name="Is Deleted?") class Meta: diff --git a/junction/proposals/views.py b/junction/proposals/views.py index d38930d4..8482b669 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -14,7 +14,7 @@ from django.views.decorators.http import require_http_methods # Junction Stuff -from junction.base.constants import PROPOSAL_REVIEW_STATUS_SELECTED, PROPOSAL_STATUS_PUBLIC +from junction.base.constants import PROPOSAL_REVIEW_STATUS_SELECTED, PROPOSAL_STATUS_PUBLIC, ConferenceStatus from junction.conferences.models import Conference, ConferenceProposalReviewer from .forms import ( @@ -120,7 +120,8 @@ def list_proposals(request, conference_slug): 'proposal_types': proposal_types, 'is_filtered': is_filtered, 'is_reviewer': is_reviewer, - 'conference': conference}) + 'conference': conference, + 'ConferenceStatus': ConferenceStatus}) @login_required diff --git a/junction/templates/proposals/list.html b/junction/templates/proposals/list.html index 48352f6b..b32c0766 100644 --- a/junction/templates/proposals/list.html +++ b/junction/templates/proposals/list.html @@ -86,7 +86,7 @@

Proposal Types

{% if is_filtered %} View all proposals {% endif %} - {% if conference.status == 1 %} + {% if conference.status == ConferenceStatus.ACCEPTING_CFP %} New Proposal diff --git a/tests/factories.py b/tests/factories.py index a0efae04..48314794 100644 --- a/tests/factories.py +++ b/tests/factories.py @@ -8,7 +8,7 @@ from factory import fuzzy # Junction Stuff -from junction.base.constants import CONFERENCE_STATUS_LIST +from junction.base.constants import ConferenceStatus class Factory(factory.DjangoModelFactory): @@ -49,7 +49,7 @@ class Meta: start_date = fuzzy.FuzzyDate(datetime.date.today(), datetime.date(2017, 1, 1)).fuzz() end_date = start_date + datetime.timedelta(3) # logo - status = factory.Iterator(dict(CONFERENCE_STATUS_LIST).keys()) + status = factory.Iterator(dict(ConferenceStatus.CHOICES).keys()) # deleted From 7518fb128cfd20ef50dcde39de327169a7ee3fcb Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sun, 12 Jul 2015 12:04:19 +0530 Subject: [PATCH 157/666] security(dep): upgrade django to 1.7.9 (security release) see: https://www.djangoproject.com/weblog/2015/jul/08/security-releases/ --- requirements.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index d14827b8..e8cf2c1f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==1.7.8 +Django==1.7.9 celery==3.1.18 # Persistent Store @@ -44,8 +44,6 @@ mdx-linkify==0.6 Markdown==2.6.2 markdown2==2.3.0 - # Server # ------------------------------------------------ uwsgi==2.0.* - From 793795bbf7f059ecdcc66d8894d0601cab8e3dad Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sun, 12 Jul 2015 12:08:20 +0530 Subject: [PATCH 158/666] Update requirements to lastest, keeping django < 1.8 --- requirements-dev.txt | 8 ++++---- requirements.txt | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 8c199363..b82830ff 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,16 +2,16 @@ # Testing # ------------------------------------------------- -mock==1.0.1 +mock==1.1.2 factory_boy==2.5.2 flake8==2.4.1 pytest-django==2.8.0 -pytest-flakes==0.2 -pytest-pythonpath==0.6 +pytest-flakes==1.0.0 +pytest-pythonpath==0.7 git+git://github.com/mverteuil/pytest-ipdb.git coverage==3.7.1 # Documentation # -------------------------------------------------- -mkdocs==0.12.2 +mkdocs==0.14.0 diff --git a/requirements.txt b/requirements.txt index e8cf2c1f..1f6afd34 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ celery==3.1.18 # Persistent Store # ------------------------------------------------- -psycopg2==2.6 +psycopg2==2.6.1 redis==2.10.3 dj-database-url==0.3.* @@ -11,20 +11,20 @@ dj-database-url==0.3.* # ------------------------------------------------- django-extensions==1.5.5 Werkzeug==0.10.4 -ipython==3.1.0 +ipython==3.2.0 pyreadline==2.0 six==1.9.0 -django-sampledatahelper==0.2.2 +django-sampledatahelper==0.3 unicode-slugify==0.1.3 # Django Model Helpers # ------------------------------------------------- django-uuid-upload-path==1.0.0 -Pillow==2.8.1 +Pillow==2.9.0 # Auth # ------------------------------------------------- -django-allauth==0.19.1 +django-allauth==0.21.0 oauthlib==0.7.2 python-openid==2.2.5 requests==2.7.0 @@ -32,9 +32,9 @@ requests-oauthlib==0.5.0 # Frontend Helpers # ------------------------------------------------- -django-bootstrap3==5.4.0 +django-bootstrap3==6.1.0 django-bootstrap-breadcrumbs==0.7.1 -django-flat-theme==0.9.3 # django admin theme +django-flat-theme==0.9.5 # Markdown Editor # ------------------------------------------------- From 6fbff3a26a743f3cc81591be56a191ddbcd5756a Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Mon, 13 Jul 2015 23:39:57 +0530 Subject: [PATCH 159/666] add support for scheduling * a models scheduleItem, venue, room * api that gives out, conference, schedule, venue, room --- junction/conferences/admin.py | 5 +- .../management/commands/sample_data.py | 28 +++++++++- .../migrations/0010_auto_20150713_2331.py | 56 +++++++++++++++++++ junction/conferences/models.py | 23 ++++++++ junction/conferences/serializers.py | 22 ++++++++ junction/conferences/views.py | 22 ++++++++ junction/proposals/serializers.py | 26 +++++++++ junction/proposals/views.py | 9 +++ junction/schedule/admin.py | 4 +- junction/schedule/migrations/0001_initial.py | 38 +++++++++++++ junction/schedule/models.py | 25 ++++++++- junction/schedule/serializers.py | 10 ++++ junction/schedule/views.py | 12 +++- junction/urls.py | 15 +++++ requirements.txt | 2 + settings/common.py | 3 + 16 files changed, 294 insertions(+), 6 deletions(-) create mode 100644 junction/conferences/migrations/0010_auto_20150713_2331.py create mode 100644 junction/conferences/serializers.py create mode 100644 junction/proposals/serializers.py create mode 100644 junction/schedule/migrations/0001_initial.py create mode 100644 junction/schedule/serializers.py diff --git a/junction/conferences/admin.py b/junction/conferences/admin.py index a02bfb32..106bc759 100644 --- a/junction/conferences/admin.py +++ b/junction/conferences/admin.py @@ -25,4 +25,7 @@ class ConferenceProposallReviewerAdmin(AuditAdmin): admin.site.register(models.Conference, ConferenceAdmin) admin.site.register(models.ConferenceModerator, ConferenceModeratorAdmin) -admin.site.register(models.ConferenceProposalReviewer, ConferenceProposallReviewerAdmin) +admin.site.register(models.ConferenceProposalReviewer, + ConferenceProposallReviewerAdmin) +admin.site.register(models.ConferenceVenue) +admin.site.register(models.Room) diff --git a/junction/conferences/management/commands/sample_data.py b/junction/conferences/management/commands/sample_data.py index 56ddd2c8..7d38dfa3 100644 --- a/junction/conferences/management/commands/sample_data.py +++ b/junction/conferences/management/commands/sample_data.py @@ -25,13 +25,14 @@ ProposalType, ProposalSectionReviewerVoteValue ) +from junction.schedule.models import ScheduleItem NUM_USERS = getattr(settings, "NUM_USERS", 10) NUM_CONFERENCES = getattr(settings, "NUM_CONFERENCES", 4) NUM_EMPTY_CONFERENCES = getattr(settings, "NUM_EMPTY_CONFERENCES", 2) NUM_PROPOSAL_SECTIONS = getattr(settings, "NUM_PROPOSAL_SECTIONS", 5) NUM_PROPOSAL_TYPES = getattr(settings, "NUM_PROPOSAL_TYPES", 8) -NUM_PUBLIC_PROPOSALS = getattr(settings, "NUM_PUBLIC_PROPOSALS", 7) +NUM_PUBLIC_PROPOSALS = getattr(settings, "NUM_PUBLIC_PROPOSALS", 20) NUM_DRAFT_PROPOSALS = getattr(settings, "NUM_DRAFT_PROPOSALS", 7) NUM_CANCELLED_PROPOSALS = getattr(settings, "NUM_CANCELLED_PROPOSALS", 7) NUM_PUBLIC_COMMENTS = getattr(settings, "NUM_PUBLIC_COMMENTS", 10) @@ -101,6 +102,14 @@ def handle(self, *args, **options): for x in range(NUM_CANCELLED_PROPOSALS): self.proposals.append(self.create_proposal(proposal_type="Cancelled")) + print(' Create sample Schedule') + for proposal in self.proposals: + if not proposal.get_status_display() == 'Public': + continue + self.create_scheduled_item(proposal=proposal) + self.create_scheduled_item(proposal='Break', + conference=self.conferences[0]) + # create comments print(' Creating sample proposal comments') for x in range(NUM_PUBLIC_COMMENTS): @@ -150,6 +159,23 @@ def create_propsoal_reviewers(self, conference): reviewer=user, active=self.sd.boolean())) return proposal_reviewers + def create_scheduled_item(self, proposal, conference=None): + kwargs = {} + kwargs['conference'] = conference if conference \ + else proposal.conference + kwargs['event_date'] = kwargs['conference'].start_date + kwargs['start_time'] = datetime.datetime.time(datetime.datetime.now()) + kwargs['end_time'] = datetime.datetime.time( + datetime.datetime.now() + datetime.timedelta(minutes=45)) + if isinstance(proposal, basestring): + ScheduleItem.objects.create( + alt_name=proposal, + **kwargs) + else: + ScheduleItem.objects.create( + session=proposal, + **kwargs) + def create_conference(self, counter, start_date=None, end_date=None): if counter == 0: min_days_from_creation = 30 diff --git a/junction/conferences/migrations/0010_auto_20150713_2331.py b/junction/conferences/migrations/0010_auto_20150713_2331.py new file mode 100644 index 00000000..51242301 --- /dev/null +++ b/junction/conferences/migrations/0010_auto_20150713_2331.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('conferences', '0009_conferenceproposalreviewer_nick'), + ] + + operations = [ + migrations.CreateModel( + name='ConferenceVenue', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')), + ('name', models.CharField(max_length=100)), + ('address', models.TextField()), + ('latitude', models.DecimalField(max_digits=17, decimal_places=15)), + ('longitudes', models.DecimalField(max_digits=19, decimal_places=16)), + ('created_by', models.ForeignKey(related_name='created_conferencevenue_set', verbose_name='Created By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ('modified_by', models.ForeignKey(related_name='updated_conferencevenue_set', verbose_name='Modified By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ], + options={ + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='Room', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')), + ('name', models.CharField(max_length=100)), + ('created_by', models.ForeignKey(related_name='created_room_set', verbose_name='Created By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ('modified_by', models.ForeignKey(related_name='updated_room_set', verbose_name='Modified By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ('venue', models.ForeignKey(to='conferences.ConferenceVenue')), + ], + options={ + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.AddField( + model_name='conference', + name='venue', + field=models.ForeignKey(to='conferences.ConferenceVenue', null=True), + preserve_default=True, + ), + ] diff --git a/junction/conferences/models.py b/junction/conferences/models.py index a04b469f..3bfd1d56 100644 --- a/junction/conferences/models.py +++ b/junction/conferences/models.py @@ -29,6 +29,8 @@ class Conference(AuditModel): logo = models.ImageField(blank=True, null=True, upload_to=upload_to) status = models.PositiveSmallIntegerField( choices=CONFERENCE_STATUS_LIST, verbose_name="Current Status") + venue = models.ForeignKey('ConferenceVenue', null=True) + deleted = models.BooleanField(default=False, verbose_name="Is Deleted?") class Meta: @@ -87,3 +89,24 @@ class Meta: def __str__(self): return "{}[{}]".format(self.reviewer.get_full_name(), self.conference) + + +@python_2_unicode_compatible +class ConferenceVenue(AuditModel): + name = models.CharField(max_length=100) + + address = models.TextField() + + latitude = models.DecimalField(max_digits=17, decimal_places=15) + longitudes = models.DecimalField(max_digits=19, decimal_places=16) + + def __str__(self): + return self.name + + +class Room(AuditModel): + name = models.CharField(max_length=100) + venue = models.ForeignKey(ConferenceVenue) + + def __str__(self): + return "{}, {}".format(self.name, self.venue) diff --git a/junction/conferences/serializers.py b/junction/conferences/serializers.py new file mode 100644 index 00000000..850df9b9 --- /dev/null +++ b/junction/conferences/serializers.py @@ -0,0 +1,22 @@ +from rest_framework import serializers + +from .models import Conference, ConferenceVenue, Room + + +class ConferenceSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Conference + fields = ('name', 'slug', 'description', 'start_date', + 'end_date', 'status', 'venue') + + +class VenueSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = ConferenceVenue + fields = ('name', 'address') + + +class RoomSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Room + fields = ('name', 'venue') diff --git a/junction/conferences/views.py b/junction/conferences/views.py index c7ee7577..774a4691 100644 --- a/junction/conferences/views.py +++ b/junction/conferences/views.py @@ -1,2 +1,24 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals + +from rest_framework import viewsets, filters + +from .models import Conference, ConferenceVenue, Room +from .serializers import ConferenceSerializer, VenueSerializer, RoomSerializer + + +class ConferenceView(viewsets.ReadOnlyModelViewSet): + queryset = Conference.objects.all() + serializer_class = ConferenceSerializer + + +class VenueView(viewsets.ReadOnlyModelViewSet): + queryset = ConferenceVenue.objects.all() + serializer_class = VenueSerializer + + +class RoomView(viewsets.ReadOnlyModelViewSet): + queryset = Room.objects.all() + serializer_class = RoomSerializer + filter_backend = (filters.DjangoFilterBackend,) + filter_fields = ('venue',) diff --git a/junction/proposals/serializers.py b/junction/proposals/serializers.py new file mode 100644 index 00000000..9f6de73e --- /dev/null +++ b/junction/proposals/serializers.py @@ -0,0 +1,26 @@ +from rest_framework import serializers + +from .models import Proposal + + +class ProposalSerializer(serializers.HyperlinkedModelSerializer): + section = serializers.SerializerMethodField() + type = serializers.SerializerMethodField() + author = serializers.SerializerMethodField() + + def get_section(self, proposal): + return proposal.proposal_section.name + + def get_type(self, proposal): + return proposal.proposal_type.name + + def get_author(self, proposal): + return "{} {}".format(proposal.author.first_name, + proposal.author.first_name) + + class Meta: + model = Proposal + fields = ('conference', 'title', 'section', 'type', 'author', + 'slug', 'description', 'target_audience', + 'prerequisites', 'content_urls', 'speaker_info', + 'speaker_links', 'status', 'review_status') diff --git a/junction/proposals/views.py b/junction/proposals/views.py index d38930d4..da03f9d1 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -13,6 +13,9 @@ from django.shortcuts import Http404, get_object_or_404, render from django.views.decorators.http import require_http_methods +from rest_framework import viewsets + + # Junction Stuff from junction.base.constants import PROPOSAL_REVIEW_STATUS_SELECTED, PROPOSAL_STATUS_PUBLIC from junction.conferences.models import Conference, ConferenceProposalReviewer @@ -33,6 +36,7 @@ ProposalSectionReviewerVote, ProposalSectionReviewerVoteValue ) +from .serializers import ProposalSerializer from .services import ( send_mail_for_new_comment, send_mail_for_new_proposal, @@ -522,3 +526,8 @@ def proposal_comment_down_vote(request, conference_slug, proposal_slug, proposal_comment_id): return proposal_comment_vote(request, conference_slug, proposal_slug, proposal_comment_id, False) + + +class ProposalView(viewsets.ReadOnlyModelViewSet): + queryset = Proposal.objects.all() + serializer_class = ProposalSerializer diff --git a/junction/schedule/admin.py b/junction/schedule/admin.py index 6af52da2..c26fa1bb 100644 --- a/junction/schedule/admin.py +++ b/junction/schedule/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin # noqa -# Register your models here. +from .models import ScheduleItem + +admin.site.register(ScheduleItem) diff --git a/junction/schedule/migrations/0001_initial.py b/junction/schedule/migrations/0001_initial.py new file mode 100644 index 00000000..ff4fbf60 --- /dev/null +++ b/junction/schedule/migrations/0001_initial.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0011_auto_20150530_0224'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('conferences', '0010_auto_20150713_2331'), + ] + + operations = [ + migrations.CreateModel( + name='ScheduleItem', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')), + ('event_date', models.DateField()), + ('start_time', models.TimeField()), + ('end_time', models.TimeField()), + ('alt_name', models.CharField(max_length=100, blank=True)), + ('conference', models.ForeignKey(to='conferences.Conference')), + ('created_by', models.ForeignKey(related_name='created_scheduleitem_set', verbose_name='Created By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ('modified_by', models.ForeignKey(related_name='updated_scheduleitem_set', verbose_name='Modified By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ('room', models.ForeignKey(to='conferences.Room', null=True)), + ('session', models.ForeignKey(to='proposals.Proposal', null=True)), + ], + options={ + 'abstract': False, + }, + bases=(models.Model,), + ), + ] diff --git a/junction/schedule/models.py b/junction/schedule/models.py index 9d57c559..5d217d00 100644 --- a/junction/schedule/models.py +++ b/junction/schedule/models.py @@ -1,3 +1,24 @@ -from django.db import models # noqa +from django.db import models -# Create your models here. +from junction.base.models import AuditModel +from junction.proposals.models import Proposal +from junction.conferences.models import Conference, Room + + +class ScheduleItem(AuditModel): + room = models.ForeignKey(Room, null=True) + # if a session is not present, venue can be null Ex: break + event_date = models.DateField() + start_time = models.TimeField() + end_time = models.TimeField() + alt_name = models.CharField(max_length=100, blank=True) + session = models.ForeignKey(Proposal, null=True) + + conference = models.ForeignKey(Conference) + + def __unicode__(self): + return self.name + + @property + def name(self): + return self.alt_name or self.session.title diff --git a/junction/schedule/serializers.py b/junction/schedule/serializers.py new file mode 100644 index 00000000..0a4a7854 --- /dev/null +++ b/junction/schedule/serializers.py @@ -0,0 +1,10 @@ +from rest_framework import serializers + +from .models import ScheduleItem + + +class ScheduleSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = ScheduleItem + fields = ('room', 'event_date', 'start_time', 'end_time', + 'name', 'session', 'conference') diff --git a/junction/schedule/views.py b/junction/schedule/views.py index 9c76e69e..83d63750 100644 --- a/junction/schedule/views.py +++ b/junction/schedule/views.py @@ -3,7 +3,17 @@ from django.http import HttpResponse from django.template.loader import render_to_string -# Create your views here. +from rest_framework import viewsets, filters + +from .models import ScheduleItem +from .serializers import ScheduleSerializer + + +class ScheduleView(viewsets.ReadOnlyModelViewSet): + queryset = ScheduleItem.objects.all() + serializer_class = ScheduleSerializer + filter_backend = (filters.DjangoFilterBackend,) + filter_fields = ('room', 'conference', 'event_date') def dummy_schedule(request, conference_slug): diff --git a/junction/urls.py b/junction/urls.py index c142b56f..6fad5959 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -8,6 +8,19 @@ from django.contrib import admin from django.views.generic.base import RedirectView, TemplateView +from rest_framework import routers +from junction.schedule import views as schedule_views +from junction.proposals import views as proposal_views +from junction.conferences import views as conference_views + +router = routers.DefaultRouter() + +router.register('schedules', schedule_views.ScheduleView) +router.register('proposals', proposal_views.ProposalView) +router.register('venues', conference_views.VenueView) +router.register('rooms', conference_views.RoomView) +router.register('conferences', conference_views.ConferenceView) + ''' Root url routering file. @@ -33,6 +46,8 @@ url(r'^(?P[\w-]+)/dashboard/', 'junction.proposals.dashboard.proposals_dashboard', name='proposal-dashboard'), + url(r'^api/v1/', include(router.urls)), + # Schedule related url(r'^(?P[\w-]+)/schedule/', include('junction.schedule.urls')), diff --git a/requirements.txt b/requirements.txt index 1f6afd34..108e5d10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,7 @@ Django==1.7.9 celery==3.1.18 +djangorestframework==3.1.3 +django-filter==0.10.0 # Persistent Store # ------------------------------------------------- diff --git a/settings/common.py b/settings/common.py index 5768c23d..d44544ac 100644 --- a/settings/common.py +++ b/settings/common.py @@ -70,12 +70,15 @@ 'pagedown', 'django_markdown', 'django_bootstrap_breadcrumbs', + + 'rest_framework', ) OUR_APPS = ( 'junction.base', 'junction.conferences', 'junction.proposals', + 'junction.schedule', 'junction.pages', ) From b34fc668f12fc9729043d7f1d44e0d6362f46ff7 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Tue, 14 Jul 2015 01:37:58 +0530 Subject: [PATCH 160/666] Move ProposalSection date check as method - Add model method `is_accepting_proposals` - `_get_proposal_section_choices` can populate choices based on action - Display `New Proposal` button based on ProposalSection date --- junction/conferences/models.py | 6 ++++++ junction/proposals/forms.py | 17 +++++++++++------ junction/proposals/views.py | 16 ++++++++-------- junction/templates/proposals/list.html | 2 +- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/junction/conferences/models.py b/junction/conferences/models.py index a04b469f..2bd7ac6c 100644 --- a/junction/conferences/models.py +++ b/junction/conferences/models.py @@ -7,6 +7,7 @@ from django.core.urlresolvers import reverse from django.db import models from django.utils.encoding import python_2_unicode_compatible +from django.utils.timezone import now from django.utils.translation import ugettext as _ from django_extensions.db.fields import AutoSlugField from slugify import slugify @@ -53,6 +54,11 @@ def save(self, *args, **kwargs): self.slug = slugify(self.name) return super(Conference, self).save(*args, **kwargs) + def is_accepting_proposals(self): + """Check if any one of the proposal section is accepting proposal. + """ + return self.proposal_sections.filter(end_date__gt=now()).exists() + @python_2_unicode_compatible class ConferenceModerator(AuditModel): diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index d7f7ed9a..222a1e9c 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -21,10 +21,15 @@ ) -def _get_proposal_section_choices(conference): - return [(str(cps.id), cps.name) - for cps in ProposalSection.objects.filter( - conferences=conference, end_date__gt=now())] +def _get_proposal_section_choices(conference, action="edit"): + if action == "create": + return [(str(cps.id), cps.name) + for cps in ProposalSection.objects.filter( + conferences=conference, end_date__gt=now())] + else: + return [(str(cps.id), cps.name) + for cps in ProposalSection.objects.filter( + conferences=conference)] def _get_proposal_type_choices(conference): @@ -86,10 +91,10 @@ class ProposalForm(forms.Form): widget=PagedownWidget(show_preview=True), required=False, help_text="Links to your previous work like Blog, Open Source Contributions etc ...") - def __init__(self, conference, *args, **kwargs): + def __init__(self, conference, action="edit", *args, **kwargs): super(ProposalForm, self).__init__(*args, **kwargs) self.fields['proposal_section'].choices = _get_proposal_section_choices( - conference) + conference, action=action) self.fields['proposal_type'].choices = _get_proposal_type_choices( conference) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index d38930d4..907bfacc 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -6,7 +6,6 @@ # Third Party Stuff from django.conf import settings -from django.utils.timezone import now from django.contrib.auth.decorators import login_required from django.core.urlresolvers import reverse from django.http.response import HttpResponse, HttpResponseForbidden, HttpResponseRedirect @@ -128,16 +127,16 @@ def list_proposals(request, conference_slug): def create_proposal(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) if request.method == 'GET': - if conference.proposal_sections.filter(end_date__gt=now()).count() == 0: + if not conference.is_accepting_proposals(): return render(request, 'proposals/closed.html', {'conference': conference}) - form = ProposalForm(conference) + form = ProposalForm(conference, action="create") return render(request, 'proposals/create.html', {'form': form, 'conference': conference, }) # POST Workflow - form = ProposalForm(conference, request.POST) + form = ProposalForm(conference, data=request.POST, action="create") if not form.is_valid(): return render(request, 'proposals/create.html', @@ -229,11 +228,12 @@ def update_proposal(request, conference_slug, slug): 'proposal': proposal}) # POST Workflow - form = ProposalForm(conference, request.POST) + form = ProposalForm(conference, data=request.POST) if not form.is_valid(): - return render(request, 'proposals/update.html', {'form': form, - 'proposal': proposal, - 'errors': form.errors}) + return render(request, 'proposals/update.html', + {'form': form, + 'proposal': proposal, + 'errors': form.errors}) # Valid Form proposal.title = form.cleaned_data['title'] diff --git a/junction/templates/proposals/list.html b/junction/templates/proposals/list.html index 48352f6b..b66a61f1 100644 --- a/junction/templates/proposals/list.html +++ b/junction/templates/proposals/list.html @@ -86,7 +86,7 @@

Proposal Types

{% if is_filtered %} View all proposals {% endif %} - {% if conference.status == 1 %} + {% if conference.is_accepting_proposals %} New Proposal From 12065a64c6586a6a0d2d4bc52eebab629653053a Mon Sep 17 00:00:00 2001 From: htrap Date: Tue, 14 Jul 2015 03:59:02 +0530 Subject: [PATCH 161/666] Add button for the content_urls of the proposal --- junction/proposals/templatetags/proposal_filters.py | 7 +++++++ .../proposals/partials/proposal-list--review-items.html | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index dfb685d8..e40d3535 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -11,3 +11,10 @@ @register.filter(name='reviewer_comments') def reviewer_comments(proposal, user): return proposal.get_reviewer_comments_count(user) > 0 + +@register.filter(name='has_content_urls') +def has_content_urls(proposal): + if proposal.content_urls: + return True + else: + return False diff --git a/junction/templates/proposals/partials/proposal-list--review-items.html b/junction/templates/proposals/partials/proposal-list--review-items.html index 3a590439..5945e810 100644 --- a/junction/templates/proposals/partials/proposal-list--review-items.html +++ b/junction/templates/proposals/partials/proposal-list--review-items.html @@ -51,6 +51,14 @@

{% endif %} + {% if proposal|has_content_urls %} + + + + {% endif %}

From 50796b14ac2b3c08ec31de845b968404221a63a3 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Wed, 15 Jul 2015 20:47:05 +0530 Subject: [PATCH 162/666] fix the issue with filters just needs to add the settings --- settings/common.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/settings/common.py b/settings/common.py index d44544ac..9948b8bc 100644 --- a/settings/common.py +++ b/settings/common.py @@ -220,3 +220,7 @@ # Add connection life time # Make sure DB request held on for minimim 5 minutes CONN_MAX_AGE = 300 + +REST_FRAMEWORK = { + 'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',) +} From 1f9c9f798641721847553964e5fcc0709f151df3 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Wed, 15 Jul 2015 20:47:38 +0530 Subject: [PATCH 163/666] conference status should be string --- junction/conferences/serializers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/junction/conferences/serializers.py b/junction/conferences/serializers.py index 850df9b9..4b645fbb 100644 --- a/junction/conferences/serializers.py +++ b/junction/conferences/serializers.py @@ -4,6 +4,8 @@ class ConferenceSerializer(serializers.HyperlinkedModelSerializer): + status = serializers.CharField(source='get_status_display') + class Meta: model = Conference fields = ('name', 'slug', 'description', 'start_date', From 7776cf992e1cf241b4414ee0013ff04609659332 Mon Sep 17 00:00:00 2001 From: htrap Date: Thu, 16 Jul 2015 03:34:20 +0530 Subject: [PATCH 164/666] fixes to show link icon in presence of content urls --- .../partials/proposal-list--review-items.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/junction/templates/proposals/partials/proposal-list--review-items.html b/junction/templates/proposals/partials/proposal-list--review-items.html index 5945e810..192173d4 100644 --- a/junction/templates/proposals/partials/proposal-list--review-items.html +++ b/junction/templates/proposals/partials/proposal-list--review-items.html @@ -47,18 +47,18 @@

{{ proposal.proposal_type }} {{ proposal.proposal_section }} {% if proposal|reviewer_comments:request.user %} - + {% endif %} - {% if proposal|has_content_urls %} - - - {% endif %} + + {% endif %}

From 7009e3e36fa5a110241f8535daae4c00e1f3388d Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Thu, 16 Jul 2015 11:39:27 +0530 Subject: [PATCH 165/666] embed proposal in schedule as session --- junction/conferences/serializers.py | 4 ++-- junction/proposals/serializers.py | 2 +- junction/proposals/views.py | 5 ----- junction/schedule/serializers.py | 4 ++++ junction/urls.py | 7 +++---- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/junction/conferences/serializers.py b/junction/conferences/serializers.py index 4b645fbb..301e5260 100644 --- a/junction/conferences/serializers.py +++ b/junction/conferences/serializers.py @@ -8,8 +8,8 @@ class ConferenceSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Conference - fields = ('name', 'slug', 'description', 'start_date', - 'end_date', 'status', 'venue') + fields = ('id', 'name', 'slug', 'description', + 'start_date', 'end_date', 'status', 'venue') class VenueSerializer(serializers.HyperlinkedModelSerializer): diff --git a/junction/proposals/serializers.py b/junction/proposals/serializers.py index 9f6de73e..58a279fc 100644 --- a/junction/proposals/serializers.py +++ b/junction/proposals/serializers.py @@ -20,7 +20,7 @@ def get_author(self, proposal): class Meta: model = Proposal - fields = ('conference', 'title', 'section', 'type', 'author', + fields = ('title', 'section', 'type', 'author', 'slug', 'description', 'target_audience', 'prerequisites', 'content_urls', 'speaker_info', 'speaker_links', 'status', 'review_status') diff --git a/junction/proposals/views.py b/junction/proposals/views.py index da03f9d1..4a553aa9 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -526,8 +526,3 @@ def proposal_comment_down_vote(request, conference_slug, proposal_slug, proposal_comment_id): return proposal_comment_vote(request, conference_slug, proposal_slug, proposal_comment_id, False) - - -class ProposalView(viewsets.ReadOnlyModelViewSet): - queryset = Proposal.objects.all() - serializer_class = ProposalSerializer diff --git a/junction/schedule/serializers.py b/junction/schedule/serializers.py index 0a4a7854..2a0233a0 100644 --- a/junction/schedule/serializers.py +++ b/junction/schedule/serializers.py @@ -1,9 +1,13 @@ from rest_framework import serializers +from junction.proposals.serializers import ProposalSerializer + from .models import ScheduleItem class ScheduleSerializer(serializers.HyperlinkedModelSerializer): + session = ProposalSerializer() + class Meta: model = ScheduleItem fields = ('room', 'event_date', 'start_time', 'end_time', diff --git a/junction/urls.py b/junction/urls.py index 6fad5959..ebb73b65 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -10,16 +10,15 @@ from rest_framework import routers from junction.schedule import views as schedule_views -from junction.proposals import views as proposal_views from junction.conferences import views as conference_views router = routers.DefaultRouter() -router.register('schedules', schedule_views.ScheduleView) -router.register('proposals', proposal_views.ProposalView) +router.register('conferences', conference_views.ConferenceView) router.register('venues', conference_views.VenueView) router.register('rooms', conference_views.RoomView) -router.register('conferences', conference_views.ConferenceView) + +router.register('schedules', schedule_views.ScheduleView) ''' Root url routering file. From 026263f3cd49c9a0e43e269bc53b7cc87b6258d5 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Thu, 16 Jul 2015 12:29:01 +0530 Subject: [PATCH 166/666] flake8 fixes --- junction/proposals/views.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 4a553aa9..6ff0044f 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -13,8 +13,6 @@ from django.shortcuts import Http404, get_object_or_404, render from django.views.decorators.http import require_http_methods -from rest_framework import viewsets - # Junction Stuff from junction.base.constants import PROPOSAL_REVIEW_STATUS_SELECTED, PROPOSAL_STATUS_PUBLIC @@ -36,7 +34,6 @@ ProposalSectionReviewerVote, ProposalSectionReviewerVoteValue ) -from .serializers import ProposalSerializer from .services import ( send_mail_for_new_comment, send_mail_for_new_proposal, From 881a0466769cf765c9aabaf82b5a24cecfc88721 Mon Sep 17 00:00:00 2001 From: htrap Date: Fri, 17 Jul 2015 05:29:34 +0530 Subject: [PATCH 167/666] Redirecting to the first content_url of the proposal on clicking the external link icon on the proposal review page --- junction/proposals/templatetags/proposal_filters.py | 6 ++++-- .../proposals/partials/proposal-list--review-items.html | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index e40d3535..201b12eb 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -13,8 +13,10 @@ def reviewer_comments(proposal, user): return proposal.get_reviewer_comments_count(user) > 0 @register.filter(name='has_content_urls') -def has_content_urls(proposal): +def get_content_urls(proposal): if proposal.content_urls: - return True + url = proposal.content_urls.split() + return url[0] + else: return False diff --git a/junction/templates/proposals/partials/proposal-list--review-items.html b/junction/templates/proposals/partials/proposal-list--review-items.html index 192173d4..4eb9cae4 100644 --- a/junction/templates/proposals/partials/proposal-list--review-items.html +++ b/junction/templates/proposals/partials/proposal-list--review-items.html @@ -52,10 +52,10 @@

{% endif %} {% if proposal|has_content_urls %} - + available" > {% endif %} From 030f0a8273d9be1f985d3fbecfb1b3837d4db293 Mon Sep 17 00:00:00 2001 From: htrap Date: Fri, 17 Jul 2015 05:42:30 +0530 Subject: [PATCH 168/666] fixing flake8 errors --- junction/proposals/dashboard.py | 16 +++------------- .../proposals/templatetags/proposal_filters.py | 2 +- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index c6111b9a..f509c1df 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -14,21 +14,18 @@ ) from junction.conferences.models import ( ConferenceProposalReviewer - ) +) @login_required @require_http_methods(['GET']) def proposals_dashboard(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) - if not request.user.is_superuser: return HttpResponseForbidden() - proposals_qs = Proposal.objects.filter( conference=conference, status=PROPOSAL_STATUS_PUBLIC) - by_type = {} by_section = {} by_reviewer = {} @@ -41,7 +38,6 @@ def proposals_dashboard(request, conference_slug): # dict structure {'id':[total, review, unreview, name]} by_type.setdefault(pro_type.id, [0, 0, 0, pro_type.name]) by_type[pro_type.id][0] = by_type[pro_type.id][0] + 1 - by_section.setdefault(section.id, [0, 0, 0, section.name]) by_section[section.id][0] = by_section[section.id][0] + 1 private_comment_count = \ @@ -57,13 +53,11 @@ def proposals_dashboard(request, conference_slug): unreviewed_count = unreviewed_count + 1 by_type[pro_type.id][2] = by_type[pro_type.id][2] + 1 by_section[section.id][2] = by_section[section.id][2] + 1 - sections = \ ProposalSectionReviewer.objects.filter( conference_reviewer__reviewer=request.user)\ .distinct('proposal_section__id') # Hande case if reviewer is added to section twice' - for section in sections: proposal_qs = proposals_qs.filter(proposal_section=section.proposal_section) # due to space and number issue for key used this @@ -78,13 +72,11 @@ def proposals_dashboard(request, conference_slug): by_reviewer[key_id][1] = by_reviewer[key_id][1] + 1 else: by_reviewer[key_id][2] = by_reviewer[key_id][2] + 1 - audience_dict = { 1: 'Beginner', 2: 'Intermediate', 3: 'Advanced' } - for proposal in proposals_qs: audience = audience_dict[proposal.target_audience] by_audience.setdefault(audience, [0, 0, 0, audience]) @@ -99,9 +91,8 @@ def proposals_dashboard(request, conference_slug): else: by_audience[audience][2] = by_audience[audience][2] + 1 by_audience[audience][0] = by_audience[audience][0] + 1 - ctx = { - 'conference': conference, + 'conference': conference, 'total': proposals_qs.count(), 'reviewed': reviewed_count, 'unreviewed': unreviewed_count, @@ -110,7 +101,6 @@ def proposals_dashboard(request, conference_slug): 'group_by_reviewer_section': by_reviewer, 'by_target_audience': by_audience } - return render(request, 'proposals/dashboard.html', ctx) @@ -159,7 +149,7 @@ def reviewer_comments_dashboard(request, conference_slug): [ proposal_qs.count(), commented, uncommented, section.proposal_section.name] - ) + ) ctx = { 'conference': conference, diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index 201b12eb..b91d0642 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -12,11 +12,11 @@ def reviewer_comments(proposal, user): return proposal.get_reviewer_comments_count(user) > 0 + @register.filter(name='has_content_urls') def get_content_urls(proposal): if proposal.content_urls: url = proposal.content_urls.split() return url[0] - else: return False From 8eb842b23ead1671f4aafb0d9a1c5cd304d9d828 Mon Sep 17 00:00:00 2001 From: htrap Date: Fri, 17 Jul 2015 05:44:41 +0530 Subject: [PATCH 169/666] adding name in the contributors file --- CONTRIBUTORS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 0cd3a52f..bd63bac0 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -15,5 +15,5 @@ Aayush Kasurde Arjoonn Sharma (gh:theSage21) Haris Ibrahim K V (gh:harisibrahimkv / @harisibrahimkv) dhilipsiva (gh:dhilipsiva / @dhilipsiva) - +Parth Oberoi (gh:htrap) * Possesses commit rights From 3cdef813683ecaedfa71eced8c1c680f705f52d5 Mon Sep 17 00:00:00 2001 From: htrap Date: Fri, 17 Jul 2015 17:52:33 +0530 Subject: [PATCH 170/666] fixing url parsing for the content urls --- junction/proposals/dashboard.py | 7 +++++++ junction/proposals/templatetags/proposal_filters.py | 9 +++++---- .../partials/proposal-list--review-items.html | 11 ++++++----- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index f509c1df..3b7380c9 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -21,11 +21,14 @@ @require_http_methods(['GET']) def proposals_dashboard(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) + if not request.user.is_superuser: return HttpResponseForbidden() + proposals_qs = Proposal.objects.filter( conference=conference, status=PROPOSAL_STATUS_PUBLIC) + by_type = {} by_section = {} by_reviewer = {} @@ -58,6 +61,7 @@ def proposals_dashboard(request, conference_slug): conference_reviewer__reviewer=request.user)\ .distinct('proposal_section__id') # Hande case if reviewer is added to section twice' + for section in sections: proposal_qs = proposals_qs.filter(proposal_section=section.proposal_section) # due to space and number issue for key used this @@ -72,11 +76,13 @@ def proposals_dashboard(request, conference_slug): by_reviewer[key_id][1] = by_reviewer[key_id][1] + 1 else: by_reviewer[key_id][2] = by_reviewer[key_id][2] + 1 + audience_dict = { 1: 'Beginner', 2: 'Intermediate', 3: 'Advanced' } + for proposal in proposals_qs: audience = audience_dict[proposal.target_audience] by_audience.setdefault(audience, [0, 0, 0, audience]) @@ -91,6 +97,7 @@ def proposals_dashboard(request, conference_slug): else: by_audience[audience][2] = by_audience[audience][2] + 1 by_audience[audience][0] = by_audience[audience][0] + 1 + ctx = { 'conference': conference, 'total': proposals_qs.count(), diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index b91d0642..9f31d33b 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -3,6 +3,7 @@ # Third Party Stuff from django import template +import re register = template.Library() @@ -13,10 +14,10 @@ def reviewer_comments(proposal, user): return proposal.get_reviewer_comments_count(user) > 0 -@register.filter(name='has_content_urls') +@register.filter(name='get_content_urls') def get_content_urls(proposal): if proposal.content_urls: - url = proposal.content_urls.split() - return url[0] + urls = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', proposal.content_urls) + return urls else: - return False + return [] diff --git a/junction/templates/proposals/partials/proposal-list--review-items.html b/junction/templates/proposals/partials/proposal-list--review-items.html index 4eb9cae4..029e7f4a 100644 --- a/junction/templates/proposals/partials/proposal-list--review-items.html +++ b/junction/templates/proposals/partials/proposal-list--review-items.html @@ -51,16 +51,17 @@

{% endif %} - {% if proposal|has_content_urls %} - - {% endif %} - -

+ {% endif %} + {% endfor %} +
From c726d2bb2da9fe7317623df88f2ef56e19cc1e91 Mon Sep 17 00:00:00 2001 From: htrap Date: Fri, 17 Jul 2015 18:05:50 +0530 Subject: [PATCH 171/666] fixing flake8 errors --- CONTRIBUTORS.txt | 1 + junction/proposals/templatetags/proposal_filters.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index bd63bac0..2368242d 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -16,4 +16,5 @@ Arjoonn Sharma (gh:theSage21) Haris Ibrahim K V (gh:harisibrahimkv / @harisibrahimkv) dhilipsiva (gh:dhilipsiva / @dhilipsiva) Parth Oberoi (gh:htrap) + * Possesses commit rights diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index 9f31d33b..ff336e36 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -17,7 +17,8 @@ def reviewer_comments(proposal, user): @register.filter(name='get_content_urls') def get_content_urls(proposal): if proposal.content_urls: - urls = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', proposal.content_urls) + urls = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', + proposal.content_urls) return urls else: return [] From 8823303947b773b8ab90fd6190571c68951147da Mon Sep 17 00:00:00 2001 From: htrap Date: Fri, 17 Jul 2015 19:06:53 +0530 Subject: [PATCH 172/666] making regex code multiline to fix flake8 error in travis build --- junction/proposals/templatetags/proposal_filters.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index ff336e36..8b97feef 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -17,8 +17,8 @@ def reviewer_comments(proposal, user): @register.filter(name='get_content_urls') def get_content_urls(proposal): if proposal.content_urls: - urls = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', - proposal.content_urls) + url_re = 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+' + urls = re.findall(url_re, proposal.content_urls) return urls else: return [] From 47d2c63dbadf6ded81508d41ad631e2ab3068949 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Fri, 17 Jul 2015 23:20:46 +0530 Subject: [PATCH 173/666] adds field type to schedule item This can be talk, lunch, break etc. --- junction/schedule/migrations/0001_initial.py | 3 ++- junction/schedule/models.py | 8 ++++++++ junction/schedule/serializers.py | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/junction/schedule/migrations/0001_initial.py b/junction/schedule/migrations/0001_initial.py index ff4fbf60..28a624d8 100644 --- a/junction/schedule/migrations/0001_initial.py +++ b/junction/schedule/migrations/0001_initial.py @@ -8,9 +8,9 @@ class Migration(migrations.Migration): dependencies = [ - ('proposals', '0011_auto_20150530_0224'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('conferences', '0010_auto_20150713_2331'), + ('proposals', '0012_auto_20150709_0842'), ] operations = [ @@ -24,6 +24,7 @@ class Migration(migrations.Migration): ('start_time', models.TimeField()), ('end_time', models.TimeField()), ('alt_name', models.CharField(max_length=100, blank=True)), + ('type', models.CharField(default=b'TALK', max_length=20, choices=[(b'TALK', b'Talk'), (b'LUNCH', b'Lunch'), (b'BREAK', b'Break')])), ('conference', models.ForeignKey(to='conferences.Conference')), ('created_by', models.ForeignKey(related_name='created_scheduleitem_set', verbose_name='Created By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), ('modified_by', models.ForeignKey(related_name='updated_scheduleitem_set', verbose_name='Modified By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), diff --git a/junction/schedule/models.py b/junction/schedule/models.py index 5d217d00..cb1bd0d3 100644 --- a/junction/schedule/models.py +++ b/junction/schedule/models.py @@ -6,6 +6,12 @@ class ScheduleItem(AuditModel): + TALK = 'TALK' + LUNCH = 'LUNCH' + BREAK = 'BREAK' + SCHEDULE_ITEM_TYPE = ((TALK, 'Talk'), + (LUNCH, 'Lunch'), + (BREAK, 'Break')) room = models.ForeignKey(Room, null=True) # if a session is not present, venue can be null Ex: break event_date = models.DateField() @@ -13,6 +19,8 @@ class ScheduleItem(AuditModel): end_time = models.TimeField() alt_name = models.CharField(max_length=100, blank=True) session = models.ForeignKey(Proposal, null=True) + type = models.CharField(max_length=20, choices=SCHEDULE_ITEM_TYPE, + default=TALK) conference = models.ForeignKey(Conference) diff --git a/junction/schedule/serializers.py b/junction/schedule/serializers.py index 2a0233a0..1bb323a8 100644 --- a/junction/schedule/serializers.py +++ b/junction/schedule/serializers.py @@ -11,4 +11,4 @@ class ScheduleSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = ScheduleItem fields = ('room', 'event_date', 'start_time', 'end_time', - 'name', 'session', 'conference') + 'name', 'session', 'type', 'conference') From b582bcbb8bc9b9416b114fecda8639ee18c19fb1 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Fri, 17 Jul 2015 23:36:12 +0530 Subject: [PATCH 174/666] prefetch in Api view for better performance. --- junction/schedule/views.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/junction/schedule/views.py b/junction/schedule/views.py index 83d63750..5c601dfd 100644 --- a/junction/schedule/views.py +++ b/junction/schedule/views.py @@ -15,6 +15,11 @@ class ScheduleView(viewsets.ReadOnlyModelViewSet): filter_backend = (filters.DjangoFilterBackend,) filter_fields = ('room', 'conference', 'event_date') + def get_queryset(self): + return super(ScheduleView, self).get_queryset().prefetch_related( + 'session', 'session__proposal_type', 'session__proposal_section', + 'session__author') + def dummy_schedule(request, conference_slug): data = render_to_string('dummy_schedule.json') From 00089612a8f54fbc4fd87bb116af1644137d32d5 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sat, 18 Jul 2015 00:07:11 +0530 Subject: [PATCH 175/666] add redundancy to author on proposal if first name or last name is not present, use username --- junction/proposals/serializers.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/junction/proposals/serializers.py b/junction/proposals/serializers.py index 58a279fc..ce46778b 100644 --- a/junction/proposals/serializers.py +++ b/junction/proposals/serializers.py @@ -15,12 +15,13 @@ def get_type(self, proposal): return proposal.proposal_type.name def get_author(self, proposal): - return "{} {}".format(proposal.author.first_name, - proposal.author.first_name) + author = proposal.author + return "{} {}".format( + author.first_name, author.last_name).strip() or author.username class Meta: model = Proposal fields = ('title', 'section', 'type', 'author', 'slug', 'description', 'target_audience', 'prerequisites', 'content_urls', 'speaker_info', - 'speaker_links', 'status', 'review_status') + 'speaker_links') From c1d7621a2f95c2e4722b06ae53554eecd951f0e4 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sat, 18 Jul 2015 00:31:07 +0530 Subject: [PATCH 176/666] add a default ordering to scheduled items --- junction/schedule/migrations/0001_initial.py | 9 ++++++--- junction/schedule/models.py | 9 +++++++-- junction/schedule/views.py | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/junction/schedule/migrations/0001_initial.py b/junction/schedule/migrations/0001_initial.py index 28a624d8..4cca1c7f 100644 --- a/junction/schedule/migrations/0001_initial.py +++ b/junction/schedule/migrations/0001_initial.py @@ -20,8 +20,8 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')), - ('event_date', models.DateField()), - ('start_time', models.TimeField()), + ('event_date', models.DateField(db_index=True)), + ('start_time', models.TimeField(db_index=True)), ('end_time', models.TimeField()), ('alt_name', models.CharField(max_length=100, blank=True)), ('type', models.CharField(default=b'TALK', max_length=20, choices=[(b'TALK', b'Talk'), (b'LUNCH', b'Lunch'), (b'BREAK', b'Break')])), @@ -32,8 +32,11 @@ class Migration(migrations.Migration): ('session', models.ForeignKey(to='proposals.Proposal', null=True)), ], options={ - 'abstract': False, }, bases=(models.Model,), ), + migrations.AlterIndexTogether( + name='scheduleitem', + index_together=set([('event_date', 'start_time')]), + ), ] diff --git a/junction/schedule/models.py b/junction/schedule/models.py index cb1bd0d3..10e9484d 100644 --- a/junction/schedule/models.py +++ b/junction/schedule/models.py @@ -14,8 +14,8 @@ class ScheduleItem(AuditModel): (BREAK, 'Break')) room = models.ForeignKey(Room, null=True) # if a session is not present, venue can be null Ex: break - event_date = models.DateField() - start_time = models.TimeField() + event_date = models.DateField(db_index=True) + start_time = models.TimeField(db_index=True) end_time = models.TimeField() alt_name = models.CharField(max_length=100, blank=True) session = models.ForeignKey(Proposal, null=True) @@ -30,3 +30,8 @@ def __unicode__(self): @property def name(self): return self.alt_name or self.session.title + + class Meta: + index_together = [ + ('event_date', 'start_time') + ] diff --git a/junction/schedule/views.py b/junction/schedule/views.py index 5c601dfd..489b78e1 100644 --- a/junction/schedule/views.py +++ b/junction/schedule/views.py @@ -18,7 +18,7 @@ class ScheduleView(viewsets.ReadOnlyModelViewSet): def get_queryset(self): return super(ScheduleView, self).get_queryset().prefetch_related( 'session', 'session__proposal_type', 'session__proposal_section', - 'session__author') + 'session__author').order_by('event_date', 'start_time') def dummy_schedule(request, conference_slug): From 1c6320010deacd88ee151344cd58285778cca793 Mon Sep 17 00:00:00 2001 From: Vignesh Sarma K Date: Sat, 18 Jul 2015 00:31:31 +0530 Subject: [PATCH 177/666] add notes to room. --- junction/conferences/migrations/0010_auto_20150713_2331.py | 1 + junction/conferences/models.py | 2 ++ junction/conferences/serializers.py | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/junction/conferences/migrations/0010_auto_20150713_2331.py b/junction/conferences/migrations/0010_auto_20150713_2331.py index 51242301..3391dccc 100644 --- a/junction/conferences/migrations/0010_auto_20150713_2331.py +++ b/junction/conferences/migrations/0010_auto_20150713_2331.py @@ -38,6 +38,7 @@ class Migration(migrations.Migration): ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')), ('name', models.CharField(max_length=100)), + ('note', models.CharField(max_length=255)), ('created_by', models.ForeignKey(related_name='created_room_set', verbose_name='Created By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), ('modified_by', models.ForeignKey(related_name='updated_room_set', verbose_name='Modified By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), ('venue', models.ForeignKey(to='conferences.ConferenceVenue')), diff --git a/junction/conferences/models.py b/junction/conferences/models.py index 3bfd1d56..e7dccb4d 100644 --- a/junction/conferences/models.py +++ b/junction/conferences/models.py @@ -108,5 +108,7 @@ class Room(AuditModel): name = models.CharField(max_length=100) venue = models.ForeignKey(ConferenceVenue) + note = models.CharField(max_length=255) + def __str__(self): return "{}, {}".format(self.name, self.venue) diff --git a/junction/conferences/serializers.py b/junction/conferences/serializers.py index 301e5260..a38b777e 100644 --- a/junction/conferences/serializers.py +++ b/junction/conferences/serializers.py @@ -21,4 +21,4 @@ class Meta: class RoomSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Room - fields = ('name', 'venue') + fields = ('name', 'venue', 'note') From 1f31b2457e3c92e0ab87b8b8b622cd341ddb52cb Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 20 Jul 2015 21:37:27 +0530 Subject: [PATCH 178/666] Update reviewer vote view Added alert message for vote value. --- junction/proposals/models.py | 5 ++++- junction/proposals/views.py | 2 +- junction/templates/proposals/vote.html | 7 ++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index a48d5030..425a91ec 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -97,6 +97,9 @@ def get_update_url(self): def get_review_url(self): return reverse('proposal-review', args=[self.conference.slug, self.slug]) + def get_vote_url(self): + return reverse('proposal-reviewer-vote', args=[self.conference.slug, self.slug]) + def get_delete_url(self): return reverse('proposal-delete', args=[self.conference.slug, self.slug]) @@ -187,7 +190,7 @@ class ProposalSectionReviewerVoteValue(AuditModel): description = models.CharField(max_length=255) def __str__(self): - return "[{}] {}".format(self.vote_value, self.description) + return "{} ({})".format(self.description, self.vote_value) class Meta: ordering = ('-vote_value',) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 907bfacc..37b7c845 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -380,7 +380,7 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): ctx = { 'proposal': proposal, 'proposal_vote_form': proposal_vote_form, - 'vote_value': vote_value, + 'vote': vote, } return render(request, 'proposals/vote.html', ctx) diff --git a/junction/templates/proposals/vote.html b/junction/templates/proposals/vote.html index 29440281..aea4a209 100644 --- a/junction/templates/proposals/vote.html +++ b/junction/templates/proposals/vote.html @@ -28,6 +28,11 @@ {% block content %}
+ {% if vote %} +
+ You have casted "{{ vote.vote_value }}" vote. Submitting again will override the existing one. +
+ {% endif %}
@@ -56,7 +61,7 @@

Proposal Voting

-
+
From 51aa94e739d094983426851d5aa2e9c8b8fa5b34 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 20 Jul 2015 21:38:10 +0530 Subject: [PATCH 179/666] Add link to reviewer vote view in proposal detail view --- junction/templates/proposals/detail/base.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index eb5e840a..1ff6e289 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -148,6 +148,16 @@

Speaker Links:

{{ proposal.speaker_links|markdown }}

{% endif %} + + {% if is_reviewer or user.is_authenticated and user.is_superuser %} +
+

Reviewer Actions:

+ + Vote for proposal + +
+ {% endif %} +
From 316926cd0b9ea302dd82256067fa69a989a6a427 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 20 Jul 2015 21:55:44 +0530 Subject: [PATCH 180/666] Show vote status in review page --- .../templatetags/proposal_filters.py | 26 ++++++++++++++++++- .../partials/proposal-list--review-items.html | 6 +++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index 8b97feef..05f0fa78 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -1,9 +1,17 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals +# Standard Library +import re + # Third Party Stuff from django import template -import re + +# Junction Stuff +from junction.proposals.models import ( + ProposalSectionReviewer, + ProposalSectionReviewerVote, +) register = template.Library() @@ -14,6 +22,22 @@ def reviewer_comments(proposal, user): return proposal.get_reviewer_comments_count(user) > 0 +@register.filter(name='is_reviewer_voted') +def is_reviewer_voted(proposal, user): + try: + vote = ProposalSectionReviewerVote.objects.get( + proposal=proposal, + voter=ProposalSectionReviewer.objects.get( + conference_reviewer__reviewer=user, + conference_reviewer__conference=proposal.conference, + proposal_section=proposal.proposal_section), + ) + except ProposalSectionReviewerVote.DoesNotExist: + vote = None + + return vote + + @register.filter(name='get_content_urls') def get_content_urls(proposal): if proposal.content_urls: diff --git a/junction/templates/proposals/partials/proposal-list--review-items.html b/junction/templates/proposals/partials/proposal-list--review-items.html index 029e7f4a..e8b5c01b 100644 --- a/junction/templates/proposals/partials/proposal-list--review-items.html +++ b/junction/templates/proposals/partials/proposal-list--review-items.html @@ -51,6 +51,12 @@

{% endif %} + {% if proposal|is_reviewer_voted:request.user %} + + + + {% endif %} + {% for url in proposal|get_content_urls %} {% if url %} Date: Mon, 20 Jul 2015 21:59:47 +0530 Subject: [PATCH 181/666] Whitespace cleanup --- junction/proposals/dashboard.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index 3b7380c9..981aaf91 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -21,14 +21,14 @@ @require_http_methods(['GET']) def proposals_dashboard(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) - + if not request.user.is_superuser: return HttpResponseForbidden() - + proposals_qs = Proposal.objects.filter( conference=conference, status=PROPOSAL_STATUS_PUBLIC) - + by_type = {} by_section = {} by_reviewer = {} @@ -61,7 +61,7 @@ def proposals_dashboard(request, conference_slug): conference_reviewer__reviewer=request.user)\ .distinct('proposal_section__id') # Hande case if reviewer is added to section twice' - + for section in sections: proposal_qs = proposals_qs.filter(proposal_section=section.proposal_section) # due to space and number issue for key used this @@ -76,13 +76,13 @@ def proposals_dashboard(request, conference_slug): by_reviewer[key_id][1] = by_reviewer[key_id][1] + 1 else: by_reviewer[key_id][2] = by_reviewer[key_id][2] + 1 - + audience_dict = { 1: 'Beginner', 2: 'Intermediate', 3: 'Advanced' } - + for proposal in proposals_qs: audience = audience_dict[proposal.target_audience] by_audience.setdefault(audience, [0, 0, 0, audience]) @@ -97,7 +97,7 @@ def proposals_dashboard(request, conference_slug): else: by_audience[audience][2] = by_audience[audience][2] + 1 by_audience[audience][0] = by_audience[audience][0] + 1 - + ctx = { 'conference': conference, 'total': proposals_qs.count(), From 231702413aeceea67b02252a504a3ac254f3b9ee Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 20 Jul 2015 23:14:13 +0530 Subject: [PATCH 182/666] Add vote field for proposal comment --- .../migrations/0013_proposalcomment_vote.py | 20 +++++++++++++++++++ junction/proposals/models.py | 1 + 2 files changed, 21 insertions(+) create mode 100644 junction/proposals/migrations/0013_proposalcomment_vote.py diff --git a/junction/proposals/migrations/0013_proposalcomment_vote.py b/junction/proposals/migrations/0013_proposalcomment_vote.py new file mode 100644 index 00000000..b86099d4 --- /dev/null +++ b/junction/proposals/migrations/0013_proposalcomment_vote.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0012_auto_20150709_0842'), + ] + + operations = [ + migrations.AddField( + model_name='proposalcomment', + name='vote', + field=models.BooleanField(default=False, verbose_name='Is Justification?'), + preserve_default=True, + ), + ] diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 425a91ec..4e5b6413 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -220,6 +220,7 @@ class ProposalComment(TimeAuditModel): commenter = models.ForeignKey(User) private = models.BooleanField(default=False, verbose_name="Is Private?") reviewer = models.BooleanField(default=False, verbose_name="Is Reviewer?") + vote = models.BooleanField(default=False, verbose_name="Is Justification?") comment = models.TextField() deleted = models.BooleanField(default=False, verbose_name="Is Deleted?") From bd7def671eaab06b225f893674549edbf9c3052d Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 20 Jul 2015 23:15:47 +0530 Subject: [PATCH 183/666] Add comment to reviewer vote page --- junction/proposals/forms.py | 5 ++++ junction/proposals/views.py | 25 ++++++++++++++-- .../templates/proposals/detail/comments.html | 7 +++-- junction/templates/proposals/vote.html | 29 ++++++------------- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index 222a1e9c..e52e26ef 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -144,6 +144,11 @@ class ProposalReviewerVoteForm(forms.Form): choices=_get_proposal_section_reviewer_vote_choices(), widget=forms.RadioSelect() ) + comment = forms.CharField( + widget=forms.Textarea, + required=False, + help_text="Leave a comment justifying your vote.", + ) class ProposalsToReviewForm(forms.Form): diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 37b7c845..f1626b4d 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -373,9 +373,20 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): except ProposalSectionReviewerVote.DoesNotExist: vote = None + try: + vote_comment = ProposalComment.objects.get( + proposal=proposal, + commenter=request.user, + vote=True, + deleted=False, + ) + except: + vote_comment = None if request.method == 'GET': - proposal_vote_form = ProposalReviewerVoteForm(initial={'vote_value': vote_value}) + proposal_vote_form = ProposalReviewerVoteForm( + initial={'vote_value': vote_value, 'vote_comment': vote_comment} + ) ctx = { 'proposal': proposal, @@ -394,6 +405,7 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): # Valid Form vote_value = form.cleaned_data['vote_value'] + comment = form.cleaned_data['comment'] if not vote: vote = ProposalSectionReviewerVote.objects.create( proposal=proposal, @@ -406,7 +418,16 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): else: vote.vote_value = ProposalSectionReviewerVoteValue.objects.get(vote_value=vote_value) vote.save() - + if not vote_comment: + vote_comment = ProposalComment.objects.create( + proposal=proposal, + commenter=request.user, + comment=comment, + vote=True, + ) + else: + vote_comment.comment = comment + vote_comment.save() return HttpResponseRedirect(reverse('proposals-list', args=[conference.slug])) diff --git a/junction/templates/proposals/detail/comments.html b/junction/templates/proposals/detail/comments.html index b76a0630..488a05fb 100644 --- a/junction/templates/proposals/detail/comments.html +++ b/junction/templates/proposals/detail/comments.html @@ -1,10 +1,11 @@ {% load bootstrap3 %} {% load django_markdown %} {% load humanize %} + {% if not comments %} -

- No comments added so far. -

+

+ No comments added so far. +

{% endif %} {% for comment in comments %} diff --git a/junction/templates/proposals/vote.html b/junction/templates/proposals/vote.html index aea4a209..f533655a 100644 --- a/junction/templates/proposals/vote.html +++ b/junction/templates/proposals/vote.html @@ -39,31 +39,20 @@

Proposal Voting


-
- {% csrf_token %} -
- {% for field in proposal_vote_form %} - {% if field.errors %} - {{field.errors}} - {% endif %} -
- {{field}} -
- {% endfor %} -
- -
-
- -
+ {% csrf_token %} + {% bootstrap_form proposal_vote_form %} + {% buttons %} +
+
+ {% endbuttons %}

-

{% endblock %} + From 50a6f72e16ce88bbcf2e1511c9fbd7e90774f7ae Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 20 Jul 2015 23:23:18 +0530 Subject: [PATCH 184/666] Update comment filters --- junction/proposals/models.py | 6 +++--- junction/proposals/views.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 4e5b6413..73b8823d 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -160,13 +160,13 @@ class Meta: class ProposalCommentQuerySet(models.QuerySet): def get_public_comments(self): - return self.filter(private=False, reviewer=False) + return self.filter(private=False, reviewer=False, vote=False) def get_reviewers_comments(self): - return self.filter(private=True) + return self.filter(private=True, vote=False) def get_reviewers_only_comments(self): - return self.filter(reviewer=True) + return self.filter(reviewer=True, vote=False) class ProposalCommentManager(models.Manager): diff --git a/junction/proposals/views.py b/junction/proposals/views.py index f1626b4d..3e66a29b 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -195,7 +195,7 @@ def detail_proposal(request, conference_slug, slug): } comments = ProposalComment.objects.filter( - proposal=proposal, deleted=False, + proposal=proposal, deleted=False, vote=False ) if read_private_comment: @@ -385,7 +385,7 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): if request.method == 'GET': proposal_vote_form = ProposalReviewerVoteForm( - initial={'vote_value': vote_value, 'vote_comment': vote_comment} + initial={'vote_value': vote_value, 'comment': vote_comment.comment} ) ctx = { From f9a94f8cd649f044eb7904c730a93d4c9d3ffa70 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Tue, 21 Jul 2015 07:49:26 +0530 Subject: [PATCH 185/666] chore(setup): add pip install command in regenerate.sh --- regenerate.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/regenerate.sh b/regenerate.sh index 8d9e742b..1287fb0c 100755 --- a/regenerate.sh +++ b/regenerate.sh @@ -1,5 +1,8 @@ #!/bin/bash +echo "-> Install requirements:" +pip install -r requirements-dev.txt + echo "-> Remove database:" rm db.sqlite3 From 16009a53462f58e3a287951e60b7fd25ea036d36 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Tue, 21 Jul 2015 09:38:55 +0530 Subject: [PATCH 186/666] chore(UI): Improve UI of reviewer proposals filter widget For #299 --- .../partials/proposal-list--review-items.html | 2 +- junction/templates/proposals/to_review.html | 26 +++++++------------ 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/junction/templates/proposals/partials/proposal-list--review-items.html b/junction/templates/proposals/partials/proposal-list--review-items.html index 029e7f4a..2f13926c 100644 --- a/junction/templates/proposals/partials/proposal-list--review-items.html +++ b/junction/templates/proposals/partials/proposal-list--review-items.html @@ -2,7 +2,7 @@
- + {% if title %}

{{ title }}

{% endif %} diff --git a/junction/templates/proposals/to_review.html b/junction/templates/proposals/to_review.html index b691eada..e64259d3 100644 --- a/junction/templates/proposals/to_review.html +++ b/junction/templates/proposals/to_review.html @@ -41,16 +41,13 @@

Proposals To Review


@@ -71,20 +68,14 @@

Filter Proposals

{% block script_extra %} From e8eb1bfc147aa053cbf4211c011812701f2bd45e Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Tue, 21 Jul 2015 09:58:46 +0530 Subject: [PATCH 187/666] style(flake8): fix flake8 warning in dashboard.py --- junction/proposals/dashboard.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index 3b7380c9..981aaf91 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -21,14 +21,14 @@ @require_http_methods(['GET']) def proposals_dashboard(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) - + if not request.user.is_superuser: return HttpResponseForbidden() - + proposals_qs = Proposal.objects.filter( conference=conference, status=PROPOSAL_STATUS_PUBLIC) - + by_type = {} by_section = {} by_reviewer = {} @@ -61,7 +61,7 @@ def proposals_dashboard(request, conference_slug): conference_reviewer__reviewer=request.user)\ .distinct('proposal_section__id') # Hande case if reviewer is added to section twice' - + for section in sections: proposal_qs = proposals_qs.filter(proposal_section=section.proposal_section) # due to space and number issue for key used this @@ -76,13 +76,13 @@ def proposals_dashboard(request, conference_slug): by_reviewer[key_id][1] = by_reviewer[key_id][1] + 1 else: by_reviewer[key_id][2] = by_reviewer[key_id][2] + 1 - + audience_dict = { 1: 'Beginner', 2: 'Intermediate', 3: 'Advanced' } - + for proposal in proposals_qs: audience = audience_dict[proposal.target_audience] by_audience.setdefault(audience, [0, 0, 0, audience]) @@ -97,7 +97,7 @@ def proposals_dashboard(request, conference_slug): else: by_audience[audience][2] = by_audience[audience][2] + 1 by_audience[audience][0] = by_audience[audience][0] + 1 - + ctx = { 'conference': conference, 'total': proposals_qs.count(), From 09bbfbb839f2bba0c28705d93c63db33acfff6fe Mon Sep 17 00:00:00 2001 From: chillaranand Date: Wed, 22 Jul 2015 20:26:57 +0530 Subject: [PATCH 188/666] Update verbose name --- junction/proposals/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 73b8823d..f4ca2451 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -220,7 +220,7 @@ class ProposalComment(TimeAuditModel): commenter = models.ForeignKey(User) private = models.BooleanField(default=False, verbose_name="Is Private?") reviewer = models.BooleanField(default=False, verbose_name="Is Reviewer?") - vote = models.BooleanField(default=False, verbose_name="Is Justification?") + vote = models.BooleanField(default=False, verbose_name="What is the reason?") comment = models.TextField() deleted = models.BooleanField(default=False, verbose_name="Is Deleted?") From 73ab924d9362c39ad4bb1dcfbef52bf9a0ff8910 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Thu, 23 Jul 2015 00:26:58 +0530 Subject: [PATCH 189/666] Check reviewer vote before rendering form --- junction/proposals/views.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 3e66a29b..8fa381a9 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -354,7 +354,8 @@ def proposal_upload_content(request, conference_slug, slug): @require_http_methods(['GET', 'POST']) def proposal_reviewer_vote(request, conference_slug, proposal_slug): conference = get_object_or_404(Conference, slug=conference_slug) - proposal = get_object_or_404(Proposal, slug=proposal_slug, conference=conference) + proposal = get_object_or_404(Proposal, slug=proposal_slug, + conference=conference) if not _is_proposal_section_reviewer(request.user, conference, proposal): return HttpResponseForbidden() @@ -383,11 +384,13 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): except: vote_comment = None if request.method == 'GET': - - proposal_vote_form = ProposalReviewerVoteForm( - initial={'vote_value': vote_value, 'comment': vote_comment.comment} - ) - + if vote_comment: + proposal_vote_form = ProposalReviewerVoteForm( + initial={'vote_value': vote_value, + 'comment': vote_comment.comment}) + else: + proposal_vote_form = ProposalReviewerVoteForm( + initial={'vote_value': vote_value}) ctx = { 'proposal': proposal, 'proposal_vote_form': proposal_vote_form, @@ -399,9 +402,10 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): # POST Workflow form = ProposalReviewerVoteForm(request.POST) if not form.is_valid(): - return render(request, 'proposals/vote.html', {'form': form, - 'proposal': proposal, - 'form_errors': form.errors}) + return render(request, 'proposals/vote.html', + {'form': form, + 'proposal': proposal, + 'form_errors': form.errors}) # Valid Form vote_value = form.cleaned_data['vote_value'] @@ -413,10 +417,12 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): conference_reviewer__reviewer=request.user, conference_reviewer__conference=conference, proposal_section=proposal.proposal_section), - vote_value=ProposalSectionReviewerVoteValue.objects.get(vote_value=vote_value), + vote_value=ProposalSectionReviewerVoteValue.objects.get( + vote_value=vote_value), ) else: - vote.vote_value = ProposalSectionReviewerVoteValue.objects.get(vote_value=vote_value) + vote.vote_value = ProposalSectionReviewerVoteValue.objects.get( + vote_value=vote_value) vote.save() if not vote_comment: vote_comment = ProposalComment.objects.create( @@ -428,7 +434,8 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): else: vote_comment.comment = comment vote_comment.save() - return HttpResponseRedirect(reverse('proposals-list', args=[conference.slug])) + return HttpResponseRedirect(reverse('proposals-to-review', + args=[conference.slug])) @login_required From 93343d2c77f85777719e7bfc4db445743fac2ab4 Mon Sep 17 00:00:00 2001 From: htrap Date: Mon, 20 Jul 2015 20:54:16 +0530 Subject: [PATCH 190/666] issue #137: highlighting up/down vote button fixed. --- junction/templates/proposals/detail/comments.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/junction/templates/proposals/detail/comments.html b/junction/templates/proposals/detail/comments.html index 488a05fb..39d7d18f 100644 --- a/junction/templates/proposals/detail/comments.html +++ b/junction/templates/proposals/detail/comments.html @@ -14,7 +14,7 @@
@@ -24,7 +24,7 @@
From 32df77585b66d60aff9e5a0bbced8485e09983ec Mon Sep 17 00:00:00 2001 From: htrap Date: Tue, 21 Jul 2015 00:42:58 +0530 Subject: [PATCH 191/666] Adding highlighting for user specific upvotes arrows for each comment --- junction/proposals/templatetags/proposal_filters.py | 5 +++++ junction/templates/proposals/detail/comments.html | 12 ++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index 05f0fa78..42c20a2d 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -46,3 +46,8 @@ def get_content_urls(proposal): return urls else: return [] + +@register.filter(name='has_upvoted_comment') +def has_upvoted_comment(comment, user): + vote = comment.proposalcommentvote_set.get(voter=user) + return vote.up_vote diff --git a/junction/templates/proposals/detail/comments.html b/junction/templates/proposals/detail/comments.html index 39d7d18f..58efba17 100644 --- a/junction/templates/proposals/detail/comments.html +++ b/junction/templates/proposals/detail/comments.html @@ -14,7 +14,11 @@
@@ -24,7 +28,11 @@
From 28b8808c120a16e23a409af278bf4d780cfe4d20 Mon Sep 17 00:00:00 2001 From: htrap Date: Tue, 21 Jul 2015 01:00:32 +0530 Subject: [PATCH 192/666] Fixing flake8 errors, also using .filter to escape DoesNotExist situations in .get --- junction/proposals/templatetags/proposal_filters.py | 8 +++++--- junction/templates/proposals/detail/comments.html | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index 42c20a2d..89de0e28 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -46,8 +46,10 @@ def get_content_urls(proposal): return urls else: return [] - + + @register.filter(name='has_upvoted_comment') def has_upvoted_comment(comment, user): - vote = comment.proposalcommentvote_set.get(voter=user) - return vote.up_vote + vote = comment.proposalcommentvote_set.filter(voter=user) + if vote: + return vote[0].up_vote diff --git a/junction/templates/proposals/detail/comments.html b/junction/templates/proposals/detail/comments.html index 58efba17..53d12de1 100644 --- a/junction/templates/proposals/detail/comments.html +++ b/junction/templates/proposals/detail/comments.html @@ -16,7 +16,7 @@
From bfd2bde3f067f87c712b6e10afb9e5deeba82f70 Mon Sep 17 00:00:00 2001 From: htrap Date: Thu, 23 Jul 2015 13:23:24 +0530 Subject: [PATCH 193/666] fixing rebase conflict --- junction/templates/proposals/detail/comments.html | 1 + 1 file changed, 1 insertion(+) diff --git a/junction/templates/proposals/detail/comments.html b/junction/templates/proposals/detail/comments.html index 53d12de1..d4c3a3b2 100644 --- a/junction/templates/proposals/detail/comments.html +++ b/junction/templates/proposals/detail/comments.html @@ -1,6 +1,7 @@ {% load bootstrap3 %} {% load django_markdown %} {% load humanize %} +{% load proposal_filters %} {% if not comments %}

From fb4ca948cafcca6f215973783689131d205e1ad7 Mon Sep 17 00:00:00 2001 From: htrap Date: Sat, 25 Jul 2015 23:26:13 +0530 Subject: [PATCH 194/666] adding dashboard, fixing issue #287 --- junction/profiles/__init__.py | 0 junction/profiles/admin.py | 3 + junction/profiles/migrations/__init__.py | 0 junction/profiles/models.py | 3 + junction/profiles/tests.py | 3 + junction/profiles/urls.py | 7 ++ junction/profiles/views.py | 17 ++++ junction/proposals/forms.py | 2 +- junction/templates/base.html | 2 +- junction/templates/profiles/dashboard.html | 110 +++++++++++++++++++++ junction/urls.py | 3 + settings/common.py | 1 + 12 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 junction/profiles/__init__.py create mode 100644 junction/profiles/admin.py create mode 100644 junction/profiles/migrations/__init__.py create mode 100644 junction/profiles/models.py create mode 100644 junction/profiles/tests.py create mode 100644 junction/profiles/urls.py create mode 100644 junction/profiles/views.py create mode 100644 junction/templates/profiles/dashboard.html diff --git a/junction/profiles/__init__.py b/junction/profiles/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/junction/profiles/admin.py b/junction/profiles/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/junction/profiles/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/junction/profiles/migrations/__init__.py b/junction/profiles/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/junction/profiles/models.py b/junction/profiles/models.py new file mode 100644 index 00000000..71a83623 --- /dev/null +++ b/junction/profiles/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/junction/profiles/tests.py b/junction/profiles/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/junction/profiles/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/junction/profiles/urls.py b/junction/profiles/urls.py new file mode 100644 index 00000000..ecce111c --- /dev/null +++ b/junction/profiles/urls.py @@ -0,0 +1,7 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url(r'^$', views.dashboard, name='dashboard'), +] diff --git a/junction/profiles/views.py b/junction/profiles/views.py new file mode 100644 index 00000000..626ca5de --- /dev/null +++ b/junction/profiles/views.py @@ -0,0 +1,17 @@ +from django.shortcuts import render + +from junction.proposals.models import Proposal +from django.contrib.auth.decorators import login_required +from django.views.decorators.http import require_http_methods + + +@login_required +@require_http_methods(['GET']) +def dashboard(request): + proposal_qs = Proposal.objects.order_by('conference__end_date') + user_proposal_list = [] + if request.user.is_authenticated(): + user_proposal_list = proposal_qs.filter(author=request.user, + deleted=False) + return render(request, 'profiles/dashboard.html', + {'user_proposal_list': user_proposal_list}) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index e52e26ef..1cdce1ec 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -63,7 +63,7 @@ class ProposalForm(forms.Form): widget=forms.TextInput(attrs={'class': 'charfield'})) description = forms.CharField(widget=PagedownWidget(show_preview=True), help_text=("Describe your proposal with clear objective in simple sentence." - " Keep it short and simple.")) + " Keep it short and simple.")) target_audience = forms.ChoiceField( choices=PROPOSAL_TARGET_AUDIENCES, widget=forms.Select(attrs={'class': 'dropdown'})) diff --git a/junction/templates/base.html b/junction/templates/base.html index 5aa37ef9..9485f644 100644 --- a/junction/templates/base.html +++ b/junction/templates/base.html @@ -106,7 +106,7 @@ {% if user.is_authenticated %} Account

ReviewersProposal commentedProposal Reviewed
{{data.0}} {{data.1}}{{data.2}}{{data.0.first_name}} {{data.0.last_name}}{{data.1}}
Target Audience: - {% if proposal.target_audience == 1 %} - Beginner - {% elif proposal.target_audience == 2 %} - Intermediate - {% else %} - Advanced - {% endif %} + {{ proposal.get_target_audience_display }}
@@ -255,10 +249,10 @@

Reviewer Actions:

{% block script_extra %} +{% endblock %} + +{% block breadcrumbs %} + {{ block.super }} + {% breadcrumb sch_item.conference.name "conference-detail" sch_item.conference.slug %} + {% breadcrumb "Proposals" "proposals-list" sch_item.conference.slug %} + {% breadcrumb sch_item.name "proposal-detail" sch_item.conference.slug sch_item.slug %} +{% endblock %} + +{% block navbar_logo %} + {% if sch_item.conference.logo %} +
+ + + {% else %} + {{ sch_item.conference.name }} + {% endif %} +{% endblock navbar_logo %} + +{% block content %} +
+
+
+
+

+ {{ sch_item.name }} +

+
+
+

Description:

+

{{ sch_item.alt_description|markdown }}

+
+
+
+
+
+
+{% endblock content %} From fbee524d7a2427e653eeec890dbf3ccd75f5b362 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 20 Sep 2015 01:03:26 +0530 Subject: [PATCH 298/666] Add schedule item id to accept integer greater 9 --- junction/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/urls.py b/junction/urls.py index c89e9222..ef11e684 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -56,7 +56,7 @@ 'junction.proposals.dashboard.export_reviewer_votes', name='export-reviewer-votes'), - url(r'^schedule_item/(?P\d)/$', + url(r'^schedule_item/(?P\d+)/$', non_proposal_schedule_item_view, name="schedule-item"), url(r'^api/v1/', include(router.urls)), From 0a69f5c82145cb7ac5a1f30f9356b1cb3b99a238 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 20 Sep 2015 15:01:40 +0530 Subject: [PATCH 299/666] Add print message and improve __str__ lookup --- junction/tickets/management/commands/explara.py | 1 + junction/tickets/models.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/junction/tickets/management/commands/explara.py b/junction/tickets/management/commands/explara.py index eb93abf1..cc471b9e 100644 --- a/junction/tickets/management/commands/explara.py +++ b/junction/tickets/management/commands/explara.py @@ -49,6 +49,7 @@ def get_orders(self, explara_eventid): # after the first batch, subsequent batches are dicts with batch no. as key. elif isinstance(attendee_response.get('attendee'), dict): ticket_orders.extend([order for order_idx, order in attendee_response.get('attendee').items()]) + print("Synced {} records".format(to_record)) from_record = to_record to_record += 50 diff --git a/junction/tickets/models.py b/junction/tickets/models.py index 0c6c392f..0329dce3 100644 --- a/junction/tickets/models.py +++ b/junction/tickets/models.py @@ -25,4 +25,4 @@ class Ticket(AuditModel): others = JSONField() def __str__(self): - return self.ticket_no + return self.name, self.email, self.ticket_no From ba2a521190dd9472452b4e94d7d2c64f8321554b Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 26 Sep 2015 00:03:27 +0530 Subject: [PATCH 300/666] Add conference name in proposal section and type in repr --- junction/proposals/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index d145152e..7cce4f58 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -32,7 +32,7 @@ class ProposalSection(AuditModel): conferences = models.ManyToManyField(to=Conference, related_name='proposal_sections') def __str__(self): - return self.name + return self.name, self.conferences @python_2_unicode_compatible @@ -60,7 +60,7 @@ class ProposalType(AuditModel): end_date = models.DateField(default=datetime.now, verbose_name="End Date") def __str__(self): - return self.name + return self.name, self.conference @python_2_unicode_compatible From 11e178cfca4c21f680c719f3fc0a9ec0bb984784 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 26 Sep 2015 00:07:18 +0530 Subject: [PATCH 301/666] Fix typeo --- junction/proposals/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 7cce4f58..281d9686 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -60,7 +60,7 @@ class ProposalType(AuditModel): end_date = models.DateField(default=datetime.now, verbose_name="End Date") def __str__(self): - return self.name, self.conference + return self.name, self.conferences @python_2_unicode_compatible From f141895d497937bda30419760ca9ffdf2faa2a98 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 26 Sep 2015 00:09:37 +0530 Subject: [PATCH 302/666] Revert proposal type and section changes --- junction/proposals/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 281d9686..d145152e 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -32,7 +32,7 @@ class ProposalSection(AuditModel): conferences = models.ManyToManyField(to=Conference, related_name='proposal_sections') def __str__(self): - return self.name, self.conferences + return self.name @python_2_unicode_compatible @@ -60,7 +60,7 @@ class ProposalType(AuditModel): end_date = models.DateField(default=datetime.now, verbose_name="End Date") def __str__(self): - return self.name, self.conferences + return self.name @python_2_unicode_compatible From bde884898868f2477941dfa60768f06707dc59b0 Mon Sep 17 00:00:00 2001 From: ChillarAnand Date: Sat, 26 Sep 2015 21:56:34 +0530 Subject: [PATCH 303/666] Use attendee name & ticketno for file names --- junction/tickets/management/commands/sync_data.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/junction/tickets/management/commands/sync_data.py b/junction/tickets/management/commands/sync_data.py index d4e2d6fe..1d989ccc 100644 --- a/junction/tickets/management/commands/sync_data.py +++ b/junction/tickets/management/commands/sync_data.py @@ -46,4 +46,5 @@ def handle(self, *args, **options): if created: qr_code = qrcode.make(ticket_no) - qr_code.save('{}/{}.png'.format(settings.QR_CODES_DIR, ticket_no)) + file_name = attendee.get('name') + '_' + ticket_no + qr_code.save('{}/{}.png'.format(settings.QR_CODES_DIR, file_name)) From c3ec949a888896cc2457c391f797c504538bcf51 Mon Sep 17 00:00:00 2001 From: ChillarAnand Date: Sun, 27 Sep 2015 18:22:11 +0530 Subject: [PATCH 304/666] Add management command to fill data for given ticket nums `fill_data` management command takes input file which has a list of ticket numbers and outputs a csv with all details of given ticket numbers --- .../tickets/management/commands/fill_data.py | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 junction/tickets/management/commands/fill_data.py diff --git a/junction/tickets/management/commands/fill_data.py b/junction/tickets/management/commands/fill_data.py new file mode 100644 index 00000000..d928c815 --- /dev/null +++ b/junction/tickets/management/commands/fill_data.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, print_function, unicode_literals + +import os +import optparse + +# Third Party Stuff +from django.core.management.base import BaseCommand, CommandError +from django.db import transaction + +# Junction Stuff +from junction.tickets.models import Ticket + + +class Command(BaseCommand): + """ + Read a csv file containing ticket numbers and + fill all the details for it. + """ + option_list = BaseCommand.option_list + ( + optparse.make_option( + "-i", + "--infile", + dest = "filename", + help = "specify import file", + metavar = "FILE" + ), + ) + + option_list = option_list + ( + optparse.make_option( + "-o", + "--outfile", + dest = "category", + help = "specify output file name", + metavar = "FILE" + ), + ) + + @transaction.atomic + def handle(self, *args, **options): + if len(args) != 2: + raise CommandError('Usage: python manage.py fill_data ') + + in_file, out_file = args + ticket_nums = [line.rstrip('\n') for line in open(in_file).readlines()] + + fh = open(out_file, 'w') + header = ','.join(('ticket_num', 'name', 'email', 'address', '\n')) + fh.write(header) + + for ticket_num in ticket_nums: + ticket = Ticket.objects.get(ticket_no=ticket_num) + + details = ticket.others + for attendee in details['attendee']: + if attendee['ticketNo'] == ticket_num: + attendee = attendee + break + else: + attendee = {} + + if not ticket.address: + ticket.address = '' + data = data = ','.join((ticket_num, ticket.name, attendee['email'], ticket.address, '\n')) + fh.write(data) From c0f6668d64b0d8f098b0962b23ab86e80e01f1d9 Mon Sep 17 00:00:00 2001 From: ChillarAnand Date: Sun, 27 Sep 2015 18:24:27 +0530 Subject: [PATCH 305/666] Remove options from command line --- .../tickets/management/commands/fill_data.py | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/junction/tickets/management/commands/fill_data.py b/junction/tickets/management/commands/fill_data.py index d928c815..8437f7e3 100644 --- a/junction/tickets/management/commands/fill_data.py +++ b/junction/tickets/management/commands/fill_data.py @@ -1,9 +1,6 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, print_function, unicode_literals -import os -import optparse - # Third Party Stuff from django.core.management.base import BaseCommand, CommandError from django.db import transaction @@ -17,28 +14,9 @@ class Command(BaseCommand): Read a csv file containing ticket numbers and fill all the details for it. """ - option_list = BaseCommand.option_list + ( - optparse.make_option( - "-i", - "--infile", - dest = "filename", - help = "specify import file", - metavar = "FILE" - ), - ) - - option_list = option_list + ( - optparse.make_option( - "-o", - "--outfile", - dest = "category", - help = "specify output file name", - metavar = "FILE" - ), - ) - @transaction.atomic def handle(self, *args, **options): + if len(args) != 2: raise CommandError('Usage: python manage.py fill_data ') From 887e0a3608d5407fa085a90921719bc36431da93 Mon Sep 17 00:00:00 2001 From: ChillarAnand Date: Sun, 27 Sep 2015 18:43:32 +0530 Subject: [PATCH 306/666] Add more details to fill_data management command --- .../tickets/management/commands/fill_data.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/junction/tickets/management/commands/fill_data.py b/junction/tickets/management/commands/fill_data.py index 8437f7e3..0c045e88 100644 --- a/junction/tickets/management/commands/fill_data.py +++ b/junction/tickets/management/commands/fill_data.py @@ -24,8 +24,8 @@ def handle(self, *args, **options): ticket_nums = [line.rstrip('\n') for line in open(in_file).readlines()] fh = open(out_file, 'w') - header = ','.join(('ticket_num', 'name', 'email', 'address', '\n')) - fh.write(header) + header = ('Ticket Number', 'Name', 'Email', 'Gender', 'Designation', 'Company', 'City', 'Address') + fh.write(','.join(header) + '\n') for ticket_num in ticket_nums: ticket = Ticket.objects.get(ticket_no=ticket_num) @@ -40,5 +40,17 @@ def handle(self, *args, **options): if not ticket.address: ticket.address = '' - data = data = ','.join((ticket_num, ticket.name, attendee['email'], ticket.address, '\n')) - fh.write(data) + + if not attendee['details']: + gender = '' + designation = '' + city = '' + company = '' + else: + gender = attendee['details']['Gender'] + company = attendee['details']['Company/Organisation'] + designation = attendee['details']['Designation'] + city = attendee['details']['City'] + + data = (ticket_num, ticket.name, attendee['email'], gender, designation, company, city, ticket.address) + fh.write(','.join(data) + '\n') From 217725b4eab3bac8b5952afa5ee96fefba6214d4 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 27 Sep 2015 23:50:28 +0530 Subject: [PATCH 307/666] Add feeback viewing option --- junction/feedback/admin.py | 2 + junction/feedback/permissions.py | 11 ++++ junction/feedback/service.py | 49 ++++++++++++++ junction/feedback/views.py | 19 +++++- junction/proposals/views.py | 7 ++ junction/static/js/Chart.min.js | 11 ++++ junction/templates/base.html | 1 + junction/templates/feedback/detail.html | 66 +++++++++++++++++++ junction/templates/proposals/detail/base.html | 4 ++ junction/urls.py | 6 +- 10 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 junction/static/js/Chart.min.js create mode 100644 junction/templates/feedback/detail.html diff --git a/junction/feedback/admin.py b/junction/feedback/admin.py index eacac2cd..1bca4ce3 100644 --- a/junction/feedback/admin.py +++ b/junction/feedback/admin.py @@ -30,11 +30,13 @@ class ChoiceFeedbackQuestionValueAdmin(TimeAuditAdmin): class ScheduleItemTextFeedbackAdmin(TimeAuditAdmin): list_display = ('schedule_item', 'question', 'text', 'device') + \ TimeAuditAdmin.list_display # noqa + list_filter = ['schedule_item'] # noqa class ScheduleItemChoiceFeedbackAdmin(TimeAuditAdmin): list_display = ('schedule_item', 'question', 'value', 'device') + \ TimeAuditAdmin.list_display # noqa + list_filter = ['schedule_item'] # noqa admin.site.register(TextFeedbackQuestion, TextFeedbackQuestionAdmin) diff --git a/junction/feedback/permissions.py b/junction/feedback/permissions.py index d30b54ab..64aed85b 100644 --- a/junction/feedback/permissions.py +++ b/junction/feedback/permissions.py @@ -23,3 +23,14 @@ def has_permission(self, request, view): uuid=view.device_uuid).exists() return False return False + + +def can_view_feedback(user, schedule_item): + """Given a schedule item object, say a requesting user can view the + feedback. + """ + if user.is_superuser: + return True + + session = schedule_item.session + return session and session.author == user diff --git a/junction/feedback/service.py b/junction/feedback/service.py index c6c7ca57..1856c123 100644 --- a/junction/feedback/service.py +++ b/junction/feedback/service.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- from collections import defaultdict + +from django.db.models import Count from django.db import transaction, IntegrityError from django.core.exceptions import ObjectDoesNotExist @@ -12,6 +14,9 @@ ChoiceFeedbackQuestionValue) +COLORS = ["#F7464A", "#46BFBD", "#FDB45C"] + + def get_feedback_questions(conference_id): """Get all feedback questions for the conference. @@ -162,6 +167,50 @@ def create_choice_feedback(schedule_item_id, feedbacks, device): return choices +def get_feedback(schedule_item): + feedback = {'text': _get_text_feedback(schedule_item=schedule_item), + 'choices': _get_choice_feedback( + schedule_item=schedule_item)} + return feedback + + +def _get_text_feedback(schedule_item): + questions = TextFeedbackQuestion.objects.filter( + schedule_item_type__title=schedule_item.type) + text = [{'question': question, + 'values': ScheduleItemTextFeedback.objects.filter( + question=question, schedule_item=schedule_item)} + for question in questions] + return text + + +def _get_choice_feedback(schedule_item): + questions = ChoiceFeedbackQuestion.objects.filter( + schedule_item_type__title=schedule_item.type).select_related( + 'allowed_values') + choices = [] + for question in questions: + values = ScheduleItemChoiceFeedback.objects.filter( + schedule_item=schedule_item, question=question).values( + 'value').annotate(Count('value')) + d = {'question': question, + 'values': _get_choice_value_for_chart(question=question, + values=values)} + choices.append(d) + return choices + + +def _get_choice_value_for_chart(question, values): + data = [] + for index, value in enumerate(values): + d = {'label': str(question.allowed_values.get( + value=value['value']).title)} + d['value'] = value['value__count'] + d['color'] = COLORS[index] + data.append(d) + return data + + def _get_question_oragnized_by_type(qs): questions = defaultdict(list) for question in qs: diff --git a/junction/feedback/views.py b/junction/feedback/views.py index 769b779b..3bdcca1a 100644 --- a/junction/feedback/views.py +++ b/junction/feedback/views.py @@ -1,10 +1,15 @@ # -*- coding: utf-8 -*- +from django.shortcuts import get_object_or_404, render +from django.http import HttpResponseForbidden +#from django.http import Http403 + from rest_framework import views, status from rest_framework.response import Response +from junction.schedule.models import ScheduleItem from .serializers import FeedbackQueryParamsSerializer, FeedbackSerializer -from .permissions import CanSubmitFeedBack +from .permissions import CanSubmitFeedBack, can_view_feedback from . import service as feedback_service @@ -41,3 +46,15 @@ def post(self, request): return Response(status=status.HTTP_201_CREATED, data=data) return Response(data=feedback.errors, status=status.HTTP_400_BAD_REQUEST) + + +def view_feedback(request, schedule_item_id): + """Show text/choice feedback for the schedule. + """ + schedule_item = get_object_or_404(ScheduleItem, pk=schedule_item_id) + if not can_view_feedback(user=request.user, + schedule_item=schedule_item): + return HttpResponseForbidden("Access Denied") + feedback = feedback_service.get_feedback(schedule_item=schedule_item) + context = {'feedback': feedback, 'schedule_item': schedule_item} + return render(request, "feedback/detail.html", context) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 61825988..594ef30f 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -16,6 +16,7 @@ # Junction Stuff from junction.base.constants import ProposalReviewStatus, ProposalStatus, ConferenceStatus, ProposalUserVoteRole from junction.conferences.models import Conference, ConferenceProposalReviewer +from junction.feedback import permissions as feedback_permission from .forms import ( ProposalCommentForm, @@ -195,8 +196,14 @@ def detail_proposal(request, conference_slug, slug): 'is_author': request.user == proposal.author, 'is_reviewer': is_reviewer, 'is_section_reviewer': is_section_reviewer, + 'can_view_feedback': False } + if proposal.scheduleitem_set.all(): + schedule_item = proposal.scheduleitem_set.all()[0] + ctx['can_view_feedback'] = feedback_permission.can_view_feedback( + user=request.user, schedule_item=schedule_item) + ctx['schedule_item'] = schedule_item comments = ProposalComment.objects.filter( proposal=proposal, deleted=False, vote=False ) diff --git a/junction/static/js/Chart.min.js b/junction/static/js/Chart.min.js new file mode 100644 index 00000000..3a0a2c87 --- /dev/null +++ b/junction/static/js/Chart.min.js @@ -0,0 +1,11 @@ +/*! + * Chart.js + * http://chartjs.org/ + * Version: 1.0.2 + * + * Copyright 2015 Nick Downie + * Released under the MIT license + * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md + */ +(function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;var i=function(t,i){return t["offset"+i]?t["offset"+i]:document.defaultView.getComputedStyle(t).getPropertyValue(i)},e=this.width=i(t.canvas,"Width"),n=this.height=i(t.canvas,"Height");t.canvas.width=e,t.canvas.height=n;var e=this.width=t.canvas.width,n=this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,customTooltips:!1,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n=0;s--){var n=t[s];if(i(n))return n}},s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e}),c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof define&&define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},m=s.min=function(t){return Math.min.apply(Math,t)},v=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),S=s.radians=function(t){return t*(Math.PI/180)},x=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),y=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),C=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=m(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=y(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,v=Math.pow(10,u),S=Math.round(f/v);(S>a||a>2*S)&&!h;)if(S>a)v*=2,S=Math.round(f/v),S%1!==0&&(h=!0);else if(n&&u>=0){if(v/2%1!==0)break;v/=2,S=Math.round(f/v)}else v/=2,S=Math.round(f/v);return h&&(S=o,v=f/S),{steps:S,stepValue:v,min:p,max:p+S*v}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),w=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=C(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),st?-.5*s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e):s*Math.pow(2,-10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*t*t*(((i*=1.525)+1)*t-i):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-w.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t:2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*w.easeInBounce(2*t):.5*w.easeOutBounce(2*t-1)+.5}}),b=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),L=(s.animationLoop=function(t,i,e,s,n,o){var a=0,h=w[e]||w.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=b(l):n.apply(o)};b(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),k=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},F=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},L(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){k(t.chart.canvas,e,i)})}),R=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},T=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},A=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),M=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},W=s.fontString=function(t,i,e){return i+" "+t+"px "+e},z=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},B=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return M(this.chart),this},stop:function(){return P(this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=R(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:T(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,A(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return C(this.options.legendTemplate,this)},destroy:function(){this.clear(),F(this,this.events);var t=this.chart.canvas;t.width=this.chart.width,t.height=this.chart.height,t.style.removeProperty?(t.style.removeProperty("width"),t.style.removeProperty("height")):(t.style.removeAttribute("width"),t.style.removeAttribute("height")),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),this.options.customTooltips&&this.options.customTooltips(!1),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(){var t,i,e,n,o,a=[],l=[],r=[];return s.each(this.datasets,function(i){t=i.points||i.bars||i.segments,t[h]&&t[h].hasValue()&&a.push(t[h])}),s.each(a,function(t){l.push(t.x),r.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),o=m(r),e=g(r),n=m(l),i=g(l),{x:n>this.chart.width/2?n:i,y:(o+e)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx,custom:this.options.customTooltips}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:C(this.options.tooltipTemplate,t),chart:this.chart,custom:this.options.customTooltips}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return f(this.value)}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=this.caretPadding=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;if(t.fillStyle=this.fillColor,this.custom)this.custom(this);else{switch(this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}B(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=W(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=z(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){if(this.custom)this.custom(this);else{B(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?z(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),tthis.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=z(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(S(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(S(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/Math.max(this.valuesCount-(this.offsetGridLines?0:1),1),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a),l=this.showHorizontalLines;t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),0!==o||l||(l=!0),l&&t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),l&&(t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+x(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+x(this.lineWidth),o=this.xLabelRotation>0,a=this.showVerticalLines;0!==e||a||(a=!0),a&&t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),a&&(t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*S(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=m([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=m([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;ip&&(p=t.x+s,n=i),t.x-sp&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;t.textAlign=0===i?"center":i===a?"center":a>i?"left":"right",t.textBaseline=r?"middle":l?"bottom":"top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'
    <% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
'};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.bars.push(new this.BarClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<% for (var i=0; i
  • <%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>'};i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(Math.abs(t)/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=Math.abs(t.value)},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)0&&ithis.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.ythis.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'
      <% for (var i=0; i
    • <%if(segments[i].label){%><%=segments[i].label%><%}%>
    • <%}%>
    '};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this); \ No newline at end of file diff --git a/junction/templates/base.html b/junction/templates/base.html index 10c257d9..02007058 100644 --- a/junction/templates/base.html +++ b/junction/templates/base.html @@ -63,6 +63,7 @@ + {% block endhead %} {% endblock %} diff --git a/junction/templates/feedback/detail.html b/junction/templates/feedback/detail.html new file mode 100644 index 00000000..de6e32df --- /dev/null +++ b/junction/templates/feedback/detail.html @@ -0,0 +1,66 @@ +{% extends 'base.html' %} +{% load bootstrap3 %} +{% load django_markdown %} +{% load static from staticfiles %} +{% load django_bootstrap_breadcrumbs %} + +{% block head_title %}{{ schedule_item.name }} {% endblock %} +{% block og_title %}{{ schedule_item.name }} {% endblock %} + +{% block endhead %} + + +{% endblock %} + +{% block breadcrumbs %} + {{ block.super }} + {% breadcrumb schedule_item.conference.name "conference-detail" schedule_item.conference.slug %} +{% endblock %} + +{% block navbar_logo %} + {% if schedule_item.conference.logo %} + + + + {% else %} + {{ schedule_item.conference.name }} + {% endif %} +{% endblock navbar_logo %} + +{% block content %} +

    {{ schedule_item.name }} - Feedback

    +
    + {% for choice_feedback in feedback.choices %} +
    +

    {{ choice_feedback.question.title }}

    +
    + {% if choice_feedback.values %} + + + + {% else %} +

    No feedback submitted

    + {% endif %} +
    + {% endfor %} +
    + {% for txt in feedback.text %} +
    +

    {{ txt.question.title }}

    +
    + {% for value in txt.values %} +
    +

    {{ value.text|markdown }}

    +
    +
    + {% empty %} +

    No feedback submitted

    + {% endfor %} + {% endfor %} +
    +{% endblock content %} diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index d0b582de..502f7d23 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -132,6 +132,10 @@

    Content URLs:

    Ask proposer to upload content + {% if schedule_item %} + Participants Feedback + {% endif %}
    {% endif %} diff --git a/junction/urls.py b/junction/urls.py index 58aa268e..f73ab1e3 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -13,7 +13,7 @@ from junction.conferences import views as conference_views from junction.devices.views import DeviceListApiView, DeviceDetailApiView from junction.feedback.views import (FeedbackQuestionListApiView, - FeedbackListApiView) + FeedbackListApiView, view_feedback) from junction.schedule.views import non_proposal_schedule_item_view @@ -58,7 +58,9 @@ url(r'^(?P[\w-]+)/dashboard/votes/export/$', 'junction.proposals.dashboard.export_reviewer_votes', name='export-reviewer-votes'), - + url(r'^feedback/(?P\d+)/$', + view_feedback, + name='feedback-detail'), url(r'^schedule_item/(?P\d+)/$', non_proposal_schedule_item_view, name="schedule-item"), From b4559e0317cdb46856aa8785212572644b0d76d5 Mon Sep 17 00:00:00 2001 From: ChillarAnand Date: Mon, 28 Sep 2015 14:58:32 +0530 Subject: [PATCH 308/666] Skip invalid tickets --- junction/tickets/management/commands/fill_data.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/junction/tickets/management/commands/fill_data.py b/junction/tickets/management/commands/fill_data.py index 0c045e88..e8fcb427 100644 --- a/junction/tickets/management/commands/fill_data.py +++ b/junction/tickets/management/commands/fill_data.py @@ -2,6 +2,7 @@ from __future__ import absolute_import, print_function, unicode_literals # Third Party Stuff +from django.core.exceptions import ObjectDoesNotExist from django.core.management.base import BaseCommand, CommandError from django.db import transaction @@ -28,7 +29,10 @@ def handle(self, *args, **options): fh.write(','.join(header) + '\n') for ticket_num in ticket_nums: - ticket = Ticket.objects.get(ticket_no=ticket_num) + try: + ticket = Ticket.objects.get(ticket_no=ticket_num) + except ObjectDoesNotExist: + continue details = ticket.others for attendee in details['attendee']: From 72071c7c205a18ed33d5380632770f6a5e1feec8 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Tue, 29 Sep 2015 22:18:47 +0530 Subject: [PATCH 309/666] Print log message --- junction/tickets/management/commands/fill_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/tickets/management/commands/fill_data.py b/junction/tickets/management/commands/fill_data.py index e8fcb427..27c0614d 100644 --- a/junction/tickets/management/commands/fill_data.py +++ b/junction/tickets/management/commands/fill_data.py @@ -32,7 +32,7 @@ def handle(self, *args, **options): try: ticket = Ticket.objects.get(ticket_no=ticket_num) except ObjectDoesNotExist: - continue + print(u"Ticket num: {} not found".format(ticket_num)) details = ticket.others for attendee in details['attendee']: From 50f23949ca06fcd5ed30eb18769e0944a8b8e682 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 3 Oct 2015 22:50:09 +0530 Subject: [PATCH 310/666] Interchange feedback choice item color --- junction/feedback/service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/feedback/service.py b/junction/feedback/service.py index 1856c123..389a5eb5 100644 --- a/junction/feedback/service.py +++ b/junction/feedback/service.py @@ -14,7 +14,7 @@ ChoiceFeedbackQuestionValue) -COLORS = ["#F7464A", "#46BFBD", "#FDB45C"] +COLORS = ["#46BFBD", "#FDB45C", "#F7464A"] def get_feedback_questions(conference_id): From fc59305daad89ce3ce76f5e4ca5a5905b39caa1c Mon Sep 17 00:00:00 2001 From: Sijo Jose Date: Sat, 24 Oct 2015 14:32:31 +0530 Subject: [PATCH 311/666] hange Reviewers heading to Reviews in comments section. #288 --- junction/templates/proposals/detail/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index 502f7d23..d36d99a1 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -207,7 +207,7 @@

    Reviewer Actions:

    {% endif %} From 5a8c46b7431da261dd3035f40976e2bc10c0a496 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 25 Oct 2015 16:11:20 +0530 Subject: [PATCH 312/666] Allow reviewers to view the feedback --- junction/conferences/permissions.py | 13 +++++++++++++ junction/feedback/permissions.py | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 junction/conferences/permissions.py diff --git a/junction/conferences/permissions.py b/junction/conferences/permissions.py new file mode 100644 index 00000000..d48892f3 --- /dev/null +++ b/junction/conferences/permissions.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- + +from .models import ConferenceProposalReviewer + + +def is_reviewer(user, conference): + if not user.is_authenticated(): + return False + + reviewer = ConferenceProposalReviewer.objects.filter( + reviewer=user, conference=conference, + active=True).exists() + return reviewer diff --git a/junction/feedback/permissions.py b/junction/feedback/permissions.py index 64aed85b..c71d7d8b 100644 --- a/junction/feedback/permissions.py +++ b/junction/feedback/permissions.py @@ -5,6 +5,7 @@ from rest_framework import permissions from junction.devices.models import Device +from junction.conferences.permissions import is_reviewer def get_authorization_header(request): @@ -33,4 +34,5 @@ def can_view_feedback(user, schedule_item): return True session = schedule_item.session - return session and session.author == user + res = is_reviewer(user=user, conference=schedule_item.conference) + return session and (session.author == user or res) From e2b8cc0b067085a4f170eeea06a3f0d8b1418498 Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Wed, 16 Dec 2015 11:06:29 +0530 Subject: [PATCH 313/666] Added python 2 to 3 changes Signed-off-by: Abhijeet Kasurde --- .travis.yml | 1 + .../conferences/management/commands/sample_data.py | 3 ++- junction/conferences/tasks.py | 2 +- junction/devices/views.py | 4 ++-- junction/feedback/service.py | 2 +- junction/feedback/views.py | 2 +- junction/proposals/dashboard.py | 5 ++++- junction/proposals/forms.py | 2 +- junction/tickets/management/commands/explara.py | 2 +- tests/factories.py | 2 +- tests/integrations/test_feedback_api.py | 11 +++++++---- tests/integrations/test_feedback_service.py | 2 +- tests/integrations/test_google_analytics.py | 4 ++-- tests/utils.py | 2 +- 14 files changed, 26 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5bfc86a0..5bd80249 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: python sudo: false python: - '2.7' +- '3.4' addons: postgresql: "9.3" diff --git a/junction/conferences/management/commands/sample_data.py b/junction/conferences/management/commands/sample_data.py index 1e42cdc8..aca8af4a 100644 --- a/junction/conferences/management/commands/sample_data.py +++ b/junction/conferences/management/commands/sample_data.py @@ -26,6 +26,7 @@ ProposalSectionReviewerVoteValue ) from junction.schedule.models import ScheduleItem +import six NUM_USERS = getattr(settings, "NUM_USERS", 10) NUM_CONFERENCES = getattr(settings, "NUM_CONFERENCES", 4) @@ -167,7 +168,7 @@ def create_scheduled_item(self, proposal, conference=None): kwargs['start_time'] = datetime.datetime.time(datetime.datetime.now()) kwargs['end_time'] = datetime.datetime.time( datetime.datetime.now() + datetime.timedelta(minutes=45)) - if isinstance(proposal, basestring): + if isinstance(proposal, six.string_types): ScheduleItem.objects.create( alt_name=proposal, **kwargs) diff --git a/junction/conferences/tasks.py b/junction/conferences/tasks.py index 7d1a0b2b..26969c68 100644 --- a/junction/conferences/tasks.py +++ b/junction/conferences/tasks.py @@ -8,4 +8,4 @@ @shared_task def add(x, y): # dummy task - print x + y + print(x + y) diff --git a/junction/devices/views.py b/junction/devices/views.py index d5b18c23..e23d1bc4 100644 --- a/junction/devices/views.py +++ b/junction/devices/views.py @@ -14,7 +14,7 @@ from .models import Device from .serializers import (DeviceRegistrationSerializer, DeviceConfirmationSerializer) - +from six.moves import range # Create your views here. @@ -23,7 +23,7 @@ def _create_device(self, data): if os.environ.get('TESTING'): code = settings.DEVICE_VERIFICATION_CODE else: - code = random.choice(range(10000, 99999)) + code = random.choice(list(range(10000, 99999))) device = Device.objects.create(uuid=data['uuid'], verification_code=code) return device diff --git a/junction/feedback/service.py b/junction/feedback/service.py index 389a5eb5..a7436a9e 100644 --- a/junction/feedback/service.py +++ b/junction/feedback/service.py @@ -224,7 +224,7 @@ def _merge_questions(text_questions, choice_questions): {'Talk': {'text': [..], 'choice': [...]},} """ types = set(text_questions.keys()) - types.union(choice_questions.keys()) + types.union(list(choice_questions.keys())) questions = {} for item in types: questions[item] = {'text': text_questions.get(item), diff --git a/junction/feedback/views.py b/junction/feedback/views.py index 3bdcca1a..d2c8f9af 100644 --- a/junction/feedback/views.py +++ b/junction/feedback/views.py @@ -2,7 +2,7 @@ from django.shortcuts import get_object_or_404, render from django.http import HttpResponseForbidden -#from django.http import Http403 +# from django.http import Http403 from rest_framework import views, status from rest_framework.response import Response diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index 6375d806..df820079 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -9,7 +9,10 @@ from django.shortcuts import get_object_or_404, render from django.views.decorators.http import require_http_methods -import cStringIO as StringIO +try: + import cStringIO as StringIO +except ImportError: + from io import StringIO from junction.base.constants import ProposalReviewVote, ProposalStatus, ProposalVotesFilter from junction.conferences.models import Conference, ConferenceProposalReviewer from xlsxwriter.workbook import Workbook diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index c4091ad3..8b807f69 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -195,5 +195,5 @@ def __init__(self, conference, *args, **kwargs): self.fields['votes'].choices = ProposalVotesFilter.CHOICES self.fields['review_status'].choices = ProposalReviewStatus.CHOICES - for name, field in self.fields.items(): + for name, field in list(self.fields.items()): field.choices.insert(0, ('all', 'All')) diff --git a/junction/tickets/management/commands/explara.py b/junction/tickets/management/commands/explara.py index cc471b9e..c088467a 100644 --- a/junction/tickets/management/commands/explara.py +++ b/junction/tickets/management/commands/explara.py @@ -48,7 +48,7 @@ def get_orders(self, explara_eventid): ticket_orders.extend([order for order in attendee_response.get('attendee')]) # after the first batch, subsequent batches are dicts with batch no. as key. elif isinstance(attendee_response.get('attendee'), dict): - ticket_orders.extend([order for order_idx, order in attendee_response.get('attendee').items()]) + ticket_orders.extend([order for order_idx, order in list(attendee_response.get('attendee').items())]) print("Synced {} records".format(to_record)) from_record = to_record to_record += 50 diff --git a/tests/factories.py b/tests/factories.py index f9dffecf..6b9169ee 100644 --- a/tests/factories.py +++ b/tests/factories.py @@ -50,7 +50,7 @@ class Meta: start_date = fuzzy.FuzzyDate(datetime.date.today(), datetime.date(2017, 1, 1)).fuzz() end_date = start_date + datetime.timedelta(3) # logo - status = factory.Iterator(dict(ConferenceStatus.CHOICES).keys()) + status = factory.Iterator(list(dict(ConferenceStatus.CHOICES).keys())) # deleted diff --git a/tests/integrations/test_feedback_api.py b/tests/integrations/test_feedback_api.py index 07f8535e..9f62e380 100644 --- a/tests/integrations/test_feedback_api.py +++ b/tests/integrations/test_feedback_api.py @@ -14,6 +14,9 @@ class TestFeedbackQuestionListApi(APITestCase): + def setUp(self): + self.schedule_item_types = ['Talk', 'Workshop'] + def test_get_questions_without_conference(self): res = self.client.get('/api/v1/feedback_questions/?conference_id=23') @@ -21,11 +24,10 @@ def test_get_questions_without_conference(self): assert res.data == {} def test_get_questions(self): - schedule_item_types = ['Workshop', 'Talk'] num_choice_questions = 2 num_text_questions = 1 objects = factories.create_feedback_questions( - schedule_item_types=schedule_item_types, + schedule_item_types=self.schedule_item_types, num_text_questions=num_text_questions, num_choice_questions=num_choice_questions) conference = objects['conference'] @@ -37,8 +39,9 @@ def test_get_questions(self): assert res.status_code == status.HTTP_200_OK result = res.data - assert result.keys() == schedule_item_types - for item_type in schedule_item_types: + for rest in list(result.keys()): + assert rest in self.schedule_item_types + for item_type in self.schedule_item_types: assert len(result[item_type]['text']) == num_text_questions assert len(result[item_type]['choice']) == num_choice_questions diff --git a/tests/integrations/test_feedback_service.py b/tests/integrations/test_feedback_service.py index e19888b9..951e0c7b 100644 --- a/tests/integrations/test_feedback_service.py +++ b/tests/integrations/test_feedback_service.py @@ -26,7 +26,7 @@ def test_get_feedback_questions_with_conference(): conference = objects['conference'] result = service.get_feedback_questions(conference_id=conference.id) - assert result.keys() == schedule_item_types + assert list(result.keys()) == schedule_item_types for item_type in schedule_item_types: assert len(result[item_type]['text']) == num_text_questions assert len(result[item_type]['choice']) == num_choice_questions diff --git a/tests/integrations/test_google_analytics.py b/tests/integrations/test_google_analytics.py index aee3e27a..a5d0af8a 100644 --- a/tests/integrations/test_google_analytics.py +++ b/tests/integrations/test_google_analytics.py @@ -9,8 +9,8 @@ def test_google_analytics_rendering(client, settings): url = reverse('pages:homepage') response = client.get(url) - assert 'UA-MY-ID' not in response.content + assert b'UA-MY-ID' not in response.content settings.SITE_VARIABLES['google_analytics_id'] = 'UA-MY-ID' response = client.get(url) - assert 'UA-MY-ID' in response.content + assert b'UA-MY-ID' in response.content diff --git a/tests/utils.py b/tests/utils.py index 53a1bde7..556b64b1 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -61,7 +61,7 @@ def wrapper(*args, **kwargs): def override_settings(new_settings): old_settings = {} - for name, new_value in new_settings.items(): + for name, new_value in list(new_settings.items()): old_settings[name] = getattr(settings, name, None) setattr(settings, name, new_value) return old_settings From 543bd00fb0d490c40be043cba72f021fc37204ae Mon Sep 17 00:00:00 2001 From: Fayaz Yusuf Khan Date: Sat, 19 Dec 2015 12:12:29 +0530 Subject: [PATCH 314/666] added requires.io badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fadcff98..4c8e069b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ junction [![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy) [![Build Status](https://travis-ci.org/pythonindia/junction.svg)](https://travis-ci.org/pythonindia/junction) [![Coverage Status](https://coveralls.io/repos/pythonindia/junction/badge.svg?branch=master)](https://coveralls.io/r/pythonindia/junction?branch=master) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pythonindia/junction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Requirements Status](https://requires.io/github/pythonindia/junction/requirements.svg?branch=master)](https://requires.io/github/pythonindia/junction/requirements/?branch=master) **Version**: 0.2.0-dev From f3ee331396e480bf2a1905a15ed3636deea882ca Mon Sep 17 00:00:00 2001 From: Sijo Jose Date: Sat, 19 Dec 2015 15:31:39 +0530 Subject: [PATCH 315/666] Allow voting for proposal till conference start date --- junction/proposals/views.py | 8 ++++-- junction/templates/proposals/detail/base.html | 26 ++++++++++++++----- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 594ef30f..904a9ed0 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -3,6 +3,7 @@ # Standard Library import collections +from datetime import datetime # Third Party Stuff from django.conf import settings @@ -178,7 +179,7 @@ def detail_proposal(request, conference_slug, slug): is_reviewer = _is_proposal_reviewer(request.user, conference) is_section_reviewer = _is_proposal_section_reviewer(request.user, conference, proposal) vote_value = 0 - + voting = True if conference.start_date > datetime.now().date() else False try: if request.user.is_authenticated(): proposal_vote = ProposalVote.objects.get( @@ -196,7 +197,8 @@ def detail_proposal(request, conference_slug, slug): 'is_author': request.user == proposal.author, 'is_reviewer': is_reviewer, 'is_section_reviewer': is_section_reviewer, - 'can_view_feedback': False + 'can_view_feedback': False, + 'can_vote':voting } if proposal.scheduleitem_set.all(): @@ -503,6 +505,8 @@ def create_proposal_comment(request, conference_slug, proposal_slug): @login_required def proposal_vote(request, conference_slug, proposal_slug, up_vote): conference = get_object_or_404(Conference, slug=conference_slug) + if conference.start_date < datetime.now().date(): + raise PermissionDenied proposal = get_object_or_404( Proposal, slug=proposal_slug, conference=conference) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index d36d99a1..0556a2e0 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -89,21 +89,33 @@


    -
    -
    +
    - + {% if can_vote %} + - - + + {% else %} + + + + {% endif %}

    {{ proposal.get_votes_count }}

    - + {% if can_vote %} + - + + {% else %} + + + + {% endif %} + +
    From 1528851a2388292678524de9e654778dbfda2fec Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 19 Dec 2015 16:12:04 +0530 Subject: [PATCH 316/666] Organize code into different views and permissions --- junction/proposals/comments_views.py | 56 ++++++ junction/proposals/permissions.py | 41 ++++ junction/proposals/urls.py | 14 +- junction/proposals/views.py | 285 ++++----------------------- junction/proposals/votes_views.py | 178 +++++++++++++++++ 5 files changed, 322 insertions(+), 252 deletions(-) create mode 100644 junction/proposals/comments_views.py create mode 100644 junction/proposals/permissions.py create mode 100644 junction/proposals/votes_views.py diff --git a/junction/proposals/comments_views.py b/junction/proposals/comments_views.py new file mode 100644 index 00000000..615bb88e --- /dev/null +++ b/junction/proposals/comments_views.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +from django.conf import settings +from django.contrib.auth.decorators import login_required +from django.views.decorators.http import require_http_methods +from django.shortcuts import Http404, get_object_or_404 +from django.http.response import HttpResponseRedirect +from django.core.urlresolvers import reverse + +from junction.conferences.models import Conference + +from .models import Proposal, ProposalComment + +from .forms import ProposalCommentForm +from .services import send_mail_for_new_comment + +from . import permissions + + +@login_required +@require_http_methods(['POST']) +def create_proposal_comment(request, conference_slug, proposal_slug): + conference = get_object_or_404(Conference, slug=conference_slug) + proposal = get_object_or_404( + Proposal, slug=proposal_slug, conference=conference) + form = ProposalCommentForm(request.POST) + if form.is_valid(): + comment = form.cleaned_data['comment'] + private = form.cleaned_data['private'] + reviewer = form.cleaned_data['reviewer'] + + has_perm = permissions.is_proposal_author_or_proposal_section_reviewer( + user=request.user, conference=conference, proposal=proposal) + + if private and not has_perm: + raise Http404() + + proposal_comment = ProposalComment.objects.create( + proposal=proposal, comment=comment, + private=private, reviewer=reviewer, commenter=request.user + ) + host = '{}://{}'.format(settings.SITE_PROTOCOL, + request.META['HTTP_HOST']) + send_mail_for_new_comment(proposal_comment, host) + + redirect_url = reverse('proposal-detail', + args=[conference.slug, proposal.slug]) + + if private: + redirect_url += "#js-reviewers" + elif reviewer: + redirect_url += "#js-only-reviewers" + else: + redirect_url += "#js-comments" + + return HttpResponseRedirect(redirect_url) diff --git a/junction/proposals/permissions.py b/junction/proposals/permissions.py new file mode 100644 index 00000000..d3319d8f --- /dev/null +++ b/junction/proposals/permissions.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- + +from django.core.exceptions import PermissionDenied +from junction.conferences.models import ConferenceProposalReviewer + +from .models import ProposalSectionReviewer + + +def is_proposal_author(user, proposal): + return user.is_authenticated() and proposal.author == user + + +def is_proposal_reviewer(user, conference): + is_reviewer = ConferenceProposalReviewer.objects.filter( + reviewer=user, conference=conference, active=True).exists() + return user.is_authenticated() and is_reviewer + + +def is_proposal_section_reviewer(user, conference, proposal): + return user.is_authenticated() and ProposalSectionReviewer.objects.filter( + conference_reviewer__reviewer=user, + conference_reviewer__conference=conference, + proposal_section=proposal.proposal_section, + active=True).exists() + + +def is_proposal_author_or_proposal_reviewer(user, conference, proposal): + return is_proposal_author(user, proposal) or \ + is_proposal_reviewer(user, conference) + + +def is_proposal_author_or_proposal_section_reviewer(user, + conference, proposal): + return is_proposal_author(user, proposal) or \ + is_proposal_section_reviewer(user, conference, proposal) + + +def is_proposal_author_or_permisson_denied(user, proposal): + if is_proposal_author(user, proposal): + return True + raise PermissionDenied diff --git a/junction/proposals/urls.py b/junction/proposals/urls.py index 4c3ae0d6..fea6077a 100644 --- a/junction/proposals/urls.py +++ b/junction/proposals/urls.py @@ -4,16 +4,16 @@ # Third Party Stuff from django.conf.urls import include, patterns, url -from . import views +from . import (views, votes_views, comments_views) comment_urls = patterns( '', url(r'^(?P[\w-]+)/create/$', - views.create_proposal_comment, name='proposal-comment-create'), + comments_views.create_proposal_comment, name='proposal-comment-create'), url(r'^(?P[\w-]+)/comments/(?P\d+)/up-vote/$', - views.proposal_comment_up_vote, name='proposal-comment-up-vote'), + votes_views.proposal_comment_up_vote, name='proposal-comment-up-vote'), url(r'^(?P[\w-]+)/comments/(?P\d+)/down-vote/$', - views.proposal_comment_down_vote, name='proposal-comment-down-vote'), + votes_views.proposal_comment_down_vote, name='proposal-comment-down-vote'), ) urlpatterns = patterns( @@ -32,7 +32,7 @@ url(r'^comment/', include(comment_urls)), # Voting - url(r'^(?P[\w-]+)/vote/$', views.proposal_reviewer_vote, name='proposal-reviewer-vote'), - url(r'^(?P[\w-]+)/down-vote/$', views.proposal_vote_down, name='proposal-vote-down'), - url(r'^(?P[\w-]+)/up-vote/$', views.proposal_vote_up, name='proposal-vote-up'), + url(r'^(?P[\w-]+)/vote/$', votes_views.proposal_reviewer_vote, name='proposal-reviewer-vote'), + url(r'^(?P[\w-]+)/down-vote/$', votes_views.proposal_vote_down, name='proposal-vote-down'), + url(r'^(?P[\w-]+)/up-vote/$', votes_views.proposal_vote_up, name='proposal-vote-up'), ) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 594ef30f..7c921309 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -10,62 +10,36 @@ from django.core.exceptions import PermissionDenied from django.core.urlresolvers import reverse from django.http.response import HttpResponse, HttpResponseRedirect -from django.shortcuts import Http404, get_object_or_404, render +from django.shortcuts import get_object_or_404, render from django.views.decorators.http import require_http_methods # Junction Stuff -from junction.base.constants import ProposalReviewStatus, ProposalStatus, ConferenceStatus, ProposalUserVoteRole -from junction.conferences.models import Conference, ConferenceProposalReviewer + +from junction.base.constants import (ProposalReviewStatus, + ProposalStatus, + ConferenceStatus) +from junction.conferences.models import Conference + from junction.feedback import permissions as feedback_permission from .forms import ( ProposalCommentForm, ProposalForm, ProposalReviewForm, - ProposalReviewerVoteForm, ProposalsToReviewForm ) from .models import ( Proposal, ProposalComment, - ProposalCommentVote, ProposalSectionReviewer, - ProposalVote, - ProposalSectionReviewerVote, - ProposalSectionReviewerVoteValue + ProposalVote ) from .services import ( - send_mail_for_new_comment, send_mail_for_new_proposal, send_mail_for_proposal_content, ) - -def _is_proposal_author(user, proposal): - return user.is_authenticated() and proposal.author == user - - -def _is_proposal_reviewer(user, conference): - return user.is_authenticated() and ConferenceProposalReviewer.objects.filter( - reviewer=user, conference=conference, active=True).exists() - - -def _is_proposal_section_reviewer(user, conference, proposal): - return user.is_authenticated() and ProposalSectionReviewer.objects.filter( - conference_reviewer__reviewer=user, - conference_reviewer__conference=conference, - proposal_section=proposal.proposal_section, - active=True).exists() - - -def _is_proposal_author_or_proposal_reviewer(user, conference, proposal): - return _is_proposal_author(user, proposal) or \ - _is_proposal_reviewer(user, conference) - - -def _is_proposal_author_or_proposal_section_reviewer(user, conference, proposal): - return _is_proposal_author(user, proposal) or \ - _is_proposal_section_reviewer(user, conference, proposal) +from . import permissions @require_http_methods(['GET']) @@ -78,7 +52,8 @@ def list_proposals(request, conference_slug): 'proposal_type', 'proposal_section', 'conference', 'author', ).filter(conference=conference) - is_reviewer = _is_proposal_reviewer(request.user, conference) + is_reviewer = permissions.is_proposal_reviewer( + user=request.user, conference=conference) # Filtering proposal_section_filter = request.GET.getlist('proposal_section') @@ -171,12 +146,13 @@ def create_proposal(request, conference_slug): def detail_proposal(request, conference_slug, slug): conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=slug, conference=conference) - read_private_comment = _is_proposal_author_or_proposal_reviewer( + read_private_comment = permissions.is_proposal_author_or_proposal_reviewer( + request.user, conference, proposal) + write_private_comment = permissions.is_proposal_author_or_proposal_section_reviewer( request.user, conference, proposal) - write_private_comment = _is_proposal_author_or_proposal_section_reviewer( + is_reviewer = permissions.is_proposal_reviewer(request.user, conference) + is_section_reviewer = permissions.is_proposal_section_reviewer( request.user, conference, proposal) - is_reviewer = _is_proposal_reviewer(request.user, conference) - is_section_reviewer = _is_proposal_section_reviewer(request.user, conference, proposal) vote_value = 0 try: @@ -229,7 +205,8 @@ def update_proposal(request, conference_slug, slug): conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=slug, conference=conference) - if not proposal.author == request.user: + if not permissions.is_proposal_author( + user=request.user, proposal=proposal): raise PermissionDenied if request.method == 'GET': @@ -266,20 +243,21 @@ def update_proposal(request, conference_slug, slug): def proposals_to_review(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) - if not _is_proposal_reviewer(request.user, conference): + if not permissions.is_proposal_reviewer(request.user, conference): raise PermissionDenied proposals_qs = Proposal.objects.select_related( 'proposal_type', 'proposal_section', 'conference', 'author', ).filter(conference=conference).filter(status=ProposalStatus.PUBLIC) - proposal_reviewer_sections = [p.proposal_section for p in - ProposalSectionReviewer.objects.filter( - conference_reviewer__reviewer=request.user)] + psr = ProposalSectionReviewer.objects.filter( + conference_reviewer__reviewer=request.user) + proposal_reviewer_sections = [p.proposal_section for p in psr] proposals_to_review = [] s_items = collections.namedtuple('section_items', 'section proposals') for section in proposal_reviewer_sections: - section_proposals = [p for p in proposals_qs if p.proposal_section == section] + section_proposals = [p for p in proposals_qs + if p.proposal_section == section] proposals_to_review.append(s_items(section, section_proposals)) proposal_sections = conference.proposal_sections.all() @@ -303,14 +281,16 @@ def review_proposal(request, conference_slug, slug): conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=slug, conference=conference) - if not _is_proposal_section_reviewer(request.user, conference, proposal): + if not permissions.is_proposal_section_reviewer(request.user, + conference, proposal): raise PermissionDenied if request.method == 'GET': + comments = ProposalComment.objects.filter(proposal=proposal, + deleted=False) - comments = ProposalComment.objects.filter(proposal=proposal, deleted=False,) - - proposal_review_form = ProposalReviewForm(initial={'review_status': proposal.review_status}) + proposal_review_form = ProposalReviewForm( + initial={'review_status': proposal.review_status}) ctx = { 'proposal': proposal, @@ -328,15 +308,17 @@ def review_proposal(request, conference_slug, slug): # POST Workflow form = ProposalReviewForm(request.POST) if not form.is_valid(): - return render(request, 'proposals/review.html', {'form': form, - 'proposal': proposal, - 'form_errors': form.errors}) + context = {'form': form, + 'proposal': proposal, + 'form_errors': form.errors} + return render(request, 'proposals/review.html', context) # Valid Form proposal.review_status = form.cleaned_data['review_status'] proposal.save() - return HttpResponseRedirect(reverse('proposals-list', args=[conference.slug])) + return HttpResponseRedirect(reverse('proposals-list', + args=[conference.slug])) @login_required @@ -345,7 +327,8 @@ def proposal_upload_content(request, conference_slug, slug): conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=slug, conference=conference) - if not (_is_proposal_section_reviewer(request.user, conference, proposal) or + if not (permissions.is_proposal_section_reviewer( + request.user, conference, proposal) or request.user.is_superuser): raise PermissionDenied @@ -360,102 +343,14 @@ def proposal_upload_content(request, conference_slug, slug): return HttpResponse(message) -@login_required -@require_http_methods(['GET', 'POST']) -def proposal_reviewer_vote(request, conference_slug, proposal_slug): - conference = get_object_or_404(Conference, slug=conference_slug) - proposal = get_object_or_404(Proposal, slug=proposal_slug, - conference=conference) - - if not _is_proposal_section_reviewer(request.user, conference, proposal): - raise PermissionDenied - - vote_value = None - - try: - vote = ProposalSectionReviewerVote.objects.get( - proposal=proposal, - voter=ProposalSectionReviewer.objects.get( - conference_reviewer__reviewer=request.user, - conference_reviewer__conference=conference, - proposal_section=proposal.proposal_section), - ) - vote_value = vote.vote_value.vote_value - except ProposalSectionReviewerVote.DoesNotExist: - vote = None - - try: - vote_comment = ProposalComment.objects.get( - proposal=proposal, - commenter=request.user, - vote=True, - deleted=False, - ) - except: - vote_comment = None - if request.method == 'GET': - if vote_comment: - proposal_vote_form = ProposalReviewerVoteForm( - initial={'vote_value': vote_value, - 'comment': vote_comment.comment}) - else: - proposal_vote_form = ProposalReviewerVoteForm( - initial={'vote_value': vote_value}) - ctx = { - 'proposal': proposal, - 'proposal_vote_form': proposal_vote_form, - 'vote': vote, - } - - return render(request, 'proposals/vote.html', ctx) - - # POST Workflow - form = ProposalReviewerVoteForm(request.POST) - if not form.is_valid(): - return render(request, 'proposals/vote.html', - {'form': form, - 'proposal': proposal, - 'form_errors': form.errors}) - - # Valid Form - vote_value = form.cleaned_data['vote_value'] - comment = form.cleaned_data['comment'] - if not vote: - vote = ProposalSectionReviewerVote.objects.create( - proposal=proposal, - voter=ProposalSectionReviewer.objects.get( - conference_reviewer__reviewer=request.user, - conference_reviewer__conference=conference, - proposal_section=proposal.proposal_section), - vote_value=ProposalSectionReviewerVoteValue.objects.get( - vote_value=vote_value), - ) - else: - vote.vote_value = ProposalSectionReviewerVoteValue.objects.get( - vote_value=vote_value) - vote.save() - if not vote_comment: - vote_comment = ProposalComment.objects.create( - proposal=proposal, - commenter=request.user, - comment=comment, - vote=True, - ) - else: - vote_comment.comment = comment - vote_comment.save() - return HttpResponseRedirect(reverse('proposals-to-review', - args=[conference.slug])) - - @login_required @require_http_methods(['GET', 'POST']) def delete_proposal(request, conference_slug, slug): conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=slug, conference=conference) - if not proposal.author == request.user: - raise PermissionDenied + permissions.is_proposal_author_or_permisson_denied( + user=request.user, proposal=proposal) if request.method == 'GET': return render(request, 'proposals/delete.html', {'proposal': proposal}) @@ -463,103 +358,3 @@ def delete_proposal(request, conference_slug, slug): proposal.delete() return HttpResponseRedirect(reverse('proposals-list', args=[conference.slug])) - - -@login_required -@require_http_methods(['POST']) -def create_proposal_comment(request, conference_slug, proposal_slug): - conference = get_object_or_404(Conference, slug=conference_slug) - proposal = get_object_or_404( - Proposal, slug=proposal_slug, conference=conference) - form = ProposalCommentForm(request.POST) - if form.is_valid(): - comment = form.cleaned_data['comment'] - private = form.cleaned_data['private'] - reviewer = form.cleaned_data['reviewer'] - - if private and not _is_proposal_author_or_proposal_section_reviewer( - request.user, conference, proposal): - raise Http404() - - proposal_comment = ProposalComment.objects.create( - proposal=proposal, comment=comment, - private=private, reviewer=reviewer, commenter=request.user - ) - host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META['HTTP_HOST']) - send_mail_for_new_comment(proposal_comment, host) - - redirect_url = reverse('proposal-detail', args=[conference.slug, proposal.slug]) - - if private: - redirect_url += "#js-reviewers" - elif reviewer: - redirect_url += "#js-only-reviewers" - else: - redirect_url += "#js-comments" - - return HttpResponseRedirect(redirect_url) - - -@login_required -def proposal_vote(request, conference_slug, proposal_slug, up_vote): - conference = get_object_or_404(Conference, slug=conference_slug) - proposal = get_object_or_404( - Proposal, slug=proposal_slug, conference=conference) - - proposal_vote, created = ProposalVote.objects.get_or_create( - proposal=proposal, voter=request.user) # @UnusedVariable - - if _is_proposal_reviewer(request.user, conference): - role = ProposalUserVoteRole.REVIEWER - else: - role = ProposalUserVoteRole.PUBLIC - - proposal_vote.role = role - proposal_vote.up_vote = up_vote - proposal_vote.save() - - return HttpResponse(proposal.get_votes_count()) - - -@login_required -@require_http_methods(['POST']) -def proposal_vote_up(request, conference_slug, proposal_slug): - return proposal_vote(request, conference_slug, proposal_slug, True) - - -@login_required -@require_http_methods(['POST']) -def proposal_vote_down(request, conference_slug, proposal_slug): - return proposal_vote(request, conference_slug, proposal_slug, False) - - -def proposal_comment_vote(request, conference_slug, proposal_slug, comment_id, - up_vote): - conference = get_object_or_404(Conference, slug=conference_slug) - proposal = get_object_or_404(Proposal, slug=proposal_slug, - conference=conference) - proposal_comment = get_object_or_404(ProposalComment, proposal=proposal, - id=comment_id) - proposal_comment_vote, created = ProposalCommentVote.objects.get_or_create( - proposal_comment=proposal_comment, voter=request.user) - proposal_comment_vote.up_vote = up_vote - proposal_comment_vote.save() - - return HttpResponseRedirect(reverse('proposal-detail', - args=[conference.slug, proposal.slug])) - - -@login_required -@require_http_methods(['POST']) -def proposal_comment_up_vote(request, conference_slug, proposal_slug, - proposal_comment_id): - return proposal_comment_vote(request, conference_slug, proposal_slug, - proposal_comment_id, True) - - -@login_required -@require_http_methods(['POST']) -def proposal_comment_down_vote(request, conference_slug, proposal_slug, - proposal_comment_id): - return proposal_comment_vote(request, conference_slug, proposal_slug, - proposal_comment_id, False) diff --git a/junction/proposals/votes_views.py b/junction/proposals/votes_views.py new file mode 100644 index 00000000..f508b3c4 --- /dev/null +++ b/junction/proposals/votes_views.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- + +from django.contrib.auth.decorators import login_required +from django.shortcuts import get_object_or_404, render +from django.views.decorators.http import require_http_methods +from django.core.urlresolvers import reverse +from django.core.exceptions import PermissionDenied +from django.http.response import HttpResponse, HttpResponseRedirect + +from junction.base.constants import ProposalUserVoteRole +from junction.conferences.models import Conference + +from .forms import ProposalReviewerVoteForm + +from .models import ( + Proposal, + ProposalVote, + ProposalComment, + ProposalCommentVote, + ProposalSectionReviewerVote, + ProposalSectionReviewer, + ProposalSectionReviewerVoteValue) + +from . import permissions + + +@login_required +def proposal_vote(request, conference_slug, proposal_slug, up_vote): + conference = get_object_or_404(Conference, slug=conference_slug) + proposal = get_object_or_404( + Proposal, slug=proposal_slug, conference=conference) + + proposal_vote, created = ProposalVote.objects.get_or_create( + proposal=proposal, voter=request.user) # @UnusedVariable + + if permissions.is_proposal_reviewer(request.user, conference): + role = ProposalUserVoteRole.REVIEWER + else: + role = ProposalUserVoteRole.PUBLIC + + proposal_vote.role = role + proposal_vote.up_vote = up_vote + proposal_vote.save() + + return HttpResponse(proposal.get_votes_count()) + + +@login_required +@require_http_methods(['POST']) +def proposal_vote_up(request, conference_slug, proposal_slug): + return proposal_vote(request, conference_slug, proposal_slug, True) + + +@login_required +@require_http_methods(['POST']) +def proposal_vote_down(request, conference_slug, proposal_slug): + return proposal_vote(request, conference_slug, proposal_slug, False) + + +def proposal_comment_vote(request, conference_slug, proposal_slug, comment_id, + up_vote): + conference = get_object_or_404(Conference, slug=conference_slug) + proposal = get_object_or_404(Proposal, slug=proposal_slug, + conference=conference) + proposal_comment = get_object_or_404(ProposalComment, proposal=proposal, + id=comment_id) + proposal_comment_vote, created = ProposalCommentVote.objects.get_or_create( + proposal_comment=proposal_comment, voter=request.user) + proposal_comment_vote.up_vote = up_vote + proposal_comment_vote.save() + + return HttpResponseRedirect(reverse('proposal-detail', + args=[conference.slug, proposal.slug])) + + +@login_required +@require_http_methods(['POST']) +def proposal_comment_up_vote(request, conference_slug, proposal_slug, + proposal_comment_id): + return proposal_comment_vote(request, conference_slug, proposal_slug, + proposal_comment_id, True) + + +@login_required +@require_http_methods(['POST']) +def proposal_comment_down_vote(request, conference_slug, proposal_slug, + proposal_comment_id): + return proposal_comment_vote(request, conference_slug, proposal_slug, + proposal_comment_id, False) + + +@login_required +@require_http_methods(['GET', 'POST']) +def proposal_reviewer_vote(request, conference_slug, proposal_slug): + conference = get_object_or_404(Conference, slug=conference_slug) + proposal = get_object_or_404(Proposal, slug=proposal_slug, + conference=conference) + + if not permissions.is_proposal_section_reviewer(request.user, + conference, proposal): + raise PermissionDenied + + vote_value = None + + try: + vote = ProposalSectionReviewerVote.objects.get( + proposal=proposal, + voter=ProposalSectionReviewer.objects.get( + conference_reviewer__reviewer=request.user, + conference_reviewer__conference=conference, + proposal_section=proposal.proposal_section), + ) + vote_value = vote.vote_value.vote_value + except ProposalSectionReviewerVote.DoesNotExist: + vote = None + + try: + vote_comment = ProposalComment.objects.get( + proposal=proposal, + commenter=request.user, + vote=True, + deleted=False, + ) + except: + vote_comment = None + if request.method == 'GET': + if vote_comment: + proposal_vote_form = ProposalReviewerVoteForm( + initial={'vote_value': vote_value, + 'comment': vote_comment.comment}) + else: + proposal_vote_form = ProposalReviewerVoteForm( + initial={'vote_value': vote_value}) + ctx = { + 'proposal': proposal, + 'proposal_vote_form': proposal_vote_form, + 'vote': vote, + } + + return render(request, 'proposals/vote.html', ctx) + + # POST Workflow + form = ProposalReviewerVoteForm(request.POST) + if not form.is_valid(): + return render(request, 'proposals/vote.html', + {'form': form, + 'proposal': proposal, + 'form_errors': form.errors}) + + # Valid Form + vote_value = form.cleaned_data['vote_value'] + comment = form.cleaned_data['comment'] + if not vote: + vote = ProposalSectionReviewerVote.objects.create( + proposal=proposal, + voter=ProposalSectionReviewer.objects.get( + conference_reviewer__reviewer=request.user, + conference_reviewer__conference=conference, + proposal_section=proposal.proposal_section), + vote_value=ProposalSectionReviewerVoteValue.objects.get( + vote_value=vote_value), + ) + else: + vote.vote_value = ProposalSectionReviewerVoteValue.objects.get( + vote_value=vote_value) + vote.save() + if not vote_comment: + vote_comment = ProposalComment.objects.create( + proposal=proposal, + commenter=request.user, + comment=comment, + vote=True, + ) + else: + vote_comment.comment = comment + vote_comment.save() + return HttpResponseRedirect(reverse('proposals-to-review', + args=[conference.slug])) From 31ee84042a12fc65be539de896daf755b342d9a0 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 19 Dec 2015 22:25:05 +0530 Subject: [PATCH 317/666] Move check for authentication to top --- junction/proposals/permissions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/junction/proposals/permissions.py b/junction/proposals/permissions.py index d3319d8f..abf7108c 100644 --- a/junction/proposals/permissions.py +++ b/junction/proposals/permissions.py @@ -11,9 +11,10 @@ def is_proposal_author(user, proposal): def is_proposal_reviewer(user, conference): + authenticated = user.is_authenticated() is_reviewer = ConferenceProposalReviewer.objects.filter( reviewer=user, conference=conference, active=True).exists() - return user.is_authenticated() and is_reviewer + return authenticated and is_reviewer def is_proposal_section_reviewer(user, conference, proposal): From 5e431f199d3cc0923bf5dde11354bf691297e096 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 19 Dec 2015 22:28:20 +0530 Subject: [PATCH 318/666] Access id in user --- junction/proposals/permissions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/proposals/permissions.py b/junction/proposals/permissions.py index abf7108c..d6958f43 100644 --- a/junction/proposals/permissions.py +++ b/junction/proposals/permissions.py @@ -13,7 +13,7 @@ def is_proposal_author(user, proposal): def is_proposal_reviewer(user, conference): authenticated = user.is_authenticated() is_reviewer = ConferenceProposalReviewer.objects.filter( - reviewer=user, conference=conference, active=True).exists() + reviewer=user.id, conference=conference, active=True).exists() return authenticated and is_reviewer From 7d9df9d1709f3346d2ee04ee05bf5f84af4e1e4c Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 19 Dec 2015 22:32:55 +0530 Subject: [PATCH 319/666] Remove under indented line - Add a space between key and value in context value --- junction/proposals/permissions.py | 5 +++-- junction/proposals/views.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/junction/proposals/permissions.py b/junction/proposals/permissions.py index d6958f43..9a740d68 100644 --- a/junction/proposals/permissions.py +++ b/junction/proposals/permissions.py @@ -26,8 +26,9 @@ def is_proposal_section_reviewer(user, conference, proposal): def is_proposal_author_or_proposal_reviewer(user, conference, proposal): - return is_proposal_author(user, proposal) or \ - is_proposal_reviewer(user, conference) + reviewer = is_proposal_reviewer(user, conference) + author = is_proposal_author(user, proposal) + return reviewer or author def is_proposal_author_or_proposal_section_reviewer(user, diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 6a3681a4..9171add9 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -174,7 +174,7 @@ def detail_proposal(request, conference_slug, slug): 'is_reviewer': is_reviewer, 'is_section_reviewer': is_section_reviewer, 'can_view_feedback': False, - 'can_vote':voting + 'can_vote': voting } if proposal.scheduleitem_set.all(): From 238b92a561f9285f7030b1dae51a3ffeb3de579e Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Tue, 5 Jan 2016 22:43:51 +0530 Subject: [PATCH 320/666] Use set to compare list of values --- tests/integrations/test_feedback_service.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integrations/test_feedback_service.py b/tests/integrations/test_feedback_service.py index 951e0c7b..e24e128d 100644 --- a/tests/integrations/test_feedback_service.py +++ b/tests/integrations/test_feedback_service.py @@ -15,7 +15,7 @@ def test_get_feedback_questions_without_conference(): def test_get_feedback_questions_with_conference(): - schedule_item_types = ['Workshop', 'Talk'] + schedule_item_types = set(['Workshop', 'Talk']) num_choice_questions = 2 num_text_questions = 1 objects = factories.create_feedback_questions( @@ -26,7 +26,7 @@ def test_get_feedback_questions_with_conference(): conference = objects['conference'] result = service.get_feedback_questions(conference_id=conference.id) - assert list(result.keys()) == schedule_item_types + assert set(result.keys()) == schedule_item_types for item_type in schedule_item_types: assert len(result[item_type]['text']) == num_text_questions assert len(result[item_type]['choice']) == num_choice_questions From c0005ba89f836d182c1698dace525ca02c3a15c8 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 10 Jan 2016 13:02:46 +0530 Subject: [PATCH 321/666] Add test cases for proposal create, update, delete views --- junction/profiles/views.py | 3 +- junction/proposals/views.py | 2 +- pytest.ini | 1 + tests/factories.py | 22 ++- tests/fixtures.py | 52 ++++++ tests/integrations/helpers.py | 11 ++ tests/integrations/test_proposal_views.py | 208 +++++++++++++++++++++- 7 files changed, 294 insertions(+), 5 deletions(-) create mode 100644 tests/integrations/helpers.py diff --git a/junction/profiles/views.py b/junction/profiles/views.py index dce00618..9044b78c 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -17,4 +17,5 @@ def dashboard(request): conf_proposals[conf.name].append(proposal) else: conf_proposals[conf.name] = [proposal] - return render(request, 'profiles/dashboard.html', {'conf_proposals': conf_proposals}) + return render(request, 'profiles/dashboard.html', + {'conf_proposals': conf_proposals}) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 9171add9..8c740398 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -136,7 +136,7 @@ def create_proposal(request, conference_slug): status=form.cleaned_data['status'], proposal_type_id=form.cleaned_data['proposal_type'], proposal_section_id=form.cleaned_data['proposal_section']) - host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META['HTTP_HOST']) + host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META.get('HTTP_HOST')) send_mail_for_new_proposal(proposal, host) return HttpResponseRedirect(reverse('proposal-detail', diff --git a/pytest.ini b/pytest.ini index 453d833b..11caccdf 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,2 +1,3 @@ [pytest] DJANGO_SETTINGS_MODULE=settings.test_settings +addopts = --reuse-db diff --git a/tests/factories.py b/tests/factories.py index 6b9169ee..c641e5e5 100644 --- a/tests/factories.py +++ b/tests/factories.py @@ -47,7 +47,8 @@ class Meta: name = factory.Sequence(lambda n: "conference{}".format(n)) # slug = factory.LazyAttribute(lambda obj: slugify) # description = - start_date = fuzzy.FuzzyDate(datetime.date.today(), datetime.date(2017, 1, 1)).fuzz() + start_date = fuzzy.FuzzyDate(datetime.date.today(), + datetime.date(datetime.date.today().year + 1, 1, 1)).fuzz() end_date = start_date + datetime.timedelta(3) # logo status = factory.Iterator(list(dict(ConferenceStatus.CHOICES).keys())) @@ -195,7 +196,24 @@ def create_conference(**kwargs): """ Create a conference """ ProposalSectionReviewerVoteValueFactory.create(vote_value=1, description="Good") - return ConferenceFactory.create(**kwargs) + conference = ConferenceFactory.create(**kwargs) + start_date = kwargs.pop('start_date', None) + end_date = kwargs.pop('end_date', None) + if start_date and end_date: + workshop = ProposalTypeFactory.create(name="Workshop", + start_date=start_date, + end_date=end_date) + conference.proposal_types.add(workshop) + talks = ProposalTypeFactory.create(name="Talks", + start_date=start_date, + end_date=end_date) + conference.proposal_types.add(talks) + conference.save() + + section = ProposalSectionFactory.create() + conference.proposal_sections.add(section) + conference.save() + return conference def create_user(**kwargs): diff --git a/tests/fixtures.py b/tests/fixtures.py index 86ca19da..21482802 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -1,11 +1,18 @@ # -*- coding: utf-8 -*- # Standard Library import functools +import datetime # Third Party Stuff import mock import pytest +from django.contrib.auth.models import User + +from junction.base.constants import ConferenceStatus + +from . import factories + class Object: pass @@ -51,3 +58,48 @@ def outbox(): from django.core import mail return mail.outbox + + +# App Fixture + + +@pytest.fixture +def conferences(): + # Create conference with closed date + today = datetime.datetime.today() + day_before_yesterday = today - datetime.timedelta(days=2) + yesterday = today - datetime.timedelta(days=1) + closed_status = ConferenceStatus._CLOSED_CFP[0] + past = factories.create_conference(name="Past", + start_date=day_before_yesterday, + end_date=yesterday, + status=closed_status) + + # Create conference with future date + today = datetime.datetime.today() + tomo = today + datetime.timedelta(days=1) + open_status = ConferenceStatus._ACCEPTING_CFP[0] + future = factories.create_conference(name="Future", + start_date=today, + end_date=tomo, + status=open_status) + return {'past': past, 'future': future} + + +@pytest.fixture +def create_user(): + username, password = "username", "password" + user = factories.create_user(username=username, + email="username@example.com", + password=password) + user.set_password(password) + user.is_active = True + user.save() + return {'username': username, 'password': password, 'user': user} + + +@pytest.fixture +def login(create_user, client): + username, password = create_user['username'], create_user['password'] + client.login(username=username, password=password) + return client, create_user['user'] diff --git a/tests/integrations/helpers.py b/tests/integrations/helpers.py new file mode 100644 index 00000000..68f57836 --- /dev/null +++ b/tests/integrations/helpers.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- + + +def assert_template_used(response, template_name): + res = False + for template in response.templates: + if template.name == template_name: + res = True + break + + assert res is True diff --git a/tests/integrations/test_proposal_views.py b/tests/integrations/test_proposal_views.py index 93658037..3ab0239f 100644 --- a/tests/integrations/test_proposal_views.py +++ b/tests/integrations/test_proposal_views.py @@ -1,13 +1,15 @@ import pytest from django.core.urlresolvers import reverse from .. import factories as f +from . import helpers pytestmark = pytest.mark.django_db def test_list_proposals_pass(client, settings): conference = f.create_conference() - url = reverse('proposals-list', kwargs={'conference_slug': conference.slug}) + url = reverse('proposals-list', kwargs={'conference_slug': + conference.slug}) response = client.get(url) assert response.status_code == 200 @@ -18,3 +20,207 @@ def test_list_proposals_fail(client, settings): response = client.get(url) assert response.status_code == 404 + + +def test_create_proposal_for_closed_conference(settings, login, conferences): + client = login[0] + conference = conferences['past'] + url = reverse('proposal-create', kwargs={'conference_slug': + conference.slug}) + response = client.get(url) + template = 'proposals/closed.html' + + assert response.status_code == 200 + helpers.assert_template_used(response=response, + template_name=template) + + +def test_create_proposal_for_open_conference_get(settings, login, conferences): + client = login[0] + conference = conferences['future'] + url = reverse('proposal-create', kwargs={'conference_slug': + conference.slug}) + response = client.get(url) + template = 'proposals/create.html' + + assert response.status_code == 200 + helpers.assert_template_used(response=response, + template_name=template) + assert response.context['conference'] == conference + + +def test_create_proposal_with_missing_data(settings, login, conferences): + client = login[0] + conference = conferences['future'] + url = reverse('proposal-create', kwargs={'conference_slug': + conference.slug}) + section = conference.proposal_sections.all()[0] + proposal_type = conference.proposal_types.all()[0] + + data = {'title': 'Proposal Title for the conf', + 'description': 'Loong Text', + 'target_audience': '1', + 'status': '2', + 'proposal_type': str(section.id), + 'proposal_section': str(proposal_type.id)} + response = client.post(url, data) + + assert response.status_code == 200 + assert set(response.context['errors'].keys()) == set(['proposal_type', + 'proposal_section']) + + +def test_create_proposal_with_all_data(settings, login, conferences): + client = login[0] + conference = conferences['future'] + url = reverse('proposal-create', kwargs={'conference_slug': + conference.slug}) + section = conference.proposal_sections.all()[0] + proposal_type = conference.proposal_types.all()[0] + + data = {'title': 'Proposal Title for the conf', + 'description': 'Loong Text', + 'target_audience': '1', + 'status': '2', + 'proposal_type': proposal_type.id, + 'proposal_section': section.id} + response = client.post(url, data) + + assert response.status_code == 302 + + +def test_delete_existing_proposal_post(settings, login, conferences): + client, user = login[0], login[1] + conference = conferences['future'] + section = conference.proposal_sections.all()[0] + proposal_type = conference.proposal_types.all()[0] + proposal = f.create_proposal(conference=conference, + proposal_section=section, + proposal_type=proposal_type, + author=user) + kwargs = {'conference_slug': conference.slug, 'slug': proposal.slug} + url = reverse('proposal-delete', kwargs=kwargs) + + response = client.post(url) + + assert response.status_code == 302 + + +def test_delete_existing_proposal_get(settings, login, conferences): + client, user = login[0], login[1] + conference = conferences['future'] + section = conference.proposal_sections.all()[0] + proposal_type = conference.proposal_types.all()[0] + proposal = f.create_proposal(conference=conference, + proposal_section=section, + proposal_type=proposal_type, + author=user) + kwargs = {'conference_slug': conference.slug, 'slug': proposal.slug} + url = reverse('proposal-delete', kwargs=kwargs) + + response = client.get(url) + + assert response.status_code == 200 + helpers.assert_template_used(response, 'proposals/delete.html') + + +def test_delete_existing_proposal_by_different_author(settings, login, + conferences): + client = login[0] + conference = conferences['future'] + section = conference.proposal_sections.all()[0] + proposal_type = conference.proposal_types.all()[0] + user = f.create_user() + proposal = f.create_proposal(conference=conference, + proposal_section=section, + proposal_type=proposal_type, + author=user) + kwargs = {'conference_slug': conference.slug, 'slug': proposal.slug} + url = reverse('proposal-delete', kwargs=kwargs) + + response = client.post(url) + + assert response.status_code == 403 + + +def test_update_proposal_get(settings, login, conferences): + client, user = login[0], login[1] + conference = conferences['future'] + section = conference.proposal_sections.all()[0] + proposal_type = conference.proposal_types.all()[0] + proposal = f.create_proposal(conference=conference, + proposal_section=section, + proposal_type=proposal_type, + author=user) + kwargs = {'conference_slug': conference.slug, 'slug': proposal.slug} + url = reverse('proposal-update', kwargs=kwargs) + + response = client.get(url) + + assert response.status_code == 200 + helpers.assert_template_used(response, 'proposals/update.html') + assert response.context['proposal'] == proposal + + +def test_update_proposal_post(settings, login, conferences): + client, user = login[0], login[1] + conference = conferences['future'] + section = conference.proposal_sections.all()[0] + proposal_type = conference.proposal_types.all()[0] + proposal = f.create_proposal(conference=conference, + proposal_section=section, + proposal_type=proposal_type, + author=user) + kwargs = {'conference_slug': conference.slug, 'slug': proposal.slug} + url = reverse('proposal-update', kwargs=kwargs) + + title = 'new proposal title' + data = {'title': title, + 'description': 'Loong Text', + 'target_audience': '1', + 'status': '2', + 'proposal_type': proposal_type.id, + 'proposal_section': section.id} + + response = client.post(url, data) + + assert response.status_code == 302 + + +def test_update_proposal_by_different_user(settings, login, conferences): + client = login[0] + conference = conferences['future'] + section = conference.proposal_sections.all()[0] + proposal_type = conference.proposal_types.all()[0] + user = f.create_user() + proposal = f.create_proposal(conference=conference, + proposal_section=section, + proposal_type=proposal_type, + author=user) + + kwargs = {'conference_slug': conference.slug, 'slug': proposal.slug} + url = reverse('proposal-update', kwargs=kwargs) + title = 'new proposal title' + data = {'title': title} + response = client.post(url, data) + + assert response.status_code == 403 + + +def test_update_proposal_with_invalid_data(settings, login, conferences): + client, user = login[0], login[1] + conference = conferences['future'] + section = conference.proposal_sections.all()[0] + proposal_type = conference.proposal_types.all()[0] + proposal = f.create_proposal(conference=conference, + proposal_section=section, + proposal_type=proposal_type, + author=user) + kwargs = {'conference_slug': conference.slug, 'slug': proposal.slug} + url = reverse('proposal-update', kwargs=kwargs) + + title = 'new title' + response = client.post(url, {'title': title}) + + assert response.status_code == 200 + assert 'title' in response.context['errors'] From 91e37b83b86f334a24e791a7a535012fa215cd2d Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 10 Jan 2016 13:13:07 +0530 Subject: [PATCH 322/666] Remove unused imports --- tests/fixtures.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/fixtures.py b/tests/fixtures.py index 21482802..f79c0521 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -7,8 +7,6 @@ import mock import pytest -from django.contrib.auth.models import User - from junction.base.constants import ConferenceStatus from . import factories From 2448bbfacac4a3981f6e1fd8c40ed6d3b577d883 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 10 Jan 2016 17:10:39 +0530 Subject: [PATCH 323/666] Add test case proposal review and comments --- junction/proposals/comments_views.py | 2 +- tests/factories.py | 8 +- tests/fixtures.py | 35 ++++++++- tests/integrations/test_proposal_views.py | 5 ++ tests/integrations/test_reviewer_views.py | 90 +++++++++++++++++++++++ 5 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 tests/integrations/test_reviewer_views.py diff --git a/junction/proposals/comments_views.py b/junction/proposals/comments_views.py index 615bb88e..bae0b5d5 100644 --- a/junction/proposals/comments_views.py +++ b/junction/proposals/comments_views.py @@ -40,7 +40,7 @@ def create_proposal_comment(request, conference_slug, proposal_slug): private=private, reviewer=reviewer, commenter=request.user ) host = '{}://{}'.format(settings.SITE_PROTOCOL, - request.META['HTTP_HOST']) + request.META.get('HTTP_HOST')) send_mail_for_new_comment(proposal_comment, host) redirect_url = reverse('proposal-detail', diff --git a/tests/factories.py b/tests/factories.py index c641e5e5..4cc40e1e 100644 --- a/tests/factories.py +++ b/tests/factories.py @@ -218,7 +218,13 @@ def create_conference(**kwargs): def create_user(**kwargs): "Create an user along with her dependencies" - return UserFactory.create(**kwargs) + user = UserFactory.create(**kwargs) + password = kwargs.pop('password', None) + if password: + user.set_password(password) + user.is_active = True + user.save() + return user def create_proposal(**kwargs): diff --git a/tests/fixtures.py b/tests/fixtures.py index f79c0521..c0fc7d22 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -8,6 +8,8 @@ import pytest from junction.base.constants import ConferenceStatus +from junction.conferences.models import ConferenceProposalReviewer +from junction.proposals.models import ProposalSectionReviewer from . import factories @@ -27,7 +29,8 @@ def __init__(self, obj, **partial_params): self.partial_params = partial_params def __getattr__(self, name): - return functools.partial(getattr(self.obj, name), **self.partial_params) + return functools.partial(getattr(self.obj, name), + **self.partial_params) @pytest.fixture @@ -35,7 +38,9 @@ def client(): from django.test.client import Client class _Client(Client): - def login(self, user=None, backend="django.contrib.auth.backends.ModelBackend", **credentials): + def login(self, user=None, + backend="django.contrib.auth.backends.ModelBackend", + **credentials): if user is None: return super(_Client, self).login(**credentials) @@ -101,3 +106,29 @@ def login(create_user, client): username, password = create_user['username'], create_user['password'] client.login(username=username, password=password) return client, create_user['user'] + + +@pytest.fixture +def create_reviewer(create_user, conferences): + user = create_user['user'] + conference = conferences['future'] + conference_reviewer = ConferenceProposalReviewer.objects.create( + conference=conference, + reviewer=user) + for section in conference.proposal_sections.all(): + ProposalSectionReviewer.objects.create( + conference_reviewer=conference_reviewer, + proposal_section=section) + return user + + +@pytest.fixture +def create_proposal(conferences, create_user): + conference, user = conferences['future'], create_user['user'] + section = conference.proposal_sections.all()[0] + proposal_type = conference.proposal_types.all()[0] + proposal = factories.create_proposal(conference=conference, + proposal_section=section, + proposal_type=proposal_type, + author=user) + return proposal diff --git a/tests/integrations/test_proposal_views.py b/tests/integrations/test_proposal_views.py index 3ab0239f..2f15c781 100644 --- a/tests/integrations/test_proposal_views.py +++ b/tests/integrations/test_proposal_views.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import pytest from django.core.urlresolvers import reverse from .. import factories as f @@ -6,6 +8,9 @@ pytestmark = pytest.mark.django_db +# Proposal + + def test_list_proposals_pass(client, settings): conference = f.create_conference() url = reverse('proposals-list', kwargs={'conference_slug': diff --git a/tests/integrations/test_reviewer_views.py b/tests/integrations/test_reviewer_views.py new file mode 100644 index 00000000..5aafd8c0 --- /dev/null +++ b/tests/integrations/test_reviewer_views.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- + +import pytest +from django.core.urlresolvers import reverse +from .. import factories as f +from . import helpers + +pytestmark = pytest.mark.django_db + + +class TestReviewerViews: + def test_reviewer_private_comment(self, settings, login, conferences, + create_proposal): + client = login[0] + conference = conferences['future'] + + proposal = create_proposal + + kwargs = {'conference_slug': conference.slug, + 'proposal_slug': proposal.slug} + url = reverse('proposal-comment-create', kwargs=kwargs) + data = {'comment': 'Test', 'private': True} + + response = client.post(url, data) + + assert response.status_code == 302 + assert response.url.endswith('#js-reviewers') + + def test_reviewer_only_private_comment(self, settings, login, conferences, + create_proposal): + client = login[0] + conference = conferences['future'] + + proposal = create_proposal + + kwargs = {'conference_slug': conference.slug, + 'proposal_slug': proposal.slug} + url = reverse('proposal-comment-create', kwargs=kwargs) + data = {'comment': 'Test', 'reviewer': True} + + response = client.post(url, data) + + assert response.status_code == 302 + assert response.url.endswith('#js-only-reviewers') + + def test_get_review_proposal_form(self, settings, login, conferences, + create_reviewer, create_proposal): + client = login[0] + conference = conferences['future'] + + proposal = create_proposal + + kwargs = {'conference_slug': conference.slug, 'slug': proposal.slug} + url = reverse('proposal-review', kwargs=kwargs) + + response = client.get(url) + context = response.context + + assert response.status_code == 200 + assert context['proposal'] == proposal + helpers.assert_template_used(response, 'proposals/review.html') + + def test_post_review_proposal(self, settings, login, conferences, + create_reviewer, create_proposal): + client = login[0] + conference = conferences['future'] + + proposal = create_proposal + + kwargs = {'conference_slug': conference.slug, 'slug': proposal.slug} + url = reverse('proposal-review', kwargs=kwargs) + + response = client.post(url, {'review_status': 3}) + + assert response.status_code == 302 + + def test_review_proposal_by_non_reviewer(self, settings, client, + conferences, create_proposal): + username, password = "temp", "temp" + f.create_user(password=password, username=username) + conference = conferences['future'] + client.login(username=username, password=password) + proposal = create_proposal + + kwargs = {'conference_slug': conference.slug, 'slug': proposal.slug} + url = reverse('proposal-review', kwargs=kwargs) + + response = client.get(url) + + assert response.status_code == 403 From a58c035b8828240394599d23c6830dc9d87c1a68 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 10 Jan 2016 22:51:19 +0530 Subject: [PATCH 324/666] Add testcase for reviewer vote and comment --- junction/proposals/forms.py | 15 ++- junction/proposals/urls.py | 9 +- junction/proposals/views.py | 2 +- junction/proposals/votes_views.py | 14 +-- tests/factories.py | 2 + tests/integrations/test_reviewer_views.py | 119 ++++++++++++++++++++++ 6 files changed, 145 insertions(+), 16 deletions(-) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index 8b807f69..eaeb4a48 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -154,7 +154,8 @@ class ProposalReviewerVoteForm(forms.Form): help_text="Leave a comment justifying your vote.", ) - def __init_(self): + def __init__(self, *args, **kwargs): + super(ProposalReviewerVoteForm, self).__init__(*args, **kwargs) choices = _get_proposal_section_reviewer_vote_choices() self.fields['vote_value'].choices = choices @@ -163,13 +164,17 @@ class ProposalTypesChoices(forms.Form): """ Base proposal form with proposal sections & types. """ - proposal_section = forms.ChoiceField(widget=forms.Select(attrs={'class': 'dropdown'})) - proposal_type = forms.ChoiceField(widget=forms.Select(attrs={'class': 'dropdown'})) + proposal_section = forms.ChoiceField(widget=forms.Select( + attrs={'class': 'dropdown'})) + proposal_type = forms.ChoiceField(widget=forms.Select( + attrs={'class': 'dropdown'})) def __init__(self, conference, *args, **kwargs): super(ProposalTypesChoices, self).__init__(*args, **kwargs) - self.fields['proposal_section'].choices = _get_proposal_section_choices(conference) - self.fields['proposal_type'].choices = _get_proposal_type_choices(conference) + self.fields['proposal_section'].choices = _get_proposal_section_choices( + conference) + self.fields['proposal_type'].choices = _get_proposal_type_choices( + conference) class ProposalsToReviewForm(ProposalTypesChoices): diff --git a/junction/proposals/urls.py b/junction/proposals/urls.py index fea6077a..fd1df68d 100644 --- a/junction/proposals/urls.py +++ b/junction/proposals/urls.py @@ -32,7 +32,10 @@ url(r'^comment/', include(comment_urls)), # Voting - url(r'^(?P[\w-]+)/vote/$', votes_views.proposal_reviewer_vote, name='proposal-reviewer-vote'), - url(r'^(?P[\w-]+)/down-vote/$', votes_views.proposal_vote_down, name='proposal-vote-down'), - url(r'^(?P[\w-]+)/up-vote/$', votes_views.proposal_vote_up, name='proposal-vote-up'), + url(r'^(?P[\w-]+)/vote/$', + votes_views.proposal_reviewer_vote, name='proposal-reviewer-vote'), + url(r'^(?P[\w-]+)/down-vote/$', + votes_views.proposal_vote_down, name='proposal-vote-down'), + url(r'^(?P[\w-]+)/up-vote/$', + votes_views.proposal_vote_up, name='proposal-vote-up'), ) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 8c740398..c1d5579f 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -308,7 +308,7 @@ def review_proposal(request, conference_slug, slug): return render(request, 'proposals/review.html', ctx) # POST Workflow - form = ProposalReviewForm(request.POST) + form = ProposalReviewForm(data=request.POST) if not form.is_valid(): context = {'form': form, 'proposal': proposal, diff --git a/junction/proposals/votes_views.py b/junction/proposals/votes_views.py index f508b3c4..ed1c34df 100644 --- a/junction/proposals/votes_views.py +++ b/junction/proposals/votes_views.py @@ -140,7 +140,7 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): return render(request, 'proposals/vote.html', ctx) # POST Workflow - form = ProposalReviewerVoteForm(request.POST) + form = ProposalReviewerVoteForm(data=request.POST) if not form.is_valid(): return render(request, 'proposals/vote.html', {'form': form, @@ -153,16 +153,16 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): if not vote: vote = ProposalSectionReviewerVote.objects.create( proposal=proposal, - voter=ProposalSectionReviewer.objects.get( + voter=ProposalSectionReviewer.objects.filter( conference_reviewer__reviewer=request.user, conference_reviewer__conference=conference, - proposal_section=proposal.proposal_section), - vote_value=ProposalSectionReviewerVoteValue.objects.get( - vote_value=vote_value), + proposal_section=proposal.proposal_section)[0], + vote_value=ProposalSectionReviewerVoteValue.objects.filter( + vote_value=vote_value)[0], ) else: - vote.vote_value = ProposalSectionReviewerVoteValue.objects.get( - vote_value=vote_value) + vote.vote_value = ProposalSectionReviewerVoteValue.objects.filter( + vote_value=vote_value)[0] vote.save() if not vote_comment: vote_comment = ProposalComment.objects.create( diff --git a/tests/factories.py b/tests/factories.py index 4cc40e1e..cee231db 100644 --- a/tests/factories.py +++ b/tests/factories.py @@ -196,6 +196,8 @@ def create_conference(**kwargs): """ Create a conference """ ProposalSectionReviewerVoteValueFactory.create(vote_value=1, description="Good") + ProposalSectionReviewerVoteValueFactory.create(vote_value=2, + description="Good") conference = ConferenceFactory.create(**kwargs) start_date = kwargs.pop('start_date', None) end_date = kwargs.pop('end_date', None) diff --git a/tests/integrations/test_reviewer_views.py b/tests/integrations/test_reviewer_views.py index 5aafd8c0..e2cdfee0 100644 --- a/tests/integrations/test_reviewer_views.py +++ b/tests/integrations/test_reviewer_views.py @@ -88,3 +88,122 @@ def test_review_proposal_by_non_reviewer(self, settings, client, response = client.get(url) assert response.status_code == 403 + + def test_proposal_reviewer_vote_by_non_reviewer(self, settings, client, + conferences, + create_proposal): + username, password = "temp", "temp" + f.create_user(password=password, username=username) + conference = conferences['future'] + client.login(username=username, password=password) + proposal = create_proposal + + kwargs = {'conference_slug': conference.slug, + 'proposal_slug': proposal.slug} + url = reverse('proposal-reviewer-vote', kwargs=kwargs) + + response = client.post(url) + + assert response.status_code == 403 + + def test_get_proposal_reviewer_vote(self, settings, login, + conferences, + create_proposal, + create_reviewer): + client = login[0] + conference = conferences['future'] + + proposal = create_proposal + + kwargs = {'conference_slug': conference.slug, + 'proposal_slug': proposal.slug} + url = reverse('proposal-reviewer-vote', kwargs=kwargs) + + response = client.get(url) + context = response.context + + assert response.status_code == 200 + assert context['proposal'] == proposal + assert context['vote'] is None + helpers.assert_template_used(response, 'proposals/vote.html') + + def test_post_proposal_reviewer_vote(self, settings, login, + conferences, + create_proposal, + create_reviewer): + client = login[0] + conference = conferences['future'] + + proposal = create_proposal + + kwargs = {'conference_slug': conference.slug, + 'proposal_slug': proposal.slug} + url = reverse('proposal-reviewer-vote', kwargs=kwargs) + data = {'vote_value': 1, 'comment': 'Must Have'} + + response = client.post(url, data) + + assert response.status_code == 302 + assert response.url.endswith('review/') is True + + def test_update_proposal_reviewer_vote(self, settings, login, + conferences, + create_proposal, + create_reviewer): + client = login[0] + conference = conferences['future'] + + proposal = create_proposal + + kwargs = {'conference_slug': conference.slug, + 'proposal_slug': proposal.slug} + url = reverse('proposal-reviewer-vote', kwargs=kwargs) + data = {'vote_value': 1, 'comment': 'Must Have'} + client.post(url, data) + + update_data = {'vote_value': 2, 'comment': 'Must Have'} + response = client.post(url, update_data) + + assert response.status_code == 302 + assert response.url.endswith('review/') is True + + def test_get_proposal_reviewer_vote_after_create(self, settings, login, + conferences, + create_proposal, + create_reviewer): + client = login[0] + conference = conferences['future'] + + proposal = create_proposal + + kwargs = {'conference_slug': conference.slug, + 'proposal_slug': proposal.slug} + url = reverse('proposal-reviewer-vote', kwargs=kwargs) + comment, vote_value = 'Must Have', 1 + data = {'vote_value': vote_value, 'comment': comment} + client.post(url, data) + + response = client.get(url) + context = response.context + + assert response.status_code == 200 + assert context['proposal_vote_form'].initial['vote_value'] == vote_value + assert context['proposal_vote_form'].initial['comment'] == comment + + # def test_post_review_proposal_vote_with_invalid_data(self, settings, login, + # conferences, + # create_proposal, + # create_reviewer): + # client = login[0] + # conference = conferences['future'] + + # proposal = create_proposal + + # kwargs = {'conference_slug': conference.slug, + # 'proposal_slug': proposal.slug} + # url = reverse('proposal-reviewer-vote', kwargs=kwargs) + # data = {'vote_value': 12} + # response = client.post(url, data) + + # assert response.status_code == 200 + # assert 'vote_value' in response.context['form_errors'] From bf57cbfa8eda1df92deefa9568cc54810741fe80 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 10 Jan 2016 23:01:42 +0530 Subject: [PATCH 325/666] Add test case for public comment --- tests/integrations/test_reviewer_views.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/integrations/test_reviewer_views.py b/tests/integrations/test_reviewer_views.py index e2cdfee0..ebcf3197 100644 --- a/tests/integrations/test_reviewer_views.py +++ b/tests/integrations/test_reviewer_views.py @@ -207,3 +207,24 @@ def test_get_proposal_reviewer_vote_after_create(self, settings, login, # assert response.status_code == 200 # assert 'vote_value' in response.context['form_errors'] + + +def test_public_comment(settings, login, conferences, + create_proposal): + client = login[0] + conference = conferences['future'] + proposal = create_proposal + + username, password = "tmp", "tmp" + f.create_user(password=password, username=username) + client.login(username=username, password=password) + kwargs = {'conference_slug': conference.slug, + 'proposal_slug': proposal.slug} + + url = reverse('proposal-comment-create', kwargs=kwargs) + data = {'comment': 'Test'} + + response = client.post(url, data) + + assert response.status_code == 302 + assert response.url.endswith('#js-comments') From 25e692d151de4b2440e76d21b9c84eecd5fe281c Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 10 Jan 2016 23:11:32 +0530 Subject: [PATCH 326/666] Pass -m argument in coverage --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5bd80249..e13f83b0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ env: script: - flake8 - coverage run --source=junction --omit='*tests*,*commands*,*migrations*,*admin*,*wsgi*' -m py.test -v --tb=native -- coverage report +- coverage report -m after_success: coveralls From 475f72eadb44222b60e63312b86bc4bfe3c936ea Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 10 Jan 2016 23:26:32 +0530 Subject: [PATCH 327/666] Add proposal filter high level testcase --- tests/factories.py | 2 ++ tests/integrations/test_proposal_views.py | 25 +++++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/tests/factories.py b/tests/factories.py index cee231db..3737f467 100644 --- a/tests/factories.py +++ b/tests/factories.py @@ -212,6 +212,8 @@ def create_conference(**kwargs): conference.proposal_types.add(talks) conference.save() + section = ProposalSectionFactory.create() + conference.proposal_sections.add(section) section = ProposalSectionFactory.create() conference.proposal_sections.add(section) conference.save() diff --git a/tests/integrations/test_proposal_views.py b/tests/integrations/test_proposal_views.py index 2f15c781..7d37127a 100644 --- a/tests/integrations/test_proposal_views.py +++ b/tests/integrations/test_proposal_views.py @@ -59,15 +59,13 @@ def test_create_proposal_with_missing_data(settings, login, conferences): conference = conferences['future'] url = reverse('proposal-create', kwargs={'conference_slug': conference.slug}) - section = conference.proposal_sections.all()[0] - proposal_type = conference.proposal_types.all()[0] data = {'title': 'Proposal Title for the conf', 'description': 'Loong Text', 'target_audience': '1', 'status': '2', - 'proposal_type': str(section.id), - 'proposal_section': str(proposal_type.id)} + 'proposal_type': 34, + 'proposal_section': 34} response = client.post(url, data) assert response.status_code == 200 @@ -229,3 +227,22 @@ def test_update_proposal_with_invalid_data(settings, login, conferences): assert response.status_code == 200 assert 'title' in response.context['errors'] + + +def test_proposal_filters(settings, login, conferences): + client, user = login[0], login[1] + conference = conferences['future'] + section = conference.proposal_sections.all()[1] + proposal_type = conference.proposal_types.all()[1] + f.create_proposal(conference=conference, + proposal_section=section, + proposal_type=proposal_type, + author=user) + kwargs = {'conference_slug': conference.slug} + url = reverse('proposals-list', kwargs=kwargs) + + response = client.get(url, {'proposal_section': section.id, + 'proposal_type': proposal_type.id}) + + assert response.status_code == 200 + assert response.context['is_filtered'] is True From 4d2367b93c9890d405ddfa7b63192deadc26325f Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sun, 31 Jan 2016 19:54:27 +0530 Subject: [PATCH 328/666] fix(proposoal/sharing): remove hardcode values for facebook and twitter - enable facebook share only when a valid facebook id is provided. - make the twitter id and hastags configurable via admin --- .../migrations/0013_auto_20160131_1954.py | 32 ++++++++++++ junction/conferences/models.py | 7 ++- junction/templates/proposals/detail/base.html | 2 +- junction/templates/social_shares.html | 49 +++++++++---------- settings/common.py | 3 +- 5 files changed, 64 insertions(+), 29 deletions(-) create mode 100644 junction/conferences/migrations/0013_auto_20160131_1954.py diff --git a/junction/conferences/migrations/0013_auto_20160131_1954.py b/junction/conferences/migrations/0013_auto_20160131_1954.py new file mode 100644 index 00000000..75467643 --- /dev/null +++ b/junction/conferences/migrations/0013_auto_20160131_1954.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('conferences', '0012_historicalconferenceproposalreviewer'), + ] + + operations = [ + migrations.AddField( + model_name='conference', + name='hashtags', + field=models.CharField(max_length=100, default='', null=True, help_text="Used in social sharing, use commas to separate to tags, no '#' required.", blank=True), + preserve_default=True, + ), + migrations.AddField( + model_name='conference', + name='twitter_id', + field=models.CharField(max_length=100, default='', null=True, help_text='Used in social share widgets.', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='conference', + name='venue', + field=models.ForeignKey(blank=True, null=True, to='conferences.ConferenceVenue'), + preserve_default=True, + ), + ] diff --git a/junction/conferences/models.py b/junction/conferences/models.py index 5d3383e8..dc20295a 100644 --- a/junction/conferences/models.py +++ b/junction/conferences/models.py @@ -31,7 +31,12 @@ class Conference(AuditModel): logo = models.ImageField(blank=True, null=True, upload_to=upload_to) status = models.PositiveSmallIntegerField( choices=ConferenceStatus.CHOICES, verbose_name="Current Status") - venue = models.ForeignKey('ConferenceVenue', null=True) + venue = models.ForeignKey('ConferenceVenue', null=True, blank=True) + + twitter_id = models.CharField(max_length=100, blank=True, null=True, default='', + help_text=_('Used in social share widgets.')) + hashtags = models.CharField(max_length=100, blank=True, null=True, default='', + help_text=_("Used in social sharing, use commas to separate to tags, no '#' required.")) deleted = models.BooleanField(default=False, verbose_name="Is Deleted?") diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index 0556a2e0..1473e49d 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -199,7 +199,7 @@

    Reviewer Actions:

    - {% include "social_shares.html" %} + {% include "social_shares.html" with conference=proposal.conference %}
    diff --git a/junction/templates/social_shares.html b/junction/templates/social_shares.html index aa4283b1..83730cd3 100644 --- a/junction/templates/social_shares.html +++ b/junction/templates/social_shares.html @@ -1,4 +1,4 @@ -
    + diff --git a/settings/common.py b/settings/common.py index 53bc1a3c..991c186c 100644 --- a/settings/common.py +++ b/settings/common.py @@ -32,7 +32,8 @@ 'site_description': 'Junction is a software to manage proposals, reviews, schedule, feedback during conference.', 'google_analytics_id': os.environ.get('GOOGLE_ANALYTICS_ID', None), 'site_url': SITE_URL, - 'footer': 'Copyright © 2015. Python Software Society of India.' + 'footer': 'Copyright © 2015. Python Software Society of India.', + 'facebook_app_id': os.environ.get('FACEBOOK_APP_ID', None), # Enables Facebook sharing of proposals } MIDDLEWARE_CLASSES = ( From fdd9d8bf2672189a65f81c49a6c83619a23299a2 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Tue, 9 Feb 2016 02:14:29 +0530 Subject: [PATCH 329/666] fix(conference): explicity closed or scheduled published should not be accepting proposals --- junction/conferences/models.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/junction/conferences/models.py b/junction/conferences/models.py index dc20295a..95e8671a 100644 --- a/junction/conferences/models.py +++ b/junction/conferences/models.py @@ -10,9 +10,9 @@ from django.utils.timezone import now from django.utils.translation import ugettext as _ from django_extensions.db.fields import AutoSlugField +from simple_history.models import HistoricalRecords from slugify import slugify from uuid_upload_path import upload_to -from simple_history.models import HistoricalRecords # Junction Stuff from junction.base.constants import ConferenceStatus @@ -65,6 +65,9 @@ def save(self, *args, **kwargs): def is_accepting_proposals(self): """Check if any one of the proposal section is accepting proposal. """ + if (self.status == ConferenceStatus.CLOSED_CFP or + self.status == ConferenceStatus.SCHEDULE_PUBLISHED): + return False return self.proposal_types.filter(end_date__gt=now()).exists() From a1319b7519560a71ad1b1c1ec7a810a2c7a1804c Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Tue, 9 Feb 2016 02:24:27 +0530 Subject: [PATCH 330/666] Fix flake8 issue --- junction/base/emailer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/junction/base/emailer.py b/junction/base/emailer.py index 2e3c573a..4b8356ae 100644 --- a/junction/base/emailer.py +++ b/junction/base/emailer.py @@ -21,7 +21,8 @@ def send_email(to, context, template_dir): :rtype: None """ - to_str = lambda x: render_to_string(path.join(template_dir, x), context).strip() + def to_str(template_name): + return render_to_string(path.join(template_dir, template_name), context).strip() subject = to_str('subject.txt') text_message = to_str('message.txt') From 846cfb091ed186b497b94bb21380f28a07f87b42 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 13 Feb 2016 22:56:52 +0530 Subject: [PATCH 331/666] Add conference setting option Conference setting option allows to toggle features like `public voting on proposals`, `displaying the proposals`. The features make the software flexible. These two features are backwward compatible. Depending on the value of the setting object proposal list and detail page is displayed differently. --- junction/base/constants.py | 11 ++++ junction/conferences/admin.py | 8 +++ .../migrations/0013_conferencesetting.py | 66 +++++++++++++++++++ junction/conferences/models.py | 23 +++++-- junction/proposals/views.py | 40 +++++++---- junction/proposals/votes_views.py | 10 ++- junction/templates/proposals/detail/base.html | 4 +- .../partials/proposal-list--items.html | 4 +- .../proposal-list--selected-items.html | 4 +- 9 files changed, 149 insertions(+), 21 deletions(-) create mode 100644 junction/conferences/migrations/0013_conferencesetting.py diff --git a/junction/base/constants.py b/junction/base/constants.py index 07683b8c..4ebc5ada 100644 --- a/junction/base/constants.py +++ b/junction/base/constants.py @@ -80,3 +80,14 @@ class ProposalVotesFilter: _NO_VOTES = [0, "No votes"] _MIN_ONE_VOTE = [1, "Minimum 1 vote"] _SORT = [2, "Sort by vote value"] + + +class ConferenceSettingConstants: + ALLOW_PUBLIC_VOTING_ON_PROPOSALS = { + "name": "allow_public_voting_on_proposals", + "value": True, + "description": "Allow public to vote on proposals"} + + DISPLAY_PROPOSALS_IN_PUBLIC = {"name": "display_proposals_in_public", + "value": True, + "description": "Display proposals in public"} diff --git a/junction/conferences/admin.py b/junction/conferences/admin.py index 767df9bb..791dd96b 100644 --- a/junction/conferences/admin.py +++ b/junction/conferences/admin.py @@ -18,10 +18,17 @@ class ConferenceAdmin(AuditAdmin): class ConferenceModeratorAdmin(AuditAdmin): list_display = ('conference', 'moderator', 'active') + AuditAdmin.list_display + list_filter = ('conference',) class ConferenceProposallReviewerAdmin(AuditAdmin, SimpleHistoryAdmin): list_display = ('conference', 'reviewer', 'active') + AuditAdmin.list_display + list_filter = ('conference',) + + +class ConferenceSettingAdmin(AuditAdmin, SimpleHistoryAdmin): + list_display = ('conference', 'name', 'value') + AuditAdmin.list_display + list_filter = ('conference',) admin.site.register(models.Conference, ConferenceAdmin) @@ -30,3 +37,4 @@ class ConferenceProposallReviewerAdmin(AuditAdmin, SimpleHistoryAdmin): ConferenceProposallReviewerAdmin) admin.site.register(models.ConferenceVenue) admin.site.register(models.Room) +admin.site.register(models.ConferenceSetting, ConferenceSettingAdmin) diff --git a/junction/conferences/migrations/0013_conferencesetting.py b/junction/conferences/migrations/0013_conferencesetting.py new file mode 100644 index 00000000..036fef75 --- /dev/null +++ b/junction/conferences/migrations/0013_conferencesetting.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +from django.conf import settings + + +from junction.base.constants import ConferenceSettingConstants + + +def add_default_values(apps, schema_editor): + """Add all default values + """ + ConferenceSetting = apps.get_model("conferences", "ConferenceSetting") + public_voting = ConferenceSettingConstants.ALLOW_PUBLIC_VOTING_ON_PROPOSALS + display_propsals = ConferenceSettingConstants.DISPLAY_PROPOSALS_IN_PUBLIC + + Conference = apps.get_model("conferences", "Conference") + for conf in Conference.objects.all(): + ConferenceSetting.objects.create( + name=public_voting['name'], + value=public_voting['value'], + description=public_voting['description'], + conference=conf) + ConferenceSetting.objects.create( + name=display_propsals['name'], + value=display_propsals['value'], + description=display_propsals['description'], + conference=conf) + + +def remove_default_values(apps, schema_editor): + ConferenceSetting = apps.get_model("conferences", "ConferenceSetting") + objs = ConferenceSetting.objects.all() + for obj in objs: + obj.delete() + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('conferences', '0012_historicalconferenceproposalreviewer'), + ] + + operations = [ + migrations.CreateModel( + name='ConferenceSetting', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')), + ('name', models.CharField(max_length=100, db_index=True)), + ('value', models.BooleanField(default=False)), + ('description', models.CharField(max_length=255)), + ('conference', models.ForeignKey(to='conferences.Conference')), + ('created_by', models.ForeignKey(related_name='created_conferencesetting_set', verbose_name='Created By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ('modified_by', models.ForeignKey(related_name='updated_conferencesetting_set', verbose_name='Modified By', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ], + options={ + 'abstract': False, + }, + bases=(models.Model,), + ), + migrations.RunPython(add_default_values, remove_default_values) + ] diff --git a/junction/conferences/models.py b/junction/conferences/models.py index 5d3383e8..466386b5 100644 --- a/junction/conferences/models.py +++ b/junction/conferences/models.py @@ -24,7 +24,8 @@ class Conference(AuditModel): """ Conference/Event master """ name = models.CharField(max_length=255, verbose_name="Conference Name") - slug = AutoSlugField(max_length=255, unique=True, populate_from=('name',), editable=True) + slug = AutoSlugField(max_length=255, unique=True, populate_from=('name',), + editable=True) description = models.TextField(default="") start_date = models.DateField(verbose_name="Start Date") end_date = models.DateField(verbose_name="End Date") @@ -45,7 +46,8 @@ def __str__(self): return self.name def get_absolute_url(self): - return reverse("conference-detail", kwargs={'conference_slug': self.slug}) + return reverse("conference-detail", kwargs={'conference_slug': + self.slug}) def clean(self): if self.end_date < self.start_date: @@ -84,10 +86,12 @@ def __str__(self): class ConferenceProposalReviewer(AuditModel): """ List of global proposal reviewers """ - conference = models.ForeignKey(Conference, related_name='proposal_reviewers') + conference = models.ForeignKey(Conference, + related_name='proposal_reviewers') reviewer = models.ForeignKey(User) active = models.BooleanField(default=True, verbose_name="Is Active?") - nick = models.CharField(max_length=255, verbose_name="Nick Name", default="Reviewer") + nick = models.CharField(max_length=255, verbose_name="Nick Name", + default="Reviewer") history = HistoricalRecords() class Meta: @@ -120,3 +124,14 @@ class Room(AuditModel): def __str__(self): return "{}, {}".format(self.name, self.venue) + + +@python_2_unicode_compatible +class ConferenceSetting(AuditModel): + conference = models.ForeignKey(Conference) + name = models.CharField(max_length=100, db_index=True) + value = models.BooleanField(default=False) + description = models.CharField(max_length=255) + + def __str__(self): + return "{}: {}".format(self.name, self.value) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index c1d5579f..6a25b772 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -18,7 +18,8 @@ from junction.base.constants import (ProposalReviewStatus, ProposalStatus, - ConferenceStatus) + ConferenceStatus, + ConferenceSettingConstants) from junction.conferences.models import Conference from junction.feedback import permissions as feedback_permission @@ -48,7 +49,13 @@ def list_proposals(request, conference_slug): conference = get_object_or_404( Conference, slug=conference_slug) # .prefetch_related('proposal_types', 'proposal_sections') - + public_voting = ConferenceSettingConstants.ALLOW_PUBLIC_VOTING_ON_PROPOSALS + public_voting_setting = conference.conferencesetting_set.filter( + name=public_voting['name']).first() + if public_voting_setting: + public_voting_setting_value = public_voting_setting.value + else: + public_voting_setting_value = True proposals_qs = Proposal.objects.select_related( 'proposal_type', 'proposal_section', 'conference', 'author', ).filter(conference=conference) @@ -96,7 +103,8 @@ def list_proposals(request, conference_slug): 'is_filtered': is_filtered, 'is_reviewer': is_reviewer, 'conference': conference, - 'ConferenceStatus': ConferenceStatus}) + 'ConferenceStatus': ConferenceStatus, + 'public_voting_setting': public_voting_setting_value}) @login_required @@ -154,15 +162,20 @@ def detail_proposal(request, conference_slug, slug): is_reviewer = permissions.is_proposal_reviewer(request.user, conference) is_section_reviewer = permissions.is_proposal_section_reviewer( request.user, conference, proposal) - vote_value = 0 - voting = True if conference.start_date > datetime.now().date() else False - try: - if request.user.is_authenticated(): - proposal_vote = ProposalVote.objects.get( - proposal=proposal, voter=request.user) - vote_value = 1 if proposal_vote.up_vote else -1 - except ProposalVote.DoesNotExist: - pass + public_voting = ConferenceSettingConstants.ALLOW_PUBLIC_VOTING_ON_PROPOSALS + public_voting_setting = conference.conferencesetting_set.filter( + name=public_voting['name']).first() + vote_value, voting, public_voting_setting_value = 0, False, True + if public_voting_setting: + public_voting_setting_value = public_voting_setting.value + voting = True if conference.start_date > datetime.now().date() else False + try: + if request.user.is_authenticated(): + proposal_vote = ProposalVote.objects.get( + proposal=proposal, voter=request.user) + vote_value = 1 if proposal_vote.up_vote else -1 + except ProposalVote.DoesNotExist: + pass ctx = { 'login_url': settings.LOGIN_URL, @@ -174,7 +187,8 @@ def detail_proposal(request, conference_slug, slug): 'is_reviewer': is_reviewer, 'is_section_reviewer': is_section_reviewer, 'can_view_feedback': False, - 'can_vote': voting + 'can_vote': voting, + 'public_voting_setting': public_voting_setting_value } if proposal.scheduleitem_set.all(): diff --git a/junction/proposals/votes_views.py b/junction/proposals/votes_views.py index ed1c34df..d5274f06 100644 --- a/junction/proposals/votes_views.py +++ b/junction/proposals/votes_views.py @@ -6,8 +6,9 @@ from django.core.urlresolvers import reverse from django.core.exceptions import PermissionDenied from django.http.response import HttpResponse, HttpResponseRedirect +from django.http import HttpResponseForbidden -from junction.base.constants import ProposalUserVoteRole +from junction.base.constants import ProposalUserVoteRole, ConferenceSettingConstants from junction.conferences.models import Conference from .forms import ProposalReviewerVoteForm @@ -27,6 +28,13 @@ @login_required def proposal_vote(request, conference_slug, proposal_slug, up_vote): conference = get_object_or_404(Conference, slug=conference_slug) + + public_voting = ConferenceSettingConstants.ALLOW_PUBLIC_VOTING_ON_PROPOSALS + public_voting_setting = conference.conferencesetting_set.filter( + name=public_voting['name']).first() + if public_voting_setting and not public_voting_setting.value: + return HttpResponseForbidden() + proposal = get_object_or_404( Proposal, slug=proposal_slug, conference=conference) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index 0556a2e0..966db7af 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -90,6 +90,7 @@


    + {% if public_voting_setting %}
    {% if can_vote %} @@ -117,7 +118,8 @@

    -
    +
    + {% endif %}
    diff --git a/junction/templates/proposals/partials/proposal-list--items.html b/junction/templates/proposals/partials/proposal-list--items.html index 25495db7..88ab1c36 100644 --- a/junction/templates/proposals/partials/proposal-list--items.html +++ b/junction/templates/proposals/partials/proposal-list--items.html @@ -6,13 +6,15 @@

    {{ title }}

    -
    +{% endblock %} diff --git a/junction/urls.py b/junction/urls.py index 0f52b6c3..16ae6402 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -52,6 +52,9 @@ url(r'^(?P[\w-]+)/dashboard/reviewers/', 'junction.proposals.dashboard.reviewer_comments_dashboard', name='proposal-reviewers-dashboard'), + url(r'^(?P[\w-]+)/dashboard/proposal_state/$', + 'junction.proposals.dashboard.proposal_state', + name='proposal-state'), url(r'^(?P[\w-]+)/dashboard/$', 'junction.proposals.dashboard.proposals_dashboard', name='proposal-dashboard'), url(r'^(?P[\w-]+)/dashboard/votes/$', From e478654a1f40a2e26a37f08766e2429df2feed74 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Thu, 14 Jul 2016 01:34:05 +0530 Subject: [PATCH 470/666] Convert defaultdict to dict before passing to template --- junction/proposals/dashboard.py | 3 +-- junction/templates/proposals/dashboard.html | 12 ++++++------ junction/templates/proposals/review_state.html | 7 ++++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index 60818180..62ba46f2 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -341,8 +341,7 @@ def proposal_state(request, conference_slug): state = request.GET.get('q', 'unreviewed') proposals = services.group_proposals_by_reveiew_state(conf=conf, state=state) - return render(request, 'proposals/review_state.html', {'conference': conf, - 'proposals': proposals, + 'proposals': dict(proposals), 'state': state.title()}) diff --git a/junction/templates/proposals/dashboard.html b/junction/templates/proposals/dashboard.html index 87b46963..9f99bf68 100644 --- a/junction/templates/proposals/dashboard.html +++ b/junction/templates/proposals/dashboard.html @@ -88,17 +88,17 @@ Type Name Total - - Reviewed - - UnReviewed + Reviewed + UnReviewed {% for group,count in group_by_type.items %} {{count.3}} {{count.0}} - {{count.1}} - {{count.2}} + + {{count.1}} + + {{count.2}} {% endfor %} diff --git a/junction/templates/proposals/review_state.html b/junction/templates/proposals/review_state.html index 74f66172..677e8e5b 100644 --- a/junction/templates/proposals/review_state.html +++ b/junction/templates/proposals/review_state.html @@ -58,13 +58,14 @@
    {{ state }} proposals
    {% for section, proposal_list in proposals.items %} -

    {{ section }}

    +

    {{ section }}

    {% for proposal in proposal_list %} -

    +

    {{ forloop.counter}}. {{ proposal.title|capfirst }} - {{ proposal.proposal_type }} -

    +

    {% endfor %} +
    {% endfor %}
    From eda3513edc235b99787df445bc7cd78fb2c4adac Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Thu, 14 Jul 2016 01:55:58 +0530 Subject: [PATCH 471/666] Fix css for review state page --- junction/templates/proposals/dashboard.html | 12 +++---- .../templates/proposals/review_state.html | 36 ++++++++++--------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/junction/templates/proposals/dashboard.html b/junction/templates/proposals/dashboard.html index 9f99bf68..5b0a9abb 100644 --- a/junction/templates/proposals/dashboard.html +++ b/junction/templates/proposals/dashboard.html @@ -72,8 +72,10 @@ {{total}} - {{reviewed}} - {{unreviewed}} + + {{reviewed}} + + {{unreviewed}}
    @@ -95,10 +97,8 @@ {{count.3}} {{count.0}} - - {{count.1}} - - {{count.2}} + {{count.1}} + {{count.2}} {% endfor %} diff --git a/junction/templates/proposals/review_state.html b/junction/templates/proposals/review_state.html index 677e8e5b..c4d2bd82 100644 --- a/junction/templates/proposals/review_state.html +++ b/junction/templates/proposals/review_state.html @@ -52,26 +52,28 @@
    -
    -
    -
    -
    {{ state }} proposals
    -
    - {% for section, proposal_list in proposals.items %} -

    {{ section }}

    - {% for proposal in proposal_list %} -

    - {{ forloop.counter}}. {{ proposal.title|capfirst }} - - {{ proposal.proposal_type }} -

    - {% endfor %} +
    +
    +
    +
    +

    +

    {{ state }} proposals

    +


    - {% endfor %} +
    + {% for section, proposal_list in proposals.items %} +

    {{ section }}

    + {% for proposal in proposal_list %} +

    + {{ forloop.counter}}. {{ proposal.title|capfirst }} + - {{ proposal.proposal_type }} +

    + {% endfor %} +
    + {% endfor %} +
    -
    - -
    {% endblock %} From 9912785136ca6224a8d4a111492679d0c546ec63 Mon Sep 17 00:00:00 2001 From: RishabhJain2018 Date: Thu, 14 Jul 2016 18:43:52 +0530 Subject: [PATCH 472/666] Added Frontend --- junction/profiles/views.py | 5 +++-- junction/templates/profiles/userprofile.html | 9 +-------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/junction/profiles/views.py b/junction/profiles/views.py index 0a9720b9..a3468324 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -34,6 +34,7 @@ def profile(request): city = request.POST['city'] contact_no = request.POST['contact_no'] Profile.objects.create(user=request.user, city=city, contact_no=contact_no) - return HttpResponseRedirect("/profile") + return HttpResponseRedirect("/profiles") + elif request.method=="GET": - return render(request, 'profiles/userprofile.html') \ No newline at end of file + return render(request, 'profiles/userprofile.html') diff --git a/junction/templates/profiles/userprofile.html b/junction/templates/profiles/userprofile.html index ffb55912..02b74c9b 100644 --- a/junction/templates/profiles/userprofile.html +++ b/junction/templates/profiles/userprofile.html @@ -42,7 +42,7 @@

    Edit Profile

    - +
    @@ -50,13 +50,6 @@

    Edit Profile

    - -
    - {% csrf_token %} -   -
    From 70b86fe871639b71ff853ac0761f9692099174c6 Mon Sep 17 00:00:00 2001 From: RishabhJain2018 Date: Thu, 14 Jul 2016 18:55:25 +0530 Subject: [PATCH 473/666] flake8 fixes --- junction/profiles/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/junction/profiles/views.py b/junction/profiles/views.py index a3468324..c7bd6965 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -10,7 +10,7 @@ # Junction Stuff from junction.conferences.models import Conference -#Profile Stuff +# Profile Stuff from .models import Profile @@ -30,11 +30,11 @@ def dashboard(request): @login_required def profile(request): - if request.method=="POST": + if request.method == "POST": city = request.POST['city'] contact_no = request.POST['contact_no'] Profile.objects.create(user=request.user, city=city, contact_no=contact_no) return HttpResponseRedirect("/profiles") elif request.method=="GET": - return render(request, 'profiles/userprofile.html') + return render(request, 'profiles/userprofile.html') From 0316b708e493832b30594d463f54557348c28c8e Mon Sep 17 00:00:00 2001 From: RishabhJain2018 Date: Thu, 14 Jul 2016 19:07:15 +0530 Subject: [PATCH 474/666] flake8 fixes --- junction/profiles/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/profiles/views.py b/junction/profiles/views.py index c7bd6965..2ceda094 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -36,5 +36,5 @@ def profile(request): Profile.objects.create(user=request.user, city=city, contact_no=contact_no) return HttpResponseRedirect("/profiles") - elif request.method=="GET": + elif request.method == "GET": return render(request, 'profiles/userprofile.html') From 0d0bfcc8021f7a06d67848fbaaa2045bb563c2c8 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sun, 17 Jul 2016 21:29:26 +0530 Subject: [PATCH 475/666] Fix form --- junction/templates/proposals/votes-dashboard.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/junction/templates/proposals/votes-dashboard.html b/junction/templates/proposals/votes-dashboard.html index a39ebea3..dfa119c4 100644 --- a/junction/templates/proposals/votes-dashboard.html +++ b/junction/templates/proposals/votes-dashboard.html @@ -30,15 +30,15 @@

    Proposal Votes Dashboard

    {% csrf_token %} {% bootstrap_form form %}

    - - {% buttons %} + {% buttons %}
    - {% endbuttons %} + {% endbuttons %} +

    From 7d27bb8ce8af973b12bb2afb33d554fd923554ac Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sun, 17 Jul 2016 22:14:12 +0530 Subject: [PATCH 476/666] Add sort by reviewer votes in votes dashboard --- junction/base/constants.py | 3 ++- junction/proposals/dashboard.py | 8 +++++++- junction/proposals/models.py | 10 ++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/junction/base/constants.py b/junction/base/constants.py index 0384cdfd..fa12d2c7 100644 --- a/junction/base/constants.py +++ b/junction/base/constants.py @@ -80,7 +80,8 @@ class ProposalReviewerComment: class ProposalVotesFilter: _NO_VOTES = [0, "No votes"] _MIN_ONE_VOTE = [1, "Minimum 1 vote"] - _SORT = [2, "Sort by vote value"] + _SORT_BY_SUM = [2, "Sort by total votes"] + _SORT_BY_REVIEWER = [3, "Sort by your votes"] class ConferenceSettingConstants: diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index 62ba46f2..469377c0 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -247,10 +247,16 @@ def reviewer_votes_dashboard(request, conference_slug): elif votes == ProposalVotesFilter.MIN_ONE_VOTE: proposals_qs = [ p for p in proposals_qs if p.get_reviewer_votes_count() >= votes] - elif votes == ProposalVotesFilter.SORT: + elif votes == ProposalVotesFilter.SORT_BY_SUM: proposals_qs = sorted( proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), reverse=True) + elif votes == ProposalVotesFilter.SORT_BY_REVIEWER: + proposals_qs = sorted( + proposals_qs, + key=lambda x: x.get_reviewer_vote_value(reviewer=request.user), + reverse=True, + ) for section in proposal_sections: section_proposals = [ diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 03dc87d7..cfcb0b11 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -187,6 +187,16 @@ def get_reviewer_votes_sum(self): sum_of_votes = sum((v.vote_value.vote_value for v in votes)) return sum_of_votes + def get_reviewer_vote_value(self, reviewer): + try: + vote = ProposalSectionReviewerVote.objects.get( + proposal=self, voter__conference_reviewer__reviewer=reviewer, + ) + return vote.vote_value.vote_value + except ProposalSectionReviewerVote.DoesNotExist as e: + print('{}'.format(e)) + return 0 + def get_reviewers_count(self): """ Count of reviewers for given proposal section """ return ProposalSectionReviewer.objects.filter( From b5fef47d6f72fa2ffb38557c449c2e7bdf9aa78b Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sun, 17 Jul 2016 22:35:37 +0530 Subject: [PATCH 477/666] Use nick name of reviewer in mails --- junction/templates/proposals/email/comment/message.html | 2 +- junction/templates/proposals/email/comment/message.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/junction/templates/proposals/email/comment/message.html b/junction/templates/proposals/email/comment/message.html index b4523b82..16e4eaa6 100644 --- a/junction/templates/proposals/email/comment/message.html +++ b/junction/templates/proposals/email/comment/message.html @@ -14,7 +14,7 @@

    {{proposal.title}}" by - {% if comment.private %} + {% if comment.private or comment.reviewer %} {% if by_author %} Author {% else %} diff --git a/junction/templates/proposals/email/comment/message.txt b/junction/templates/proposals/email/comment/message.txt index a827aadf..a9a3e656 100644 --- a/junction/templates/proposals/email/comment/message.txt +++ b/junction/templates/proposals/email/comment/message.txt @@ -1,4 +1,4 @@ -There is a new comment on {{host}}{{proposal.get_absolute_url}} by {% if comment.private %}one of the reviewer{% else %}*{{comment.commenter}}*{% endif %}: +There is a new comment on {{host}}{{proposal.get_absolute_url}} by {% if comment.private or comment.reviewer %}{% if by_author %}Author{% else %}{{comment.get_reviewer_nick}}{% endif %}{% else %}{{comment.commenter}}{% endif %}: "{{comment.comment}}" From eb02763073de91ae2ac2b57abab134490a2afddc Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sun, 17 Jul 2016 22:39:39 +0530 Subject: [PATCH 478/666] Update text in template --- junction/templates/proposals/to_review.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/templates/proposals/to_review.html b/junction/templates/proposals/to_review.html index 672fc008..3a5dc38c 100644 --- a/junction/templates/proposals/to_review.html +++ b/junction/templates/proposals/to_review.html @@ -40,7 +40,7 @@ {% if proposals_to_review %}

    Proposals To Review


    -

    You can review proposals from these section(s).

    +

    Your sections to review are

    {% for section in proposal_reviewer_sections %} {{ section.name }}
    {% endfor %} From 67b41239848c80334d48e68525f919ebbf894241 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 18 Jul 2016 22:28:15 +0530 Subject: [PATCH 479/666] Sort all proposals when sorting by total votes --- junction/proposals/dashboard.py | 17 +++++++++-------- .../templates/proposals/votes-dashboard.html | 1 + 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index 469377c0..cea45e30 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -247,21 +247,22 @@ def reviewer_votes_dashboard(request, conference_slug): elif votes == ProposalVotesFilter.MIN_ONE_VOTE: proposals_qs = [ p for p in proposals_qs if p.get_reviewer_votes_count() >= votes] - elif votes == ProposalVotesFilter.SORT_BY_SUM: - proposals_qs = sorted( - proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), - reverse=True) elif votes == ProposalVotesFilter.SORT_BY_REVIEWER: proposals_qs = sorted( proposals_qs, key=lambda x: x.get_reviewer_vote_value(reviewer=request.user), reverse=True, ) + elif votes == ProposalVotesFilter.SORT_BY_SUM: + proposals_qs = sorted( + proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), + reverse=True) + proposals = [s_items('', proposals_qs)] - for section in proposal_sections: - section_proposals = [ - p for p in proposals_qs if p.proposal_section == section] - proposals.append(s_items(section, section_proposals)) + if votes != ProposalVotesFilter.SORT_BY_SUM: + for section in proposal_sections: + section_proposals = [p for p in proposals_qs if p.proposal_section == section] + proposals.append(s_items(section, section_proposals)) return render(request, 'proposals/votes-dashboard.html', {'conference': conference, diff --git a/junction/templates/proposals/votes-dashboard.html b/junction/templates/proposals/votes-dashboard.html index dfa119c4..0cb4564d 100644 --- a/junction/templates/proposals/votes-dashboard.html +++ b/junction/templates/proposals/votes-dashboard.html @@ -41,6 +41,7 @@

    Proposal Votes Dashboard


    +
    {% for section_items in proposals %} {% if section_items.proposals %} From 51dc483439dc94f4b17113c4c6dbd8d9c02397c5 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Mon, 18 Jul 2016 22:32:05 +0530 Subject: [PATCH 480/666] Remove print statement --- junction/proposals/models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index cfcb0b11..a220612f 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -193,8 +193,7 @@ def get_reviewer_vote_value(self, reviewer): proposal=self, voter__conference_reviewer__reviewer=reviewer, ) return vote.vote_value.vote_value - except ProposalSectionReviewerVote.DoesNotExist as e: - print('{}'.format(e)) + except ProposalSectionReviewerVote.DoesNotExist: return 0 def get_reviewers_count(self): From 5951407ba6221548ddd319846bef8653b8f0793d Mon Sep 17 00:00:00 2001 From: RishabhJain2018 Date: Mon, 18 Jul 2016 22:57:13 +0530 Subject: [PATCH 481/666] Exception Handled --- junction/profiles/views.py | 4 ++-- junction/templates/profiles/userprofile.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/junction/profiles/views.py b/junction/profiles/views.py index 2ceda094..d98d3a6f 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -31,8 +31,8 @@ def dashboard(request): @login_required def profile(request): if request.method == "POST": - city = request.POST['city'] - contact_no = request.POST['contact_no'] + city = request.POST.get('city') + contact_no = request.POST.get('contact_no') Profile.objects.create(user=request.user, city=city, contact_no=contact_no) return HttpResponseRedirect("/profiles") diff --git a/junction/templates/profiles/userprofile.html b/junction/templates/profiles/userprofile.html index 02b74c9b..a2b2a591 100644 --- a/junction/templates/profiles/userprofile.html +++ b/junction/templates/profiles/userprofile.html @@ -42,7 +42,7 @@

    Edit Profile

    - +
    From 99ed2d8afa40067e7f373e955bb3f713fe25bb31 Mon Sep 17 00:00:00 2001 From: RaviShanker B Date: Tue, 19 Jul 2016 13:21:04 +0530 Subject: [PATCH 482/666] upgrade django to 1.8 --- .travis.yml | 2 +- junction/feedback/service.py | 2 +- requirements.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8428752f..bc344982 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: python sudo: false python: - '2.7' -- '3.4' +- '3.5' addons: postgresql: "9.3" diff --git a/junction/feedback/service.py b/junction/feedback/service.py index f40e026c..0bd39d7b 100644 --- a/junction/feedback/service.py +++ b/junction/feedback/service.py @@ -56,7 +56,7 @@ def get_choice_feedback_questions(conference_id): schedule item type. """ qs = ChoiceFeedbackQuestion.objects.filter( - conference_id=conference_id).select_related('allowed_values') + conference_id=conference_id).prefetch_related('allowed_values') return _get_question_oragnized_by_type(qs) diff --git a/requirements.txt b/requirements.txt index b084b10e..1ed613dc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==1.7.9 +Django==1.8.14 celery==3.1.18 djangorestframework==3.1.3 django-filter==0.10.0 From 8256cb83ab365c617a082712db80198062a12c83 Mon Sep 17 00:00:00 2001 From: RaviShanker B Date: Tue, 19 Jul 2016 13:55:35 +0530 Subject: [PATCH 483/666] upgrade pip to 8.1.2 --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bc344982..83c683d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,8 @@ cache: - $HOME/.pip-cache/ install: - - pip install -r requirements-dev.txt --allow-all-external --download-cache $HOME/.pip-cache + - pip install pip==8.1.2 + - pip install -r requirements-dev.txt --allow-all-external - pip install coveralls env: From c32035b851d1beb9a9b08edf3abc1e46f710a09b Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sat, 23 Jul 2016 16:35:50 +0530 Subject: [PATCH 484/666] Add sort option based on proposal selection --- junction/base/constants.py | 1 + junction/proposals/dashboard.py | 41 ++------------ junction/proposals/models.py | 9 +++- junction/proposals/utils.py | 94 +++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 39 deletions(-) create mode 100644 junction/proposals/utils.py diff --git a/junction/base/constants.py b/junction/base/constants.py index fa12d2c7..bff88dc7 100644 --- a/junction/base/constants.py +++ b/junction/base/constants.py @@ -82,6 +82,7 @@ class ProposalVotesFilter: _MIN_ONE_VOTE = [1, "Minimum 1 vote"] _SORT_BY_SUM = [2, "Sort by total votes"] _SORT_BY_REVIEWER = [3, "Sort by your votes"] + _SORT_BY_SELECTION = [4, "Sort by selection"] class ConferenceSettingConstants: diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index cea45e30..d5a36c5b 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -25,7 +25,7 @@ from .forms import ProposalVotesFilterForm from .permissions import is_conference_moderator - +from .utils import _sort_proposals_for_dashboard from .models import ( Proposal, ProposalComment, @@ -193,7 +193,7 @@ def reviewer_comments_dashboard(request, conference_slug): @require_http_methods(['GET', 'POST']) def reviewer_votes_dashboard(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) - + user = request.user if not is_conference_moderator(user=request.user, conference=conference): raise PermissionDenied @@ -226,43 +226,8 @@ def reviewer_votes_dashboard(request, conference_slug): 'errors': form.errors}) # Valid form - cps = form.cleaned_data['proposal_section'] - cpt = form.cleaned_data['proposal_type'] - votes = form.cleaned_data['votes'] - review_status = form.cleaned_data['review_status'] - proposal_sections = conference.proposal_sections.all() - if cps != 'all': - proposal_sections = ProposalSection.objects.filter(pk=cps) - if cpt != 'all': - proposals_qs = proposals_qs.filter(proposal_type__id__in=cpt) - if votes != 'all': - votes = int(votes) - if review_status != 'all': - proposals_qs = proposals_qs.filter(review_status=review_status) - - if votes == ProposalVotesFilter.NO_VOTES: - proposals_qs = [ - p for p in proposals_qs if p.get_reviewer_votes_count() == votes] - elif votes == ProposalVotesFilter.MIN_ONE_VOTE: - proposals_qs = [ - p for p in proposals_qs if p.get_reviewer_votes_count() >= votes] - elif votes == ProposalVotesFilter.SORT_BY_REVIEWER: - proposals_qs = sorted( - proposals_qs, - key=lambda x: x.get_reviewer_vote_value(reviewer=request.user), - reverse=True, - ) - elif votes == ProposalVotesFilter.SORT_BY_SUM: - proposals_qs = sorted( - proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), - reverse=True) - proposals = [s_items('', proposals_qs)] - - if votes != ProposalVotesFilter.SORT_BY_SUM: - for section in proposal_sections: - section_proposals = [p for p in proposals_qs if p.proposal_section == section] - proposals.append(s_items(section, section_proposals)) + proposals = _sort_proposals_for_dashboard(conference, proposals_qs, user, form) return render(request, 'proposals/votes-dashboard.html', {'conference': conference, diff --git a/junction/proposals/models.py b/junction/proposals/models.py index a220612f..3c4bf95b 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -15,7 +15,8 @@ from simple_history.models import HistoricalRecords # Junction Stuff -from junction.base.constants import ProposalReviewStatus, ProposalStatus, ProposalTargetAudience, ProposalUserVoteRole +from junction.base.constants import ProposalReviewStatus, ProposalStatus, ProposalTargetAudience, ProposalUserVoteRole, \ + ProposalReviewVote from junction.base.models import AuditModel, TimeAuditModel from junction.conferences.models import Conference, ConferenceProposalReviewer @@ -202,6 +203,12 @@ def get_reviewers_count(self): proposal_section=self.proposal_section ).count() + def has_negative_votes(self): + """ Show sum of reviewer votes for given vote value. """ + return ProposalSectionReviewerVote.objects.filter( + proposal=self, vote_value__vote_value=ProposalReviewVote.NOT_ALLOWED, + ).count() > 0 + class Meta: unique_together = ("conference", "slug") diff --git a/junction/proposals/utils.py b/junction/proposals/utils.py new file mode 100644 index 00000000..859c789b --- /dev/null +++ b/junction/proposals/utils.py @@ -0,0 +1,94 @@ +import collections + +from junction.base.constants import ProposalReviewVote, ProposalVotesFilter +from junction.proposals.models import ProposalSection + + +def _sort_proposals_for_dashboard(conference, proposals_qs, user, form): + """ + """ + cps = form.cleaned_data['proposal_section'] + cpt = form.cleaned_data['proposal_type'] + votes = form.cleaned_data['votes'] + review_status = form.cleaned_data['review_status'] + + proposal_sections = conference.proposal_sections.all() + s_items = collections.namedtuple('section_items', 'section proposals') + proposals = [] + + if cps != 'all': + proposal_sections = ProposalSection.objects.filter(pk=cps) + if cpt != 'all': + proposals_qs = proposals_qs.filter(proposal_type__id__in=cpt) + if votes != 'all': + votes = int(votes) + if review_status != 'all': + proposals_qs = proposals_qs.filter(review_status=review_status) + + if votes == ProposalVotesFilter.NO_VOTES: + proposals_qs = [ + p for p in proposals_qs if p.get_reviewer_votes_count() == votes] + elif votes == ProposalVotesFilter.MIN_ONE_VOTE: + proposals_qs = [ + p for p in proposals_qs if p.get_reviewer_votes_count() >= votes] + elif votes == ProposalVotesFilter.SORT_BY_REVIEWER: + proposals_qs = sorted( + proposals_qs, + key=lambda x: x.get_reviewer_vote_value(reviewer=user), + reverse=True, + ) + elif votes == ProposalVotesFilter.SORT_BY_SUM: + proposals_qs = sorted( + proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), + reverse=True) + proposals = [s_items('', proposals_qs)] + + elif votes == ProposalVotesFilter.SORT_BY_SELECTION: + # Selection of proposal is based on conference guidelines. + # More info is available at http://tiny.cc/qzo5cy + + proposals_qs = [p for p in proposals_qs if not p.has_negative_votes()] + proposals_qs = sorted(proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), reverse=True) + + selected = [p for p in proposals_qs if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) > 1] + proposals.append(s_items('Selected', selected)) + + batches = [] + + batch1 = [p for p in proposals_qs + if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) > 0 and + p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 1] + proposals.append(s_items('Batch 1', batch1)) + batches += batch1 + + batch2 = [p for p in proposals_qs + if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) > 0 and + p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 0 and + p not in batches] + proposals.append(s_items('Batch 2', batch2)) + batches += batch2 + + batch3 = [p for p in proposals_qs + if p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 1 and + p not in batches] + proposals.append(s_items('Batch 3', batch3)) + batches += batch3 + + batch4 = [p for p in proposals_qs + if p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 0 and + p.get_reviewer_votes_count_by_value(ProposalReviewVote.NOT_BAD) > 1 and + p not in batches] + proposals.append(s_items('Batch 4', batch4)) + + # proposals = selected + batch1 + batch2 + batch3 + batch4 + # unique_proposals = set() + # proposals = [x for x in proposals if not (x in unique_proposals or unique_proposals.add(x))] + # proposals = [s_items('', set(proposals))] + + if votes not in (ProposalVotesFilter.SORT_BY_SUM, ProposalVotesFilter.SORT_BY_SELECTION): + print('f') + for section in proposal_sections: + section_proposals = [p for p in proposals_qs if p.proposal_section == section] + proposals.append(s_items(section, section_proposals)) + + return proposals From bc9fea5457522e85b2777af0c2924e45a8996c3e Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sat, 23 Jul 2016 16:38:28 +0530 Subject: [PATCH 485/666] Fix flake8 errors --- junction/proposals/dashboard.py | 2 -- junction/proposals/models.py | 4 ++-- junction/proposals/utils.py | 6 ------ 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index d5a36c5b..e86dd7f3 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -19,7 +19,6 @@ from junction.base.constants import ( ProposalReviewVote, ProposalStatus, - ProposalVotesFilter ) from junction.conferences.models import Conference, ConferenceProposalReviewer @@ -29,7 +28,6 @@ from .models import ( Proposal, ProposalComment, - ProposalSection, ProposalSectionReviewer, ProposalSectionReviewerVoteValue ) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 3c4bf95b..7099e51f 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -15,8 +15,8 @@ from simple_history.models import HistoricalRecords # Junction Stuff -from junction.base.constants import ProposalReviewStatus, ProposalStatus, ProposalTargetAudience, ProposalUserVoteRole, \ - ProposalReviewVote +from junction.base.constants import ProposalReviewStatus, ProposalStatus, ProposalTargetAudience, \ + ProposalUserVoteRole, ProposalReviewVote from junction.base.models import AuditModel, TimeAuditModel from junction.conferences.models import Conference, ConferenceProposalReviewer diff --git a/junction/proposals/utils.py b/junction/proposals/utils.py index 859c789b..41d1c722 100644 --- a/junction/proposals/utils.py +++ b/junction/proposals/utils.py @@ -80,13 +80,7 @@ def _sort_proposals_for_dashboard(conference, proposals_qs, user, form): p not in batches] proposals.append(s_items('Batch 4', batch4)) - # proposals = selected + batch1 + batch2 + batch3 + batch4 - # unique_proposals = set() - # proposals = [x for x in proposals if not (x in unique_proposals or unique_proposals.add(x))] - # proposals = [s_items('', set(proposals))] - if votes not in (ProposalVotesFilter.SORT_BY_SUM, ProposalVotesFilter.SORT_BY_SELECTION): - print('f') for section in proposal_sections: section_proposals = [p for p in proposals_qs if p.proposal_section == section] proposals.append(s_items(section, section_proposals)) From b8057d929a90fcc1ec713911e50b4901e662ef58 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraj Date: Sat, 23 Jul 2016 23:09:20 +0530 Subject: [PATCH 486/666] Revert "upgrade django to 1.8 #201" --- .travis.yml | 5 ++--- junction/feedback/service.py | 2 +- requirements.txt | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 83c683d3..8428752f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: python sudo: false python: - '2.7' -- '3.5' +- '3.4' addons: postgresql: "9.3" @@ -11,8 +11,7 @@ cache: - $HOME/.pip-cache/ install: - - pip install pip==8.1.2 - - pip install -r requirements-dev.txt --allow-all-external + - pip install -r requirements-dev.txt --allow-all-external --download-cache $HOME/.pip-cache - pip install coveralls env: diff --git a/junction/feedback/service.py b/junction/feedback/service.py index 0bd39d7b..f40e026c 100644 --- a/junction/feedback/service.py +++ b/junction/feedback/service.py @@ -56,7 +56,7 @@ def get_choice_feedback_questions(conference_id): schedule item type. """ qs = ChoiceFeedbackQuestion.objects.filter( - conference_id=conference_id).prefetch_related('allowed_values') + conference_id=conference_id).select_related('allowed_values') return _get_question_oragnized_by_type(qs) diff --git a/requirements.txt b/requirements.txt index 1ed613dc..b084b10e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==1.8.14 +Django==1.7.9 celery==3.1.18 djangorestframework==3.1.3 django-filter==0.10.0 From 8626b1253527ae94cb8b63460551a58bffc02358 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sat, 23 Jul 2016 23:39:35 +0530 Subject: [PATCH 487/666] Update to Django 1.8 --- .travis.yml | 4 +++- junction/feedback/service.py | 2 +- requirements.txt | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8428752f..bfd6f1e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ sudo: false python: - '2.7' - '3.4' +- '3.5' addons: postgresql: "9.3" @@ -11,7 +12,8 @@ cache: - $HOME/.pip-cache/ install: - - pip install -r requirements-dev.txt --allow-all-external --download-cache $HOME/.pip-cache + - pip install pip==8.1.2 + - pip install -r requirements-dev.txt --allow-all-external - pip install coveralls env: diff --git a/junction/feedback/service.py b/junction/feedback/service.py index f40e026c..0bd39d7b 100644 --- a/junction/feedback/service.py +++ b/junction/feedback/service.py @@ -56,7 +56,7 @@ def get_choice_feedback_questions(conference_id): schedule item type. """ qs = ChoiceFeedbackQuestion.objects.filter( - conference_id=conference_id).select_related('allowed_values') + conference_id=conference_id).prefetch_related('allowed_values') return _get_question_oragnized_by_type(qs) diff --git a/requirements.txt b/requirements.txt index b084b10e..1ed613dc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==1.7.9 +Django==1.8.14 celery==3.1.18 djangorestframework==3.1.3 django-filter==0.10.0 From 1a842bf57929fe1e1fcc059442315fca89e095b5 Mon Sep 17 00:00:00 2001 From: Kracekumar Ramaraju Date: Sun, 24 Jul 2016 00:28:36 +0530 Subject: [PATCH 488/666] Pass user object in get_reviewer_vote_details --- junction/proposals/templatetags/proposal_filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index 5e1cd388..4688d75b 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -77,7 +77,7 @@ def get_reviewers_vote_details(proposal, user): vc_qs = ProposalComment.objects.filter( proposal=proposal, - commenter=reviewer, + commenter=reviewer.conference_reviewer.reviewer, vote=True) if vc_qs: vote_comment = vc_qs[0].comment From b6bda9d79df9a11ccf1c604cbbe7b6e4b54557af Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sun, 24 Jul 2016 11:53:04 +0530 Subject: [PATCH 489/666] Update heading in votes dashboard --- junction/proposals/utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/junction/proposals/utils.py b/junction/proposals/utils.py index 41d1c722..f0d33029 100644 --- a/junction/proposals/utils.py +++ b/junction/proposals/utils.py @@ -58,27 +58,27 @@ def _sort_proposals_for_dashboard(conference, proposals_qs, user, form): batch1 = [p for p in proposals_qs if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) > 0 and p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 1] - proposals.append(s_items('Batch 1', batch1)) + proposals.append(s_items('1 Must Have & 2+ Good Votes', batch1)) batches += batch1 batch2 = [p for p in proposals_qs if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) > 0 and p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 0 and p not in batches] - proposals.append(s_items('Batch 2', batch2)) + proposals.append(s_items('1 Must Have & 1 Good Vote', batch2)) batches += batch2 batch3 = [p for p in proposals_qs if p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 1 and p not in batches] - proposals.append(s_items('Batch 3', batch3)) + proposals.append(s_items('2+ Good Votes', batch3)) batches += batch3 batch4 = [p for p in proposals_qs if p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 0 and p.get_reviewer_votes_count_by_value(ProposalReviewVote.NOT_BAD) > 1 and p not in batches] - proposals.append(s_items('Batch 4', batch4)) + proposals.append(s_items('1 Good & 2+ Not Bad votes', batch4)) if votes not in (ProposalVotesFilter.SORT_BY_SUM, ProposalVotesFilter.SORT_BY_SELECTION): for section in proposal_sections: From f60cfe8b55def83f7d76ac0fad71f9cac3f396ff Mon Sep 17 00:00:00 2001 From: chillaranand Date: Sun, 24 Jul 2016 15:14:37 +0530 Subject: [PATCH 490/666] Update sorting logic --- junction/proposals/models.py | 2 +- junction/proposals/utils.py | 26 ++++++++++---------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 7099e51f..4a740c95 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -178,7 +178,7 @@ def get_reviewer_votes_count(self): def get_reviewer_votes_count_by_value(self, vote_value): """ Show sum of reviewer votes for given vote value. """ return ProposalSectionReviewerVote.objects.filter( - proposal=self, vote_value=vote_value + proposal=self, vote_value__vote_value=vote_value ).count() def get_reviewer_votes_sum(self): diff --git a/junction/proposals/utils.py b/junction/proposals/utils.py index f0d33029..0e16ee0c 100644 --- a/junction/proposals/utils.py +++ b/junction/proposals/utils.py @@ -50,34 +50,28 @@ def _sort_proposals_for_dashboard(conference, proposals_qs, user, form): proposals_qs = [p for p in proposals_qs if not p.has_negative_votes()] proposals_qs = sorted(proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), reverse=True) - selected = [p for p in proposals_qs if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) > 1] + selected = [p for p in proposals_qs if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) >= 2] proposals.append(s_items('Selected', selected)) - batches = [] - batch1 = [p for p in proposals_qs - if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) > 0 and - p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 1] + if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) == 1 and + p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 2] proposals.append(s_items('1 Must Have & 2+ Good Votes', batch1)) - batches += batch1 batch2 = [p for p in proposals_qs - if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) > 0 and - p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 0 and - p not in batches] + if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) == 1 and + p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) == 1] proposals.append(s_items('1 Must Have & 1 Good Vote', batch2)) - batches += batch2 batch3 = [p for p in proposals_qs - if p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 1 and - p not in batches] + if p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 2 and + p not in batch1] proposals.append(s_items('2+ Good Votes', batch3)) - batches += batch3 batch4 = [p for p in proposals_qs - if p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 0 and - p.get_reviewer_votes_count_by_value(ProposalReviewVote.NOT_BAD) > 1 and - p not in batches] + if p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) == 1 and + p.get_reviewer_votes_count_by_value(ProposalReviewVote.NOT_BAD) > 2 and + p not in batch2] proposals.append(s_items('1 Good & 2+ Not Bad votes', batch4)) if votes not in (ProposalVotesFilter.SORT_BY_SUM, ProposalVotesFilter.SORT_BY_SELECTION): From 562a55079bb6d6efeb69cdd05003bd1b5579373c Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Sat, 6 Aug 2016 13:57:29 +0530 Subject: [PATCH 491/666] Add view for second phase voting --- junction/proposals/dashboard.py | 79 ++++++++++++++++++- junction/proposals/urls.py | 3 +- junction/templates/proposals/list.html | 1 + .../proposals/second_phase_voting.html | 57 +++++++++++++ 4 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 junction/templates/proposals/second_phase_voting.html diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index 62ba46f2..6b78ad4f 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -19,7 +19,8 @@ from junction.base.constants import ( ProposalReviewVote, ProposalStatus, - ProposalVotesFilter + ProposalVotesFilter, + ProposalReviewStatus, ) from junction.conferences.models import Conference, ConferenceProposalReviewer @@ -263,6 +264,82 @@ def reviewer_votes_dashboard(request, conference_slug): 'form': form}) +@require_http_methods(['GET', 'POST']) +def second_phase_voting(request, conference_slug): + conference = get_object_or_404(Conference, slug=conference_slug) + + if not is_conference_moderator(user=request.user, conference=conference): + raise PermissionDenied + + proposal_sections = conference.proposal_sections.all() + proposals_qs = Proposal.objects.select_related( + 'proposal_type', 'proposal_section', 'conference', 'author', + ).filter( + conference=conference, + review_status=ProposalReviewStatus.SELECTED + ) + + proposals = [] + s_items = collections.namedtuple('section_items', 'section proposals') + form = ProposalVotesFilterForm(conference=conference) + + if request.method == 'GET': + for section in proposal_sections: + section_proposals = [ + p for p in proposals_qs if p.proposal_section == section] + proposals.append(s_items(section, section_proposals)) + + return render(request, 'proposals/second_phase_voting.html', + {'conference': conference, + 'proposals': proposals, + 'form': form}) + + form = ProposalVotesFilterForm(conference=conference, data=request.POST) + + if not form.is_valid(): + return render(request, 'proposals/votes-dashboard.html', + {'form': form, + 'conference': conference, + 'errors': form.errors}) + + # Valid form + cps = form.cleaned_data['proposal_section'] + cpt = form.cleaned_data['proposal_type'] + votes = form.cleaned_data['votes'] + review_status = form.cleaned_data['review_status'] + proposal_sections = conference.proposal_sections.all() + + if cps != 'all': + proposal_sections = ProposalSection.objects.filter(pk=cps) + if cpt != 'all': + proposals_qs = proposals_qs.filter(proposal_type__id__in=cpt) + if votes != 'all': + votes = int(votes) + if review_status != 'all': + proposals_qs = proposals_qs.filter(review_status=review_status) + + if votes == ProposalVotesFilter.NO_VOTES: + proposals_qs = [ + p for p in proposals_qs if p.get_reviewer_votes_count() == votes] + elif votes == ProposalVotesFilter.MIN_ONE_VOTE: + proposals_qs = [ + p for p in proposals_qs if p.get_reviewer_votes_count() >= votes] + elif votes == ProposalVotesFilter.SORT: + proposals_qs = sorted( + proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), + reverse=True) + + for section in proposal_sections: + section_proposals = [ + p for p in proposals_qs if p.proposal_section == section] + proposals.append(s_items(section, section_proposals)) + + return render(request, 'proposals/second_phase_voting.html', + {'conference': conference, + 'proposals': proposals, + 'form': form}) + + @require_http_methods(['GET', 'POST']) def export_reviewer_votes(request, conference_slug): """ diff --git a/junction/proposals/urls.py b/junction/proposals/urls.py index f390b7fa..fb5c6109 100644 --- a/junction/proposals/urls.py +++ b/junction/proposals/urls.py @@ -4,7 +4,7 @@ # Third Party Stuff from django.conf.urls import include, patterns, url -from . import comments_views, views, votes_views +from . import comments_views, views, votes_views, dashboard comment_urls = patterns( '', @@ -22,6 +22,7 @@ url(r'^$', views.list_proposals, name='proposals-list'), url(r'^create/$', views.create_proposal, name='proposal-create'), url(r'^to_review/$', views.proposals_to_review, name='proposals-to-review'), + url(r'^second_phase_voting/$', dashboard.second_phase_voting, name='second-phase-voting'), url(r'^(?P[\w-]+)/$', views.detail_proposal, name='proposal-detail'), url(r'^(?P[\w-]+)~(?P.*)/$', views.detail_proposal, name='proposal-detail'), url(r'^(?P[\w-]+)/delete/$', views.delete_proposal, name='proposal-delete'), diff --git a/junction/templates/proposals/list.html b/junction/templates/proposals/list.html index f1ecb84f..f9666844 100644 --- a/junction/templates/proposals/list.html +++ b/junction/templates/proposals/list.html @@ -54,6 +54,7 @@

    {{ conference.description|markdown }}

    {% if is_reviewer %} Proposals To Review + Second Phase Voting {% endif %} {% if user.is_superuser or user.is_stuff %} diff --git a/junction/templates/proposals/second_phase_voting.html b/junction/templates/proposals/second_phase_voting.html new file mode 100644 index 00000000..a390fcc1 --- /dev/null +++ b/junction/templates/proposals/second_phase_voting.html @@ -0,0 +1,57 @@ +{% extends 'base.html' %} +{% load bootstrap3 %} + +{% load django_markdown %} +{% load static from staticfiles %} +{% load django_bootstrap_breadcrumbs %} + +{% block head_title %} {{ conference.name }} Second phase voting {% endblock %} +{% block og_title %} {{ conference.name }} Second phase voting {% endblock %} +{% block og_description %} {{ conference.description|markdown|safe|striptags}} {% endblock %} +{% block page_description %} {{ conference.description|markdown|safe|striptags}} {% endblock %} + +{% block endhead %} + + +{% endblock %} + +{% block breadcrumbs %} + {{ block.super }} + {% breadcrumb conference.name "conference-detail" conference.slug %} + {% breadcrumb "Second phase voting" "proposals-to-review" conference.slug %} +{% endblock %} + +{% block navbar_logo %} + {% if conference.logo %} + + + + {% else %} + {{ conference.name }} + {% endif %} +{% endblock navbar_logo %} + +{% block page_classes %}{{ block.super}} page-proposals{% endblock page_classes %} + +{% block content %} +
    +
    + + {% if proposals %} +

    Second Phase Voting

    +
    + +
    + {% for section_items in proposals %} + {% if section_items.proposals %} + {% include 'proposals/partials/proposal-list--review-items.html' with proposals=section_items.proposals title=section_items.section display_status=False %} + {% endif %} + {% endfor %} +
    + + {% else %} +

    No proposals to vote.

    + {% endif %} +
    +
    +{% endblock %} From 5aba98ace2f89a575012c6533eaa1aed10ecb165 Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Sat, 6 Aug 2016 17:04:17 +0530 Subject: [PATCH 492/666] Add proposal comment type --- junction/base/constants.py | 6 ++++++ .../migrations/0017_proposalcomment_type.py | 20 +++++++++++++++++++ junction/proposals/models.py | 7 +++++-- 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 junction/proposals/migrations/0017_proposalcomment_type.py diff --git a/junction/base/constants.py b/junction/base/constants.py index 0384cdfd..95e7d808 100644 --- a/junction/base/constants.py +++ b/junction/base/constants.py @@ -96,3 +96,9 @@ class ConferenceSettingConstants: ALLOW_PLUS_ZERO_REVIEWER_VOTE = {"name": "allow_plus_zero_reviewer_vote", "value": True, "description": "Allow +0 vote in reviewer votes"} + + +@choices +class ProposalCommentType: + _GENERAL = [0, 'Unclassified'] + _SECOND_PHASE_VOTING = [1, 'Second phase voting'] diff --git a/junction/proposals/migrations/0017_proposalcomment_type.py b/junction/proposals/migrations/0017_proposalcomment_type.py new file mode 100644 index 00000000..0d5ff51f --- /dev/null +++ b/junction/proposals/migrations/0017_proposalcomment_type.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0016_auto_20160221_0240'), + ] + + operations = [ + migrations.AddField( + model_name='proposalcomment', + name='type', + field=models.PositiveSmallIntegerField(default=0, choices=[(0, 'Unclassified'), (1, 'Second phase voting')]), + preserve_default=True, + ), + ] diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 03dc87d7..1ca9e169 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -15,7 +15,10 @@ from simple_history.models import HistoricalRecords # Junction Stuff -from junction.base.constants import ProposalReviewStatus, ProposalStatus, ProposalTargetAudience, ProposalUserVoteRole +from junction.base.constants import ( + ProposalReviewStatus, ProposalStatus, ProposalTargetAudience, ProposalUserVoteRole, + ProposalCommentType +) from junction.base.models import AuditModel, TimeAuditModel from junction.conferences.models import Conference, ConferenceProposalReviewer @@ -268,7 +271,7 @@ class ProposalComment(TimeAuditModel): vote = models.BooleanField(default=False, verbose_name="What is the reason?") comment = models.TextField() deleted = models.BooleanField(default=False, verbose_name="Is Deleted?") - + type = models.PositiveSmallIntegerField(choices=ProposalCommentType.CHOICES, default=ProposalCommentType.GENERAL) objects = ProposalCommentQuerySet.as_manager() def __str__(self): From ccf73492d0d256a72eb18f9d9c52a602584508ea Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Sat, 6 Aug 2016 20:19:14 +0530 Subject: [PATCH 493/666] Updated secondary vote phase --- junction/base/constants.py | 10 +++++-- .../migrations/0018_auto_20160806_1727.py | 30 +++++++++++++++++++ junction/proposals/models.py | 12 ++++++-- junction/proposals/urls.py | 4 ++- junction/proposals/votes_views.py | 22 ++++++++++++-- junction/templates/proposals/detail/base.html | 5 ++-- 6 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 junction/proposals/migrations/0018_auto_20160806_1727.py diff --git a/junction/base/constants.py b/junction/base/constants.py index 95e7d808..0b1e9068 100644 --- a/junction/base/constants.py +++ b/junction/base/constants.py @@ -98,7 +98,13 @@ class ConferenceSettingConstants: "description": "Allow +0 vote in reviewer votes"} +@choices +class PSRVotePhase: + _PRIMARY = [0, 'Initial voting'] + _SECONDARY = [1, 'Second phase voting'] + + @choices class ProposalCommentType: - _GENERAL = [0, 'Unclassified'] - _SECOND_PHASE_VOTING = [1, 'Second phase voting'] + _GENERAL = [0, 'All general comments'] + _SECONDARY_VOTING = [1, 'Second phase voting'] diff --git a/junction/proposals/migrations/0018_auto_20160806_1727.py b/junction/proposals/migrations/0018_auto_20160806_1727.py new file mode 100644 index 00000000..c459c8af --- /dev/null +++ b/junction/proposals/migrations/0018_auto_20160806_1727.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0017_proposalcomment_type'), + ] + + operations = [ + migrations.RemoveField( + model_name='proposalcomment', + name='type', + ), + migrations.AddField( + model_name='historicalproposalsectionreviewervote', + name='phase', + field=models.PositiveSmallIntegerField(default=0, choices=[(0, 'Initial voting'), (1, 'Second phase voting')]), + preserve_default=True, + ), + migrations.AddField( + model_name='proposalsectionreviewervote', + name='phase', + field=models.PositiveSmallIntegerField(default=0, choices=[(0, 'Initial voting'), (1, 'Second phase voting')]), + preserve_default=True, + ), + ] diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 1ca9e169..1b5eefc6 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -17,7 +17,7 @@ # Junction Stuff from junction.base.constants import ( ProposalReviewStatus, ProposalStatus, ProposalTargetAudience, ProposalUserVoteRole, - ProposalCommentType + PSRVotePhase, ProposalCommentType, ) from junction.base.models import AuditModel, TimeAuditModel from junction.conferences.models import Conference, ConferenceProposalReviewer @@ -124,6 +124,10 @@ def get_vote_url(self): return reverse('proposal-reviewer-vote', args=[self.conference.slug, self.slug]) + def get_secondary_vote_url(self): + return reverse('proposal-reviewer-secondary-vote', + args=[self.conference.slug, self.slug]) + def get_delete_url(self): return reverse('proposal-delete', args=[self.conference.slug, self.slug]) @@ -250,6 +254,8 @@ class ProposalSectionReviewerVote(TimeAuditModel): role = models.PositiveSmallIntegerField( choices=ProposalUserVoteRole.CHOICES, default=ProposalUserVoteRole.REVIEWER) vote_value = models.ForeignKey(ProposalSectionReviewerVoteValue) + phase = models.PositiveSmallIntegerField(choices=PSRVotePhase.CHOICES, default=PSRVotePhase.PRIMARY) + history = HistoricalRecords() def __str__(self): @@ -260,6 +266,7 @@ class Meta: verbose_name = 'ProposalSectionReviewerVote' +#FIXME: Need to move private, reviewer, vote to type @python_2_unicode_compatible class ProposalComment(TimeAuditModel): @@ -271,7 +278,8 @@ class ProposalComment(TimeAuditModel): vote = models.BooleanField(default=False, verbose_name="What is the reason?") comment = models.TextField() deleted = models.BooleanField(default=False, verbose_name="Is Deleted?") - type = models.PositiveSmallIntegerField(choices=ProposalCommentType.CHOICES, default=ProposalCommentType.GENERAL) + comment_type = models.PositiveSmallIntegerField( + choices=ProposalCommentType.CHOICES, default=ProposalCommentType.GENERAL) objects = ProposalCommentQuerySet.as_manager() def __str__(self): diff --git a/junction/proposals/urls.py b/junction/proposals/urls.py index fb5c6109..5564e697 100644 --- a/junction/proposals/urls.py +++ b/junction/proposals/urls.py @@ -34,8 +34,10 @@ url(r'^comment/', include(comment_urls)), # Voting - url(r'^(?P[\w-]+)/vote/$', votes_views.proposal_reviewer_vote, name='proposal-reviewer-vote'), url(r'^(?P[\w-]+)/down-vote/$', votes_views.proposal_vote_down, name='proposal-vote-down'), url(r'^(?P[\w-]+)/up-vote/$', votes_views.proposal_vote_up, name='proposal-vote-up'), url(r'^(?P[\w-]+)/remove-vote/$', votes_views.proposal_vote_remove, name='proposal-vote-remove'), + url(r'^(?P[\w-]+)/vote/$', votes_views.proposal_reviewer_vote, name='proposal-reviewer-vote'), + url(r'^(?P[\w-]+)/second-vote/$', votes_views.proposal_reviewer_secondary_vote, + name='proposal-reviewer-secondary-vote'), ) diff --git a/junction/proposals/votes_views.py b/junction/proposals/votes_views.py index 0534287d..ef5fbecd 100644 --- a/junction/proposals/votes_views.py +++ b/junction/proposals/votes_views.py @@ -18,11 +18,13 @@ from .models import ( Proposal, ProposalComment, + ProposalCommentType, ProposalCommentVote, ProposalSectionReviewer, ProposalSectionReviewerVote, ProposalSectionReviewerVoteValue, - ProposalVote + ProposalVote, + PSRVotePhase, ) @@ -111,7 +113,14 @@ def proposal_comment_down_vote(request, conference_slug, proposal_slug, @login_required @require_http_methods(['GET', 'POST']) -def proposal_reviewer_vote(request, conference_slug, proposal_slug): +def proposal_reviewer_vote(request, conference_slug, proposal_slug, vote_phase=None): + if not vote_phase: + vote_phase = PSRVotePhase.PRIMARY + comment_type = ProposalCommentType.GENERAL + elif vote_phase == PSRVotePhase.SECONDARY: + print('aaaaaaaaaaaaaaaaaaaaa') + comment_type = ProposalCommentType.SECONDARY_VOTING + conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=proposal_slug, conference=conference) @@ -130,6 +139,7 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): conference_reviewer__reviewer=request.user, conference_reviewer__conference=conference, proposal_section=proposal.proposal_section), + phase=vote_phase, ) vote_value = vote.vote_value.vote_value except ProposalSectionReviewerVote.DoesNotExist: @@ -141,6 +151,7 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): commenter=request.user, vote=True, deleted=False, + comment_type=comment_type, ) except: vote_comment = None @@ -182,6 +193,7 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): proposal_section=proposal.proposal_section)[0], vote_value=ProposalSectionReviewerVoteValue.objects.filter( vote_value=vote_value)[0], + phase=vote_phase, ) else: vote.vote_value = ProposalSectionReviewerVoteValue.objects.filter( @@ -193,9 +205,15 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): commenter=request.user, comment=comment, vote=True, + comment_type=comment_type, ) else: vote_comment.comment = comment vote_comment.save() return HttpResponseRedirect(reverse('proposals-to-review', args=[conference.slug])) + + +def proposal_reviewer_secondary_vote(request, conference_slug, proposal_slug): + vote_phase = PSRVotePhase.SECONDARY + return proposal_reviewer_vote(request, conference_slug, proposal_slug, vote_phase=vote_phase) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index af35a1d1..a72d88f4 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -173,9 +173,8 @@

    Speaker Links:

    {% if is_section_reviewer or user.is_authenticated and user.is_superuser %} {% endif %} From 4eb3cad1472a83eb4c25c4b7e6553b7466b0307b Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Sat, 6 Aug 2016 20:24:01 +0530 Subject: [PATCH 494/666] Remove unique together constraint --- .../0019_proposalcomment_comment_type.py | 20 +++++++++++++++++++ .../migrations/0020_auto_20160806_2023.py | 18 +++++++++++++++++ junction/proposals/models.py | 1 - 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 junction/proposals/migrations/0019_proposalcomment_comment_type.py create mode 100644 junction/proposals/migrations/0020_auto_20160806_2023.py diff --git a/junction/proposals/migrations/0019_proposalcomment_comment_type.py b/junction/proposals/migrations/0019_proposalcomment_comment_type.py new file mode 100644 index 00000000..98efc20c --- /dev/null +++ b/junction/proposals/migrations/0019_proposalcomment_comment_type.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0018_auto_20160806_1727'), + ] + + operations = [ + migrations.AddField( + model_name='proposalcomment', + name='comment_type', + field=models.PositiveSmallIntegerField(default=0, choices=[(0, 'All general comments'), (1, 'Second phase voting')]), + preserve_default=True, + ), + ] diff --git a/junction/proposals/migrations/0020_auto_20160806_2023.py b/junction/proposals/migrations/0020_auto_20160806_2023.py new file mode 100644 index 00000000..ba1fb14a --- /dev/null +++ b/junction/proposals/migrations/0020_auto_20160806_2023.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0019_proposalcomment_comment_type'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='proposalsectionreviewervote', + unique_together=set([]), + ), + ] diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 1b5eefc6..88d1e852 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -262,7 +262,6 @@ def __str__(self): return "[{}] {}".format(self.vote_value, self.proposal) class Meta: - unique_together = ("proposal", "voter") verbose_name = 'ProposalSectionReviewerVote' From ccc027648d62b1e48b3dda23c26b07a8a2b1d966 Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Sat, 6 Aug 2016 20:26:07 +0530 Subject: [PATCH 495/666] Update proposal filters --- junction/proposals/templatetags/proposal_filters.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index 5e1cd388..137ee5c1 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -1,15 +1,14 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals -# Standard Library import collections import re -# Third Party Stuff from django import template +from junction.base.constants import PSRVotePhase +from junction.proposals.models import ProposalComment, ProposalSectionReviewer, \ + ProposalSectionReviewerVote -# Junction Stuff -from junction.proposals.models import ProposalComment, ProposalSectionReviewer, ProposalSectionReviewerVote register = template.Library() @@ -20,7 +19,9 @@ def reviewer_comments(proposal, user): @register.filter(name='is_reviewer_voted') -def is_reviewer_voted(proposal, user): +def is_reviewer_voted(proposal, user, phase=None): + if not phase: + phase = PSRVotePhase.PRIMARY try: vote = ProposalSectionReviewerVote.objects.get( proposal=proposal, @@ -28,6 +29,7 @@ def is_reviewer_voted(proposal, user): conference_reviewer__reviewer=user, conference_reviewer__conference=proposal.conference, proposal_section=proposal.proposal_section), + phase=phase, ) except ProposalSectionReviewerVote.DoesNotExist: vote = None From a9f2859898014247d6d6a1c835ef4f48a37ae9e3 Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Sat, 6 Aug 2016 22:02:42 +0530 Subject: [PATCH 496/666] Refactor PSR vote views --- junction/proposals/forms.py | 1 - junction/proposals/utils.py | 69 +++++++++++++ junction/proposals/votes_views.py | 154 +++++++++++++----------------- 3 files changed, 134 insertions(+), 90 deletions(-) create mode 100644 junction/proposals/utils.py diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index 3e287223..f99315b4 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -152,7 +152,6 @@ class ProposalReviewForm(forms.Form): class ProposalReviewerVoteForm(forms.Form): - """ Used by ProposalSectionReviewers to vote on proposals. """ diff --git a/junction/proposals/utils.py b/junction/proposals/utils.py new file mode 100644 index 00000000..9e9a130b --- /dev/null +++ b/junction/proposals/utils.py @@ -0,0 +1,69 @@ +from django.core.exceptions import PermissionDenied + +from junction.base.constants import PSRVotePhase, ProposalCommentType +from junction.proposals import permissions +from junction.proposals.models import ProposalComment, ProposalSectionReviewer, \ + ProposalSectionReviewerVote, ProposalSectionReviewerVoteValue + + +def get_reviewer_vote_info(user, conference, proposal, vote_phase): + + if vote_phase == PSRVotePhase.PRIMARY: + comment_type = ProposalCommentType.GENERAL + elif vote_phase == PSRVotePhase.SECONDARY: + comment_type = ProposalCommentType.SECONDARY_VOTING + + if not (permissions.is_proposal_section_reviewer(user, + conference, proposal) and + permissions.is_proposal_voting_allowed(proposal)): + raise PermissionDenied + + voter = ProposalSectionReviewer.objects.get( + conference_reviewer__reviewer=user, + conference_reviewer__conference=conference, + proposal_section=proposal.proposal_section) + + try: + psr_vote = ProposalSectionReviewerVote.objects.get(proposal=proposal, voter=voter, phase=vote_phase) + except ProposalSectionReviewerVote.DoesNotExist: + psr_vote = None + + try: + vote_comment = ProposalComment.objects.get( + proposal=proposal, + commenter=user, + vote=True, + deleted=False, + comment_type=comment_type, + ) + except: + vote_comment = None + + return psr_vote, vote_comment + + +def update_reviewer_vote_info(user, psr_vote, vote_value, comment, phase, proposal, conference): + + if phase == PSRVotePhase.PRIMARY: + comment_type = ProposalCommentType.GENERAL + elif phase == PSRVotePhase.SECONDARY: + comment_type = ProposalCommentType.SECONDARY_VOTING + + voter = ProposalSectionReviewer.objects.filter( + conference_reviewer__reviewer=user, + conference_reviewer__conference=conference, + proposal_section=proposal.proposal_section)[0] + + vote_value = ProposalSectionReviewerVoteValue.objects.filter(vote_value=vote_value)[0] + + psr_vote, _ = ProposalSectionReviewerVote.objects.update_or_create( + proposal=proposal, voter=voter, phase=phase, + defaults={'vote_value': vote_value} + ) + + p_comment, _ = ProposalComment.objects.update_or_create( + proposal=proposal, commenter=user, vote=True, comment_type=comment_type, + defaults={'comment': comment} + ) + + return psr_vote, p_comment diff --git a/junction/proposals/votes_views.py b/junction/proposals/votes_views.py index ef5fbecd..c0487ec0 100644 --- a/junction/proposals/votes_views.py +++ b/junction/proposals/votes_views.py @@ -1,31 +1,21 @@ # -*- coding: utf-8 -*- - -# Third Party Stuff from django.contrib.auth.decorators import login_required -from django.core.exceptions import PermissionDenied from django.core.urlresolvers import reverse from django.http import HttpResponseForbidden from django.http.response import HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.views.decorators.http import require_http_methods -# Junction Stuff -from junction.base.constants import ConferenceSettingConstants, ProposalUserVoteRole +from junction.base.constants import ConferenceSettingConstants, \ + ProposalUserVoteRole from junction.conferences.models import Conference from . import permissions +from . import utils from .forms import ProposalReviewerVoteForm -from .models import ( - Proposal, - ProposalComment, - ProposalCommentType, - ProposalCommentVote, - ProposalSectionReviewer, - ProposalSectionReviewerVote, - ProposalSectionReviewerVoteValue, - ProposalVote, - PSRVotePhase, -) +from .models import PSRVotePhase, Proposal, ProposalComment, \ + ProposalCommentVote, ProposalSectionReviewer, ProposalSectionReviewerVote, \ + ProposalSectionReviewerVoteValue, ProposalVote @login_required @@ -113,62 +103,30 @@ def proposal_comment_down_vote(request, conference_slug, proposal_slug, @login_required @require_http_methods(['GET', 'POST']) -def proposal_reviewer_vote(request, conference_slug, proposal_slug, vote_phase=None): - if not vote_phase: - vote_phase = PSRVotePhase.PRIMARY - comment_type = ProposalCommentType.GENERAL - elif vote_phase == PSRVotePhase.SECONDARY: - print('aaaaaaaaaaaaaaaaaaaaa') - comment_type = ProposalCommentType.SECONDARY_VOTING - +def proposal_reviewer_vote(request, conference_slug, proposal_slug): + user = request.user + vote_phase = PSRVotePhase.PRIMARY conference = get_object_or_404(Conference, slug=conference_slug) proposal = get_object_or_404(Proposal, slug=proposal_slug, conference=conference) - if not (permissions.is_proposal_section_reviewer(request.user, - conference, proposal) and - permissions.is_proposal_voting_allowed(proposal)): - raise PermissionDenied - - vote_value = None - - try: - vote = ProposalSectionReviewerVote.objects.get( - proposal=proposal, - voter=ProposalSectionReviewer.objects.get( - conference_reviewer__reviewer=request.user, - conference_reviewer__conference=conference, - proposal_section=proposal.proposal_section), - phase=vote_phase, - ) - vote_value = vote.vote_value.vote_value - except ProposalSectionReviewerVote.DoesNotExist: - vote = None - - try: - vote_comment = ProposalComment.objects.get( - proposal=proposal, - commenter=request.user, - vote=True, - deleted=False, - comment_type=comment_type, - ) - except: - vote_comment = None + psr_vote, p_comment = utils.get_reviewer_vote_info(user, conference, proposal, vote_phase) + if request.method == 'GET': - if vote_comment: + if psr_vote and p_comment: proposal_vote_form = ProposalReviewerVoteForm( - initial={'vote_value': vote_value, - 'comment': vote_comment.comment}, - conference=conference) + conference=conference, + initial={ + 'vote_value': psr_vote.vote_value.vote_value, + 'comment': p_comment.comment + }, + ) else: - proposal_vote_form = ProposalReviewerVoteForm( - initial={'vote_value': vote_value}, - conference=conference) + proposal_vote_form = ProposalReviewerVoteForm(conference=conference) ctx = { 'proposal': proposal, 'form': proposal_vote_form, - 'vote': vote, + 'vote': psr_vote, } return render(request, 'proposals/vote.html', ctx) @@ -184,36 +142,54 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug, vote_phase=N # Valid Form vote_value = form.cleaned_data['vote_value'] comment = form.cleaned_data['comment'] - if not vote: - vote = ProposalSectionReviewerVote.objects.create( - proposal=proposal, - voter=ProposalSectionReviewer.objects.filter( - conference_reviewer__reviewer=request.user, - conference_reviewer__conference=conference, - proposal_section=proposal.proposal_section)[0], - vote_value=ProposalSectionReviewerVoteValue.objects.filter( - vote_value=vote_value)[0], - phase=vote_phase, - ) - else: - vote.vote_value = ProposalSectionReviewerVoteValue.objects.filter( - vote_value=vote_value)[0] - vote.save() - if not vote_comment: - vote_comment = ProposalComment.objects.create( - proposal=proposal, - commenter=request.user, - comment=comment, - vote=True, - comment_type=comment_type, - ) - else: - vote_comment.comment = comment - vote_comment.save() + print(comment) + utils.update_reviewer_vote_info(user, psr_vote, vote_value, comment, vote_phase, proposal, conference) return HttpResponseRedirect(reverse('proposals-to-review', args=[conference.slug])) +@login_required +@require_http_methods(['GET', 'POST']) def proposal_reviewer_secondary_vote(request, conference_slug, proposal_slug): vote_phase = PSRVotePhase.SECONDARY - return proposal_reviewer_vote(request, conference_slug, proposal_slug, vote_phase=vote_phase) + user = request.user + conference = get_object_or_404(Conference, slug=conference_slug) + proposal = get_object_or_404(Proposal, slug=proposal_slug, + conference=conference) + + psr_vote, p_comment = utils.get_reviewer_vote_info(user, conference, proposal, vote_phase) + + if request.method == 'GET': + if psr_vote and p_comment: + proposal_vote_form = ProposalReviewerVoteForm( + conference=conference, + initial={ + 'vote_value': psr_vote.vote_value.vote_value, + 'comment': p_comment.comment + }, + ) + else: + proposal_vote_form = ProposalReviewerVoteForm(conference=conference) + ctx = { + 'proposal': proposal, + 'form': proposal_vote_form, + 'vote': psr_vote, + } + + return render(request, 'proposals/vote.html', ctx) + + # POST Workflow + form = ProposalReviewerVoteForm(data=request.POST, conference=conference) + if not form.is_valid(): + ctx = {'form': form, + 'proposal': proposal, + 'form_errors': form.errors} + return render(request, 'proposals/vote.html', ctx) + + # Valid Form + vote_value = form.cleaned_data['vote_value'] + comment = form.cleaned_data['comment'] + print(comment) + utils.update_reviewer_vote_info(user, psr_vote, vote_value, comment, vote_phase, proposal, conference) + return HttpResponseRedirect(reverse('proposals-to-review', + args=[conference.slug])) From 732a7d3cbc12ae47507978d55b459059a79afb88 Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Wed, 10 Aug 2016 00:06:51 +0530 Subject: [PATCH 497/666] Refactor dashboard views --- junction/proposals/dashboard.py | 33 ++----------------------------- junction/proposals/utils.py | 2 -- junction/proposals/votes_views.py | 4 ++-- 3 files changed, 4 insertions(+), 35 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index 8caf530f..aa6a3ed9 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -19,7 +19,6 @@ from junction.base.constants import ( ProposalReviewVote, ProposalStatus, - ProposalVotesFilter, ProposalReviewStatus, ) from junction.conferences.models import Conference, ConferenceProposalReviewer @@ -238,6 +237,7 @@ def reviewer_votes_dashboard(request, conference_slug): @require_http_methods(['GET', 'POST']) def second_phase_voting(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) + user = request.user if not is_conference_moderator(user=request.user, conference=conference): raise PermissionDenied @@ -274,36 +274,7 @@ def second_phase_voting(request, conference_slug): 'errors': form.errors}) # Valid form - cps = form.cleaned_data['proposal_section'] - cpt = form.cleaned_data['proposal_type'] - votes = form.cleaned_data['votes'] - review_status = form.cleaned_data['review_status'] - proposal_sections = conference.proposal_sections.all() - - if cps != 'all': - proposal_sections = ProposalSection.objects.filter(pk=cps) - if cpt != 'all': - proposals_qs = proposals_qs.filter(proposal_type__id__in=cpt) - if votes != 'all': - votes = int(votes) - if review_status != 'all': - proposals_qs = proposals_qs.filter(review_status=review_status) - - if votes == ProposalVotesFilter.NO_VOTES: - proposals_qs = [ - p for p in proposals_qs if p.get_reviewer_votes_count() == votes] - elif votes == ProposalVotesFilter.MIN_ONE_VOTE: - proposals_qs = [ - p for p in proposals_qs if p.get_reviewer_votes_count() >= votes] - elif votes == ProposalVotesFilter.SORT: - proposals_qs = sorted( - proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), - reverse=True) - - for section in proposal_sections: - section_proposals = [ - p for p in proposals_qs if p.proposal_section == section] - proposals.append(s_items(section, section_proposals)) + proposals = _sort_proposals_for_dashboard(conference, proposals_qs, user, form) return render(request, 'proposals/second_phase_voting.html', {'conference': conference, diff --git a/junction/proposals/utils.py b/junction/proposals/utils.py index 87227bc6..b59d30fc 100644 --- a/junction/proposals/utils.py +++ b/junction/proposals/utils.py @@ -74,8 +74,6 @@ def update_reviewer_vote_info(user, psr_vote, vote_value, comment, phase, propos def _sort_proposals_for_dashboard(conference, proposals_qs, user, form): - """ - """ cps = form.cleaned_data['proposal_section'] cpt = form.cleaned_data['proposal_type'] votes = form.cleaned_data['votes'] diff --git a/junction/proposals/votes_views.py b/junction/proposals/votes_views.py index c0487ec0..9c677445 100644 --- a/junction/proposals/votes_views.py +++ b/junction/proposals/votes_views.py @@ -142,7 +142,7 @@ def proposal_reviewer_vote(request, conference_slug, proposal_slug): # Valid Form vote_value = form.cleaned_data['vote_value'] comment = form.cleaned_data['comment'] - print(comment) + utils.update_reviewer_vote_info(user, psr_vote, vote_value, comment, vote_phase, proposal, conference) return HttpResponseRedirect(reverse('proposals-to-review', args=[conference.slug])) @@ -189,7 +189,7 @@ def proposal_reviewer_secondary_vote(request, conference_slug, proposal_slug): # Valid Form vote_value = form.cleaned_data['vote_value'] comment = form.cleaned_data['comment'] - print(comment) + utils.update_reviewer_vote_info(user, psr_vote, vote_value, comment, vote_phase, proposal, conference) return HttpResponseRedirect(reverse('proposals-to-review', args=[conference.slug])) From 08ac3f067216ef945eb6ce0ac4919e57c30fd399 Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Wed, 10 Aug 2016 00:08:49 +0530 Subject: [PATCH 498/666] Fix flake8 issues --- junction/profiles/admin.py | 3 --- junction/proposals/models.py | 2 +- junction/proposals/votes_views.py | 6 ++---- 3 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 junction/profiles/admin.py diff --git a/junction/profiles/admin.py b/junction/profiles/admin.py deleted file mode 100644 index 4185d360..00000000 --- a/junction/profiles/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -# from django.contrib import admin - -# Register your models here. diff --git a/junction/proposals/models.py b/junction/proposals/models.py index ca2a0bc6..f4814d6e 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -276,7 +276,7 @@ class Meta: verbose_name = 'ProposalSectionReviewerVote' -#FIXME: Need to move private, reviewer, vote to type +# FIXME: Need to move private, reviewer, vote to type @python_2_unicode_compatible class ProposalComment(TimeAuditModel): diff --git a/junction/proposals/votes_views.py b/junction/proposals/votes_views.py index 9c677445..e063208c 100644 --- a/junction/proposals/votes_views.py +++ b/junction/proposals/votes_views.py @@ -10,12 +10,10 @@ ProposalUserVoteRole from junction.conferences.models import Conference -from . import permissions -from . import utils +from . import permissions, utils from .forms import ProposalReviewerVoteForm from .models import PSRVotePhase, Proposal, ProposalComment, \ - ProposalCommentVote, ProposalSectionReviewer, ProposalSectionReviewerVote, \ - ProposalSectionReviewerVoteValue, ProposalVote + ProposalCommentVote, ProposalVote @login_required From a391eaf224579a8a3fa95ab1767009806712b64c Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Thu, 11 Aug 2016 19:28:29 +0530 Subject: [PATCH 499/666] Only PSR should see second phase voting --- junction/proposals/dashboard.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index aa6a3ed9..640d636f 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -34,6 +34,7 @@ ) from . import services +from . import permissions @login_required @@ -239,7 +240,7 @@ def second_phase_voting(request, conference_slug): conference = get_object_or_404(Conference, slug=conference_slug) user = request.user - if not is_conference_moderator(user=request.user, conference=conference): + if not permissions.is_proposal_reviewer(request.user, conference): raise PermissionDenied proposal_sections = conference.proposal_sections.all() From 1079b398d84af4b7897d32a09f930c6421fdc0bf Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Tue, 16 Aug 2016 19:33:39 +0530 Subject: [PATCH 500/666] Catch PSR doesnotexist before checking for votes --- .../proposals/templatetags/proposal_filters.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index 5be967b0..a6d5a4d1 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -22,16 +22,15 @@ def reviewer_comments(proposal, user): def is_reviewer_voted(proposal, user, phase=None): if not phase: phase = PSRVotePhase.PRIMARY + try: - vote = ProposalSectionReviewerVote.objects.get( - proposal=proposal, - voter=ProposalSectionReviewer.objects.get( - conference_reviewer__reviewer=user, - conference_reviewer__conference=proposal.conference, - proposal_section=proposal.proposal_section), - phase=phase, + voter = ProposalSectionReviewer.objects.get( + conference_reviewer__reviewer=user, + conference_reviewer__conference=proposal.conference, + proposal_section=proposal.proposal_section ) - except ProposalSectionReviewerVote.DoesNotExist: + vote = ProposalSectionReviewerVote.objects.get(proposal=proposal, voter=voter, phase=phase) + except (ProposalSectionReviewer.DoesNotExist, ProposalSectionReviewerVote.DoesNotExist): vote = None return vote From 4f72923b415ab78c98449a9768706370fee11244 Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Mon, 22 Aug 2016 18:51:23 +0530 Subject: [PATCH 501/666] Sort comments by created date --- junction/proposals/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index f4814d6e..14709ff2 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -292,6 +292,9 @@ class ProposalComment(TimeAuditModel): choices=ProposalCommentType.CHOICES, default=ProposalCommentType.GENERAL) objects = ProposalCommentQuerySet.as_manager() + class Meta: + ordering = ('created_at', ) + def __str__(self): return "[{} by {}] {}".format(self.comment, self.commenter.get_full_name(), From e7f0e8df261025c24308bb554a789ac6c6d5cdbb Mon Sep 17 00:00:00 2001 From: RishabhJain2018 Date: Mon, 5 Sep 2016 02:15:23 +0530 Subject: [PATCH 502/666] Taking data using Model Form Django --- junction/profiles/admin.py | 9 +++++++ junction/profiles/forms.py | 9 +++++++ .../migrations/0005_auto_20160905_0044.py | 26 +++++++++++++++++++ junction/profiles/views.py | 15 +++++++---- .../migrations/0021_auto_20160905_0044.py | 18 +++++++++++++ 5 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 junction/profiles/admin.py create mode 100644 junction/profiles/forms.py create mode 100644 junction/profiles/migrations/0005_auto_20160905_0044.py create mode 100644 junction/proposals/migrations/0021_auto_20160905_0044.py diff --git a/junction/profiles/admin.py b/junction/profiles/admin.py new file mode 100644 index 00000000..75653d62 --- /dev/null +++ b/junction/profiles/admin.py @@ -0,0 +1,9 @@ +from django.contrib import admin +from .models import Profile + + +class ProfileAdmin(admin.ModelAdmin): + list_display = ('__unicode__', 'city', 'contact_no') + search_fields = ('contact_no', 'city') + +admin.site.register(Profile, ProfileAdmin) diff --git a/junction/profiles/forms.py b/junction/profiles/forms.py new file mode 100644 index 00000000..fde34ccb --- /dev/null +++ b/junction/profiles/forms.py @@ -0,0 +1,9 @@ +from django import forms +from .models import Profile + + +class ProfileForm(forms.ModelForm): + class Meta: + model = Profile + fields = ['city', 'contact_no'] + exclude = ('user',) diff --git a/junction/profiles/migrations/0005_auto_20160905_0044.py b/junction/profiles/migrations/0005_auto_20160905_0044.py new file mode 100644 index 00000000..211223d1 --- /dev/null +++ b/junction/profiles/migrations/0005_auto_20160905_0044.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('profiles', '0004_auto_20160709_2023'), + ] + + operations = [ + migrations.AlterField( + model_name='profile', + name='city', + field=models.CharField(max_length=100, null=True, blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='profile', + name='contact_no', + field=models.CharField(max_length=15, null=True, blank=True), + preserve_default=True, + ), + ] diff --git a/junction/profiles/views.py b/junction/profiles/views.py index d98d3a6f..3d8f7bc5 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -12,6 +12,7 @@ # Profile Stuff from .models import Profile +from .forms import ProfileForm @login_required @@ -30,11 +31,15 @@ def dashboard(request): @login_required def profile(request): + form = ProfileForm() + user = request.user if request.method == "POST": - city = request.POST.get('city') - contact_no = request.POST.get('contact_no') - Profile.objects.create(user=request.user, city=city, contact_no=contact_no) - return HttpResponseRedirect("/profiles") - + form = ProfileForm(request.POST) + if form.is_valid(): + form = form.save(commit=False) + form.user = user + form.save() + print "form saved" + return HttpResponseRedirect("/profiles") elif request.method == "GET": return render(request, 'profiles/userprofile.html') diff --git a/junction/proposals/migrations/0021_auto_20160905_0044.py b/junction/proposals/migrations/0021_auto_20160905_0044.py new file mode 100644 index 00000000..0a8f38e0 --- /dev/null +++ b/junction/proposals/migrations/0021_auto_20160905_0044.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0020_auto_20160806_2023'), + ] + + operations = [ + migrations.AlterModelOptions( + name='proposalcomment', + options={'ordering': ('created_at',)}, + ), + ] From faf9607e24b109d53be7e6b28787f52100fffad3 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Tue, 6 Sep 2016 16:03:24 +0530 Subject: [PATCH 503/666] Update contributors list --- README.md | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 1890aea5..912c1c79 100644 --- a/README.md +++ b/README.md @@ -89,12 +89,12 @@ Contributing
    Aayush (@Aayush-Kasurde)
    Abhijeet (@Akasurde) -
    AMiT Kumar (@aktech) +
    Akshay Arora (@akshayaurora) +
    Amit Kumar (@aktech)
    Anand B Pillai (@pythonhacker) -
    Anand Chitipothu (@anandology) -
    Anand Pandikunta (@ChillarAnand) +
    Anand Chitipothu (@anandology)
    Anirudh (@animenon)
    Ankesh Anand (@ankeshanand)
    Anshul Sharma (@raun) @@ -102,63 +102,65 @@ Contributing
    arjoonn sharma (@theSage21) +
    Chillar Anand (@ChillarAnand)
    Deep Sukhwani (@ProProgrammer)
    dhilipsiva (@dhilipsiva)
    Fayaz Yusuf Khan (@fayazkhan) -
    Ganeshkumar S (@ganeshks) +
    Ganeshkumar S (@ganeshks)
    @gangadharmgithub -
    Geetanjali (@geetanjaligg) +
    Geetanjali (@geetanjaligg)
    Hari (@haridjango123)
    Haris Ibrahim K. V. (@harisibrahimkv) -
    Imran Ahmed (@rekenerd) +
    Imran Ahmed (@rekenerd)
    Indradhanush Gupta (@indradhanush) -
    jaocb (@jklmn13) +
    jaocb (@jklmn13)
    Karanveer Singh (@kvsingh)
    Kenith Aiyappa (@K-7) -
    Kishor Bhat (@therealkbhat) +
    Kishor Bhat (@therealkbhat)
    Kracekumar Ramaraj (@kracekumar)
    Kumar Anirudha (@anistark)
    Mudassir (@mudassir0909)
    Nabeel Valapra (@nabeelvalapra) -
    Navaneethan (@nava45) +
    Navaneethan (@nava45)
    Noufal Ibrahim (@nibrahim)
    Parbhat Puri (@Parbhat)
    Parth Oberoi (@hTrap) -
    Peeyush Aggarwal (@PeeyushAgg) -
    Puneeth Chaganti (@punchagan) +
    Peeyush Aggarwal (@dhuadaar) +
    Puneeth Chaganti (@punchagan)
    @rahulrb0509 +
    Ramaseshan (@ramaseshan) +
    Ravi Shanker B (@ravishanker404)
    Sai Krishna (@psykrsna) + +
    Saurabh (@saurabh-fueled)
    Saurabh Kumar (@theskumar)
    Shrayas Rajagopal (@shrayasr) - -
    Sivasubramaniam Arunachalam (@sivaa)
    @sjose1x + +
    Sumit Chahal (@smtchahal)
    Suraj Jayakumar (@sjayakum)
    Suresh R. (@umulingu) - -
    Tapasweni Pathak (@tapasweni-pathak)
    The Gitter Badger (@gitter-badger) + +
    @vanishan
    Vignesh Sarma K (@vigneshsarma)
    Vijay (@vnbang2003) - -
    Vinay Singh (@vinay13) -
    VoidspaceXYZ (@ramaseshan) From 2affb321bbd23f24f90a787a3feec71b34d16432 Mon Sep 17 00:00:00 2001 From: RishabhJain2018 Date: Fri, 9 Sep 2016 23:57:54 +0530 Subject: [PATCH 504/666] Added profile view with update feature. --- junction/profiles/forms.py | 2 +- junction/profiles/views.py | 33 +++++++++++++------- junction/templates/profiles/userprofile.html | 4 +-- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/junction/profiles/forms.py b/junction/profiles/forms.py index fde34ccb..cfe6e940 100644 --- a/junction/profiles/forms.py +++ b/junction/profiles/forms.py @@ -6,4 +6,4 @@ class ProfileForm(forms.ModelForm): class Meta: model = Profile fields = ['city', 'contact_no'] - exclude = ('user',) + exclude = ['user',] diff --git a/junction/profiles/views.py b/junction/profiles/views.py index 3d8f7bc5..4895a550 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -3,9 +3,11 @@ # Third Party Stuff from django.contrib.auth.decorators import login_required -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404, redirect from django.views.decorators.http import require_http_methods from django.http import HttpResponseRedirect +from django.core.urlresolvers import reverse +from django.contrib.auth.models import User # Junction Stuff from junction.conferences.models import Conference @@ -31,15 +33,22 @@ def dashboard(request): @login_required def profile(request): - form = ProfileForm() - user = request.user - if request.method == "POST": - form = ProfileForm(request.POST) - if form.is_valid(): - form = form.save(commit=False) - form.user = user - form.save() - print "form saved" - return HttpResponseRedirect("/profiles") + username = request.user + detail = None + + if request.method == "POST" and username == request.user: + user = get_object_or_404(User, pk=username.id) + detail = get_object_or_404(Profile, user=user) + detail_form = ProfileForm(request.POST, instance=detail) + + if detail_form.is_valid(): + detail = detail_form.save() + return HttpResponseRedirect(reverse('profiles:dashboard')) + elif request.method == "GET": - return render(request, 'profiles/userprofile.html') + user = get_object_or_404(User, pk=username.id) + detail = get_object_or_404(Profile, user=user) + if detail: + return render(request, 'profiles/userprofile.html', {'detail':detail}) + else: + return render(request, 'profiles/userprofile.html') diff --git a/junction/templates/profiles/userprofile.html b/junction/templates/profiles/userprofile.html index a2b2a591..a02ab062 100644 --- a/junction/templates/profiles/userprofile.html +++ b/junction/templates/profiles/userprofile.html @@ -36,13 +36,13 @@

    Edit Profile

    - +
    - +
    From 8463b41d205f4f54974b1a0880a381c92dcecc9a Mon Sep 17 00:00:00 2001 From: RishabhJain2018 Date: Sat, 10 Sep 2016 00:10:10 +0530 Subject: [PATCH 505/666] flake8 fixes --- junction/profiles/forms.py | 8 ++++---- junction/profiles/views.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/junction/profiles/forms.py b/junction/profiles/forms.py index cfe6e940..0a05f170 100644 --- a/junction/profiles/forms.py +++ b/junction/profiles/forms.py @@ -3,7 +3,7 @@ class ProfileForm(forms.ModelForm): - class Meta: - model = Profile - fields = ['city', 'contact_no'] - exclude = ['user',] + class Meta: + model = Profile + fields = ['city', 'contact_no',] + exclude = ['user',] diff --git a/junction/profiles/views.py b/junction/profiles/views.py index 4895a550..a8037dd4 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -3,7 +3,7 @@ # Third Party Stuff from django.contrib.auth.decorators import login_required -from django.shortcuts import render, get_object_or_404, redirect +from django.shortcuts import render, get_object_or_404 from django.views.decorators.http import require_http_methods from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse @@ -49,6 +49,6 @@ def profile(request): user = get_object_or_404(User, pk=username.id) detail = get_object_or_404(Profile, user=user) if detail: - return render(request, 'profiles/userprofile.html', {'detail':detail}) + return render(request, 'profiles/userprofile.html', {'detail': detail}) else: return render(request, 'profiles/userprofile.html') From 72e8f75acc92f8794d66b132c00ed40d7172c8a4 Mon Sep 17 00:00:00 2001 From: RishabhJain2018 Date: Sat, 10 Sep 2016 00:25:14 +0530 Subject: [PATCH 506/666] flake8 fixes --- junction/profiles/admin.py | 4 ++-- junction/profiles/forms.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/junction/profiles/admin.py b/junction/profiles/admin.py index 75653d62..9131d9f2 100644 --- a/junction/profiles/admin.py +++ b/junction/profiles/admin.py @@ -3,7 +3,7 @@ class ProfileAdmin(admin.ModelAdmin): - list_display = ('__unicode__', 'city', 'contact_no') - search_fields = ('contact_no', 'city') + list_display = ('__unicode__', 'city', 'contact_no') + search_fields = ('contact_no', 'city') admin.site.register(Profile, ProfileAdmin) diff --git a/junction/profiles/forms.py b/junction/profiles/forms.py index 0a05f170..0d5014bf 100644 --- a/junction/profiles/forms.py +++ b/junction/profiles/forms.py @@ -5,5 +5,5 @@ class ProfileForm(forms.ModelForm): class Meta: model = Profile - fields = ['city', 'contact_no',] - exclude = ['user',] + fields = ['city', 'contact_no', ] + exclude = ['user', ] From 118477e8239ac6dc48e20b83eb31e8ee7731bddf Mon Sep 17 00:00:00 2001 From: RishabhJain2018 Date: Thu, 15 Sep 2016 23:35:06 +0530 Subject: [PATCH 507/666] Reverted Indendation --- junction/profiles/urls.py | 1 - junction/profiles/views.py | 3 + junction/templates/base.html | 321 +++++++++++++++++------------------ 3 files changed, 163 insertions(+), 162 deletions(-) diff --git a/junction/profiles/urls.py b/junction/profiles/urls.py index 3924343f..17cd761e 100644 --- a/junction/profiles/urls.py +++ b/junction/profiles/urls.py @@ -5,5 +5,4 @@ urlpatterns = [ url(r'^$', views.dashboard, name='dashboard'), - url(r'edit/$', views.profile, name='profile') ] diff --git a/junction/profiles/views.py b/junction/profiles/views.py index a8037dd4..430994e4 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -29,6 +29,7 @@ def dashboard(request): conf_proposals[conf.name] = [proposal] return render(request, 'profiles/dashboard.html', {'conf_proposals': conf_proposals}) +<<<<<<< HEAD @login_required @@ -52,3 +53,5 @@ def profile(request): return render(request, 'profiles/userprofile.html', {'detail': detail}) else: return render(request, 'profiles/userprofile.html') +======= +>>>>>>> parent of 13c807e... Template Added diff --git a/junction/templates/base.html b/junction/templates/base.html index 445bdadf..f5fc70fd 100644 --- a/junction/templates/base.html +++ b/junction/templates/base.html @@ -3,174 +3,173 @@ {% load static from staticfiles %} {% load django_bootstrap_breadcrumbs %} {% block breadcrumbs %} - {% clear_breadcrumbs %} - {% breadcrumb_safe "" "page-home" %} + {% clear_breadcrumbs %} + {% breadcrumb_safe "" "page-home" %} {% endblock %} - - - - - - - - - - - {# Place icon files in the root if possible (let browsers look for them where they expect them to be) #} - - - - - - - - {# Tile icon for Win8 (144x144 + tile color) #} - - - - - {# Theme color on android #} - - - {% block head_title %}{{ SITE_INFO.site_name }}{% endblock head_title %} - - - {# SEO and OpenGraph data - Needs to be fed dynamically according to the content of the page #} - - - - - - - - {# A high-level section name. E.g. Technology #} - {# permalink to the curent page #} - {# A path to an image used on the page. Helpful for telling crawlers what image to use for a page preview. Can be an array, meaning, there can be more than one of these tags (duplicate the WHOLE tag). #} - - - - - - {% block style_extra %} {% endblock %} - - - - - - - - - - {% block endhead %} - {% endblock %} + + + + + + + + + + + {# Place icon files in the root if possible (let browsers look for them where they expect them to be) #} + + + + + + + + {# Tile icon for Win8 (144x144 + tile color) #} + + + + + {# Theme color on android #} + + + {% block head_title %}{{ SITE_INFO.site_name }}{% endblock head_title %} + + + {# SEO and OpenGraph data - Needs to be fed dynamically according to the content of the page #} + + + + + + + + {# A high-level section name. E.g. Technology #} + {# permalink to the curent page #} + {# A path to an image used on the page. Helpful for telling crawlers what image to use for a page preview. Can be an array, meaning, there can be more than one of these tags (duplicate the WHOLE tag). #} + + + + + + {% block style_extra %} {% endblock %} + + + + + + + + + + {% block endhead %} + {% endblock %} - - - - {% block header %} - {% endblock %} - - {% render_breadcrumbs "django_bootstrap_breadcrumbs/bootstrap3.html" %} - - -
    -
    -
    - {% block content %} - {% endblock %} -
    -
    -
    - - -
    -
    -
    -
    -

    {{ SITE_INFO.footer|safe }} • Powered by Junction

    -
    -
    -
    -
    - - - - - - {% block script_extra %}{% endblock %} - - {# -- Google Analytics -- #} - {% if SITE_INFO.google_analytics_id %} - - {% endif %} + + + + {% block header %} + {% endblock %} + + {% render_breadcrumbs "django_bootstrap_breadcrumbs/bootstrap3.html" %} + + +
    +
    +
    + {% block content %} + {% endblock %} +
    +
    +
    + + +
    +
    +
    +
    +

    {{ SITE_INFO.footer|safe }} • Powered by Junction

    +
    +
    +
    +
    + + + + + + {% block script_extra %}{% endblock %} + + {# -- Google Analytics -- #} + {% if SITE_INFO.google_analytics_id %} + + {% endif %} From 5bf8175a3c18447cf33e08c3323ee66967c01334 Mon Sep 17 00:00:00 2001 From: RishabhJain2018 Date: Thu, 15 Sep 2016 23:39:22 +0530 Subject: [PATCH 508/666] Removing Comments --- junction/profiles/views.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/junction/profiles/views.py b/junction/profiles/views.py index 430994e4..a8037dd4 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -29,7 +29,6 @@ def dashboard(request): conf_proposals[conf.name] = [proposal] return render(request, 'profiles/dashboard.html', {'conf_proposals': conf_proposals}) -<<<<<<< HEAD @login_required @@ -53,5 +52,3 @@ def profile(request): return render(request, 'profiles/userprofile.html', {'detail': detail}) else: return render(request, 'profiles/userprofile.html') -======= ->>>>>>> parent of 13c807e... Template Added From 8db1f43a571fd2d6b3c3ab8b473b8a5202f30ff1 Mon Sep 17 00:00:00 2001 From: RishabhJain2018 Date: Sun, 18 Sep 2016 00:53:47 +0530 Subject: [PATCH 509/666] Added Changes --- junction/profiles/urls.py | 3 +++ junction/profiles/views.py | 4 ++-- junction/templates/base.html | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/junction/profiles/urls.py b/junction/profiles/urls.py index 17cd761e..63de9408 100644 --- a/junction/profiles/urls.py +++ b/junction/profiles/urls.py @@ -5,4 +5,7 @@ urlpatterns = [ url(r'^$', views.dashboard, name='dashboard'), + url(r'^edit/$', views.profile, name='profile'), + + ] diff --git a/junction/profiles/views.py b/junction/profiles/views.py index a8037dd4..5fbb7684 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -46,8 +46,8 @@ def profile(request): return HttpResponseRedirect(reverse('profiles:dashboard')) elif request.method == "GET": - user = get_object_or_404(User, pk=username.id) - detail = get_object_or_404(Profile, user=user) + user = User.objects.get(pk=username.id) + detail = Profile.objects.filter(user=user).exists() if detail: return render(request, 'profiles/userprofile.html', {'detail': detail}) else: diff --git a/junction/templates/base.html b/junction/templates/base.html index f5fc70fd..7ca43821 100644 --- a/junction/templates/base.html +++ b/junction/templates/base.html @@ -109,6 +109,7 @@
    {% endblock %} - - - From c3f9f481463df7e03e1ffb225f56bc5da62d23ea Mon Sep 17 00:00:00 2001 From: shweta Date: Tue, 21 Mar 2017 16:35:09 +0530 Subject: [PATCH 524/666] Django version upgraded from 1.8 to 1.9 --- junction/tickets/migrations/0003_merge.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 junction/tickets/migrations/0003_merge.py diff --git a/junction/tickets/migrations/0003_merge.py b/junction/tickets/migrations/0003_merge.py new file mode 100644 index 00000000..0f17f1d8 --- /dev/null +++ b/junction/tickets/migrations/0003_merge.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2017-03-20 17:35 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('tickets', '0002_auto_20170105_1713'), + ('tickets', '0002_auto_20170104_0124'), + ] + + operations = [ + ] From 999ee44d2fb51f8190b5f32eec9a973a2bdce2e0 Mon Sep 17 00:00:00 2001 From: shashankaryan Date: Sun, 26 Mar 2017 11:18:33 +0530 Subject: [PATCH 525/666] Revert "Update breadcrumbs" This reverts commit 5649824f7f90a2d3c5d6d00b53253484e8027529. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 7efaff7a..1ed613dc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,7 +39,7 @@ django_simple_history==1.6.3 # Frontend Helpers # ------------------------------------------------- django-bootstrap3==6.1.0 -django-bootstrap-breadcrumbs==0.8 +django-bootstrap-breadcrumbs==0.7.3 django-flat-theme==1.1.3 # Markdown Editor From dccbbf6623e6583d7ed4742233b4c8f5555ed832 Mon Sep 17 00:00:00 2001 From: shashankaryan Date: Sun, 26 Mar 2017 11:47:33 +0530 Subject: [PATCH 526/666] CSS updated for social auth buttons. --- junction/static/css/app.css | 175 ++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/junction/static/css/app.css b/junction/static/css/app.css index 6ed9cd75..83ae5056 100644 --- a/junction/static/css/app.css +++ b/junction/static/css/app.css @@ -8649,6 +8649,181 @@ fieldset[disabled] .btn-github.focus { color: #eee; background-color: #454545; } + +.btn-twitter { + color: white; + background-color: #4099FF; + border-color: #4585f3; +} +.btn-twitter:focus, +.btn-twitter.focus { + color: white; + background-color: #1566f0; + border-color: #0b47ad; +} +.btn-twitter:hover { + color: white; + background-color: #1566f0; + border-color: #0f60ec; +} +.btn-twitter:active, +.btn-twitter.active, +.open > .dropdown-toggle.btn-twitter { + color: white; + background-color: #1566f0; + border-color: #0f60ec; +} +.btn-twitter:active:hover, +.btn-twitter.active:hover, +.open > .dropdown-toggle.btn-twitter:hover, +.btn-twitter:active:focus, +.btn-twitter.active:focus, +.open > .dropdown-toggle.btn-twitter:focus, +.btn-twitter:active.focus, +.btn-twitter.active.focus, +.open > .dropdown-toggle.btn-twitter.focus { + color: white; + background-color: #0e56d4; + border-color: #0b47ad; +} +.btn-twitter:active, +.btn-twitter.active, +.open > .dropdown-toggle.btn-twitter { + background-image: none; +} +.btn-twitter.disabled:hover, +.btn-twitter[disabled]:hover, +fieldset[disabled] .btn-twitter:hover, +.btn-twitter.disabled:focus, +.btn-twitter[disabled]:focus, +fieldset[disabled] .btn-twitter:focus, +.btn-twitter.disabled.focus, +.btn-twitter[disabled].focus, +fieldset[disabled] .btn-twitter.focus { + background-color: #4585f3; + border-color: #4585f3; +} +.btn-twitter .badge { + color: #4585f3; + background-color: white; +} +.btn-linkedin { + color: white; + background-color: #007bb6; + border-color: #4585f3; +} +.btn-linkedin:focus, +.btn-linkedin.focus { + color: white; + background-color: #1566f0; + border-color: #0b47ad; +} +.btn-linkedin:hover { + color: white; + background-color: #1566f0; + border-color: #0f60ec; +} +.btn-linkedin:active, +.btn-linkedin.active, +.open > .dropdown-toggle.btn-linkedin { + color: white; + background-color: #1566f0; + border-color: #0f60ec; +} +.btn-linkedin:active:hover, +.btn-linkedin.active:hover, +.open > .dropdown-toggle.btn-linkedin:hover, +.btn-linkedin:active:focus, +.btn-linkedin.active:focus, +.open > .dropdown-toggle.btn-linkedin:focus, +.btn-linkedin:active.focus, +.btn-linkedin.active.focus, +.open > .dropdown-toggle.btn-linkedin.focus { + color: white; + background-color: #0e56d4; + border-color: #0b47ad; +} +.btn-linkedin:active, +.btn-linkedin.active, +.open > .dropdown-toggle.btn-linkedin { + background-image: none; +} +.btn-linkedin.disabled:hover, +.btn-linkedin[disabled]:hover, +fieldset[disabled] .btn-linkedin:hover, +.btn-linkedin.disabled:focus, +.btn-linkedin[disabled]:focus, +fieldset[disabled] .btn-linkedin:focus, +.btn-linkedin.disabled.focus, +.btn-linkedin[disabled].focus, +fieldset[disabled] .btn-linkedin.focus { + background-color: #4585f3; + border-color: #4585f3; +} +.btn-linkedin .badge { + color: #4585f3; + background-color: white; +} + +.btn-facebook { + padding: 6px; + color: white; + background-color: #8b9dc3; + border-color: #3b5998; +} +.btn-facebook:focus, +.btn-facebook.focus { + color: white; + background-color: #1566f0; + border-color: #0b47ad; +} +.btn-facebook:hover { + color: white; + background-color: #3b5998; + border-color: #3b5998; +} +.btn-facebook:active, +.btn-facebook.active, +.open > .dropdown-toggle.btn-facebook { + color: white; + background-color: #1566f0; + border-color: #0f60ec; +} +.btn-facebook:active:hover, +.btn-facebook.active:hover, +.open > .dropdown-toggle.btn-facebook:hover, +.btn-facebook:active:focus, +.btn-facebook.active:focus, +.open > .dropdown-toggle.btn-facebook:focus, +.btn-facebook:active.focus, +.btn-facebook.active.focus, +.open > .dropdown-toggle.btn-facebook.focus { + color: white; + background-color: #0e56d4; + border-color: #0b47ad; +} +.btn-facebook:active, +.btn-facebook.active, +.open > .dropdown-toggle.btn-facebook { + background-image: none; +} +.btn-facebook.disabled:hover, +.btn-facebook[disabled]:hover, +fieldset[disabled] .btn-facebook:hover, +.btn-facebook.disabled:focus, +.btn-facebook[disabled]:focus, +fieldset[disabled] .btn-facebook:focus, +.btn-facebook.disabled.focus, +.btn-facebook[disabled].focus, +fieldset[disabled] .btn-facebook.focus { + background-color: #4585f3; + border-color: #4585f3; +} +.btn-facebook .badge { + color: #4585f3; + background-color: white; +} + .hr-mini { margin: 10px 0; } From f9f0e3dc5c6c46b2ce75e3e24c64e9692b6f2d95 Mon Sep 17 00:00:00 2001 From: shashankaryan Date: Sun, 26 Mar 2017 11:59:53 +0530 Subject: [PATCH 527/666] updated breadcrumbs --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1ed613dc..7efaff7a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,7 +39,7 @@ django_simple_history==1.6.3 # Frontend Helpers # ------------------------------------------------- django-bootstrap3==6.1.0 -django-bootstrap-breadcrumbs==0.7.3 +django-bootstrap-breadcrumbs==0.8 django-flat-theme==1.1.3 # Markdown Editor From ae1f561797addf98e0a7449d043ccd5f52affd23 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Mon, 27 Mar 2017 20:02:52 +0530 Subject: [PATCH 528/666] cleanup(static): remove unnessary tracked css files --- junction/static/css/app.css | 178 +- .../static/css/bootstrap-markdown.min.css | 1 - junction/static/css/bootstrap.css | 6203 ----------------- junction/static/css/bootstrap.min.css | 5 - junction/static/css/details.css | 73 - junction/static/css/fonts.css | 47 - junction/static/css/form.css | 54 - junction/static/css/layout.css | 460 -- junction/static/css/list.css | 43 - junction/static/css/style.css | 377 - junction/static/css/sweetalert.css | 715 -- junction/static/css/ui.css | 7 - 12 files changed, 3 insertions(+), 8160 deletions(-) delete mode 100644 junction/static/css/bootstrap-markdown.min.css delete mode 100644 junction/static/css/bootstrap.css delete mode 100644 junction/static/css/bootstrap.min.css delete mode 100644 junction/static/css/details.css delete mode 100644 junction/static/css/fonts.css delete mode 100644 junction/static/css/form.css delete mode 100644 junction/static/css/layout.css delete mode 100644 junction/static/css/list.css delete mode 100644 junction/static/css/style.css delete mode 100644 junction/static/css/sweetalert.css delete mode 100644 junction/static/css/ui.css diff --git a/junction/static/css/app.css b/junction/static/css/app.css index 83ae5056..b0a16788 100644 --- a/junction/static/css/app.css +++ b/junction/static/css/app.css @@ -8480,6 +8480,9 @@ input#id_remember { z-index: 90000; border-radius: 0; } +.green { + color: green; +} .align-bottom { vertical-align: bottom; } @@ -8649,181 +8652,6 @@ fieldset[disabled] .btn-github.focus { color: #eee; background-color: #454545; } - -.btn-twitter { - color: white; - background-color: #4099FF; - border-color: #4585f3; -} -.btn-twitter:focus, -.btn-twitter.focus { - color: white; - background-color: #1566f0; - border-color: #0b47ad; -} -.btn-twitter:hover { - color: white; - background-color: #1566f0; - border-color: #0f60ec; -} -.btn-twitter:active, -.btn-twitter.active, -.open > .dropdown-toggle.btn-twitter { - color: white; - background-color: #1566f0; - border-color: #0f60ec; -} -.btn-twitter:active:hover, -.btn-twitter.active:hover, -.open > .dropdown-toggle.btn-twitter:hover, -.btn-twitter:active:focus, -.btn-twitter.active:focus, -.open > .dropdown-toggle.btn-twitter:focus, -.btn-twitter:active.focus, -.btn-twitter.active.focus, -.open > .dropdown-toggle.btn-twitter.focus { - color: white; - background-color: #0e56d4; - border-color: #0b47ad; -} -.btn-twitter:active, -.btn-twitter.active, -.open > .dropdown-toggle.btn-twitter { - background-image: none; -} -.btn-twitter.disabled:hover, -.btn-twitter[disabled]:hover, -fieldset[disabled] .btn-twitter:hover, -.btn-twitter.disabled:focus, -.btn-twitter[disabled]:focus, -fieldset[disabled] .btn-twitter:focus, -.btn-twitter.disabled.focus, -.btn-twitter[disabled].focus, -fieldset[disabled] .btn-twitter.focus { - background-color: #4585f3; - border-color: #4585f3; -} -.btn-twitter .badge { - color: #4585f3; - background-color: white; -} -.btn-linkedin { - color: white; - background-color: #007bb6; - border-color: #4585f3; -} -.btn-linkedin:focus, -.btn-linkedin.focus { - color: white; - background-color: #1566f0; - border-color: #0b47ad; -} -.btn-linkedin:hover { - color: white; - background-color: #1566f0; - border-color: #0f60ec; -} -.btn-linkedin:active, -.btn-linkedin.active, -.open > .dropdown-toggle.btn-linkedin { - color: white; - background-color: #1566f0; - border-color: #0f60ec; -} -.btn-linkedin:active:hover, -.btn-linkedin.active:hover, -.open > .dropdown-toggle.btn-linkedin:hover, -.btn-linkedin:active:focus, -.btn-linkedin.active:focus, -.open > .dropdown-toggle.btn-linkedin:focus, -.btn-linkedin:active.focus, -.btn-linkedin.active.focus, -.open > .dropdown-toggle.btn-linkedin.focus { - color: white; - background-color: #0e56d4; - border-color: #0b47ad; -} -.btn-linkedin:active, -.btn-linkedin.active, -.open > .dropdown-toggle.btn-linkedin { - background-image: none; -} -.btn-linkedin.disabled:hover, -.btn-linkedin[disabled]:hover, -fieldset[disabled] .btn-linkedin:hover, -.btn-linkedin.disabled:focus, -.btn-linkedin[disabled]:focus, -fieldset[disabled] .btn-linkedin:focus, -.btn-linkedin.disabled.focus, -.btn-linkedin[disabled].focus, -fieldset[disabled] .btn-linkedin.focus { - background-color: #4585f3; - border-color: #4585f3; -} -.btn-linkedin .badge { - color: #4585f3; - background-color: white; -} - -.btn-facebook { - padding: 6px; - color: white; - background-color: #8b9dc3; - border-color: #3b5998; -} -.btn-facebook:focus, -.btn-facebook.focus { - color: white; - background-color: #1566f0; - border-color: #0b47ad; -} -.btn-facebook:hover { - color: white; - background-color: #3b5998; - border-color: #3b5998; -} -.btn-facebook:active, -.btn-facebook.active, -.open > .dropdown-toggle.btn-facebook { - color: white; - background-color: #1566f0; - border-color: #0f60ec; -} -.btn-facebook:active:hover, -.btn-facebook.active:hover, -.open > .dropdown-toggle.btn-facebook:hover, -.btn-facebook:active:focus, -.btn-facebook.active:focus, -.open > .dropdown-toggle.btn-facebook:focus, -.btn-facebook:active.focus, -.btn-facebook.active.focus, -.open > .dropdown-toggle.btn-facebook.focus { - color: white; - background-color: #0e56d4; - border-color: #0b47ad; -} -.btn-facebook:active, -.btn-facebook.active, -.open > .dropdown-toggle.btn-facebook { - background-image: none; -} -.btn-facebook.disabled:hover, -.btn-facebook[disabled]:hover, -fieldset[disabled] .btn-facebook:hover, -.btn-facebook.disabled:focus, -.btn-facebook[disabled]:focus, -fieldset[disabled] .btn-facebook:focus, -.btn-facebook.disabled.focus, -.btn-facebook[disabled].focus, -fieldset[disabled] .btn-facebook.focus { - background-color: #4585f3; - border-color: #4585f3; -} -.btn-facebook .badge { - color: #4585f3; - background-color: white; -} - .hr-mini { margin: 10px 0; } diff --git a/junction/static/css/bootstrap-markdown.min.css b/junction/static/css/bootstrap-markdown.min.css deleted file mode 100644 index 388b2f5f..00000000 --- a/junction/static/css/bootstrap-markdown.min.css +++ /dev/null @@ -1 +0,0 @@ -.md-editor{display:block;border:1px solid #ddd}.md-editor .md-footer,.md-editor>.md-header{display:block;padding:6px 4px;background:#f5f5f5}.md-editor>.md-header{margin:0}.md-editor>.md-preview{background:#fff;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;min-height:10px;overflow:auto}.md-editor>textarea{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:14px;outline:0;margin:0;display:block;padding:0;width:100%;border:0;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;border-radius:0;box-shadow:none;background:#eee}.md-editor>textarea:focus{box-shadow:none;background:#fff}.md-editor.active{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.md-editor .md-controls{float:right;padding:3px}.md-editor .md-controls .md-control{right:5px;color:#bebebe;padding:3px 3px 3px 10px}.md-editor .md-controls .md-control:hover{color:#333}.md-editor.md-fullscreen-mode{width:100%;height:100%;position:fixed;top:0;left:0;z-index:99999;padding:60px 30px 15px;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-footer{display:none}.md-editor.md-fullscreen-mode .md-input,.md-editor.md-fullscreen-mode .md-preview{margin:0 auto!important;height:100%!important;font-size:20px!important;padding:20px!important;color:#999;line-height:1.6em!important;resize:none!important;box-shadow:none!important;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-preview{color:#333;overflow:auto}.md-editor.md-fullscreen-mode .md-input:focus,.md-editor.md-fullscreen-mode .md-input:hover{color:#333;background:#fff!important}.md-editor.md-fullscreen-mode .md-header{background:0 0;text-align:center;position:fixed;width:100%;top:20px}.md-editor.md-fullscreen-mode .btn-group{float:none}.md-editor.md-fullscreen-mode .btn{border:0;background:0 0;color:#b3b3b3}.md-editor.md-fullscreen-mode .btn.active,.md-editor.md-fullscreen-mode .btn:active,.md-editor.md-fullscreen-mode .btn:focus,.md-editor.md-fullscreen-mode .btn:hover{box-shadow:none;color:#333}.md-editor.md-fullscreen-mode .md-fullscreen-controls{position:absolute;top:20px;right:20px;text-align:right;z-index:1002;display:block}.md-editor.md-fullscreen-mode .md-fullscreen-controls a{color:#b3b3b3;clear:right;margin:10px;width:30px;height:30px;text-align:center}.md-editor.md-fullscreen-mode .md-fullscreen-controls a:hover{color:#333;text-decoration:none}.md-editor.md-fullscreen-mode .md-editor{height:100%!important;position:relative}.md-editor .md-fullscreen-controls{display:none}.md-nooverflow{overflow:hidden;position:fixed;width:100%} \ No newline at end of file diff --git a/junction/static/css/bootstrap.css b/junction/static/css/bootstrap.css deleted file mode 100644 index 037dd056..00000000 --- a/junction/static/css/bootstrap.css +++ /dev/null @@ -1,6203 +0,0 @@ -/*! - * Bootstrap v3.2.0 (http://getbootstrap.com) - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ - -/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ -html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -body { - margin: 0; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -nav, -section, -summary { - display: block; -} -audio, -canvas, -progress, -video { - display: inline-block; - vertical-align: baseline; -} -audio:not([controls]) { - display: none; - height: 0; -} -[hidden], -template { - display: none; -} -a { - background: transparent; -} -a:active, -a:hover { - outline: 0; -} -abbr[title] { - border-bottom: 1px dotted; -} -b, -strong { - font-weight: bold; -} -dfn { - font-style: italic; -} -h1 { - margin: .67em 0; - font-size: 2em; -} -mark { - color: #000; - background: #ff0; -} -small { - font-size: 80%; -} -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} -sup { - top: -.5em; -} -sub { - bottom: -.25em; -} -img { - border: 0; -} -svg:not(:root) { - overflow: hidden; -} -figure { - margin: 1em 40px; -} -hr { - height: 0; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -pre { - overflow: auto; -} -code, -kbd, -pre, -samp { - font-family: monospace, monospace; - font-size: 1em; -} -button, -input, -optgroup, -select, -textarea { - margin: 0; - font: inherit; - color: inherit; -} -button { - overflow: visible; -} -button, -select { - text-transform: none; -} -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; - cursor: pointer; -} -button[disabled], -html input[disabled] { - cursor: default; -} -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} -input { - line-height: normal; -} -input[type="checkbox"], -input[type="radio"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 0; -} -input[type="number"]::-webkit-inner-spin-button, -input[type="number"]::-webkit-outer-spin-button { - height: auto; -} -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} -fieldset { - padding: .35em .625em .75em; - margin: 0 2px; - border: 1px solid #c0c0c0; -} -legend { - padding: 0; - border: 0; -} -textarea { - overflow: auto; -} -optgroup { - font-weight: bold; -} -table { - border-spacing: 0; - border-collapse: collapse; -} -td, -th { - padding: 0; -} -@media print { - * { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } - select { - background: #fff !important; - } - .navbar { - display: none; - } - .table td, - .table th { - background-color: #fff !important; - } - .btn > .caret, - .dropup > .btn > .caret { - border-top-color: #000 !important; - } - .label { - border: 1px solid #000; - } - .table { - border-collapse: collapse !important; - } - .table-bordered th, - .table-bordered td { - border: 1px solid #ddd !important; - } -} -@font-face { - font-family: 'Glyphicons Halflings'; - - src: url('../fonts/glyphicons-halflings-regular.eot'); - src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); -} -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - font-style: normal; - font-weight: normal; - line-height: 1; - - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.glyphicon-asterisk:before { - content: "\2a"; -} -.glyphicon-plus:before { - content: "\2b"; -} -.glyphicon-euro:before { - content: "\20ac"; -} -.glyphicon-minus:before { - content: "\2212"; -} -.glyphicon-cloud:before { - content: "\2601"; -} -.glyphicon-envelope:before { - content: "\2709"; -} -.glyphicon-pencil:before { - content: "\270f"; -} -.glyphicon-glass:before { - content: "\e001"; -} -.glyphicon-music:before { - content: "\e002"; -} -.glyphicon-search:before { - content: "\e003"; -} -.glyphicon-heart:before { - content: "\e005"; -} -.glyphicon-star:before { - content: "\e006"; -} -.glyphicon-star-empty:before { - content: "\e007"; -} -.glyphicon-user:before { - content: "\e008"; -} -.glyphicon-film:before { - content: "\e009"; -} -.glyphicon-th-large:before { - content: "\e010"; -} -.glyphicon-th:before { - content: "\e011"; -} -.glyphicon-th-list:before { - content: "\e012"; -} -.glyphicon-ok:before { - content: "\e013"; -} -.glyphicon-remove:before { - content: "\e014"; -} -.glyphicon-zoom-in:before { - content: "\e015"; -} -.glyphicon-zoom-out:before { - content: "\e016"; -} -.glyphicon-off:before { - content: "\e017"; -} -.glyphicon-signal:before { - content: "\e018"; -} -.glyphicon-cog:before { - content: "\e019"; -} -.glyphicon-trash:before { - content: "\e020"; -} -.glyphicon-home:before { - content: "\e021"; -} -.glyphicon-file:before { - content: "\e022"; -} -.glyphicon-time:before { - content: "\e023"; -} -.glyphicon-road:before { - content: "\e024"; -} -.glyphicon-download-alt:before { - content: "\e025"; -} -.glyphicon-download:before { - content: "\e026"; -} -.glyphicon-upload:before { - content: "\e027"; -} -.glyphicon-inbox:before { - content: "\e028"; -} -.glyphicon-play-circle:before { - content: "\e029"; -} -.glyphicon-repeat:before { - content: "\e030"; -} -.glyphicon-refresh:before { - content: "\e031"; -} -.glyphicon-list-alt:before { - content: "\e032"; -} -.glyphicon-lock:before { - content: "\e033"; -} -.glyphicon-flag:before { - content: "\e034"; -} -.glyphicon-headphones:before { - content: "\e035"; -} -.glyphicon-volume-off:before { - content: "\e036"; -} -.glyphicon-volume-down:before { - content: "\e037"; -} -.glyphicon-volume-up:before { - content: "\e038"; -} -.glyphicon-qrcode:before { - content: "\e039"; -} -.glyphicon-barcode:before { - content: "\e040"; -} -.glyphicon-tag:before { - content: "\e041"; -} -.glyphicon-tags:before { - content: "\e042"; -} -.glyphicon-book:before { - content: "\e043"; -} -.glyphicon-bookmark:before { - content: "\e044"; -} -.glyphicon-print:before { - content: "\e045"; -} -.glyphicon-camera:before { - content: "\e046"; -} -.glyphicon-font:before { - content: "\e047"; -} -.glyphicon-bold:before { - content: "\e048"; -} -.glyphicon-italic:before { - content: "\e049"; -} -.glyphicon-text-height:before { - content: "\e050"; -} -.glyphicon-text-width:before { - content: "\e051"; -} -.glyphicon-align-left:before { - content: "\e052"; -} -.glyphicon-align-center:before { - content: "\e053"; -} -.glyphicon-align-right:before { - content: "\e054"; -} -.glyphicon-align-justify:before { - content: "\e055"; -} -.glyphicon-list:before { - content: "\e056"; -} -.glyphicon-indent-left:before { - content: "\e057"; -} -.glyphicon-indent-right:before { - content: "\e058"; -} -.glyphicon-facetime-video:before { - content: "\e059"; -} -.glyphicon-picture:before { - content: "\e060"; -} -.glyphicon-map-marker:before { - content: "\e062"; -} -.glyphicon-adjust:before { - content: "\e063"; -} -.glyphicon-tint:before { - content: "\e064"; -} -.glyphicon-edit:before { - content: "\e065"; -} -.glyphicon-share:before { - content: "\e066"; -} -.glyphicon-check:before { - content: "\e067"; -} -.glyphicon-move:before { - content: "\e068"; -} -.glyphicon-step-backward:before { - content: "\e069"; -} -.glyphicon-fast-backward:before { - content: "\e070"; -} -.glyphicon-backward:before { - content: "\e071"; -} -.glyphicon-play:before { - content: "\e072"; -} -.glyphicon-pause:before { - content: "\e073"; -} -.glyphicon-stop:before { - content: "\e074"; -} -.glyphicon-forward:before { - content: "\e075"; -} -.glyphicon-fast-forward:before { - content: "\e076"; -} -.glyphicon-step-forward:before { - content: "\e077"; -} -.glyphicon-eject:before { - content: "\e078"; -} -.glyphicon-chevron-left:before { - content: "\e079"; -} -.glyphicon-chevron-right:before { - content: "\e080"; -} -.glyphicon-plus-sign:before { - content: "\e081"; -} -.glyphicon-minus-sign:before { - content: "\e082"; -} -.glyphicon-remove-sign:before { - content: "\e083"; -} -.glyphicon-ok-sign:before { - content: "\e084"; -} -.glyphicon-question-sign:before { - content: "\e085"; -} -.glyphicon-info-sign:before { - content: "\e086"; -} -.glyphicon-screenshot:before { - content: "\e087"; -} -.glyphicon-remove-circle:before { - content: "\e088"; -} -.glyphicon-ok-circle:before { - content: "\e089"; -} -.glyphicon-ban-circle:before { - content: "\e090"; -} -.glyphicon-arrow-left:before { - content: "\e091"; -} -.glyphicon-arrow-right:before { - content: "\e092"; -} -.glyphicon-arrow-up:before { - content: "\e093"; -} -.glyphicon-arrow-down:before { - content: "\e094"; -} -.glyphicon-share-alt:before { - content: "\e095"; -} -.glyphicon-resize-full:before { - content: "\e096"; -} -.glyphicon-resize-small:before { - content: "\e097"; -} -.glyphicon-exclamation-sign:before { - content: "\e101"; -} -.glyphicon-gift:before { - content: "\e102"; -} -.glyphicon-leaf:before { - content: "\e103"; -} -.glyphicon-fire:before { - content: "\e104"; -} -.glyphicon-eye-open:before { - content: "\e105"; -} -.glyphicon-eye-close:before { - content: "\e106"; -} -.glyphicon-warning-sign:before { - content: "\e107"; -} -.glyphicon-plane:before { - content: "\e108"; -} -.glyphicon-calendar:before { - content: "\e109"; -} -.glyphicon-random:before { - content: "\e110"; -} -.glyphicon-comment:before { - content: "\e111"; -} -.glyphicon-magnet:before { - content: "\e112"; -} -.glyphicon-chevron-up:before { - content: "\e113"; -} -.glyphicon-chevron-down:before { - content: "\e114"; -} -.glyphicon-retweet:before { - content: "\e115"; -} -.glyphicon-shopping-cart:before { - content: "\e116"; -} -.glyphicon-folder-close:before { - content: "\e117"; -} -.glyphicon-folder-open:before { - content: "\e118"; -} -.glyphicon-resize-vertical:before { - content: "\e119"; -} -.glyphicon-resize-horizontal:before { - content: "\e120"; -} -.glyphicon-hdd:before { - content: "\e121"; -} -.glyphicon-bullhorn:before { - content: "\e122"; -} -.glyphicon-bell:before { - content: "\e123"; -} -.glyphicon-certificate:before { - content: "\e124"; -} -.glyphicon-thumbs-up:before { - content: "\e125"; -} -.glyphicon-thumbs-down:before { - content: "\e126"; -} -.glyphicon-hand-right:before { - content: "\e127"; -} -.glyphicon-hand-left:before { - content: "\e128"; -} -.glyphicon-hand-up:before { - content: "\e129"; -} -.glyphicon-hand-down:before { - content: "\e130"; -} -.glyphicon-circle-arrow-right:before { - content: "\e131"; -} -.glyphicon-circle-arrow-left:before { - content: "\e132"; -} -.glyphicon-circle-arrow-up:before { - content: "\e133"; -} -.glyphicon-circle-arrow-down:before { - content: "\e134"; -} -.glyphicon-globe:before { - content: "\e135"; -} -.glyphicon-wrench:before { - content: "\e136"; -} -.glyphicon-tasks:before { - content: "\e137"; -} -.glyphicon-filter:before { - content: "\e138"; -} -.glyphicon-briefcase:before { - content: "\e139"; -} -.glyphicon-fullscreen:before { - content: "\e140"; -} -.glyphicon-dashboard:before { - content: "\e141"; -} -.glyphicon-paperclip:before { - content: "\e142"; -} -.glyphicon-heart-empty:before { - content: "\e143"; -} -.glyphicon-link:before { - content: "\e144"; -} -.glyphicon-phone:before { - content: "\e145"; -} -.glyphicon-pushpin:before { - content: "\e146"; -} -.glyphicon-usd:before { - content: "\e148"; -} -.glyphicon-gbp:before { - content: "\e149"; -} -.glyphicon-sort:before { - content: "\e150"; -} -.glyphicon-sort-by-alphabet:before { - content: "\e151"; -} -.glyphicon-sort-by-alphabet-alt:before { - content: "\e152"; -} -.glyphicon-sort-by-order:before { - content: "\e153"; -} -.glyphicon-sort-by-order-alt:before { - content: "\e154"; -} -.glyphicon-sort-by-attributes:before { - content: "\e155"; -} -.glyphicon-sort-by-attributes-alt:before { - content: "\e156"; -} -.glyphicon-unchecked:before { - content: "\e157"; -} -.glyphicon-expand:before { - content: "\e158"; -} -.glyphicon-collapse-down:before { - content: "\e159"; -} -.glyphicon-collapse-up:before { - content: "\e160"; -} -.glyphicon-log-in:before { - content: "\e161"; -} -.glyphicon-flash:before { - content: "\e162"; -} -.glyphicon-log-out:before { - content: "\e163"; -} -.glyphicon-new-window:before { - content: "\e164"; -} -.glyphicon-record:before { - content: "\e165"; -} -.glyphicon-save:before { - content: "\e166"; -} -.glyphicon-open:before { - content: "\e167"; -} -.glyphicon-saved:before { - content: "\e168"; -} -.glyphicon-import:before { - content: "\e169"; -} -.glyphicon-export:before { - content: "\e170"; -} -.glyphicon-send:before { - content: "\e171"; -} -.glyphicon-floppy-disk:before { - content: "\e172"; -} -.glyphicon-floppy-saved:before { - content: "\e173"; -} -.glyphicon-floppy-remove:before { - content: "\e174"; -} -.glyphicon-floppy-save:before { - content: "\e175"; -} -.glyphicon-floppy-open:before { - content: "\e176"; -} -.glyphicon-credit-card:before { - content: "\e177"; -} -.glyphicon-transfer:before { - content: "\e178"; -} -.glyphicon-cutlery:before { - content: "\e179"; -} -.glyphicon-header:before { - content: "\e180"; -} -.glyphicon-compressed:before { - content: "\e181"; -} -.glyphicon-earphone:before { - content: "\e182"; -} -.glyphicon-phone-alt:before { - content: "\e183"; -} -.glyphicon-tower:before { - content: "\e184"; -} -.glyphicon-stats:before { - content: "\e185"; -} -.glyphicon-sd-video:before { - content: "\e186"; -} -.glyphicon-hd-video:before { - content: "\e187"; -} -.glyphicon-subtitles:before { - content: "\e188"; -} -.glyphicon-sound-stereo:before { - content: "\e189"; -} -.glyphicon-sound-dolby:before { - content: "\e190"; -} -.glyphicon-sound-5-1:before { - content: "\e191"; -} -.glyphicon-sound-6-1:before { - content: "\e192"; -} -.glyphicon-sound-7-1:before { - content: "\e193"; -} -.glyphicon-copyright-mark:before { - content: "\e194"; -} -.glyphicon-registration-mark:before { - content: "\e195"; -} -.glyphicon-cloud-download:before { - content: "\e197"; -} -.glyphicon-cloud-upload:before { - content: "\e198"; -} -.glyphicon-tree-conifer:before { - content: "\e199"; -} -.glyphicon-tree-deciduous:before { - content: "\e200"; -} -* { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -*:before, -*:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -html { - font-size: 10px; - - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - color: #333; - background-color: #fff; -} -input, -button, -select, -textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; -} -a { - color: #428bca; - text-decoration: none; -} -a:hover, -a:focus { - color: #2a6496; - text-decoration: underline; -} -a:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -figure { - margin: 0; -} -img { - vertical-align: middle; -} -.img-responsive, -.thumbnail > img, -.thumbnail a > img, -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - width: 100% \9; - max-width: 100%; - height: auto; -} -.img-rounded { - border-radius: 6px; -} -.img-thumbnail { - display: inline-block; - width: 100% \9; - max-width: 100%; - height: auto; - padding: 4px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - -o-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; -} -.img-circle { - border-radius: 50%; -} -hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eee; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} -h1, -h2, -h3, -h4, -h5, -h6, -.h1, -.h2, -.h3, -.h4, -.h5, -.h6 { - font-family: inherit; - font-weight: 500; - line-height: 1.1; - color: inherit; -} -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small, -.h1 small, -.h2 small, -.h3 small, -.h4 small, -.h5 small, -.h6 small, -h1 .small, -h2 .small, -h3 .small, -h4 .small, -h5 .small, -h6 .small, -.h1 .small, -.h2 .small, -.h3 .small, -.h4 .small, -.h5 .small, -.h6 .small { - font-weight: normal; - line-height: 1; - color: #777; -} -h1, -.h1, -h2, -.h2, -h3, -.h3 { - margin-top: 20px; - margin-bottom: 10px; -} -h1 small, -.h1 small, -h2 small, -.h2 small, -h3 small, -.h3 small, -h1 .small, -.h1 .small, -h2 .small, -.h2 .small, -h3 .small, -.h3 .small { - font-size: 65%; -} -h4, -.h4, -h5, -.h5, -h6, -.h6 { - margin-top: 10px; - margin-bottom: 10px; -} -h4 small, -.h4 small, -h5 small, -.h5 small, -h6 small, -.h6 small, -h4 .small, -.h4 .small, -h5 .small, -.h5 .small, -h6 .small, -.h6 .small { - font-size: 75%; -} -h1, -.h1 { - font-size: 36px; -} -h2, -.h2 { - font-size: 30px; -} -h3, -.h3 { - font-size: 24px; -} -h4, -.h4 { - font-size: 18px; -} -h5, -.h5 { - font-size: 14px; -} -h6, -.h6 { - font-size: 12px; -} -p { - margin: 0 0 10px; -} -.lead { - margin-bottom: 20px; - font-size: 16px; - font-weight: 300; - line-height: 1.4; -} -@media (min-width: 768px) { - .lead { - font-size: 21px; - } -} -small, -.small { - font-size: 85%; -} -cite { - font-style: normal; -} -mark, -.mark { - padding: .2em; - background-color: #fcf8e3; -} -.text-left { - text-align: left; -} -.text-right { - text-align: right; -} -.text-center { - text-align: center; -} -.text-justify { - text-align: justify; -} -.text-nowrap { - white-space: nowrap; -} -.text-lowercase { - text-transform: lowercase; -} -.text-uppercase { - text-transform: uppercase; -} -.text-capitalize { - text-transform: capitalize; -} -.text-muted { - color: #777; -} -.text-primary { - color: #428bca; -} -a.text-primary:hover { - color: #3071a9; -} -.text-success { - color: #3c763d; -} -a.text-success:hover { - color: #2b542c; -} -.text-info { - color: #31708f; -} -a.text-info:hover { - color: #245269; -} -.text-warning { - color: #8a6d3b; -} -a.text-warning:hover { - color: #66512c; -} -.text-danger { - color: #a94442; -} -a.text-danger:hover { - color: #843534; -} -.bg-primary { - color: #fff; - background-color: #428bca; -} -a.bg-primary:hover { - background-color: #3071a9; -} -.bg-success { - background-color: #dff0d8; -} -a.bg-success:hover { - background-color: #c1e2b3; -} -.bg-info { - background-color: #d9edf7; -} -a.bg-info:hover { - background-color: #afd9ee; -} -.bg-warning { - background-color: #fcf8e3; -} -a.bg-warning:hover { - background-color: #f7ecb5; -} -.bg-danger { - background-color: #f2dede; -} -a.bg-danger:hover { - background-color: #e4b9b9; -} -.page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eee; -} -ul, -ol { - margin-top: 0; - margin-bottom: 10px; -} -ul ul, -ol ul, -ul ol, -ol ol { - margin-bottom: 0; -} -.list-unstyled { - padding-left: 0; - list-style: none; -} -.list-inline { - padding-left: 0; - margin-left: -5px; - list-style: none; -} -.list-inline > li { - display: inline-block; - padding-right: 5px; - padding-left: 5px; -} -dl { - margin-top: 0; - margin-bottom: 20px; -} -dt, -dd { - line-height: 1.42857143; -} -dt { - font-weight: bold; -} -dd { - margin-left: 0; -} -@media (min-width: 768px) { - .dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - } - .dl-horizontal dd { - margin-left: 180px; - } -} -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #777; -} -.initialism { - font-size: 90%; - text-transform: uppercase; -} -blockquote { - padding: 10px 20px; - margin: 0 0 20px; - font-size: 17.5px; - border-left: 5px solid #eee; -} -blockquote p:last-child, -blockquote ul:last-child, -blockquote ol:last-child { - margin-bottom: 0; -} -blockquote footer, -blockquote small, -blockquote .small { - display: block; - font-size: 80%; - line-height: 1.42857143; - color: #777; -} -blockquote footer:before, -blockquote small:before, -blockquote .small:before { - content: '\2014 \00A0'; -} -.blockquote-reverse, -blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - text-align: right; - border-right: 5px solid #eee; - border-left: 0; -} -.blockquote-reverse footer:before, -blockquote.pull-right footer:before, -.blockquote-reverse small:before, -blockquote.pull-right small:before, -.blockquote-reverse .small:before, -blockquote.pull-right .small:before { - content: ''; -} -.blockquote-reverse footer:after, -blockquote.pull-right footer:after, -.blockquote-reverse small:after, -blockquote.pull-right small:after, -.blockquote-reverse .small:after, -blockquote.pull-right .small:after { - content: '\00A0 \2014'; -} -blockquote:before, -blockquote:after { - content: ""; -} -address { - margin-bottom: 20px; - font-style: normal; - line-height: 1.42857143; -} -code, -kbd, -pre, -samp { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; -} -code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - background-color: #f9f2f4; - border-radius: 4px; -} -kbd { - padding: 2px 4px; - font-size: 90%; - color: #fff; - background-color: #333; - border-radius: 3px; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); -} -kbd kbd { - padding: 0; - font-size: 100%; - -webkit-box-shadow: none; - box-shadow: none; -} -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.42857143; - color: #333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #ccc; - border-radius: 4px; -} -pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0; -} -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} -.container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -@media (min-width: 768px) { - .container { - width: 750px; - } -} -@media (min-width: 992px) { - .container { - width: 970px; - } -} -@media (min-width: 1200px) { - .container { - width: 1170px; - } -} -.container-fluid { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -.row { - margin-right: -15px; - margin-left: -15px; -} -.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; -} -.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { - float: left; -} -.col-xs-12 { - width: 100%; -} -.col-xs-11 { - width: 91.66666667%; -} -.col-xs-10 { - width: 83.33333333%; -} -.col-xs-9 { - width: 75%; -} -.col-xs-8 { - width: 66.66666667%; -} -.col-xs-7 { - width: 58.33333333%; -} -.col-xs-6 { - width: 50%; -} -.col-xs-5 { - width: 41.66666667%; -} -.col-xs-4 { - width: 33.33333333%; -} -.col-xs-3 { - width: 25%; -} -.col-xs-2 { - width: 16.66666667%; -} -.col-xs-1 { - width: 8.33333333%; -} -.col-xs-pull-12 { - right: 100%; -} -.col-xs-pull-11 { - right: 91.66666667%; -} -.col-xs-pull-10 { - right: 83.33333333%; -} -.col-xs-pull-9 { - right: 75%; -} -.col-xs-pull-8 { - right: 66.66666667%; -} -.col-xs-pull-7 { - right: 58.33333333%; -} -.col-xs-pull-6 { - right: 50%; -} -.col-xs-pull-5 { - right: 41.66666667%; -} -.col-xs-pull-4 { - right: 33.33333333%; -} -.col-xs-pull-3 { - right: 25%; -} -.col-xs-pull-2 { - right: 16.66666667%; -} -.col-xs-pull-1 { - right: 8.33333333%; -} -.col-xs-pull-0 { - right: auto; -} -.col-xs-push-12 { - left: 100%; -} -.col-xs-push-11 { - left: 91.66666667%; -} -.col-xs-push-10 { - left: 83.33333333%; -} -.col-xs-push-9 { - left: 75%; -} -.col-xs-push-8 { - left: 66.66666667%; -} -.col-xs-push-7 { - left: 58.33333333%; -} -.col-xs-push-6 { - left: 50%; -} -.col-xs-push-5 { - left: 41.66666667%; -} -.col-xs-push-4 { - left: 33.33333333%; -} -.col-xs-push-3 { - left: 25%; -} -.col-xs-push-2 { - left: 16.66666667%; -} -.col-xs-push-1 { - left: 8.33333333%; -} -.col-xs-push-0 { - left: auto; -} -.col-xs-offset-12 { - margin-left: 100%; -} -.col-xs-offset-11 { - margin-left: 91.66666667%; -} -.col-xs-offset-10 { - margin-left: 83.33333333%; -} -.col-xs-offset-9 { - margin-left: 75%; -} -.col-xs-offset-8 { - margin-left: 66.66666667%; -} -.col-xs-offset-7 { - margin-left: 58.33333333%; -} -.col-xs-offset-6 { - margin-left: 50%; -} -.col-xs-offset-5 { - margin-left: 41.66666667%; -} -.col-xs-offset-4 { - margin-left: 33.33333333%; -} -.col-xs-offset-3 { - margin-left: 25%; -} -.col-xs-offset-2 { - margin-left: 16.66666667%; -} -.col-xs-offset-1 { - margin-left: 8.33333333%; -} -.col-xs-offset-0 { - margin-left: 0; -} -@media (min-width: 768px) { - .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { - float: left; - } - .col-sm-12 { - width: 100%; - } - .col-sm-11 { - width: 91.66666667%; - } - .col-sm-10 { - width: 83.33333333%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-8 { - width: 66.66666667%; - } - .col-sm-7 { - width: 58.33333333%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-5 { - width: 41.66666667%; - } - .col-sm-4 { - width: 33.33333333%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-2 { - width: 16.66666667%; - } - .col-sm-1 { - width: 8.33333333%; - } - .col-sm-pull-12 { - right: 100%; - } - .col-sm-pull-11 { - right: 91.66666667%; - } - .col-sm-pull-10 { - right: 83.33333333%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-8 { - right: 66.66666667%; - } - .col-sm-pull-7 { - right: 58.33333333%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-5 { - right: 41.66666667%; - } - .col-sm-pull-4 { - right: 33.33333333%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-2 { - right: 16.66666667%; - } - .col-sm-pull-1 { - right: 8.33333333%; - } - .col-sm-pull-0 { - right: auto; - } - .col-sm-push-12 { - left: 100%; - } - .col-sm-push-11 { - left: 91.66666667%; - } - .col-sm-push-10 { - left: 83.33333333%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-8 { - left: 66.66666667%; - } - .col-sm-push-7 { - left: 58.33333333%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-5 { - left: 41.66666667%; - } - .col-sm-push-4 { - left: 33.33333333%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-2 { - left: 16.66666667%; - } - .col-sm-push-1 { - left: 8.33333333%; - } - .col-sm-push-0 { - left: auto; - } - .col-sm-offset-12 { - margin-left: 100%; - } - .col-sm-offset-11 { - margin-left: 91.66666667%; - } - .col-sm-offset-10 { - margin-left: 83.33333333%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-8 { - margin-left: 66.66666667%; - } - .col-sm-offset-7 { - margin-left: 58.33333333%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-5 { - margin-left: 41.66666667%; - } - .col-sm-offset-4 { - margin-left: 33.33333333%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-2 { - margin-left: 16.66666667%; - } - .col-sm-offset-1 { - margin-left: 8.33333333%; - } - .col-sm-offset-0 { - margin-left: 0; - } -} -@media (min-width: 992px) { - .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { - float: left; - } - .col-md-12 { - width: 100%; - } - .col-md-11 { - width: 91.66666667%; - } - .col-md-10 { - width: 83.33333333%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666667%; - } - .col-md-7 { - width: 58.33333333%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666667%; - } - .col-md-4 { - width: 33.33333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.66666667%; - } - .col-md-1 { - width: 8.33333333%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666667%; - } - .col-md-pull-10 { - right: 83.33333333%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666667%; - } - .col-md-pull-7 { - right: 58.33333333%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666667%; - } - .col-md-pull-4 { - right: 33.33333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.66666667%; - } - .col-md-pull-1 { - right: 8.33333333%; - } - .col-md-pull-0 { - right: auto; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666667%; - } - .col-md-push-10 { - left: 83.33333333%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666667%; - } - .col-md-push-7 { - left: 58.33333333%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666667%; - } - .col-md-push-4 { - left: 33.33333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.66666667%; - } - .col-md-push-1 { - left: 8.33333333%; - } - .col-md-push-0 { - left: auto; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666667%; - } - .col-md-offset-10 { - margin-left: 83.33333333%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666667%; - } - .col-md-offset-7 { - margin-left: 58.33333333%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.66666667%; - } - .col-md-offset-1 { - margin-left: 8.33333333%; - } - .col-md-offset-0 { - margin-left: 0; - } -} -@media (min-width: 1200px) { - .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { - float: left; - } - .col-lg-12 { - width: 100%; - } - .col-lg-11 { - width: 91.66666667%; - } - .col-lg-10 { - width: 83.33333333%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666667%; - } - .col-lg-7 { - width: 58.33333333%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666667%; - } - .col-lg-4 { - width: 33.33333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.66666667%; - } - .col-lg-1 { - width: 8.33333333%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666667%; - } - .col-lg-pull-10 { - right: 83.33333333%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666667%; - } - .col-lg-pull-7 { - right: 58.33333333%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666667%; - } - .col-lg-pull-4 { - right: 33.33333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.66666667%; - } - .col-lg-pull-1 { - right: 8.33333333%; - } - .col-lg-pull-0 { - right: auto; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666667%; - } - .col-lg-push-10 { - left: 83.33333333%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666667%; - } - .col-lg-push-7 { - left: 58.33333333%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666667%; - } - .col-lg-push-4 { - left: 33.33333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.66666667%; - } - .col-lg-push-1 { - left: 8.33333333%; - } - .col-lg-push-0 { - left: auto; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666667%; - } - .col-lg-offset-10 { - margin-left: 83.33333333%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666667%; - } - .col-lg-offset-7 { - margin-left: 58.33333333%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.66666667%; - } - .col-lg-offset-1 { - margin-left: 8.33333333%; - } - .col-lg-offset-0 { - margin-left: 0; - } -} -table { - background-color: transparent; -} -th { - text-align: left; -} -.table { - width: 100%; - max-width: 100%; - margin-bottom: 20px; -} -.table > thead > tr > th, -.table > tbody > tr > th, -.table > tfoot > tr > th, -.table > thead > tr > td, -.table > tbody > tr > td, -.table > tfoot > tr > td { - padding: 8px; - line-height: 1.42857143; - vertical-align: top; - border-top: 1px solid #ddd; -} -.table > thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid #ddd; -} -.table > caption + thead > tr:first-child > th, -.table > colgroup + thead > tr:first-child > th, -.table > thead:first-child > tr:first-child > th, -.table > caption + thead > tr:first-child > td, -.table > colgroup + thead > tr:first-child > td, -.table > thead:first-child > tr:first-child > td { - border-top: 0; -} -.table > tbody + tbody { - border-top: 2px solid #ddd; -} -.table .table { - background-color: #fff; -} -.table-condensed > thead > tr > th, -.table-condensed > tbody > tr > th, -.table-condensed > tfoot > tr > th, -.table-condensed > thead > tr > td, -.table-condensed > tbody > tr > td, -.table-condensed > tfoot > tr > td { - padding: 5px; -} -.table-bordered { - border: 1px solid #ddd; -} -.table-bordered > thead > tr > th, -.table-bordered > tbody > tr > th, -.table-bordered > tfoot > tr > th, -.table-bordered > thead > tr > td, -.table-bordered > tbody > tr > td, -.table-bordered > tfoot > tr > td { - border: 1px solid #ddd; -} -.table-bordered > thead > tr > th, -.table-bordered > thead > tr > td { - border-bottom-width: 2px; -} -.table-striped > tbody > tr:nth-child(odd) > td, -.table-striped > tbody > tr:nth-child(odd) > th { - background-color: #f9f9f9; -} -.table-hover > tbody > tr:hover > td, -.table-hover > tbody > tr:hover > th { - background-color: #f5f5f5; -} -table col[class*="col-"] { - position: static; - display: table-column; - float: none; -} -table td[class*="col-"], -table th[class*="col-"] { - position: static; - display: table-cell; - float: none; -} -.table > thead > tr > td.active, -.table > tbody > tr > td.active, -.table > tfoot > tr > td.active, -.table > thead > tr > th.active, -.table > tbody > tr > th.active, -.table > tfoot > tr > th.active, -.table > thead > tr.active > td, -.table > tbody > tr.active > td, -.table > tfoot > tr.active > td, -.table > thead > tr.active > th, -.table > tbody > tr.active > th, -.table > tfoot > tr.active > th { - background-color: #f5f5f5; -} -.table-hover > tbody > tr > td.active:hover, -.table-hover > tbody > tr > th.active:hover, -.table-hover > tbody > tr.active:hover > td, -.table-hover > tbody > tr:hover > .active, -.table-hover > tbody > tr.active:hover > th { - background-color: #e8e8e8; -} -.table > thead > tr > td.success, -.table > tbody > tr > td.success, -.table > tfoot > tr > td.success, -.table > thead > tr > th.success, -.table > tbody > tr > th.success, -.table > tfoot > tr > th.success, -.table > thead > tr.success > td, -.table > tbody > tr.success > td, -.table > tfoot > tr.success > td, -.table > thead > tr.success > th, -.table > tbody > tr.success > th, -.table > tfoot > tr.success > th { - background-color: #dff0d8; -} -.table-hover > tbody > tr > td.success:hover, -.table-hover > tbody > tr > th.success:hover, -.table-hover > tbody > tr.success:hover > td, -.table-hover > tbody > tr:hover > .success, -.table-hover > tbody > tr.success:hover > th { - background-color: #d0e9c6; -} -.table > thead > tr > td.info, -.table > tbody > tr > td.info, -.table > tfoot > tr > td.info, -.table > thead > tr > th.info, -.table > tbody > tr > th.info, -.table > tfoot > tr > th.info, -.table > thead > tr.info > td, -.table > tbody > tr.info > td, -.table > tfoot > tr.info > td, -.table > thead > tr.info > th, -.table > tbody > tr.info > th, -.table > tfoot > tr.info > th { - background-color: #d9edf7; -} -.table-hover > tbody > tr > td.info:hover, -.table-hover > tbody > tr > th.info:hover, -.table-hover > tbody > tr.info:hover > td, -.table-hover > tbody > tr:hover > .info, -.table-hover > tbody > tr.info:hover > th { - background-color: #c4e3f3; -} -.table > thead > tr > td.warning, -.table > tbody > tr > td.warning, -.table > tfoot > tr > td.warning, -.table > thead > tr > th.warning, -.table > tbody > tr > th.warning, -.table > tfoot > tr > th.warning, -.table > thead > tr.warning > td, -.table > tbody > tr.warning > td, -.table > tfoot > tr.warning > td, -.table > thead > tr.warning > th, -.table > tbody > tr.warning > th, -.table > tfoot > tr.warning > th { - background-color: #fcf8e3; -} -.table-hover > tbody > tr > td.warning:hover, -.table-hover > tbody > tr > th.warning:hover, -.table-hover > tbody > tr.warning:hover > td, -.table-hover > tbody > tr:hover > .warning, -.table-hover > tbody > tr.warning:hover > th { - background-color: #faf2cc; -} -.table > thead > tr > td.danger, -.table > tbody > tr > td.danger, -.table > tfoot > tr > td.danger, -.table > thead > tr > th.danger, -.table > tbody > tr > th.danger, -.table > tfoot > tr > th.danger, -.table > thead > tr.danger > td, -.table > tbody > tr.danger > td, -.table > tfoot > tr.danger > td, -.table > thead > tr.danger > th, -.table > tbody > tr.danger > th, -.table > tfoot > tr.danger > th { - background-color: #f2dede; -} -.table-hover > tbody > tr > td.danger:hover, -.table-hover > tbody > tr > th.danger:hover, -.table-hover > tbody > tr.danger:hover > td, -.table-hover > tbody > tr:hover > .danger, -.table-hover > tbody > tr.danger:hover > th { - background-color: #ebcccc; -} -@media screen and (max-width: 767px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-x: auto; - overflow-y: hidden; - -webkit-overflow-scrolling: touch; - -ms-overflow-style: -ms-autohiding-scrollbar; - border: 1px solid #ddd; - } - .table-responsive > .table { - margin-bottom: 0; - } - .table-responsive > .table > thead > tr > th, - .table-responsive > .table > tbody > tr > th, - .table-responsive > .table > tfoot > tr > th, - .table-responsive > .table > thead > tr > td, - .table-responsive > .table > tbody > tr > td, - .table-responsive > .table > tfoot > tr > td { - white-space: nowrap; - } - .table-responsive > .table-bordered { - border: 0; - } - .table-responsive > .table-bordered > thead > tr > th:first-child, - .table-responsive > .table-bordered > tbody > tr > th:first-child, - .table-responsive > .table-bordered > tfoot > tr > th:first-child, - .table-responsive > .table-bordered > thead > tr > td:first-child, - .table-responsive > .table-bordered > tbody > tr > td:first-child, - .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; - } - .table-responsive > .table-bordered > thead > tr > th:last-child, - .table-responsive > .table-bordered > tbody > tr > th:last-child, - .table-responsive > .table-bordered > tfoot > tr > th:last-child, - .table-responsive > .table-bordered > thead > tr > td:last-child, - .table-responsive > .table-bordered > tbody > tr > td:last-child, - .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; - } - .table-responsive > .table-bordered > tbody > tr:last-child > th, - .table-responsive > .table-bordered > tfoot > tr:last-child > th, - .table-responsive > .table-bordered > tbody > tr:last-child > td, - .table-responsive > .table-bordered > tfoot > tr:last-child > td { - border-bottom: 0; - } -} -fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0; -} -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} -label { - display: inline-block; - max-width: 100%; - margin-bottom: 5px; - font-weight: bold; -} -input[type="search"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - line-height: normal; -} -input[type="file"] { - display: block; -} -input[type="range"] { - display: block; - width: 100%; -} -select[multiple], -select[size] { - height: auto; -} -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -output { - display: block; - padding-top: 7px; - font-size: 14px; - line-height: 1.42857143; - color: #555; -} -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857143; - color: #555; - background-color: #fff; - background-image: none; - border: 1px solid #ccc; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; - -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -} -.form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); -} -.form-control::-moz-placeholder { - color: #777; - opacity: 1; -} -.form-control:-ms-input-placeholder { - color: #777; -} -.form-control::-webkit-input-placeholder { - color: #777; -} -.form-control[disabled], -.form-control[readonly], -fieldset[disabled] .form-control { - cursor: not-allowed; - background-color: #eee; - opacity: 1; -} -textarea.form-control { - height: auto; -} -input[type="search"] { - -webkit-appearance: none; -} -input[type="date"], -input[type="time"], -input[type="datetime-local"], -input[type="month"] { - line-height: 34px; - line-height: 1.42857143 \0; -} -input[type="date"].input-sm, -input[type="time"].input-sm, -input[type="datetime-local"].input-sm, -input[type="month"].input-sm { - line-height: 30px; -} -input[type="date"].input-lg, -input[type="time"].input-lg, -input[type="datetime-local"].input-lg, -input[type="month"].input-lg { - line-height: 46px; -} -.form-group { - margin-bottom: 15px; -} -.radio, -.checkbox { - position: relative; - display: block; - min-height: 20px; - margin-top: 10px; - margin-bottom: 10px; -} -.radio label, -.checkbox label { - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - cursor: pointer; -} -.radio input[type="radio"], -.radio-inline input[type="radio"], -.checkbox input[type="checkbox"], -.checkbox-inline input[type="checkbox"] { - position: absolute; - margin-top: 4px \9; - margin-left: -20px; -} -.radio + .radio, -.checkbox + .checkbox { - margin-top: -5px; -} -.radio-inline, -.checkbox-inline { - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - vertical-align: middle; - cursor: pointer; -} -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; -} -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"].disabled, -input[type="checkbox"].disabled, -fieldset[disabled] input[type="radio"], -fieldset[disabled] input[type="checkbox"] { - cursor: not-allowed; -} -.radio-inline.disabled, -.checkbox-inline.disabled, -fieldset[disabled] .radio-inline, -fieldset[disabled] .checkbox-inline { - cursor: not-allowed; -} -.radio.disabled label, -.checkbox.disabled label, -fieldset[disabled] .radio label, -fieldset[disabled] .checkbox label { - cursor: not-allowed; -} -.form-control-static { - padding-top: 7px; - padding-bottom: 7px; - margin-bottom: 0; -} -.form-control-static.input-lg, -.form-control-static.input-sm { - padding-right: 0; - padding-left: 0; -} -.input-sm, -.form-horizontal .form-group-sm .form-control { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-sm { - height: 30px; - line-height: 30px; -} -textarea.input-sm, -select[multiple].input-sm { - height: auto; -} -.input-lg, -.form-horizontal .form-group-lg .form-control { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} -select.input-lg { - height: 46px; - line-height: 46px; -} -textarea.input-lg, -select[multiple].input-lg { - height: auto; -} -.has-feedback { - position: relative; -} -.has-feedback .form-control { - padding-right: 42.5px; -} -.form-control-feedback { - position: absolute; - top: 25px; - right: 0; - z-index: 2; - display: block; - width: 34px; - height: 34px; - line-height: 34px; - text-align: center; -} -.input-lg + .form-control-feedback { - width: 46px; - height: 46px; - line-height: 46px; -} -.input-sm + .form-control-feedback { - width: 30px; - height: 30px; - line-height: 30px; -} -.has-success .help-block, -.has-success .control-label, -.has-success .radio, -.has-success .checkbox, -.has-success .radio-inline, -.has-success .checkbox-inline { - color: #3c763d; -} -.has-success .form-control { - border-color: #3c763d; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-success .form-control:focus { - border-color: #2b542c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; -} -.has-success .input-group-addon { - color: #3c763d; - background-color: #dff0d8; - border-color: #3c763d; -} -.has-success .form-control-feedback { - color: #3c763d; -} -.has-warning .help-block, -.has-warning .control-label, -.has-warning .radio, -.has-warning .checkbox, -.has-warning .radio-inline, -.has-warning .checkbox-inline { - color: #8a6d3b; -} -.has-warning .form-control { - border-color: #8a6d3b; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-warning .form-control:focus { - border-color: #66512c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; -} -.has-warning .input-group-addon { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #8a6d3b; -} -.has-warning .form-control-feedback { - color: #8a6d3b; -} -.has-error .help-block, -.has-error .control-label, -.has-error .radio, -.has-error .checkbox, -.has-error .radio-inline, -.has-error .checkbox-inline { - color: #a94442; -} -.has-error .form-control { - border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-error .form-control:focus { - border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; -} -.has-error .input-group-addon { - color: #a94442; - background-color: #f2dede; - border-color: #a94442; -} -.has-error .form-control-feedback { - color: #a94442; -} -.has-feedback label.sr-only ~ .form-control-feedback { - top: 0; -} -.help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #737373; -} -@media (min-width: 768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .form-inline .input-group { - display: inline-table; - vertical-align: middle; - } - .form-inline .input-group .input-group-addon, - .form-inline .input-group .input-group-btn, - .form-inline .input-group .form-control { - width: auto; - } - .form-inline .input-group > .form-control { - width: 100%; - } - .form-inline .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio, - .form-inline .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio label, - .form-inline .checkbox label { - padding-left: 0; - } - .form-inline .radio input[type="radio"], - .form-inline .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .form-inline .has-feedback .form-control-feedback { - top: 0; - } -} -.form-horizontal .radio, -.form-horizontal .checkbox, -.form-horizontal .radio-inline, -.form-horizontal .checkbox-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0; -} -.form-horizontal .radio, -.form-horizontal .checkbox { - min-height: 27px; -} -.form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .form-horizontal .control-label { - padding-top: 7px; - margin-bottom: 0; - text-align: right; - } -} -.form-horizontal .has-feedback .form-control-feedback { - top: 0; - right: 15px; -} -@media (min-width: 768px) { - .form-horizontal .form-group-lg .control-label { - padding-top: 14.3px; - } -} -@media (min-width: 768px) { - .form-horizontal .form-group-sm .control-label { - padding-top: 6px; - } -} -.btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: normal; - line-height: 1.42857143; - text-align: center; - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} -.btn:focus, -.btn:active:focus, -.btn.active:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.btn:hover, -.btn:focus { - color: #333; - text-decoration: none; -} -.btn:active, -.btn.active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -} -.btn.disabled, -.btn[disabled], -fieldset[disabled] .btn { - pointer-events: none; - cursor: not-allowed; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - box-shadow: none; - opacity: .65; -} -.btn-default { - color: #333; - background-color: #fff; - border-color: #ccc; -} -.btn-default:hover, -.btn-default:focus, -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - color: #333; - background-color: #e6e6e6; - border-color: #adadad; -} -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - background-image: none; -} -.btn-default.disabled, -.btn-default[disabled], -fieldset[disabled] .btn-default, -.btn-default.disabled:hover, -.btn-default[disabled]:hover, -fieldset[disabled] .btn-default:hover, -.btn-default.disabled:focus, -.btn-default[disabled]:focus, -fieldset[disabled] .btn-default:focus, -.btn-default.disabled:active, -.btn-default[disabled]:active, -fieldset[disabled] .btn-default:active, -.btn-default.disabled.active, -.btn-default[disabled].active, -fieldset[disabled] .btn-default.active { - background-color: #fff; - border-color: #ccc; -} -.btn-default .badge { - color: #fff; - background-color: #333; -} -.btn-primary { - color: #fff; - background-color: #428bca; - border-color: #357ebd; -} -.btn-primary:hover, -.btn-primary:focus, -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - color: #fff; - background-color: #3071a9; - border-color: #285e8e; -} -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - background-image: none; -} -.btn-primary.disabled, -.btn-primary[disabled], -fieldset[disabled] .btn-primary, -.btn-primary.disabled:hover, -.btn-primary[disabled]:hover, -fieldset[disabled] .btn-primary:hover, -.btn-primary.disabled:focus, -.btn-primary[disabled]:focus, -fieldset[disabled] .btn-primary:focus, -.btn-primary.disabled:active, -.btn-primary[disabled]:active, -fieldset[disabled] .btn-primary:active, -.btn-primary.disabled.active, -.btn-primary[disabled].active, -fieldset[disabled] .btn-primary.active { - background-color: #428bca; - border-color: #357ebd; -} -.btn-primary .badge { - color: #428bca; - background-color: #fff; -} -.btn-success { - color: #fff; - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success:hover, -.btn-success:focus, -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - color: #fff; - background-color: #449d44; - border-color: #398439; -} -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - background-image: none; -} -.btn-success.disabled, -.btn-success[disabled], -fieldset[disabled] .btn-success, -.btn-success.disabled:hover, -.btn-success[disabled]:hover, -fieldset[disabled] .btn-success:hover, -.btn-success.disabled:focus, -.btn-success[disabled]:focus, -fieldset[disabled] .btn-success:focus, -.btn-success.disabled:active, -.btn-success[disabled]:active, -fieldset[disabled] .btn-success:active, -.btn-success.disabled.active, -.btn-success[disabled].active, -fieldset[disabled] .btn-success.active { - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success .badge { - color: #5cb85c; - background-color: #fff; -} -.btn-info { - color: #fff; - background-color: #5bc0de; - border-color: #46b8da; -} -.btn-info:hover, -.btn-info:focus, -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - color: #fff; - background-color: #31b0d5; - border-color: #269abc; -} -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - background-image: none; -} -.btn-info.disabled, -.btn-info[disabled], -fieldset[disabled] .btn-info, -.btn-info.disabled:hover, -.btn-info[disabled]:hover, -fieldset[disabled] .btn-info:hover, -.btn-info.disabled:focus, -.btn-info[disabled]:focus, -fieldset[disabled] .btn-info:focus, -.btn-info.disabled:active, -.btn-info[disabled]:active, -fieldset[disabled] .btn-info:active, -.btn-info.disabled.active, -.btn-info[disabled].active, -fieldset[disabled] .btn-info.active { - background-color: #5bc0de; - border-color: #46b8da; -} -.btn-info .badge { - color: #5bc0de; - background-color: #fff; -} -.btn-warning { - color: #fff; - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-warning:hover, -.btn-warning:focus, -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - color: #fff; - background-color: #ec971f; - border-color: #d58512; -} -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - background-image: none; -} -.btn-warning.disabled, -.btn-warning[disabled], -fieldset[disabled] .btn-warning, -.btn-warning.disabled:hover, -.btn-warning[disabled]:hover, -fieldset[disabled] .btn-warning:hover, -.btn-warning.disabled:focus, -.btn-warning[disabled]:focus, -fieldset[disabled] .btn-warning:focus, -.btn-warning.disabled:active, -.btn-warning[disabled]:active, -fieldset[disabled] .btn-warning:active, -.btn-warning.disabled.active, -.btn-warning[disabled].active, -fieldset[disabled] .btn-warning.active { - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-warning .badge { - color: #f0ad4e; - background-color: #fff; -} -.btn-danger { - color: #fff; - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger:hover, -.btn-danger:focus, -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - color: #fff; - background-color: #c9302c; - border-color: #ac2925; -} -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - background-image: none; -} -.btn-danger.disabled, -.btn-danger[disabled], -fieldset[disabled] .btn-danger, -.btn-danger.disabled:hover, -.btn-danger[disabled]:hover, -fieldset[disabled] .btn-danger:hover, -.btn-danger.disabled:focus, -.btn-danger[disabled]:focus, -fieldset[disabled] .btn-danger:focus, -.btn-danger.disabled:active, -.btn-danger[disabled]:active, -fieldset[disabled] .btn-danger:active, -.btn-danger.disabled.active, -.btn-danger[disabled].active, -fieldset[disabled] .btn-danger.active { - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger .badge { - color: #d9534f; - background-color: #fff; -} -.btn-link { - font-weight: normal; - color: #428bca; - cursor: pointer; - border-radius: 0; -} -.btn-link, -.btn-link:active, -.btn-link[disabled], -fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; -} -.btn-link, -.btn-link:hover, -.btn-link:focus, -.btn-link:active { - border-color: transparent; -} -.btn-link:hover, -.btn-link:focus { - color: #2a6496; - text-decoration: underline; - background-color: transparent; -} -.btn-link[disabled]:hover, -fieldset[disabled] .btn-link:hover, -.btn-link[disabled]:focus, -fieldset[disabled] .btn-link:focus { - color: #777; - text-decoration: none; -} -.btn-lg, -.btn-group-lg > .btn { - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} -.btn-sm, -.btn-group-sm > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-xs, -.btn-group-xs > .btn { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-block { - display: block; - width: 100%; -} -.btn-block + .btn-block { - margin-top: 5px; -} -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} -.fade { - opacity: 0; - -webkit-transition: opacity .15s linear; - -o-transition: opacity .15s linear; - transition: opacity .15s linear; -} -.fade.in { - opacity: 1; -} -.collapse { - display: none; -} -.collapse.in { - display: block; -} -tr.collapse.in { - display: table-row; -} -tbody.collapse.in { - display: table-row-group; -} -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height .35s ease; - -o-transition: height .35s ease; - transition: height .35s ease; -} -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px solid; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} -.dropdown { - position: relative; -} -.dropdown-toggle:focus { - outline: 0; -} -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - text-align: left; - list-style: none; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); - box-shadow: 0 6px 12px rgba(0, 0, 0, .175); -} -.dropdown-menu.pull-right { - right: 0; - left: auto; -} -.dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.42857143; - color: #333; - white-space: nowrap; -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - color: #262626; - text-decoration: none; - background-color: #f5f5f5; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #fff; - text-decoration: none; - background-color: #428bca; - outline: 0; -} -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #777; -} -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.open > .dropdown-menu { - display: block; -} -.open > a { - outline: 0; -} -.dropdown-menu-right { - right: 0; - left: auto; -} -.dropdown-menu-left { - right: auto; - left: 0; -} -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.42857143; - color: #777; - white-space: nowrap; -} -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; -} -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - content: ""; - border-top: 0; - border-bottom: 4px solid; -} -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; -} -@media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } - .navbar-right .dropdown-menu-left { - right: auto; - left: 0; - } -} -.btn-group, -.btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; -} -.btn-group > .btn, -.btn-group-vertical > .btn { - position: relative; - float: left; -} -.btn-group > .btn:hover, -.btn-group-vertical > .btn:hover, -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus, -.btn-group > .btn:active, -.btn-group-vertical > .btn:active, -.btn-group > .btn.active, -.btn-group-vertical > .btn.active { - z-index: 2; -} -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus { - outline: 0; -} -.btn-group .btn + .btn, -.btn-group .btn + .btn-group, -.btn-group .btn-group + .btn, -.btn-group .btn-group + .btn-group { - margin-left: -1px; -} -.btn-toolbar { - margin-left: -5px; -} -.btn-toolbar .btn-group, -.btn-toolbar .input-group { - float: left; -} -.btn-toolbar > .btn, -.btn-toolbar > .btn-group, -.btn-toolbar > .input-group { - margin-left: 5px; -} -.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; -} -.btn-group > .btn:first-child { - margin-left: 0; -} -.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group > .btn-group { - float: left; -} -.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group > .btn-group:first-child > .btn:last-child, -.btn-group > .btn-group:first-child > .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn-group:last-child > .btn:first-child { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} -.btn-group > .btn + .dropdown-toggle { - padding-right: 8px; - padding-left: 8px; -} -.btn-group > .btn-lg + .dropdown-toggle { - padding-right: 12px; - padding-left: 12px; -} -.btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -} -.btn-group.open .dropdown-toggle.btn-link { - -webkit-box-shadow: none; - box-shadow: none; -} -.btn .caret { - margin-left: 0; -} -.btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0; -} -.dropup .btn-lg .caret { - border-width: 0 5px 5px; -} -.btn-group-vertical > .btn, -.btn-group-vertical > .btn-group, -.btn-group-vertical > .btn-group > .btn { - display: block; - float: none; - width: 100%; - max-width: 100%; -} -.btn-group-vertical > .btn-group > .btn { - float: none; -} -.btn-group-vertical > .btn + .btn, -.btn-group-vertical > .btn + .btn-group, -.btn-group-vertical > .btn-group + .btn, -.btn-group-vertical > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; -} -.btn-group-vertical > .btn:not(:first-child):not(:last-child) { - border-radius: 0; -} -.btn-group-vertical > .btn:first-child:not(:last-child) { - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn:last-child:not(:first-child) { - border-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-left-radius: 4px; -} -.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, -.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; -} -.btn-group-justified > .btn, -.btn-group-justified > .btn-group { - display: table-cell; - float: none; - width: 1%; -} -.btn-group-justified > .btn-group .btn { - width: 100%; -} -.btn-group-justified > .btn-group .dropdown-menu { - left: auto; -} -[data-toggle="buttons"] > .btn > input[type="radio"], -[data-toggle="buttons"] > .btn > input[type="checkbox"] { - position: absolute; - z-index: -1; - filter: alpha(opacity=0); - opacity: 0; -} -.input-group { - position: relative; - display: table; - border-collapse: separate; -} -.input-group[class*="col-"] { - float: none; - padding-right: 0; - padding-left: 0; -} -.input-group .form-control { - position: relative; - z-index: 2; - float: left; - width: 100%; - margin-bottom: 0; -} -.input-group-lg > .form-control, -.input-group-lg > .input-group-addon, -.input-group-lg > .input-group-btn > .btn { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} -select.input-group-lg > .form-control, -select.input-group-lg > .input-group-addon, -select.input-group-lg > .input-group-btn > .btn { - height: 46px; - line-height: 46px; -} -textarea.input-group-lg > .form-control, -textarea.input-group-lg > .input-group-addon, -textarea.input-group-lg > .input-group-btn > .btn, -select[multiple].input-group-lg > .form-control, -select[multiple].input-group-lg > .input-group-addon, -select[multiple].input-group-lg > .input-group-btn > .btn { - height: auto; -} -.input-group-sm > .form-control, -.input-group-sm > .input-group-addon, -.input-group-sm > .input-group-btn > .btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-group-sm > .form-control, -select.input-group-sm > .input-group-addon, -select.input-group-sm > .input-group-btn > .btn { - height: 30px; - line-height: 30px; -} -textarea.input-group-sm > .form-control, -textarea.input-group-sm > .input-group-addon, -textarea.input-group-sm > .input-group-btn > .btn, -select[multiple].input-group-sm > .form-control, -select[multiple].input-group-sm > .input-group-addon, -select[multiple].input-group-sm > .input-group-btn > .btn { - height: auto; -} -.input-group-addon, -.input-group-btn, -.input-group .form-control { - display: table-cell; -} -.input-group-addon:not(:first-child):not(:last-child), -.input-group-btn:not(:first-child):not(:last-child), -.input-group .form-control:not(:first-child):not(:last-child) { - border-radius: 0; -} -.input-group-addon, -.input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; -} -.input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: normal; - line-height: 1; - color: #555; - text-align: center; - background-color: #eee; - border: 1px solid #ccc; - border-radius: 4px; -} -.input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px; -} -.input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px; -} -.input-group-addon input[type="radio"], -.input-group-addon input[type="checkbox"] { - margin-top: 0; -} -.input-group .form-control:first-child, -.input-group-addon:first-child, -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .btn-group > .btn, -.input-group-btn:first-child > .dropdown-toggle, -.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), -.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.input-group-addon:first-child { - border-right: 0; -} -.input-group .form-control:last-child, -.input-group-addon:last-child, -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .btn-group > .btn, -.input-group-btn:last-child > .dropdown-toggle, -.input-group-btn:first-child > .btn:not(:first-child), -.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.input-group-addon:last-child { - border-left: 0; -} -.input-group-btn { - position: relative; - font-size: 0; - white-space: nowrap; -} -.input-group-btn > .btn { - position: relative; -} -.input-group-btn > .btn + .btn { - margin-left: -1px; -} -.input-group-btn > .btn:hover, -.input-group-btn > .btn:focus, -.input-group-btn > .btn:active { - z-index: 2; -} -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .btn-group { - margin-right: -1px; -} -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .btn-group { - margin-left: -1px; -} -.nav { - padding-left: 0; - margin-bottom: 0; - list-style: none; -} -.nav > li { - position: relative; - display: block; -} -.nav > li > a { - position: relative; - display: block; - padding: 10px 15px; -} -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eee; -} -.nav > li.disabled > a { - color: #777; -} -.nav > li.disabled > a:hover, -.nav > li.disabled > a:focus { - color: #777; - text-decoration: none; - cursor: not-allowed; - background-color: transparent; -} -.nav .open > a, -.nav .open > a:hover, -.nav .open > a:focus { - background-color: #eee; - border-color: #428bca; -} -.nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.nav > li > a > img { - max-width: none; -} -.nav-tabs { - border-bottom: 1px solid #ddd; -} -.nav-tabs > li { - float: left; - margin-bottom: -1px; -} -.nav-tabs > li > a { - margin-right: 2px; - line-height: 1.42857143; - border: 1px solid transparent; - border-radius: 4px 4px 0 0; -} -.nav-tabs > li > a:hover { - border-color: #eee #eee #ddd; -} -.nav-tabs > li.active > a, -.nav-tabs > li.active > a:hover, -.nav-tabs > li.active > a:focus { - color: #555; - cursor: default; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} -.nav-tabs.nav-justified { - width: 100%; - border-bottom: 0; -} -.nav-tabs.nav-justified > li { - float: none; -} -.nav-tabs.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} -.nav-tabs.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} -@media (min-width: 768px) { - .nav-tabs.nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-tabs.nav-justified > li > a { - margin-bottom: 0; - } -} -.nav-tabs.nav-justified > li > a { - margin-right: 0; - border-radius: 4px; -} -.nav-tabs.nav-justified > .active > a, -.nav-tabs.nav-justified > .active > a:hover, -.nav-tabs.nav-justified > .active > a:focus { - border: 1px solid #ddd; -} -@media (min-width: 768px) { - .nav-tabs.nav-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs.nav-justified > .active > a, - .nav-tabs.nav-justified > .active > a:hover, - .nav-tabs.nav-justified > .active > a:focus { - border-bottom-color: #fff; - } -} -.nav-pills > li { - float: left; -} -.nav-pills > li > a { - border-radius: 4px; -} -.nav-pills > li + li { - margin-left: 2px; -} -.nav-pills > li.active > a, -.nav-pills > li.active > a:hover, -.nav-pills > li.active > a:focus { - color: #fff; - background-color: #428bca; -} -.nav-stacked > li { - float: none; -} -.nav-stacked > li + li { - margin-top: 2px; - margin-left: 0; -} -.nav-justified { - width: 100%; -} -.nav-justified > li { - float: none; -} -.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} -.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} -@media (min-width: 768px) { - .nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-justified > li > a { - margin-bottom: 0; - } -} -.nav-tabs-justified { - border-bottom: 0; -} -.nav-tabs-justified > li > a { - margin-right: 0; - border-radius: 4px; -} -.nav-tabs-justified > .active > a, -.nav-tabs-justified > .active > a:hover, -.nav-tabs-justified > .active > a:focus { - border: 1px solid #ddd; -} -@media (min-width: 768px) { - .nav-tabs-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs-justified > .active > a, - .nav-tabs-justified > .active > a:hover, - .nav-tabs-justified > .active > a:focus { - border-bottom-color: #fff; - } -} -.tab-content > .tab-pane { - display: none; -} -.tab-content > .active { - display: block; -} -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.navbar { - position: relative; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent; -} -@media (min-width: 768px) { - .navbar { - border-radius: 4px; - } -} -@media (min-width: 768px) { - .navbar-header { - float: left; - } -} -.navbar-collapse { - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - -webkit-overflow-scrolling: touch; - border-top: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); -} -.navbar-collapse.in { - overflow-y: auto; -} -@media (min-width: 768px) { - .navbar-collapse { - width: auto; - border-top: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important; - } - .navbar-collapse.in { - overflow-y: visible; - } - .navbar-fixed-top .navbar-collapse, - .navbar-static-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - padding-right: 0; - padding-left: 0; - } -} -.navbar-fixed-top .navbar-collapse, -.navbar-fixed-bottom .navbar-collapse { - max-height: 340px; -} -@media (max-width: 480px) and (orientation: landscape) { - .navbar-fixed-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - max-height: 200px; - } -} -.container > .navbar-header, -.container-fluid > .navbar-header, -.container > .navbar-collapse, -.container-fluid > .navbar-collapse { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .container > .navbar-header, - .container-fluid > .navbar-header, - .container > .navbar-collapse, - .container-fluid > .navbar-collapse { - margin-right: 0; - margin-left: 0; - } -} -.navbar-static-top { - z-index: 1000; - border-width: 0 0 1px; -} -@media (min-width: 768px) { - .navbar-static-top { - border-radius: 0; - } -} -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; - -webkit-transform: translate3d(0, 0, 0); - -o-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); -} -@media (min-width: 768px) { - .navbar-fixed-top, - .navbar-fixed-bottom { - border-radius: 0; - } -} -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px; -} -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; - border-width: 1px 0 0; -} -.navbar-brand { - float: left; - height: 50px; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; -} -.navbar-brand:hover, -.navbar-brand:focus { - text-decoration: none; -} -@media (min-width: 768px) { - .navbar > .container .navbar-brand, - .navbar > .container-fluid .navbar-brand { - margin-left: -15px; - } -} -.navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 8px; - margin-right: 15px; - margin-bottom: 8px; - background-color: transparent; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} -.navbar-toggle:focus { - outline: 0; -} -.navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px; -} -.navbar-toggle .icon-bar + .icon-bar { - margin-top: 4px; -} -@media (min-width: 768px) { - .navbar-toggle { - display: none; - } -} -.navbar-nav { - margin: 7.5px -15px; -} -.navbar-nav > li > a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px; -} -@media (max-width: 767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-nav .open .dropdown-menu > li > a, - .navbar-nav .open .dropdown-menu .dropdown-header { - padding: 5px 15px 5px 25px; - } - .navbar-nav .open .dropdown-menu > li > a { - line-height: 20px; - } - .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-nav .open .dropdown-menu > li > a:focus { - background-image: none; - } -} -@media (min-width: 768px) { - .navbar-nav { - float: left; - margin: 0; - } - .navbar-nav > li { - float: left; - } - .navbar-nav > li > a { - padding-top: 15px; - padding-bottom: 15px; - } - .navbar-nav.navbar-right:last-child { - margin-right: -15px; - } -} -@media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - } -} -.navbar-form { - padding: 10px 15px; - margin-top: 8px; - margin-right: -15px; - margin-bottom: 8px; - margin-left: -15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); -} -@media (min-width: 768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .navbar-form .input-group { - display: inline-table; - vertical-align: middle; - } - .navbar-form .input-group .input-group-addon, - .navbar-form .input-group .input-group-btn, - .navbar-form .input-group .form-control { - width: auto; - } - .navbar-form .input-group > .form-control { - width: 100%; - } - .navbar-form .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio, - .navbar-form .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio label, - .navbar-form .checkbox label { - padding-left: 0; - } - .navbar-form .radio input[type="radio"], - .navbar-form .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .navbar-form .has-feedback .form-control-feedback { - top: 0; - } -} -@media (max-width: 767px) { - .navbar-form .form-group { - margin-bottom: 5px; - } -} -@media (min-width: 768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-form.navbar-right:last-child { - margin-right: -15px; - } -} -.navbar-nav > li > .dropdown-menu { - margin-top: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.navbar-btn { - margin-top: 8px; - margin-bottom: 8px; -} -.navbar-btn.btn-sm { - margin-top: 10px; - margin-bottom: 10px; -} -.navbar-btn.btn-xs { - margin-top: 14px; - margin-bottom: 14px; -} -.navbar-text { - margin-top: 15px; - margin-bottom: 15px; -} -@media (min-width: 768px) { - .navbar-text { - float: left; - margin-right: 15px; - margin-left: 15px; - } - .navbar-text.navbar-right:last-child { - margin-right: 0; - } -} -.navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7; -} -.navbar-default .navbar-brand { - color: #777; -} -.navbar-default .navbar-brand:hover, -.navbar-default .navbar-brand:focus { - color: #5e5e5e; - background-color: transparent; -} -.navbar-default .navbar-text { - color: #777; -} -.navbar-default .navbar-nav > li > a { - color: #777; -} -.navbar-default .navbar-nav > li > a:hover, -.navbar-default .navbar-nav > li > a:focus { - color: #333; - background-color: transparent; -} -.navbar-default .navbar-nav > .active > a, -.navbar-default .navbar-nav > .active > a:hover, -.navbar-default .navbar-nav > .active > a:focus { - color: #555; - background-color: #e7e7e7; -} -.navbar-default .navbar-nav > .disabled > a, -.navbar-default .navbar-nav > .disabled > a:hover, -.navbar-default .navbar-nav > .disabled > a:focus { - color: #ccc; - background-color: transparent; -} -.navbar-default .navbar-toggle { - border-color: #ddd; -} -.navbar-default .navbar-toggle:hover, -.navbar-default .navbar-toggle:focus { - background-color: #ddd; -} -.navbar-default .navbar-toggle .icon-bar { - background-color: #888; -} -.navbar-default .navbar-collapse, -.navbar-default .navbar-form { - border-color: #e7e7e7; -} -.navbar-default .navbar-nav > .open > a, -.navbar-default .navbar-nav > .open > a:hover, -.navbar-default .navbar-nav > .open > a:focus { - color: #555; - background-color: #e7e7e7; -} -@media (max-width: 767px) { - .navbar-default .navbar-nav .open .dropdown-menu > li > a { - color: #777; - } - .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { - color: #333; - background-color: transparent; - } - .navbar-default .navbar-nav .open .dropdown-menu > .active > a, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #555; - background-color: #e7e7e7; - } - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #ccc; - background-color: transparent; - } -} -.navbar-default .navbar-link { - color: #777; -} -.navbar-default .navbar-link:hover { - color: #333; -} -.navbar-default .btn-link { - color: #777; -} -.navbar-default .btn-link:hover, -.navbar-default .btn-link:focus { - color: #333; -} -.navbar-default .btn-link[disabled]:hover, -fieldset[disabled] .navbar-default .btn-link:hover, -.navbar-default .btn-link[disabled]:focus, -fieldset[disabled] .navbar-default .btn-link:focus { - color: #ccc; -} -.navbar-inverse { - background-color: #222; - border-color: #080808; -} -.navbar-inverse .navbar-brand { - color: #777; -} -.navbar-inverse .navbar-brand:hover, -.navbar-inverse .navbar-brand:focus { - color: #fff; - background-color: transparent; -} -.navbar-inverse .navbar-text { - color: #777; -} -.navbar-inverse .navbar-nav > li > a { - color: #777; -} -.navbar-inverse .navbar-nav > li > a:hover, -.navbar-inverse .navbar-nav > li > a:focus { - color: #fff; - background-color: transparent; -} -.navbar-inverse .navbar-nav > .active > a, -.navbar-inverse .navbar-nav > .active > a:hover, -.navbar-inverse .navbar-nav > .active > a:focus { - color: #fff; - background-color: #080808; -} -.navbar-inverse .navbar-nav > .disabled > a, -.navbar-inverse .navbar-nav > .disabled > a:hover, -.navbar-inverse .navbar-nav > .disabled > a:focus { - color: #444; - background-color: transparent; -} -.navbar-inverse .navbar-toggle { - border-color: #333; -} -.navbar-inverse .navbar-toggle:hover, -.navbar-inverse .navbar-toggle:focus { - background-color: #333; -} -.navbar-inverse .navbar-toggle .icon-bar { - background-color: #fff; -} -.navbar-inverse .navbar-collapse, -.navbar-inverse .navbar-form { - border-color: #101010; -} -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .open > a:hover, -.navbar-inverse .navbar-nav > .open > a:focus { - color: #fff; - background-color: #080808; -} -@media (max-width: 767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { - border-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu .divider { - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { - color: #777; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { - color: #fff; - background-color: transparent; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #fff; - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #444; - background-color: transparent; - } -} -.navbar-inverse .navbar-link { - color: #777; -} -.navbar-inverse .navbar-link:hover { - color: #fff; -} -.navbar-inverse .btn-link { - color: #777; -} -.navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link:focus { - color: #fff; -} -.navbar-inverse .btn-link[disabled]:hover, -fieldset[disabled] .navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link[disabled]:focus, -fieldset[disabled] .navbar-inverse .btn-link:focus { - color: #444; -} -.breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px; -} -.breadcrumb > li { - display: inline-block; -} -.breadcrumb > li + li:before { - padding: 0 5px; - color: #ccc; - content: "/\00a0"; -} -.breadcrumb > .active { - color: #777; -} -.pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px; -} -.pagination > li { - display: inline; -} -.pagination > li > a, -.pagination > li > span { - position: relative; - float: left; - padding: 6px 12px; - margin-left: -1px; - line-height: 1.42857143; - color: #428bca; - text-decoration: none; - background-color: #fff; - border: 1px solid #ddd; -} -.pagination > li:first-child > a, -.pagination > li:first-child > span { - margin-left: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; -} -.pagination > li:last-child > a, -.pagination > li:last-child > span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} -.pagination > li > a:hover, -.pagination > li > span:hover, -.pagination > li > a:focus, -.pagination > li > span:focus { - color: #2a6496; - background-color: #eee; - border-color: #ddd; -} -.pagination > .active > a, -.pagination > .active > span, -.pagination > .active > a:hover, -.pagination > .active > span:hover, -.pagination > .active > a:focus, -.pagination > .active > span:focus { - z-index: 2; - color: #fff; - cursor: default; - background-color: #428bca; - border-color: #428bca; -} -.pagination > .disabled > span, -.pagination > .disabled > span:hover, -.pagination > .disabled > span:focus, -.pagination > .disabled > a, -.pagination > .disabled > a:hover, -.pagination > .disabled > a:focus { - color: #777; - cursor: not-allowed; - background-color: #fff; - border-color: #ddd; -} -.pagination-lg > li > a, -.pagination-lg > li > span { - padding: 10px 16px; - font-size: 18px; -} -.pagination-lg > li:first-child > a, -.pagination-lg > li:first-child > span { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px; -} -.pagination-lg > li:last-child > a, -.pagination-lg > li:last-child > span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px; -} -.pagination-sm > li > a, -.pagination-sm > li > span { - padding: 5px 10px; - font-size: 12px; -} -.pagination-sm > li:first-child > a, -.pagination-sm > li:first-child > span { - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; -} -.pagination-sm > li:last-child > a, -.pagination-sm > li:last-child > span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} -.pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none; -} -.pager li { - display: inline; -} -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 15px; -} -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #eee; -} -.pager .next > a, -.pager .next > span { - float: right; -} -.pager .previous > a, -.pager .previous > span { - float: left; -} -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #777; - cursor: not-allowed; - background-color: #fff; -} -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; -} -a.label:hover, -a.label:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -.label:empty { - display: none; -} -.btn .label { - position: relative; - top: -1px; -} -.label-default { - background-color: #777; -} -.label-default[href]:hover, -.label-default[href]:focus { - background-color: #5e5e5e; -} -.label-primary { - background-color: #428bca; -} -.label-primary[href]:hover, -.label-primary[href]:focus { - background-color: #3071a9; -} -.label-success { - background-color: #5cb85c; -} -.label-success[href]:hover, -.label-success[href]:focus { - background-color: #449d44; -} -.label-info { - background-color: #5bc0de; -} -.label-info[href]:hover, -.label-info[href]:focus { - background-color: #31b0d5; -} -.label-warning { - background-color: #f0ad4e; -} -.label-warning[href]:hover, -.label-warning[href]:focus { - background-color: #ec971f; -} -.label-danger { - background-color: #d9534f; -} -.label-danger[href]:hover, -.label-danger[href]:focus { - background-color: #c9302c; -} -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - background-color: #777; - border-radius: 10px; -} -.badge:empty { - display: none; -} -.btn .badge { - position: relative; - top: -1px; -} -.btn-xs .badge { - top: 0; - padding: 1px 5px; -} -a.badge:hover, -a.badge:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -a.list-group-item.active > .badge, -.nav-pills > .active > a > .badge { - color: #428bca; - background-color: #fff; -} -.nav-pills > li > a > .badge { - margin-left: 3px; -} -.jumbotron { - padding: 30px; - margin-bottom: 30px; - color: inherit; - background-color: #eee; -} -.jumbotron h1, -.jumbotron .h1 { - color: inherit; -} -.jumbotron p { - margin-bottom: 15px; - font-size: 21px; - font-weight: 200; -} -.jumbotron > hr { - border-top-color: #d5d5d5; -} -.container .jumbotron { - border-radius: 6px; -} -.jumbotron .container { - max-width: 100%; -} -@media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron { - padding-right: 60px; - padding-left: 60px; - } - .jumbotron h1, - .jumbotron .h1 { - font-size: 63px; - } -} -.thumbnail { - display: block; - padding: 4px; - margin-bottom: 20px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - -o-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; -} -.thumbnail > img, -.thumbnail a > img { - margin-right: auto; - margin-left: auto; -} -a.thumbnail:hover, -a.thumbnail:focus, -a.thumbnail.active { - border-color: #428bca; -} -.thumbnail .caption { - padding: 9px; - color: #333; -} -.alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px; -} -.alert h4 { - margin-top: 0; - color: inherit; -} -.alert .alert-link { - font-weight: bold; -} -.alert > p, -.alert > ul { - margin-bottom: 0; -} -.alert > p + p { - margin-top: 5px; -} -.alert-dismissable, -.alert-dismissible { - padding-right: 35px; -} -.alert-dismissable .close, -.alert-dismissible .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; -} -.alert-success { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.alert-success hr { - border-top-color: #c9e2b3; -} -.alert-success .alert-link { - color: #2b542c; -} -.alert-info { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} -.alert-info hr { - border-top-color: #a6e1ec; -} -.alert-info .alert-link { - color: #245269; -} -.alert-warning { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} -.alert-warning hr { - border-top-color: #f7e1b5; -} -.alert-warning .alert-link { - color: #66512c; -} -.alert-danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} -.alert-danger hr { - border-top-color: #e4b9c0; -} -.alert-danger .alert-link { - color: #843534; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f5f5f5; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); -} -.progress-bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - line-height: 20px; - color: #fff; - text-align: center; - background-color: #428bca; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - -webkit-transition: width .6s ease; - -o-transition: width .6s ease; - transition: width .6s ease; -} -.progress-striped .progress-bar, -.progress-bar-striped { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - background-size: 40px 40px; -} -.progress.active .progress-bar, -.progress-bar.active { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} -.progress-bar[aria-valuenow="1"], -.progress-bar[aria-valuenow="2"] { - min-width: 30px; -} -.progress-bar[aria-valuenow="0"] { - min-width: 30px; - color: #777; - background-color: transparent; - background-image: none; - -webkit-box-shadow: none; - box-shadow: none; -} -.progress-bar-success { - background-color: #5cb85c; -} -.progress-striped .progress-bar-success { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-info { - background-color: #5bc0de; -} -.progress-striped .progress-bar-info { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-warning { - background-color: #f0ad4e; -} -.progress-striped .progress-bar-warning { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-danger { - background-color: #d9534f; -} -.progress-striped .progress-bar-danger { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.media, -.media-body { - overflow: hidden; - zoom: 1; -} -.media, -.media .media { - margin-top: 15px; -} -.media:first-child { - margin-top: 0; -} -.media-object { - display: block; -} -.media-heading { - margin: 0 0 5px; -} -.media > .pull-left { - margin-right: 10px; -} -.media > .pull-right { - margin-left: 10px; -} -.media-list { - padding-left: 0; - list-style: none; -} -.list-group { - padding-left: 0; - margin-bottom: 20px; -} -.list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #fff; - border: 1px solid #ddd; -} -.list-group-item:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px; -} -.list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -.list-group-item > .badge { - float: right; -} -.list-group-item > .badge + .badge { - margin-right: 5px; -} -a.list-group-item { - color: #555; -} -a.list-group-item .list-group-item-heading { - color: #333; -} -a.list-group-item:hover, -a.list-group-item:focus { - color: #555; - text-decoration: none; - background-color: #f5f5f5; -} -.list-group-item.disabled, -.list-group-item.disabled:hover, -.list-group-item.disabled:focus { - color: #777; - background-color: #eee; -} -.list-group-item.disabled .list-group-item-heading, -.list-group-item.disabled:hover .list-group-item-heading, -.list-group-item.disabled:focus .list-group-item-heading { - color: inherit; -} -.list-group-item.disabled .list-group-item-text, -.list-group-item.disabled:hover .list-group-item-text, -.list-group-item.disabled:focus .list-group-item-text { - color: #777; -} -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - z-index: 2; - color: #fff; - background-color: #428bca; - border-color: #428bca; -} -.list-group-item.active .list-group-item-heading, -.list-group-item.active:hover .list-group-item-heading, -.list-group-item.active:focus .list-group-item-heading, -.list-group-item.active .list-group-item-heading > small, -.list-group-item.active:hover .list-group-item-heading > small, -.list-group-item.active:focus .list-group-item-heading > small, -.list-group-item.active .list-group-item-heading > .small, -.list-group-item.active:hover .list-group-item-heading > .small, -.list-group-item.active:focus .list-group-item-heading > .small { - color: inherit; -} -.list-group-item.active .list-group-item-text, -.list-group-item.active:hover .list-group-item-text, -.list-group-item.active:focus .list-group-item-text { - color: #e1edf7; -} -.list-group-item-success { - color: #3c763d; - background-color: #dff0d8; -} -a.list-group-item-success { - color: #3c763d; -} -a.list-group-item-success .list-group-item-heading { - color: inherit; -} -a.list-group-item-success:hover, -a.list-group-item-success:focus { - color: #3c763d; - background-color: #d0e9c6; -} -a.list-group-item-success.active, -a.list-group-item-success.active:hover, -a.list-group-item-success.active:focus { - color: #fff; - background-color: #3c763d; - border-color: #3c763d; -} -.list-group-item-info { - color: #31708f; - background-color: #d9edf7; -} -a.list-group-item-info { - color: #31708f; -} -a.list-group-item-info .list-group-item-heading { - color: inherit; -} -a.list-group-item-info:hover, -a.list-group-item-info:focus { - color: #31708f; - background-color: #c4e3f3; -} -a.list-group-item-info.active, -a.list-group-item-info.active:hover, -a.list-group-item-info.active:focus { - color: #fff; - background-color: #31708f; - border-color: #31708f; -} -.list-group-item-warning { - color: #8a6d3b; - background-color: #fcf8e3; -} -a.list-group-item-warning { - color: #8a6d3b; -} -a.list-group-item-warning .list-group-item-heading { - color: inherit; -} -a.list-group-item-warning:hover, -a.list-group-item-warning:focus { - color: #8a6d3b; - background-color: #faf2cc; -} -a.list-group-item-warning.active, -a.list-group-item-warning.active:hover, -a.list-group-item-warning.active:focus { - color: #fff; - background-color: #8a6d3b; - border-color: #8a6d3b; -} -.list-group-item-danger { - color: #a94442; - background-color: #f2dede; -} -a.list-group-item-danger { - color: #a94442; -} -a.list-group-item-danger .list-group-item-heading { - color: inherit; -} -a.list-group-item-danger:hover, -a.list-group-item-danger:focus { - color: #a94442; - background-color: #ebcccc; -} -a.list-group-item-danger.active, -a.list-group-item-danger.active:hover, -a.list-group-item-danger.active:focus { - color: #fff; - background-color: #a94442; - border-color: #a94442; -} -.list-group-item-heading { - margin-top: 0; - margin-bottom: 5px; -} -.list-group-item-text { - margin-bottom: 0; - line-height: 1.3; -} -.panel { - margin-bottom: 20px; - background-color: #fff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: 0 1px 1px rgba(0, 0, 0, .05); -} -.panel-body { - padding: 15px; -} -.panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel-heading > .dropdown .dropdown-toggle { - color: inherit; -} -.panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; - color: inherit; -} -.panel-title > a { - color: inherit; -} -.panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .list-group { - margin-bottom: 0; -} -.panel > .list-group .list-group-item { - border-width: 1px 0; - border-radius: 0; -} -.panel > .list-group:first-child .list-group-item:first-child { - border-top: 0; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .list-group:last-child .list-group-item:last-child { - border-bottom: 0; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel-heading + .list-group .list-group-item:first-child { - border-top-width: 0; -} -.list-group + .panel-footer { - border-top-width: 0; -} -.panel > .table, -.panel > .table-responsive > .table, -.panel > .panel-collapse > .table { - margin-bottom: 0; -} -.panel > .table:first-child, -.panel > .table-responsive:first-child > .table:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, -.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { - border-top-left-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, -.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, -.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, -.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { - border-top-right-radius: 3px; -} -.panel > .table:last-child, -.panel > .table-responsive:last-child > .table:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, -.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, -.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { - border-bottom-right-radius: 3px; -} -.panel > .panel-body + .table, -.panel > .panel-body + .table-responsive { - border-top: 1px solid #ddd; -} -.panel > .table > tbody:first-child > tr:first-child th, -.panel > .table > tbody:first-child > tr:first-child td { - border-top: 0; -} -.panel > .table-bordered, -.panel > .table-responsive > .table-bordered { - border: 0; -} -.panel > .table-bordered > thead > tr > th:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, -.panel > .table-bordered > tbody > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, -.panel > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-bordered > thead > tr > td:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, -.panel > .table-bordered > tbody > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, -.panel > .table-bordered > tfoot > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; -} -.panel > .table-bordered > thead > tr > th:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, -.panel > .table-bordered > tbody > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, -.panel > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-bordered > thead > tr > td:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, -.panel > .table-bordered > tbody > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, -.panel > .table-bordered > tfoot > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; -} -.panel > .table-bordered > thead > tr:first-child > td, -.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, -.panel > .table-bordered > tbody > tr:first-child > td, -.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, -.panel > .table-bordered > thead > tr:first-child > th, -.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, -.panel > .table-bordered > tbody > tr:first-child > th, -.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { - border-bottom: 0; -} -.panel > .table-bordered > tbody > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, -.panel > .table-bordered > tfoot > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, -.panel > .table-bordered > tbody > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, -.panel > .table-bordered > tfoot > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { - border-bottom: 0; -} -.panel > .table-responsive { - margin-bottom: 0; - border: 0; -} -.panel-group { - margin-bottom: 20px; -} -.panel-group .panel { - margin-bottom: 0; - border-radius: 4px; -} -.panel-group .panel + .panel { - margin-top: 5px; -} -.panel-group .panel-heading { - border-bottom: 0; -} -.panel-group .panel-heading + .panel-collapse > .panel-body { - border-top: 1px solid #ddd; -} -.panel-group .panel-footer { - border-top: 0; -} -.panel-group .panel-footer + .panel-collapse .panel-body { - border-bottom: 1px solid #ddd; -} -.panel-default { - border-color: #ddd; -} -.panel-default > .panel-heading { - color: #333; - background-color: #f5f5f5; - border-color: #ddd; -} -.panel-default > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #ddd; -} -.panel-default > .panel-heading .badge { - color: #f5f5f5; - background-color: #333; -} -.panel-default > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ddd; -} -.panel-primary { - border-color: #428bca; -} -.panel-primary > .panel-heading { - color: #fff; - background-color: #428bca; - border-color: #428bca; -} -.panel-primary > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #428bca; -} -.panel-primary > .panel-heading .badge { - color: #428bca; - background-color: #fff; -} -.panel-primary > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #428bca; -} -.panel-success { - border-color: #d6e9c6; -} -.panel-success > .panel-heading { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.panel-success > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #d6e9c6; -} -.panel-success > .panel-heading .badge { - color: #dff0d8; - background-color: #3c763d; -} -.panel-success > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #d6e9c6; -} -.panel-info { - border-color: #bce8f1; -} -.panel-info > .panel-heading { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} -.panel-info > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #bce8f1; -} -.panel-info > .panel-heading .badge { - color: #d9edf7; - background-color: #31708f; -} -.panel-info > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #bce8f1; -} -.panel-warning { - border-color: #faebcc; -} -.panel-warning > .panel-heading { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} -.panel-warning > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #faebcc; -} -.panel-warning > .panel-heading .badge { - color: #fcf8e3; - background-color: #8a6d3b; -} -.panel-warning > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #faebcc; -} -.panel-danger { - border-color: #ebccd1; -} -.panel-danger > .panel-heading { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} -.panel-danger > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #ebccd1; -} -.panel-danger > .panel-heading .badge { - color: #f2dede; - background-color: #a94442; -} -.panel-danger > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ebccd1; -} -.embed-responsive { - position: relative; - display: block; - height: 0; - padding: 0; - overflow: hidden; -} -.embed-responsive .embed-responsive-item, -.embed-responsive iframe, -.embed-responsive embed, -.embed-responsive object { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 100%; - height: 100%; - border: 0; -} -.embed-responsive.embed-responsive-16by9 { - padding-bottom: 56.25%; -} -.embed-responsive.embed-responsive-4by3 { - padding-bottom: 75%; -} -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); -} -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, .15); -} -.well-lg { - padding: 24px; - border-radius: 6px; -} -.well-sm { - padding: 9px; - border-radius: 3px; -} -.close { - float: right; - font-size: 21px; - font-weight: bold; - line-height: 1; - color: #000; - text-shadow: 0 1px 0 #fff; - filter: alpha(opacity=20); - opacity: .2; -} -.close:hover, -.close:focus { - color: #000; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity=50); - opacity: .5; -} -button.close { - -webkit-appearance: none; - padding: 0; - cursor: pointer; - background: transparent; - border: 0; -} -.modal-open { - overflow: hidden; -} -.modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1050; - display: none; - overflow: hidden; - -webkit-overflow-scrolling: touch; - outline: 0; -} -.modal.fade .modal-dialog { - -webkit-transition: -webkit-transform .3s ease-out; - -o-transition: -o-transform .3s ease-out; - transition: transform .3s ease-out; - -webkit-transform: translate3d(0, -25%, 0); - -o-transform: translate3d(0, -25%, 0); - transform: translate3d(0, -25%, 0); -} -.modal.in .modal-dialog { - -webkit-transform: translate3d(0, 0, 0); - -o-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); -} -.modal-open .modal { - overflow-x: hidden; - overflow-y: auto; -} -.modal-dialog { - position: relative; - width: auto; - margin: 10px; -} -.modal-content { - position: relative; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - outline: 0; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); - box-shadow: 0 3px 9px rgba(0, 0, 0, .5); -} -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000; -} -.modal-backdrop.fade { - filter: alpha(opacity=0); - opacity: 0; -} -.modal-backdrop.in { - filter: alpha(opacity=50); - opacity: .5; -} -.modal-header { - min-height: 16.42857143px; - padding: 15px; - border-bottom: 1px solid #e5e5e5; -} -.modal-header .close { - margin-top: -2px; -} -.modal-title { - margin: 0; - line-height: 1.42857143; -} -.modal-body { - position: relative; - padding: 15px; -} -.modal-footer { - padding: 15px; - text-align: right; - border-top: 1px solid #e5e5e5; -} -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} -.modal-scrollbar-measure { - position: absolute; - top: -9999px; - width: 50px; - height: 50px; - overflow: scroll; -} -@media (min-width: 768px) { - .modal-dialog { - width: 600px; - margin: 30px auto; - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - } - .modal-sm { - width: 300px; - } -} -@media (min-width: 992px) { - .modal-lg { - width: 900px; - } -} -.tooltip { - position: absolute; - z-index: 1070; - display: block; - font-size: 12px; - line-height: 1.4; - visibility: visible; - filter: alpha(opacity=0); - opacity: 0; -} -.tooltip.in { - filter: alpha(opacity=90); - opacity: .9; -} -.tooltip.top { - padding: 5px 0; - margin-top: -3px; -} -.tooltip.right { - padding: 0 5px; - margin-left: 3px; -} -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px; -} -.tooltip.left { - padding: 0 5px; - margin-left: -3px; -} -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - text-decoration: none; - background-color: #000; - border-radius: 4px; -} -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.top-left .tooltip-arrow { - bottom: 0; - left: 5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.top-right .tooltip-arrow { - right: 5px; - bottom: 0; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000; -} -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000; -} -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip.bottom-left .tooltip-arrow { - top: 0; - left: 5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip.bottom-right .tooltip-arrow { - top: 0; - right: 5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1060; - display: none; - max-width: 276px; - padding: 1px; - text-align: left; - white-space: normal; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - box-shadow: 0 5px 10px rgba(0, 0, 0, .2); -} -.popover.top { - margin-top: -10px; -} -.popover.right { - margin-left: 10px; -} -.popover.bottom { - margin-top: 10px; -} -.popover.left { - margin-left: -10px; -} -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - font-weight: normal; - line-height: 18px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0; -} -.popover-content { - padding: 9px 14px; -} -.popover > .arrow, -.popover > .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.popover > .arrow { - border-width: 11px; -} -.popover > .arrow:after { - content: ""; - border-width: 10px; -} -.popover.top > .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, .25); - border-bottom-width: 0; -} -.popover.top > .arrow:after { - bottom: 1px; - margin-left: -10px; - content: " "; - border-top-color: #fff; - border-bottom-width: 0; -} -.popover.right > .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, .25); - border-left-width: 0; -} -.popover.right > .arrow:after { - bottom: -10px; - left: 1px; - content: " "; - border-right-color: #fff; - border-left-width: 0; -} -.popover.bottom > .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, .25); -} -.popover.bottom > .arrow:after { - top: 1px; - margin-left: -10px; - content: " "; - border-top-width: 0; - border-bottom-color: #fff; -} -.popover.left > .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-right-width: 0; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, .25); -} -.popover.left > .arrow:after { - right: 1px; - bottom: -10px; - content: " "; - border-right-width: 0; - border-left-color: #fff; -} -.carousel { - position: relative; -} -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: .6s ease-in-out left; - -o-transition: .6s ease-in-out left; - transition: .6s ease-in-out left; -} -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - line-height: 1; -} -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} -.carousel-inner > .active { - left: 0; -} -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} -.carousel-inner > .next { - left: 100%; -} -.carousel-inner > .prev { - left: -100%; -} -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} -.carousel-inner > .active.left { - left: -100%; -} -.carousel-inner > .active.right { - left: 100%; -} -.carousel-control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); - filter: alpha(opacity=50); - opacity: .5; -} -.carousel-control.left { - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control:hover, -.carousel-control:focus { - color: #fff; - text-decoration: none; - filter: alpha(opacity=90); - outline: 0; - opacity: .9; -} -.carousel-control .icon-prev, -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-left, -.carousel-control .glyphicon-chevron-right { - position: absolute; - top: 50%; - z-index: 5; - display: inline-block; -} -.carousel-control .icon-prev, -.carousel-control .glyphicon-chevron-left { - left: 50%; - margin-left: -10px; -} -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-right { - right: 50%; - margin-right: -10px; -} -.carousel-control .icon-prev, -.carousel-control .icon-next { - width: 20px; - height: 20px; - margin-top: -10px; - font-family: serif; -} -.carousel-control .icon-prev:before { - content: '\2039'; -} -.carousel-control .icon-next:before { - content: '\203a'; -} -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none; -} -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - background-color: #000 \9; - background-color: rgba(0, 0, 0, 0); - border: 1px solid #fff; - border-radius: 10px; -} -.carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #fff; -} -.carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); -} -.carousel-caption .btn { - text-shadow: none; -} -@media screen and (min-width: 768px) { - .carousel-control .glyphicon-chevron-left, - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-prev, - .carousel-control .icon-next { - width: 30px; - height: 30px; - margin-top: -15px; - font-size: 30px; - } - .carousel-control .glyphicon-chevron-left, - .carousel-control .icon-prev { - margin-left: -15px; - } - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-next { - margin-right: -15px; - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px; - } - .carousel-indicators { - bottom: 20px; - } -} -.clearfix:before, -.clearfix:after, -.dl-horizontal dd:before, -.dl-horizontal dd:after, -.container:before, -.container:after, -.container-fluid:before, -.container-fluid:after, -.row:before, -.row:after, -.form-horizontal .form-group:before, -.form-horizontal .form-group:after, -.btn-toolbar:before, -.btn-toolbar:after, -.btn-group-vertical > .btn-group:before, -.btn-group-vertical > .btn-group:after, -.nav:before, -.nav:after, -.navbar:before, -.navbar:after, -.navbar-header:before, -.navbar-header:after, -.navbar-collapse:before, -.navbar-collapse:after, -.pager:before, -.pager:after, -.panel-body:before, -.panel-body:after, -.modal-footer:before, -.modal-footer:after { - display: table; - content: " "; -} -.clearfix:after, -.dl-horizontal dd:after, -.container:after, -.container-fluid:after, -.row:after, -.form-horizontal .form-group:after, -.btn-toolbar:after, -.btn-group-vertical > .btn-group:after, -.nav:after, -.navbar:after, -.navbar-header:after, -.navbar-collapse:after, -.pager:after, -.panel-body:after, -.modal-footer:after { - clear: both; -} -.center-block { - display: block; - margin-right: auto; - margin-left: auto; -} -.pull-right { - float: right !important; -} -.pull-left { - float: left !important; -} -.hide { - display: none !important; -} -.show { - display: block !important; -} -.invisible { - visibility: hidden; -} -.text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} -.hidden { - display: none !important; - visibility: hidden !important; -} -.affix { - position: fixed; - -webkit-transform: translate3d(0, 0, 0); - -o-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); -} -@-ms-viewport { - width: device-width; -} -.visible-xs, -.visible-sm, -.visible-md, -.visible-lg { - display: none !important; -} -.visible-xs-block, -.visible-xs-inline, -.visible-xs-inline-block, -.visible-sm-block, -.visible-sm-inline, -.visible-sm-inline-block, -.visible-md-block, -.visible-md-inline, -.visible-md-inline-block, -.visible-lg-block, -.visible-lg-inline, -.visible-lg-inline-block { - display: none !important; -} -@media (max-width: 767px) { - .visible-xs { - display: block !important; - } - table.visible-xs { - display: table; - } - tr.visible-xs { - display: table-row !important; - } - th.visible-xs, - td.visible-xs { - display: table-cell !important; - } -} -@media (max-width: 767px) { - .visible-xs-block { - display: block !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline { - display: inline !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline-block { - display: inline-block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm { - display: block !important; - } - table.visible-sm { - display: table; - } - tr.visible-sm { - display: table-row !important; - } - th.visible-sm, - td.visible-sm { - display: table-cell !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-block { - display: block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline { - display: inline !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline-block { - display: inline-block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md { - display: block !important; - } - table.visible-md { - display: table; - } - tr.visible-md { - display: table-row !important; - } - th.visible-md, - td.visible-md { - display: table-cell !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-block { - display: block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline { - display: inline !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline-block { - display: inline-block !important; - } -} -@media (min-width: 1200px) { - .visible-lg { - display: block !important; - } - table.visible-lg { - display: table; - } - tr.visible-lg { - display: table-row !important; - } - th.visible-lg, - td.visible-lg { - display: table-cell !important; - } -} -@media (min-width: 1200px) { - .visible-lg-block { - display: block !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline { - display: inline !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline-block { - display: inline-block !important; - } -} -@media (max-width: 767px) { - .hidden-xs { - display: none !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .hidden-sm { - display: none !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-md { - display: none !important; - } -} -@media (min-width: 1200px) { - .hidden-lg { - display: none !important; - } -} -.visible-print { - display: none !important; -} -@media print { - .visible-print { - display: block !important; - } - table.visible-print { - display: table; - } - tr.visible-print { - display: table-row !important; - } - th.visible-print, - td.visible-print { - display: table-cell !important; - } -} -.visible-print-block { - display: none !important; -} -@media print { - .visible-print-block { - display: block !important; - } -} -.visible-print-inline { - display: none !important; -} -@media print { - .visible-print-inline { - display: inline !important; - } -} -.visible-print-inline-block { - display: none !important; -} -@media print { - .visible-print-inline-block { - display: inline-block !important; - } -} -@media print { - .hidden-print { - display: none !important; - } -} -/*# sourceMappingURL=bootstrap.css.map */ diff --git a/junction/static/css/bootstrap.min.css b/junction/static/css/bootstrap.min.css deleted file mode 100644 index a9f35cee..00000000 --- a/junction/static/css/bootstrap.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Bootstrap v3.2.0 (http://getbootstrap.com) - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.1 | MIT License | git.io/normalize */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;width:100% \9;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;width:100% \9;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}mark,.mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#777;opacity:1}.form-control:-ms-input-placeholder{color:#777}.form-control::-webkit-input-placeholder{color:#777}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{line-height:34px;line-height:1.42857143 \0}input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;min-height:20px;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{position:absolute;margin-top:4px \9;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],input[type=radio].disabled,input[type=checkbox].disabled,fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm,.form-horizontal .form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg,.form-horizontal .form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:25px;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.3px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#3071a9;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px solid}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn>input[type=radio],[data-toggle=buttons]>.btn>input[type=checkbox]{position:absolute;z-index:-1;filter:alpha(opacity=0);opacity:0}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#777}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#777}.navbar-inverse .navbar-nav>li>a{color:#777}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#777}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#777}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#428bca;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar[aria-valuenow="1"],.progress-bar[aria-valuenow="2"]{min-width:30px}.progress-bar[aria-valuenow="0"]{min-width:30px;color:#777;background-color:transparent;background-image:none;-webkit-box-shadow:none;box-shadow:none}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{color:#555;text-decoration:none;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{color:#777;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#428bca}.panel-primary>.panel-heading .badge{color:#428bca;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate3d(0,-25%,0);-o-transform:translate3d(0,-25%,0);transform:translate3d(0,-25%,0)}.modal.in .modal-dialog{-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-size:12px;line-height:1.4;visibility:visible;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{display:table;content:" "}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed;-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none!important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} \ No newline at end of file diff --git a/junction/static/css/details.css b/junction/static/css/details.css deleted file mode 100644 index d6600093..00000000 --- a/junction/static/css/details.css +++ /dev/null @@ -1,73 +0,0 @@ -.proposal-details{ - padding:10px; - margin-top:10px; - border:1px solid #ccc; - border-radius:5px; -} -.proposal-details h1 { - margin:0px; - font-size:1.5em; - padding:6px; -} -.proposal-title{ - padding-bottom: 10px; -} -.icon-holder{ - width: 60px; - height: 54px; - border: 1px solid #3BABEA; - vertical-align: middle; - border-radius: 6px; -} -.icon-holder-inverse{ - background: transparent; - padding: 0px 8px 0px 8px; - color: #000; - height: 40px; -} -.icon-holder h4 { - margin:5px 0px 5px 0px; -} -.icon-holder > i { - margin-left:5px; -} -.icon-holder-bottom{ - background: #3BABEA; - height: 23px; - color:#ffffff; - cursor:pointer; -} -.icon-holder-bottom i { - padding:5px; -} -.porsal-title-section{ - padding:5px; - color:#ffffff; -} -.porsal-title-section .col-sm-12{ - padding-top:10px; - padding-bottom:10px; -} -.porsal-description h4{ - font-weight:600; -} -.proposal-update { - padding-top:15px; -} -.proposal-update a{ - font-size:1.5em; - color:#000; - padding-right:10px; -} -.proposal-comments{ - padding:5px 10px 5px 10px; - margin-left:-10px; - margin-right:-10px; - color:#ffffff; - background-color: #6F6F6F; -} -@media (max-width: 480px) { - .porsal-title-section .col-sm-12{ - height:100px; - } -} diff --git a/junction/static/css/fonts.css b/junction/static/css/fonts.css deleted file mode 100644 index 1d71e20b..00000000 --- a/junction/static/css/fonts.css +++ /dev/null @@ -1,47 +0,0 @@ -@font-face { - font-family: 'icomoon'; - src:url('../fonts/icomoon.eot?21i6q3'); - src:url('../fonts/icomoon.eot?#iefix21i6q3') format('embedded-opentype'), - url('../fonts/icomoon.woff?21i6q3') format('woff'), - url('../fonts/icomoon.ttf?21i6q3') format('truetype'), - url('../fonts/icomoon.svg?21i6q3#icomoon') format('svg'); - font-weight: normal; - font-style: normal; -} - -[class^="icon-"], [class*=" icon-"] { - font-family: 'icomoon'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.icon-user:before { - content: "\e600"; -} -.icon-checkmark-circle:before { - content: "\e606"; -} -.icon-checkmark:before { - content: "\e601"; -} -.icon-enter:before { - content: "\e603"; -} -.icon-exit:before { - content: "\e604"; -} -.icon-google:before { - content: "\e605"; -} -.icon-github:before { - content: "\e602"; -} - diff --git a/junction/static/css/form.css b/junction/static/css/form.css deleted file mode 100644 index ac1a0fef..00000000 --- a/junction/static/css/form.css +++ /dev/null @@ -1,54 +0,0 @@ - .form-container{ - box-shadow:none; - } - .required > label.control-label:after { - content: "*:"; - } - label.control-label:after{ - content :":"; - } - label.control-label{ - text-align:right; - padding-right: 1em; - } - .form-container input[type=text]{ - display: inline; - width: 76%; - } - - @media (max-width: 480px) { - label.control-label{ - display: block; - width:100%; - text-align:left; - } - .form-container input[type=text]{ - display: block; - width: 100%; - } -} - - -/* Proposals */ - -.dropdown { - display: inline; - width: auto; -} - - -/* Editor */ - -.wmd-preview { - background-color: #fff !important; - border: 2px dashed #ccc; -} -@media (min-width: 800px) { - .wmd-panel { - margin-top: -35px; - margin-bottom: 50px; - } - .wmd-preview { - margin-bottom: 10px; - } -} diff --git a/junction/static/css/layout.css b/junction/static/css/layout.css deleted file mode 100644 index 617786b7..00000000 --- a/junction/static/css/layout.css +++ /dev/null @@ -1,460 +0,0 @@ -.nospace, .nospace-top { - margin-top: 0 !important; -} - -.nospace, .nospace-bottom { - margin-bottom: 0 !important; -} - -.space-1q, .space-1q-top { - margin-top: 0.25em; -} - -.space-1q, .space-1q-bottom { - margin-bottom: 0.25em; -} - -.space-half, .space-half-top { - margin-top: 0.5em; -} - -.space-half, .space-half-bottom { - margin-bottom: 0.5em; -} - -.space-3q, .space-3q-top { - margin-top: 0.75em; -} - -.space-3q, .space-3q-bottom { - margin-bottom: 0.75em; -} - -.space-1, .space-1-top { - margin-top: 1em; -} - -.space-1, .space-1-bottom { - margin-bottom: 1em; -} - -.space-line, .space-line-top { - margin-top: 1.5em; -} - -.space-line, .space-line-bottom { - margin-bottom: 1.5em; -} - -.space-2, .space-2-top { - margin-top: 2em; -} - -.space-2, .space-2-bottom { - margin-bottom: 2em; -} - -.space-2h, .space-2h-top { - margin-top: 2.5em; -} - -.space-2h, .space-2h-bottom { - margin-bottom: 2.5em; -} - -.space-3, .space-3-top { - margin-top: 3em; -} - -.space-3, .space-3-bottom { - margin-bottom: 3em; -} - -.space-4, .space-4-top { - margin-top: 4em; -} - -.space-4, .space-4-bottom { - margin-bottom: 4em; -} - -.space-neg-1q, .space-neg-1q-top { - margin-top: -0.25em; -} - -.space-neg-1q, .space-neg-1q-bottom { - margin-bottom: -0.25em; -} - -.space-neg-half, .space-neg-half-top { - margin-top: -0.5em; -} - -.space-neg-half, .space-neg-half-bottom { - margin-bottom: -0.5em; -} - -.space-neg-3q, .space-neg-3q-top { - margin-top: -0.75em; -} - -.space-neg-3q, .space-neg-3q-bottom { - margin-bottom: -0.75em; -} - -.space-neg-1, .space-neg-1-top { - margin-top: -1em; -} - -.space-ned-1, .space-neg-1-bottom { - margin-bottom: -1em; -} - -.space-neg-2, .space-neg-2-top { - margin-top: -2em; -} - -.space-ned-2, .space-neg-2-bottom { - margin-bottom: -2em; -} - -.space-neg-3, .space-neg-3-top { - margin-top: -3em; -} - -.space-ned-3, .space-neg-3-bottom { - margin-bottom: -3em; -} - -.space-neg-box, .space-neg-box-top { - margin-top: -3.7em; -} - -.space-neg-box, .space-neg-box-bottom { - margin-bottom: -3.7em; -} - -.space-neg-4, .space-neg-4-top { - margin-top: -4em; -} - -.space-ned-4, .space-neg-4-bottom { - margin-bottom: -4em; -} - -.push-1q, .push-1q-top { - padding-top: 0.25em; -} - -.push-1q, .push-1q-bottom { - padding-bottom: 0.25em; -} - -.push-half, .push-half-top { - padding-top: 0.5em; -} - -.push-half, .push-half-bottom { - padding-bottom: 0.5em; -} - -.push-3q, .push-3q-top { - padding-top: 0.75em; -} - -.push-3q, .push-3q-bottom { - padding-bottom: 0.75em; -} - -.push-1, .push-1-top { - padding-top: 1em; -} - -.push-1, .push-1-bottom { - padding-bottom: 1em; -} - -.push-line, .push-line-top { - padding-top: 1.5em; -} - -.push-line, .push-line-bottom { - padding-bottom: 1.5em; -} - -.push-2, .push-2-top { - padding-top: 2em; -} - -.push-2, .push-2-bottom { - padding-bottom: 2em; -} - -.push-2h, .push-2h-top { - padding-top: 2.5em; -} - -.push-2h, .push-2h-bottom { - padding-bottom: 2.5em; -} - -.push-3, .push-3-top { - padding-top: 3em; -} - -.push-3, .push-3-bottom { - padding-bottom: 3em; -} - -.push-4, .push-4-top { - padding-top: 4em; -} - -.push-4, .push-4-bottom { - padding-bottom: 4em; -} - -.push-5, .push-5-top { - padding-top: 5em; -} - -.push-5, .push-5-bottom { - padding-bottom: 5em; -} - -.push-6, .push-6-top { - padding-top: 6em; -} - -.push-6, .push-6-bottom { - padding-bottom: 6em; -} - -.push-8, .push-8-top { - padding-top: 8em; -} - -.push-8, .push-8-bottom { - padding-bottom: 8em; -} - -.no-pad, .no-pad-left { - padding-left: 0; -} - -.no-pad, .no-pad-right { - padding-right: 0; -} - -.pad-half, .pad-half-left { - padding-left: 0.5em; -} - -.pad-half, .pad-half-right { - padding-right: 0.5em; -} - -.pad-3q, .pad-3q-left { - padding-left: 0.75em; -} - -.pad-3q, .pad-3q-right { - padding-right: 0.75em; -} - -.pad-1, .pad-1-left { - padding-left: 1em; -} - -.pad-1, .pad-1-right { - padding-right: 1em; -} - -.pad-line, .pad-line-left { - padding-left: 1.5em; -} - -.pad-line, .pad-line-right { - padding-right: 1.5em; -} - -.pad-2, .pad-2-left { - padding-left: 2em; -} - -.pad-2, .pad-2-right { - padding-right: 2em; -} - -.pad-2h, .pad-2h-left { - padding-left: 2.5em; -} - -.pad-2h, .pad-2h-right { - padding-right: 2.5em; -} - -.pad-3, .pad-3-left { - padding-left: 3em; -} - -.pad-3, .pad-3-right { - padding-right: 3em; -} - -.pad-4, .pad-4-left { - padding-left: 4em; -} - -.pad-4, .pad-4-right { - padding-right: 4em; -} - -.inlineblock { - display: inline-block !important; -} -a.white:hover { - color: white; -} -.white { - color: #FFF; -} -.yellow { - color: #ffdd55 !important; -} -.blue { - color: #2c5aa0; -} -.green { - color: #75c16a; -} -.red { - color: #a94442; -} -.gray{ - color: #CCC; -} -.fill-yellow { - background-color: #ffdd55; -} -.fill-blue { - background-color: #2c5aa0; -} -.fill-blue-alt { - background-color: #214478; -} -.fill-white { - background-color: #FFF; -} -.fill-gray { - background-color: #EEE; -} -.normal { - font-weight: 400; -} -.card { - box-shadow: 1px 1px 3px rgba(0,0,0,0.1); -} - -.center-wrapper { - display: table; -} -.absolute-center { - display: table-cell; - vertical-align: middle; -} -.measure-block { - width: 80%; - margin: auto; -} -.tint { - font-size: 0.6em; -} -html, body { - height: 100%; -} -body { - height: auto; - min-height: 100%; - position: relative; -} -footer { - position: absolute; - left: 0; - right: 0; - bottom: 0; - top: auto; -} - -.form-container { - background: #FFF; - box-shadow: 1px 1px 3px rgba(0,0,0,0.1); - border-radius: 0.15em; -} -.form-container h2 { - text-transform: uppercase; - font-size: 1.1em; - padding: 0.8em 0; - border-top-left-radius: 0.15em; - border-top-right-radius: 0.15em; - color: #FBFBF6; -} -.form-container input[type=text] + label { - visibility: hidden; - width: 0; - height: 0; -} -.form-container input[type=text], .form-container input[type=password], .form-container input[type=email], .form-container input[type=url], .form-container textarea { - border: 2px solid #CCC; - padding: 0.5em 1em; - width: 100%; - border-radius: 0.3em; -} -button, .form-container input[type=submit] { - background: #ffdd55; - border: 1px solid #dabd42; - border-radius: 0.3em; - color: #7C6E0D; - padding: 0.3em 1.5em 0.4em 1.5em; -} -button:hover { - color: #695E13; - background-color: #dabd42; - border-color: #C2A737; -} -.flushright { - float: right; -} -.flushleft { - float: left; -} -.clearboth { - clear: both; -} - -ul.errorlist{ - padding: 0; - margin: 0; -} -ul.errorlist li { - list-style-type: none; - background-color: #f2dede; - border: 1px solid #ebccd1; - border-radius: 4px; - color: #a94442; - padding: 0.5em 1em; - margin-bottom: 1em; -} - -.legible { - font-size: 1.5em; - line-height: 1.4em; -} -.legible-prose { - font-size: 1.2em; - line-height: 1.5em; -} -.regular { - font-size: 1em; - line-height: 1.4em; -} diff --git a/junction/static/css/list.css b/junction/static/css/list.css deleted file mode 100644 index f24cec8d..00000000 --- a/junction/static/css/list.css +++ /dev/null @@ -1,43 +0,0 @@ - header.custom-container{ - padding:10px; - } - .proposal-list h1 { - margin:0px; - } - .icon-holder{ - display: block; - width: 40px; - height: 50px; - background-color: #3BABEA; - padding: 8px; - vertical-align: middle; - border-radius: 6px; - color:#ffffff; - } - .icon-holder-inverse{ - background: transparent; - padding: 0px 8px 0px 8px; - color: #000; - height: 40px; - } - .icon-holder > h4 { - margin:0px; - } - .icon-holder > i { - margin-left:5px; - } - .proposal-list-content { - padding-bottom: 3px; - padding-top:20px; - border-bottom:1px dotted #ccc; - display:table; - width:100%; - } - - .proposal-list .title-underline{ - border-bottom:1px solid #ccc; - } - .border-less{ - border-top:none; - border-bottom:none; - } diff --git a/junction/static/css/style.css b/junction/static/css/style.css deleted file mode 100644 index 668c4c79..00000000 --- a/junction/static/css/style.css +++ /dev/null @@ -1,377 +0,0 @@ -/* Common styles */ -html { - font-size: 1em; -} -body { - padding-top: 5em; - padding-bottom:60px; - font-family: 'Open Sans', sans-serif; - background-color: #f5f5f5; - color: #333; - font-size: 0.885em; - line-height: 1.45em; -} - -/* Homepage styles */ -.masthead { - height: 27em; - display: block; - background: url('/static/images/masthead.jpg') center center no-repeat scroll; - -webkit-background-size: cover; - -moz-background-size: cover; - background-size: cover; - -o-background-size: cover; - position: relative; -} -.header-big h2 { - font-size: 1.5em; - line-height: 1.4em; -} -.header-big { - height: 18em; - width: 100%; -} -.masthead:after { - background: rgba(43, 91, 132, 0.1); - content: ''; - display: block; - height: inherit; - width: inherit; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; -} - -/* Customize Bootstrap */ -.navbar-default { - background-color: #FFF; - border: 0; - box-shadow: 0 0 3px rgba(0,0,0,0.1); -} -.navbar, .navbar-header { - margin-bottom: 0; - min-height: 5em; -} -.navbar-default .navbar-brand, .navbar-default .navbar-nav > li > a { - color: #333; - font-size: 1.08em; -} -.navbar-brand { - padding: 0.9em 0 0.7em 0.6em; - height: 70px; -} -.navbar-brand img { - height: 100%; -} -.navbar-nav > li > a, .navbar-toggle { - height: 4.7em; - line-height: 4.7em; - vertical-align: middle; -} -.navbar-toggle { - border: 0; -} -.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus { - background-color: #0d202b; -} -.navbar-default .navbar-collapse, .navbar-default .navbar-form { - border-color: transparent; -} -.navbar-nav > li > a { - padding-top: 0; - padding-bottom: 0; -} -.navbar-default .navbar-nav>li>a:hover, .navbar-default .navbar-nav>li>a:focus, .navbar-default .navbar-nav>.open>a, .navbar-default .navbar-nav>.open>a:hover { - background: #EEE; - color: #D5A952; -} -.navbar-default .navbar-nav>.open>a:focus { - background: #EEE; - color: #2b5b84; -} -.navbar-default .navbar-nav>li>a>.caret { - color: rgba(0,0,0,0.3); -} -.dropdown-menu { - background: #FFF; -} -.dropdown-menu>li>a { - color: #333; -} -.dropdown-menu>li>a:hover { - color: #D5A952; - background: rgba(0,0,0,0.1); -} -@media (max-width: 767px) { - .navbar-default .navbar-nav .open .dropdown-menu>li>a { - color: #CCC; - } - .navbar-default .navbar-nav .open .dropdown-menu>li>a:hover, .navbar-default .navbar-nav .open .dropdown-menu>li>a:focus { - color: #D5A952; - } - .dropdown .visible-xs{ - display: inline-block !important; - } -} -ul.socialaccount_providers { - padding-left: 0; - list-style-type: none; -} -a.socialaccount_provider { - margin: 1em 0; - text-align: center; - padding: 0.5em 0.5em 0.35em 0.5em; - border-bottom: 0.15em solid transparent; - width: 100%; - display: block; - text-decoration: none; - border-radius: 0.3em; -} -a.socialaccount_provider.github { - background-color: #DDD; - color: #444444; -} -a.socialaccount_provider.google { - background-color: #4683ea; - color: #FFF; -} -a.socialaccount_provider.google:hover { - border-bottom: 0.15em solid #4683ea; - background-color: #4387fd; -} -a.socialaccount_provider.github:hover { - border-bottom: 0.15em solid #DBDBDB; - background-color: #E5E5E5; -} -.icon { - padding-right: 0.4em; -} - -.btn-primary { - background: #ffdd55; - color: #7C6E0D; - border-color: #dabd42; -} -.btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open>.dropdown-toggle.btn-primary { - color: #695E13; - background-color: #dabd42; - border-color: #C2A737; -} - -/* Sidebar navigation */ -.nav-sidebar { - margin-right: -21px; /* 20px padding + 1px border */ - margin-bottom: 20px; - margin-left: -20px; -} -.nav-sidebar > li > a { - padding-right: 20px; - padding-left: 20px; -} -.nav-sidebar > .active > a, -.nav-sidebar > .active > a:hover, -.nav-sidebar > .active > a:focus { - color: #fff; - background-color: #428bca; -} -.content { - /* width: 90%; */ - margin: 0 auto; -} -@media (max-width: 768px) { - .sidebar { - margin-top: 1em; - } -} -@media (min-width: 768px) { - .sidebar { - display: block; - height: 100%; - position: fixed; - width: 25%; - } -} - - -.im-checkout { - margin: 0 auto; -} -.custom-container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} - -.wmd-wrapper>.wmd-panel{ -margin-left:auto; -margin-right:auto; -} -#tabs { - float: right; - font-weight: normal; - margin-top: -42px; -} -#tabs a.youarehere { - background: #fff; - border: 1px solid #ccc; - border-bottom-color: #fff; - color: #000; - font-size: 120%; - height: 30px; - line-height: 28px; - margin-top: 3px; - padding: 0 11px 0 11px; -} - -#tabs a { - background: inherit; - border: 1px solid transparent; - color: #777; - display: block; - float: left; - font-size: 90%; - height: 24px; - line-height: 20px; - margin: 9px 8px 0 0; - padding: 0 11px 0 11px; - text-decoration: none; - border-bottom: 1px solid #ccc; -} -#tabs a:hover { - background: #fff; - border: 1px solid #ccc; - border-bottom-color: #fff; -} -@media (min-width: 320px) { - .custom-container { - padding-right: 0px; - padding-left: 0px; - } -} -@media (max-width: 480px) { - #tabs { - margin-top: 0px; - } - #tabs a { - margin-left:0px; - margin-right:0px; - } -} -@media (min-width: 768px) { - .custom-container { - width: 750px; - } - .wmd-wrapper>.wmd-panel{ - margin-left:24%; - margin-right:auto; - width:76%; - } -} -@media (min-width: 992px){ - .custom-container { - width: 960px; - } -} -@media (min-width: 1200px){ - .custom-container { - width: 960px; - } -} - - -.wmd-panel .wmd-input{ - background-color:#ffffff; -} - - -.header-tab { - width:100%; - margin-top: 10px; - margin-bottom: 10px; - padding-bottom: 20px; -} - - -.header-tab-title { - margin-bottom: -10px; - border-bottom: 1px solid #ccc; - height: 34px; - clear: both; -} -header-tab-title >h2{ - float: left; - font-size: 18px; - line-height: 34px; - margin-bottom: 0; -} - - - -.statscontainer { - float: left; - padding:0px; -} -.stats { - background:#BDD7E6; - margin: 0px; - padding: 4px 7px 6px 7px; - width: 58px; - border-radius: 8px; -} -.proposal-list h3 , p { - margin:0px; - margin-bottom:5px; -} -.margin-less{ - margin:0px; -} -.padding-less{ - padding:0px; -} -.border-less{ - border-top:none; - border-bottom:none; -} - -/* - Header - --------------------------------------------------------------------------- -*/ - -.head_content { - text-align: center; - background: #2c5aa0; - color: #fff; - padding: 2em 1em 2em 1em; -} -.head_content h1 { - color: #ffdd55; -} - -/* Arrow after status - .stats:after, .stats:before { - left: 73px; - top: 50%; - border: solid transparent; - content: " "; - height: 0; - width: 0; - position: absolute; - pointer-events: none; -} - -.stats:after { - border-color: rgba(136, 183, 213, 0); - border-left-color: #88b7d5; - border-width: 9px; - margin-top: -10px; -} -.stats:before { - border-color: rgba(194, 225, 245, 0); - border-left-color: #c2e1f5; - border-width: 15px; - margin-top: -16px; -} */ diff --git a/junction/static/css/sweetalert.css b/junction/static/css/sweetalert.css deleted file mode 100644 index 4469aea6..00000000 --- a/junction/static/css/sweetalert.css +++ /dev/null @@ -1,715 +0,0 @@ -body.stop-scrolling { - height: 100%; - overflow: hidden; } - -.sweet-overlay { - background-color: black; - /* IE8 */ - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)"; - /* IE8 */ - background-color: rgba(0, 0, 0, 0.4); - position: fixed; - left: 0; - right: 0; - top: 0; - bottom: 0; - display: none; - z-index: 10000; } - -.sweet-alert { - background-color: white; - font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; - width: 478px; - padding: 17px; - border-radius: 5px; - text-align: center; - position: fixed; - left: 50%; - top: 50%; - margin-left: -256px; - margin-top: -200px; - overflow: hidden; - display: none; - z-index: 99999; } - @media all and (max-width: 540px) { - .sweet-alert { - width: auto; - margin-left: 0; - margin-right: 0; - left: 15px; - right: 15px; } } - .sweet-alert h2 { - color: #575757; - font-size: 30px; - text-align: center; - font-weight: 600; - text-transform: none; - position: relative; - margin: 25px 0; - padding: 0; - line-height: 40px; - display: block; } - .sweet-alert p { - color: #797979; - font-size: 16px; - text-align: center; - font-weight: 300; - position: relative; - text-align: inherit; - float: none; - margin: 0; - padding: 0; - line-height: normal; } - .sweet-alert fieldset { - border: none; - position: relative; } - .sweet-alert .sa-error-container { - background-color: #f1f1f1; - margin-left: -17px; - margin-right: -17px; - overflow: hidden; - padding: 0 10px; - max-height: 0; - webkit-transition: padding 0.15s, max-height 0.15s; - transition: padding 0.15s, max-height 0.15s; } - .sweet-alert .sa-error-container.show { - padding: 10px 0; - max-height: 100px; - webkit-transition: padding 0.2s, max-height 0.2s; - transition: padding 0.25s, max-height 0.25s; } - .sweet-alert .sa-error-container .icon { - display: inline-block; - width: 24px; - height: 24px; - border-radius: 50%; - background-color: #ea7d7d; - color: white; - line-height: 24px; - text-align: center; - margin-right: 3px; } - .sweet-alert .sa-error-container p { - display: inline-block; } - .sweet-alert .sa-input-error { - position: absolute; - top: 29px; - right: 26px; - width: 20px; - height: 20px; - opacity: 0; - -webkit-transform: scale(0.5); - transform: scale(0.5); - -webkit-transform-origin: 50% 50%; - transform-origin: 50% 50%; - -webkit-transition: all 0.1s; - transition: all 0.1s; } - .sweet-alert .sa-input-error::before, .sweet-alert .sa-input-error::after { - content: ""; - width: 20px; - height: 6px; - background-color: #f06e57; - border-radius: 3px; - position: absolute; - top: 50%; - margin-top: -4px; - left: 50%; - margin-left: -9px; } - .sweet-alert .sa-input-error::before { - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); } - .sweet-alert .sa-input-error::after { - -webkit-transform: rotate(45deg); - transform: rotate(45deg); } - .sweet-alert .sa-input-error.show { - opacity: 1; - -webkit-transform: scale(1); - transform: scale(1); } - .sweet-alert input { - width: 100%; - box-sizing: border-box; - border-radius: 3px; - border: 1px solid #d7d7d7; - height: 43px; - margin-top: 10px; - margin-bottom: 17px; - font-size: 18px; - box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.06); - padding: 0 12px; - display: none; - -webkit-transition: all 0.3s; - transition: all 0.3s; } - .sweet-alert input:focus { - outline: none; - box-shadow: 0px 0px 3px #c4e6f5; - border: 1px solid #b4dbed; } - .sweet-alert input:focus::-moz-placeholder { - transition: opacity 0.3s 0.03s ease; - opacity: 0.5; } - .sweet-alert input:focus:-ms-input-placeholder { - transition: opacity 0.3s 0.03s ease; - opacity: 0.5; } - .sweet-alert input:focus::-webkit-input-placeholder { - transition: opacity 0.3s 0.03s ease; - opacity: 0.5; } - .sweet-alert input::-moz-placeholder { - color: #bdbdbd; } - .sweet-alert input:-ms-input-placeholder { - color: #bdbdbd; } - .sweet-alert input::-webkit-input-placeholder { - color: #bdbdbd; } - .sweet-alert.show-input input { - display: block; } - .sweet-alert button { - background-color: #AEDEF4; - color: white; - border: none; - box-shadow: none; - font-size: 17px; - font-weight: 500; - -webkit-border-radius: 4px; - border-radius: 5px; - padding: 10px 32px; - margin: 26px 5px 0 5px; - cursor: pointer; } - .sweet-alert button:focus { - outline: none; - box-shadow: 0 0 2px rgba(128, 179, 235, 0.5), inset 0 0 0 1px rgba(0, 0, 0, 0.05); } - .sweet-alert button:hover { - background-color: #a1d9f2; } - .sweet-alert button:active { - background-color: #81ccee; } - .sweet-alert button.cancel { - background-color: #D0D0D0; } - .sweet-alert button.cancel:hover { - background-color: #c8c8c8; } - .sweet-alert button.cancel:active { - background-color: #b6b6b6; } - .sweet-alert button.cancel:focus { - box-shadow: rgba(197, 205, 211, 0.8) 0px 0px 2px, rgba(0, 0, 0, 0.0470588) 0px 0px 0px 1px inset !important; } - .sweet-alert button::-moz-focus-inner { - border: 0; } - .sweet-alert[data-has-cancel-button=false] button { - box-shadow: none !important; } - .sweet-alert[data-has-confirm-button=false][data-has-cancel-button=false] { - padding-bottom: 40px; } - .sweet-alert .sa-icon { - width: 80px; - height: 80px; - border: 4px solid gray; - -webkit-border-radius: 40px; - border-radius: 40px; - border-radius: 50%; - margin: 20px auto; - padding: 0; - position: relative; - box-sizing: content-box; } - .sweet-alert .sa-icon.sa-error { - border-color: #F27474; } - .sweet-alert .sa-icon.sa-error .sa-x-mark { - position: relative; - display: block; } - .sweet-alert .sa-icon.sa-error .sa-line { - position: absolute; - height: 5px; - width: 47px; - background-color: #F27474; - display: block; - top: 37px; - border-radius: 2px; } - .sweet-alert .sa-icon.sa-error .sa-line.sa-left { - -webkit-transform: rotate(45deg); - transform: rotate(45deg); - left: 17px; } - .sweet-alert .sa-icon.sa-error .sa-line.sa-right { - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); - right: 16px; } - .sweet-alert .sa-icon.sa-warning { - border-color: #F8BB86; } - .sweet-alert .sa-icon.sa-warning .sa-body { - position: absolute; - width: 5px; - height: 47px; - left: 50%; - top: 10px; - -webkit-border-radius: 2px; - border-radius: 2px; - margin-left: -2px; - background-color: #F8BB86; } - .sweet-alert .sa-icon.sa-warning .sa-dot { - position: absolute; - width: 7px; - height: 7px; - -webkit-border-radius: 50%; - border-radius: 50%; - margin-left: -3px; - left: 50%; - bottom: 10px; - background-color: #F8BB86; } - .sweet-alert .sa-icon.sa-info { - border-color: #C9DAE1; } - .sweet-alert .sa-icon.sa-info::before { - content: ""; - position: absolute; - width: 5px; - height: 29px; - left: 50%; - bottom: 17px; - border-radius: 2px; - margin-left: -2px; - background-color: #C9DAE1; } - .sweet-alert .sa-icon.sa-info::after { - content: ""; - position: absolute; - width: 7px; - height: 7px; - border-radius: 50%; - margin-left: -3px; - top: 19px; - background-color: #C9DAE1; } - .sweet-alert .sa-icon.sa-success { - border-color: #A5DC86; } - .sweet-alert .sa-icon.sa-success::before, .sweet-alert .sa-icon.sa-success::after { - content: ''; - -webkit-border-radius: 40px; - border-radius: 40px; - border-radius: 50%; - position: absolute; - width: 60px; - height: 120px; - background: white; - -webkit-transform: rotate(45deg); - transform: rotate(45deg); } - .sweet-alert .sa-icon.sa-success::before { - -webkit-border-radius: 120px 0 0 120px; - border-radius: 120px 0 0 120px; - top: -7px; - left: -33px; - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); - -webkit-transform-origin: 60px 60px; - transform-origin: 60px 60px; } - .sweet-alert .sa-icon.sa-success::after { - -webkit-border-radius: 0 120px 120px 0; - border-radius: 0 120px 120px 0; - top: -11px; - left: 30px; - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); - -webkit-transform-origin: 0px 60px; - transform-origin: 0px 60px; } - .sweet-alert .sa-icon.sa-success .sa-placeholder { - width: 80px; - height: 80px; - border: 4px solid rgba(165, 220, 134, 0.2); - -webkit-border-radius: 40px; - border-radius: 40px; - border-radius: 50%; - box-sizing: content-box; - position: absolute; - left: -4px; - top: -4px; - z-index: 2; } - .sweet-alert .sa-icon.sa-success .sa-fix { - width: 5px; - height: 90px; - background-color: white; - position: absolute; - left: 28px; - top: 8px; - z-index: 1; - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); } - .sweet-alert .sa-icon.sa-success .sa-line { - height: 5px; - background-color: #A5DC86; - display: block; - border-radius: 2px; - position: absolute; - z-index: 2; } - .sweet-alert .sa-icon.sa-success .sa-line.sa-tip { - width: 25px; - left: 14px; - top: 46px; - -webkit-transform: rotate(45deg); - transform: rotate(45deg); } - .sweet-alert .sa-icon.sa-success .sa-line.sa-long { - width: 47px; - right: 8px; - top: 38px; - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); } - .sweet-alert .sa-icon.sa-custom { - background-size: contain; - border-radius: 0; - border: none; - background-position: center center; - background-repeat: no-repeat; } - -/* - * Animations - */ -@-webkit-keyframes showSweetAlert { - 0% { - transform: scale(0.7); - -webkit-transform: scale(0.7); } - 45% { - transform: scale(1.05); - -webkit-transform: scale(1.05); } - 80% { - transform: scale(0.95); - -webkit-transform: scale(0.95); } - 100% { - transform: scale(1); - -webkit-transform: scale(1); } } - -@keyframes showSweetAlert { - 0% { - transform: scale(0.7); - -webkit-transform: scale(0.7); } - 45% { - transform: scale(1.05); - -webkit-transform: scale(1.05); } - 80% { - transform: scale(0.95); - -webkit-transform: scale(0.95); } - 100% { - transform: scale(1); - -webkit-transform: scale(1); } } - -@-webkit-keyframes hideSweetAlert { - 0% { - transform: scale(1); - -webkit-transform: scale(1); } - 100% { - transform: scale(0.5); - -webkit-transform: scale(0.5); } } - -@keyframes hideSweetAlert { - 0% { - transform: scale(1); - -webkit-transform: scale(1); } - 100% { - transform: scale(0.5); - -webkit-transform: scale(0.5); } } - -@-webkit-keyframes slideFromTop { - 0% { - top: 0%; } - 100% { - top: 50%; } } - -@keyframes slideFromTop { - 0% { - top: 0%; } - 100% { - top: 50%; } } - -@-webkit-keyframes slideToTop { - 0% { - top: 50%; } - 100% { - top: 0%; } } - -@keyframes slideToTop { - 0% { - top: 50%; } - 100% { - top: 0%; } } - -@-webkit-keyframes slideFromBottom { - 0% { - top: 70%; } - 100% { - top: 50%; } } - -@keyframes slideFromBottom { - 0% { - top: 70%; } - 100% { - top: 50%; } } - -@-webkit-keyframes slideToBottom { - 0% { - top: 50%; } - 100% { - top: 70%; } } - -@keyframes slideToBottom { - 0% { - top: 50%; } - 100% { - top: 70%; } } - -.showSweetAlert[data-animation=pop] { - -webkit-animation: showSweetAlert 0.3s; - animation: showSweetAlert 0.3s; } - -.showSweetAlert[data-animation=none] { - -webkit-animation: none; - animation: none; } - -.showSweetAlert[data-animation=slide-from-top] { - -webkit-animation: slideFromTop 0.3s; - animation: slideFromTop 0.3s; } - -.showSweetAlert[data-animation=slide-from-bottom] { - -webkit-animation: slideFromBottom 0.3s; - animation: slideFromBottom 0.3s; } - -.hideSweetAlert[data-animation=pop] { - -webkit-animation: hideSweetAlert 0.2s; - animation: hideSweetAlert 0.2s; } - -.hideSweetAlert[data-animation=none] { - -webkit-animation: none; - animation: none; } - -.hideSweetAlert[data-animation=slide-from-top] { - -webkit-animation: slideToTop 0.4s; - animation: slideToTop 0.4s; } - -.hideSweetAlert[data-animation=slide-from-bottom] { - -webkit-animation: slideToBottom 0.3s; - animation: slideToBottom 0.3s; } - -@-webkit-keyframes animateSuccessTip { - 0% { - width: 0; - left: 1px; - top: 19px; } - 54% { - width: 0; - left: 1px; - top: 19px; } - 70% { - width: 50px; - left: -8px; - top: 37px; } - 84% { - width: 17px; - left: 21px; - top: 48px; } - 100% { - width: 25px; - left: 14px; - top: 45px; } } - -@keyframes animateSuccessTip { - 0% { - width: 0; - left: 1px; - top: 19px; } - 54% { - width: 0; - left: 1px; - top: 19px; } - 70% { - width: 50px; - left: -8px; - top: 37px; } - 84% { - width: 17px; - left: 21px; - top: 48px; } - 100% { - width: 25px; - left: 14px; - top: 45px; } } - -@-webkit-keyframes animateSuccessLong { - 0% { - width: 0; - right: 46px; - top: 54px; } - 65% { - width: 0; - right: 46px; - top: 54px; } - 84% { - width: 55px; - right: 0px; - top: 35px; } - 100% { - width: 47px; - right: 8px; - top: 38px; } } - -@keyframes animateSuccessLong { - 0% { - width: 0; - right: 46px; - top: 54px; } - 65% { - width: 0; - right: 46px; - top: 54px; } - 84% { - width: 55px; - right: 0px; - top: 35px; } - 100% { - width: 47px; - right: 8px; - top: 38px; } } - -@-webkit-keyframes rotatePlaceholder { - 0% { - transform: rotate(-45deg); - -webkit-transform: rotate(-45deg); } - 5% { - transform: rotate(-45deg); - -webkit-transform: rotate(-45deg); } - 12% { - transform: rotate(-405deg); - -webkit-transform: rotate(-405deg); } - 100% { - transform: rotate(-405deg); - -webkit-transform: rotate(-405deg); } } - -@keyframes rotatePlaceholder { - 0% { - transform: rotate(-45deg); - -webkit-transform: rotate(-45deg); } - 5% { - transform: rotate(-45deg); - -webkit-transform: rotate(-45deg); } - 12% { - transform: rotate(-405deg); - -webkit-transform: rotate(-405deg); } - 100% { - transform: rotate(-405deg); - -webkit-transform: rotate(-405deg); } } - -.animateSuccessTip { - -webkit-animation: animateSuccessTip 0.75s; - animation: animateSuccessTip 0.75s; } - -.animateSuccessLong { - -webkit-animation: animateSuccessLong 0.75s; - animation: animateSuccessLong 0.75s; } - -.sa-icon.sa-success.animate::after { - -webkit-animation: rotatePlaceholder 4.25s ease-in; - animation: rotatePlaceholder 4.25s ease-in; } - -@-webkit-keyframes animateErrorIcon { - 0% { - transform: rotateX(100deg); - -webkit-transform: rotateX(100deg); - opacity: 0; } - 100% { - transform: rotateX(0deg); - -webkit-transform: rotateX(0deg); - opacity: 1; } } - -@keyframes animateErrorIcon { - 0% { - transform: rotateX(100deg); - -webkit-transform: rotateX(100deg); - opacity: 0; } - 100% { - transform: rotateX(0deg); - -webkit-transform: rotateX(0deg); - opacity: 1; } } - -.animateErrorIcon { - -webkit-animation: animateErrorIcon 0.5s; - animation: animateErrorIcon 0.5s; } - -@-webkit-keyframes animateXMark { - 0% { - transform: scale(0.4); - -webkit-transform: scale(0.4); - margin-top: 26px; - opacity: 0; } - 50% { - transform: scale(0.4); - -webkit-transform: scale(0.4); - margin-top: 26px; - opacity: 0; } - 80% { - transform: scale(1.15); - -webkit-transform: scale(1.15); - margin-top: -6px; } - 100% { - transform: scale(1); - -webkit-transform: scale(1); - margin-top: 0; - opacity: 1; } } - -@keyframes animateXMark { - 0% { - transform: scale(0.4); - -webkit-transform: scale(0.4); - margin-top: 26px; - opacity: 0; } - 50% { - transform: scale(0.4); - -webkit-transform: scale(0.4); - margin-top: 26px; - opacity: 0; } - 80% { - transform: scale(1.15); - -webkit-transform: scale(1.15); - margin-top: -6px; } - 100% { - transform: scale(1); - -webkit-transform: scale(1); - margin-top: 0; - opacity: 1; } } - -.animateXMark { - -webkit-animation: animateXMark 0.5s; - animation: animateXMark 0.5s; } - -@-webkit-keyframes pulseWarning { - 0% { - border-color: #F8D486; } - 100% { - border-color: #F8BB86; } } - -@keyframes pulseWarning { - 0% { - border-color: #F8D486; } - 100% { - border-color: #F8BB86; } } - -.pulseWarning { - -webkit-animation: pulseWarning 0.75s infinite alternate; - animation: pulseWarning 0.75s infinite alternate; } - -@-webkit-keyframes pulseWarningIns { - 0% { - background-color: #F8D486; } - 100% { - background-color: #F8BB86; } } - -@keyframes pulseWarningIns { - 0% { - background-color: #F8D486; } - 100% { - background-color: #F8BB86; } } - -.pulseWarningIns { - -webkit-animation: pulseWarningIns 0.75s infinite alternate; - animation: pulseWarningIns 0.75s infinite alternate; } - -/* Internet Explorer 9 has some special quirks that are fixed here */ -/* The icons are not animated. */ -/* This file is automatically merged into sweet-alert.min.js through Gulp */ -/* Error icon */ -.sweet-alert .sa-icon.sa-error .sa-line.sa-left { - -ms-transform: rotate(45deg) \9; } - -.sweet-alert .sa-icon.sa-error .sa-line.sa-right { - -ms-transform: rotate(-45deg) \9; } - -/* Success icon */ -.sweet-alert .sa-icon.sa-success { - border-color: transparent\9; } - -.sweet-alert .sa-icon.sa-success .sa-line.sa-tip { - -ms-transform: rotate(45deg) \9; } - -.sweet-alert .sa-icon.sa-success .sa-line.sa-long { - -ms-transform: rotate(-45deg) \9; } diff --git a/junction/static/css/ui.css b/junction/static/css/ui.css deleted file mode 100644 index 68c384f3..00000000 --- a/junction/static/css/ui.css +++ /dev/null @@ -1,7 +0,0 @@ -/* - Markdown Editor - ============================================================================ */ - -.wmd-preview { - background-color: #fff; -} From 74a23c3e9218211792b44a837964b3ad656e78e3 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Mon, 27 Mar 2017 20:03:08 +0530 Subject: [PATCH 529/666] Add yarn.lock file --- junction/static/yarn.lock | 2088 +++++++++++++++++++++++++++++++++++++ 1 file changed, 2088 insertions(+) create mode 100644 junction/static/yarn.lock diff --git a/junction/static/yarn.lock b/junction/static/yarn.lock new file mode 100644 index 00000000..c7df175d --- /dev/null +++ b/junction/static/yarn.lock @@ -0,0 +1,2088 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +abbrev@1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" + +ajv@^4.9.1: + version "4.11.5" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.5.tgz#b6ee74657b993a01dce44b7944d56f485828d5bd" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +append-transform@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" + dependencies: + default-require-extensions "^1.0.0" + +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +"argparse@~ 0.1.11": + version "0.1.16" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-0.1.16.tgz#cfd01e0fbba3d6caed049fbd758d40f65196f57c" + dependencies: + underscore "~1.7.0" + underscore.string "~2.4.0" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +asap@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +async@^1.4.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + +async@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/async/-/async-2.2.0.tgz#c324eba010a237e4fbd55a12dee86367d5c0ef32" + dependencies: + lodash "^4.14.0" + +async@~0.1.22: + version "0.1.22" + resolved "https://registry.yarnpkg.com/async/-/async-0.1.22.tgz#0fc1aaa088a0e3ef0ebe2d8831bab0dcf8845061" + +async@~0.2.9: + version "0.2.10" + resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws4@^1.2.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + +babel-code-frame@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" + dependencies: + chalk "^1.1.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +babel-generator@^6.18.0: + version "6.24.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.0.tgz#eba270a8cc4ce6e09a61be43465d7c62c1f87c56" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-types "^6.23.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.2.0" + source-map "^0.5.0" + trim-right "^1.0.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-runtime@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.10.0" + +babel-template@^6.16.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.23.0.tgz#04d4f270adbb3aa704a8143ae26faa529238e638" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.23.0" + babel-types "^6.23.0" + babylon "^6.11.0" + lodash "^4.2.0" + +babel-traverse@^6.18.0, babel-traverse@^6.23.0: + version "6.23.1" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48" + dependencies: + babel-code-frame "^6.22.0" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-types "^6.23.0" + babylon "^6.15.0" + debug "^2.2.0" + globals "^9.0.0" + invariant "^2.2.0" + lodash "^4.2.0" + +babel-types@^6.18.0, babel-types@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.23.0.tgz#bb17179d7538bad38cd0c9e115d340f77e7e9acf" + dependencies: + babel-runtime "^6.22.0" + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^1.0.1" + +babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0: + version "6.16.1" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +bcrypt-pbkdf@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + dependencies: + tweetnacl "^0.14.3" + +bluebird@^3.3.1: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +brace-expansion@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +buffer-shims@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" + +builtin-modules@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +caching-transform@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" + dependencies: + md5-hex "^1.2.0" + mkdirp "^0.5.1" + write-file-atomic "^1.1.4" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + +caseless@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +clean-yaml-object@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz#63fb110dc2ce1a84dc21f6d9334876d010ae8b68" + +cli@0.6.x: + version "0.6.6" + resolved "https://registry.yarnpkg.com/cli/-/cli-0.6.6.tgz#02ad44a380abf27adac5e6f0cdd7b043d74c53e3" + dependencies: + exit "0.1.2" + glob "~ 3.2.1" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +coffee-script@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.3.3.tgz#150d6b4cb522894369efed6a2101c20bc7f4a4f4" + +color-support@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.2.tgz#49cc99b89d1bdef1292e9d9323c66971a33eb89d" + +colors@~0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + dependencies: + delayed-stream "~1.0.0" + +commander@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +console-browserify@1.1.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + +convert-source-map@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.4.0.tgz#e3dad195bf61bfe13a7a3c73e9876ec14a0268f3" + +core-js@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +coveralls@^2.11.2: + version "2.12.0" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.12.0.tgz#b3d064108e29728385b56e42fc2d119f43e0e517" + dependencies: + js-yaml "3.6.1" + lcov-parse "0.0.10" + log-driver "1.2.5" + minimist "1.2.0" + request "2.79.0" + +cross-spawn@^4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + +dateformat@1.0.2-1.2.3: + version "1.0.2-1.2.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.2-1.2.3.tgz#b0220c02de98617433b72851cf47de3df2cdbee9" + +debug@^2.1.3, debug@^2.2.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.3.tgz#0f7eb8c30965ec08c72accfa0130c8b79984141d" + dependencies: + ms "0.7.2" + +debug@~0.7.0: + version "0.7.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" + +decamelize@^1.0.0, decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deeper@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/deeper/-/deeper-2.1.0.tgz#bc564e5f73174fdf201e08b00030e8a14da74368" + +default-require-extensions@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" + dependencies: + strip-bom "^2.0.0" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +diff@^1.3.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" + +dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domelementtype@1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" + dependencies: + domelementtype "1" + +domutils@1.5: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +entities@1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" + +entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +errno@^0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" + dependencies: + prr "~0.0.0" + +error-ex@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +esprima@^2.6.0: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + +esprima@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + +"esprima@~ 1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +eventemitter2@~0.4.13: + version "0.4.14" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab" + +events-to-array@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/events-to-array/-/events-to-array-1.0.2.tgz#b3484465534fe4ff66fbdd1a83b777713ba404aa" + +exit@0.1.2, exit@0.1.x, exit@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +extend@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +extsprintf@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" + +faye-websocket@~0.4.3: + version "0.4.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.4.4.tgz#c14c5b3bf14d7417ffbfd990c0a7495cd9f337bc" + +filename-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.0.tgz#996e3e80479b98b9897f15a8a58b3d084e926775" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +find-cache-dir@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" + dependencies: + commondir "^1.0.1" + mkdirp "^0.5.1" + pkg-dir "^1.0.0" + +find-up@^1.0.0, find-up@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +findup-sync@~0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.1.3.tgz#7f3e7a97b82392c653bf06589bd85190e93c3683" + dependencies: + glob "~3.2.9" + lodash "~2.4.1" + +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + +foreground-child@^1.3.3, foreground-child@^1.5.3, foreground-child@^1.5.6: + version "1.5.6" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" + dependencies: + cross-spawn "^4" + signal-exit "^3.0.0" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +gaze@~0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-0.5.2.tgz#40b709537d24d1d45767db5a908689dfe69ac44f" + dependencies: + globule "~0.1.0" + +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + +get-caller-file@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + +getobject@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/getobject/-/getobject-0.1.0.tgz#047a449789fa160d018f5486ed91320b6ec7885c" + +getpass@^0.1.1: + version "0.1.6" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +"glob@~ 3.2.1", glob@~3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" + dependencies: + inherits "2" + minimatch "0.3" + +glob@~3.1.21: + version "3.1.21" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" + dependencies: + graceful-fs "~1.2.0" + inherits "1" + minimatch "~0.2.11" + +globals@^9.0.0: + version "9.17.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" + +globule@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/globule/-/globule-0.1.0.tgz#d9c8edde1da79d125a151b79533b978676346ae5" + dependencies: + glob "~3.1.21" + lodash "~1.0.1" + minimatch "~0.2.11" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +graceful-fs@~1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364" + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + +grunt-contrib-jshint@~0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/grunt-contrib-jshint/-/grunt-contrib-jshint-0.10.0.tgz#57ebccca87e8f327af6645d8a3c586d4845e4d81" + dependencies: + hooker "~0.2.3" + jshint "~2.5.0" + +grunt-contrib-less@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/grunt-contrib-less/-/grunt-contrib-less-1.4.1.tgz#3bbdec0b75d12ceaa55d62943625c0b0861cdf6f" + dependencies: + async "^2.0.0" + chalk "^1.0.0" + less "~2.7.1" + lodash "^4.8.2" + +grunt-contrib-nodeunit@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/grunt-contrib-nodeunit/-/grunt-contrib-nodeunit-0.4.1.tgz#943393ee5d66b1cdadb49a9b23aaee44455095b2" + dependencies: + hooker "~0.2.3" + nodeunit "~0.9.0" + +grunt-contrib-watch@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/grunt-contrib-watch/-/grunt-contrib-watch-0.6.1.tgz#64fdcba25a635f5b4da1b6ce6f90da0aeb6e3f15" + dependencies: + async "~0.2.9" + gaze "~0.5.1" + lodash "~2.4.1" + tiny-lr-fork "0.0.5" + +grunt-legacy-log-utils@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz#c0706b9dd9064e116f36f23fe4e6b048672c0f7e" + dependencies: + colors "~0.6.2" + lodash "~2.4.1" + underscore.string "~2.3.3" + +grunt-legacy-log@~0.1.0: + version "0.1.3" + resolved "https://registry.yarnpkg.com/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz#ec29426e803021af59029f87d2f9cd7335a05531" + dependencies: + colors "~0.6.2" + grunt-legacy-log-utils "~0.1.1" + hooker "~0.2.3" + lodash "~2.4.1" + underscore.string "~2.3.3" + +grunt-legacy-util@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz#93324884dbf7e37a9ff7c026dff451d94a9e554b" + dependencies: + async "~0.1.22" + exit "~0.1.1" + getobject "~0.1.0" + hooker "~0.2.3" + lodash "~0.9.2" + underscore.string "~2.2.1" + which "~1.0.5" + +grunt@^0.4.5: + version "0.4.5" + resolved "https://registry.yarnpkg.com/grunt/-/grunt-0.4.5.tgz#56937cd5194324adff6d207631832a9d6ba4e7f0" + dependencies: + async "~0.1.22" + coffee-script "~1.3.3" + colors "~0.6.2" + dateformat "1.0.2-1.2.3" + eventemitter2 "~0.4.13" + exit "~0.1.1" + findup-sync "~0.1.2" + getobject "~0.1.0" + glob "~3.1.21" + grunt-legacy-log "~0.1.0" + grunt-legacy-util "~0.2.0" + hooker "~0.2.3" + iconv-lite "~0.2.11" + js-yaml "~2.0.5" + lodash "~0.9.2" + minimatch "~0.2.12" + nopt "~1.0.10" + rimraf "~2.2.8" + underscore.string "~2.2.1" + which "~1.0.5" + +handlebars@^4.0.3: + version "4.0.6" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.6.tgz#2ce4484850537f9c97a8026d5399b935c4ed4ed7" + dependencies: + async "^1.4.0" + optimist "^0.6.1" + source-map "^0.4.4" + optionalDependencies: + uglify-js "^2.6" + +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" + +har-validator@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" + dependencies: + chalk "^1.1.1" + commander "^2.9.0" + is-my-json-valid "^2.12.4" + pinkie-promise "^2.0.0" + +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +hooker@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/hooker/-/hooker-0.2.3.tgz#b834f723cc4a242aa65963459df6d984c5d3d959" + +hosted-git-info@^2.1.4: + version "2.4.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.1.tgz#4b0445e41c004a8bd1337773a4ff790ca40318c8" + +htmlparser2@3.8.x: + version "3.8.3" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" + dependencies: + domelementtype "1" + domhandler "2.3" + domutils "1.5" + entities "1.0" + readable-stream "1.1" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +iconv-lite@~0.2.11: + version "0.2.11" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.2.11.tgz#1ce60a3a57864a292d1321ff4609ca4bb965adc8" + +image-size@~0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.1.tgz#28eea8548a4b1443480ddddc1e083ae54652439f" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" + +inherits@2, inherits@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +invariant@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-buffer@^1.0.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-dotfile@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-my-json-valid@^2.12.4: + version "2.16.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-number@^2.0.2, is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +istanbul-lib-coverage@^1.0.0-alpha.4, istanbul-lib-coverage@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.0.2.tgz#87a0c015b6910651cb3b184814dfb339337e25e1" + +istanbul-lib-hook@^1.0.0-alpha.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.5.tgz#6ca3d16d60c5f4082da39f7c5cd38ea8a772b88e" + dependencies: + append-transform "^0.4.0" + +istanbul-lib-instrument@^1.1.0-alpha.3: + version "1.7.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.0.tgz#b8e0dc25709bb44e17336ab47b7bb5c97c23f659" + dependencies: + babel-generator "^6.18.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + babylon "^6.13.0" + istanbul-lib-coverage "^1.0.2" + semver "^5.3.0" + +istanbul-lib-report@^1.0.0-alpha.3: + version "1.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.0.0.tgz#d83dac7f26566b521585569367fe84ccfc7aaecb" + dependencies: + istanbul-lib-coverage "^1.0.2" + mkdirp "^0.5.1" + path-parse "^1.0.5" + supports-color "^3.1.2" + +istanbul-lib-source-maps@^1.0.0-alpha.10: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.1.1.tgz#f8c8c2e8f2160d1d91526d97e5bd63b2079af71c" + dependencies: + istanbul-lib-coverage "^1.0.2" + mkdirp "^0.5.1" + rimraf "^2.4.4" + source-map "^0.5.3" + +istanbul-reports@^1.0.0-alpha.8: + version "1.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.0.2.tgz#4e8366abe6fa746cc1cd6633f108de12cc6ac6fa" + dependencies: + handlebars "^4.0.3" + +jodid25519@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" + dependencies: + jsbn "~0.1.0" + +js-tokens@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" + +js-yaml@3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" + dependencies: + argparse "^1.0.7" + esprima "^2.6.0" + +js-yaml@^3.2.7, js-yaml@^3.3.1: + version "3.8.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.2.tgz#02d3e2c0f6beab20248d412c352203827d786721" + dependencies: + argparse "^1.0.7" + esprima "^3.1.1" + +js-yaml@~2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-2.0.5.tgz#a25ae6509999e97df278c6719da11bd0687743a8" + dependencies: + argparse "~ 0.1.11" + esprima "~ 1.0.2" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jshint@~2.5.0: + version "2.5.11" + resolved "https://registry.yarnpkg.com/jshint/-/jshint-2.5.11.tgz#e2d95858bbb1aa78300108a2e81099fb095622e0" + dependencies: + cli "0.6.x" + console-browserify "1.1.x" + exit "0.1.x" + htmlparser2 "3.8.x" + minimatch "1.0.x" + shelljs "0.3.x" + strip-json-comments "1.0.x" + underscore "1.6.x" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + +jsprim@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918" + dependencies: + assert-plus "1.0.0" + extsprintf "1.0.2" + json-schema "0.2.3" + verror "1.3.6" + +kind-of@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47" + dependencies: + is-buffer "^1.0.2" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +lcov-parse@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" + +less@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/less/-/less-2.7.2.tgz#368d6cc73e1fb03981183280918743c5dcf9b3df" + optionalDependencies: + errno "^0.1.1" + graceful-fs "^4.1.2" + image-size "~0.5.0" + mime "^1.2.11" + mkdirp "^0.5.0" + promise "^7.1.1" + request "^2.72.0" + source-map "^0.5.3" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +lodash.assign@^4.0.3, lodash.assign@^4.0.6, lodash.assign@^4.0.9: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + +lodash@^4.14.0, lodash@^4.2.0, lodash@^4.8.2: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +lodash@~0.9.2: + version "0.9.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-0.9.2.tgz#8f3499c5245d346d682e5b0d3b40767e09f1a92c" + +lodash@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" + +lodash@~2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" + +log-driver@1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + +loose-envify@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + +lru-cache@2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + +lru-cache@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" + dependencies: + pseudomap "^1.0.1" + yallist "^2.0.0" + +md5-hex@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" + dependencies: + md5-o-matic "^0.1.1" + +md5-o-matic@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" + +micromatch@^2.3.11, micromatch@^2.3.8: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +mime-db@~1.27.0: + version "1.27.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1" + +mime-types@^2.1.12, mime-types@~2.1.7: + version "2.1.15" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed" + dependencies: + mime-db "~1.27.0" + +mime@^1.2.11: + version "1.3.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" + +minimatch@0.3: + version "0.3.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimatch@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-1.0.0.tgz#e0dd2120b49e1b724ce8d714c520822a9438576d" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimatch@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" + +minimatch@~0.2.11, minimatch@~0.2.12: + version "0.2.14" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimist@0.0.8, minimist@~0.0.1: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + +nodeunit@~0.9.0: + version "0.9.5" + resolved "https://registry.yarnpkg.com/nodeunit/-/nodeunit-0.9.5.tgz#0b632368007d94651ccf0a18999807982f073866" + dependencies: + tap "^7.0.0" + +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + dependencies: + abbrev "1" + +nopt@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-2.0.0.tgz#ca7416f20a5e3f9c3b86180f96295fa3d0b52e0d" + dependencies: + abbrev "1" + +noptify@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/noptify/-/noptify-0.0.3.tgz#58f654a73d9753df0c51d9686dc92104a67f4bbb" + dependencies: + nopt "~2.0.0" + +normalize-package-data@^2.3.2: + version "2.3.6" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.6.tgz#498fa420c96401f787402ba21e600def9f981fff" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +nyc@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-7.1.0.tgz#8e14971f3a15d1abbec7ac610ef54cb889e9ffb4" + dependencies: + arrify "^1.0.1" + caching-transform "^1.0.0" + convert-source-map "^1.3.0" + default-require-extensions "^1.0.0" + find-cache-dir "^0.1.1" + find-up "^1.1.2" + foreground-child "^1.5.3" + glob "^7.0.3" + istanbul-lib-coverage "^1.0.0-alpha.4" + istanbul-lib-hook "^1.0.0-alpha.4" + istanbul-lib-instrument "^1.1.0-alpha.3" + istanbul-lib-report "^1.0.0-alpha.3" + istanbul-lib-source-maps "^1.0.0-alpha.10" + istanbul-reports "^1.0.0-alpha.8" + md5-hex "^1.2.0" + micromatch "^2.3.11" + mkdirp "^0.5.0" + pkg-up "^1.0.0" + resolve-from "^2.0.0" + rimraf "^2.5.4" + signal-exit "^3.0.0" + spawn-wrap "^1.2.4" + test-exclude "^1.1.0" + yargs "^4.8.1" + yargs-parser "^2.4.1" + +oauth-sign@~0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +only-shallow@^1.0.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/only-shallow/-/only-shallow-1.2.0.tgz#71cecedba9324bc0518aef10ec080d3249dc2465" + +opener@^1.4.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +os-homedir@1.0.1, os-homedir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.1.tgz#0d62bdf44b916fd3bbdcf2cab191948fb094f007" + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + dependencies: + lcid "^1.0.0" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + +pkg-up@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26" + dependencies: + find-up "^1.0.0" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +promise@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf" + dependencies: + asap "~2.0.3" + +prr@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" + +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +punycode@^1.3.2, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +qs@~0.5.2: + version "0.5.6" + resolved "https://registry.yarnpkg.com/qs/-/qs-0.5.6.tgz#31b1ad058567651c526921506b9a8793911a0384" + +qs@~6.3.0: + version "6.3.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" + +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + +randomatic@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb" + dependencies: + is-number "^2.0.2" + kind-of "^3.0.2" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +readable-stream@1.1: + version "1.1.13" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2, readable-stream@^2.0.2, readable-stream@^2.1.5: + version "2.2.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.6.tgz#8b43aed76e71483938d12a8d46c6cf1a00b1f816" + dependencies: + buffer-shims "^1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +regenerator-runtime@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz#8c4367a904b51ea62a908ac310bf99ff90a82a3e" + +regex-cache@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" + dependencies: + is-equal-shallow "^0.1.3" + is-primitive "^2.0.0" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request@2.79.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" + +request@^2.72.0: + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + +resolve-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + dependencies: + align-text "^0.1.1" + +rimraf@^2.3.3, rimraf@^2.4.4, rimraf@^2.5.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" + dependencies: + glob "^7.0.5" + +rimraf@~2.2.8: + version "2.2.8" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" + +safe-buffer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" + +"semver@2 || 3 || 4 || 5", semver@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +shelljs@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" + +sigmund@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + +signal-exit@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-2.1.2.tgz#375879b1f92ebc3b334480d038dc546a6d558564" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +slide@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +source-map@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +source-map@^0.5.0, source-map@^0.5.3, source-map@~0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + +spawn-wrap@^1.2.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.3.4.tgz#5d133070fef81cd26d8259acaa07fc1a86fd45dc" + dependencies: + foreground-child "^1.5.6" + mkdirp "^0.5.0" + os-homedir "^1.0.1" + rimraf "^2.3.3" + signal-exit "^2.0.0" + which "^1.2.4" + +spdx-correct@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" + dependencies: + spdx-license-ids "^1.0.2" + +spdx-expression-parse@~1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" + +spdx-license-ids@^1.0.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.11.0.tgz#2d8d5ebb4a6fab28ffba37fa62a90f4a3ea59d77" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jodid25519 "^1.0.0" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +stack-utils@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-0.4.0.tgz#940cb82fccfa84e8ff2f3fdf293fe78016beccd1" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +stringstream@~0.0.4: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + +strip-json-comments@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^3.1.2: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +tap-mocha-reporter@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tap-mocha-reporter/-/tap-mocha-reporter-2.0.1.tgz#c70316173d6e3a16c58e1ba92d5d6cd8de58a12e" + dependencies: + color-support "^1.1.0" + debug "^2.1.3" + diff "^1.3.2" + escape-string-regexp "^1.0.3" + glob "^7.0.5" + js-yaml "^3.3.1" + tap-parser "^2.0.0" + unicode-length "^1.0.0" + optionalDependencies: + readable-stream "^2.1.5" + +tap-parser@^2.0.0, tap-parser@^2.2.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/tap-parser/-/tap-parser-2.2.3.tgz#ade6e96e37bfd38ce0f162da067f34034f068b01" + dependencies: + events-to-array "^1.0.1" + js-yaml "^3.2.7" + optionalDependencies: + readable-stream "^2" + +tap@^7.0.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/tap/-/tap-7.1.2.tgz#dfac3ecf14ac8547bbad25bbd16cf2c3743f65cf" + dependencies: + bluebird "^3.3.1" + clean-yaml-object "^0.1.0" + color-support "^1.1.0" + coveralls "^2.11.2" + deeper "^2.1.0" + foreground-child "^1.3.3" + glob "^7.0.0" + isexe "^1.0.0" + js-yaml "^3.3.1" + nyc "^7.1.0" + only-shallow "^1.0.2" + opener "^1.4.1" + os-homedir "1.0.1" + readable-stream "^2.0.2" + signal-exit "^3.0.0" + stack-utils "^0.4.0" + tap-mocha-reporter "^2.0.0" + tap-parser "^2.2.0" + tmatch "^2.0.1" + +test-exclude@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-1.1.0.tgz#f5ddd718927b12fd02f270a0aa939ceb6eea4151" + dependencies: + arrify "^1.0.1" + lodash.assign "^4.0.9" + micromatch "^2.3.8" + read-pkg-up "^1.0.1" + require-main-filename "^1.0.1" + +tiny-lr-fork@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/tiny-lr-fork/-/tiny-lr-fork-0.0.5.tgz#1e99e1e2a8469b736ab97d97eefa98c71f76ed0a" + dependencies: + debug "~0.7.0" + faye-websocket "~0.4.3" + noptify "~0.0.3" + qs "~0.5.2" + +tmatch@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tmatch/-/tmatch-2.0.1.tgz#0c56246f33f30da1b8d3d72895abaf16660f38cf" + +to-fast-properties@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320" + +tough-cookie@~2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" + dependencies: + punycode "^1.4.1" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tunnel-agent@~0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +uglify-js@^2.6: + version "2.8.16" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.16.tgz#d286190b6eefc6fd65eb0ecac6551e0b0e8839a4" + dependencies: + source-map "~0.5.1" + yargs "~3.10.0" + optionalDependencies: + uglify-to-browserify "~1.0.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + +underscore.string@~2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.2.1.tgz#d7c0fa2af5d5a1a67f4253daee98132e733f0f19" + +underscore.string@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.3.3.tgz#71c08bf6b428b1133f37e78fa3a21c82f7329b0d" + +underscore.string@~2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.4.0.tgz#8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b" + +underscore@1.6.x: + version "1.6.0" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" + +underscore@~1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" + +unicode-length@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/unicode-length/-/unicode-length-1.0.3.tgz#5ada7a7fed51841a418a328cf149478ac8358abb" + dependencies: + punycode "^1.3.2" + strip-ansi "^3.0.1" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +uuid@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" + +validate-npm-package-license@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + dependencies: + spdx-correct "~1.0.0" + spdx-expression-parse "~1.0.0" + +verror@1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" + dependencies: + extsprintf "1.0.2" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + +which@^1.2.4, which@^1.2.9: + version "1.2.14" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" + dependencies: + isexe "^2.0.0" + +which@~1.0.5: + version "1.0.9" + resolved "https://registry.yarnpkg.com/which/-/which-1.0.9.tgz#460c1da0f810103d0321a9b633af9e575e64486f" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + +window-size@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write-file-atomic@^1.1.4: + version "1.3.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.1.tgz#7d45ba32316328dd1ec7d90f60ebc0d845bb759a" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" + +xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +yallist@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs-parser@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" + dependencies: + camelcase "^3.0.0" + lodash.assign "^4.0.6" + +yargs@^4.8.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" + dependencies: + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + lodash.assign "^4.0.3" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.1" + which-module "^1.0.0" + window-size "^0.2.0" + y18n "^3.2.1" + yargs-parser "^2.4.1" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" From fb5d901fe6a7e427594ae562edef665eef9b3603 Mon Sep 17 00:00:00 2001 From: Anand B Pillai Date: Tue, 4 Apr 2017 22:24:41 +0530 Subject: [PATCH 530/666] Fixing tests --- junction/templates/account/email.html | 2 +- junction/templates/account/email_confirm.html | 2 +- junction/templates/account/logout.html | 2 +- junction/templates/account/password_change.html | 2 +- junction/templates/account/password_reset.html | 2 +- junction/templates/account/password_reset_from_key.html | 2 +- junction/templates/account/password_reset_from_key_done.html | 2 +- junction/templates/account/password_set.html | 2 +- junction/templates/account/signup.html | 2 +- junction/templates/account/signup_closed.html | 2 +- junction/templates/openid/login.html | 2 +- junction/templates/proposals/closed.html | 3 +-- junction/templates/socialaccount/connections.html | 2 +- junction/templates/socialaccount/login_cancelled.html | 2 +- junction/templates/socialaccount/signup.html | 2 +- 15 files changed, 15 insertions(+), 16 deletions(-) diff --git a/junction/templates/account/email.html b/junction/templates/account/email.html index 559a16ab..42566569 100644 --- a/junction/templates/account/email.html +++ b/junction/templates/account/email.html @@ -1,6 +1,6 @@ {% extends "account/base.html" %} {% load i18n %} -{% load url from future %} + {% load django_bootstrap_breadcrumbs %} diff --git a/junction/templates/account/email_confirm.html b/junction/templates/account/email_confirm.html index 60443976..3afaf6fa 100644 --- a/junction/templates/account/email_confirm.html +++ b/junction/templates/account/email_confirm.html @@ -1,5 +1,5 @@ {% extends "account/base.html" %} -{% load url from future %} + {% load i18n %} {% load account %} {% load django_bootstrap_breadcrumbs %} diff --git a/junction/templates/account/logout.html b/junction/templates/account/logout.html index 24d8e9a8..080705c7 100644 --- a/junction/templates/account/logout.html +++ b/junction/templates/account/logout.html @@ -1,5 +1,5 @@ {% extends "account/base.html" %} -{% load url from future %} + {% load i18n %} {% load django_bootstrap_breadcrumbs %} diff --git a/junction/templates/account/password_change.html b/junction/templates/account/password_change.html index ccebff44..4c871d80 100644 --- a/junction/templates/account/password_change.html +++ b/junction/templates/account/password_change.html @@ -1,5 +1,5 @@ {% extends "account/base.html" %} -{% load url from future %} + {% load i18n %} {% load django_bootstrap_breadcrumbs %} diff --git a/junction/templates/account/password_reset.html b/junction/templates/account/password_reset.html index c16f71d9..82bf8d95 100644 --- a/junction/templates/account/password_reset.html +++ b/junction/templates/account/password_reset.html @@ -1,7 +1,7 @@ {% extends "account/base.html" %} {% load i18n %} {% load account %} -{% load url from future %} + {% load django_bootstrap_breadcrumbs %} {% block head_title %}{% trans "Password Reset" %} · {{ block.super }}{% endblock %} diff --git a/junction/templates/account/password_reset_from_key.html b/junction/templates/account/password_reset_from_key.html index ccd6cc10..e0278e52 100644 --- a/junction/templates/account/password_reset_from_key.html +++ b/junction/templates/account/password_reset_from_key.html @@ -1,5 +1,5 @@ {% extends "account/base.html" %} -{% load url from future %} + {% load django_bootstrap_breadcrumbs %} {% load i18n %} diff --git a/junction/templates/account/password_reset_from_key_done.html b/junction/templates/account/password_reset_from_key_done.html index 510c1a2a..a1e89b1a 100644 --- a/junction/templates/account/password_reset_from_key_done.html +++ b/junction/templates/account/password_reset_from_key_done.html @@ -1,5 +1,5 @@ {% extends "account/base.html" %} -{% load url from future %} + {% load django_bootstrap_breadcrumbs %} {% load i18n %} diff --git a/junction/templates/account/password_set.html b/junction/templates/account/password_set.html index c6add98a..cb62150c 100644 --- a/junction/templates/account/password_set.html +++ b/junction/templates/account/password_set.html @@ -1,5 +1,5 @@ {% extends "account/base.html" %} -{% load url from future %} + {% load i18n %} {% load django_bootstrap_breadcrumbs %} diff --git a/junction/templates/account/signup.html b/junction/templates/account/signup.html index 06042769..0179f09c 100644 --- a/junction/templates/account/signup.html +++ b/junction/templates/account/signup.html @@ -1,6 +1,6 @@ {% extends "account/base.html" %} {% load i18n %} -{% load url from future %} + {% load django_bootstrap_breadcrumbs %} {% block head_title %}{% trans "Sign Up" %} · {{ block.super }}{% endblock %} diff --git a/junction/templates/account/signup_closed.html b/junction/templates/account/signup_closed.html index 3ff1b0cf..e10f9c37 100644 --- a/junction/templates/account/signup_closed.html +++ b/junction/templates/account/signup_closed.html @@ -1,5 +1,5 @@ {% extends "account/base.html" %} -{% load url from future %} + {% load i18n %} {% load django_bootstrap_breadcrumbs %} diff --git a/junction/templates/openid/login.html b/junction/templates/openid/login.html index 2fbe793d..c1ebe6ab 100644 --- a/junction/templates/openid/login.html +++ b/junction/templates/openid/login.html @@ -1,5 +1,5 @@ {% extends "openid/base.html" %} -{% load url from future %} + {% load i18n %} {% block head_title %}OpenID Sign In{% endblock %} diff --git a/junction/templates/proposals/closed.html b/junction/templates/proposals/closed.html index dd0cb7f3..d01ee49b 100644 --- a/junction/templates/proposals/closed.html +++ b/junction/templates/proposals/closed.html @@ -2,7 +2,6 @@ {% load bootstrap3 %} {% load static from staticfiles %} {% load django_bootstrap_breadcrumbs %} -{% load url from future %} {% load i18n %} {% block head_title %} CFP submission is closed | {{ block.super }} {% endblock %} @@ -20,7 +19,7 @@

    {% trans "CFP submission is closed" %}

    -

    {% trans "We are no longer accepting proposals. You can prepare a session for open spaces or flash talks." %}

    +

    {% trans "We are no longer accepting proposals. You can prepare a session for open spaces or flash talks." %}

    diff --git a/junction/templates/socialaccount/connections.html b/junction/templates/socialaccount/connections.html index 57856d0b..cf7ce780 100644 --- a/junction/templates/socialaccount/connections.html +++ b/junction/templates/socialaccount/connections.html @@ -1,6 +1,6 @@ {% extends "socialaccount/base.html" %} {% load i18n %} -{% load url from future %} + {% load django_bootstrap_breadcrumbs %} {% block breadcrumbs %} diff --git a/junction/templates/socialaccount/login_cancelled.html b/junction/templates/socialaccount/login_cancelled.html index 73113701..60896199 100644 --- a/junction/templates/socialaccount/login_cancelled.html +++ b/junction/templates/socialaccount/login_cancelled.html @@ -1,5 +1,5 @@ {% extends "socialaccount/base.html" %} -{% load url from future %} + {% load i18n %} {% block head_title %}{% trans "Login Cancelled" %}{% endblock %} diff --git a/junction/templates/socialaccount/signup.html b/junction/templates/socialaccount/signup.html index 06ef3e25..53b8566b 100644 --- a/junction/templates/socialaccount/signup.html +++ b/junction/templates/socialaccount/signup.html @@ -1,5 +1,5 @@ {% extends "socialaccount/base.html" %} -{% load url from future %} + {% load i18n %} {% block head_title %}{% trans "Signup" %}{% endblock %} From c17521e55fee312af809994917785a771842287e Mon Sep 17 00:00:00 2001 From: shweta Date: Tue, 4 Apr 2017 23:05:43 +0530 Subject: [PATCH 531/666] flake8 error resolves --- junction/base/monkey.py | 3 ++- .../migrations/0002_auto_20170404_2243.py | 19 +++++++++++++++++++ junction/urls.py | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 junction/tickets/migrations/0002_auto_20170404_2243.py diff --git a/junction/base/monkey.py b/junction/base/monkey.py index f5bd8014..6821d0a0 100644 --- a/junction/base/monkey.py +++ b/junction/base/monkey.py @@ -37,7 +37,8 @@ def patch_urlresolvers(): old_reverse = urlresolvers.reverse def new_reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None): - path = old_reverse(viewname, urlconf=urlconf, args=args, kwargs=kwargs, prefix=prefix, current_app=current_app) + path = old_reverse(viewname, urlconf=urlconf, args=args, kwargs=kwargs, + prefix=prefix, current_app=current_app) if is_absolute_url(path): return path diff --git a/junction/tickets/migrations/0002_auto_20170404_2243.py b/junction/tickets/migrations/0002_auto_20170404_2243.py new file mode 100644 index 00000000..285e98a2 --- /dev/null +++ b/junction/tickets/migrations/0002_auto_20170404_2243.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tickets', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='ticket', + name='email', + field=models.EmailField(max_length=254), + ), + ] diff --git a/junction/urls.py b/junction/urls.py index 16ae6402..8cd15c9f 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -2,8 +2,8 @@ from __future__ import absolute_import, unicode_literals # Third Party Stuff -from django.conf import settings from django.conf.urls import include, patterns, url +from django.conf import settings from django.conf.urls.static import static from django.contrib import admin from django.views.generic.base import RedirectView, TemplateView From f0568887a73456c2fc2f41148154f2de1b67fc29 Mon Sep 17 00:00:00 2001 From: shweta Date: Wed, 5 Apr 2017 20:26:55 +0530 Subject: [PATCH 532/666] flake8 error resolved --- junction/base/monkey.py | 9 ++------- junction/urls.py | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/junction/base/monkey.py b/junction/base/monkey.py index 3364f0d8..cc911004 100644 --- a/junction/base/monkey.py +++ b/junction/base/monkey.py @@ -36,15 +36,10 @@ def patch_urlresolvers(): old_reverse = urlresolvers.reverse -<<<<<<< HEAD - def new_reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None): + def new_reverse(viewname, urlconf=None, args=None, kwargs=None, + prefix=None, current_app=None): path = old_reverse(viewname, urlconf=urlconf, args=args, kwargs=kwargs, prefix=prefix, current_app=current_app) -======= - - def new_reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None): - path = old_reverse(viewname, urlconf=urlconf, args=args, kwargs=kwargs, current_app=current_app) ->>>>>>> fb5d901fe6a7e427594ae562edef665eef9b3603 if is_absolute_url(path): return path diff --git a/junction/urls.py b/junction/urls.py index 9d12b113..a5b9caea 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -4,7 +4,7 @@ import django.views.defaults # Third Party Stuff -from django.conf.urls import include, patterns, url +from django.conf.urls import include, url from django.conf import settings from django.conf.urls.static import static from django.contrib import admin From 2c9225f36853d9c79b5fe0f8583d75e7d30526a2 Mon Sep 17 00:00:00 2001 From: Anand B Pillai Date: Wed, 5 Apr 2017 22:50:02 +0530 Subject: [PATCH 533/666] Prefix argument not needed --- junction/base/monkey.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/junction/base/monkey.py b/junction/base/monkey.py index cc911004..53527ef7 100644 --- a/junction/base/monkey.py +++ b/junction/base/monkey.py @@ -36,10 +36,9 @@ def patch_urlresolvers(): old_reverse = urlresolvers.reverse - def new_reverse(viewname, urlconf=None, args=None, kwargs=None, - prefix=None, current_app=None): + def new_reverse(viewname, urlconf=None, args=None, kwargs=None,current_app=None): path = old_reverse(viewname, urlconf=urlconf, args=args, kwargs=kwargs, - prefix=prefix, current_app=current_app) + current_app=current_app) if is_absolute_url(path): return path From 5309ae2bda7d90db3c38d9d65b7450fe973f0bf2 Mon Sep 17 00:00:00 2001 From: Anand B Pillai Date: Wed, 5 Apr 2017 22:51:55 +0530 Subject: [PATCH 534/666] Migrations - merge branches to fix tests --- junction/tickets/migrations/0004_merge.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 junction/tickets/migrations/0004_merge.py diff --git a/junction/tickets/migrations/0004_merge.py b/junction/tickets/migrations/0004_merge.py new file mode 100644 index 00000000..b7571e3c --- /dev/null +++ b/junction/tickets/migrations/0004_merge.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2017-04-05 17:12 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('tickets', '0003_merge'), + ('tickets', '0002_auto_20170404_2243'), + ] + + operations = [ + ] From 1bf74a9046f4e05113435eeb3588a17b9e3fcede Mon Sep 17 00:00:00 2001 From: Anand B Pillai Date: Wed, 5 Apr 2017 22:56:16 +0530 Subject: [PATCH 535/666] Fixing flake8 error --- junction/base/monkey.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/base/monkey.py b/junction/base/monkey.py index 53527ef7..b81837da 100644 --- a/junction/base/monkey.py +++ b/junction/base/monkey.py @@ -36,7 +36,7 @@ def patch_urlresolvers(): old_reverse = urlresolvers.reverse - def new_reverse(viewname, urlconf=None, args=None, kwargs=None,current_app=None): + def new_reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None): path = old_reverse(viewname, urlconf=urlconf, args=args, kwargs=kwargs, current_app=current_app) if is_absolute_url(path): From 5f34d02c2f66c1b3c6e1fbe68e1ca5044e660d77 Mon Sep 17 00:00:00 2001 From: shweta Date: Sun, 9 Apr 2017 22:05:32 +0530 Subject: [PATCH 536/666] suggestion addressed for settings/common.py --- settings/common.py | 1 - 1 file changed, 1 deletion(-) diff --git a/settings/common.py b/settings/common.py index 5e5ca464..a25fc93f 100644 --- a/settings/common.py +++ b/settings/common.py @@ -18,7 +18,6 @@ ADMINS = () -DEBUG = True # Absolute Url of frontend hosted site. Used to render the urls in templattes, # static and media files appropriately. e.g 'https://in.pycon.org/junction' From ba50adc5f3e2a151f30a17a356dbc2fb9718c0ab Mon Sep 17 00:00:00 2001 From: Rahul Arora Date: Sun, 14 May 2017 17:01:03 +0530 Subject: [PATCH 537/666] Enhancement: Sending emails via Celery in Proposals --- junction/proposals/comments_views.py | 2 +- junction/proposals/services.py | 121 ++++++++++++++------------- junction/proposals/views.py | 9 +- settings/dev.py | 30 +++++++ 4 files changed, 99 insertions(+), 63 deletions(-) create mode 100644 settings/dev.py diff --git a/junction/proposals/comments_views.py b/junction/proposals/comments_views.py index 689a9ae8..0023e115 100644 --- a/junction/proposals/comments_views.py +++ b/junction/proposals/comments_views.py @@ -41,7 +41,7 @@ def create_proposal_comment(request, conference_slug, proposal_slug): ) host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META.get('HTTP_HOST')) - send_mail_for_new_comment(proposal_comment, host) + send_mail_for_new_comment.delay(proposal_comment.id, host) redirect_url = reverse('proposal-detail', args=[conference.slug, proposal.slug]) diff --git a/junction/proposals/services.py b/junction/proposals/services.py index d3998986..982a8dc7 100644 --- a/junction/proposals/services.py +++ b/junction/proposals/services.py @@ -9,16 +9,51 @@ # Third Party Stuff from django.conf import settings from markdown2 import markdown +from celery import shared_task # Junction Stuff from junction.base.emailer import send_email from junction.base.constants import ProposalStatus -from .models import ProposalSection, ProposalSectionReviewer +from .models import Proposal, ProposalComment, ProposalSection, ProposalSectionReviewer +from junction.conferences.models import Conference logger = logging.getLogger(__name__) +def _get_proposal_section_reviewers(proposal): + proposal_reviewers = set(ProposalSectionReviewer.objects.filter( + proposal_section=proposal.proposal_section)) + recipients = {proposal_reviewer.conference_reviewer.reviewer + for proposal_reviewer in proposal_reviewers} + return recipients + + +def _arrange_proposals_by_section(proposal_qs): + res = collections.defaultdict(list) + for proposal in proposal_qs: + res[proposal.proposal_section.name].append(proposal) + return res + + +def group_proposals_by_reveiew_state(conf, state='reviewed'): + reviewed_qs = conf.proposal_set.filter( + status=ProposalStatus.PUBLIC).select_related( + 'proposal_type', 'proposal_section', + 'proposalsection').filter(proposalcomment__private=True, + proposalcomment__deleted=False) + if state == 'reviewed': + proposal_qs = reviewed_qs.distinct() + return _arrange_proposals_by_section(proposal_qs) + else: + ids = reviewed_qs.values_list('id').distinct() + qs = conf.proposal_set.filter( + status=ProposalStatus.PUBLIC).select_related( + 'proposal_type', 'proposal_section', + 'proposalsection').exclude(pk__in=ids) + return _arrange_proposals_by_section(qs) + + def markdown_to_html(md): """ Convert given markdown to html. @@ -28,7 +63,28 @@ def markdown_to_html(md): return markdown(md) -def send_mail_for_new_comment(proposal_comment, host): +def comment_recipients(proposal_comment): + proposal = proposal_comment.proposal + if proposal_comment.reviewer: + recipients = _get_proposal_section_reviewers( + proposal=proposal) + elif proposal_comment.private: + recipients = _get_proposal_section_reviewers( + proposal=proposal) + recipients.add(proposal.author) + else: + recipients = { + comment.commenter + for comment in proposal.proposalcomment_set + .all().select_related('commenter')} + recipients.add(proposal.author) + + return recipients + + +@shared_task(ignore_result=True) +def send_mail_for_new_comment(proposal_comment_id, host): + proposal_comment = ProposalComment.objects.get(id=proposal_comment_id) proposal = proposal_comment.proposal login_url = '{}?next={}'.format(settings.LOGIN_URL, proposal.get_absolute_url()) send_to = comment_recipients(proposal_comment) @@ -51,26 +107,9 @@ def send_mail_for_new_comment(proposal_comment, host): 'comment_type': comment_type}) -def comment_recipients(proposal_comment): - proposal = proposal_comment.proposal - if proposal_comment.reviewer: - recipients = _get_proposal_section_reviewers( - proposal=proposal) - elif proposal_comment.private: - recipients = _get_proposal_section_reviewers( - proposal=proposal) - recipients.add(proposal.author) - else: - recipients = { - comment.commenter - for comment in proposal.proposalcomment_set - .all().select_related('commenter')} - recipients.add(proposal.author) - - return recipients - - -def send_mail_for_new_proposal(proposal, host): +@shared_task(ignore_result=True) +def send_mail_for_new_proposal(proposal_id, host): + proposal = Proposal.objects.get(id=proposal_id) proposal_section = ProposalSection.objects.get( pk=proposal.proposal_section_id) send_to = [p.conference_reviewer.reviewer for p in @@ -92,18 +131,13 @@ def send_mail_for_new_proposal(proposal, host): 'login_url': login_url}) -def _get_proposal_section_reviewers(proposal): - proposal_reviewers = set(ProposalSectionReviewer.objects.filter( - proposal_section=proposal.proposal_section)) - recipients = {proposal_reviewer.conference_reviewer.reviewer - for proposal_reviewer in proposal_reviewers} - return recipients - - -def send_mail_for_proposal_content(conference, proposal, host): +@shared_task(ignore_result=True) +def send_mail_for_proposal_content(conference_id, proposal_id, host): """ Send mail to proposal author to upload content for proposal. """ + conference = Conference.objects.get(id=conference_id) + proposal = Proposal.objects.get(id=proposal_id) login_url = '{}?next={}'.format(settings.LOGIN_URL, proposal.get_absolute_url()) author = proposal.author author_name = author.get_full_name() or author.username @@ -116,28 +150,3 @@ def send_mail_for_proposal_content(conference, proposal, host): } return send_email(to=author, template_dir='proposals/email/upload_content', context=context) - - -def group_proposals_by_reveiew_state(conf, state='reviewed'): - reviewed_qs = conf.proposal_set.filter( - status=ProposalStatus.PUBLIC).select_related( - 'proposal_type', 'proposal_section', - 'proposalsection').filter(proposalcomment__private=True, - proposalcomment__deleted=False) - if state == 'reviewed': - proposal_qs = reviewed_qs.distinct() - return _arrange_proposals_by_section(proposal_qs) - else: - ids = reviewed_qs.values_list('id').distinct() - qs = conf.proposal_set.filter( - status=ProposalStatus.PUBLIC).select_related( - 'proposal_type', 'proposal_section', - 'proposalsection').exclude(pk__in=ids) - return _arrange_proposals_by_section(qs) - - -def _arrange_proposals_by_section(proposal_qs): - res = collections.defaultdict(list) - for proposal in proposal_qs: - res[proposal.proposal_section.name].append(proposal) - return res diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 26c76aa5..24f20e00 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -131,7 +131,7 @@ def create_proposal(request, conference_slug): proposal_type_id=form.cleaned_data['proposal_type'], proposal_section_id=form.cleaned_data['proposal_section']) host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META.get('HTTP_HOST')) - send_mail_for_new_proposal(proposal, host) + send_mail_for_new_proposal.delay(proposal.id, host) return HttpResponseRedirect(reverse('proposal-detail', args=[conference.slug, proposal.slug])) @@ -387,12 +387,9 @@ def proposal_upload_content(request, conference_slug, slug): raise PermissionDenied host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META['HTTP_HOST']) - response = send_mail_for_proposal_content(conference, proposal, host) + send_mail_for_proposal_content.delay(conference.id, proposal.id, host) - if response == 1: - message = 'Email sent successfully.' - else: - message = 'There is problem in sending mail. Please contact conference chair.' + message = 'Email sent successfully.' return HttpResponse(message) diff --git a/settings/dev.py b/settings/dev.py new file mode 100644 index 00000000..73a4d60a --- /dev/null +++ b/settings/dev.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +import os + +from .common import * # noqa + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(ROOT_DIR, 'db.sqlite3'), + } +} + +ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'http' + +TEMPLATE_CONTEXT_PROCESSORS += ( + "django.core.context_processors.debug", +) + +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + +INSTALLED_APPS += ('django_extensions',) + +# settings for celery +BROKER_URL = os.environ.get("BROKER_URL", "redis://127.0.0.1:6379/0") +CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", 'redis://127.0.0.1:6379/0') From 8b77e1e865d72720a602b7b7cc5912cb852d68cf Mon Sep 17 00:00:00 2001 From: Rahul Arora Date: Sun, 14 May 2017 17:14:59 +0530 Subject: [PATCH 538/666] Revert back to original settings for Celery Broker --- settings/dev.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings/dev.py b/settings/dev.py index 73a4d60a..75ac5bc9 100644 --- a/settings/dev.py +++ b/settings/dev.py @@ -26,5 +26,5 @@ INSTALLED_APPS += ('django_extensions',) # settings for celery -BROKER_URL = os.environ.get("BROKER_URL", "redis://127.0.0.1:6379/0") -CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", 'redis://127.0.0.1:6379/0') +BROKER_URL = os.environ.get("BROKER_URL", "redis://redis:6379/0") +CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", 'redis://redis:6379/0') From 3271c0c466a561ca2e063e73fa1fd9d58914bbd0 Mon Sep 17 00:00:00 2001 From: Rahul Arora Date: Sun, 14 May 2017 22:08:02 +0530 Subject: [PATCH 539/666] Modified travis.yml to install redis --- .travis.yml | 6 ++++++ README.md | 6 +++++- settings/dev.py | 4 ++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8f4362db..7b67d333 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,3 +31,9 @@ notifications: email: on_success: change # [always|never|change] on_failure: always # [always|never|change] + +services: + - redis-server + +before_script: + - celery -A junction worker -l info diff --git a/README.md b/README.md index 912c1c79..87646900 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,14 @@ It is advised to install all the requirements inside [virtualenv], use [virtuale [virtualenvwrapper]: https://virtualenvwrapper.readthedocs.org/en/latest/ ``` -sudo apt-get install libpq-dev python-dev +sudo apt-get update +sudo apt-get upgrade +sudo apt-get install libpq-dev python-dev build-essential tcl pip install -r requirements-dev.txt cp settings/dev.py.sample settings/dev.py python manage.py migrate --noinput python manage.py sample_data +sudo apt-get -y install redis-server ``` Initial auth data: admin/123123 @@ -161,6 +164,7 @@ Contributing
    Vignesh Sarma K (@vigneshsarma)
    Vijay (@vnbang2003)
    Vinay Singh (@vinay13) +
    Rahul Arora (@rahulxxarora) diff --git a/settings/dev.py b/settings/dev.py index 75ac5bc9..73a4d60a 100644 --- a/settings/dev.py +++ b/settings/dev.py @@ -26,5 +26,5 @@ INSTALLED_APPS += ('django_extensions',) # settings for celery -BROKER_URL = os.environ.get("BROKER_URL", "redis://redis:6379/0") -CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", 'redis://redis:6379/0') +BROKER_URL = os.environ.get("BROKER_URL", "redis://127.0.0.1:6379/0") +CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", 'redis://127.0.0.1:6379/0') From 36c315649c15e79e2c32c383426622fde8265dc8 Mon Sep 17 00:00:00 2001 From: Rahul Arora Date: Sun, 14 May 2017 22:28:46 +0530 Subject: [PATCH 540/666] Modified travis file to start celery worker --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7b67d333..a8a3e307 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,4 +36,4 @@ services: - redis-server before_script: - - celery -A junction worker -l info + - celery -A junction worker -l info & From a4ff804837144e5035935c6a777afe9ef4587012 Mon Sep 17 00:00:00 2001 From: Rahul Arora Date: Wed, 17 May 2017 01:24:31 +0530 Subject: [PATCH 541/666] Added USE_ASYNC_FOR_EMAIL to settings --- junction/proposals/comments_views.py | 6 +++++- junction/proposals/views.py | 17 ++++++++++++++--- settings/common.py | 2 ++ settings/dev.py | 4 ++-- settings/dev.py.sample | 8 ++++---- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/junction/proposals/comments_views.py b/junction/proposals/comments_views.py index 0023e115..4d293d98 100644 --- a/junction/proposals/comments_views.py +++ b/junction/proposals/comments_views.py @@ -41,7 +41,11 @@ def create_proposal_comment(request, conference_slug, proposal_slug): ) host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META.get('HTTP_HOST')) - send_mail_for_new_comment.delay(proposal_comment.id, host) + + if settings.USE_ASYNC_FOR_EMAIL: + send_mail_for_new_comment.delay(proposal_comment.id, host) + else: + send_mail_for_new_comment(proposal_comment.id, host) redirect_url = reverse('proposal-detail', args=[conference.slug, proposal.slug]) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 24f20e00..e810c3bd 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -131,7 +131,11 @@ def create_proposal(request, conference_slug): proposal_type_id=form.cleaned_data['proposal_type'], proposal_section_id=form.cleaned_data['proposal_section']) host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META.get('HTTP_HOST')) - send_mail_for_new_proposal.delay(proposal.id, host) + + if settings.USE_ASYNC_FOR_EMAIL: + send_mail_for_new_proposal.delay(proposal.id, host) + else: + send_mail_for_new_proposal(proposal.id, host) return HttpResponseRedirect(reverse('proposal-detail', args=[conference.slug, proposal.slug])) @@ -387,9 +391,16 @@ def proposal_upload_content(request, conference_slug, slug): raise PermissionDenied host = '{}://{}'.format(settings.SITE_PROTOCOL, request.META['HTTP_HOST']) - send_mail_for_proposal_content.delay(conference.id, proposal.id, host) - message = 'Email sent successfully.' + if settings.USE_ASYNC_FOR_EMAIL: + send_mail_for_proposal_content.delay(conference.id, proposal.id, host) + message = 'Email sent successfully.' + else: + response = send_mail_for_proposal_content(conference.id, proposal.id, host) + if response == 1: + message = 'Email sent successfully.' + else: + message = 'There is problem in sending mail. Please contact conference chair.' return HttpResponse(message) diff --git a/settings/common.py b/settings/common.py index a25fc93f..ca9792b3 100644 --- a/settings/common.py +++ b/settings/common.py @@ -247,3 +247,5 @@ EXPLARA_API_TOKEN = "shjbalkfbdskjlbdskljbdskaljfb" QR_CODES_DIR = ROOT_DIR + '/qr_files' + +USE_ASYNC_FOR_EMAIL = False diff --git a/settings/dev.py b/settings/dev.py index 73a4d60a..75ac5bc9 100644 --- a/settings/dev.py +++ b/settings/dev.py @@ -26,5 +26,5 @@ INSTALLED_APPS += ('django_extensions',) # settings for celery -BROKER_URL = os.environ.get("BROKER_URL", "redis://127.0.0.1:6379/0") -CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", 'redis://127.0.0.1:6379/0') +BROKER_URL = os.environ.get("BROKER_URL", "redis://redis:6379/0") +CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", 'redis://redis:6379/0') diff --git a/settings/dev.py.sample b/settings/dev.py.sample index ec3e126d..73a4d60a 100644 --- a/settings/dev.py.sample +++ b/settings/dev.py.sample @@ -15,7 +15,7 @@ DATABASES = { } } -ACCOUNT_DEFAULT_HTTP_PROTOCOL='http' +ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'http' TEMPLATE_CONTEXT_PROCESSORS += ( "django.core.context_processors.debug", @@ -25,6 +25,6 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' INSTALLED_APPS += ('django_extensions',) -#settings for celery -BROKER_URL = os.environ.get("BROKER_URL", "redis://redis:6379/0") -CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", 'redis://redis:6379/0') +# settings for celery +BROKER_URL = os.environ.get("BROKER_URL", "redis://127.0.0.1:6379/0") +CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", 'redis://127.0.0.1:6379/0') From 408f0c03910ea4aff748c2bdadafe1bd8585f74b Mon Sep 17 00:00:00 2001 From: kracekumar Date: Wed, 17 May 2017 15:17:10 +0530 Subject: [PATCH 542/666] Add mock dep and remove markdown extension --- requirements.txt | 1 + settings/common.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 28514805..26116232 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,6 +31,7 @@ oauthlib==1.1.2 python-openid==2.2.5 requests==2.7.0 requests-oauthlib==0.5.0 +mock==1.10 # Django all auth needs # Admin # ------------------------------------------------- diff --git a/settings/common.py b/settings/common.py index a25fc93f..a3b81956 100644 --- a/settings/common.py +++ b/settings/common.py @@ -226,7 +226,7 @@ SITE_PROTOCOL = 'http' -MARKDOWN_EXTENSIONS = ['linkify'] +#MARKDOWN_EXTENSIONS = ['linkify'] # twitter settings From cb24c5c77e12dedd789d045f3e6b6a7903320c9f Mon Sep 17 00:00:00 2001 From: kracekumar Date: Wed, 17 May 2017 15:22:18 +0530 Subject: [PATCH 543/666] Remove mock requirement in dev requirements --- requirements-dev.txt | 1 - requirements.txt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 1fd5aca8..3a386fe1 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,6 @@ # Testing # ------------------------------------------------- -mock==2.0.0 # Fix for travis CI tests failing # Ref: https://github.com/FactoryBoy/factory_boy/issues/334#issuecomment-267696136 fake-factory==0.7.4 diff --git a/requirements.txt b/requirements.txt index 26116232..ceb3961e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,7 +31,7 @@ oauthlib==1.1.2 python-openid==2.2.5 requests==2.7.0 requests-oauthlib==0.5.0 -mock==1.10 # Django all auth needs +mock==2.0.0 # Django all auth needs # Admin # ------------------------------------------------- From 8310e0c9132e323b0ced3881b2f63ac780310daf Mon Sep 17 00:00:00 2001 From: kracekumar Date: Wed, 17 May 2017 15:34:02 +0530 Subject: [PATCH 544/666] Flake8 nicety --- settings/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/common.py b/settings/common.py index a3b81956..6ff8a9f6 100644 --- a/settings/common.py +++ b/settings/common.py @@ -226,7 +226,7 @@ SITE_PROTOCOL = 'http' -#MARKDOWN_EXTENSIONS = ['linkify'] +# MARKDOWN_EXTENSIONS = ['linkify'] # twitter settings From 5263dcb55ba0cdd100b0978eb3d107ea23d141a9 Mon Sep 17 00:00:00 2001 From: kracekumar Date: Thu, 18 May 2017 14:11:00 +0530 Subject: [PATCH 545/666] Fix social accounts in login page --- junction/templates/account/login.html | 4 +++- junction/templates/socialaccount/snippets/provider_list.html | 3 ++- settings/common.py | 3 --- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/junction/templates/account/login.html b/junction/templates/account/login.html index 564283b3..0b81a8a1 100644 --- a/junction/templates/account/login.html +++ b/junction/templates/account/login.html @@ -2,6 +2,7 @@ {% load i18n %} {% load account %} {% load django_bootstrap_breadcrumbs %} +{% load account socialaccount %} {% block head_title %}{% trans "Sign In" %} · {{ block.super }}{% endblock %} @@ -17,7 +18,8 @@
    diff --git a/junction/templates/proposals/partials/proposal-list--review-items.html b/junction/templates/proposals/partials/proposal-list--review-items.html index 1e698e0f..cf961759 100644 --- a/junction/templates/proposals/partials/proposal-list--review-items.html +++ b/junction/templates/proposals/partials/proposal-list--review-items.html @@ -82,7 +82,7 @@

    {{ proposal.author.username }} {% endif %} |  - {{ proposal.created_at|date:"d M, Y" }} + {{ proposal.created_at|date:"d M, Y" }} diff --git a/junction/templates/proposals/partials/proposal-list--selected-items.html b/junction/templates/proposals/partials/proposal-list--selected-items.html index ed72f410..4a125f50 100644 --- a/junction/templates/proposals/partials/proposal-list--selected-items.html +++ b/junction/templates/proposals/partials/proposal-list--selected-items.html @@ -61,7 +61,7 @@

    {{ proposal.author.username }} {% endif %} |  - {{ proposal.created_at|date:"d M, Y" }} + {{ proposal.created_at|date:"d M, Y" }} From 549a08b85e2e6e7e18f0f6befb93ec2c40dc51c4 Mon Sep 17 00:00:00 2001 From: Sumit Chahal Date: Wed, 6 Sep 2017 23:37:05 +0530 Subject: [PATCH 554/666] Expand "Created on" tooltip to include exact time --- junction/templates/proposals/detail/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index c49a7cdb..71ff09c0 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -51,7 +51,7 @@

    {{ proposal.author.username }} {% endif %} |  - +

    From bb38eeffe85a4461a0df6b2abf5ef2fa213b5589 Mon Sep 17 00:00:00 2001 From: kracekumar Date: Sat, 23 Sep 2017 20:07:31 +0530 Subject: [PATCH 555/666] Filter conference proposals in the review page --- junction/proposals/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index e810c3bd..6aaf4374 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -271,7 +271,8 @@ def proposals_to_review(request, conference_slug): 'proposal_type', 'proposal_section', 'conference', 'author', ).filter(conference=conference).filter(status=ProposalStatus.PUBLIC) psr = ProposalSectionReviewer.objects.filter( - conference_reviewer__reviewer=request.user) + conference_reviewer__reviewer=request.user, + conference_reviewer__conference=conference) proposal_reviewer_sections = [p.proposal_section for p in psr] proposal_sections = conference.proposal_sections.all() proposal_types = conference.proposal_types.all() From e8cefd7910f807873a9f0d7650f6868ccffbeac0 Mon Sep 17 00:00:00 2001 From: kracekumar Date: Fri, 29 Sep 2017 12:48:14 +0530 Subject: [PATCH 556/666] Fix export votes --- junction/proposals/dashboard.py | 5 +++-- junction/proposals/views.py | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/junction/proposals/dashboard.py b/junction/proposals/dashboard.py index 640d636f..e3a7b845 100644 --- a/junction/proposals/dashboard.py +++ b/junction/proposals/dashboard.py @@ -301,6 +301,7 @@ def export_reviewer_votes(request, conference_slug): proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), reverse=True) vote_values_list = ProposalSectionReviewerVoteValue.objects.order_by( '-vote_value') + vote_values_list = [v.vote_value for v in vote_values_list] vote_values_desc = tuple(i.description for i in ProposalSectionReviewerVoteValue.objects.order_by('-vote_value')) header = ('Proposal Type', 'Title', 'Sum of reviewer votes', 'No. of reviewer votes') + \ @@ -327,11 +328,11 @@ def export_reviewer_votes(request, conference_slug): vote_details + (p.get_votes_count(), vote_comment,) if p.get_reviewer_votes_count_by_value( ProposalSectionReviewerVoteValue.objects.get( - vote_value=ProposalReviewVote.NOT_ALLOWED)) > 0: + vote_value=ProposalReviewVote.NOT_ALLOWED).vote_value) > 0: cell_format = book.add_format({'bg_color': 'red'}) elif p.get_reviewer_votes_count_by_value( ProposalSectionReviewerVoteValue.objects.get( - vote_value=ProposalReviewVote.MUST_HAVE)) > 2: + vote_value=ProposalReviewVote.MUST_HAVE).vote_value) > 2: cell_format = book.add_format({'bg_color': 'green'}) elif p.get_reviewer_votes_count() < 2: cell_format = book.add_format({'bg_color': 'yellow'}) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 6aaf4374..e529b945 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -286,7 +286,8 @@ def proposals_to_review(request, conference_slug): if p.proposal_section == section] proposals_to_review.append(s_items(section, section_proposals)) - form = ProposalsToReviewForm(conference=conference, proposal_sections=proposal_reviewer_sections) + form = ProposalsToReviewForm(conference=conference, + proposal_sections=proposal_reviewer_sections) context = { 'proposals_to_review': proposals_to_review, From 1c4db1b23d80307c1eb7718fb9fdf67779dab8af Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Sun, 1 Oct 2017 11:40:14 +0530 Subject: [PATCH 557/666] Sort proposals in reverse cronological order in dashboard --- junction/profiles/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/profiles/views.py b/junction/profiles/views.py index e377b405..2e704fbc 100644 --- a/junction/profiles/views.py +++ b/junction/profiles/views.py @@ -21,7 +21,7 @@ @require_http_methods(['GET']) def dashboard(request): conf_proposals = OrderedDict() - for conf in Conference.objects.order_by('end_date'): + for conf in Conference.objects.order_by('-end_date'): for proposal in conf.proposal_set.filter(author=request.user).all(): if conf.name in conf_proposals: conf_proposals[conf.name].append(proposal) From 052e0a058dbcd1009138856e4628858287d4c745 Mon Sep 17 00:00:00 2001 From: Shashank Aryan Date: Fri, 10 Nov 2017 16:53:40 +0530 Subject: [PATCH 558/666] psycopg2 version modified. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f998f0d6..aee6dfb1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ django-filter==1.0.1 # Persistent Store # ------------------------------------------------- -psycopg2==2.6.2 +psycopg2==2.7.3 redis==2.10.0 dj-database-url==0.4.1 From 981d33ee494964d7b26e366bbf8a36ec6900a922 Mon Sep 17 00:00:00 2001 From: Ananyo Maiti Date: Wed, 4 Jul 2018 18:35:48 +0530 Subject: [PATCH 559/666] Proposals: Improvements in Review Process Change form label and remove vote values from ProposalReviewerVote form Add filter for Proposal Section Reviwer Make radio buttons horizontally aligned in the Vote form Use nickname for showing votes and remove vote value from Reviwer dashboard Fix bug: Review Dashboard button not showing for section reviwer Remove Accept/reject proposal from Vote dashbaord for now Upgrade pytest version in CI Fixes #560 --- .travis.yml | 1 + junction/proposals/forms.py | 8 +++++--- .../proposals/templatetags/proposal_filters.py | 16 ++++++++++++---- junction/static/css/app.css | 2 +- junction/templates/proposals/list.html | 2 +- .../partials/proposal-list--votes-dashboard.html | 14 ++++++++------ 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index a8a3e307..4f35e5b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ install: - pip install pip==9.0.1 - pip install -r requirements-dev.txt --allow-all-external - pip install coveralls + - pip install --upgrade pytest env: - DJANGO_SETTINGS_MODULE="settings.test_settings" diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index f99315b4..d6eb52fb 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -53,8 +53,7 @@ def _get_proposal_section_reviewer_vote_choices(conference): for i in ProposalSectionReviewerVoteValue.objects.all(): if i.vote_value == 0 and not plus_zero_vote_setting_value: continue - values.append((i.vote_value, '{} ({})'.format( - i.description, i.vote_value))) + values.append((i.vote_value, '{}'.format(i.description))) return values @@ -155,7 +154,10 @@ class ProposalReviewerVoteForm(forms.Form): """ Used by ProposalSectionReviewers to vote on proposals. """ - vote_value = forms.ChoiceField(widget=forms.RadioSelect()) + vote_value = forms.ChoiceField( + widget=forms.RadioSelect(), + label="Do you think this proposal will make a good addition to PyCon India 2018?" + ) comment = forms.CharField( widget=forms.Textarea(attrs={'minlength': '30'}), help_text="Leave a comment justifying your vote.", diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index a6d5a4d1..e2b4013b 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -8,7 +8,7 @@ from junction.base.constants import PSRVotePhase from junction.proposals.models import ProposalComment, ProposalSectionReviewer, \ ProposalSectionReviewerVote - +from junction.proposals.permissions import is_proposal_section_reviewer register = template.Library() @@ -53,13 +53,21 @@ def has_upvoted_comment(comment, user): return vote[0].up_vote +@register.filter(name='proposal_section_reviewer') +def proposal_section_reviewer(proposal, user): + """ + Checks if the logged in user is a section reviewer + """ + return is_proposal_section_reviewer(user, proposal.conference, proposal) + + @register.filter(name='get_reviewers_vote_details') def get_reviewers_vote_details(proposal, user): """ Get voter name & details for given proposals. """ v_detail = collections.namedtuple('v_detail', - 'voter vote_value vote_comment') + 'voter_nick vote_value vote_comment') reviewers = ProposalSectionReviewer.objects.filter( proposal_section=proposal.proposal_section, conference_reviewer__conference=proposal.conference, @@ -67,7 +75,7 @@ def get_reviewers_vote_details(proposal, user): vote_details = [] for reviewer in reviewers: - voter = reviewer.conference_reviewer.reviewer.get_full_name() + voter_nick = reviewer.conference_reviewer.nick rv_qs = ProposalSectionReviewerVote.objects.filter( proposal=proposal, voter=reviewer) @@ -85,6 +93,6 @@ def get_reviewers_vote_details(proposal, user): else: vote_comment = None - vote_details.append(v_detail(voter, vote_value, vote_comment)) + vote_details.append(v_detail(voter_nick, vote_value, vote_comment)) return vote_details diff --git a/junction/static/css/app.css b/junction/static/css/app.css index 15c944f4..7f28042a 100644 --- a/junction/static/css/app.css +++ b/junction/static/css/app.css @@ -2623,7 +2623,7 @@ input[type="search"] { .radio, .checkbox { position: relative; - display: block; + display: inline; margin-top: 10px; margin-bottom: 10px; } diff --git a/junction/templates/proposals/list.html b/junction/templates/proposals/list.html index f9666844..62a0f4c9 100644 --- a/junction/templates/proposals/list.html +++ b/junction/templates/proposals/list.html @@ -56,7 +56,7 @@ Proposals To Review Second Phase Voting {% endif %} - {% if user.is_superuser or user.is_stuff %} + {% if user.is_superuser or user.is_staff %} Reviewer Votes Dashboard diff --git a/junction/templates/proposals/partials/proposal-list--votes-dashboard.html b/junction/templates/proposals/partials/proposal-list--votes-dashboard.html index 90ac9f4d..adc831a5 100644 --- a/junction/templates/proposals/partials/proposal-list--votes-dashboard.html +++ b/junction/templates/proposals/partials/proposal-list--votes-dashboard.html @@ -39,18 +39,20 @@

    Sum of Votes: {{ proposal.get_reviewer_votes_sum }} {% for vote in proposal|get_reviewers_vote_details:request.user %}
  • - {{ vote.voter }}: - {{ vote.vote_value }} + {{ vote.voter_nick }}: + {% if vote.vote_comment %} - , "{{ vote.vote_comment }}" + "{{ vote.vote_comment }}" {% endif %}
  • {% endfor %}
    - - Accept/Reject Proposal - + From b8f5262ce383549e6965a41a8da33772a302b9fc Mon Sep 17 00:00:00 2001 From: Ananyo Maiti Date: Thu, 12 Jul 2018 12:17:48 +0530 Subject: [PATCH 560/666] Remove Sum of votes from votes dashboard (#562) Reverse order of display of votes in Voting page --- junction/proposals/forms.py | 2 +- .../proposals/partials/proposal-list--votes-dashboard.html | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index d6eb52fb..56b0606a 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -50,7 +50,7 @@ def _get_proposal_section_reviewer_vote_choices(conference): else: plus_zero_vote_setting_value = True values = [] - for i in ProposalSectionReviewerVoteValue.objects.all(): + for i in ProposalSectionReviewerVoteValue.objects.all().reverse(): if i.vote_value == 0 and not plus_zero_vote_setting_value: continue values.append((i.vote_value, '{}'.format(i.description))) diff --git a/junction/templates/proposals/partials/proposal-list--votes-dashboard.html b/junction/templates/proposals/partials/proposal-list--votes-dashboard.html index adc831a5..8fd100c9 100644 --- a/junction/templates/proposals/partials/proposal-list--votes-dashboard.html +++ b/junction/templates/proposals/partials/proposal-list--votes-dashboard.html @@ -36,7 +36,6 @@

    - Sum of Votes: {{ proposal.get_reviewer_votes_sum }} {% for vote in proposal|get_reviewers_vote_details:request.user %}
  • {{ vote.voter_nick }}: From 67463c288d5136c7412481cc6477001f756da61b Mon Sep 17 00:00:00 2001 From: Ananyo Maiti Date: Sat, 4 Aug 2018 00:58:52 +0530 Subject: [PATCH 561/666] Re-add Proposal Vote Value in votes dashboard (#567) --- .gitignore | 1 + junction/proposals/templatetags/proposal_filters.py | 2 +- .../proposals/partials/proposal-list--votes-dashboard.html | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 9b08add3..b7a9a45f 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ htmlcov/ .tox/ .coverage .cache +.pytest_cache/ nosetests.xml coverage.xml diff --git a/junction/proposals/templatetags/proposal_filters.py b/junction/proposals/templatetags/proposal_filters.py index e2b4013b..666449d8 100644 --- a/junction/proposals/templatetags/proposal_filters.py +++ b/junction/proposals/templatetags/proposal_filters.py @@ -80,7 +80,7 @@ def get_reviewers_vote_details(proposal, user): proposal=proposal, voter=reviewer) if rv_qs: - vote_value = rv_qs[0].vote_value + vote_value = rv_qs[0].vote_value.description else: vote_value = None diff --git a/junction/templates/proposals/partials/proposal-list--votes-dashboard.html b/junction/templates/proposals/partials/proposal-list--votes-dashboard.html index 8fd100c9..b2aa39c3 100644 --- a/junction/templates/proposals/partials/proposal-list--votes-dashboard.html +++ b/junction/templates/proposals/partials/proposal-list--votes-dashboard.html @@ -39,7 +39,7 @@

    {% for vote in proposal|get_reviewers_vote_details:request.user %}
  • {{ vote.voter_nick }}: - + {{ vote.vote_value }} {% if vote.vote_comment %} "{{ vote.vote_comment }}" {% endif %} From 5823dcb83dffbe122ca81ce20d52f4688627ad79 Mon Sep 17 00:00:00 2001 From: Navin Pai Date: Wed, 8 Aug 2018 09:04:08 +0530 Subject: [PATCH 562/666] Adding a Proposals API (#566) * Adding an API for getting proposals. - This allows API access to all proposals similar to https://fifthelephant.talkfunnel.com/2018/json - Only shows public proposals (not cancelled and drafts). - Allows filtering to get proposals for a single conference, or of a proposal_type/section * flake8 issues fixed --- junction/proposals/models.py | 24 ++++++++++++++++++++++++ junction/proposals/views.py | 22 ++++++++++++++++++++++ junction/urls.py | 3 +++ 3 files changed, 49 insertions(+) diff --git a/junction/proposals/models.py b/junction/proposals/models.py index af508413..d2dc0008 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -11,6 +11,7 @@ from django_extensions.db.fields import AutoSlugField from hashids import Hashids from simple_history.models import HistoricalRecords +from rest_framework.reverse import reverse as rf_reverse from junction.base.constants import PSRVotePhase, ProposalCommentType, \ ProposalReviewStatus, ProposalReviewVote, ProposalStatus, \ @@ -211,6 +212,29 @@ def has_negative_votes(self): proposal=self, vote_value__vote_value=ProposalReviewVote.NOT_ALLOWED, ).count() > 0 + def to_response(self, request): + """method will return dict which can be passed to response + """ + author = u"{} {}".format(self.author.first_name, + self.author.last_name) + data = {'id': self.id, + 'author': author, + 'title': self.title, + 'description': self.description, + 'target_audience': dict(ProposalTargetAudience.CHOICES)[self.target_audience], + 'status': dict(ProposalStatus.CHOICES)[self.status], + 'review_status': dict(ProposalReviewStatus.CHOICES)[self.review_status], + 'proposal_type': self.proposal_type.name, + 'proposal_section': self.proposal_section.name, + 'votes_count': self.get_votes_count(), + 'speaker_info': self.speaker_info, + 'speaker_links': self.speaker_links, + 'content_urls': self.content_urls, + 'conference': rf_reverse("conference-detail", + kwargs={'pk': self.conference_id}, + request=request)} + return data + class Meta: unique_together = ("conference", "slug") diff --git a/junction/proposals/views.py b/junction/proposals/views.py index e529b945..3fdc357f 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -15,6 +15,9 @@ from django.views.decorators.http import require_http_methods from hashids import Hashids +from rest_framework import filters, viewsets +from rest_framework.response import Response + # Junction Stuff from junction.base.constants import ConferenceSettingConstants, ConferenceStatus, ProposalReviewStatus, ProposalStatus from junction.conferences.models import Conference @@ -26,6 +29,25 @@ from .services import send_mail_for_new_proposal, send_mail_for_proposal_content +class ProposalView(viewsets.ReadOnlyModelViewSet): + queryset = Proposal.objects.filter(status=2) + serializer_class = serializers.ProposalSerializer + filter_backend = (filters.DjangoFilterBackend,) + filter_fields = ('conference', 'review_status', 'proposal_type', 'proposal_section') + + def get_queryset(self): + data = super(ProposalView, self).get_queryset() + return self.filter_queryset(data) + + def list(self, request): + data = self.get_queryset() + response = {'proposals': []} + for datum in data: + d = datum.to_response(request=request) + response['proposals'].append(d) + return Response(response) + + # Filtering def _filter_proposals(request, proposals_qs): """Filters a proposal queryset based on the values present in the request's diff --git a/junction/urls.py b/junction/urls.py index a5b9caea..c9c82daf 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -13,6 +13,7 @@ # Junction Stuff from junction.conferences import views as conference_views +from junction.proposals import views as proposal_views from junction.devices.views import DeviceDetailApiView, DeviceListApiView from junction.feedback.views import FeedbackListApiView, FeedbackQuestionListApiView, view_feedback from junction.schedule import views as schedule_views @@ -26,6 +27,8 @@ router.register('venues', conference_views.VenueView) router.register('rooms', conference_views.RoomView) +router.register('proposals', proposal_views.ProposalView) + router.register('schedules', schedule_views.ScheduleView) ''' From 15c7cee368c21448f9f4f72b540682d1e9bd1471 Mon Sep 17 00:00:00 2001 From: Ananyo Maiti Date: Sat, 1 Sep 2018 13:56:58 +0530 Subject: [PATCH 563/666] Umcomment Accept/reject button --- .../proposals/partials/proposal-list--votes-dashboard.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/junction/templates/proposals/partials/proposal-list--votes-dashboard.html b/junction/templates/proposals/partials/proposal-list--votes-dashboard.html index b2aa39c3..2c435db4 100644 --- a/junction/templates/proposals/partials/proposal-list--votes-dashboard.html +++ b/junction/templates/proposals/partials/proposal-list--votes-dashboard.html @@ -47,11 +47,11 @@

  • {% endfor %}
    - + {% endif %}

  • From 15c18269717f812ca7424708bc47c36aaa5b3018 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 3 Apr 2019 12:06:33 +0530 Subject: [PATCH 564/666] #dropthedot --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4f35e5b4..befcff2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ env: script: - flake8 -- py.test --cov -v --tb=native +- pytest --cov -v --tb=native - coverage report -m after_success: From bb1e0d095ca3342ed0c728ec4b4f5d384c1f1857 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 3 Apr 2019 12:06:49 +0530 Subject: [PATCH 565/666] Use the newer tool:pytest section for pytest --- setup.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 7d167bb9..1e03a4af 100644 --- a/setup.cfg +++ b/setup.cfg @@ -7,7 +7,7 @@ tag = True [bumpversion:file:README.md] -[pytest] +[tool:pytest] DJANGO_SETTINGS_MODULE = settings.test_settings addopts = --reuse-db norecursedirs = .tox .git */migrations/* */static/* docs venv @@ -18,7 +18,7 @@ exclude = .tox,.git,*/migrations/*,*/static/*,docs,venv [coverage:run] source = junction/ -omit = +omit = *tests* *commands* *migrations* From eafbb3f8b84337e8a37f52f0da646aac0e7319b1 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 3 Apr 2019 12:59:38 +0530 Subject: [PATCH 566/666] Minimal dependency upgrades for fixing pytest runs --- requirements-dev.txt | 22 +++++++++------------- requirements.txt | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 3a386fe1..68084f58 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,27 +2,23 @@ # Testing # ------------------------------------------------- -# Fix for travis CI tests failing -# Ref: https://github.com/FactoryBoy/factory_boy/issues/334#issuecomment-267696136 -fake-factory==0.7.4 -factory-boy==2.7.0 +factory-boy==2.11.1 -flake8==2.4.1 -pytest-django==2.9.1 -pytest-cov==2.2.1 -pytest-flakes==1.0.0 +flake8==3.7.7 +pytest-django==3.4.8 +pytest-flakes==4.0.0 -coverage==4.1 +coverage==4.5.3 # Documentation # -------------------------------------------------- -mkdocs==0.15.3 +mkdocs==1.0.4 bumpversion==0.5.3 # Debugging # -------------------------------------------------- -ipdb==0.9.0 +ipdb==0.12 # Patch for html5lib - issue #520 -html5lib<0.99999999 -bleach<2.0.0 +html5lib==1.0.1 +bleach==3.1.0 diff --git a/requirements.txt b/requirements.txt index aee6dfb1..b5d381fe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,7 +22,7 @@ hashids==1.1.0 # Django Model Helpers # ------------------------------------------------- django-uuid-upload-path==1.0.0 -Pillow==2.9.0 +Pillow==6.0.0 # Auth # ------------------------------------------------- From 08b7ceb83ad5be9e8fa6f5a026c46a54f1e15100 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 3 Apr 2019 13:03:27 +0530 Subject: [PATCH 567/666] We're still Python 2. :( --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b5d381fe..a81dc30b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,7 +22,7 @@ hashids==1.1.0 # Django Model Helpers # ------------------------------------------------- django-uuid-upload-path==1.0.0 -Pillow==6.0.0 +Pillow==5.4.1 # Auth # ------------------------------------------------- From b3ced1fca395e38e210e047b1112856c6b0242b5 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 3 Apr 2019 13:09:22 +0530 Subject: [PATCH 568/666] Use older flake8 to not need code changes --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 68084f58..c4b0bbf5 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,7 +4,7 @@ # ------------------------------------------------- factory-boy==2.11.1 -flake8==3.7.7 +flake8==2.4.1 pytest-django==3.4.8 pytest-flakes==4.0.0 From a061a31d366ce206ef7c0f37b8c5cae5a6b6a683 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 3 Apr 2019 14:00:12 +0530 Subject: [PATCH 569/666] Bump down pytest-flakes to make things work --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index c4b0bbf5..ad5fa5c2 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -6,7 +6,7 @@ factory-boy==2.11.1 flake8==2.4.1 pytest-django==3.4.8 -pytest-flakes==4.0.0 +pytest-flakes==2.0.0 coverage==4.5.3 From 3f31197caa57fadf81f5420437fceaa62b62470e Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 3 Apr 2019 14:10:29 +0530 Subject: [PATCH 570/666] Re-add pytest-cov --- requirements-dev.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements-dev.txt b/requirements-dev.txt index ad5fa5c2..2fdd7590 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -7,6 +7,7 @@ factory-boy==2.11.1 flake8==2.4.1 pytest-django==3.4.8 pytest-flakes==2.0.0 +pytest-cov==2.6.1 coverage==4.5.3 From 47f6a20b4d6437ce37814d80901aff22afc07ffe Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 3 Apr 2019 10:49:15 +0530 Subject: [PATCH 571/666] Fix the mkdocs configuration for modern versions --- mkdocs.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 095f02b7..837d5aeb 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -2,14 +2,13 @@ site_name: Junction site_description: Junction is a software to manage proposals, reviews, schedule, feedback during conference. theme: 'mkdocs' -theme_center_lead: false repo_url: https://github.com/pythonindia/junction pages: -- ['index.md', 'Home'] -- ['release_notes.md', 'Release Notes'] -- ['conference_reviewers.md', 'Add Reviewers'] -- ['api.md', 'API'] +- {'index.md': 'Home'} +- {'release_notes.md': 'Release Notes'} +- {'conference_reviewers.md': 'Add Reviewers'} +- {'api.md': 'API'} copyright: Copyright © 2015, PSSI. From a771b7c9911b093b0d16414540bb0fd94ad3a8a0 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 3 Apr 2019 11:10:59 +0530 Subject: [PATCH 572/666] Adopt the PSF CoC --- CODE_OF_CONDUCT.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..b15afc93 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,9 @@ +# Code of Conduct + +Please note that all interactions related to Junction are covered by +the [PSF Code of Conduct](https://www.python.org/psf/codeofconduct/), +which includes all infrastructure used in the development of Junction +(e.g. mailing lists, issue trackers, GitHub, etc.). + +In general this means everyone is expected to be open, considerate, and +respectful of others no matter what their position is within the project. From cd538570cce14b3dc6c7058490ae87b5ed296fb8 Mon Sep 17 00:00:00 2001 From: Deepa Date: Wed, 10 Apr 2019 14:27:38 +0530 Subject: [PATCH 573/666] Completed - #579 --- junction/proposals/forms.py | 7 +++---- junction/templates/proposals/create.html | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index 56b0606a..cc3509cb 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -74,11 +74,10 @@ class ProposalForm(forms.Form): Used for create/edit ''' title = forms.CharField(min_length=10, - help_text="Title of the proposal, no buzz words!", + help_text="Title of the Proposal", widget=forms.TextInput(attrs={'class': 'charfield'})) description = forms.CharField(widget=PagedownWidget(show_preview=True), - help_text=("Describe your proposal with clear objective in simple sentence." - " Keep it short and simple.")) + help_text=("Describe your Proposal")) target_audience = forms.ChoiceField( choices=ProposalTargetAudience.CHOICES, widget=forms.Select(attrs={'class': 'dropdown'})) @@ -86,7 +85,7 @@ class ProposalForm(forms.Form): widget=forms.Select(attrs={'class': 'dropdown'}), choices=ProposalStatus.CHOICES, help_text=("If you choose DRAFT people can't the see the session in the list." - " Make the proposal PUBLIC when you're done with editing the session.")) + " Make the proposal PUBLIC when you're done editing.")) proposal_type = forms.ChoiceField( widget=forms.Select(attrs={'class': 'dropdown'})) proposal_section = forms.ChoiceField( diff --git a/junction/templates/proposals/create.html b/junction/templates/proposals/create.html index ea3cbe61..5285062a 100644 --- a/junction/templates/proposals/create.html +++ b/junction/templates/proposals/create.html @@ -24,6 +24,7 @@

    New Proposal

    This form supports markdown for formatting.

    +

    Take a look at the best practices before submitting.


    {% csrf_token %} From 4f3da520dbc62f12fc1fafd58987469329249fd7 Mon Sep 17 00:00:00 2001 From: Deepa Date: Mon, 15 Apr 2019 18:54:19 +0530 Subject: [PATCH 574/666] Fixing issue 583 --- junction/templates/feedback/detail.html | 2 +- junction/templates/proposals/dashboard.html | 2 +- junction/templates/proposals/detail/base.html | 10 +++++----- junction/templates/proposals/detail/comments.html | 2 +- junction/templates/proposals/detail/schedule-item.html | 2 +- junction/templates/proposals/reviewers_dashboard.html | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/junction/templates/feedback/detail.html b/junction/templates/feedback/detail.html index de6e32df..86ca9875 100644 --- a/junction/templates/feedback/detail.html +++ b/junction/templates/feedback/detail.html @@ -55,7 +55,7 @@

    {{ txt.question.title }}

    {% for value in txt.values %}
    -

    {{ value.text|markdown }}

    +

    {{ value.text|markdown_safe }}


    {% empty %} diff --git a/junction/templates/proposals/dashboard.html b/junction/templates/proposals/dashboard.html index 5b0a9abb..e1154845 100644 --- a/junction/templates/proposals/dashboard.html +++ b/junction/templates/proposals/dashboard.html @@ -53,7 +53,7 @@


    -

    {{ conference.description|markdown }}

    +

    {{ conference.description|markdown_safe }}

    diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index 71ff09c0..7084e795 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -127,20 +127,20 @@

    Description:

    -

    {{ proposal.description|markdown }}

    +

    {{ proposal.description|markdown_safe }}

    {% if proposal.prerequisites %}

    Prerequisites:

    -

    {{ proposal.prerequisites|markdown }}

    +

    {{ proposal.prerequisites|markdown_safe }}

    {% endif %} {% if proposal.content_urls %}

    Content URLs:

    -

    {{ proposal.content_urls|markdown }}

    +

    {{ proposal.content_urls|markdown_safe }}

    {% endif %} @@ -159,14 +159,14 @@

    Content URLs:

    {% if proposal.speaker_info %}

    Speaker Info:

    -

    {{ proposal.speaker_info|markdown }}

    +

    {{ proposal.speaker_info|markdown_safe }}

    {% endif %} {% if proposal.speaker_links %}

    Speaker Links:

    -

    {{ proposal.speaker_links|markdown }}

    +

    {{ proposal.speaker_links|markdown_safe }}

    {% endif %} diff --git a/junction/templates/proposals/detail/comments.html b/junction/templates/proposals/detail/comments.html index 1167ee7c..2653a920 100644 --- a/junction/templates/proposals/detail/comments.html +++ b/junction/templates/proposals/detail/comments.html @@ -44,7 +44,7 @@
    {% endif %}

    {% else %}
    - {{ comment.comment|markdown }} + {{ comment.comment|markdown_safe }} {% if request.user.is_authenticated and request.user != comment.commenter %} Mark as spam

    {% endif %} diff --git a/junction/templates/proposals/detail/schedule-item.html b/junction/templates/proposals/detail/schedule-item.html index 5fa0726c..eb0c54fb 100644 --- a/junction/templates/proposals/detail/schedule-item.html +++ b/junction/templates/proposals/detail/schedule-item.html @@ -44,7 +44,7 @@

    Description:

    -

    {{ sch_item.alt_description|markdown }}

    +

    {{ sch_item.alt_description|markdown_safe }}

    diff --git a/junction/templates/proposals/reviewers_dashboard.html b/junction/templates/proposals/reviewers_dashboard.html index cafa1652..4d680839 100644 --- a/junction/templates/proposals/reviewers_dashboard.html +++ b/junction/templates/proposals/reviewers_dashboard.html @@ -53,7 +53,7 @@


    -

    {{ conference.description|markdown }}

    +

    {{ conference.description|markdown_safe }}

    From d99b5691b25eb549da3f33218b67c63400af59bc Mon Sep 17 00:00:00 2001 From: Abhishek Yadav Date: Tue, 11 Jun 2019 14:54:22 +0530 Subject: [PATCH 575/666] Comments should be visible only to authenticated users. Fixes #595 partly --- junction/templates/proposals/detail/base.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index 7084e795..b8772284 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -245,9 +245,12 @@

    Reviewer Actions:

    + {% if user.is_authenticated %}
    - {% include "proposals/detail/comments.html"%} + {% include "proposals/detail/comments.html" %}
    + {% endif %} + {% if read_private_comment %}
    We hide reviewers information to prevent biased feedback. From fb0803c7bf6d9d92d78e51972ed1f1f440a3fd16 Mon Sep 17 00:00:00 2001 From: Abhishek Yadav Date: Mon, 17 Jun 2019 20:06:35 +0530 Subject: [PATCH 576/666] Add proposal id to the list page --- .gitignore | 3 +++ .../templates/proposals/partials/proposal-list--items.html | 1 + 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index b7a9a45f..3ace00b8 100644 --- a/.gitignore +++ b/.gitignore @@ -82,3 +82,6 @@ _docs_html/ # generated by unit tests qr_files/ + + +tmp/ diff --git a/junction/templates/proposals/partials/proposal-list--items.html b/junction/templates/proposals/partials/proposal-list--items.html index fd1787e2..aed4aacb 100644 --- a/junction/templates/proposals/partials/proposal-list--items.html +++ b/junction/templates/proposals/partials/proposal-list--items.html @@ -43,6 +43,7 @@

    {{ proposal.get_status_display }} {% endif %} + ({{ proposal.id }}) {{ proposal.proposal_type }} From 7846c0b6af211038a2cb46023a7e999fc1af0295 Mon Sep 17 00:00:00 2001 From: Deepa Date: Mon, 24 Jun 2019 17:01:54 +0530 Subject: [PATCH 577/666] Fixing issue 598 --- junction/proposals/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index cc3509cb..f118f593 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -84,7 +84,7 @@ class ProposalForm(forms.Form): status = forms.ChoiceField( widget=forms.Select(attrs={'class': 'dropdown'}), choices=ProposalStatus.CHOICES, - help_text=("If you choose DRAFT people can't the see the session in the list." + help_text=("If you choose DRAFT people can't see the session in the list." " Make the proposal PUBLIC when you're done editing.")) proposal_type = forms.ChoiceField( widget=forms.Select(attrs={'class': 'dropdown'})) From 4e5d5232a46def477ee553fbd95b3a2f488cf34c Mon Sep 17 00:00:00 2001 From: Abhishek Yadav Date: Sat, 29 Jun 2019 14:05:15 +0530 Subject: [PATCH 578/666] Fixes css on vote-view page --- junction/proposals/forms.py | 2 +- junction/static/css/app.css | 7 +++++++ junction/templates/proposals/vote.html | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/junction/proposals/forms.py b/junction/proposals/forms.py index cc3509cb..c3664ed3 100644 --- a/junction/proposals/forms.py +++ b/junction/proposals/forms.py @@ -155,7 +155,7 @@ class ProposalReviewerVoteForm(forms.Form): """ vote_value = forms.ChoiceField( widget=forms.RadioSelect(), - label="Do you think this proposal will make a good addition to PyCon India 2018?" + label="Do you think this proposal will make a good addition to PyCon India ?" ) comment = forms.CharField( widget=forms.Textarea(attrs={'minlength': '30'}), diff --git a/junction/static/css/app.css b/junction/static/css/app.css index 7f28042a..2cf6a13a 100644 --- a/junction/static/css/app.css +++ b/junction/static/css/app.css @@ -2627,6 +2627,13 @@ input[type="search"] { margin-top: 10px; margin-bottom: 10px; } +form#reviewer-vote .radio { + position: inherit; + display: block; +} +form#reviewer-vote label.control-label{ + text-align: left; +} .radio label, .checkbox label { min-height: 20px; diff --git a/junction/templates/proposals/vote.html b/junction/templates/proposals/vote.html index 07e456d9..c46b2f3b 100644 --- a/junction/templates/proposals/vote.html +++ b/junction/templates/proposals/vote.html @@ -39,7 +39,7 @@

    Proposal Voting


    - {% csrf_token %} + {% csrf_token %} {% bootstrap_form form %} {% buttons %}
    From 74ef9d5f57b09c00061b7fd2d413ef52686f19db Mon Sep 17 00:00:00 2001 From: Abhishek Yadav Date: Sat, 29 Jun 2019 16:56:40 +0530 Subject: [PATCH 579/666] Disable the *second-phase-voting* button and the *upload-details* buttons from the proposal details page --- junction/proposals/views.py | 3 +++ junction/templates/proposals/detail/base.html | 8 +++++++- settings/common.py | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 3fdc357f..26c4c94d 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -239,6 +239,9 @@ def detail_proposal(request, conference_slug, slug, hashid=None): ctx.update({'comments': comments.get_public_comments(), 'proposal_comment_form': ProposalCommentForm()}) + ctx['enable_upload_content'] = settings.ENABLE_UPLOAD_CONTENT + ctx['enable_second_phase_voting'] = settings.ENABLE_SECOND_PHASE_VOTING + return render(request, 'proposals/detail/base.html', ctx) diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index b8772284..1b872717 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -146,9 +146,12 @@

    Content URLs:

    {% if is_reviewer or user.is_authenticated and user.is_superuser %}
    + {% if enable_upload_content %} Ask proposer to upload content + {% endif %} + {% if schedule_item %} Participants Feedback @@ -174,7 +177,10 @@

    Speaker Links:

    Reviewer Actions:

    Vote for proposal - Second phase voting + + {% if enable_second_phase_voting %} + Second phase voting + {% endif %}
    {% endif %} diff --git a/settings/common.py b/settings/common.py index febe1fab..865589da 100644 --- a/settings/common.py +++ b/settings/common.py @@ -250,3 +250,7 @@ USER_SPAM_THRESHOLD = 2 SPAM_MODERATION_ADMINS = [] + + +ENABLE_SECOND_PHASE_VOTING = False +ENABLE_UPLOAD_CONTENT = False From b5da5ad50a3ab175e13cec681041ef7f9faa3302 Mon Sep 17 00:00:00 2001 From: Abhishek Yadav Date: Thu, 4 Jul 2019 20:45:55 +0530 Subject: [PATCH 580/666] Proposals should be ordered as oldest first. Affects: list_proposals and proposals_to_review --- junction/proposals/views.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 26c4c94d..c94aca08 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -100,7 +100,7 @@ def list_proposals(request, conference_slug): # Display proposals which are public public_proposals_list = proposals_qs.exclude(review_status=ProposalReviewStatus.SELECTED).filter( - status=ProposalStatus.PUBLIC).order_by('-created_at') + status=ProposalStatus.PUBLIC).order_by('created_at') return render(request, 'proposals/list.html', {'public_proposals_list': public_proposals_list, @@ -292,9 +292,10 @@ def proposals_to_review(request, conference_slug): if not permissions.is_proposal_reviewer(request.user, conference): raise PermissionDenied + proposals_qs = Proposal.objects.select_related( 'proposal_type', 'proposal_section', 'conference', 'author', - ).filter(conference=conference).filter(status=ProposalStatus.PUBLIC) + ).filter(conference=conference).filter(status=ProposalStatus.PUBLIC).order_by('created_at') psr = ProposalSectionReviewer.objects.filter( conference_reviewer__reviewer=request.user, conference_reviewer__conference=conference) From 3ea9bda93d42801834c575bbb49a5ae7939b4424 Mon Sep 17 00:00:00 2001 From: Abhishek Yadav Date: Thu, 31 Oct 2019 12:22:28 +0530 Subject: [PATCH 581/666] Dont show proposals marked as deleted --- junction/proposals/views.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index c94aca08..52b805ad 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -183,6 +183,9 @@ def detail_proposal(request, conference_slug, slug, hashid=None): proposal = get_object_or_404(Proposal, slug=slug, conference=conference) return HttpResponseRedirect(proposal.get_absolute_url()) + if proposal.deleted == True: + raise Http404("404") + # Here we have obtained the proposal that we want to display. conference = proposal.conference read_private_comment = permissions.is_proposal_author_or_proposal_reviewer( From 416bba0d2922036e68930e26d565702f85a3202d Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 10 Mar 2020 15:33:20 +0530 Subject: [PATCH 582/666] Drop outdated Docker configuration We can re-add it at a later date if needed. --- Dockerfile | 11 ----------- docker-compose.yml | 30 ------------------------------ 2 files changed, 41 deletions(-) delete mode 100644 Dockerfile delete mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 21c3dce2..00000000 --- a/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM ubuntu:14.04 -MAINTAINER Anuvrat Parashar "anuvrat@anuvrat.in" - -RUN apt-get update && apt-get -y upgrade && apt-get install -y git python2.7 python-pip python-dev postgresql-server-dev-all -ADD requirements.txt /srv/requirements.txt -ADD requirements-dev.txt /srv/requirements-dev.txt -WORKDIR /srv/ -RUN pip install -r /srv/requirements.txt -RUN rm -rf /usr/local/lib/python2.7/dist-packages/requests -RUN pip install -r /srv/requirements-dev.txt - diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index a44b7e97..00000000 --- a/docker-compose.yml +++ /dev/null @@ -1,30 +0,0 @@ -redis: - image: redis:2.8.17 - volumes: - - /var/docker/junction/redis/:/data/ - ports: - - "6380:6379" - privileged: true - -web: - build: . - command: python manage.py runserver 0.0.0.0:8000 - volumes: - - .:/srv/ - links: - - redis:redis - ports: - - "8000:8000" - privileged: true - -celery: - image: junction_web - command: celery worker -A junction -l info - volumes: - - .:/srv/ - links: - - redis:redis - - web:web - environment: - - C_FORCE_ROOT=true - From 43b5ebbe787659b37f0312bb91d37c72607ae84e Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 10 Mar 2020 15:33:45 +0530 Subject: [PATCH 583/666] Drop the MkDocs configuration --- mkdocs.yml | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 mkdocs.yml diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index 837d5aeb..00000000 --- a/mkdocs.yml +++ /dev/null @@ -1,16 +0,0 @@ -# see: https://github.com/tomchristie/mkdocs/blob/master/mkdocs.yml -site_name: Junction -site_description: Junction is a software to manage proposals, reviews, schedule, feedback during conference. -theme: 'mkdocs' -repo_url: https://github.com/pythonindia/junction - -pages: -- {'index.md': 'Home'} -- {'release_notes.md': 'Release Notes'} -- {'conference_reviewers.md': 'Add Reviewers'} -- {'api.md': 'API'} - -copyright: Copyright © 2015, PSSI. - -# directory to output HTML build -site_dir: _docs_html From 12e2a1544526ff13e2ed98b20c82d0fddc365950 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 10 Mar 2020 15:34:21 +0530 Subject: [PATCH 584/666] Move CoC to .github --- CODE_OF_CONDUCT.md => .github/CODE_OF_CONDUCT.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CODE_OF_CONDUCT.md => .github/CODE_OF_CONDUCT.md (100%) diff --git a/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md similarity index 100% rename from CODE_OF_CONDUCT.md rename to .github/CODE_OF_CONDUCT.md From 80bc485d1f939efc609ddd90b421018768bc5d4b Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 10 Mar 2020 15:36:03 +0530 Subject: [PATCH 585/666] Remove spam.csv This seems to be for training a model for spam detection, but this file isn't referenced in the codebase. --- spam.csv | 1765 ------------------------------------------------------ 1 file changed, 1765 deletions(-) delete mode 100644 spam.csv diff --git a/spam.csv b/spam.csv deleted file mode 100644 index 21dbcb72..00000000 --- a/spam.csv +++ /dev/null @@ -1,1765 +0,0 @@ -comment,is_spam -Please remove contact email from Speaker Info. ,0 -Removed.,0 -You can create github/bitbucket repo for the workshop and share it later.,0 -"Yes, that is my plan. Hopefully in a couple of weeks. ",0 -"Please add a few more details about the Pythonic part of your talk. For example, write a bit about which Python modules you used in your stack. - -Thanks",0 -"Please add slides from any previous presentation you might have made on this topic. If you have tentative slides planned for this presentation, which you are incrementally working on, sharing them would be useful too. - -Thanks",0 -Sure Jaidev will add same.,0 -Just Added the slides from one of our previous talks. It was on introduction to Deep Learning. The PyCon talk will be more about python methods / libraries to implement such algorithms.,0 -"A detailed description breaking down the talk into smaller sections with more detailed description would be great! These are [some examples][1] of proposals with detailed descriptions. - - - [1]: http://rhodesmill.org/brandon/2013/example-pycon-proposals/",0 -Please let me know if you would like any particular topic from FLASK framework to be covered. I will try to include that in my workshop/session.,0 -Good Content.. Will Attend ,0 -the topic is good but i am not seeing much in the slide... it will be great if the author will share github samples...,0 -"Thanks Puneeth -Template was helpful. - -Have updated the talk based on same.",0 -"I was a successful student TUCKER BALCH, PH.D ASSOCIATE PROFESSOR COLLEGE OF COMPUTING -GEORGIA INSTITUTE OF TECHNOLOGY in his computation investment part 1 course. This subject is interesting and will be useful. Incidentally the professor is also conducting many interesting courses on automation/machine learning. For instance for a large world wide manufacturer like Brachot Hermant NV Belgium, it will be useful to use data on raw blocks and color area to predict the rejects in the final polished slabs etc. -",0 -"I was a successful student TUCKER BALCH, PH.D ASSOCIATE PROFESSOR COLLEGE OF COMPUTING -GEORGIA INSTITUTE OF TECHNOLOGY in his computation investment part 1 course. This subject is interesting and will be useful. Incidentally the professor is also conducting many interesting courses on automation/machine learning. For instance for a large world wide manufacturer like Brachot Hermant NV Belgium, it will be useful to use data on raw blocks and color area to predict the rejects in the final polished slabs etc. -",0 -"It is very much the need of the hour that we(Indians) should start developing applications in our languages. Along with this initiative, it is good to know that Tamil, one of the classical languages - leads the first step for other Indian languages. ",0 -"The CAP theorem is an impossibility result according to wikipedia. So could you explain what you mean by ""Distributed systems always demands to meet CAP theorem which is really hard to meet with a good performance numbers""?",0 -"CAP theorem happens to gurantee any two of consistency, availability & partition tolerance. If you fail to meet even two out of three then you are in danger. IMO, meeting all three is impossible, but not two.",0 -This seems really interesting. I'd be really interested to learn the ins and outs of this! :),0 -Online judges are imperative to coding competitions which form the basis for all great progrmmers. Learning to build one will be an exciting challenge and I look forward to learning more about it. ,0 -Is this the same thing which judged during cybercept15?,0 -Yes aditya.,0 -Link of pydanny-cookiecutter under **proposal description** throws 404 error and also same error to the link of cookiecutter under **Speaker-Info**,0 -"All the urls should be working fine now. Thanks a lot, Sheesh!",0 -"> It was really a great work. Good initiative effort from your side. Let -> us know more in the same which helps **students from rural areas** -> also to get involved in this to develop their own application to get -> their things done & prove themselves to the world. -> -> It's good to know that this **initiative & innovation** will sure -> bring changes & also help us to sustain with Tamil Language forever. -> All the very best for your upcoming works.",0 -I have got really high expectations from this one. Hopefully it would be good.,0 -Thanks! Hopefully I'll meet them.,0 -This seems super interesting!,0 -"Nice and Challenging Topic. -does this module deal with Data cleansing of text also.",0 -"Sorry the github link was wrong. Its - -https://github.com/saisrk",0 -"It directly supports only regular expressions for text cleaning, but it also provides third-party support for arbitrary data cleaning. So you can have all the text cleaning functionality in a separate module and this module will automate all of that.",0 -This is wonderful Course content for Beginners like me. Please let me know when you are conducting.,0 -"Looks like there is duplicate talk . Can one of you delete on the talk. -https://in.pycon.org/cfp/pycon-india-2015/proposals/building-nextgen-iot-solutions-using-python-and-cloud/",0 -"This talk is to explain how a distributed database architecture can drive more reliable web apps. Even for startups who use Python and wants a database which is fault tolerant with no down time ,Riak is helpful. Talk will clarify when to use Riak DB and how we can exploit it using Python ,the easiest language to write more efficient Web apps.",0 -"This one will be hands-on workshop, where people will build the solution on development boards. We will do the session talk first in https://in.pycon.org/cfp/pycon-india-2015/proposals/building-nextgen-iot-solutions-using-python-and-cloud/ which will involve demos, and then people who are interested to do hands-on can attend this workshop.",0 -Seems to be good implementation of python + mongo + web interface. Complete end to end usage of mongo database and python coding.,0 -"Just in case this was not clear. - -This proposal is a second step to the one I did last year, It's supposed to teach advanced concepts and design patterns to be used in mobile development. - -The slides are right now a copy of what we had last year with minor changes. I am adding new content every day to it to include advanced concepts inside it instead of the old content. - -I have the basic outline of the presentation mentioned in the proposal above. The slides will be updated based on that.",0 -"good work effort - ""changing passcode easy"" :) :) :) ",0 -"It would be especially interesting to have a talk related to Cyber Security and Python at Pycon. I have been interested in attending talks on Python and its use in Cyber security but surprisingly there have not been many talks in this area at Pycon. I was at Pycon North America and OWASP team had visited Pycon North America this year but there was no talk by them. There was one by Jacob Kaplan Moss at Pycon Australia which was really cool. [1] - -[1] https://www.youtube.com/watch?v=sra9x44lXgU",0 -NIce Article !! ,0 -Great to know...,0 -"It is a great topic. -Looking forward to attend same. -",0 -Nice article,0 -Nice *Proposal,0 -Nice proposal samarth!!,0 -Great idea....,0 -"Saurabh, I guess the workshops are on the first day of the event, before the talks happen. So what you are suggesting, will not work.",0 -"As one of the co-authors of Two Scoops of Django, I can say that Saurabh's contributions to the book were useful and voluminous. His work on cookiecutter-django is nothing short of brilliant. He has my full confidence. I recommend this talk very highly.",0 -"The description of the talk is way short for the topic, and it does not explain why the speakers are the best person to give this talk.",0 -Missing speaker info. There should be enough material to prove why the speaker is a good person to talk about Python3. He should also point to the Python3 projects he worked on.,0 -Please add an outline of your talk to the description. Otherwise this looks good.,0 -A well written proposal.,0 -This should be a good talk.,0 -"Very good topic, but please add an outline of the talk.",0 -Thanks Kushal. I'll add an outline shortly. ,0 -Thank you!,0 -Can you please add some talk outline to the description? The current description does not give any details about the talk itself.,0 -Can you please add some talk outline in the description? ,0 -Looking forward to the talk. :),0 -"Can you please elaborate on your approach? - -Are you hacking python's safe builtins? Are you relying on a library or are you running the whole thing in a container? ",0 -Thanks :),0 -A good proposal. It would be interesting to learn about using Python for things other than traditional programming.,0 -Interesting talk and by a speaker who knows what he is talking about. Will encourage new contributors. Definite +1.,0 -Definitely going to sit for this talk.,0 -I really hope that this talk gets selected. Documentation is often treated as a step child or a second class citizen. Experience shows that how much it helps when you have good and correct documentation and thusly removes a lot of technical debt.,0 -"A solid technical speaker, someone who personally uses Openshift.",0 -A very interesting and relevant topic. Look forward to attending the talk. ,0 -The talk description needs more details about the talk.,0 -The description does not have enough content.,0 -The description does not have enough content.,0 -This is a good proposal. It will be nice if you can add a point based talk outline.,0 -The talk description is too small. Looks like the speaker(s) did not spend enough time for this talk.,0 -Haris is a good coder and great speaker. I would love to come and watch his talk.,0 -"Arun knows his stuff, which is why we link to his book from ours (Two Scoops of Django). ",0 -"I don't think this is a talk for beginners. Beginners may not know what CI is. Also, there is not enough detail in the description to compare this with Jenkins or Travis. On what basis is Tunir simpler than these CI systems? Please add more details.",0 -"Thanks for the comment, marking it for the beginners was a typo. I will be adding few more points about why tunir is easier to use. ",0 -Thanks Ronojoy,0 -"Flask ( Werkzeug ) debugger uses this approach to render traceback. Developer can go back to any point and inspect the variable. Good topic. - -![Werkzeug Error Image][1] - - - [1]: http://werkzeug.pocoo.org/docs/0.10/_images/debug-screenshot.png ",0 -"Hi Jaseem, - We have built our own python sandbox in python itself. We are not using any external libraries.",0 -@kushal Done. Hope the outline is helpful and the way you were expecting.,0 -I updated the talk. Let me know if I can fix something more.,0 -"Hi Vishal, - -Thank you for the proposal. Can you provide some information on the following : - -1. Pandas, Sci-Kit learn, MRJob, Matplotlib : All of these are comprehensive in themselves, how do you plan to cover them in the stipulated time. -2. You mentioned demonstrating few practical applications, can you share what kind of examples are you planning to cover ? -3. What features will you covering when you talk about MRjob ? Do you also plan to cover topics like deployments and dependency resolutions on the data node when using Python with MRJob. -4. What all data sets are you planning to use . -5. Can you also share you previous talk videos / slides. - -Looking forward for more discussions. -",0 -Please provide with more details. On what all do you plan to discuss.,0 -"The objective is to expose audience on how to build big data streaming architecture. The talk would include 3 aspects: Challenges of building streaming architecture, tools and technologies for building such an architecture and finally Python libraries and tools available that can be used. - -Focus is on big data design paradigm and tools available in python to facilitate it. - - ",0 -"A problem I've not seen addressed (to my personal satisfaction) is about provisioning. i.e. how do you ensure that the development team is working in an identical environment as the production server? Initial setup is well and good, but how to maintain it? As in; when more and more features are added, some developer boxes get out-of-sync with production - and you don't exactly realize this until something horrible happens. Will something like this be covered in the talk?",0 -Nice one.,0 -"Please add the real life use-cases, how FUSE helps writing file systems in few lines of code..may be accessing social content on filesystem as a usecase in addition to toyfs ! - -Also describe your intended audience ! - -Cheers!",0 -"@Rohit : I pretty much like the experiences you have shared in the blogpost mentioned above, but to me it looks like a very DevOps talk comparing one monitoring sytem with other, rather than a PyCon Talk. That said, I would still love to see it on stage if not on the main talks but certainly as lightning talk or open spaces. - -Can you try write shed some more light if you can suit it more to pythonic audience. ?",0 -"Looking at the slides you shared, to me it is a hello word for Vagrant. Can you list more detailed points of how you plan to make it suitable for PyCon India audience. ",0 -Please add a detailed outline of how and what you plan to share to the audience.,0 -"Hi Konark, - -Good to hear your viewpoint. I think, it is a pythonic talk because: - -* Shinken is a 100% python project. The package is available in PyPi (pip install shinken). -* It has a very modular design. Even the default web UI is a separate python module. Installed using shinken installer (shinken install webui). -* Plugins can be written in any language, including python. I have some of mine in a [github repo](https://github.com/rohit01/nrpe-plugins). - -\> *Can you try write shed some more light if you can suit it more to pythonic audience. ?* -I see a lot of talks, which talks about how python is being used instead of talking about the syntax. This talk presents shinken, a tool built using python, its high level architecture and demonstrates how it is better than Nagios (written in C). - -Thanks",0 -"Vagrant is for every web developer or designer. So I think this talk is for everyone in the conference. -My PRUG meetup talk was just a getting started with vagrant. -But here I am planning to use Django project for demo and will play with it using vagrant. -I am planning to show how we can deploy app on cloud using vagrant. -Nowadays we have complex server architectures. -I will show how we can have different django web and database server And how they communicate with each other. -",0 -Good topic I must say. ,0 -"@sarthak : Thank you for your proposal. Would request you please write down a rough agenda of your talk. Also, assuming you are writing your topologies in Python , please mention the libraries you plan to use. - -Looking forward to it.",0 -"AFAIK, now it's an Apache foundation project, so you might want to update the abstract with the same instead of Twitter.",0 -"@sagar : Request you to edit the abstract, and add a detailed list of things and how you plan to present them. Bullet points at this time should be good.",0 -@venu : Can you share more details the things / concepts / code you are to talk about. ,0 -@Anuvrat : Thank you for your detailed proposal.,0 -"Hi, - -Please share more details on what kind of plugins are you going to present, if possible link to the repos. where the code is hosted. Also, please provide an agenda of how you plan to structure your talk. -",0 -"where could i get the content of this speech, i want learn and test the navigation on RPi2. if i can get it somewhere, it will be very helpful.",0 -"Hi Wang - -I will upload the slides soons. Was busy with some projects, thats why its delayed. - -Thanks",0 -"@konark: kindly take a look at the slides as well ... -shall soon be adding some code to them.",0 -"nice, it will been so helpful for me. -thank you very much.",0 -Is there an Open Source project that will be showcased or it would be more of an take-pointers-and-do-it-yourself talk?,0 -"@konark: The library I am using is [streamparse][1] by the guys at [Parse.ly][2]. - -The rough agenda would be to take the audience through Storm, it's power and capabilities and then running through a Python way to do this. Maybe even ship in a small demo. - -Also, I have mentioned Apache Storm itself throughout. Twitter now owns this project, by the way. - - - [1]: http://streamparse.readthedocs.org/en/latest/index.html - [2]: http://www.parsely.com/",0 -Yes we will be showcasing an open source project that will utilize the Open source threat feeds and based on that will will extract meaningful and actionable information for security operations and engineering.,0 -"Thats really cool. Would look forward to the talk. - -If you are willing you can add some more details about the Open source project/threat feeds/preso/links! - -Just brief pointers would be suffice, for the audience to have a better know-how/background about the talk. -",0 -Looking forward for this talk.,0 -"@arocks: intent here is to help Python developers code faster using the VS IDE with VS Tools for Python. The focus is on Python tools for developer productivity -",0 -"@arocks: and probably it got so many votes because it sounds interesting, why else I wonder",0 -"how much of Django would we need to know for the workshop to benefit us? -Say I don't know any Django now but I'm willing to learn a bit before the workshop, would I be able to grasp it? Also, would you be teaching some part of how to make good web apps with Django? ",0 -"Typo in slide 8 -- ""XSS protection in DJnago""",0 -"@kahlil - It would be advantageous if have already tried out one or two projects in Django. Even if you do have done the Django official polls tutorial, you'll be able to pickup a lot of things. ",0 -"Arink, - Is this talk you are proposing here ? if not what is the project which you want people to contribute to ? - ",0 -"Here, It is not related to any project. This proposal is for talk.",0 -"Hey Swapnil, - I see your workshop is selected for this year PyCon India. - Just for information Devsprint and workshop will be happening parallel. - Am not sure how will you manage both places ?",0 -"Presentation Link - -https://docs.google.com/presentation/d/1OSdw6D8vkjuXsGJVTACTxJfISSi7E8G1QGbgqSXZxog/edit#slide=id.p3",0 -"Presentation Link - -https://docs.google.com/presentation/d/1OSdw6D8vkjuXsGJVTACTxJfISSi7E8G1QGbgqSXZxog/edit#slide=id.p3",0 -"Presentation Link - -https://docs.google.com/presentation/d/1OSdw6D8vkjuXsGJVTACTxJfISSi7E8G1QGbgqSXZxog/edit#slide=id.p3",0 -"Hi: - -I made some changes to the presentation: - -Link here: https://docs.google.com/presentation/d/1lvexV8yKJckedrGRTk_63_K7vWhLv-z80yaKbvFTBbs/edit#slide=id.p - -Would love to discuss improvements. One of the reviewers had mentioned continuity issues and I would be happy to discuss how we can fix this. - -Best regards, -Jeet",0 -"it would be really great if we could do a meetup in Bangalore. I am sure there are lot of developers willing to use Kivy. I am one of them. I missed last year's con. I will try to go through the docs link that you have added. And thanks, this is one of my interest since java is not in cup. ",0 -"Hi Rakesh, - -I would love to do a workshop in Bangalore in one of your meet-ups. Btw for people who didn't get to be a part of the original workshop, I would be available the entire day of the workshop. We have a section for kivy in dev sprints if you want to come over and try to follow the old workshop material yourself I will be available to help out if you have any problems.",0 -Here is my talk slide. https://www.slideshare.net/secret/3kOc9GTTiNYxlv,0 -"Here is my talk slide for PyCon 2015 - - https://www.slideshare.net/secret/3kOc9GTTiNYxlv",0 -"For online slides please visit - - -http://narenaryan.github.io/Pycon-India-2015-Talk/",0 -"That's great Akshay, I have purchased this workshop ticket. as you said i will attend the Kivy dev sprints too. I have filled the registration form too and I have not gotten the confirmation. should I be waiting of should I contact some one else. -",0 -"Thanks for submitting. -Can you please attach the link of the poster for the talk?",0 -"@rakesh The dev sprints were just finalized, let's wait for one more day, if you still don't get a confirmation then you can e-mail me and I will ask the organizers to get in touch with you. -",0 -"Hello Praveen, - -Thanks for submitting the proposal. -http://etpython.info/media/releases/psf-python-brochure-vol.-i-final-download.pdf is not working. Please fix it. -Can you attach the poster image url in the proposal? - -Thanks, - -Chandan Kumar",0 -"Hello Chandan, - -I have added the poster deck. - -",0 -"Please assemble add the slides in a single poster for example check here: https://drive.google.com/file/d/0B3WeDMkqc0DoUFM3elJwV2F0cEU/view?usp=sharing -",0 -"I can help by sharing my experiences with the Chennai Python User Group, Chennaipy.",0 -"I would request to name topic as ""Discussion on Building and Running Communities"" ",0 -"Changed the topic , feel free to suggest changes and jot down any points that come to your mind on to the piratepad link http://piratepad.net/pycondiscussion",0 -"Vignesh, - We need to add even PyChill topic.",0 -"Hi Chandan Kumar - -I have fixed the link and have also added the link to the poster. - -Thanks and regards -Praveen",0 -Requesting a response again. One of the review comments mentioned issues with continuity. Can you please help me fix it?,0 -"Thanks akshay, I got the confirmation and i am selected for Dev Sprints. At what time is the Kivy dev sprints? ",0 -"@Rakesh, I guess they will start at the time other dev sprints do start. I will try to make it by 9:30pm.",0 -"@Akshay, you mean 9.30 A.M right not 9.30 P.M :) ",0 -"yes, 9:30 am :)",0 -"Please find venue and time detail for your talks: - -Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) - -Time: 11 am - 11:30 am - -Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 -Date for talk is 3rd Oct.,0 -"Please find venue and time detail for your talks: - -Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) - -Time: 11:30 am - 12:00 noon - -Date: 3rd Oct - -Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 -"Please find venue and time detail for your talks: - -Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) - -Time: 12 noon - 12:30 am - -Date : 3rd Oct - -Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 -Sorry the Time is 12 noon - 12:30 pm,0 -"Please find venue and time detail for your talks: - -Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) - -Time: 11 am - 11:30 am - -Date : 4th Oct - -Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 -"Please find venue and time detail for your talks: - -Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) - -Time: 11:30 am - 12:00 noon - -Date : 4th Oct - -Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 -"Please find venue and time detail for your talks: - -Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) - -Time: 12:00 noon - 12: 30 pm - -Date : 4th Oct - -Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 -"Satyaakam, - -This topic will be shifted to one of the Audi's . Time and venue details will be updated to you by the team on Conf day.",0 -"Please cancel this session. Encountered other important assignments that has come in. Assign this slot to some one else. - -Please take note of the same.",0 -"Please cancel this session. Encountered other important assignments that has come in. Assign this slot to some one else. - -Please take note of the same.",0 -"Guys, -updated the content slides. -Github repo for the code will be updated soon, struggling with slow internet speed at conference. ",0 -updated the repository which have all the demos.,0 -"Great info.I like all your post.I will keep visiting this blog very often.It is good to see you verbalize from the heart and your clarity on this important subject can be easily observed. Thanks again! -If you love gaming for unity games kindly visit…. - mobile app & game development -",1 -Can you share more relevant links to the project.,0 -"Hi, I've edited the doc and added few more links.",0 - ,0 -Looks good...,0 -"

    Nice. I'm curious to know what new features will be coming up on pagure. :)

    -+1 for this.",0 -"Hey, can you add some slides or more info about the project.",0 -Sure . I am in the process of creating them . Will put them up as soon as i finish them up . ,0 -All the Best. Do your best for all developer community worldwide.,0 -Thank you so much. @Limbani Bhavik,0 -Nice,0 -Nice bro !! I'm with you ,0 -@meet2 thanks man!!,0 - Good Job Bro..,0 - Good Job Bro..,0 - Good Job Bro..,0 -"Thanks soni kunjan @soni2 -",0 -Worth going to..,0 -"Good going, bro...!!",0 -This one is helpful..,0 -Deserves to be attended. ,0 -Feeling proud ...kashyap,0 -"Very passionate, dedicated and hard working guy. You will definitely love his sessions....",0 -great . Al the best bro,0 -"Hi Sourav, Impressive talk!. Great presentation for an undergraduate level and keep up your passion. ",0 -"Waiting to see Health Monitoring with Python. -We can team up together as i am working on python for UMLS, SNOMED and HL7. -See More : https://in.pycon.org/cfp/2016/proposals/python-for-healthcare-medical-terminologies-for-python-umls-snomed-ct-icd10-hl7~b28Je/ -",0 -@vickysam Cool. Thanx for contacting. Lets chat sometimes on e-mail at sandeep.nagar@gmail.com,0 -@Sandeep That's cool. You can catch me at vicky.chawda@gmail.com / https://in.linkedin.com/in/vicky-chawda-37b3a9100,0 -Looking forward to this talk,0 -Interesting stuff!,0 -"Siddharth, I'll complete those slides by next few weeks and I'll write here after completion. -Any input and expectation will help me. ",0 -"Interesting. -I use algo in stock market. My talk "" Application of Machine Learning and Sentiment analysis in stock market""",0 -"Will you show output of sentiment analysis using flask? -I use sentiment analysis in stock market. MY talk: "" Application of Machine Learning and Sentiment analysis in stock market""",0 -Looking forward to this talk. ,0 -@parthasen Yes I'll show the output of sentiment analysis using flask!!,0 -I'm looking forward to this. Good job @jargnar,0 -The blog post I linked should be updated in the next week to reflect some changes I made to the algorithm.,0 -This indeed does look very interesting! ,0 -Looking forward to this.,0 -Would love to attend this talk. +1,0 -Interesting one. Hoping to see this in PyCon 2016,0 -Indeed an interesting and useful topic. Looking forward to attend the talk.,0 -+1 to this,0 -+1 to this. Would love to attend the talk.,0 -The best person in Asia to give this talk. He is constantly one of the top package reviewer in Fedora land for many years.,0 -Can you please update you talk to show what all things you will talk? The current state of the proposal does not give any idea about the details.,0 -"The content may become difficult, but should be an useful talk for many.",0 -Just wondering about the standard library tag :) As Kivy is not part of the Python stdlib.,0 -Can you please add more details to your talk? It should show the things you want to talk about. Please also update the speaker's info to understand why you are the right person to give this talk.,0 -The current proposal shows more of a statement than a talk proposal with details about the talk. Please update your talk proposal to reflect the actual contents of your talk.,0 -"Thank you Kushal :-) . I tagged it this way on purpoes. If i got chance to conduct this workshop, i will share that why i tagged stldlib with this and why kivy should be be in stdlib.",0 -"this talk would bring some of the features of opencv 2 not in openCV 3 by default. Some of these features like SURF and SIFT absent in openCV 3 by defaut.Every time someone needs his old favourite tool,he has to build the binaries from scratch and then can use it. If we are able to write python libraries for opencv then that would be really great. This was just one instace, there are many more where getting a prebuit library really makes the work easier -",0 -"CFFI is good, and listening it from Noufal would be nice.",0 -Can you please update your profile to showcase your experience about flask?,0 -Thanks for this proposal.,0 -Can you please update your proposal to show more details about your talk? Like the major points you will talk about etc. Right now it is very small amount of text.,0 -Can you please update the speaker's profile section to showcase why are you a good fit to give the talk on this topic?,0 -Please update your talk proposal with more information.,0 -I have made an effort to keep the talk as informative as possible without introducing complexity into it. But you do have a point. It might end up being a heavy one.,0 -"Hi Kushal, - -Updated speaker's profile.",0 -Looking for this talk!. We are facing scaling problems .,0 -Yeah it is a wonderful concept ,0 -Yeah I too used django it works like a 'wow',0 -Yea looking for this good type of talks,0 -I think this is worth of listening,0 -I think this is worth of listening,0 -Now thats something interesting. Looking forward to this talk. ,0 -Good one bro,0 -Good job,0 -Please add more details in your talk proposal. ,0 -"Can you clarify a little more? If someone attends this talk, what will they learn? ",0 -"They will get a insight on how OpenCv gets more easier by using python. Simply , how more one can achieve by writing less and simple code.",0 -This talk needs to be more focussed. Talking about all the points mentioned in 30 minutes will not be possible in a useful fashion.,0 -Thanks. That clarifies it a little but I think a rough outline of what you're going to present will help us to understand what you're going to be talking about. Is this about using some kind of FFI to call openCV functions from within Python?,0 -"Yes FFi is the solution on one hand but what we can do is write complete newpython libraries that can be used for some basic operations that take a lot of lengthy lines of code in c++. Making it short and simple will be the key in the talk. -",0 -"Hi Kushal, - -What other details do you want in the talk proposal. I will upload the slides in another few days. - -Thanks and regards, -Annapoornima",0 -"So, is your talk about reimplementing some parts of OpenCV in pure python?",0 -"This is what actually I was looking for, thanks man good job :) ",0 -"Hi Annapoornima, -Can you clarify what is the purpose of this IoT solution? What is the problem you are trying to address? -Kind regards",0 -great work !!,0 -If you want to understand fedora package ecosystem then you don't want to miss it.,0 -Precise and informative! Piqued my curiosity further to read about Recommendation Engines. Waiting for your next write up!,0 -"Looking forward for this talk -",0 -Thanks @abhay @tushar3 . ,0 -"This proposal is selected to be for an ""Advanced"" audience. Would it be possible to add the expected outcome for the audience? As in, at the end of this presentation, what are the things they would be able to achieve?",0 -"A small set of comments - is this an overview of the experiences and challenges faced by the presenters or, does this talk intended to guide the audience (real-time) into submitting patches into the OpenStack project? Also, it does not seem very clearly articulate about how it aligns with the general theme/focus of PyCon.",0 -"This presentation is slated for an audience classified as ""Intermediate"". I'd request that the speaker (re)consider the agenda of the talk. The first two items should be provided as (pre)talk requirements and the various challenges/complexities of deploying a number of (choosing a wider pattern of applications would be great!) applications in the target environment would be a good place to start from. From thereon, moving to aspects of application lifecycle maintenance, security, availability/resiliency etc would be good-to-have topics.",0 -"""Measuring Semantic Similarity between sentences in Python"" should probably read ""Using Python to measure semantic similarity between sentences"". - -There's been a number of approaches on similar topics using nltk - if you'd like to cite them for the audience to have a conceptual grasp of the problem domain you are trying to address, it would be nice to do.",0 -"Do you happen to have a list of useful websites which could be scraped and such? I am suggesting that a bunch of ""ToDo"" or, ""Now that we have shared our knowledge, how about you/the audience consider working on these sites"" kind of list.",0 -The proposal (as read here) does not seem to clearly articulate the outcome for the audience - what would they be able to do after this talk?,0 -"The proposal (as read in the current form) does not provide adequate detail about the expected outcome for the audience - what would they be able to do at the end of the talk? Also, the scope of the topic would need some re-think. ""Core Python"" sets off expectations of deep/technical discussion around specific aspects of the programming language/design and at present the talk is a list of topics which should be available to anyone with access to documentation.",0 -"The prerequisites section could do with further detail. ""Basic knowledge"" could mean a variety of things and the audience should be clear about the expectations being set up by the speaker.",0 -"The proposal does not have adequate detail about the outcome from this talk - what can the audience get done after this talk? Also, the prerequisites section is somewhat vague. - -The current form of the proposal seems to be about ""how to use Ansible for consistent deployments"" while the ML systems are a workload specific aspect of it. Perhaps the author would (re)consider the description.",0 -Sure I am adding outcome for the audience to description. ,0 -@sankarshan The talk would enable the audience to actually get acquainted with the two above-mentioned architectures and get in a position to make a well informed decision to zero down on following either of the practice in accordance with their needs and purposes . The talk also would give them clarity on the decision to adapt a framework amidst the available python based frameworks . ,0 -"I've recently wrote a blog post for ""Getting started with scraping in python"". The site I used for my tutorial is this ""Pycon India 2016"" site itself. Please have a look at it http://satwik.ghost.io/2016/06/19/any/ . <- This is the temporary link as of now. -Regarding useful sites to scrape, there's no limit to that. A rule of thumb may be ""Whenever you want to use some data that any website is displaying, but that website doesn't have an API then you should scrape."" For example, you can scrape bookmyshow.com for list of events in your area, Flipkart for making sites like buyhatke, cricbuzz for getting cricket statistics and score and so on. However, I'll make a list of all the practical applications I could think of and upload a link to it soon. Thanks for your suggestions by the way :).",0 -There's a fine line between scraping a site and DOSing a site. Please explain to the audience the importance of not accidentally bringing the site down.,0 -"I would request that you re-visit the intended audience. I agree with your premise that Python's adoption and popularity is increasing. However, the order in which you desire the audience may just be too niche/difficult for a PyCon (and I'd be happy to be proven wrong). Instead, if you focus on the newbies and demonstrate Python's ability to be extended into calculation of risk and such, you'd probably have an audience who are hooked (there have been previous instances where risk analysis etc have been great talks).",0 -"I'd suggest that you assume that the audience is aware of the first two topics (in your proposal) and for the subsequent items, please provide a link to a dataset of reasonable size which you'd be working with and they can tinker around to reach similar results.",0 -"Do you intend to take a specific case and walk the audience through the problems and solutions in order to arrive at this stack? Or, is it an overview of how the components fit together?",0 -"Thanks, sure that helps",0 -"The typo in the title would need to be fixed. That aside, would you be using a mock application to demonstrate the test paths (along with how the actual code can be written better to aid testing)? Or, is this a general overview? - -It is intended at an ""Advanced"" level, but the proposal does not seem to address any of the topics which an advanced user of such a flow will be faced with.",0 -"The current set of topics being covered in this proposal would appeal to a beginner rather than an intermediate practitioner. Would you like to add more detail about complexities and challenges involved in building such an infrastructure or, is this a general overview?",0 -Its neither of those. 1 would be a sales pitch for SPA with redux as solution. 2 would just be an overview. The talk delves into much finer technical details mentioned in bullet points in the description. Let me know if you have any further queries. Happy to answer them. ,0 -"I noticed that there is a workshop proposal with the same title - are these two unique bits or, the same thing? Building hyperlocal weather sensors is an interesting exercise. Do you intend to cover how your audience can DIY and how it can be useful for them?",0 -"I wanted to check if you have previously presented on this topic at any local meetup. This is an interesting proposal and often, these form of proposals evolve if the speaker has been discussing these over a period of time.",0 -It would be good to have a link to the dataset you'll be using as part of the demo. The audience can choose to continue after the talk and learn.,0 -"I'd recommend turning this talk on its head. Instead of ""a gentle introduction to Ansible"" (which is a good thing, but fairly mundane), how about building up good habits in beginners and showing them how some of the common problems/pitfalls from code -> deploy can be managed via Ansible?",0 -"Hi Sankarshan: - -Yes, I am sorry for the typo, I meant Beginner's level only, I will change the level, basically the talk would just need a basic understanding or awareness of AWS EcoSystem and its components. - -Regards, -Suman++",0 -"Thanks, I've added a slide for 'Ethics of Scraping' :)",0 -Fixed..,0 -"Yes i would take a demo application and run thru the end to end testing of API using requests and unittest module. - -The Description of the talk is updated accordingly",0 -"@Sankarshan, I want to present a talk and do a workshop as well. Talk is preferable. If time permits and if I have people to do the DIY workshop, I am for it. - -@misccold, I am presenting how to collect temperature data and pass it on to the Raspberry Pi. Further, there are a plethora of things that can be done with data, some of the things that I can think on top of my head are, display heat maps, develop home automation tools, etc. Sky is just the beginning for limits.",0 -"Hey Sankarshan, thanks for asking. I have discussed about these topics with my colleagues and friends many times. Previously i have given a bunch of talks in few colleges and other meetups. My previous talks revolved around IoT and python mostly. In next month's ChennaiPy meetup, i will be giving a talk on the above proposed topic.",0 -"The goal is to guide attendees through the contribution process and encourage them that given the open nature of open source communities (in terms of documentation, guidelines, bug triage, help on IRC, review feedbacks), it becomes really simple to get acquainted with the workflow quickly and make an initial first contribution and then go on making more contributions slowly and gradually as you learn more. - -Since OpenStack is a Python based Open Source Project that is why we submitted the proposal under the Other Category.",0 -"You have written in your first line ""This workshop"" but categorized it in the form of talk. Is it suppose to be a talk or a workshop?",0 -"I had a confusion between a workshop and a talk, since the way I see it, my proposal lies between workshop and a talk. Still thanks for pointing this out. I will edit it.",0 -"It seems more apt for a workshop to me! Btw, nice proposal, looking forward for it :)",0 -"CI is a must feature for any git repo and having it on pagure is a must - -I am interested in attending this talk",0 -"Hi @megha , than you for submitting the proposal, is it possible for you to share the video / slides for the events you have spoken in the past. - -Looking at the description it seems to be more oriented towards MySQL, can these ""Best pracitices"" be applied to any DB or specifically MySQL. What is specific to python in this talk or does it revolve around databases only ? -",0 -"Can you provide more details / examples / sample code for ""Automated API Security Assessment tool"" ?",0 -"Any session by Anand is worth the time. His clarity of thought and simplicity of presentation cuts through all the cruft and explains what is needed in a clear, precise way. ",0 -" -Thanks for responding. Of course I can submit more details. Where do you want me to share it ? - -Hilal",0 -Thanks Saurabh. ,0 -Would love to attend:-). I wasn't aware about Kivy before this. I request Pycon teamm to arrange this workshop...,0 -Would love to attend...Good Job..:-),0 -"As Kivy is free and open source software ,it will have a wide scope, all the best !",0 -"@Kajal, Updated the talk. The earlier content was way too generic. ",0 -I had an opportunity to be at the audience when this talk was on Chennaipy. I had never thought about CPython in this angle. The talk gave me the insight on things that happen behind the screens. Looking forward to know about the reaction of PyCon audience.,0 -"Thank you for your submission. While the proposal, and your slides look fine as they stand, I have two questions/suggestions: -* Your slides cover basic graph theory. How about adding: - - Some example usages of graph networks in real life in order to motivate your audience - - Some advanced examples of real-life problems that are more tractable to solutions through graph networks; maybe contrasting graph networks to more commonly used relational databases -* Why a workshop? Is there enough material that cannot be covered in 40min., and needs 2-3 hours?",0 -"Thanks for showing interest. I have explained that basic knowledge of Selenium, Python and HTML is needed. Audience can expect a simple and helpful talk, which will help them to get data by themselves for their projects. ",0 -"Thank you sir for your humble suggestion. We will be adding some real life implementation of network sciences in further slides. we are still preparing the slides. There are many real time examples to discuss and brainstorm that will motivate the audience with great curiosity. we will update the slides by today. -Yes, we thought of giving some hands on experience to audience in network analysis but if it is not feasible we can shift it as a talk session. We are also planning to add some code snippets that will help attendees to understand the domain at better extent.",0 -"""""Thanks for your submission. Please provide more details, as it is difficult to judge from this what is being proposed beyond a basic introduction to app development with Kivy. Kivy has been around for a while, and many people have probably seen introductory talks. What are you going to demonstrate that is new, and why are you suited to making such a presentation. - -Please note that time is short."""" - -@Reply: Thank you sir for your humble comment. yes, I will be covering the basics along with the development of small ping pong game. In latter part, we will be developing a small git interface application with which we can update and commit the various changes in the code stored in our github repository. Its Functionality might be limited but enough to carry out basic operations like edit,update & commit. Thank you.o",0 -@prastut Its good enough! :),0 -"Seems interesting and informative, Looking forward to it!",0 -"Please add what your talk will cover about MicroPython. It will be a good idea to add talk outline, see https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example.",0 -It is not clear from the description what you will be covering in your talk. Can you please add a talk outline? See https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example.,0 -Looks like you trying cram in a lot of things into a single talk. How about focusing on one of them instead?,0 -"While you are working on the content, it would be good to make a talk outline available in the talk description. Please see https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example.",0 -"The talk looks interesting. The LinkedIn link is broken, can you please fix it. - -Also it will be great if you can elaborate on the topics you have mentioned. For example, what do you mean by ""Usage or Proper keywords""? Also what do you mean by ""Proxy layer""?",0 -"The slides seem to be inaccessible, can you please fix that? Also is the PyUnit you are referring to, the unittest module that is part of the standard library?",0 -Looks interesting ,0 -Looks interesting ,0 -Looks interesting ,0 -Added the outline!,0 -Quite interesting .. ,0 -I have added the details. Please have a look at that.,0 -"Thanks! BTW, formatting using MarkDown will make it appear better.",0 -"Yes, pyunit is part of python library.",0 -"Thanks for letting me know, fixed the link - -those are the reasons this presentation is for but if you cant wait till i attach a presentation to this talk, you can always ping me on the side ",0 -"Making things a bit explicit, will increase the chances of your proposal getting selected. Also the talk selection happens before the slide upload deadline. So it is better to beef up the talk description.",0 -Is this talk about BDD in general or is it about a particular framework?,0 -"sure, will do",0 -I have read Kashif's code and discussed some technical aspects with him. It would definitely be useful to pick his mind through this talk. Bumped it up.,0 -This is mostly about BDD framework with python and selenium. We are focusing on front-end and back-end automation using python selenium where test cases are in BDD.,0 -That's very nice. ,0 -Please provide an outline of the workshop. See https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example.,0 -"It will great if you can break the topics into subtopics and provide an outline of the talk. See https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example. - -In my opinion, the talk would be interesting if the talk includes real world implementation issues, solutions tried, what worked or what did not, etc. Or how this was used to address a specific real world problem, like in pollution control, outcomes, improvements, etc.",0 -"Thanks for the details. Please be aware that the talk duration is 30 min + 10 min for questions. Rather than talking about many different things about Micropython it would be nice to focus on one aspect. For example you might just want to drop of the part three. - -In part one, you might just want to focus on those areas that are different in Micropython. For example it would be interesting to talk about Micropython's viper and inline assembler support, and other speed optimizations done in Micropython. - -In part two, not sure why you want to use ""few"" different boards. Wouldn't a single type board suffice? You might want to list out the demos you are planning to do.",0 -Looks Interesting,0 -Looks Interesting,0 -"Thanks for review, I changed it to ""beginner"". Topics which you suggested will discuss with interested folks or will propose a session during breakout which will focus on lifecycle management, maintenance, security and availability. ",0 -"I don't think that 30 min will be sufficient to talk about the entire internal architecture of Micropython. I think I can start by introducing the board and then starting from simple examples to various code optimization parts like using native code emitters and micropython's viper code emitters. -I said multiple boards because say if you have esp8266, you can't get the inline assembler functionality( the core is based on Xtensa ) . esp8266 is the cheapest micropython board that you can get online. just for Rs.200. I can cover those areas using pyboard. I am getting 4 pyboards next week. :) - -If I talk too much about the internals then I am not sure that how many of the audience can catch-up all those. It will be better to cover those areas through examples without opening the ""C"" part of it. - -I wish I could get more suggestions and comments here. - -Thank you",0 -Sounds interesting! Looking forward to your talk. :),0 -"After learning about Machine Learning, I am all hyped up about every field which deals with data and recommendation engines sound great. -",0 -Will be adding slide in few hours. :) ,0 -"I received an email saying Reviewer01 has left a comment, but I can not see it here after login.",0 -The framework is ready to use right now. However by the time the event is held I expect many more features to be added to the framework.,0 -"Why is this classified under Python 3k? There is nothing here that talks about 2 to 3 migration, or writing compatible code. May be ""Others"" will be appropriate.",0 -"Should this be classified under ""Network Programming""?",0 -"Should this be classified under ""Network Programming""?",0 -"""Data Visualization and Analytics"" might be a more appropriate category.",0 -"""Scientific Computing"" might be a more appropriate category.",0 -"""Scientific Computing"" might be a more appropriate category.",0 -"The ""Embedded Python"" category is for hardware, electronics, and interfacting. Please re-categorize to make sure your talk gets better visibility.",0 -"Changed to ""Embedded Python"". -Thanks for the suggestion.",0 -what is the problem solving ?? then next ... ,0 -"I am not sure if I am missing something here, but BDD is a development style / process not a ""framework"" in itself. Cucumber & Robot are BDD Frameworks. Please correct me if I am wrong. - -",0 -"You have good internet connection as a pre-requisite. - -Internet issues are common at conferences. You should plan to have things working locally, instead. ",0 -"As Vijay already pointed out, can you please make the slides publicly viewable? -Thanks!",0 -"I second Vijay's suggestion of beefing up the description. An outline with -finer detail on what you want to cover will go a long way! - -If you have slides/videos of any previous talks you have given, that would be -helpful too.",0 -"It should be manageable without internet as well. - -Just in reply to one of the query thru mail, I will plan to keep this talk as simple as possible to make beginners understand what is REST API and why it is important to test an API in any application first and then making them understand the concepts of testing REST API with the help of GET/POST/PUT/DELETE methods and will detail out the demo scenarios for testing an API and then will go ahead with the use of python libraries(Requests and Unittest) for testing the REST API's. - -Also by built-in features of Requests I mean to say how with the help of requests one can GET/POST the data from/to a service and how to validate the API response and how you define the headers/params needed to access the API's. - -Try to keep the talk as simple as possible for the Python Novice to understand - -Updated the Pre-requisite accordingly.",0 -"Hello Arthy, - -Thank you for proposing this talk. - -It is not clear which tool you are describing in the description. Is it an open -source tool that the audience will be able to use for their work? If not, what -are the take aways from your talk? Are there other tools like the ones you are -going to talk about? What are your take aways from building/using this tool? - - - -",0 -I had classified this as 3k since I've only tested the code on 3k. Now that you mention it it does fit the others category too. I'll ask an admin and change if allowed.,0 -"Could you please update your proposal with your slides, at least a preliminary outline of your talk. - -We would also need links to previous talks experience in public speaking etc. - -It's also to be noted that this talk was in draft mode and made public after deadline.",0 -Could you please upload the slides of your talks along with details of any previous experience giving talks or workshops etc.,0 -Can you please upload a preliminary outline of your talk slides? Something that can help reviewers.,0 -Nice ,0 -Nice ,0 -Excellent. .very comprehensive stuff. .Good luck ,0 -"Thank you for the proposal, looks like an interesting topic, I looked at the talk shared and it would be great if you can provide some details on the following questions: - -1. How different are you planning this talk to be from the one given at PyDelhi. Please share a concrete plan. -2. Until the example shared by you which talk about the deal codes and it's user, the talk looked fairly simple of How-Tos of various tools, which I will advice to restrain from. The example looked like it's more a porblem of grep's then why this elaborate setup. -3. Since you are one of the largest e-comm companies, it would great to get some insights on numbers, throughput and scale challenges. -4. Please list down the libraries you will be using to talk to various components like elastic-search, Kafka, elastic-alert, map-reduce etc etc. - -If not structured well, this talk will be too much in too little time.",0 -"You can update the description with the same, that would be great.",0 -"Hi, - -Please update the description with a proper outline of what the talk is going to be about. - -Can you talk about: - -1. Scale at which Apache Storm is being used. -2. Is the use-case mentioned by you a production use-case or ""How to get started with Apache Storm"". -3. What libraries are you planning to share like StreamParse, Pyleus or any other. Why you would choose one over the other ? -4. What kind of deployment strategies do you follow to deploy storm cluster like green/blue deployment strategy or something else ? -5. Since you are mentioning Big Data, will you also cover how Storm cluster can be tuned and configured beyond basic deployment ? -",0 -"Prerequisites, is what the audience should know before attending your talk.",0 -aah... I think in hurry I typed it in the wrong section. Apologies. I'll update the section accordingly Vijay Kumar,0 -"@akshayaurora -I have shared the link to my slides. Note that this is just my first draft. Looking forward to your feedback.",0 -"You might want to add more information, unless this is a joke. :-)",0 -"Well the description talks about Box0. It does not what you are going to cover in your talk. Please add an outline of your talk, see https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example.",0 -"If you have done previous talks on the subject at local user groups, please mention them in your proposal. ",0 -I have taken workshops/seminars previously in my university but not on the same subject. Will that be useful?,0 -Excellent stuff..,0 -Excellent stuff..,0 -"Hi Vijay, I think we do not use keywords like 'style' or automation 'process' in organizations as we QE's see everything as in every tool as a framework and that is the reason we used the word 'framework'. Also our perspective while presenting the session will be 'Automation' and not developing anything new and we already have implemented it and use it regularly for our Behaviour Driven automation in our team. You can refer the wiki of the same where the keyword 'framework' is used along with BDD many a times: https://en.wikipedia.org/wiki/Behavior-driven_development . Still, If you want we can change or remove the work 'framework' from the title.. -Let me know if you have any more questions apart from this.",0 -git now has bit more content on the talk and would fill up electronic circuit diagrams as well as data analysis results when we finalize our data analysis part of experiment in coming weeks.,0 -"Please fixup the section, so that the talk gets better visibility.",0 -"Please update the section, so that your get better visibility.",0 -You might want to include that under Speaker Info.,0 -I just thought that it would be a good idea to focus on the areas that made MicroPython special. I don't think Micropython does anything special when it comes to tokenizing and parsing (correct me if I am wrong.),0 -"Hi Akshay, - -I have just submitted to the reviewer the presentation abstract, Please check. - -https://docs.google.com/presentation/d/19hr8I7ZgdOT-uQI-7fHB1QQ8tRvSmg_HAY0V0RDLjH8/edit?usp=sharing - -I have also shared my blog in my profile. Otherwise a good speaker :)",0 -Surely I will update more details about this talk. This will give you a clear idea about the topic and also the takeaways.,0 -Added presentation link,0 -You are right. Lexical analyzer/ Lexer and tokenizer are functionally the same as the original Cpython. But the way Damien wrote these blocks are in a different way compared to the typical cpython implementation. ,0 -"OK. Didn't realize that. If you have a point to make, then fine.",0 -Looking forward to this.,0 -"Thanks for your comment. - - This talk is intended for beginners who wants to know how to get - started with Apache Storm for Real time Processing. I do use storm - to process the huge data that we get from multiple sources (Spouts) - -The use case that I mentioned (Sentiment Analysis) is just to motivate the attendees towards it. Processing the data (Tweets) that we get from Twitter will be one use case that I will be mentioning in my talk. - -I will be using Petrel Library so as to make it simple and easy to build and help others to understand better. - -And this will be a basic deployment. - - - - - ",0 -"Dear review team members, - -Thank you for sharing positive review about our outline talk. Appreciate it. - -Wish to share with you the paper and power presentation accompanying the talk have been added in the Content URLs section. We would love to hear your review on our paper. Wish to ask you whether it would be possible for PyCon India papers to get accepted in The Python Papers Journal (http://ojs.pythonpapers.org/index.php/tpp) - -Wish to share with you that we submitted papers in PyCon Singapore conference in 2009 and all of them were accepted and later published in the above mentioned Python Journal. We are submitting our paper to PyCon India 2016. Looking forward to your review. - -Regards, - -Manu Sheel Gupta",0 -"Dear review team members, - -We look forward to your review on the paper and presentation. - -Regards, - -Manu Sheel Gupta",0 -"Hi, Can you provide few code samples that you will be sharing, the description is too less to understand how the talk will be structured. -",0 -Please update the description.,0 -"Hey , thanks for taking interest in my proposal . - -About code samples : My talk targets beginners who might know how to code or might not . Considering this case i have tried to keep the code as minimal as possible but have focused a lot on **LIVE DEMO's** and **EXAMPLES** . - -here is an example of how i will explain topics : ( - -> this is just an example , i have not given full details here . In -> real talk it would be more graphical and interactive - -) - -**XOR** - -1. description - -2. a few properties of XOR - - 0 ⊕ 0=0 1 ⊕ 0=1 - 0 ⊕ 1=1 1 ⊕ 1=0 - -3. Bitwise XOR : python provide ^ operator to perform bitwise XOR on integers. It does this by first expressing those two integers in binary , and then performing XOR on their respective bits. Hence the name, bitwise XOR. - - 73 ⊕ 87 = 0b1001001 ⊕ 0b1010111 - - 1 0 0 1 0 0 1 (left) - = ⊕ ⊕ ⊕ ⊕ ⊕ ⊕ ⊕ - 1 0 1 0 1 1 1 (right) - = 0 0 1 1 1 1 0 - = 0b0011110 - = 30 - -4. One-time pads : explanation of one time pads . - -5. Attacks on One time pads : reuse of same key , crib drabbing . - -6. Live example : - -![Plain text][1] - -![cipher text][2] - -![Reused key and XOR of ciphertext][3] - - - [1]: https://s31.postimg.org/ep0y1mdi3/image.png - [2]: https://s32.postimg.org/etwhsq3xx/image.png - [3]: https://s31.postimg.org/qef1k5ox7/image.png - - -How the talk will be structured : the talk will proceed in same way as i have provided in description - -i will start with XOR ( explain what it is ? , implementation ? , attacks on it ) and will follow the below sequence - - 1. XOR - - 2. One TIme Pad - - 3. Ciphers : block ciphers , stream ciphers - - 4. TLS - - 5. Diffiew-Hellman Key exchange - - 6. Authenticity - - 7. Cryptographic Hash Functions - - 8. Password Storage ( brute force , dictionary attacks , salts , bcrypt - , scrypt ) - - 9. Public Key Cryptography - - 10. Key Generation - - 11. Signing ( RSA , chains of signatures , GPG Key Signing ) - -",0 -"@Kuldeep could you please upload the contents of your presentation? -Along with the links to any prior experience in giving a talk.",0 -"Could you please upload the slides of your talk, have you had any previous experience giving talks etc, can you post links to your experience in public talking if any.",0 -"Hello Akshay, I'm a regular speaker at conferences, few links are available above at Speaker Links. Please have a look !",0 -Seems interesting . I will surely attend this one ,0 -Looking forward to this one ,0 -Your comment was informative . I am excited for your talk ,0 -the contents are now added...the talk will showcase the power and possibilities with python. The code and the logic behind the whole circuit is not difficult to grasp.,0 -"Could you please upload your slides asap? - -The slides don't have to be detailed just a overview will do for now. - -We need you to upload the slides within the next 3 days to be able to consider it for selection.",0 -"@AkshayArora Presentation content is updated, although It will still be evolving till the last week.",0 -"Can you add timing for your talk, something like:: - -introduction: 0-2 minutes -Plyer: examples: 2-10 minutes -Pyjnius examples: 10-15 minutes -... - -This will help you structure your talk and stick to the time allotted to you.",0 -"Have forwarded your question about access to reviewer comments to people who manage the site. However, are you sure that you are logged in, and looking at the correct tab? There should be a Reviews tab to the right of the Comments tab.",0 -Update with Slide link,0 -"[Draft presentation for review][1] - - - [1]: https://github.com/jjaimon/conferences/blob/master/talks/PyCon%20BLR%202016/PyCon2016-iot-platform.pdf",0 -"I just got a mail stating, i need to reply for the reviewer's comment. here is the reply to the following comment. ""Thanks for your submission. Please provide more details, as it is difficult to judge from this what is being proposed beyond a basic introduction to app development with Kivy. Kivy has been around for a while, and many people have probably seen introductory talks. What are you going to demonstrate that is new, and why are you suited to making such a presentation."" - -@ Reviewer01 : -Thank you sir for your humble comment. yes, I will be covering the basics along with the development of small ping pong game. In latter part, we will be developing a small git interface application with which we can update and commit the various changes in the code stored in our github repository. Its Functionality might be limited but enough to carry out basic operations like edit,update & commit. Thank you.",0 -@vickysam sure. Please check the presentation at git address. It will be completed in coming time. We are working on performing experiments right now and then data will be processed using python.,0 -"Kindly, ignore last two comment, i didn't notice there is reviews tab to reply to the reviewers.",0 -I have updated the proposal and added a presentation about what the workshop will be about.,0 -"Hi, - -Can you please provide some concrete examples and problem statements, where you are using this library and the others failed. - - -Also, Curious to know are you one of the main authors for this library because the abstract is very similar to what the library documentation is : https://cryptography.io/en/latest/ ",0 -"No , i am not the main author of cryptography library . I just use that library in my work . About the description being similar to documentation , it is quite same because documentation fit my idea and what i want to present at the talk . - -Most of my criticism of other Python cryptographic packages has already been stated in Pycon 2014 . - -You can see them here : https://lwn.net/Articles/595790/ <- The state of crypto in Python - -Talk Video : http://pyvideo.org/video/2583/the-state-of-crypto-in-python - -Qualification of package contributors/code - -Jarret Raim : Raim is the cloud security product manager for Rackspace - -Paul Kehrer : Kehrer is a software developer for Rackspace working on the Barbican key management service for OpenStack - -Other contributors : https://github.com/alex",0 -Updated Description and Outline for the talk,0 -"Hi Konark, - -Though I have chosen MySQL as an exemplary name but yes the session will be around the various security features available for the database that an admin should deploy to make the instance highly secure. - ---megha",0 -"We are going through deployments this week, could not manage time. - -Please find the presentation link which I created for presenting in a meetup. - -https://docs.google.com/presentation/d/1Ng6PU8N3pr25ywVQcldCbr9x6YbYBzhi5oxA1CkHAfY/edit?usp=sharing",0 -"Hi, This is a nice topic to cover. Topics covered in the slides seem pretty exhaustive, please consider the content to match the talk time. -Can you add Python code snippets for the application and the Python bindings for AWS Lambda, this maybe useful to audience? ",0 -"You could add how Python contributed to building a distributed version control system. -You could also focus on certain aspects of Mercurial which will be compelling for developers to move away from other version control systems. -Also, bring other the architectural advantages in Mercurial that makes it stand out. If organisations want to host their own version control, can Mercurial be better? -",0 -"I was mainly targeting the audience who has less or no knowledge about such things. Either I have to target developers, or I have to start with the basic and then end with all these things which you suggested. I think the later one is better. Thanks for the suggestions, I will surely include them.",0 -"Hi Sankarshan -I will be using raw data and few corpus which come with NLTK. So no specific data-set to be downloaded. -",0 -"Wrote a blog article based on the proposed topic, please see http://www.bravegnu.org/blog/python-byte-code-hacks.html Let me know what you think.",0 -"Talk content: https://gist.github.com/manojpandey/41b90cba1fd62095e247d1b2448ef85b - -Most of it would be more of an interactive session, but I've added my thoughts in the gist above what I'd be discussing. I'm open to more ideas on improving it. Thanks !",0 -"Thank you so much for the comments and details, the content looks good. I would give the following suggestions: -1. Need to structure it better for a 40 minute slot. -2. Need to ensure the examples are showcased using Python libs.",0 -"> Thank you so much for the comments and details, the content looks good. I would give the following suggestions: 1. Need to structure it better for a 40 minute slot. 2. Need to ensure the examples are showcased using Python libs. - -1. about structuring the talk for 40 Minutes . I have been doing practice/ rehearsels with my slides and most of the time the talk comes to an end in 35 min . - -2. about ensuring that examples are showcased using python libs : as I said in my abstract "" This talk is aimed at programmers of any skill level that lack crypto knowledge. "" I will surely show examples / live demo with python libs but some examples are best explained if they are simple . - -P.S. i know the slides looks like those are too much , but trust me don't go on number of slides , they will be turned to next slides quickly . - -P.S. I will add some examples with python libs in my slides :) ",0 -"Around 40 slides including relevant code and version of packages will be uploaded soon. Few slides are uploaded, rest are in progress. ",0 -"Not sure why this is classified under ""Concurrency"". Concurrency is for topics related to Twisted, threading, asyncio, etc. It would be best to categorize it under ""Embedded Python"". Classifying it under the right category will improve the visibility of your talk.",0 -"I have received your comments that more details are needed -and I am working up a draft outline/slide set to convey that.",0 -"Added URL for Draft power point. - -There are lot of improvements in terms of fonts,color,snapshots and examples needs to be done. This is work in progress document.",0 -"The problem I will discuss is somewhat like: -Currently, OpenStack's end user stories for both command-line and application developer-consumers of OpenStack-based clouds is confusing, fractured, and inconsistent. This means that if a non-operator or OpenStack developer attempts to consume more than a single service from a deployed OpenStack system, they face an uphill battle. With a consumer application requiring potentially 22 individual python-* clients to install, each with different APIs and nuances, it becomes increasingly difficult to consume OpenStack clouds. The python-openstacksdk project proposes a new project with a single API namespace (""OpenStack"") that would provide users with a single point of entry and series of supporting functions/methods from which to build applications and tools. As a side effect of this consolidation, it becomes very easy to derive a unified CLI, such as OpenStack client, or specialized pre-service CLI tools. However, it is important that the definition of SDK -- the compilation of the APIs and developer functions -- and CLI tools stay separate as it is easy to conflate the idea of ""clients,"" which is the state we have today. -I hope I answer your question.",0 -"Dear review team members, - -Thank you so much for sharing feedback. Appreciate it. - -We have added 3 case studies and will be uploading the revised ppt by today morning. These case studies have been derived from our product implementations. - -We would be happy to make further additions and revisions if the review team feels the need. - -Thanks again, - -Manu Sheel Gupta",0 -"Dear review team members, - -Thank you so much for sharing feedback. Appreciate it. - -We have added 3 case studies and will be uploading the revised ppt by today morning. These case studies have been derived from our product implementations. - -We would be happy to make further additions and revisions if the review team feels the need. - -Thanks again, - -Manu Sheel Gupta",0 -I think I would want the focus on concurrency (see the changed title). I will not be discussing any embedded stuff.,0 -"Isn't the title misleading. Isn't the workshop just about Docker and Kubernatics? Django happens to be the example you might be taking, but the flow wouldn't change if you replace Django with Rails. Did I miss something? -",0 -"The workshop is NOT just about Docker and Kubernetes. Its more about Scaling Django with Kubernetes. Similar ideas can be applied to Rails. - -The talk is more of a demo to how you would start up with a sample runserver in django, to gunicorn, which later will be monitored using supervisor or any process manager, then eventually leading to container. Now when it comes to docker, how would you address issues of multiple containers, how would you go about securing them, what is the typical architecture for django in a cluster, so on and so forth. ",0 -"Docker is an interesting tools many Python developers would be interested to know about. I've looked at your notes and it looked like it doesn't cover some important topics are required even to move a simple webapp to Docker. Could you please see if you can try to include the following topics: - -- Introduction to volumes -- persisting data in containers -- Example to how to dockerize a simple python CRUD webapp with mysql/postgres database -- More emphasis on docker-compose as that would make it possible to manage multi-container apps easily",0 -"Hi, Plz help me where to upload the presentation.",0 -"Dear review team members, - -We have updated the content URL of the presentation and have added 3 case studies. We have shared slides about them from a product implementation perspective. We wish to share that we would be explaining the issues encountered and lessons learned as we go case by case. - -Looking forward to hearing your feedback. - -Regards, - -Manu Sheel Gupta -",0 -@konark - We have modified our talk basis of inputs provided by you :) let us know what you think of it now. ,0 -@konark - We have modified our talk basis of inputs provided by you :) let us know what you think of it now. ,0 -@konark - We have modified our talk basis of inputs provided by you :) let us know what you think of it now. ,0 -I will upload the presentation asap. I am currently incapable of doing so due to lack of communication facilities in Kashmir valley owing to limits put on Internet in the valley.,0 -Sure. We will include those suggestions in the workshop material. With respect to docker compose we want to keep the workshop neutral to docker compose and Kubernetes. So we have to talk about both. However we will not be able to cover everything in 2 to 3 hours. But participants can go back and follow the same material and finish the workshop. ,0 -"Dear review team members, - -We have added 2 presentations that we would be sharing with the audience before the session - - -1. Case Study - Make an in-app payment system using Python based Rest APIs and Cordova app framework. -2. Steps on how to create a hybrid mobile application. We'll be sharing with the audience the demo on using Python based Rest APIs in hybrid mobile applications that we have implemented for our clients and shared in the content presentation. - -Regards, - -Manu Sheel Gupta",0 -Apache storm ! How exactly can it help us Shaik asifullah,0 -Apache storm ! How exactly can it help us Shaik asifullah,0 -"Thanks Riyaz. Say you want to analyze the twitter data flowing in real time, and to process such a large flow of data, you use Apache Storm. Attend the talk, to know more.",0 -"@Sandeep Congratulations, Your talk got selected, will be eager to see Python in Health Monitoring :) ",0 -@vickysam: Thankyou. My team will be eager to meet yourself and share our experiences too :),0 -Let's catch up @ the Event. :),0 -Looking forward to it. ,0 -"Please add the presentation link in the Content URLs section, so that it is obvious to reviewers",0 -"After considering your comments, I have renamed the talk to be more generic, -created an initial set of slides that I've shared with you, and shifted the focus -to the ""why"" of architectural decisions. In the talk I'll discuss the use of -Pika/RabbitMQ, Pyramid/Zope, ZSQL, SQLAlchemy, RESTful principles, Python -decorators, AngularJs and websockets over the STOMP protocol. - -I will keep the mention of healthcare to a minimum, to make the talk useful -to anyone building a 500-1000 user all-day business-class web application.",0 -https://github.com/suman-d/AWSBoto3,0 -can you compare event driven architecture of python with popular frameworks/applications like nodejs/expressjs.,0 -can you compare event driven architecture of python with popular frameworks/applications like nodejs/expressjs.,0 -can you compare event driven architecture of python with popular frameworks/applications like nodejs/expressjs.,0 -can you compare event driven architecture of python with popular frameworks/applications like nodejs/expressjs.,0 -"Hey Akriti, I think it would be very interesting to compare with other frameworks. But, I am not very familiar with building web services using JS. -That being said, I still have a month's time, so would definitely try to include one or two slides on the comparison.",0 -Is it related to python Twisted framework??,0 -Go gensim :D,0 -Would be a wonderful experience for anyone interested in getting a hands-on experience in machine learning and natural language processing!,0 -"Hello Vijay, - I request you to add the instructions for setting up the project. Thanks!",0 -"Hello Mayank, - Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 -"Hello Vivek and Farhaan, - Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 -"Hello Saptak, Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 -"Hello Sharad, Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 -"Hello Karan, Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 -"Hello Lev, Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 -"The link is already there but in case you missed it , here you go, - -[How to set up Pagure for development ?][1] - -Happy Hacking! - - - [1]: https://docs.pagure.org/pagure/development.html# - ",0 -@ultimatecoder I will add the steps for creating the developer environment on Github for your kind reference.,0 -"@UltiateCoder. Thanks for the tip. Added env setup to the pre-reqs section. -",0 -"Hi Jaysinh, - - Setup instructions can be found in repo's Readme page. (https://github.com/pythonindia/wye/blob/development/README.md)",0 -"Hi @ultimatecoder, I've made the changes. ",0 -Hello UltimateCoder. I have already mentioned the link which has all the setup information for the project. The link is https://github.com/fossasia/open-event-orga-server/blob/development/README.md. ,0 -"Hi Arif, Please add instructions for creating developer environment and setting up the project.",0 -"Hello Brijraj, Please add information for setting up developer environment. Thanks!",0 -"Shyam is a student of mine. I am very proud for all his capabilities, skills and accomplishments. Good luck to you Shyam. God bless ! - -Kiran Kankipati",0 -looks interesting :),0 -Before you come to workshop please do as mentioned in https://github.com/container-workbook/docker-workshop#9-prerequisite-for-the-workshop,0 -"Is there a Docker container with everything at the exact versions you recommend, for easier installation? -",0 -"Hi Jeff, - -Installing from github develop into a virtualenv on a machine with BLAS is best. - -Regards -Lev",0 -"@rootmonk -Canbyou please share your email id, so that we can send you details. ",0 -"@Rishab - -Can you share your email id, so that we can send you further details. ",0 -"Hi Saurabh, - -My email id is rgoel0112@gmail.com - -Regards, -Rishab",0 -"Will you just dwell on the procedures and implementations of Apache Spark during the talk or the installation too? -",0 -Great session. ,0 -"I'm not able to attend PyCon this year. -I'm gone through your proposal i feel its quite interesting to me. I study and execute the example you gave in the proposal. I have a few questions: - -1) I need few real time examples and real time scenarios. -2) Where can i implement this ast module ? - - ",0 -This looks interesting!,0 -"The slides are distributed under CC-Attribution-ShareAlike. -",0 -"In view of this, it is more likely than not valuable to learn theano before you begin Keras on the grounds that most illustrations have guide calls to theano which are not covered up in APIs. Furthermore, being an analyst, you would love to be able to make new layers to try out new speculations. Theano gives you a chance. -Go to : [best essay writing service][1] - - - [1]: http://www.bestessaywritingservice.co/",1 -"You can easily create, develop, edit, improve and integrate mobile applications for ios and android without almost any coding/programming knowledge! Advanced http://appyresto.com app making service will help your ideas come true.",1 -"Regardless of the difficulty exhibited by my understudies' difference of familiarity and welfare, we figured out how to get past the semester with insignificant soul-pulverizing weariness. [Research Paper Help][1] This was expectant altogether by the large quantity of open source instructive equipment and apparatus nearby in the Python outer space - - - [1]: http://www.ordercollegepapers.com/",1 -"Thanks for the useful information. Frankly speaking, I haven’t heard of Python yet and it’s the first time I hear about this tool. I think that it can be very helpful for economic professionals and those working on finance modeling. It’s important to create an effective economic models that can bring an economy on a higher level. I think today American economy is quite stable but still there are people living through [quick loan][1] tools and who aren’t happy with their financial life. - - - [1]: http://quickandeasyloanservice.com/",1 -"Thanks a lot for telling about this helpful tool! To be honest, I don't know much about stock markets and I'm really new to investments. However, I consider investing my money because I want to be able to provide myself my future and I hope that I will not have a need to use [Installment Credits][1] for that. Thus, it's great that there are technology tools that help to understand stock markets much better, I think I definiletely have to try that! Thanks so much for the information provided! I'm sure it will be helpful to everyone making investments. - - - [1]: http://installmentcredits.com/",1 -"Notwithstanding the trouble displayed by my understudies' distinction of commonality and welfare, we made sense of how to move beyond the semester with immaterial soul-pummeling exhaustion. [My paper writer][1] .This was hopeful inside and out by the vast amount of open source informational hardware and mechanical assembly close-by in the Python space. - - - [1]: http://www.mypaperwriter.co.uk",1 -"Where reqs is the reaction and x is your response. Additionally could catch up with various reactions to a similar question utilizing the arbitrary library, or simply emphasizing through a predefined list. [Custom Essay Help][1]. In the event that you need it to gain from others inputs, you can compose that the PC will ask thus learning, and replicating a comparable response to that of the human utilizing above code. - - - [1]: http://www.essaymania.co.uk/",1 -"There's fairly no should be prepared scripting initial, a couple of the models are an indistinguishable. It’s regularly basically the sentence structure that contrasts, and in the meantime Python's linguistic structure maybe to some degree less hard to be prepared, I question it could require significantly greater investment to settle on up C/C++. The biggest change among C and C++ is the use of classifications. [Help with Essay][1]. There are two or three unique varieties; however that is no doubt the fundamental one. - - - [1]: http://www.shineessay.com/",1 -"Where reqs is the response and x is your reaction. Moreover could get up to speed with different responses to a comparative question using the subjective library, or essentially underscoring through a predefined list. If you require it to pick up from others inputs, [Can Someone Do My Assignment - Customassignment.com][1] you can make that the PC will ask in this way learning, and duplicating a tantamount reaction to that of the human using above code. - - - [1]: http://www.customassignment.com/do-my-assignment.html",1 -"The earth is going away server less where another person deals with running your code naturally at whatever point you need. Later on, I sophisticated the discussion to [Write My Assignment | BuyAssignmentService.com][1] adopts a well ordered strategy that gives the obliged foundation to comprehend the formula bringing about the present type of the discussion. - - - [1]: http://www.buyassignmentservice.com/write-my-assignment-for-me",1 -"Music can't be comprehended by a basic arrangement of equation. The largest part intriguing and testing part is delivering extraordinary music devoid of [Gethomeworkonline.com][1] encroaching the patent. This television shows how profound knowledge was utilized to create music. - - - [1]: http://www.gethomeworkonline.com/",1 -"Most machine learning procedures do play out some example acknowledgment work, in spite of the fact that it's important that most such frameworks don't store singular examples to ""match"" against. [website explainer video to explain][1]. All the more frequently, both machine learning and example acknowledgment frameworks endeavor to lessen the accumulation of preparing cases to a more straightforward shape, for example, if..Then rules or numerical equations. - - - [1]: http://www.demoduck.co.uk/explainer-videos-online/",1 -"The language provides a portion of the implicit answers for break down issues into. Purchase Essay Online ,The style of the dialect impacts how you'll presumably separate an issue. Terms like 'protest arranged' are methods for handling issues, you can do it in any programming language, - -",1 -"Network packet crafting tool how can i use it? Well You can use this Do My Assignment to having a wonderful assistant in writing and even you can get the guidelines too.",1 -"I have been working so long on Java And C++ both languages are similar but now I want to try python to make some New and interesting Software. I have such a New Ideas in the [assignment writing services][1] a Software that helps the student to make assignment but where can I find best resources to learn phyton. - - - [1]: https://www.assignmenttutor.co.uk/",1 -"Developers enjoy the variety plus quality of Python features though, it is not the best programming [buy custom essay][1] language,there are best features like, - Data structures - Classes - Flexible function calling syntax - Iterators - Nested functions - Kitchen-sink-included standard library - Great scientific libraries - Cool open source libraries Numpy, Cython, IPython, MatPlotLib - - - [1]: http://www.urgentessayhelp.co.uk/buy-essay/",1 -"I am expert in Programming and I Worked on my programming languages but and also I work as In [seo company Pakistan][1] now I want to learn phyton I have little bit knowledge of phyton programming but I want to be Expert in this suggest me best-Paid resources for Phyton programming. - - - [1]: http://www.found.com.pk/",1 -"Algorithms (or, at any rate, formal arrangements of standards) have been used to [Write My Custom Essay For Me Cheap][1] create music for quite a long time; the procedures used to plot voice-driving in Western counterpoint, for example, can regularly be reduced to algorithmic determinacy. - - - [1]: http://www.wewriteessay.co.uk/",1 -"The first generally used drone was a full-estimate retooling of the de Havilland DH82B ""Ruler Bee"" biplane, which was fitted out with [Buy coursework writing service][1] a radio and servo-worked controls in the secondary lounge. - - - [1]: http://www.premiumwritersclub.com/Coursework.php",1 -"I have dependably rather delighted in Eric Lippert's blog ""Breathtaking Adventures In Coding"". It's not awesome for remaining fully informed regarding the most recent advances however deals with a considerable measure of the complexities of C#/.NET. [Marketing Essay Writing Services Uk][1] An extraordinary site to sharpen your C# abilities. - - - [1]: https://www.customessayswriter.co.uk/marketing-essay-writing-service.php",1 -"It's intended to be an advantageous editorial manager and debugger. For altering python it's superior to WordPad yet easily proven wrong versus gvim. You can run a script as observe the outcomes in a shell rather than the cmd line or whatever that thing is in windows. [seo.services.land][1]. You can see the stack; set interferes with, check punctuation, and so forth to debug. You can open a module by name (utilizing the python seek way). - - - [1]: http://www.seoservicesland.com/",1 -"Furthermore could make up for lost time with different responses to a comparable question using the discretionary library, or just underscoring through a predefined list if you require it to pick up from others inputs, you can create that the PC will ask along these lines learning, [Can Someone Help For Me in Essay][1] duplicating a tantamount reaction to that of the human using above computer languages - - - [1]: http://www.mbaessayhelp.co.uk",1 -"I have to make a talk bot for an autonomous [Assignment doer uk][1] class . I don't know excessively about Python. I know the nuts and bolts. What I was considering accomplishing for the program is it to have a couple of characteristics: 1. A group of per-modified reactions to specific data sources. - - - [1]: http://www.assignmentdoer.co.uk/",1 -"Scapy is a authoritative interactive packet management tool, packet creator, network scanner, network detection tool, and packet sniffer. Note that Scapy is a very low-level tool [Write my essay uk][1] you cooperate with it using the Python programming language. - - - [1]: https://www.ukwritingexperts.co.uk/essay-writing.php",1 -"The discussion is expected to be a stroll through to empower gathering of people to outline profound learning calculations utilizing Theano and grow profound learning applications utilizing Keras, which is based on top of Theano. [Cipher Fast 8 Jacket Instylejackets][1] - - - [1]: http://www.instylejackets.com/product/fast-furious-8-villain-charlize-theron-jacket",1 -"Furthermore might conjure for lost time with completely different responses to a comparable question mistreatment the discretionary library, or simply underscoring through a predefined list if you need it to select up from others inputs, you'll produce that the laptop can raise on these lines learning, Essays Writing Service UK duplicating an equal reaction thereto of the human mistreatment higher than laptop languages.",1 -"Transfer is a more in attendance day system we're working here, and power parts of our portable site. It's be a truly clever examining process and the transmit [Pay for Essay Writing][1] group is doing marvelous work to complete some last details for a fundamental discharge. - - - [1]: http://www.bestassignmentservice.com/help-me-write-my-essay",1 -"no i don't think because those [essayleaks][1] which i use is good.python is also a good language. - - [1]: http://www.essayleaks.com/",1 -"The style of the idiom impacts however you may presumptively separate a difficulty. [Assignment Help UK][1] Terms like 'protest arranged' square measure ways for handling problems, you'll be able to the couple in any artificial language. - - - [1]: https://www.essayswritingservice.co.uk/assignment-writing.php",1 -"I have tried many CMS for creating website. Python is better web language than PHP. [buy essay UK][1] it is much more suitable for development of website. you can also use Django which can do most of your tasks. - - - [1]: http://www.urgentessayhelp.co.uk/buy-essay/",1 -"This is a great opportunity for everyone who wants to get experience in this direction. Thanks! -Also I looking for person who can help me [write my essay][1] about C++. Can someone help me? - - - [1]: http://www.essaytoday.net/",1 -"I want a 110 lb Latina with pure black hair and absolutely at all no morality. Lacking the ability to speak, and make sandwiches for me and bring me beer on command. She has 36DD breasts and a * a quarter from the bounce [Cick essay][1] could you. She has many fetishes and the need, they all have recorded on video. The only thing that you have is a smile and slutty purple eyeshadow. She has also no gag reflex - - - [1]: http://www.clickessay.com/",1 -"Is it possible to apply it to python? Thanks in advance! -Inquiry for technical [essays][1]. - - - [1]: http://pimion.com",1 -Yes. :),0 -"Python highlights a dynamic type system and programmed memory management and backings different programming ideal models, including [buy an assignment online][1] object-situated, basic, useful programming, and procedural styles. It has a huge and far reaching standard library. - - - [1]: http://www.assignmentninja.co.uk/buy-an-assignment-online",1 -"OpenStack started in 2010 as a joint project of Rackspace Hosting and NASA. Starting at 2016, it is overseen by the [Buy an Essay Online][1] OpenStack Foundation, a non-benefit corporate element built up in September 2012 to advance OpenStack software and its group. - - - [1]: http://www.wewriteessay.co.uk/buy-essay",1 -"Really a good job here done by the team of Pycon.org. I will recommend you to the [dissertation writing service][1]. - - - [1]: http://dissertationwritingservices.org/",1 -"This introduction depends on our participation in creation and conveying a vast level predict, [Master Paper Writers][1] framework which is being utilize live over all staff. - - - [1]: http://www.masterpaperwriters.com/",1 -"A venture is an examination task given to an substitute which for the most fraction require a bigger gauge of effort and more independent work. Read more at [Help with Myassignmentservice.com][1] - - - [1]: http://www.myassignmentservice.com/",1 -"They frame the cause for some astoundingly strong machine knowledge calculations like random timberlands and angle boost machines. Read more at [Assignment Service by Buyassignment.com][1] - - - [1]: http://www.buyassignment.com/",1 -"Ultimately this relies upon for your bot’s requirements and what makes maximum experience given the the time and effort you want to spend developing. Personally, [UK essays][1] I discover AIML to bulky to to construct out a totally useful bot and like RiveScript for simple bots - - - [1]: https://www.ukessaysexperts.co.uk/",1 -"In software engineering, you frequently hear the expression ""toning it down would be ideal"". As a rule, on the off chance that you can take care of an issue in less lines of code, the better. It will likely require you less investment to [marketing essay][1] comprehend a 200-line class than a 500-line class. - - - [1]: https://www.customessayswriter.co.uk/marketing-essay-writing-service.php",1 -"Scapy is a new manipulation tool for computer networks in python. It is one of the best network tool with extend features. Customer feedback and reviews about this tool are positive. Go through the reviews from [essay writing service reviews][1] to get more idea about it. - - - [1]: http://essaywriting-servicereviews.com/",1 -"Your provided resource is very helpful i recently switch for C language to python for [assignment writing service][1] - - - [1]: https://www.britishassignmentwriters.co.uk/",1 -"Commonly, a prescribed framework looks at a client profile to some reference qualities, and tries to foresee the ""rating"" that a client would provide for a thing they had not yet considered. [college assignment help][1]. These attributes might be from the data thing (the substance based approach) or the client's social condition (the community oriented separating approach). - - - [1]: http://www.australianessay.com/assignment-services-with-quality-writing",1 -"Generally speaking, the speed of your site greaterly affects client fulfillment than additional ""extravagant accessories"". It doesn't make a difference how extraordinary a site looks: [Essay writing service uk | Ukwritingexperts.co.uk][1] on the off chance that it stacks too gradually, clients will click away. - - - [1]: https://www.ukwritingexperts.co.uk",1 -"game programming is really getting fame among the developers and this will be the next level technology. IT students should concentrate on their studies as this might help them in learning more about game development and programming. Also they can look for [assignment writing online][1] in order to get their IT assignments done with unique contents. - - - [1]: https://www.britishassignmentshelp.co.uk",1 -"Bidirectional recurring neural nets explain promising outcome, as they aim to [write me an essay][1] imprison both contextual dependence between words through repetition and position-invariant semantics through complication. - - - [1]: http://www.needpaperhelp.com/write-my-college-essay",1 -"This place just gives instance of some areas that can source problems, and may rouse some thought when deceitful your app. [Essay service from theessayhelp.co.uk][1] - - - [1]: http://www.theessayhelp.co.uk",1 -"In deep knowledge systems, this is not the case as an alternative algorithm can [pay someone to write my essay][1] mechanically teach feature hierarchies, which symbolize objects in growing levels of concept. - - - [1]: http://www.midnightessays.com/help-me-write-essay",1 -"It has an extensive convention in neural networks explore, as the dataset is relatively small but still very difficult to [explainer videos][1] organize suitably. - - - [1]: http://www.seekclip.com/explainer-animated-videos/",1 -"There is always a way-out to incur less costs for something really valuable. Even [finding a qualified essay writer][1] might be much cheaper if you follow the instructions on this article. - - - [1]: http://%20http://www.cedargroveschool.com/finding-a-qualified-essay-writer-tips-for-beginners/",1 -"There is always a way-out to incur less costs for something really valuable. Even [finding a qualified essay writer][1] might be much cheaper if you follow the instructions on this article. - - - [1]: http://%20http://www.cedargroveschool.com/finding-a-qualified-essay-writer-tips-for-beginners/",1 -"Usually when developers are working on the Python so they must be enjoyed it during the projects and also learn the many skills because development is the very interesting field. Well, this post is very informative thanks, author you share a very nice post and I am a professional expert from best [assignment writing service][1]. We provide the high-quality writing services and also work on the development, softwares, marketing, and designing. If someone needs any types of assistance so they can take help with us. - - - [1]: http://www.assignmentace.co.uk/",1 -"I'm guessing you have not programmed much before. You might want to get someone to help you download and install Python and show you how to use the interpretor and how to save and run a simple program. If you can get someone to help you with [Ez Assignment Writing Help][1] that, you'll be up and running in an hour. Then it might take you a month before you can write programs that really do something interesting. Python is not a *fast* language so it is not good for things like graphics intensive games. But it is easy and fast to write most programs. - - - [1]: http://www.ezassignmenthelp.co.uk",1 -"On the off chance that you have a modest bunch of models and few points, then you could run the manual assessments in a sensible measure of time. Shading swing words in your particular area is a critical one to get right. [Dissertation editing online][1] In different circumstances manual reviews are not achievable. - - - [1]: http://www.dissertationtime.co.uk/editing-service",1 -"Machine learning via get better Gensim lesson is good but not for everyone as a writer of [Dissertation Service UK][1] I realize we need universities which have all kind of classes. - - - [1]: http://www.DissertationHouse.co.uk/",1 -"I need more description on workshop collaboration software I belongs to [Custom Essay Writing Company][1] and it is my first time that I am writing on programming language that’s why I am asking. - - - [1]: http://www.AOneEssays.net/",1 -"One surely understood issue with Dicker based forms is the compute of dialect particular circumstances requisite by your method on top of the official dialect picture. [Write My Essay][1] We've developed this by making a strong-minded information quantity for those conditions, and share that volume from work to fabricate. - - - [1]: http://www.helpinessays.com/someone-write-my-essay.html",1 -Please drop email to contact [at] pythonexpress [dot] [in] we can answer all queries.,0 -"Organize information bundles contain different data incorporate information, source address, goal address, variant, length, convention, and [custom assignment help][1] couple of different things relying upon the convention. - - - [1]: http://www.assignmentbay.co.uk/assignment-writing-service",1 -"Actually the Chatter bot the machine learning based dialogue engine which is build in platform Python is usually interesting and makes possible to generate responses based on some known conversations. So I hope developers enjoy this kind of work since I used to enjoy each bit of my development work in [buy essays online][1] and here it is well expressed too - - - [1]: http://www.buy-custom-essays-online.com/",1 -"I am a professional writer i need to study the python and the other computer language for the academic research paper work for my new client. Currently i am working with the [best essay writing service][1] . This is one among the top most online writing firm with well qualified writers. - - - [1]: http://essaywritersworld.com/",1 -"You should be comfortable with java before learning Hadoop technology. Hadoop having two parts- development plus admin. hadoop development is based on java. admin require good knowledge od database. map/reduce, HDFS, Hive, Pig, Mahout, Sqoop are main components of Hadoop. [Do Write My Essay][1] Data analyst require good to have in Pl/Sql, database, application domain specific knowledge, dataanalysis framework like hadoop etc. - - - [1]: http://www.writecheapessay.com",1 -"I am working with [dissertation writing services][1], I know the importance of python and other languages. I am interested in computer languages but I need to study more about python because it has good chance on this developing world. - - - [1]: http://best-uk-dissertation.com/",1 -"Catalysts communicated by exceptionally salt-tolerant living beings demonstrate numerous changes contrasted and salt-influenced partners including one-sided amino corrosive and lower α-helix content, bring down dissolvable openness and negative surface charge. Here, we demonstrate that halotolerance can be produced in a chemical exclusively by altering surface deposits. Normal plan of carbonic anhydrase II is attempted in three phases supplanting 18 buildups altogether, gem structures affirm changes are kept to surface deposits. -Ref: [cheap essay writing service][1] - - - [1]: https://essayservices.org",1 -"The article describe about the python applications.python applications can be written to be managed by Helix.this application used to convert the high volume of program to user understand format.this application is very much useful for all.thanks a lot for sharing such an important informations. i really like to read this article. [hearing aid service center Pathanamthitta][1] - - - [1]: http://shabdhaclinic.com/hearing-aid-&-speech-therapy",1 -"Thanks for sharing this informations.this is the new informations for me.the word2vect used to calculate the document similarity.the commonly used words are chosen by using the word2vect. this method used to identify easily to the documents.thanks a lot for sharing such an important article.its very very useful for me. [aluminium foil containers][1] - - - [1]: http://supremepackaginguae.com/aluminium-Container-suppliers.html",1 -"Thanku so much for sharing this article.here describe about the projects useful for me.as a college professor.this include the software and hardware based projects are doing to my students.this article is helpful for knowing more informations.i like to share this informations to my students.thanks a lot for sharing this post. [job oriented diploma courses][1] - - - [1]: http://collegesniper.com/course/diploma",1 -"NSE's website used to download the data and document directly.this is the new informations for me.i like to share this information to others.i am very happy to read this article.i hope you more useful articles.thanks a lot for sharing this article. [Plumbing Services Dubai][1] - - - [1]: https://daddyservices.com/Dubai/Plumbing-Services",1 -"This is the new informations for me. the python hacks related informations included here.as a software developer.this include informations are very much useful for me.this article help me to understand some new informations.i am erp developer, for more informations about include the website [ERP Development Company Dubai][1] - - - [1]: http://adeptsol.com/",1 -"Web development structure is better for improvement. Rails 4 presents various client confronting changes, and the digital book has been refreshed to match all the most recent changes and new accepted procedures in Rails as elaborated at an [Essay Writing Service][1] . While Django as an open source extend with a name (On account of a specific late motion picture that sounds cool) appears to be intriguing and is intended for information driven activities. - - - [1]: http://www.writingbunch.co.uk/",1 -"The heart of the expectation frameworks are the machine learning calculations. Python has solid support for machine learning calculations. The [www.researchpaperlabs.com][1] key bundle we will utilize is the scikit-learn bundle. This bundle is intense and empowers designers with insignificant machine learning knowledge to grow effective characterization frameworks. - - - [1]: http://www.researchpaperlabs.com/",0 -"I want to be able to open a website from python, I've tried every tutorial online and all the python sites with their ""urlib"" thing, but I can't seem to get any of the codes to work. -all I want to do is have a function where I type a ur like [Essay Writing Service][1] -l as an argument into the function and the program will open up IE, firefox chrome or w/e and display that website. - - - [1]: http://www.essaygala.com/",1 -"This introduction is about how to construct an adaptable expectation framework for close ongoing use utilizing Python. A client will enter his/her necessities utilizing Natural dialect. The framework will do a characteristic dialect preparing of the information content. Machine learning models will be utilized to foresee the required fields. This arrangement can be utilized for various utilize cases including specialist portions for Incident work seat , Recommendation administrations , and so forth. [Help with Research Paper][1] - - - [1]: http://www.researchpapergurus.com/",1 -"The expected takeaway from this discussion would be a greatly improved comprehension of what occurs in the background when a record is asked for from the plate and how one can think past customary methods for putting away information. [Do My Dissertation for Me][1] - - - [1]: http://www.donedissertations.co.uk/do-my-dissertation",1 -"debugger utilizes this way to deal with render traceback. Engineer can backpedal to any point and examine the variable. Great point. [Admission Essay Writing][1] - - - [1]: http://www.essaytiger.co.uk/admission-essay-writing",1 -"Framework is constructed utilizing mix of Natural Language Processing systems and machine learning methods with Python as the overwhelming dialect. [Professional Essay Writing Service][1] Takeaways from the discussion will incorporate what to search for in content grouping and how to assemble a real content classifier in Python. - - - [1]: http://www.groovyessays.com/",1 -"One thing we’ve struggled about while setting up a home office is space insufficiency. This becomes extreme if you want to bring in a computer desk to the same. L Shaped Computer desk",1 -"Well, there should be some entertainment in the school which catch the attention of students to school. If your class is so boring then a student will get fed up and will not concentrate in the class. The entertainment can only catch the attention of students to the school and one more thing is, [UK essay help][1] interest can only be developed in students by the teacher. If the teacher is frank with the students and share lots of different ideas and give funny interesting examples then the student start taking the interest. Discipline is also very necessary. - - - [1]: http://www.essaybliss.co.uk/",1 -"The dialect is Python. Pycharm is an IDE used to create Python code. There are others. - -More often than not ""word"" in an issue implies anything non-clear, [online assignment help uk][1] isolated by spaces from whatever else in the string. In Python, you can change over a string to a rundown of words basically: - - - [1]: http://www.assignmentmoz.co.uk/",1 -"The dialect is Python. Pycharm is an IDE used to create Python code. There are others. - -More often than not ""word"" in an issue implies anything non-clear, [online assignment help uk][1] isolated by spaces from whatever else in the string. In Python, you can change over a string to a rundown of words basically: - - - [1]: http://www.assignmentmoz.co.uk/",1 -"Actually, Python is the coding language and it is difficult to understand rather than to HTME, but we can learn this language with the help of a different kind of programming languages. And this kind of languages is taught in bachelor program so that learners can easily understand this language easily. Now this time have the opportunity to learn on the web where also to continue academic education just [enroll for non fake degrees - gain non fake college degrees][1] in any faculty easily. - - - [1]: http://www.degreeforlifeexperience.com/non-fake/",1 -"Eventually, this depends upon your bot’s necessities and what creates supreme practice given the time and exertion you want to devote developing. For myself, dissertation help services determine AIML to bulky to concept out the completely valuable bot.",1 -"Gensim is a machine learning bundle for normal dialect understanding. For instance, it can reveal to you the primary points of a site page. It has word2vec and doc2vec machine learning calculations. - -He is a specialist in common dialect preparing, is a Python and Java engineer. Animated Videos For Business Lev has broad experience working with money related foundations and is RaRe Technologies' chief of open source groups including gensim, an open source machine learning toolbox for understanding human dialect.",1 -"which seems to be more easy when it comes to operating python or C language? [Essay writing help][1] - - - [1]: https://www.papermatic.co.uk",1 -"Subsequent to acquainting Python with my classes in 2011, a non-registering partner requesting that I keep in touch with a few arranges that would empower her to acquaint Python with her classes. [Ghost Rider Costume Jacket][1] - - - [1]: http://www.celebsfit.com/ghost-rider-agents-of-shield-jacket",1 -"What you are asking approximately is public lending rights. Plr is a government funded scheme that can pay Assignment help UK authors around five½ pence on every occasion their books are loaned out. They do not depend each single loan from every library in the usa, of direction; the scheme is based totally on samples from selected public libraries. A distinct set of libraries is chosen every yr, and authors aren't advised in advance which libraries they're, to prevent manipulation of the service! Fee is made each february.",1 -"There is dependably an exit plan to bring about less expenses for something truly profitable. Notwithstanding finding a prestige chauffeurs may be significantly less expensive on the off chance that you take after the directions on this article.",1 -"There is always a way-out to incur less costs for something really valuable. Even finding a Download Youtube Videos online might be much cheaper if you follow the instructions on this article.",1 -"Great Information,it has lot for stuff Do MY Programming Assignment For Me which is informative.I will share the post with my friends.",1 -"This is really great work. Thank you for R Assignment Help sharing such a useful information here in the blog.",1 -"I loved the way you discuss the topic Solidworks Assignment Help great work thanks for the share Your informative post.",1 -"Science Channel’s are giving a complete knowledge to its viewers Make My SPSS Homework about every thing students write done dissertation on this subjects and show its importance.",1 -"Those who come to read your article Digital Marketing Course In Pakistan will find lots of helpful and informative tips",1 -"如果你想要像我这样的最好的内容,导师写作 只需要快速访问这个网站,因为它提供功能内容,谢谢",1 -"This is a very interesting post thanks for sharing the post and I hope every people learn many skills in this post. Well, I am a professional expert and I provide the [research paper writing services][1] for the students because it is the very complicated task for the students and their have no writing about the research paper. - - - [1]: http://essaywriting.com.pk/research-paper-writing/",1 -"John arnold is an academic writer of the Dissertation-Guidance.Can Someone Do My Exam Who writes quality academic papers for students to help them in accomplishing their goals.",1 -"The leading assignment help UK firm offers state Write My Medical Thesis of the art services to its clients with a promise of delivering all the required work well within the deadline.",1 -"Great Information, Help With Audit Assignment it has lot for stuff which is informative.I will share the post with my friends.",1 -"John arnold is an academic writer of the Statistics Assignment Help Dissertation-Guidance. Who writes quality academic papers for students to help them in accomplishing their goals.",1 -"Yes, learning English is a really important thing for everyone who wants to keep up with the times. That is why writing skills are so important too. Click the link [https://thrivingwriter.com/proofreading-service/][1] to know more about the modern specification of the text and learn how to keep them. Professional writers here will help you to update your text to the perfect level. Proofreading in the shortest time and editing is their hobby which they know better than anything. - - - [1]: https://thrivingwriter.com/proofreading-service/",1 -"Big data analytics inspect large quantity of data to expose hidden pattern, association and other imminent. [Buy Assignment][1] for college and university students, With today’s knowledge, it’s possible to investigate your data and get answer from it almost straight away – an effort that’s slower and less well-organized with more customary business intelligence solution. - - - [1]: http://www.readyassignment.co.uk/buy-assignment/",1 -"It's September as of now! PyCon India is not over 15 days away...24-25 September 2016. Not to overlook the workshop on 23 September 2016. [url=""http://www.idealjackets.com/product-category/dark-matter-series-leather-jacket-and-vest""]Roger Cross Coat[/url]",1 -"It's September as of now! PyCon India is not over 15 days away...24-25 September 2016. Not to overlook the workshop on 23 September 2016. [Roger Cross Coat][1] - - - [1]: http://www.idealjackets.com/product-category/dark-matter-series-leather-jacket-and-vest",1 -"Viruses had been the first laptop insects, initially designed with the [Essay Writers UK][1] aid of programmers to test the integrity of the software program code for sturdiness and compatibility. The internet modified matters a piece, the malicious hackers used this new medium inject their codes into regarded software flaws to contaminate heaps. Why? Due to the fact they might. Anti virus software program became created to delete these malicious virus codes . Subsequent got here the worm, a exclusive form of code to the virus, the av software program has a more difficult time choosing these out. Subsequent came the malicious program, unique once more from both the virus and bug as it assaults the av software in addition to the operating device, exploiting weaknesses inside. Trojans regularly create copies of themselves in other places and re-infect a just wiped clean computer on restarting. Av turned into no longer designed to cope with this sort of threat and the arrival of anti spyware to deal specifically with it became a should. - - - [1]: http://www.essayace.co.uk/",1 -"If you have interest towards machine language it will be very easy to study it. Hope this Gensim package will be a best tutorial guide for the begineers. There are so many other packages, get more about it from [Admission essay writing services][1] - - - [1]: http://essaysmaster.com/admission-essay-writing",1 -"Can I have a separate link to the Introduction to OpenCV? I'm a beginner in Sentiment Analysis and my assignment deadline is coming soon. I chose a distance learning course at Arizona State University from this list of top unis for distance learning https://essaydune.com/top-10-us-universities-for-getting-distance-education/ and can't pass the exams and all tasks. Please, help.",1 -"Can I have a separate link to the Introduction to OpenCV? I'm a beginner in Sentiment Analysis and my assignment deadline is coming soon. I chose a distance learning course at Arizona State University from this list of top unis for distance learning [https://essaydune.com/top-10-us-universities-for-getting-distance-education/][1] and can't pass the exams and all tasks. Please, help. - - - [1]: https://essaydune.com/top-10-us-universities-for-getting-distance-education/",1 -"Scapy is an effective intelligent parcel control program. It can produce or unravel bundles of a wide number of conventions, [British Essay Writing][1] send them on the wire, catch them, coordinate demands and answers, and a great deal more. - - - [1]: http://www.britishessaywriting.co.uk",1 -"I want to work with advancements that make designers lives simple, once in a while another item turns out that makes the procedures more less demanding, my employment is to convey that learning to devs and make our lives less difficult. Ashton from [http://payforessays.org][1] . - - - [1]: http://payforessays.org",1 -"As per my observation, the event has been ended. I am also an [android app developer at Branex][1]. could you please share the presentation of this event publicly? This will definably provide me a new professional experience for developing the Android mobile apps via the Kivy, a Cross-platform Python Framework for rapid app development instead of Java. - -Cheer, - -Robert Downey - - - [1]: https://branex.com/app-solutions/",1 -"In comparison to Java, Python projects Python projects are commonly 3-5 times shorter than proportionate Java programs. This distinction can be ascribed to Python's inherent abnormal state information sorts and its dynamic writing. For instance, a Python software engineer squanders no time pronouncing the sorts of contentions or factors, and Python's capable polymorphic rundown and word reference sorts, for which rich syntactic support is incorporated straight with the dialect, discover an utilization in practically every Python program. In view of the run-time writing, Python's run time must work harder than Java's. For instance, while assessing the expression a+b, it should first investigate the articles an and b to discover their sort, which is not known at arrange time. It then conjures the proper expansion operation, which might be an over-burden client characterized strategy. Java, then again, can play out a proficient number or skimming point expansion, however requires variable presentations for an and b, and does not permit over-burdening of the + administrator for examples of client characterized classes. I like Python language and completed so many [term papers][1] on it at university. - - - [1]: http://thetermpapers.net/",1 -"What are the requirements for Basic Python Programming Skills? I mean are these soft skills too? I need to investigate the topic and [write my college essay][1] on Natural Language Processing for Programming class at Ulster University. - - - [1]: http://essayforcollege.org/write-my-college-essay.html",1 -"Being a developer you need to always be upgraded about things python generator is one of the new addition for software engineers. With support and [Essay Help UK][1] by expert’s software engineer like Anand you can grasp thing easily and start working on the projects. - - - [1]: http://www.writing-victors.co.uk/essay-services/",1 -"Learning is a basic need of everyone, because without an education or lack of education, we cannot get a successful career, so that every individual is looking for getting an education for making their career successful and in these there are such a great options for getting an education, and even high school drop outs can also get their education done. As internet has made it quite easier for getting an assistance regarding any requirement, so that many students are getting their [dissertation help][1] through online resources for their academic writing programs and it is such a great way to get an assistance through using online technologies and it is the best way and it saves time and effort and many individuals are making the most of this online technology. Thanks for sharing such a useful information. I am looking forward to get more useful ways to get an assistance. - - - [1]: http://www.realdissertationhelp.co.uk/",1 -"this technology is great and It Will be very helpful for [cheap seo service][1] and It makes our work easier I was searching for the Best article about this technology and finally I found this article. - - - [1]: http://www.found.com.pk/",1 -"As with the practice of Reasoning Abstractly and Quantitatively, which was the focus of Part 1 of this series, the practice we will focus on in Part 2 also asks students to reason with mathematics. As I am teaching a class and working to integrate the mathematical practices, I think of these two practices together, [instant Essay writing service][1]. even though there are distinct differences. In this blog, we will look specifically at how to get students to Construct Viable Arguments and Critique the Reasoning of Others. I am sure that after you look at these examples, you will see how reasoning is used in two well-defined ways. - - - [1]: http://www.proessay.co.uk/",1 -"The functions and classes in the humanfriendly package can be used to make text interfaces more user friendly. Some example features: - -Parsing and formatting numbers, file sizes, pathnames and timespans in simple, human friendly formats. -Easy to use timers for long running operations, with human friendly formatting of the resulting timespans. -Prompting the user to select a choice from a list of options by typing the option’s number or a unique substring of the option. -Terminal interaction including text styling (ANSI escape sequences), user friendly rendering of usage messages and querying the terminal for its size. [Dissertation Services UK][1] - - - [1]: http://www.dissertationmill.co.uk",1 -"Well, if to speak of designing big programs, then here is my good advice for you. -Try not to outline a framework to be object oriented. Simply plan it consistently that is as decoupled as could be allowed. Will need to test your code and the more coupled it is, the harder that will be to do. -You simply begin composing it and you refactor a great deal. You begin perplexed of things like rundown perception and before long need to learn guide, channel, and lessen. On my open source venture which is an IO to a beast of a building program, I've completely rejected the input reader 4 times while leaving the information essentially the same. I've revised the yield the output one two times (taking a shot at a third). You do this since some new component is difficult to get working steadily due to all your code hacks, so you will re-write it with ideally a couple of lessons taught. Python is a real great [essay writer][1] programming language. - - - [1]: http://www.writemyessay24h.net/",1 -"Great reading so far! I didn't know much better about Workshop collaboration software before today. By the way, if you need writing on the same topic you can visit https://hitthegrade.com/ this anytime and order. Thank you so much and keep posting things like this.",1 -"Great reading so far! I didn't know much better about Workshop collaboration software before today. By the way, if you need writing on the same topic you can visit https://hitthegrade.com/ this anytime and order. Thank you so much and keep posting things like this.",1 -"Sorry to learn about your missing snake, this is dependably a troublesome pill to swallow! I would exhort hunting down your snake by tidying up your room. It is more probable that your snake is still in your room. Yes, it can for beyond any doubt fit under the entryway in the event that it is a child, yet its not likely that it would travel that far if there are sufficient [Online Dissertation Help UK][1] different spots for it to cover up. Your snake will be more dynamic around evening time, and may move so that is the point at which I'd do the greater part of the seeking. - - - [1]: http://www.dissertationhub.co.uk",1 -"Thank you for this , I'm glad I found this website on google. -[assignment writing service][1]  - - - [1]: http://myassignmenthelp.co.uk/assignment-writing-service.html",1 -"In the event that you've perused first experience with Python, you definitely realize that it's a standout amongst the most generally utilized programming dialects today, celebrated for its productivity and code meaningfulness [Do my assignment][1] As a programming dialect for information science, Python speaks to a trade off between R, which is intensely centered around information investigation and perception, and Java, which shapes the foundation of some huge scale applications. - - - [1]: http://www.assignmentcamp.co.uk/someone-write-my-assignment",1 -"This discussion will present us with various proposition of [assignment writer uk][1]. It's be a really sharp looking at process and the transmit gathering is doing wonderful work. - - - [1]: https://www.ukassignmentshelp.co.uk/",1 -"We always should be supportive and look to become a various think we need to become a supportive one in good deeds of life Learn Machine [Dissertation Writing Service UK][1] - - - [1]: http://www.dissertationcorp.co.uk/",1 -"This is really unique but we always should become a various think to do in a perfect way of life in order to maintain a useful think we need [Write My Dissertation][1] - - - [1]: http://www.thedissertationhouse.co.uk/",1 -"Sometime we always need to become a various think to do something better in our life but we should keep the good changes in our common life to become [Professional research paper][1] - - - [1]: http://www.proresearchpapers.com/",1 -"Designers appreciate the assortment in addition to nature of Python elements however, it is not the best programming purchase [essays tigers][1] language,there are best components like, Data structures Classes Flexible capacity calling grammar Iterators Nested capacities Kitchen-sink-included standard library Great logical libraries Cool open source libraries Numpy, Cython, IPython, MatPlotLib - - - [1]: http://www.essaystigers.co.uk",1 -"Composing a little C/C++ wrapper around Python, concealing the way that the application is really composed in Python (to make a custom order line interface; for dispersion purposes; or just to make it somewhat harder to figure out the application). - -[click here][1] - - - [1]: http://laustan.com/",1 -"I myself am new to web dev. I also just started using git, although it's fun, the learning curve is quite steep for me. -But I would gladly want to contribute in an open-source project :) and for your essay needs, be sure to visit bestwritingadvisor !",1 -"Hey! Deep learning is a cool thing when it comes to effective learning. But when speaking of the deep learning, it must include more problems and difficulties. Simple students face packs of college papers, tests, and other assignments... Fortunately, there are lots of resources that facilitate academic process. I have already found out about websites for students as I can't cope with all essays and other college papers independently and British Essay Writer can help me with it. I know that some students are cautious about essay writers online but believe me - it's a cool opportunity to receive professional essay, get high grades and avoid stresses!",1 -"The term static analysis is conflated, yet here we utilize it to mean an accumulation of calculations and strategies used to break down source code with a specific end goal to consequently discover bugs. The thought is comparable in soul to compiler notices, Writing Help By Assignment Empire yet to make that thought a stride further and discover bugs that are customarily discovered utilizing run-time debugging techniques such as testing.",1 -"You can compose a Telegram visit bot in any dialect you need. A portion of the fundamental alternatives separated from Python would be Java, PHP, or Ruby [write my research paper for me][1] On the off chance that you are more comfortable with an alternate abnormal state programming dialect, then you may want to utilize that rather, yet Python is a decent decision for a few reasons. - - - [1]: http://www.rushpapers.co.uk/",1 -"It isn't a smart thought to no end to come up when the client dispatches stuff.exe. Consider the possibility that it requires a long investment. [promotional video][1]. Perhaps your server is running moderate. Or, then again the client is on dial-up (those clients still exist). For sure if the whole web is down Chances are, your client will think stuff didn't run, so they will attempt to run it once more. What's more, once more. And after that they will get confounded and irritated. - - - [1]: http://www.vidwonders.com/",1 -"We assemble information from various online networking locales and clarify utilizing three annotators. At that point this information is encouraged into the profound learning model which is made by convolutional neural system and takes word2vec word embeddings as information. [Custom Dissertation Writing Service][1]  The model can group the information into two classifications with great measurements. - - - [1]: http://www.dissertationshouse.co.uk/",1 -"i really like this article please keep it up. cccam server",1 -"The discussion gives a fundamental prologue to Bokeh Python. A concise depiction to bokeh is given in the slides. The slides contains prologue to unique elements like Bokeh Server and Bokeh Flask. [Coursework Writing Service][1] This improves the dynamic interactability of Bokeh. Alongwith the slides I have arranged two ipython scratch pad. One has essential plotting in Bokeh , with information extricated from a csv document utilizing Pandas. Another clarifies an extremely helpful element of Bokeh known as Interactors - - - [1]: http://www.essaycorp.co.uk/coursework-writing-service/",1 -"coala gives a typical multiplatform interface to linting and settling all your code, paying little heed to the programming dialect you utilize. Its advantageous UI disposes of a considerable measure of regular undertakings for the designer. [Assignment Writing-Groovyessays][1] coala likewise encourages individuals entering the universe of open source by giving them important input on coding measures and organizing. Along these lines, more or less coala is a valuable reflection for static code examination that is pertinent to any content based dialect. - - - [1]: http://www.groovyessays.co.uk/assignment-writing-service/",1 -"I'm speculating you have not customized much some time recently. You might need to motivate somebody to enable you to download and introduce Python and demonstrate to you industry standards to utilize the translator and how to spare and run a straightforward program. In the event that you can motivate somebody to help you with [EssayChamp][1] that, you'll be up and running in 60 minutes. At that point it may take you a month prior to you can compose programs that truly accomplish something fascinating. Python is not a quick dialect so it is bad for things like illustrations concentrated amusements. Be that as it may, it is simple and quick to compose generally programs. - - - [1]: http://www.essaychamp.co.uk/",1 -"This is an incredibly instructive article of On time paper writing. I in like way concur with your post title and your really well illustrate your perspective. I am to an extraordinary degree cheerful to see this post. A commitment of gratefulness is all together for an offer with us. Keep it up and share the all the more most related post.",1 -"The writer has formed a unimaginable article of Custom Assignment. You made you show up and no exchange about. Without a doubt this undeniable truth that you can not battle with the fact of the matter is not serious, everything has its remarkable case. A devotion of appreciation is all together for this data.",1 -"I basically need to offer critical an obligation of appreciation is all together for this brilliant post of Reliable Essay Writing, quality article and will look a more unmistakable measure of your assorted spellbinding substance. Magnificent sharing!",1 -"there is the thing I think you should have to in Realtime microservices and Make them better are that Will be popular in people When the will this Kind of new technology [PPC service in Pakistan][1] with so many benefits. - - - [1]: http://www.found.com.pk/services/pay-per-click-management/",1 -"Big data or large data is something that cannot be done on small scale. It always was done on large scale.PySpark is an API used for a python-A programming language. To analysis big data we use apache-spark which is an open source and it is mainly used for big data. If you have data of your assignments and wanted to provide [assignment help][1] to students through big data then you can use apache-spark. - - - [1]: https://www.assignmenttutor.co.uk",1 -"All things considered, we as a whole revere the individuals who acknowledges the significance of shielding their oakley sunglasses cheap eyes from UV beams, however for this situation",1 -"Wayfarer ray ban sunglasses was composed by the American optical originator Raymond Stegeman from Ray-Ban and that has now turned out to be one of the style image of the entire world. This style of shades too has experienced an unpleasant time amid cheap ray bans the previous 60 years where a ton of different styles have gone ahead load up.",1 -"Feline eye ray ban sunglasses for Women then again have an upsweep at the external edges of the arms and it joins the casing front. This style of shades was promoted by superstars like Audrey Hepburn, Marilyn Monroe, Elizabeth Taylor and ray ban outlet Madonna since 1950's. It was worn by the most elegant women around the local area and its prominence brought considerably more up in the times of 70's",1 -"On the off Rolex watches chance that you have an adoration for the better things in life, you will love Rolex watches. On the off chance that you cherish the things that are known as materialistic trifles and have essentially the best quality around, you will love this marked timepiece.Is it accurate to say that you are searching for the ideal present for the extraordinary men throughout your life or notwithstanding for yourself? Furthermore, you can even buy knockoff looks for both men and ladies that are being sold for a small amount of the general. Rolex is one of the prestigious Swiss watches. Rolex and different prestigious uk replica watches marked timepieces go as one. watches were made in 1905 and have turns into a portion of the finest watches accessible that one can discover.",1 -"Tissot dependably remains replique montre de luxe consistent with its exemplary engineering. This T035.446.16.051.00 timepiece mirrors the tasteful look of customary workmanship through its lovely plan. The 39mm dark dial takes you back ever. The 28mm silver dial has dew-drops that infuse another and new thought in the wearers. The look of the timepiece is to such an extent that it moves the ladies to accomplish their fantasies. The a la mode and intense look of replique montre omega the watch is without a doubt hard to overlook. Added to this, the dark cowhide strap takes care of the demand of the age. Offering a hoisted style a reprieve, Tissot engineers this look for the individuals who welcome the normal magnificence. The brilliance of watchmaking is unmistakable through its bleeding edge innovation and strong files. The dial is encompassed by a silver montre rolex bezel that runs splendidly with the dark cowhide strap. With this http://www.repliquemontre1735.com watch, men's identity will get a nostalgic touch.",1 -"For any winter garments, Moncler, jazzy appearance by moncler utilizing light notwithstanding warm substance. It will be the most recent acclaimed, exceptional outline and very in vogue. When you got the thought, you can get that it truly is worth to possess. Gone ahead and work with us. You generally found what you might want. Red sewed Vest through Moncler Clothes with not one but rather two front side affixed wallets. The Vest offers focus section packed studs affixing proceeding into the high back of the shirt. Winter's Men and ladies coats gathering never showed up back notwithstanding moncler sale dependably take after the development in the main successive pies the young's tendency. Moncler by utilizing immaculate plan indicates basically the most one of a kind style and polished spruce up these months. Moncler jacken stylish to pick up each of the lights in the winter, Moncler at http://www.cheapmonclersale.co.uk materials is probably the critical matter texture, a strong Moncler is in all probability the sun's natural brilliance.",1 -"This is a great inspiring article.I am pretty much pleased with your good work.You put really very helpful information... Free music downloads for android",1 -"I read a article under the same title some time ago, but this articles quality is much, much better. How you do this.. voyance amour",1 -"I read a article under the same title some time ago, but this articles quality is much, much better. How you do this.. voyance amour",1 -"I have read your blog it is very helpful for me. I want to say thanks to you. I have bookmark your site for future updates. Le Quest Qingjian Realty 516 Units",1 -"دانلود قسمت 1 اول فصل دوم سریال شهرزاد, دانلود رایگان فصل اول و دوم سریال شهرزاد, دانلود سریال جدید شهرزاد , دانلود سریال شهرزاد با لینک مستقیم, دانلود فیلم های جدید و برتر, دانلود رایگان فیلم و سریال با لینک مستقیم دانلود قسمت 1 اول فصل دوم سریال شهرزاد",1 -"Such a nice blog and i appreciate your all efforts about your thoughts. it's really good work. well done.I would like to share something really helpful for education. [College Essay Help][1] - - - [1]: https://myassignmenthelp.com/essay-help/college-essays-help.html",1 -"I like this post,And I figure that they having a ton of fun to peruse this post,they might take a decent site to make an information,thanks for sharing it to me. dentist juarez mexico",1 -"It became indispensable set of tools after I learned about it from [buy esssay info][1] immediately! I used to work with Python Libraries and I am glad those tools appeared! - - - [1]: http://buyessay.info/",1 -"Furnished with cluster of valuable control and estimation apparatuses. This little yet effective Pocket Science Lab empowers you to perform different investigations and [Do My Homework][1] study an extensive variety of wonders. - - - [1]: http://www.homeworkclock.com/",1 -"I have read your blog it is very helpful for me. I want to say thanks to you. I have bookmark your site for future updates. me atelie",1 -"The Python Software Foundation (PSF) is a 501(c)(3) non-benefit organization that holds the protected innovation rights behind the Python programming dialect. We deal with the open source permitting [Essay Writers][1] for Python rendition 2.1 and later and claim and ensure the trademarks related with Python. - - - [1]: http://www.essaystigers.co.uk",1 -"This discussion will present us with various proposition of [Assignment Writers][1] . It's be a surely sharp searching at process and the transmit amassing is doing doing wonderful work. - - [1]: https://www.lawessayshelp.co.uk/law-assignment.php",1 -"There is a great book that helped me [make my thesis][1] and develop my own library in Python. Natural Language Toolkit (set of libraries and projects for typical NLP for English coded in the Python) saved my own project. - - - [1]: http://www.buythesisonline.org/write-my-thesis.php",1 -"A programming dialect like pycon is splendid for doing little projects like this as the projects are effectively changed to suit your necessities This is valid for pie diagrams, bar graphs and histograms. You can even make shapes (ie application frame as [Dissertation Writing Service UK][1] has) utilizing print proclamations and yielding to the printer when you have the Presentation agreeable to you. - - - [1]: http://www.dissertationhelpdeal.co.uk/",1 -"Get free gift cards online free keys generated online. you can find stmkeyscodes.net steam gift cards and wallet codes at retail stores across the world in a variety of denomination.",1 -"It sounds like you are attempting to keep running before you can walk. On the off chance that you don't know anything about programming (HTML is a record increase dialect and has nothing to do with programming) you ought to begin by picking up programming/python. [top paper service][1] When you know python you will have a more prominent comprehension of what (or in the event that) you would require Django/Flask and so forth. - - - [1]: http://www.toppaperservice.com",1 -"Django is a free and open source web application structure, written in Python, [toppaperservice][1] which takes after the model–view–controller building design it is kept up by the Django Software Foundation (DSF), an autonomous association built up as non-beneficial. - - - [1]: http://www.toppaperservice.com",1 -"This is really unique post for me to read about animal computer interaction. I am an experienced assignment writer as well as I work at [UK Assignment Help][1] agency and talking to machine is my favorite topic and I have written many thesis and research paper on it. now I'm working on Neural Networks in Machine Learning which is almost completed. - - - [1]: https://www.assignmenthelponweb.co.uk/",1 -"Rather than fighting against something that's already broken beyond repair, create something new that causes that thing to become irrelevant ([custom essay company][1]'s citation). This is precisely how paradigms change. - - - [1]: http://essaywriting.center",1 -"This talk will give us different recommendation of task essayist uk. It's be a truly sharp taking a gander at process and the transmit social affair is doing great work. [Buy Dissertation Online][1] - - - [1]: https://www.affordable-dissertation.co.uk/buy-dissertations-online/",1 -"The discussion expect some commonality or interest about high volume applications and general comprehension of grouping, apportioning and so forth. Some perusing of the accompanying connections may be useful yet is a bit much... [Dissertation Writing Service][1] - - - [1]: https://www.theacademicpapers.co.uk/dissertation-writing-services-uk.php",1 -"Greatful post! I added to bookmarks this page, keep this level up! [192.168.0.1][1] - - - [1]: http://19216801ip.com/",1 -"Thanks for this well and amazing post given here [Snapchat Login][1]. - - - [1]: https://snapchatonlinelogin.org",1 -"wow! we are as a programmer this is good news for us! becaus Python is one of the famous programming laguage people want to developed software in pathon we know pathon is really complicated programming diynamic laguage its not easy task for every programmer because of this weshoud take help such kind articles and videos as well, and we should do need more practice then may be we will understand this language expert programmer said about paython its very complicated then C++, C#.[Suicide Squad Leather Coat][1] - - - [1]: http://www.getmyleather.com/product/suicide-squad-joker-coat",1 -"Decorator charges can fluctuate contingent upon your area. Decorators in some cases include commission the item they are obtaining for you since we get the item at a lesser cost than if a standard customer strolled in. For the most part, that is the thing that you pay when you go to a furniture store and work with their decorator [Complete Seo Services][1] On the off chance that you employ an expert planner that is authorized (ASID or IIDA) hope to pay at least $75.00 and hour and they for the most part make commission on item also. The originator will work up an agreement for your particular needs. -Yes, decorators and creators will run shopping with you to help you, as a rule this is the point at which the planner charges by the hour. - - - [1]: http://www.seoservicesland.com",1 -"A great deal of companies that provide [write essays for me][1] services are scams, look out only for the best. - - - [1]: https://gradexy.com",1 -"Thanks for sharing nice post please do share [Pizza Hut hours][1] - - - [1]: http://usholidayhours.com/pizza-hut-hours-near-me/",1 -"Thanks for sharing please do share such post [McDonald's hours][1] - - - [1]: http://usholidayhours.com/mcdonalds-hours-near-me/",1 -"[Costco hours][1] - - -[Chase bank hours][2] - - -[KFC hours][3] - - - [1]: http://usholidayhours.com/costco-hours-near-me/ - [2]: http://usholidayhours.com/chase-bank-hours-near-me/ - [3]: http://usholidayhours.com/kfc-hours-near-me/",1 -"Relatively few individuals would utilize the words Python and Microsoft in a similar sentence. In any case, as a general rule there is parcel of Python advancement occurring at Microsoft, In this open talk, we will discuss Python Development focus on Azure, Python instruments for Visual Studio, [Essay Writing Services][1] different Python SDKs accessible for Azure administrations et cetera. To put it plainly, we will discuss everything that Microsoft is doing with Python. - - - [1]: http://www.assignmentgurus.co.uk/essay-writing-service/",1 -"May i know the procedure of improvement of foods grown from the ground in the plant? help me please...? - [writing assignment help in uk][1] (amid the germination of dust grain, a dust tube is formed)explain to me what is the ""generative core"" and ""vegetative core"" and how are the procedure? - - - [1]: http://www.assignmentmaster.co.uk/",1 -Check comment,0 -"Thanks, like your linkedin account. NVF seems to be worthy. I'll have a look at it. -[domyhomeworkonline.net][1] webmaster - - - [1]: http://domyhomeworkonline.net/",1 -"Ability of gaining knowledge of new things quick and easily is an tremendous talent of some human beings however there are approaches to growth mastering agility mainly for newly graduated college students who've taken Essay Writing Service UK for writing their essay.",1 -"Ability of gaining knowledge of new things quick and easily is an tremendous talent of some human beings however there are approaches to growth mastering agility mainly for newly graduated college students who've taken Essay Writing Service UK for writing their essay.",1 -"You need to probable pursue Data Science first, on the way to come up with the technical skills and experience.[Assignment Help][1] - - - [1]: https://www.lawessayshelp.co.uk/law-assignment.php",1 -"Thanks for sharing this post please do share such post [USPS hours][1] - - - [1]: http://uspstrackingdetails.com/usps-saturday-sunday-delivery-time/",1 -"Thanks for sharing please do sharing [USPS tracking][1] - - -[USPS hold mail][2] - - - [1]: http://uspstrackingdetails.com/usps-tracking/ - [2]: http://%20%20http://uspstrackingdetails.com/usps-hold-mail/",1 -"Thanks for sharing please do sharing [USPS change of Address][1] - - - [1]: http://uspstrackingdetails.com/usps-change-of-address/",1 -"Thanks for sharing please do sharing [USPS change of Address][1] - - -[USPS lost tracking Number][2] - - - [1]: http://uspstrackingdetails.com/usps-change-of-address/ - [2]: http://uspstrackingdetails.com/usps-lost-tracking-number/",1 -"Love what you're doing here guys, keep it up you also go here: http://www.kizigamesxl.com/",1 -"It’s viable to feature the predicted outcome for the target market As in, on the quilt of this presentation. [Buy Essay UK][1] - - - [1]: https://www.britishessaywritingservice.co.uk/buy-essay-uk.php",1 -"It’s viable to feature the predicted outcome for the target market As in, on the quilt of this presentation. [Buy Essay UK][1] - - - [1]: https://www.britishessaywritingservice.co.uk/buy-essay-uk.php",1 -"Heard about Sairam before. Really interesting young man. Hope new workshop would be interesting too, `cause I want to take a part in it too",1 From 5ed8ffd91f4e72ec64b0f9faabbbc2e43cc3bbc5 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 10 Mar 2020 15:55:09 +0530 Subject: [PATCH 586/666] Adopt nox and get rid of requirements-dev.txt --- .gitignore | 1 + noxfile.py | 45 +++++++++++++++++++++++++++++++++++++ requirements-dev.txt | 25 --------------------- tools/requirements-docs.txt | 2 ++ tools/requirements-lint.txt | 1 + tools/requirements-test.txt | 6 +++++ 6 files changed, 55 insertions(+), 25 deletions(-) create mode 100644 noxfile.py delete mode 100644 requirements-dev.txt create mode 100644 tools/requirements-docs.txt create mode 100644 tools/requirements-lint.txt create mode 100644 tools/requirements-test.txt diff --git a/.gitignore b/.gitignore index 3ace00b8..5e56fe35 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ +.nox/ .coverage .cache .pytest_cache/ diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 00000000..90838bcb --- /dev/null +++ b/noxfile.py @@ -0,0 +1,45 @@ +"""Automation using nox. +""" + +import nox + + +@nox.session(python=["3.5", "3.6", "3.7", "3.8"]) +def test(session): + session.install("-r", "requirements.txt") + session.install("-r", "tools/requirements-test.txt") + + session.run("pytest", "--cov", "-v", "--tb=native") + session.run("coverage", "report", "-m") + + +@nox.session(python=["3.5", "3.6", "3.7", "3.8"]) +def lint(session): + session.install("-r", "tools/requirements-lint.txt") + session.run( + "flake8", + "--max-complexity=24", + "--statistics", + "--benchmark", + "--ignore=E5,F4", + "junction/" + ) + # TODO: Add tests/ to the arguments above. + + +@nox.session(python="3.5") +def docs(session): + session.install("-r", "tools/requirements-docs.txt") + + def get_sphinx_build_command(kind): + return [ + "sphinx-build", + "-W", + "-c", "docs/", # see note above + "-d", "docs/build/_doctrees/" + kind, + "-b", kind, + "docs/" + kind, + "docs/_build/" + kind, + ] + + session.run(*get_sphinx_build_command("html")) diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 2fdd7590..00000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,25 +0,0 @@ --r requirements.txt - -# Testing -# ------------------------------------------------- -factory-boy==2.11.1 - -flake8==2.4.1 -pytest-django==3.4.8 -pytest-flakes==2.0.0 -pytest-cov==2.6.1 - -coverage==4.5.3 - -# Documentation -# -------------------------------------------------- -mkdocs==1.0.4 -bumpversion==0.5.3 - -# Debugging -# -------------------------------------------------- -ipdb==0.12 - -# Patch for html5lib - issue #520 -html5lib==1.0.1 -bleach==3.1.0 diff --git a/tools/requirements-docs.txt b/tools/requirements-docs.txt new file mode 100644 index 00000000..2f271cb0 --- /dev/null +++ b/tools/requirements-docs.txt @@ -0,0 +1,2 @@ +sphinx==2.4.4 +recommonmark==0.6.0 diff --git a/tools/requirements-lint.txt b/tools/requirements-lint.txt new file mode 100644 index 00000000..6d831fb1 --- /dev/null +++ b/tools/requirements-lint.txt @@ -0,0 +1 @@ +flake8==2.4.1 diff --git a/tools/requirements-test.txt b/tools/requirements-test.txt new file mode 100644 index 00000000..a6b423c8 --- /dev/null +++ b/tools/requirements-test.txt @@ -0,0 +1,6 @@ +factory-boy==2.11.1 + +pytest-django==3.4.8 +pytest-cov==2.6.1 + +coverage==4.5.3 From 2f58f9076faafc2c5a226c749fa18b95d0557b1e Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 10 Mar 2020 16:01:34 +0530 Subject: [PATCH 587/666] Rework Travis CI setup --- .travis.yml | 73 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index befcff2d..32a7687f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,40 +1,63 @@ -language: python -sudo: false -python: -- '2.7' -- '3.4' -- '3.5' +# System information +os: linux addons: postgresql: "9.3" +services: + - redis -cache: - directories: - - $HOME/.pip-cache/ +language: python +python: 3.5 +cache: pip + +# Use a two-stage approach, to minimize CI time on failures. +stages: +- primary +- secondary + +env: DJANGO_SETTINGS_MODULE="settings.test_settings" + +jobs: + include: + # Basic Checks + - stage: primary + env: NOXSESSION=lint-3.5 + - env: NOXSESSION=test-3.5 + # - env: NOXSESSION=docs + + - stage: secondary + env: NOXSESSION=test-3.6 + python: 3.6 + ## Commented out, due to: Pinned psycopg2 not being compatible. + # - env: NOXSESSION=test-3.7 + # python: 3.7 + ## Commented out, due to: + ## 1. Pinned celery version not being compatible. + ## 2. Pinned Django version not being compatible with newer celery. + ## 3. Current codebase needing quite a few changes to be compatible + ## with newer Django. + # - env: NOXSESSION=test-3.7 + # python: 3.7 install: - - pip install pip==9.0.1 - - pip install -r requirements-dev.txt --allow-all-external - - pip install coveralls - - pip install --upgrade pytest + # Get the latest pip + - python -m pip install --upgrade pip + # Reinstall pip, using the latest pip + - python -m pip install --force-reinstall pip -env: - - DJANGO_SETTINGS_MODULE="settings.test_settings" + # Install the CI dependencies + - python -m pip install -r requirements.txt + - python -m pip install nox + - python -m pip install coveralls +before_script: + - celery -A junction worker -l info & script: -- flake8 -- pytest --cov -v --tb=native -- coverage report -m - + - nox after_success: - coveralls + - coveralls notifications: email: on_success: change # [always|never|change] on_failure: always # [always|never|change] -services: - - redis-server - -before_script: - - celery -A junction worker -l info & From 3e8c345752e2e126a0bb4607b9f9798737ee549a Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 10 Mar 2020 18:07:12 +0530 Subject: [PATCH 588/666] Make flake8 happy --- junction/proposals/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/junction/proposals/views.py b/junction/proposals/views.py index 52b805ad..ec1a0410 100644 --- a/junction/proposals/views.py +++ b/junction/proposals/views.py @@ -183,7 +183,7 @@ def detail_proposal(request, conference_slug, slug, hashid=None): proposal = get_object_or_404(Proposal, slug=slug, conference=conference) return HttpResponseRedirect(proposal.get_absolute_url()) - if proposal.deleted == True: + if proposal.deleted: raise Http404("404") # Here we have obtained the proposal that we want to display. @@ -295,7 +295,6 @@ def proposals_to_review(request, conference_slug): if not permissions.is_proposal_reviewer(request.user, conference): raise PermissionDenied - proposals_qs = Proposal.objects.select_related( 'proposal_type', 'proposal_section', 'conference', 'author', ).filter(conference=conference).filter(status=ProposalStatus.PUBLIC).order_by('created_at') From 1132663190eafb1d1e575bea3c587a9d5b5d4968 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 10 Mar 2020 18:18:01 +0530 Subject: [PATCH 589/666] HACK: Install pinned celery in Travis CI This should reduce our install times --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 32a7687f..826ab43e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,7 @@ install: - python -m pip install --force-reinstall pip # Install the CI dependencies - - python -m pip install -r requirements.txt + - python -m pip install celery==3.1.20 # pin from requirements.txt - python -m pip install nox - python -m pip install coveralls From 6a6b487cb60b038c2ad14684d6c8f0cf8876e02f Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 10 Mar 2020 20:59:15 +0530 Subject: [PATCH 590/666] Update .travis.yml --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 826ab43e..81acded2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,7 +50,7 @@ install: - python -m pip install coveralls before_script: - - celery -A junction worker -l info & + - celery -A junction worker -l info --detach script: - nox after_success: @@ -60,4 +60,3 @@ notifications: email: on_success: change # [always|never|change] on_failure: always # [always|never|change] - From caaeec7b436765447dffd44f85c5b07ee3c110e1 Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Tue, 17 Mar 2020 16:18:32 +0530 Subject: [PATCH 591/666] Use psycopg2-binary instead of psycopg2 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a81dc30b..a4110d3c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ django-filter==1.0.1 # Persistent Store # ------------------------------------------------- -psycopg2==2.7.3 +psycopg2-binary==2.8.4 redis==2.10.0 dj-database-url==0.4.1 From c23b1dcfdd39d316bed5c6db4df8d18d253e8729 Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Tue, 17 Mar 2020 16:24:58 +0530 Subject: [PATCH 592/666] Add missing Django install to travis CI steps --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 81acded2..37e3977b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,6 +46,7 @@ install: # Install the CI dependencies - python -m pip install celery==3.1.20 # pin from requirements.txt + - python -m pip install Django==1.9 # pin from requirements.txt - python -m pip install nox - python -m pip install coveralls From d07f8cb1fcd2bef3158569a0f4c6eeaef5daf9fe Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Tue, 17 Mar 2020 16:36:21 +0530 Subject: [PATCH 593/666] Upgrade Postgres in CI environment to 12.2 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 37e3977b..907cbce6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ # System information os: linux addons: - postgresql: "9.3" + postgresql: "12.2" services: - redis From ddc1ccc8f31683321dceba754987486a341e9c43 Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Tue, 17 Mar 2020 16:50:56 +0530 Subject: [PATCH 594/666] Upgrade coverage to 5.0.4 There was a version mismatch in coverage. pytest was generating reports with 4.x while CI environment was fetching coverage using 5.x --- tools/requirements-test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/requirements-test.txt b/tools/requirements-test.txt index a6b423c8..c0eae20c 100644 --- a/tools/requirements-test.txt +++ b/tools/requirements-test.txt @@ -3,4 +3,4 @@ factory-boy==2.11.1 pytest-django==3.4.8 pytest-cov==2.6.1 -coverage==4.5.3 +coverage==5.0.4 From 474af2b0bfe0da002078827ab47c4db5bc47e4fa Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Tue, 17 Mar 2020 16:57:50 +0530 Subject: [PATCH 595/666] Re-enable tests on Python 3.7 --- .travis.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 907cbce6..fe9c2282 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,16 +27,8 @@ jobs: - stage: secondary env: NOXSESSION=test-3.6 python: 3.6 - ## Commented out, due to: Pinned psycopg2 not being compatible. - # - env: NOXSESSION=test-3.7 - # python: 3.7 - ## Commented out, due to: - ## 1. Pinned celery version not being compatible. - ## 2. Pinned Django version not being compatible with newer celery. - ## 3. Current codebase needing quite a few changes to be compatible - ## with newer Django. - # - env: NOXSESSION=test-3.7 - # python: 3.7 + - env: NOXSESSION=test-3.7 + python: 3.7 install: # Get the latest pip From 13b49475dd62a08c4b6d6a544c0ef4ff09ab5b57 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 3 Apr 2019 10:35:12 +0530 Subject: [PATCH 596/666] Rewrite contributing guide to ReST --- CONTRIBUTING.md | 40 ---------------------------------- CONTRIBUTING.rst | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 40 deletions(-) delete mode 100644 CONTRIBUTING.md create mode 100644 CONTRIBUTING.rst diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 21bd7b5b..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,40 +0,0 @@ -# Contributing - -All contributions are much welcome and greatly appreciated! Expect to be credited for you effort. - - -## General - -Generally try to limit the scope of any Pull Request to an atomic update if possible. This way, it's much easier to assess and review your changes. - -You should expect a considerably faster turn around if you submit two or more PRs instead of baking them all into one major PR. - - -## Pull Request Guidelines - -Before you submit a pull request, check that it meets these guidelines: - -1. All the pull requests are made against `master` branch. - -2. The pull request should include tests. - -3. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.md. - -4. The pull request containing UI changes should have screen shots. - -5. If you are already not added to `CONTRIBUTORS.txt`, please add yourself in :) - -## Conventions - -- Read and pay attention to current code in the repository -- For the Python part, we follow pep8 in most cases. We use [`flake8`](http://flake8.readthedocs.org/en/latest/) to check for linting errors. Once you're ready to commit changes, check your code with `flake8` with this command - - - flake8 --max-complexity=24 --statistics --benchmark --ignore=E5,F4 / - -If there is any error, fix it and then commit. - -- For the Django part, we follow standard [Django coding style](https://docs.djangoproject.com/en/1.7/internals/contributing/writing-code/coding-style/). - -- If you are changing/creating any model, use `./manage.py makemigrations ` to generate the migrations. Send PR. Let other's review the models. - -- And always remember the Zen. diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 00000000..22c7e3ec --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,56 @@ +Thank you for your interest in contributing to Junction. We welcome all +contributions and greatly appreciate your effort! + +Bugs / Feature Requests +----------------------- + +If you have found any bugs or would like to request a new feature, please do +check if there is an existing issue already filed for the same, in the +project's GitHub `issue tracker`_. If not, please file a new issue. + +Issue Workflow +-------------- + +Choose an issue from the `issue tracker`_ to work on and claim it by posting +a comment saying "I would like to work on this.". Feel free to ask any doubts +in the issue thread. + +Once you have implemented the feature to an extent, go ahead and file a pull +request, following the tips below. File a pull request early to get as much +feedback early as possible. + +Pull Requests Tips +------------------ + +Pull Requests should be small to facilitate easier review. Keep them +self-contained, and limited in scope. Studies have shown that review quality +falls off as patch size grows. Sometimes this will result in many small PRs to +land a single large feature. + +Checklist: + +1. All pull requests *must* be made against the ``master`` branch. +2. Include tests for any functionality you implement. Any contributions helping + improve existing tests is welcome. +3. Update documentation as necessary and provide documentation for any new + functionality. +4. In case of UI changes, please include screenshots. +5. Add yourself to ``CONTRIBUTORS.txt`` if you're not there already. :) + +Code Convention +--------------- + +We follow the `Django Coding Style`_ and enforce it using `flake8`_. + +In general, if flake8 is happy with your code, you should be fine. To use +``flake8`` to check your code, you can use the following command:: + + $ flake8 --max-complexity=24 --statistics --benchmark --ignore=E5,F4 / + +If you do make any changes to models (modification or addition), make sure to +run ``python manage.py makemigrations`` to enable the server to migrate existing +data to the new models. + +.. _`issue tracker`: https://github.com/pythonindia/junction/issues +.. _`flake8`: https://flake8.readthedocs.org/en/latest/ +.. _`Django Coding Style`: https://docs.djangoproject.com/en/2.2/internals/contributing/writing-code/coding-style/ From a43029fe0a0e60df5ea4f3629d467f1485530608 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 3 Apr 2019 15:05:47 +0530 Subject: [PATCH 597/666] Simplify CONTRIBUTING.rst --- CONTRIBUTING.rst | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 22c7e3ec..7885cacc 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,26 +1,23 @@ Thank you for your interest in contributing to Junction. We welcome all contributions and greatly appreciate your effort! -Bugs / Feature Requests ------------------------ +Bugs and Features +----------------- If you have found any bugs or would like to request a new feature, please do check if there is an existing issue already filed for the same, in the project's GitHub `issue tracker`_. If not, please file a new issue. -Issue Workflow --------------- - -Choose an issue from the `issue tracker`_ to work on and claim it by posting -a comment saying "I would like to work on this.". Feel free to ask any doubts -in the issue thread. +If you want to help out by fixing bugs, choose an issue from the `issue +tracker`_ to work on and claim it by posting a comment saying "I would like to +work on this.". Feel free to ask any doubts in the issue thread. Once you have implemented the feature to an extent, go ahead and file a pull -request, following the tips below. File a pull request early to get as much -feedback early as possible. +request, following the tips below. File a pull request early to get feedback as +early as possible. -Pull Requests Tips ------------------- +Pull Requests +------------- Pull Requests should be small to facilitate easier review. Keep them self-contained, and limited in scope. Studies have shown that review quality @@ -37,6 +34,10 @@ Checklist: 4. In case of UI changes, please include screenshots. 5. Add yourself to ``CONTRIBUTORS.txt`` if you're not there already. :) +If you do make any changes to models (modification or addition), make sure to +run ``python manage.py makemigrations`` to enable the server to migrate existing +data to the new models. + Code Convention --------------- @@ -47,10 +48,6 @@ In general, if flake8 is happy with your code, you should be fine. To use $ flake8 --max-complexity=24 --statistics --benchmark --ignore=E5,F4 / -If you do make any changes to models (modification or addition), make sure to -run ``python manage.py makemigrations`` to enable the server to migrate existing -data to the new models. - .. _`issue tracker`: https://github.com/pythonindia/junction/issues .. _`flake8`: https://flake8.readthedocs.org/en/latest/ .. _`Django Coding Style`: https://docs.djangoproject.com/en/2.2/internals/contributing/writing-code/coding-style/ From 8a144a98ced424c3cf253080d706160acbfa4742 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 10 Mar 2020 15:30:34 +0530 Subject: [PATCH 598/666] Move contributing file into .github --- CONTRIBUTING.rst => .github/CONTRIBUTING.rst | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CONTRIBUTING.rst => .github/CONTRIBUTING.rst (100%) diff --git a/CONTRIBUTING.rst b/.github/CONTRIBUTING.rst similarity index 100% rename from CONTRIBUTING.rst rename to .github/CONTRIBUTING.rst From ce4e9415f134022acfabeef3eb71278c129de7ef Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Thu, 19 Mar 2020 23:54:47 +0530 Subject: [PATCH 599/666] Address review comments --- .github/CONTRIBUTING.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/CONTRIBUTING.rst b/.github/CONTRIBUTING.rst index 7885cacc..ec7ed753 100644 --- a/.github/CONTRIBUTING.rst +++ b/.github/CONTRIBUTING.rst @@ -5,16 +5,16 @@ Bugs and Features ----------------- If you have found any bugs or would like to request a new feature, please do -check if there is an existing issue already filed for the same, in the -project's GitHub `issue tracker`_. If not, please file a new issue. +check in the project's GitHub `issue tracker`_, if there is a similar existing +issue already filed. If not, please file a new issue. If you want to help out by fixing bugs, choose an issue from the `issue tracker`_ to work on and claim it by posting a comment saying "I would like to work on this.". Feel free to ask any doubts in the issue thread. Once you have implemented the feature to an extent, go ahead and file a pull -request, following the tips below. File a pull request early to get feedback as -early as possible. +request by following the tips below. File a pull request early to get feedback +as early as possible. Pull Requests ------------- @@ -27,8 +27,8 @@ land a single large feature. Checklist: 1. All pull requests *must* be made against the ``master`` branch. -2. Include tests for any functionality you implement. Any contributions helping - improve existing tests is welcome. +2. Include tests for any functionality you implement. Contributions that + improve existing tests are welcome. 3. Update documentation as necessary and provide documentation for any new functionality. 4. In case of UI changes, please include screenshots. From 23c67ac132abe8ec925bea34923344b4ee3f9e6d Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Fri, 20 Mar 2020 01:19:24 +0530 Subject: [PATCH 600/666] Better nox automation (#630) * Fix nox -s docs * Add default "dev" session, as a development env --- noxfile.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/noxfile.py b/noxfile.py index 90838bcb..bd3c0ce6 100644 --- a/noxfile.py +++ b/noxfile.py @@ -3,6 +3,17 @@ import nox +nox.options.sessions = ["dev"] +nox.options.reuse_existing_virtualenvs = True +nox.options.error_on_external_run = True + + +@nox.session(python="3.5") +def dev(session): + session.install("-r", "requirements.txt") + + session.run("python", "manage.py", *session.posargs) + @nox.session(python=["3.5", "3.6", "3.7", "3.8"]) def test(session): @@ -35,11 +46,10 @@ def get_sphinx_build_command(kind): return [ "sphinx-build", "-W", - "-c", "docs/", # see note above "-d", "docs/build/_doctrees/" + kind, "-b", kind, - "docs/" + kind, - "docs/_build/" + kind, + "docs/source", + "docs/build/" + kind, ] session.run(*get_sphinx_build_command("html")) From 9198b96faa7a4c17530a94c97e6cf7195c630b6a Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Fri, 20 Mar 2020 02:14:50 +0530 Subject: [PATCH 601/666] Add Sphinx documentation and Getting Started guide (#620) * Add an initial skeleton for Sphinx documentation * Onboard existing documentation to new docs/ * Update getting started guide * Update Getting Started for nox-based development --- docs/Makefile | 19 +++ docs/make.bat | 35 +++++ .../images/add_new_proposal_reviewer.png | Bin .../images/add_proposal_section_reviewer.png | Bin .../_static}/images/list_reviews.png | Bin .../images/proposal_reviewers_list.png | Bin .../images/proposal_section_reviewer_list.png | Bin .../images/reviewers_proposal_detail.png | Bin .../_static}/images/reviewers_talk.png | Bin docs/source/conf.py | 51 +++++++ docs/source/development/getting-started.rst | 130 ++++++++++++++++++ docs/source/development/index.rst | 11 ++ docs/source/index.rst | 21 +++ docs/{ => source/old}/api.md | 6 +- docs/{ => source/old}/conference_reviewers.md | 18 +-- docs/{ => source/old}/index.md | 10 +- docs/{ => source/old}/release_notes.md | 7 +- 17 files changed, 294 insertions(+), 14 deletions(-) create mode 100644 docs/Makefile create mode 100644 docs/make.bat rename docs/{ => source/_static}/images/add_new_proposal_reviewer.png (100%) rename docs/{ => source/_static}/images/add_proposal_section_reviewer.png (100%) rename docs/{ => source/_static}/images/list_reviews.png (100%) rename docs/{ => source/_static}/images/proposal_reviewers_list.png (100%) rename docs/{ => source/_static}/images/proposal_section_reviewer_list.png (100%) rename docs/{ => source/_static}/images/reviewers_proposal_detail.png (100%) rename docs/{ => source/_static}/images/reviewers_talk.png (100%) create mode 100644 docs/source/conf.py create mode 100644 docs/source/development/getting-started.rst create mode 100644 docs/source/development/index.rst create mode 100644 docs/source/index.rst rename docs/{ => source/old}/api.md (97%) rename docs/{ => source/old}/conference_reviewers.md (58%) rename docs/{ => source/old}/index.md (86%) rename docs/{ => source/old}/release_notes.md (96%) diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..ba501f6f --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,19 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..7665eb05 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/docs/images/add_new_proposal_reviewer.png b/docs/source/_static/images/add_new_proposal_reviewer.png similarity index 100% rename from docs/images/add_new_proposal_reviewer.png rename to docs/source/_static/images/add_new_proposal_reviewer.png diff --git a/docs/images/add_proposal_section_reviewer.png b/docs/source/_static/images/add_proposal_section_reviewer.png similarity index 100% rename from docs/images/add_proposal_section_reviewer.png rename to docs/source/_static/images/add_proposal_section_reviewer.png diff --git a/docs/images/list_reviews.png b/docs/source/_static/images/list_reviews.png similarity index 100% rename from docs/images/list_reviews.png rename to docs/source/_static/images/list_reviews.png diff --git a/docs/images/proposal_reviewers_list.png b/docs/source/_static/images/proposal_reviewers_list.png similarity index 100% rename from docs/images/proposal_reviewers_list.png rename to docs/source/_static/images/proposal_reviewers_list.png diff --git a/docs/images/proposal_section_reviewer_list.png b/docs/source/_static/images/proposal_section_reviewer_list.png similarity index 100% rename from docs/images/proposal_section_reviewer_list.png rename to docs/source/_static/images/proposal_section_reviewer_list.png diff --git a/docs/images/reviewers_proposal_detail.png b/docs/source/_static/images/reviewers_proposal_detail.png similarity index 100% rename from docs/images/reviewers_proposal_detail.png rename to docs/source/_static/images/reviewers_proposal_detail.png diff --git a/docs/images/reviewers_talk.png b/docs/source/_static/images/reviewers_talk.png similarity index 100% rename from docs/images/reviewers_talk.png rename to docs/source/_static/images/reviewers_talk.png diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 00000000..4eb84cd5 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,51 @@ +project = 'Junction' +copyright = '2019, Junction Developers' +author = 'Junction Developers' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['recommonmark'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + +# The suffix of source filenames. +source_suffix = { + '.rst': 'restructuredtext', + '.md': 'markdown', +} + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# -- Recommonmark/Markdown stuff --------------------------------------------- +# NOTE: This entire section should be removed once the old/ folder is removed +# from the docs/ directory. + +from recommonmark.parser import CommonMarkParser +from recommonmark.transform import AutoStructify + + +def setup(app): + app.add_config_value('recommonmark_config', { + 'enable_auto_toc_tree': True, + }, True) + app.add_transform(AutoStructify) diff --git a/docs/source/development/getting-started.rst b/docs/source/development/getting-started.rst new file mode 100644 index 00000000..3f438155 --- /dev/null +++ b/docs/source/development/getting-started.rst @@ -0,0 +1,130 @@ +=============== +Getting Started +=============== + +We’re pleased that you are interested in working on Junction. + +This document is meant to get you setup to work on Junction and to act as a +guide and reference to the the development setup. If you face any issues during +this process, please `open an issue`_ about it on the issue tracker. + + +Initial Setup +============= + +Junction's development workflow is automated using `nox`_. Thus, you need +the ``nox`` command to be installed on your system. We recommend using ``pipx`` +to install ``nox`` in its own isolated environment. + +.. code-block:: console + + $ python -m pip install pipx + $ pipx install nox + +You will need to have a working Redis server on your system. You may +additionally need PostgreSQL and TCL as well. + +.. note:: + + On Debian based systems, these can be installed using: + + .. code-block:: console + + $ sudo apt-get install redis-server libpq-dev tcl + +Backend +------- + +Create a "settings" file for local development with Django. + +.. code-block:: console + + $ cp settings/dev.py.sample settings/dev.py + +Create the database structure and populate it with sample data. + +.. code-block:: console + + $ nox -- migrate --noinput + $ nox -- sample_data + +Admin Access +^^^^^^^^^^^^ + +When sample data is generated with ``nox -- sample_data``, a superuser is +created with the username ``admin`` and password ``123123``. + + +Frontend +-------- + +Working on Junction's frontend requires `NodeJS`_ to be installed on your +system. The frontend is built using `bower`_ and `grunt`_. To setup the working +environment, run the following: + +.. code-block:: console + + $ cd junction/static + $ npm install + $ bower install + +Development workflow +==================== + +Frontend Autobuilding +--------------------- + +Junction has a Grunt configuration that is useful when working on the frontend. +The following command starts a build watcher which rebuilds the frontend on +every file change. + +.. code-block:: console + + $ grunt + +Invoking ``manage.py`` +---------------------- + +Junction's ``nox`` configuration is set up to invoke manage.py when no other +session (i.e. ``-s ...``) is specified. This also automatically sets up an +isolated environment that contains the dependencies of Junction. + +.. code-block:: console + + $ nox # equivalent to 'python manage.py' + $ nox -- runserver # equivalent to 'python manage.py runserver' + $ nox -- migrate # equivalent to 'python manage.py migrate' + +Running tests +------------- + +For running the tests, run: + +.. code-block:: console + + $ nox -s tests + +Running linters +--------------- + +For running the linters, run: + +.. code-block:: console + + $ nox -s lint + +Building documentation +---------------------- + +For building the documentation, run: + +.. code-block:: console + + $ nox -s docs + +.. _`open an issue`: https://github.com/pythonindia/junction/issues +.. _`virtualenv`: https://virtualenv.pypa.io/en/stable/ +.. _`nox`: https://nox.readthedocs.io/en/stable/ +.. _`NodeJS`: https://nodejs.org/ +.. _`bower`: https://bower.io/ +.. _`grunt`: https://gruntjs.com/ diff --git a/docs/source/development/index.rst b/docs/source/development/index.rst new file mode 100644 index 00000000..c4f6b665 --- /dev/null +++ b/docs/source/development/index.rst @@ -0,0 +1,11 @@ +Development +=========== + +Junction is a volunteer maintained open source project and we welcome +contributions of all forms. The sections below will help you get started with +development, testing, and documentation. + +.. toctree:: + :maxdepth: 2 + + getting-started diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 00000000..6056fec0 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,21 @@ +Junction +======== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + development/index + +.. toctree:: + :glob: + :hidden: + + old/index + +Indices and tables +------------------ + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/api.md b/docs/source/old/api.md similarity index 97% rename from docs/api.md rename to docs/source/old/api.md index 5fc1f955..cba51222 100644 --- a/docs/api.md +++ b/docs/source/old/api.md @@ -1,5 +1,6 @@ -### API +# API +**NOTE: This document and linked sections may be out of date.** Junction provides API to access information about the conference, schedule, and feedback. The API is for mobile clients to assist conference attendees. All the request and response format is `application/json`. @@ -171,7 +172,8 @@ Junction provides API to access information about the conference, schedule, and - Sample Payload: -```{'text': [{'text': 'Ok', 'id': 1}], 'schedule_item_id': 1, 'choices': [{'id': 1, 'value_id': 1}]} +``` +{'text': [{'text': 'Ok', 'id': 1}], 'schedule_item_id': 1, 'choices': [{'id': 1, 'value_id': 1}]} ``` diff --git a/docs/conference_reviewers.md b/docs/source/old/conference_reviewers.md similarity index 58% rename from docs/conference_reviewers.md rename to docs/source/old/conference_reviewers.md index a77273fa..0ecb3ee9 100644 --- a/docs/conference_reviewers.md +++ b/docs/source/old/conference_reviewers.md @@ -1,20 +1,22 @@ # Add conference moderators +**NOTE: This document and linked sections may be out of date.** + First add users to `Proposal Reviewers` model and assign them to `Proposal Sections` as reviewers. -![List Proposal Reviewers](https://raw.githubusercontent.com/pythonindia/junction/master/docs/images/proposal_reviewers_list.png) -![Add proposal Reviewers](https://raw.githubusercontent.com/pythonindia/junction/master/docs/images/add_new_proposal_reviewer.png) +![List Proposal Reviewers](https://raw.githubusercontent.com/pythonindia/junction/master/docs/_static/images/_proposal_reviewers_list.png) +![Add proposal Reviewers](https://raw.githubusercontent.com/pythonindia/junction/master/docs/_static/images/_add_new_proposal_reviewer.png) - Assign unique name to reviewer. This name will be shown in review comments to proposers. All reviewers can see other reviewers comments. Section reviewers can only add reviews. -![List Proposal Section Reviewer](https://raw.githubusercontent.com/pythonindia/junction/master/docs/images/proposal_section_reviewer_list.png) -![Add Proposal Section Reviewer](https://raw.githubusercontent.com/pythonindia/junction/master/docs/images/add_proposal_section_reviewer.png) +![List Proposal Section Reviewer](https://raw.githubusercontent.com/pythonindia/junction/master/docs/_static/images/_proposal_section_reviewer_list.png) +![Add Proposal Section Reviewer](https://raw.githubusercontent.com/pythonindia/junction/master/docs/_static/images/_add_proposal_section_reviewer.png) -# Reviewer Comments +## Reviewer Comments On the proposal page, reviewers can see all `Reviews` and `Reviewers Talk` section. -![Proposal Page](https://raw.githubusercontent.com/pythonindia/junction/master/docs/images/reviewers_proposal_detail.png) -![Proposal Review](https://raw.githubusercontent.com/pythonindia/junction/master/docs/images/list_reviews.png) -![Proposal Reviewer Talk](https://raw.githubusercontent.com/pythonindia/junction/master/docs/images/reviewers_talk.png) +![Proposal Page](https://raw.githubusercontent.com/pythonindia/junction/master/docs/_static/images/_reviewers_proposal_detail.png) +![Proposal Review](https://raw.githubusercontent.com/pythonindia/junction/master/docs/_static/images/_list_reviews.png) +![Proposal Reviewer Talk](https://raw.githubusercontent.com/pythonindia/junction/master/docs/_static/images/_reviewers_talk.png) diff --git a/docs/index.md b/docs/source/old/index.md similarity index 86% rename from docs/index.md rename to docs/source/old/index.md index 397f987a..84d06230 100644 --- a/docs/index.md +++ b/docs/source/old/index.md @@ -1,8 +1,14 @@ -# Junction [![Build Status](https://travis-ci.org/pythonindia/junction.svg)](https://travis-ci.org/pythonindia/junction) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pythonindia/junction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +# Junction (old) + +[![Build Status](https://travis-ci.org/pythonindia/junction.svg)](https://travis-ci.org/pythonindia/junction) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pythonindia/junction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +**NOTE: This document and linked sections may be out of date.** ---- +* [API](../api.md) +* [Release notes](../release_notes.md) +* [Conference reviewers](../conference_reviewers.md) **Version**: 0.2.0-dev diff --git a/docs/release_notes.md b/docs/source/old/release_notes.md similarity index 96% rename from docs/release_notes.md rename to docs/source/old/release_notes.md index 877bb43f..c5d11254 100644 --- a/docs/release_notes.md +++ b/docs/source/old/release_notes.md @@ -1,5 +1,8 @@ # Release Notes +**NOTE: This document and linked sections may be out of date.** + + ## [0.4.0][0.4.0] - Fix filters on the proposal review form #418 (@ChillarAnand) @@ -18,7 +21,7 @@ __Features__ - Improved conference admin. - Basic REST API for accessing conference details and proposals. - REST API to submit feedback for a talk/workshop. -- UI updates +- UI updates __Fixes__ - fix the tag filtering for all the proposal sections inside proposal list (#170) @@ -33,7 +36,7 @@ __Added__ - add support for fig based development environment (#129) - django admin got a new theme based on django-flat-theme - setup social sharing on proposal detail pages (#185) -- add `SITE_URL` settings to support path based root url of site. +- add `SITE_URL` settings to support path based root url of site. - add docker/fig setup - add celery support - send mail to reviewers for new proposals From e9b198e5dbe3841e97bb2e4d5a59d4efc62f8e3b Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Fri, 20 Mar 2020 23:54:24 +0530 Subject: [PATCH 602/666] Update common settings for take USE_ASYNC_FOR_EMAIL from environment (#634) The default value is kept to `False` to ensure backward compatibility functionally. --- settings/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/common.py b/settings/common.py index 865589da..1cdc5914 100644 --- a/settings/common.py +++ b/settings/common.py @@ -245,7 +245,7 @@ QR_CODES_DIR = ROOT_DIR + '/qr_files' -USE_ASYNC_FOR_EMAIL = False +USE_ASYNC_FOR_EMAIL = os.environ.get('USE_ASYNC_FOR_EMAIL', False) USER_SPAM_THRESHOLD = 2 From 287bb9c89ffbde3cffc11d0120b9f475bfa6f9b7 Mon Sep 17 00:00:00 2001 From: Shashank Kumar Date: Sat, 21 Mar 2020 01:02:17 +0530 Subject: [PATCH 603/666] Fixes 404 Error on conference index url (#563) --- junction/urls.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junction/urls.py b/junction/urls.py index c9c82daf..ac68cbb6 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -54,6 +54,9 @@ url(r'^tickets/', include('junction.tickets.urls')), # Proposals related + url(r'^(?P[\w-]+)/$', + RedirectView.as_view(pattern_name="proposals-list"), + name='conference-index'), url(r'^(?P[\w-]+)/proposals/', include('junction.proposals.urls')), url(r'^(?P[\w-]+)/dashboard/reviewers/', junction.proposals.dashboard.reviewer_comments_dashboard, From 37cdb911d538aecab4892940a0f5b39802bf2a15 Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Sat, 21 Mar 2020 02:08:22 +0530 Subject: [PATCH 604/666] Update .gitignore (#636) --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5e56fe35..eaa6fc9f 100644 --- a/.gitignore +++ b/.gitignore @@ -84,5 +84,7 @@ _docs_html/ # generated by unit tests qr_files/ +# mypy cache +**/.mypy_cache tmp/ From 524f2eebe4948b0f5adc19fd749563053341b3ea Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Sat, 21 Mar 2020 02:03:50 +0530 Subject: [PATCH 605/666] Fix a minor with the development setup instructions --- docs/source/development/getting-started.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/development/getting-started.rst b/docs/source/development/getting-started.rst index 3f438155..a2d6222c 100644 --- a/docs/source/development/getting-started.rst +++ b/docs/source/development/getting-started.rst @@ -22,7 +22,7 @@ to install ``nox`` in its own isolated environment. $ pipx install nox You will need to have a working Redis server on your system. You may -additionally need PostgreSQL and TCL as well. +additionally want to install Postgres, although it is optional. .. note:: @@ -30,7 +30,7 @@ additionally need PostgreSQL and TCL as well. .. code-block:: console - $ sudo apt-get install redis-server libpq-dev tcl + $ sudo apt install redis-server postgres Backend ------- From ba2a19c923f53a50046070025a0803aec39bbc65 Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Sat, 21 Mar 2020 02:04:01 +0530 Subject: [PATCH 606/666] Fix an issue with repeatability of the sample_data command The sample_data management command fails when run twice. The script should be idempotent in nature --- junction/conferences/management/commands/sample_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junction/conferences/management/commands/sample_data.py b/junction/conferences/management/commands/sample_data.py index 98748d9a..bfd1cbd5 100644 --- a/junction/conferences/management/commands/sample_data.py +++ b/junction/conferences/management/commands/sample_data.py @@ -214,7 +214,7 @@ def create_user(self, counter=None, username=None, email=None, **kwargs): "is_superuser": kwargs.get('is_superuser', False), "is_staff": kwargs.get('is_staff', kwargs.get('is_superuser', self.sd.boolean())), } - user = get_user_model().objects.create(**params) + user, _ = get_user_model().objects.get_or_create(**params) password = '123123' user.set_password(password) From c57bfdfae235e7ed7b5f13922a7fbc64dbd112f1 Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Sat, 21 Mar 2020 01:59:20 +0530 Subject: [PATCH 607/666] Add a missing migration --- .../migrations/0025_auto_20200321_0049.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 junction/proposals/migrations/0025_auto_20200321_0049.py diff --git a/junction/proposals/migrations/0025_auto_20200321_0049.py b/junction/proposals/migrations/0025_auto_20200321_0049.py new file mode 100644 index 00000000..78f5a3e4 --- /dev/null +++ b/junction/proposals/migrations/0025_auto_20200321_0049.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2020-03-20 19:19 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0024_auto_20170610_1857'), + ] + + operations = [ + migrations.AlterIndexTogether( + name='proposalcomment', + index_together=set([('is_spam', 'marked_as_spam_by'), ('commenter', 'is_spam')]), + ), + ] From 7ce60f95d610ad2febce1208c76bd071153e3695 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Sat, 21 Mar 2020 11:48:56 +0530 Subject: [PATCH 608/666] Delete .gitattributes (#633) The current configuration doesn't add much value, and I'm all for removing unnecessary files from a repository. --- .gitattributes | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 21256661..00000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto \ No newline at end of file From 87c317215aec4c71250e0150dc65b8a92db15882 Mon Sep 17 00:00:00 2001 From: Shrikrishna Singh Date: Sat, 21 Mar 2020 12:10:42 +0530 Subject: [PATCH 609/666] Suggest contributors to create a new branch to work on a new issue (#638) --- .github/CONTRIBUTING.rst | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/CONTRIBUTING.rst b/.github/CONTRIBUTING.rst index ec7ed753..1bcc55b8 100644 --- a/.github/CONTRIBUTING.rst +++ b/.github/CONTRIBUTING.rst @@ -23,16 +23,20 @@ Pull Requests should be small to facilitate easier review. Keep them self-contained, and limited in scope. Studies have shown that review quality falls off as patch size grows. Sometimes this will result in many small PRs to land a single large feature. - Checklist: -1. All pull requests *must* be made against the ``master`` branch. -2. Include tests for any functionality you implement. Contributions that +1. Always create a new branch to work on a new issue:: + + $ git checkout -b + +2. Make sure your branch is up-to-date with upstream master before you file + a pull request. +3. All pull requests *must* be made against the ``master`` branch. +4. Include tests for any functionality you implement. Contributions that improve existing tests are welcome. -3. Update documentation as necessary and provide documentation for any new +5. Update documentation as necessary and provide documentation for any new functionality. -4. In case of UI changes, please include screenshots. -5. Add yourself to ``CONTRIBUTORS.txt`` if you're not there already. :) +6. In case of UI changes, please include screenshots. If you do make any changes to models (modification or addition), make sure to run ``python manage.py makemigrations`` to enable the server to migrate existing From 2d9e8bcb9a13eff1501513af34a55e3c848fd389 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Mon, 23 Mar 2020 14:55:51 +0530 Subject: [PATCH 610/666] Fix deprecations: Round 1 (#643) * Remove an unneccesary include * Declare the app name for namespaced-include * Drop django.contrib.webdesign * Correctly hook into template settings --- junction/profiles/urls.py | 4 ++-- junction/templates/pages/home_page.html | 1 - junction/templates/static-content/blog-archive.html | 3 +-- junction/templates/static-content/coc.html | 3 +-- junction/templates/static-content/faq.html | 3 +-- junction/templates/static-content/schedule.html | 3 +-- junction/templates/static-content/speakers.html | 3 +-- junction/templates/static-content/sponsors.html | 3 +-- junction/templates/static-content/venue.html | 3 +-- junction/urls.py | 2 +- settings/common.py | 1 - settings/dev.py.sample | 6 +++--- settings/test_settings.py | 6 +++--- 13 files changed, 16 insertions(+), 25 deletions(-) diff --git a/junction/profiles/urls.py b/junction/profiles/urls.py index 63de9408..4fd15cc3 100644 --- a/junction/profiles/urls.py +++ b/junction/profiles/urls.py @@ -3,9 +3,9 @@ from . import views +app_name = "junction.profiles" + urlpatterns = [ url(r'^$', views.dashboard, name='dashboard'), url(r'^edit/$', views.profile, name='profile'), - - ] diff --git a/junction/templates/pages/home_page.html b/junction/templates/pages/home_page.html index 77c75851..b705ee24 100644 --- a/junction/templates/pages/home_page.html +++ b/junction/templates/pages/home_page.html @@ -1,7 +1,6 @@ {% extends 'base.html' %} {% load django_markdown %} -{% load webdesign %} {% load static from staticfiles %} {% block head_title %}Welcome to {{ SITE_INFO.site_name }}{% endblock %} diff --git a/junction/templates/static-content/blog-archive.html b/junction/templates/static-content/blog-archive.html index bb1a4342..4a80190e 100644 --- a/junction/templates/static-content/blog-archive.html +++ b/junction/templates/static-content/blog-archive.html @@ -1,6 +1,5 @@ {% extends 'base.html' %} -{% load webdesign %} {% block head_title %}{{ block.super }}{% endblock %} @@ -10,4 +9,4 @@

    Blog Archive

    {% block content %} {% lorem 3 p %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/junction/templates/static-content/coc.html b/junction/templates/static-content/coc.html index 4f68de15..04b1386e 100644 --- a/junction/templates/static-content/coc.html +++ b/junction/templates/static-content/coc.html @@ -1,6 +1,5 @@ {% extends 'base.html' %} -{% load webdesign %} {% block head_title %}{{ block.super }}{% endblock %} @@ -10,4 +9,4 @@

    Code of Conduct

    {% block content %} {% lorem 3 p %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/junction/templates/static-content/faq.html b/junction/templates/static-content/faq.html index da330d00..62bd7e85 100644 --- a/junction/templates/static-content/faq.html +++ b/junction/templates/static-content/faq.html @@ -1,6 +1,5 @@ {% extends 'base.html' %} -{% load webdesign %} {% block head_title %}{{ block.super }}{% endblock %} @@ -10,4 +9,4 @@

    Frequently Asked Questions

    {% block content %} {% lorem 3 p %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/junction/templates/static-content/schedule.html b/junction/templates/static-content/schedule.html index a01a55c7..07cff6b3 100644 --- a/junction/templates/static-content/schedule.html +++ b/junction/templates/static-content/schedule.html @@ -1,6 +1,5 @@ {% extends 'base.html' %} -{% load webdesign %} {% block head_title %}{{ block.super }}{% endblock %} @@ -10,4 +9,4 @@

    Schedule

    {% block content %} {% lorem 3 p %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/junction/templates/static-content/speakers.html b/junction/templates/static-content/speakers.html index bcdeecd7..621af3e3 100644 --- a/junction/templates/static-content/speakers.html +++ b/junction/templates/static-content/speakers.html @@ -1,6 +1,5 @@ {% extends 'base.html' %} -{% load webdesign %} {% block head_title %}{{ block.super }}{% endblock %} @@ -10,4 +9,4 @@

    Speakers

    {% block content %} {% lorem 3 p %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/junction/templates/static-content/sponsors.html b/junction/templates/static-content/sponsors.html index 755e573b..a9290e3f 100644 --- a/junction/templates/static-content/sponsors.html +++ b/junction/templates/static-content/sponsors.html @@ -1,6 +1,5 @@ {% extends 'base.html' %} -{% load webdesign %} {% block head_title %}{{ block.super }}{% endblock %} @@ -10,4 +9,4 @@

    Sponsors

    {% block content %} {% lorem 3 p %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/junction/templates/static-content/venue.html b/junction/templates/static-content/venue.html index 02312ead..5b55feaa 100644 --- a/junction/templates/static-content/venue.html +++ b/junction/templates/static-content/venue.html @@ -1,6 +1,5 @@ {% extends 'base.html' %} -{% load webdesign %} {% block head_title %}{{ block.super }}{% endblock %} @@ -10,4 +9,4 @@

    Venue

    {% block content %} {% lorem 3 p %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/junction/urls.py b/junction/urls.py index ac68cbb6..b422c83e 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -44,7 +44,7 @@ url(r'^$', HomePageView.as_view(), name="page-home"), # Django Admin - url(r'^nimda/', include(admin.site.urls)), + url(r'^nimda/', admin.site.urls), # Third Party Stuff url(r'^accounts/', include('allauth.urls')), diff --git a/settings/common.py b/settings/common.py index 1cdc5914..9a1350a2 100644 --- a/settings/common.py +++ b/settings/common.py @@ -57,7 +57,6 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.sites', - 'django.contrib.webdesign', ) THIRD_PARTY_APPS = ( diff --git a/settings/dev.py.sample b/settings/dev.py.sample index 77797bfb..8d6455a0 100644 --- a/settings/dev.py.sample +++ b/settings/dev.py.sample @@ -6,7 +6,7 @@ import os from .common import * # noqa DEBUG = True -TEMPLATE_DEBUG = DEBUG +TEMPLATES[0]['OPTIONS']['debug'] = DEBUG DATABASES = { 'default': { @@ -17,9 +17,9 @@ DATABASES = { ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'http' -TEMPLATE_CONTEXT_PROCESSORS += ( +TEMPLATES[0]['OPTIONS']['context_processors'].extend([ "django.core.context_processors.debug", -) +]) EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' diff --git a/settings/test_settings.py b/settings/test_settings.py index a9d0ac93..f4be826d 100644 --- a/settings/test_settings.py +++ b/settings/test_settings.py @@ -6,7 +6,7 @@ from .common import * # noqa DEBUG = True -TEMPLATE_DEBUG = DEBUG +TEMPLATES[0]['OPTIONS']['debug'] = DEBUG DATABASES = { 'default': { @@ -15,9 +15,9 @@ } } -TEMPLATE_CONTEXT_PROCESSORS += ( +TEMPLATES[0]['OPTIONS']['context_processors'].extend([ "django.core.context_processors.debug", -) +]) EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' From 677fa095763318447e7b549a7706869818cca7be Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Mon, 23 Mar 2020 16:34:25 +0530 Subject: [PATCH 611/666] Add get conference view to handle / urls and act accordingly (#647) Two cases may exist when accessing `/` : 1. Conference Exists - Redirect to `//proposals` 2. Conference Does not exist - Show 404 Page Integration Tests for the above cases are also added. --- junction/conferences/urls.py | 10 ++++ junction/conferences/views.py | 14 +++++ junction/urls.py | 73 ++++++++++++++++---------- tests/integrations/test_conferences.py | 21 ++++++++ 4 files changed, 91 insertions(+), 27 deletions(-) create mode 100644 junction/conferences/urls.py diff --git a/junction/conferences/urls.py b/junction/conferences/urls.py new file mode 100644 index 00000000..3361b7cf --- /dev/null +++ b/junction/conferences/urls.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- + +from django.conf.urls import include, url + +from . import views + + +urlpatterns = [ + url(r'^$', views.get_conference, name='get-conference') +] diff --git a/junction/conferences/views.py b/junction/conferences/views.py index 025ed1ba..899b1b08 100644 --- a/junction/conferences/views.py +++ b/junction/conferences/views.py @@ -2,6 +2,10 @@ from __future__ import absolute_import, unicode_literals # Third Party Stuff +from django.shortcuts import get_object_or_404 +from django.core.urlresolvers import reverse +from django.http.response import HttpResponseRedirect +from django.views.decorators.http import require_http_methods from rest_framework import filters, viewsets from .models import Conference, ConferenceVenue, Room @@ -23,3 +27,13 @@ class RoomView(viewsets.ReadOnlyModelViewSet): serializer_class = RoomSerializer filter_backend = (filters.DjangoFilterBackend,) filter_fields = ('venue',) + + +@require_http_methods(['GET']) +def get_conference(request, conference_slug): + # if the conference does not exist, render 404 + get_object_or_404(Conference, slug=conference_slug) + + # redirect to /proposals else + return HttpResponseRedirect( + reverse('proposals-list', kwargs={'conference_slug': conference_slug})) diff --git a/junction/urls.py b/junction/urls.py index b422c83e..fa9338f1 100644 --- a/junction/urls.py +++ b/junction/urls.py @@ -53,31 +53,14 @@ # Tickets url(r'^tickets/', include('junction.tickets.urls')), - # Proposals related - url(r'^(?P[\w-]+)/$', - RedirectView.as_view(pattern_name="proposals-list"), - name='conference-index'), - url(r'^(?P[\w-]+)/proposals/', include('junction.proposals.urls')), - url(r'^(?P[\w-]+)/dashboard/reviewers/', - junction.proposals.dashboard.reviewer_comments_dashboard, - name='proposal-reviewers-dashboard'), - url(r'^(?P[\w-]+)/dashboard/proposal_state/$', - junction.proposals.dashboard.proposal_state, - name='proposal-state'), - url(r'^(?P[\w-]+)/dashboard/$', - junction.proposals.dashboard.proposals_dashboard, name='proposal-dashboard'), - url(r'^(?P[\w-]+)/dashboard/votes/$', - junction.proposals.dashboard.reviewer_votes_dashboard, - name='proposal-reviewer-votes-dashboard'), - url(r'^(?P[\w-]+)/dashboard/votes/export/$', - junction.proposals.dashboard.export_reviewer_votes, - name='export-reviewer-votes'), + url(r'^feedback/(?P\d+)/$', view_feedback, name='feedback-detail'), url(r'^schedule_item/(?P\d+)/$', non_proposal_schedule_item_view, name="schedule-item"), + url(r'^api/v1/', include(router.urls)), # Device url(r'^api/v1/devices/$', DeviceListApiView.as_view(), name='device-list'), @@ -90,19 +73,55 @@ url('^api/v1/feedback/$', FeedbackListApiView.as_view(), name='feedback-list'), + # User Dashboard url(r'^profiles/', include('junction.profiles.urls', namespace="profiles")), + # Static Pages. TODO: to be refactored + url(r'^speakers/$', + TemplateView.as_view(template_name='static-content/speakers.html',), + name='speakers-static'), + url(r'^schedule/$', + TemplateView.as_view(template_name='static-content/schedule.html',), + name='schedule-static'), + url(r'^venue/$', + TemplateView.as_view(template_name='static-content/venue.html',), + name='venue-static'), + url(r'^sponsors/$', + TemplateView.as_view(template_name='static-content/sponsors.html',), + name='sponsors-static'), + url(r'^blog/$', + TemplateView.as_view(template_name='static-content/blog-archive.html',), + name='blog-archive'), + url(r'^coc/$', + TemplateView.as_view(template_name='static-content/coc.html',), + name='coc-static'), + url(r'^faq/$', + TemplateView.as_view(template_name='static-content/faq.html',), + name='faq-static'), + + # Conference Pages + url(r'^(?P[\w-]+)/', include('junction.conferences.urls')), + + # Proposals related + url(r'^(?P[\w-]+)/proposals/', include('junction.proposals.urls')), + url(r'^(?P[\w-]+)/dashboard/reviewers/', + junction.proposals.dashboard.reviewer_comments_dashboard, + name='proposal-reviewers-dashboard'), + url(r'^(?P[\w-]+)/dashboard/proposal_state/$', + junction.proposals.dashboard.proposal_state, + name='proposal-state'), + url(r'^(?P[\w-]+)/dashboard/$', + junction.proposals.dashboard.proposals_dashboard, name='proposal-dashboard'), + url(r'^(?P[\w-]+)/dashboard/votes/$', + junction.proposals.dashboard.reviewer_votes_dashboard, + name='proposal-reviewer-votes-dashboard'), + url(r'^(?P[\w-]+)/dashboard/votes/export/$', + junction.proposals.dashboard.export_reviewer_votes, + name='export-reviewer-votes'), + # Schedule related url(r'^(?P[\w-]+)/schedule/', include('junction.schedule.urls')), - # Static Pages. TODO: to be refactored - url(r'^speakers/$', TemplateView.as_view(template_name='static-content/speakers.html',), name='speakers-static'), - url(r'^schedule/$', TemplateView.as_view(template_name='static-content/schedule.html',), name='schedule-static'), - url(r'^venue/$', TemplateView.as_view(template_name='static-content/venue.html',), name='venue-static'), - url(r'^sponsors/$', TemplateView.as_view(template_name='static-content/sponsors.html',), name='sponsors-static'), - url(r'^blog/$', TemplateView.as_view(template_name='static-content/blog-archive.html',), name='blog-archive'), - url(r'^coc/$', TemplateView.as_view(template_name='static-content/coc.html',), name='coc-static'), - url(r'^faq/$', TemplateView.as_view(template_name='static-content/faq.html',), name='faq-static'), # Proposals as conference home page. TODO: Needs to be enhanced url(r'^(?P[\w-]+)--/', diff --git a/tests/integrations/test_conferences.py b/tests/integrations/test_conferences.py index 666271fd..8741fe2d 100644 --- a/tests/integrations/test_conferences.py +++ b/tests/integrations/test_conferences.py @@ -1,5 +1,9 @@ +# -*- coding: utf-8 -*- + from .. import factories as f +from django.core.urlresolvers import reverse + def test_conferences(client, db): conference = f.ConferenceFactory() @@ -11,3 +15,20 @@ def test_conferences(client, db): conference.save() response = client.get('/') assert str(conference.name) not in str(response.content) + + +def test_get_conference_found(client, db): + conference = f.ConferenceFactory() + url = reverse('get-conference', kwargs={'conference_slug': conference.slug}) + response = client.get(url, follow=True) + assert response.redirect_chain == [ + (reverse('proposals-list', kwargs={ + 'conference_slug': conference.slug}), 302)] + assert str(conference.name) in str(response.content) + + +def test_conference_not_found(client, db): + url = reverse('get-conference', kwargs={'conference_slug': 'non-existent-conference'}) + response = client.get(url, follow=True) + assert len(response.redirect_chain) == 0 + assert response.status_code == 404 From 7f93dc203041401e0d06cef9edd292035ebf1059 Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Tue, 24 Mar 2020 04:10:47 +0530 Subject: [PATCH 612/666] Update requests to 2.20.0 Ref: https://github.com/pythonindia/junction/network/alerts --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a4110d3c..12db2c8b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,7 +29,7 @@ Pillow==5.4.1 django-allauth==0.32.0 oauthlib==1.1.2 python-openid==2.2.5 -requests==2.7.0 +requests==2.20.0 requests-oauthlib==0.5.0 mock==2.0.0 # Django all auth needs From 29682c06531dbf9cc62f7e8a329def39e3322460 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 24 Mar 2020 16:19:55 +0530 Subject: [PATCH 613/666] lint: Add pre-commit for linters --- .pre-commit-config.yaml | 12 ++++ junction/static/fonts/fontawesome-webfont.svg | 2 +- .../fonts/glyphicons-halflings-regular.svg | 2 +- junction/static/fonts/icomoon.svg | 2 +- junction/static/js/Chart.min.js | 2 +- junction/static/js/bootstrap-markdown.js | 2 +- junction/static/js/bootstrap.min.js | 2 +- junction/static/js/jquery-1.11.0.js | 2 +- junction/static/js/markdown.js | 2 +- junction/static/js/sweetalert.min.js | 2 +- junction/static/less/vendor.less | 2 +- .../templates/account/account_inactive.html | 2 - .../email/password_reset_key_subject.txt | 2 +- junction/templates/account/email_confirm.html | 4 -- junction/templates/account/logout.html | 2 - .../account/messages/password_changed.txt | 1 - .../account/messages/password_set.txt | 1 - .../account/password_reset_from_key.html | 2 - .../account/password_reset_from_key_done.html | 2 - junction/templates/account/password_set.html | 2 - junction/templates/account/signup_closed.html | 2 - .../email/upload_content/message.txt | 3 +- junction/templates/proposals/review.html | 2 +- junction/templates/socialaccount/base.html | 1 - .../templates/socialaccount/connections.html | 1 - .../socialaccount/snippets/login_extra.html | 1 - .../socialaccount/snippets/provider_list.html | 1 - junction/tickets/templates/sync_data.html | 3 +- junction/tickets/templates/sync_data.html~ | 3 +- setup.cfg | 1 - .../management/commands/test_sync_data.py | 64 +++++++++---------- 31 files changed, 59 insertions(+), 73 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..a6e650b5 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,12 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.5.0 + hooks: + - id: check-builtin-literals + - id: check-added-large-files + - id: check-case-conflict + - id: check-yaml + - id: debug-statements + - id: end-of-file-fixer + - id: forbid-new-submodules + - id: trailing-whitespace diff --git a/junction/static/fonts/fontawesome-webfont.svg b/junction/static/fonts/fontawesome-webfont.svg index d907b25a..b6129693 100644 --- a/junction/static/fonts/fontawesome-webfont.svg +++ b/junction/static/fonts/fontawesome-webfont.svg @@ -517,4 +517,4 @@ - \ No newline at end of file + diff --git a/junction/static/fonts/glyphicons-halflings-regular.svg b/junction/static/fonts/glyphicons-halflings-regular.svg index e3e2dc73..265491f5 100644 --- a/junction/static/fonts/glyphicons-halflings-regular.svg +++ b/junction/static/fonts/glyphicons-halflings-regular.svg @@ -226,4 +226,4 @@ - \ No newline at end of file + diff --git a/junction/static/fonts/icomoon.svg b/junction/static/fonts/icomoon.svg index 6653629f..c97c422a 100644 --- a/junction/static/fonts/icomoon.svg +++ b/junction/static/fonts/icomoon.svg @@ -14,4 +14,4 @@ - \ No newline at end of file + diff --git a/junction/static/js/Chart.min.js b/junction/static/js/Chart.min.js index 3a0a2c87..fdbb8d9d 100644 --- a/junction/static/js/Chart.min.js +++ b/junction/static/js/Chart.min.js @@ -8,4 +8,4 @@ * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md */ (function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;var i=function(t,i){return t["offset"+i]?t["offset"+i]:document.defaultView.getComputedStyle(t).getPropertyValue(i)},e=this.width=i(t.canvas,"Width"),n=this.height=i(t.canvas,"Height");t.canvas.width=e,t.canvas.height=n;var e=this.width=t.canvas.width,n=this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,customTooltips:!1,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n=0;s--){var n=t[s];if(i(n))return n}},s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e}),c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof define&&define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},m=s.min=function(t){return Math.min.apply(Math,t)},v=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),S=s.radians=function(t){return t*(Math.PI/180)},x=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),y=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),C=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=m(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=y(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,v=Math.pow(10,u),S=Math.round(f/v);(S>a||a>2*S)&&!h;)if(S>a)v*=2,S=Math.round(f/v),S%1!==0&&(h=!0);else if(n&&u>=0){if(v/2%1!==0)break;v/=2,S=Math.round(f/v)}else v/=2,S=Math.round(f/v);return h&&(S=o,v=f/S),{steps:S,stepValue:v,min:p,max:p+S*v}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),w=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=C(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),st?-.5*s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e):s*Math.pow(2,-10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*t*t*(((i*=1.525)+1)*t-i):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-w.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t:2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*w.easeInBounce(2*t):.5*w.easeOutBounce(2*t-1)+.5}}),b=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),L=(s.animationLoop=function(t,i,e,s,n,o){var a=0,h=w[e]||w.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=b(l):n.apply(o)};b(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),k=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},F=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},L(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){k(t.chart.canvas,e,i)})}),R=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},T=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},A=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),M=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},W=s.fontString=function(t,i,e){return i+" "+t+"px "+e},z=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},B=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return M(this.chart),this},stop:function(){return P(this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=R(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:T(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,A(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return C(this.options.legendTemplate,this)},destroy:function(){this.clear(),F(this,this.events);var t=this.chart.canvas;t.width=this.chart.width,t.height=this.chart.height,t.style.removeProperty?(t.style.removeProperty("width"),t.style.removeProperty("height")):(t.style.removeAttribute("width"),t.style.removeAttribute("height")),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),this.options.customTooltips&&this.options.customTooltips(!1),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(){var t,i,e,n,o,a=[],l=[],r=[];return s.each(this.datasets,function(i){t=i.points||i.bars||i.segments,t[h]&&t[h].hasValue()&&a.push(t[h])}),s.each(a,function(t){l.push(t.x),r.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),o=m(r),e=g(r),n=m(l),i=g(l),{x:n>this.chart.width/2?n:i,y:(o+e)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx,custom:this.options.customTooltips}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:C(this.options.tooltipTemplate,t),chart:this.chart,custom:this.options.customTooltips}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return f(this.value)}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=this.caretPadding=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;if(t.fillStyle=this.fillColor,this.custom)this.custom(this);else{switch(this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}B(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=W(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=z(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){if(this.custom)this.custom(this);else{B(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?z(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),tthis.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=z(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(S(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(S(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/Math.max(this.valuesCount-(this.offsetGridLines?0:1),1),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a),l=this.showHorizontalLines;t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),0!==o||l||(l=!0),l&&t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),l&&(t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+x(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+x(this.lineWidth),o=this.xLabelRotation>0,a=this.showVerticalLines;0!==e||a||(a=!0),a&&t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),a&&(t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*S(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=m([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=m([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;ip&&(p=t.x+s,n=i),t.x-sp&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;t.textAlign=0===i?"center":i===a?"center":a>i?"left":"right",t.textBaseline=r?"middle":l?"bottom":"top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'
      <% for (var i=0; i
    • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
    • <%}%>
    '};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.bars.push(new this.BarClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<% for (var i=0; i
  • <%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>'};i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(Math.abs(t)/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=Math.abs(t.value)},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)0&&ithis.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.ythis.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'
      <% for (var i=0; i
    • <%if(segments[i].label){%><%=segments[i].label%><%}%>
    • <%}%>
    '};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this); \ No newline at end of file +},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.bars.shift()},this),this.update()},reflow:function(){e.extend(this.BarClass.prototype,{y:this.scale.endPoint,base:this.scale.endPoint});var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();this.chart.ctx;this.scale.draw(i),e.each(this.datasets,function(t,s){e.each(t.bars,function(t,e){t.hasValue()&&(t.base=this.scale.endPoint,t.transition({x:this.scale.calculateBarX(this.datasets.length,s,e),y:this.scale.calculateY(t.value),width:this.scale.calculateBarWidth(this.datasets.length)},i).draw())},this)},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,percentageInnerCutout:50,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'
      <% for (var i=0; i
    • <%if(segments[i].label){%><%=segments[i].label%><%}%>
    • <%}%>
    '};i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(Math.abs(t)/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=Math.abs(t.value)},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)0&&ithis.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.ythis.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'
      <% for (var i=0; i
    • <%if(segments[i].label){%><%=segments[i].label%><%}%>
    • <%}%>
    '};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this); diff --git a/junction/static/js/bootstrap-markdown.js b/junction/static/js/bootstrap-markdown.js index a0053515..c778059a 100644 --- a/junction/static/js/bootstrap-markdown.js +++ b/junction/static/js/bootstrap-markdown.js @@ -1037,7 +1037,7 @@ if (link != null && link != '' && link != 'http://' && link.substr(0,4) == 'http') { var sanitizedLink = $('
    '+link+'
    ').text() - + // transform selection and set the cursor into chunked text e.replaceSelection('!['+chunk+']('+sanitizedLink+' "'+e.__localize('enter image title here')+'")') cursor = selected.start+2 diff --git a/junction/static/js/bootstrap.min.js b/junction/static/js/bootstrap.min.js index 7c1561a8..ceb0492b 100644 --- a/junction/static/js/bootstrap.min.js +++ b/junction/static/js/bootstrap.min.js @@ -3,4 +3,4 @@ * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('

    {% trans "Sign In" %}

    - {% if socialaccount.providers %} + {% get_providers as socialaccount_providers %} + {% if socialaccount_providers %}

    {% blocktrans %}Sign in with your third party accounts or using an existing account:{% endblocktrans %}

    diff --git a/junction/templates/socialaccount/snippets/provider_list.html b/junction/templates/socialaccount/snippets/provider_list.html index 96a29b2a..f460b3a6 100644 --- a/junction/templates/socialaccount/snippets/provider_list.html +++ b/junction/templates/socialaccount/snippets/provider_list.html @@ -1,6 +1,7 @@ {% load socialaccount %} +{% get_providers as socialaccount_providers %} -{% for provider in socialaccount.providers %} +{% for provider in socialaccount_providers %} {% if provider.id == "openid" %} {% for brand in provider.get_brands %}
  • diff --git a/settings/common.py b/settings/common.py index 6ff8a9f6..acef0347 100644 --- a/settings/common.py +++ b/settings/common.py @@ -66,9 +66,6 @@ 'allauth.socialaccount', 'allauth.socialaccount.providers.google', 'allauth.socialaccount.providers.github', - 'allauth.socialaccount.providers.twitter', - 'allauth.socialaccount.providers.linkedin', - 'allauth.socialaccount.providers.facebook', 'bootstrap3', From 5bed84d67715e07770a5659d6131bee273bd2a9f Mon Sep 17 00:00:00 2001 From: kracekumar Date: Tue, 30 May 2017 23:04:02 +0530 Subject: [PATCH 546/666] Remove dev.py --- settings/dev.py | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 settings/dev.py diff --git a/settings/dev.py b/settings/dev.py deleted file mode 100644 index 75ac5bc9..00000000 --- a/settings/dev.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -import os - -from .common import * # noqa - -DEBUG = True -TEMPLATE_DEBUG = DEBUG - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(ROOT_DIR, 'db.sqlite3'), - } -} - -ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'http' - -TEMPLATE_CONTEXT_PROCESSORS += ( - "django.core.context_processors.debug", -) - -EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' - -INSTALLED_APPS += ('django_extensions',) - -# settings for celery -BROKER_URL = os.environ.get("BROKER_URL", "redis://redis:6379/0") -CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", 'redis://redis:6379/0') From 4b70b2d49587ad865790bbf21c98c9554b1d781f Mon Sep 17 00:00:00 2001 From: kracekumar Date: Sun, 11 Jun 2017 23:06:39 +0530 Subject: [PATCH 547/666] Add mark as spam --- junction/proposals/comments_views.py | 60 ++++++++++++++++++- .../migrations/0022_auto_20170610_1600.py | 45 ++++++++++++++ .../migrations/0023_auto_20170610_1633.py | 19 ++++++ .../migrations/0024_auto_20170610_1857.py | 46 ++++++++++++++ junction/proposals/models.py | 13 ++++ junction/proposals/services.py | 19 ++++++ junction/proposals/urls.py | 4 ++ junction/static/css/app.css | 3 + .../templates/proposals/detail/comments.html | 27 ++++++++- .../proposals/email/comment/message.html | 2 +- .../proposals/email/comment/message.txt | 2 +- settings/common.py | 4 ++ settings/dev.py.sample | 2 + 13 files changed, 240 insertions(+), 6 deletions(-) create mode 100644 junction/proposals/migrations/0022_auto_20170610_1600.py create mode 100644 junction/proposals/migrations/0023_auto_20170610_1633.py create mode 100644 junction/proposals/migrations/0024_auto_20170610_1857.py diff --git a/junction/proposals/comments_views.py b/junction/proposals/comments_views.py index 4d293d98..46bc8161 100644 --- a/junction/proposals/comments_views.py +++ b/junction/proposals/comments_views.py @@ -4,8 +4,10 @@ from django.conf import settings from django.contrib.auth.decorators import login_required from django.core.urlresolvers import reverse -from django.http.response import HttpResponseRedirect +from django.http.response import (HttpResponseRedirect, HttpResponse, + HttpResponseForbidden) from django.shortcuts import Http404, get_object_or_404 +from django.core.exceptions import PermissionDenied from django.views.decorators.http import require_http_methods # Junction Stuff @@ -14,7 +16,7 @@ from . import permissions from .forms import ProposalCommentForm from .models import Proposal, ProposalComment -from .services import send_mail_for_new_comment +from .services import send_mail_for_new_comment, user_action_for_spam @login_required @@ -24,6 +26,10 @@ def create_proposal_comment(request, conference_slug, proposal_slug): proposal = get_object_or_404( Proposal, slug=proposal_slug, conference=conference) form = ProposalCommentForm(request.POST) + + if request.user.is_active == False: + raise PermissionDenied() + if form.is_valid(): comment = form.cleaned_data['comment'] private = form.cleaned_data['private'] @@ -58,3 +64,53 @@ def create_proposal_comment(request, conference_slug, proposal_slug): redirect_url += "#js-comments" return HttpResponseRedirect(redirect_url) + + +@login_required +@require_http_methods(['POST']) +def mark_comment_as_spam(request, conference_slug, proposal_slug, proposal_comment_id): + if not request.is_ajax() or request.user.is_active == False: + return HttpResponseForbidden() + + conference = get_object_or_404(Conference, slug=conference_slug) + proposal = get_object_or_404( + Proposal, slug=proposal_slug, conference=conference) + proposal_comment = get_object_or_404(ProposalComment, proposal=proposal, + id=proposal_comment_id) + + if proposal_comment.is_spam: + return HttpResponse('Already marked as spam') + + proposal_comment.is_spam = True + proposal_comment.marked_as_spam_by = request.user + proposal_comment.save() + + user_action_for_spam(proposal_comment.commenter, + getattr(settings, 'USER_SPAM_THRESHOLD', 2)) + + return HttpResponse('Marked as spam') + + +@login_required +@require_http_methods(['POST']) +def unmark_comment_as_spam(request, conference_slug, proposal_slug, proposal_comment_id): + if not request.is_ajax() or request.user.is_active == False: + return HttpResponseForbidden() + + conference = get_object_or_404(Conference, slug=conference_slug) + proposal = get_object_or_404( + Proposal, slug=proposal_slug, conference=conference) + proposal_comment = get_object_or_404(ProposalComment, proposal=proposal, + id=proposal_comment_id) + + if proposal_comment.is_spam and proposal_comment.marked_as_spam_by == request.user: + proposal_comment.is_spam = False + proposal_comment.marked_as_spam_by = None + proposal_comment.save() + + user_action_for_spam(proposal_comment.commenter, + getattr(settings, 'USER_SPAM_THRESHOLD', 2)) + + return HttpResponse('Unmarked as spam') + + return HttpResponseForbidden() diff --git a/junction/proposals/migrations/0022_auto_20170610_1600.py b/junction/proposals/migrations/0022_auto_20170610_1600.py new file mode 100644 index 00000000..b231370e --- /dev/null +++ b/junction/proposals/migrations/0022_auto_20170610_1600.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2017-06-10 10:30 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('proposals', '0021_auto_20160905_0044'), + ] + + operations = [ + migrations.CreateModel( + name='SpamComment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')), + ], + ), + migrations.AddField( + model_name='proposalcomment', + name='is_spam', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='spamcomment', + name='comment', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='proposals.ProposalComment'), + ), + migrations.AddField( + model_name='spamcomment', + name='marked_by', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + migrations.AlterUniqueTogether( + name='spamcomment', + unique_together=set([('comment', 'marked_by')]), + ), + ] diff --git a/junction/proposals/migrations/0023_auto_20170610_1633.py b/junction/proposals/migrations/0023_auto_20170610_1633.py new file mode 100644 index 00000000..8cdb5ee7 --- /dev/null +++ b/junction/proposals/migrations/0023_auto_20170610_1633.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2017-06-10 11:03 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0022_auto_20170610_1600'), + ] + + operations = [ + migrations.AlterIndexTogether( + name='spamcomment', + index_together=set([('comment', 'marked_by')]), + ), + ] diff --git a/junction/proposals/migrations/0024_auto_20170610_1857.py b/junction/proposals/migrations/0024_auto_20170610_1857.py new file mode 100644 index 00000000..64c95f85 --- /dev/null +++ b/junction/proposals/migrations/0024_auto_20170610_1857.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2017-06-10 13:27 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('proposals', '0023_auto_20170610_1633'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='spamcomment', + unique_together=set([]), + ), + migrations.AlterIndexTogether( + name='spamcomment', + index_together=set([]), + ), + migrations.RemoveField( + model_name='spamcomment', + name='comment', + ), + migrations.RemoveField( + model_name='spamcomment', + name='marked_by', + ), + migrations.AddField( + model_name='proposalcomment', + name='marked_as_spam_by', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='marked_as_spam_by', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterIndexTogether( + name='proposalcomment', + index_together=set([('is_spam', 'marked_as_spam_by')]), + ), + migrations.DeleteModel( + name='SpamComment', + ), + ] diff --git a/junction/proposals/models.py b/junction/proposals/models.py index 14709ff2..af508413 100644 --- a/junction/proposals/models.py +++ b/junction/proposals/models.py @@ -291,9 +291,14 @@ class ProposalComment(TimeAuditModel): comment_type = models.PositiveSmallIntegerField( choices=ProposalCommentType.CHOICES, default=ProposalCommentType.GENERAL) objects = ProposalCommentQuerySet.as_manager() + is_spam = models.BooleanField(default=False, blank=True) + marked_as_spam_by = models.ForeignKey(User, related_name='marked_as_spam_by', + default=None, null=True, blank=True) class Meta: ordering = ('created_at', ) + index_together = [['is_spam', 'marked_as_spam_by'], + ['commenter', 'is_spam']] def __str__(self): return "[{} by {}] {}".format(self.comment, @@ -306,6 +311,14 @@ def get_up_vote_url(self): def get_down_vote_url(self): return reverse('proposal-comment-down-vote', args=[self.proposal.conference.slug, self.proposal.slug, self.id]) + def get_mark_spam_url(self): + return reverse('comment_mark_spam', + args=[self.proposal.conference.slug, self.proposal.slug, self.id]) + + def get_unmark_spam_url(self): + return reverse('comment_unmark_spam', + args=[self.proposal.conference.slug, self.proposal.slug, self.id]) + def get_votes_count(self): up_vote_count = ProposalCommentVote.objects.filter(proposal_comment=self, up_vote=True).count() down_vote_count = ProposalCommentVote.objects.filter(proposal_comment=self, up_vote=False).count() diff --git a/junction/proposals/services.py b/junction/proposals/services.py index 982a8dc7..a52775cf 100644 --- a/junction/proposals/services.py +++ b/junction/proposals/services.py @@ -8,6 +8,7 @@ # Third Party Stuff from django.conf import settings +from django.contrib.auth.models import User from markdown2 import markdown from celery import shared_task @@ -78,6 +79,10 @@ def comment_recipients(proposal_comment): for comment in proposal.proposalcomment_set .all().select_related('commenter')} recipients.add(proposal.author) + ADMINS = getattr(settings, 'SPAM_MODERATION_ADMINS', []) + if ADMINS: + for admin in ADMINS: + recipients.add(User.objects.get(email=admin)) return recipients @@ -150,3 +155,17 @@ def send_mail_for_proposal_content(conference_id, proposal_id, host): } return send_email(to=author, template_dir='proposals/email/upload_content', context=context) + + +def user_action_for_spam(user, threshold): + """When a comment is mark as spam, make appropriate status update to user model + """ + total_spam = ProposalComment.objects.filter(commenter=user, is_spam=True).count() + if total_spam >= threshold: + if user.is_active != False: + user.is_active = False + user.save() + else: + if user.is_active != True: + user.is_active = True + user.save() diff --git a/junction/proposals/urls.py b/junction/proposals/urls.py index 497b4ace..eeb05717 100644 --- a/junction/proposals/urls.py +++ b/junction/proposals/urls.py @@ -14,6 +14,10 @@ votes_views.proposal_comment_up_vote, name='proposal-comment-up-vote'), url(r'^(?P[\w-]+)/comments/(?P\d+)/down-vote/$', votes_views.proposal_comment_down_vote, name='proposal-comment-down-vote'), + url(r'^(?P[\w-]+)/comments/(?P\d+)/mark_spam/$', + comments_views.mark_comment_as_spam, name='comment_mark_spam'), + url(r'^(?P[\w-]+)/comments/(?P\d+)/unmark_spam/$', + comments_views.unmark_comment_as_spam, name='comment_unmark_spam'), ] urlpatterns = [ diff --git a/junction/static/css/app.css b/junction/static/css/app.css index b0a16788..15c944f4 100644 --- a/junction/static/css/app.css +++ b/junction/static/css/app.css @@ -8993,3 +8993,6 @@ textarea.review-form select { .dropdown { margin-left: 10px; } +.spam{ + background-color: #b3a6a6; +} diff --git a/junction/templates/proposals/detail/comments.html b/junction/templates/proposals/detail/comments.html index 574ae491..31772cd6 100644 --- a/junction/templates/proposals/detail/comments.html +++ b/junction/templates/proposals/detail/comments.html @@ -36,8 +36,19 @@
  • -
    - {{ comment.comment|markdown }} + {% if comment.is_spam %} +
    + The comment is marked as spam. + {% if request.user.is_authenticated and request.user == comment.marked_marked_as_spam_by %} + Unmark as spam + {% endif %}

    + {% else %} +
    + {{ comment.comment|markdown }} + {% if request.user.is_authenticated and request.user != comment.commenter %} + Mark as spam

    + {% endif %} + {% endif %} {% if comment.private or comment.reviewer %} {% if comment.commenter == proposal.author %} @@ -118,6 +129,18 @@
    $(_that).siblings('.vote-count').html(result); }); }); + $('.js-mark-spam').click(function(e){ + e.preventDefault(); + var that = $(this); + var url = that.attr('data-url'); + $.ajax({ + method: "POST", + url: url}) + .done(function( msg ){ + location.reload(true); + }); + }); + {% else %} $('.js-proposal-upvote, .js-proposal-downvote, .js-proposal-comment-upvote, .js-proposal-comment-downvote').click(function(e){ e.preventDefault(); diff --git a/junction/templates/proposals/email/comment/message.html b/junction/templates/proposals/email/comment/message.html index 16e4eaa6..a3fc416e 100644 --- a/junction/templates/proposals/email/comment/message.html +++ b/junction/templates/proposals/email/comment/message.html @@ -36,7 +36,7 @@

    - Click here to leave a comment + Click here to leave a comment or mark the comment as spam diff --git a/junction/templates/proposals/email/comment/message.txt b/junction/templates/proposals/email/comment/message.txt index a9a3e656..8414c04f 100644 --- a/junction/templates/proposals/email/comment/message.txt +++ b/junction/templates/proposals/email/comment/message.txt @@ -3,4 +3,4 @@ There is a new comment on {{host}}{{proposal.get_absolute_url}} by {% if comment "{{comment.comment}}" ------------------------------------------------------------------------------- -PS: Please, don't reply to the email. You can login({{host}}{{login_url}})to and leave a comment +PS: Please, don't reply to the email. You can login({{host}}{{login_url}})to and leave a comment or mark the comment as spam. diff --git a/settings/common.py b/settings/common.py index bfa7e04a..febe1fab 100644 --- a/settings/common.py +++ b/settings/common.py @@ -246,3 +246,7 @@ QR_CODES_DIR = ROOT_DIR + '/qr_files' USE_ASYNC_FOR_EMAIL = False + +USER_SPAM_THRESHOLD = 2 + +SPAM_MODERATION_ADMINS = [] diff --git a/settings/dev.py.sample b/settings/dev.py.sample index 73a4d60a..77797bfb 100644 --- a/settings/dev.py.sample +++ b/settings/dev.py.sample @@ -28,3 +28,5 @@ INSTALLED_APPS += ('django_extensions',) # settings for celery BROKER_URL = os.environ.get("BROKER_URL", "redis://127.0.0.1:6379/0") CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", 'redis://127.0.0.1:6379/0') + +SPAM_MODERATION_ADMINS = [] From 38ec44589ec68d820205211e7ce1ad39c76c081f Mon Sep 17 00:00:00 2001 From: kracekumar Date: Sun, 11 Jun 2017 23:16:56 +0530 Subject: [PATCH 548/666] Make if condition on boolean more readable --- junction/proposals/comments_views.py | 6 +++--- junction/proposals/services.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/junction/proposals/comments_views.py b/junction/proposals/comments_views.py index 46bc8161..cac3ae73 100644 --- a/junction/proposals/comments_views.py +++ b/junction/proposals/comments_views.py @@ -27,7 +27,7 @@ def create_proposal_comment(request, conference_slug, proposal_slug): Proposal, slug=proposal_slug, conference=conference) form = ProposalCommentForm(request.POST) - if request.user.is_active == False: + if request.user.is_active is False: raise PermissionDenied() if form.is_valid(): @@ -69,7 +69,7 @@ def create_proposal_comment(request, conference_slug, proposal_slug): @login_required @require_http_methods(['POST']) def mark_comment_as_spam(request, conference_slug, proposal_slug, proposal_comment_id): - if not request.is_ajax() or request.user.is_active == False: + if not request.is_ajax() or request.user.is_active is False: return HttpResponseForbidden() conference = get_object_or_404(Conference, slug=conference_slug) @@ -94,7 +94,7 @@ def mark_comment_as_spam(request, conference_slug, proposal_slug, proposal_comme @login_required @require_http_methods(['POST']) def unmark_comment_as_spam(request, conference_slug, proposal_slug, proposal_comment_id): - if not request.is_ajax() or request.user.is_active == False: + if not request.is_ajax() or request.user.is_active is False: return HttpResponseForbidden() conference = get_object_or_404(Conference, slug=conference_slug) diff --git a/junction/proposals/services.py b/junction/proposals/services.py index a52775cf..672b514c 100644 --- a/junction/proposals/services.py +++ b/junction/proposals/services.py @@ -158,14 +158,14 @@ def send_mail_for_proposal_content(conference_id, proposal_id, host): def user_action_for_spam(user, threshold): - """When a comment is mark as spam, make appropriate status update to user model + """When a comment is marked as spam, make appropriate status update to user model """ total_spam = ProposalComment.objects.filter(commenter=user, is_spam=True).count() if total_spam >= threshold: - if user.is_active != False: + if user.is_active is True: user.is_active = False user.save() else: - if user.is_active != True: + if user.is_active is False: user.is_active = True user.save() From 19f77151c98aeb8353e33cc44f7f04cce1117f2c Mon Sep 17 00:00:00 2001 From: kracekumar Date: Mon, 19 Jun 2017 22:25:10 +0530 Subject: [PATCH 549/666] Make csrf exempt --- junction/proposals/comments_views.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junction/proposals/comments_views.py b/junction/proposals/comments_views.py index cac3ae73..ebd7165c 100644 --- a/junction/proposals/comments_views.py +++ b/junction/proposals/comments_views.py @@ -9,6 +9,7 @@ from django.shortcuts import Http404, get_object_or_404 from django.core.exceptions import PermissionDenied from django.views.decorators.http import require_http_methods +from django.views.decorators.csrf import csrf_exempt # Junction Stuff from junction.conferences.models import Conference @@ -67,6 +68,7 @@ def create_proposal_comment(request, conference_slug, proposal_slug): @login_required +@csrf_exempt @require_http_methods(['POST']) def mark_comment_as_spam(request, conference_slug, proposal_slug, proposal_comment_id): if not request.is_ajax() or request.user.is_active is False: @@ -92,6 +94,7 @@ def mark_comment_as_spam(request, conference_slug, proposal_slug, proposal_comme @login_required +@csrf_exempt @require_http_methods(['POST']) def unmark_comment_as_spam(request, conference_slug, proposal_slug, proposal_comment_id): if not request.is_ajax() or request.user.is_active is False: From 782fb53659acfa8f2472cb2f44b8abdbdbbbfc91 Mon Sep 17 00:00:00 2001 From: kracekumar Date: Mon, 19 Jun 2017 22:39:19 +0530 Subject: [PATCH 550/666] Change .ajax call to .post --- junction/templates/proposals/detail/comments.html | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/junction/templates/proposals/detail/comments.html b/junction/templates/proposals/detail/comments.html index 31772cd6..1167ee7c 100644 --- a/junction/templates/proposals/detail/comments.html +++ b/junction/templates/proposals/detail/comments.html @@ -133,10 +133,8 @@
    e.preventDefault(); var that = $(this); var url = that.attr('data-url'); - $.ajax({ - method: "POST", - url: url}) - .done(function( msg ){ + $.post(url, {}, function(result){ + console.log(result); location.reload(true); }); }); From f08e4f0bccb0d830b366581d3fe7bcb579904259 Mon Sep 17 00:00:00 2001 From: kracekumar Date: Fri, 23 Jun 2017 01:31:18 +0530 Subject: [PATCH 551/666] Add spam.csv for spam filtering model --- spam.csv | 1765 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1765 insertions(+) create mode 100644 spam.csv diff --git a/spam.csv b/spam.csv new file mode 100644 index 00000000..21dbcb72 --- /dev/null +++ b/spam.csv @@ -0,0 +1,1765 @@ +comment,is_spam +Please remove contact email from Speaker Info. ,0 +Removed.,0 +You can create github/bitbucket repo for the workshop and share it later.,0 +"Yes, that is my plan. Hopefully in a couple of weeks. ",0 +"Please add a few more details about the Pythonic part of your talk. For example, write a bit about which Python modules you used in your stack. + +Thanks",0 +"Please add slides from any previous presentation you might have made on this topic. If you have tentative slides planned for this presentation, which you are incrementally working on, sharing them would be useful too. + +Thanks",0 +Sure Jaidev will add same.,0 +Just Added the slides from one of our previous talks. It was on introduction to Deep Learning. The PyCon talk will be more about python methods / libraries to implement such algorithms.,0 +"A detailed description breaking down the talk into smaller sections with more detailed description would be great! These are [some examples][1] of proposals with detailed descriptions. + + + [1]: http://rhodesmill.org/brandon/2013/example-pycon-proposals/",0 +Please let me know if you would like any particular topic from FLASK framework to be covered. I will try to include that in my workshop/session.,0 +Good Content.. Will Attend ,0 +the topic is good but i am not seeing much in the slide... it will be great if the author will share github samples...,0 +"Thanks Puneeth +Template was helpful. + +Have updated the talk based on same.",0 +"I was a successful student TUCKER BALCH, PH.D ASSOCIATE PROFESSOR COLLEGE OF COMPUTING +GEORGIA INSTITUTE OF TECHNOLOGY in his computation investment part 1 course. This subject is interesting and will be useful. Incidentally the professor is also conducting many interesting courses on automation/machine learning. For instance for a large world wide manufacturer like Brachot Hermant NV Belgium, it will be useful to use data on raw blocks and color area to predict the rejects in the final polished slabs etc. +",0 +"I was a successful student TUCKER BALCH, PH.D ASSOCIATE PROFESSOR COLLEGE OF COMPUTING +GEORGIA INSTITUTE OF TECHNOLOGY in his computation investment part 1 course. This subject is interesting and will be useful. Incidentally the professor is also conducting many interesting courses on automation/machine learning. For instance for a large world wide manufacturer like Brachot Hermant NV Belgium, it will be useful to use data on raw blocks and color area to predict the rejects in the final polished slabs etc. +",0 +"It is very much the need of the hour that we(Indians) should start developing applications in our languages. Along with this initiative, it is good to know that Tamil, one of the classical languages - leads the first step for other Indian languages. ",0 +"The CAP theorem is an impossibility result according to wikipedia. So could you explain what you mean by ""Distributed systems always demands to meet CAP theorem which is really hard to meet with a good performance numbers""?",0 +"CAP theorem happens to gurantee any two of consistency, availability & partition tolerance. If you fail to meet even two out of three then you are in danger. IMO, meeting all three is impossible, but not two.",0 +This seems really interesting. I'd be really interested to learn the ins and outs of this! :),0 +Online judges are imperative to coding competitions which form the basis for all great progrmmers. Learning to build one will be an exciting challenge and I look forward to learning more about it. ,0 +Is this the same thing which judged during cybercept15?,0 +Yes aditya.,0 +Link of pydanny-cookiecutter under **proposal description** throws 404 error and also same error to the link of cookiecutter under **Speaker-Info**,0 +"All the urls should be working fine now. Thanks a lot, Sheesh!",0 +"> It was really a great work. Good initiative effort from your side. Let +> us know more in the same which helps **students from rural areas** +> also to get involved in this to develop their own application to get +> their things done & prove themselves to the world. +> +> It's good to know that this **initiative & innovation** will sure +> bring changes & also help us to sustain with Tamil Language forever. +> All the very best for your upcoming works.",0 +I have got really high expectations from this one. Hopefully it would be good.,0 +Thanks! Hopefully I'll meet them.,0 +This seems super interesting!,0 +"Nice and Challenging Topic. +does this module deal with Data cleansing of text also.",0 +"Sorry the github link was wrong. Its + +https://github.com/saisrk",0 +"It directly supports only regular expressions for text cleaning, but it also provides third-party support for arbitrary data cleaning. So you can have all the text cleaning functionality in a separate module and this module will automate all of that.",0 +This is wonderful Course content for Beginners like me. Please let me know when you are conducting.,0 +"Looks like there is duplicate talk . Can one of you delete on the talk. +https://in.pycon.org/cfp/pycon-india-2015/proposals/building-nextgen-iot-solutions-using-python-and-cloud/",0 +"This talk is to explain how a distributed database architecture can drive more reliable web apps. Even for startups who use Python and wants a database which is fault tolerant with no down time ,Riak is helpful. Talk will clarify when to use Riak DB and how we can exploit it using Python ,the easiest language to write more efficient Web apps.",0 +"This one will be hands-on workshop, where people will build the solution on development boards. We will do the session talk first in https://in.pycon.org/cfp/pycon-india-2015/proposals/building-nextgen-iot-solutions-using-python-and-cloud/ which will involve demos, and then people who are interested to do hands-on can attend this workshop.",0 +Seems to be good implementation of python + mongo + web interface. Complete end to end usage of mongo database and python coding.,0 +"Just in case this was not clear. + +This proposal is a second step to the one I did last year, It's supposed to teach advanced concepts and design patterns to be used in mobile development. + +The slides are right now a copy of what we had last year with minor changes. I am adding new content every day to it to include advanced concepts inside it instead of the old content. + +I have the basic outline of the presentation mentioned in the proposal above. The slides will be updated based on that.",0 +"good work effort - ""changing passcode easy"" :) :) :) ",0 +"It would be especially interesting to have a talk related to Cyber Security and Python at Pycon. I have been interested in attending talks on Python and its use in Cyber security but surprisingly there have not been many talks in this area at Pycon. I was at Pycon North America and OWASP team had visited Pycon North America this year but there was no talk by them. There was one by Jacob Kaplan Moss at Pycon Australia which was really cool. [1] + +[1] https://www.youtube.com/watch?v=sra9x44lXgU",0 +NIce Article !! ,0 +Great to know...,0 +"It is a great topic. +Looking forward to attend same. +",0 +Nice article,0 +Nice *Proposal,0 +Nice proposal samarth!!,0 +Great idea....,0 +"Saurabh, I guess the workshops are on the first day of the event, before the talks happen. So what you are suggesting, will not work.",0 +"As one of the co-authors of Two Scoops of Django, I can say that Saurabh's contributions to the book were useful and voluminous. His work on cookiecutter-django is nothing short of brilliant. He has my full confidence. I recommend this talk very highly.",0 +"The description of the talk is way short for the topic, and it does not explain why the speakers are the best person to give this talk.",0 +Missing speaker info. There should be enough material to prove why the speaker is a good person to talk about Python3. He should also point to the Python3 projects he worked on.,0 +Please add an outline of your talk to the description. Otherwise this looks good.,0 +A well written proposal.,0 +This should be a good talk.,0 +"Very good topic, but please add an outline of the talk.",0 +Thanks Kushal. I'll add an outline shortly. ,0 +Thank you!,0 +Can you please add some talk outline to the description? The current description does not give any details about the talk itself.,0 +Can you please add some talk outline in the description? ,0 +Looking forward to the talk. :),0 +"Can you please elaborate on your approach? + +Are you hacking python's safe builtins? Are you relying on a library or are you running the whole thing in a container? ",0 +Thanks :),0 +A good proposal. It would be interesting to learn about using Python for things other than traditional programming.,0 +Interesting talk and by a speaker who knows what he is talking about. Will encourage new contributors. Definite +1.,0 +Definitely going to sit for this talk.,0 +I really hope that this talk gets selected. Documentation is often treated as a step child or a second class citizen. Experience shows that how much it helps when you have good and correct documentation and thusly removes a lot of technical debt.,0 +"A solid technical speaker, someone who personally uses Openshift.",0 +A very interesting and relevant topic. Look forward to attending the talk. ,0 +The talk description needs more details about the talk.,0 +The description does not have enough content.,0 +The description does not have enough content.,0 +This is a good proposal. It will be nice if you can add a point based talk outline.,0 +The talk description is too small. Looks like the speaker(s) did not spend enough time for this talk.,0 +Haris is a good coder and great speaker. I would love to come and watch his talk.,0 +"Arun knows his stuff, which is why we link to his book from ours (Two Scoops of Django). ",0 +"I don't think this is a talk for beginners. Beginners may not know what CI is. Also, there is not enough detail in the description to compare this with Jenkins or Travis. On what basis is Tunir simpler than these CI systems? Please add more details.",0 +"Thanks for the comment, marking it for the beginners was a typo. I will be adding few more points about why tunir is easier to use. ",0 +Thanks Ronojoy,0 +"Flask ( Werkzeug ) debugger uses this approach to render traceback. Developer can go back to any point and inspect the variable. Good topic. + +![Werkzeug Error Image][1] + + + [1]: http://werkzeug.pocoo.org/docs/0.10/_images/debug-screenshot.png ",0 +"Hi Jaseem, + We have built our own python sandbox in python itself. We are not using any external libraries.",0 +@kushal Done. Hope the outline is helpful and the way you were expecting.,0 +I updated the talk. Let me know if I can fix something more.,0 +"Hi Vishal, + +Thank you for the proposal. Can you provide some information on the following : + +1. Pandas, Sci-Kit learn, MRJob, Matplotlib : All of these are comprehensive in themselves, how do you plan to cover them in the stipulated time. +2. You mentioned demonstrating few practical applications, can you share what kind of examples are you planning to cover ? +3. What features will you covering when you talk about MRjob ? Do you also plan to cover topics like deployments and dependency resolutions on the data node when using Python with MRJob. +4. What all data sets are you planning to use . +5. Can you also share you previous talk videos / slides. + +Looking forward for more discussions. +",0 +Please provide with more details. On what all do you plan to discuss.,0 +"The objective is to expose audience on how to build big data streaming architecture. The talk would include 3 aspects: Challenges of building streaming architecture, tools and technologies for building such an architecture and finally Python libraries and tools available that can be used. + +Focus is on big data design paradigm and tools available in python to facilitate it. + + ",0 +"A problem I've not seen addressed (to my personal satisfaction) is about provisioning. i.e. how do you ensure that the development team is working in an identical environment as the production server? Initial setup is well and good, but how to maintain it? As in; when more and more features are added, some developer boxes get out-of-sync with production - and you don't exactly realize this until something horrible happens. Will something like this be covered in the talk?",0 +Nice one.,0 +"Please add the real life use-cases, how FUSE helps writing file systems in few lines of code..may be accessing social content on filesystem as a usecase in addition to toyfs ! + +Also describe your intended audience ! + +Cheers!",0 +"@Rohit : I pretty much like the experiences you have shared in the blogpost mentioned above, but to me it looks like a very DevOps talk comparing one monitoring sytem with other, rather than a PyCon Talk. That said, I would still love to see it on stage if not on the main talks but certainly as lightning talk or open spaces. + +Can you try write shed some more light if you can suit it more to pythonic audience. ?",0 +"Looking at the slides you shared, to me it is a hello word for Vagrant. Can you list more detailed points of how you plan to make it suitable for PyCon India audience. ",0 +Please add a detailed outline of how and what you plan to share to the audience.,0 +"Hi Konark, + +Good to hear your viewpoint. I think, it is a pythonic talk because: + +* Shinken is a 100% python project. The package is available in PyPi (pip install shinken). +* It has a very modular design. Even the default web UI is a separate python module. Installed using shinken installer (shinken install webui). +* Plugins can be written in any language, including python. I have some of mine in a [github repo](https://github.com/rohit01/nrpe-plugins). + +\> *Can you try write shed some more light if you can suit it more to pythonic audience. ?* +I see a lot of talks, which talks about how python is being used instead of talking about the syntax. This talk presents shinken, a tool built using python, its high level architecture and demonstrates how it is better than Nagios (written in C). + +Thanks",0 +"Vagrant is for every web developer or designer. So I think this talk is for everyone in the conference. +My PRUG meetup talk was just a getting started with vagrant. +But here I am planning to use Django project for demo and will play with it using vagrant. +I am planning to show how we can deploy app on cloud using vagrant. +Nowadays we have complex server architectures. +I will show how we can have different django web and database server And how they communicate with each other. +",0 +Good topic I must say. ,0 +"@sarthak : Thank you for your proposal. Would request you please write down a rough agenda of your talk. Also, assuming you are writing your topologies in Python , please mention the libraries you plan to use. + +Looking forward to it.",0 +"AFAIK, now it's an Apache foundation project, so you might want to update the abstract with the same instead of Twitter.",0 +"@sagar : Request you to edit the abstract, and add a detailed list of things and how you plan to present them. Bullet points at this time should be good.",0 +@venu : Can you share more details the things / concepts / code you are to talk about. ,0 +@Anuvrat : Thank you for your detailed proposal.,0 +"Hi, + +Please share more details on what kind of plugins are you going to present, if possible link to the repos. where the code is hosted. Also, please provide an agenda of how you plan to structure your talk. +",0 +"where could i get the content of this speech, i want learn and test the navigation on RPi2. if i can get it somewhere, it will be very helpful.",0 +"Hi Wang + +I will upload the slides soons. Was busy with some projects, thats why its delayed. + +Thanks",0 +"@konark: kindly take a look at the slides as well ... +shall soon be adding some code to them.",0 +"nice, it will been so helpful for me. +thank you very much.",0 +Is there an Open Source project that will be showcased or it would be more of an take-pointers-and-do-it-yourself talk?,0 +"@konark: The library I am using is [streamparse][1] by the guys at [Parse.ly][2]. + +The rough agenda would be to take the audience through Storm, it's power and capabilities and then running through a Python way to do this. Maybe even ship in a small demo. + +Also, I have mentioned Apache Storm itself throughout. Twitter now owns this project, by the way. + + + [1]: http://streamparse.readthedocs.org/en/latest/index.html + [2]: http://www.parsely.com/",0 +Yes we will be showcasing an open source project that will utilize the Open source threat feeds and based on that will will extract meaningful and actionable information for security operations and engineering.,0 +"Thats really cool. Would look forward to the talk. + +If you are willing you can add some more details about the Open source project/threat feeds/preso/links! + +Just brief pointers would be suffice, for the audience to have a better know-how/background about the talk. +",0 +Looking forward for this talk.,0 +"@arocks: intent here is to help Python developers code faster using the VS IDE with VS Tools for Python. The focus is on Python tools for developer productivity +",0 +"@arocks: and probably it got so many votes because it sounds interesting, why else I wonder",0 +"how much of Django would we need to know for the workshop to benefit us? +Say I don't know any Django now but I'm willing to learn a bit before the workshop, would I be able to grasp it? Also, would you be teaching some part of how to make good web apps with Django? ",0 +"Typo in slide 8 -- ""XSS protection in DJnago""",0 +"@kahlil - It would be advantageous if have already tried out one or two projects in Django. Even if you do have done the Django official polls tutorial, you'll be able to pickup a lot of things. ",0 +"Arink, + Is this talk you are proposing here ? if not what is the project which you want people to contribute to ? + ",0 +"Here, It is not related to any project. This proposal is for talk.",0 +"Hey Swapnil, + I see your workshop is selected for this year PyCon India. + Just for information Devsprint and workshop will be happening parallel. + Am not sure how will you manage both places ?",0 +"Presentation Link + +https://docs.google.com/presentation/d/1OSdw6D8vkjuXsGJVTACTxJfISSi7E8G1QGbgqSXZxog/edit#slide=id.p3",0 +"Presentation Link + +https://docs.google.com/presentation/d/1OSdw6D8vkjuXsGJVTACTxJfISSi7E8G1QGbgqSXZxog/edit#slide=id.p3",0 +"Presentation Link + +https://docs.google.com/presentation/d/1OSdw6D8vkjuXsGJVTACTxJfISSi7E8G1QGbgqSXZxog/edit#slide=id.p3",0 +"Hi: + +I made some changes to the presentation: + +Link here: https://docs.google.com/presentation/d/1lvexV8yKJckedrGRTk_63_K7vWhLv-z80yaKbvFTBbs/edit#slide=id.p + +Would love to discuss improvements. One of the reviewers had mentioned continuity issues and I would be happy to discuss how we can fix this. + +Best regards, +Jeet",0 +"it would be really great if we could do a meetup in Bangalore. I am sure there are lot of developers willing to use Kivy. I am one of them. I missed last year's con. I will try to go through the docs link that you have added. And thanks, this is one of my interest since java is not in cup. ",0 +"Hi Rakesh, + +I would love to do a workshop in Bangalore in one of your meet-ups. Btw for people who didn't get to be a part of the original workshop, I would be available the entire day of the workshop. We have a section for kivy in dev sprints if you want to come over and try to follow the old workshop material yourself I will be available to help out if you have any problems.",0 +Here is my talk slide. https://www.slideshare.net/secret/3kOc9GTTiNYxlv,0 +"Here is my talk slide for PyCon 2015 + + https://www.slideshare.net/secret/3kOc9GTTiNYxlv",0 +"For online slides please visit + + +http://narenaryan.github.io/Pycon-India-2015-Talk/",0 +"That's great Akshay, I have purchased this workshop ticket. as you said i will attend the Kivy dev sprints too. I have filled the registration form too and I have not gotten the confirmation. should I be waiting of should I contact some one else. +",0 +"Thanks for submitting. +Can you please attach the link of the poster for the talk?",0 +"@rakesh The dev sprints were just finalized, let's wait for one more day, if you still don't get a confirmation then you can e-mail me and I will ask the organizers to get in touch with you. +",0 +"Hello Praveen, + +Thanks for submitting the proposal. +http://etpython.info/media/releases/psf-python-brochure-vol.-i-final-download.pdf is not working. Please fix it. +Can you attach the poster image url in the proposal? + +Thanks, + +Chandan Kumar",0 +"Hello Chandan, + +I have added the poster deck. + +",0 +"Please assemble add the slides in a single poster for example check here: https://drive.google.com/file/d/0B3WeDMkqc0DoUFM3elJwV2F0cEU/view?usp=sharing +",0 +"I can help by sharing my experiences with the Chennai Python User Group, Chennaipy.",0 +"I would request to name topic as ""Discussion on Building and Running Communities"" ",0 +"Changed the topic , feel free to suggest changes and jot down any points that come to your mind on to the piratepad link http://piratepad.net/pycondiscussion",0 +"Vignesh, + We need to add even PyChill topic.",0 +"Hi Chandan Kumar + +I have fixed the link and have also added the link to the poster. + +Thanks and regards +Praveen",0 +Requesting a response again. One of the review comments mentioned issues with continuity. Can you please help me fix it?,0 +"Thanks akshay, I got the confirmation and i am selected for Dev Sprints. At what time is the Kivy dev sprints? ",0 +"@Rakesh, I guess they will start at the time other dev sprints do start. I will try to make it by 9:30pm.",0 +"@Akshay, you mean 9.30 A.M right not 9.30 P.M :) ",0 +"yes, 9:30 am :)",0 +"Please find venue and time detail for your talks: + +Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) + +Time: 11 am - 11:30 am + +Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 +Date for talk is 3rd Oct.,0 +"Please find venue and time detail for your talks: + +Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) + +Time: 11:30 am - 12:00 noon + +Date: 3rd Oct + +Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 +"Please find venue and time detail for your talks: + +Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) + +Time: 12 noon - 12:30 am + +Date : 3rd Oct + +Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 +Sorry the Time is 12 noon - 12:30 pm,0 +"Please find venue and time detail for your talks: + +Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) + +Time: 11 am - 11:30 am + +Date : 4th Oct + +Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 +"Please find venue and time detail for your talks: + +Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) + +Time: 11:30 am - 12:00 noon + +Date : 4th Oct + +Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 +"Please find venue and time detail for your talks: + +Venue: Nimhans 1st floor left side (We will put directions or some board to help you reach venue ) + +Time: 12:00 noon - 12: 30 pm + +Date : 4th Oct + +Note: We will display the Open Space talks and time slot available in white board(board will be kept at ground floor on 2nd Oct and, 1st floor on 3rd and 4th Oct). If you want to change your time slots, please reach out the board and move your talk to available time slots.",0 +"Satyaakam, + +This topic will be shifted to one of the Audi's . Time and venue details will be updated to you by the team on Conf day.",0 +"Please cancel this session. Encountered other important assignments that has come in. Assign this slot to some one else. + +Please take note of the same.",0 +"Please cancel this session. Encountered other important assignments that has come in. Assign this slot to some one else. + +Please take note of the same.",0 +"Guys, +updated the content slides. +Github repo for the code will be updated soon, struggling with slow internet speed at conference. ",0 +updated the repository which have all the demos.,0 +"Great info.I like all your post.I will keep visiting this blog very often.It is good to see you verbalize from the heart and your clarity on this important subject can be easily observed. Thanks again! +If you love gaming for unity games kindly visit…. + mobile app & game development +",1 +Can you share more relevant links to the project.,0 +"Hi, I've edited the doc and added few more links.",0 + ,0 +Looks good...,0 +"

    Nice. I'm curious to know what new features will be coming up on pagure. :)

    ++1 for this.",0 +"Hey, can you add some slides or more info about the project.",0 +Sure . I am in the process of creating them . Will put them up as soon as i finish them up . ,0 +All the Best. Do your best for all developer community worldwide.,0 +Thank you so much. @Limbani Bhavik,0 +Nice,0 +Nice bro !! I'm with you ,0 +@meet2 thanks man!!,0 + Good Job Bro..,0 + Good Job Bro..,0 + Good Job Bro..,0 +"Thanks soni kunjan @soni2 +",0 +Worth going to..,0 +"Good going, bro...!!",0 +This one is helpful..,0 +Deserves to be attended. ,0 +Feeling proud ...kashyap,0 +"Very passionate, dedicated and hard working guy. You will definitely love his sessions....",0 +great . Al the best bro,0 +"Hi Sourav, Impressive talk!. Great presentation for an undergraduate level and keep up your passion. ",0 +"Waiting to see Health Monitoring with Python. +We can team up together as i am working on python for UMLS, SNOMED and HL7. +See More : https://in.pycon.org/cfp/2016/proposals/python-for-healthcare-medical-terminologies-for-python-umls-snomed-ct-icd10-hl7~b28Je/ +",0 +@vickysam Cool. Thanx for contacting. Lets chat sometimes on e-mail at sandeep.nagar@gmail.com,0 +@Sandeep That's cool. You can catch me at vicky.chawda@gmail.com / https://in.linkedin.com/in/vicky-chawda-37b3a9100,0 +Looking forward to this talk,0 +Interesting stuff!,0 +"Siddharth, I'll complete those slides by next few weeks and I'll write here after completion. +Any input and expectation will help me. ",0 +"Interesting. +I use algo in stock market. My talk "" Application of Machine Learning and Sentiment analysis in stock market""",0 +"Will you show output of sentiment analysis using flask? +I use sentiment analysis in stock market. MY talk: "" Application of Machine Learning and Sentiment analysis in stock market""",0 +Looking forward to this talk. ,0 +@parthasen Yes I'll show the output of sentiment analysis using flask!!,0 +I'm looking forward to this. Good job @jargnar,0 +The blog post I linked should be updated in the next week to reflect some changes I made to the algorithm.,0 +This indeed does look very interesting! ,0 +Looking forward to this.,0 +Would love to attend this talk. +1,0 +Interesting one. Hoping to see this in PyCon 2016,0 +Indeed an interesting and useful topic. Looking forward to attend the talk.,0 ++1 to this,0 ++1 to this. Would love to attend the talk.,0 +The best person in Asia to give this talk. He is constantly one of the top package reviewer in Fedora land for many years.,0 +Can you please update you talk to show what all things you will talk? The current state of the proposal does not give any idea about the details.,0 +"The content may become difficult, but should be an useful talk for many.",0 +Just wondering about the standard library tag :) As Kivy is not part of the Python stdlib.,0 +Can you please add more details to your talk? It should show the things you want to talk about. Please also update the speaker's info to understand why you are the right person to give this talk.,0 +The current proposal shows more of a statement than a talk proposal with details about the talk. Please update your talk proposal to reflect the actual contents of your talk.,0 +"Thank you Kushal :-) . I tagged it this way on purpoes. If i got chance to conduct this workshop, i will share that why i tagged stldlib with this and why kivy should be be in stdlib.",0 +"this talk would bring some of the features of opencv 2 not in openCV 3 by default. Some of these features like SURF and SIFT absent in openCV 3 by defaut.Every time someone needs his old favourite tool,he has to build the binaries from scratch and then can use it. If we are able to write python libraries for opencv then that would be really great. This was just one instace, there are many more where getting a prebuit library really makes the work easier +",0 +"CFFI is good, and listening it from Noufal would be nice.",0 +Can you please update your profile to showcase your experience about flask?,0 +Thanks for this proposal.,0 +Can you please update your proposal to show more details about your talk? Like the major points you will talk about etc. Right now it is very small amount of text.,0 +Can you please update the speaker's profile section to showcase why are you a good fit to give the talk on this topic?,0 +Please update your talk proposal with more information.,0 +I have made an effort to keep the talk as informative as possible without introducing complexity into it. But you do have a point. It might end up being a heavy one.,0 +"Hi Kushal, + +Updated speaker's profile.",0 +Looking for this talk!. We are facing scaling problems .,0 +Yeah it is a wonderful concept ,0 +Yeah I too used django it works like a 'wow',0 +Yea looking for this good type of talks,0 +I think this is worth of listening,0 +I think this is worth of listening,0 +Now thats something interesting. Looking forward to this talk. ,0 +Good one bro,0 +Good job,0 +Please add more details in your talk proposal. ,0 +"Can you clarify a little more? If someone attends this talk, what will they learn? ",0 +"They will get a insight on how OpenCv gets more easier by using python. Simply , how more one can achieve by writing less and simple code.",0 +This talk needs to be more focussed. Talking about all the points mentioned in 30 minutes will not be possible in a useful fashion.,0 +Thanks. That clarifies it a little but I think a rough outline of what you're going to present will help us to understand what you're going to be talking about. Is this about using some kind of FFI to call openCV functions from within Python?,0 +"Yes FFi is the solution on one hand but what we can do is write complete newpython libraries that can be used for some basic operations that take a lot of lengthy lines of code in c++. Making it short and simple will be the key in the talk. +",0 +"Hi Kushal, + +What other details do you want in the talk proposal. I will upload the slides in another few days. + +Thanks and regards, +Annapoornima",0 +"So, is your talk about reimplementing some parts of OpenCV in pure python?",0 +"This is what actually I was looking for, thanks man good job :) ",0 +"Hi Annapoornima, +Can you clarify what is the purpose of this IoT solution? What is the problem you are trying to address? +Kind regards",0 +great work !!,0 +If you want to understand fedora package ecosystem then you don't want to miss it.,0 +Precise and informative! Piqued my curiosity further to read about Recommendation Engines. Waiting for your next write up!,0 +"Looking forward for this talk +",0 +Thanks @abhay @tushar3 . ,0 +"This proposal is selected to be for an ""Advanced"" audience. Would it be possible to add the expected outcome for the audience? As in, at the end of this presentation, what are the things they would be able to achieve?",0 +"A small set of comments - is this an overview of the experiences and challenges faced by the presenters or, does this talk intended to guide the audience (real-time) into submitting patches into the OpenStack project? Also, it does not seem very clearly articulate about how it aligns with the general theme/focus of PyCon.",0 +"This presentation is slated for an audience classified as ""Intermediate"". I'd request that the speaker (re)consider the agenda of the talk. The first two items should be provided as (pre)talk requirements and the various challenges/complexities of deploying a number of (choosing a wider pattern of applications would be great!) applications in the target environment would be a good place to start from. From thereon, moving to aspects of application lifecycle maintenance, security, availability/resiliency etc would be good-to-have topics.",0 +"""Measuring Semantic Similarity between sentences in Python"" should probably read ""Using Python to measure semantic similarity between sentences"". + +There's been a number of approaches on similar topics using nltk - if you'd like to cite them for the audience to have a conceptual grasp of the problem domain you are trying to address, it would be nice to do.",0 +"Do you happen to have a list of useful websites which could be scraped and such? I am suggesting that a bunch of ""ToDo"" or, ""Now that we have shared our knowledge, how about you/the audience consider working on these sites"" kind of list.",0 +The proposal (as read here) does not seem to clearly articulate the outcome for the audience - what would they be able to do after this talk?,0 +"The proposal (as read in the current form) does not provide adequate detail about the expected outcome for the audience - what would they be able to do at the end of the talk? Also, the scope of the topic would need some re-think. ""Core Python"" sets off expectations of deep/technical discussion around specific aspects of the programming language/design and at present the talk is a list of topics which should be available to anyone with access to documentation.",0 +"The prerequisites section could do with further detail. ""Basic knowledge"" could mean a variety of things and the audience should be clear about the expectations being set up by the speaker.",0 +"The proposal does not have adequate detail about the outcome from this talk - what can the audience get done after this talk? Also, the prerequisites section is somewhat vague. + +The current form of the proposal seems to be about ""how to use Ansible for consistent deployments"" while the ML systems are a workload specific aspect of it. Perhaps the author would (re)consider the description.",0 +Sure I am adding outcome for the audience to description. ,0 +@sankarshan The talk would enable the audience to actually get acquainted with the two above-mentioned architectures and get in a position to make a well informed decision to zero down on following either of the practice in accordance with their needs and purposes . The talk also would give them clarity on the decision to adapt a framework amidst the available python based frameworks . ,0 +"I've recently wrote a blog post for ""Getting started with scraping in python"". The site I used for my tutorial is this ""Pycon India 2016"" site itself. Please have a look at it http://satwik.ghost.io/2016/06/19/any/ . <- This is the temporary link as of now. +Regarding useful sites to scrape, there's no limit to that. A rule of thumb may be ""Whenever you want to use some data that any website is displaying, but that website doesn't have an API then you should scrape."" For example, you can scrape bookmyshow.com for list of events in your area, Flipkart for making sites like buyhatke, cricbuzz for getting cricket statistics and score and so on. However, I'll make a list of all the practical applications I could think of and upload a link to it soon. Thanks for your suggestions by the way :).",0 +There's a fine line between scraping a site and DOSing a site. Please explain to the audience the importance of not accidentally bringing the site down.,0 +"I would request that you re-visit the intended audience. I agree with your premise that Python's adoption and popularity is increasing. However, the order in which you desire the audience may just be too niche/difficult for a PyCon (and I'd be happy to be proven wrong). Instead, if you focus on the newbies and demonstrate Python's ability to be extended into calculation of risk and such, you'd probably have an audience who are hooked (there have been previous instances where risk analysis etc have been great talks).",0 +"I'd suggest that you assume that the audience is aware of the first two topics (in your proposal) and for the subsequent items, please provide a link to a dataset of reasonable size which you'd be working with and they can tinker around to reach similar results.",0 +"Do you intend to take a specific case and walk the audience through the problems and solutions in order to arrive at this stack? Or, is it an overview of how the components fit together?",0 +"Thanks, sure that helps",0 +"The typo in the title would need to be fixed. That aside, would you be using a mock application to demonstrate the test paths (along with how the actual code can be written better to aid testing)? Or, is this a general overview? + +It is intended at an ""Advanced"" level, but the proposal does not seem to address any of the topics which an advanced user of such a flow will be faced with.",0 +"The current set of topics being covered in this proposal would appeal to a beginner rather than an intermediate practitioner. Would you like to add more detail about complexities and challenges involved in building such an infrastructure or, is this a general overview?",0 +Its neither of those. 1 would be a sales pitch for SPA with redux as solution. 2 would just be an overview. The talk delves into much finer technical details mentioned in bullet points in the description. Let me know if you have any further queries. Happy to answer them. ,0 +"I noticed that there is a workshop proposal with the same title - are these two unique bits or, the same thing? Building hyperlocal weather sensors is an interesting exercise. Do you intend to cover how your audience can DIY and how it can be useful for them?",0 +"I wanted to check if you have previously presented on this topic at any local meetup. This is an interesting proposal and often, these form of proposals evolve if the speaker has been discussing these over a period of time.",0 +It would be good to have a link to the dataset you'll be using as part of the demo. The audience can choose to continue after the talk and learn.,0 +"I'd recommend turning this talk on its head. Instead of ""a gentle introduction to Ansible"" (which is a good thing, but fairly mundane), how about building up good habits in beginners and showing them how some of the common problems/pitfalls from code -> deploy can be managed via Ansible?",0 +"Hi Sankarshan: + +Yes, I am sorry for the typo, I meant Beginner's level only, I will change the level, basically the talk would just need a basic understanding or awareness of AWS EcoSystem and its components. + +Regards, +Suman++",0 +"Thanks, I've added a slide for 'Ethics of Scraping' :)",0 +Fixed..,0 +"Yes i would take a demo application and run thru the end to end testing of API using requests and unittest module. + +The Description of the talk is updated accordingly",0 +"@Sankarshan, I want to present a talk and do a workshop as well. Talk is preferable. If time permits and if I have people to do the DIY workshop, I am for it. + +@misccold, I am presenting how to collect temperature data and pass it on to the Raspberry Pi. Further, there are a plethora of things that can be done with data, some of the things that I can think on top of my head are, display heat maps, develop home automation tools, etc. Sky is just the beginning for limits.",0 +"Hey Sankarshan, thanks for asking. I have discussed about these topics with my colleagues and friends many times. Previously i have given a bunch of talks in few colleges and other meetups. My previous talks revolved around IoT and python mostly. In next month's ChennaiPy meetup, i will be giving a talk on the above proposed topic.",0 +"The goal is to guide attendees through the contribution process and encourage them that given the open nature of open source communities (in terms of documentation, guidelines, bug triage, help on IRC, review feedbacks), it becomes really simple to get acquainted with the workflow quickly and make an initial first contribution and then go on making more contributions slowly and gradually as you learn more. + +Since OpenStack is a Python based Open Source Project that is why we submitted the proposal under the Other Category.",0 +"You have written in your first line ""This workshop"" but categorized it in the form of talk. Is it suppose to be a talk or a workshop?",0 +"I had a confusion between a workshop and a talk, since the way I see it, my proposal lies between workshop and a talk. Still thanks for pointing this out. I will edit it.",0 +"It seems more apt for a workshop to me! Btw, nice proposal, looking forward for it :)",0 +"CI is a must feature for any git repo and having it on pagure is a must + +I am interested in attending this talk",0 +"Hi @megha , than you for submitting the proposal, is it possible for you to share the video / slides for the events you have spoken in the past. + +Looking at the description it seems to be more oriented towards MySQL, can these ""Best pracitices"" be applied to any DB or specifically MySQL. What is specific to python in this talk or does it revolve around databases only ? +",0 +"Can you provide more details / examples / sample code for ""Automated API Security Assessment tool"" ?",0 +"Any session by Anand is worth the time. His clarity of thought and simplicity of presentation cuts through all the cruft and explains what is needed in a clear, precise way. ",0 +" +Thanks for responding. Of course I can submit more details. Where do you want me to share it ? + +Hilal",0 +Thanks Saurabh. ,0 +Would love to attend:-). I wasn't aware about Kivy before this. I request Pycon teamm to arrange this workshop...,0 +Would love to attend...Good Job..:-),0 +"As Kivy is free and open source software ,it will have a wide scope, all the best !",0 +"@Kajal, Updated the talk. The earlier content was way too generic. ",0 +I had an opportunity to be at the audience when this talk was on Chennaipy. I had never thought about CPython in this angle. The talk gave me the insight on things that happen behind the screens. Looking forward to know about the reaction of PyCon audience.,0 +"Thank you for your submission. While the proposal, and your slides look fine as they stand, I have two questions/suggestions: +* Your slides cover basic graph theory. How about adding: + - Some example usages of graph networks in real life in order to motivate your audience + - Some advanced examples of real-life problems that are more tractable to solutions through graph networks; maybe contrasting graph networks to more commonly used relational databases +* Why a workshop? Is there enough material that cannot be covered in 40min., and needs 2-3 hours?",0 +"Thanks for showing interest. I have explained that basic knowledge of Selenium, Python and HTML is needed. Audience can expect a simple and helpful talk, which will help them to get data by themselves for their projects. ",0 +"Thank you sir for your humble suggestion. We will be adding some real life implementation of network sciences in further slides. we are still preparing the slides. There are many real time examples to discuss and brainstorm that will motivate the audience with great curiosity. we will update the slides by today. +Yes, we thought of giving some hands on experience to audience in network analysis but if it is not feasible we can shift it as a talk session. We are also planning to add some code snippets that will help attendees to understand the domain at better extent.",0 +"""""Thanks for your submission. Please provide more details, as it is difficult to judge from this what is being proposed beyond a basic introduction to app development with Kivy. Kivy has been around for a while, and many people have probably seen introductory talks. What are you going to demonstrate that is new, and why are you suited to making such a presentation. + +Please note that time is short."""" + +@Reply: Thank you sir for your humble comment. yes, I will be covering the basics along with the development of small ping pong game. In latter part, we will be developing a small git interface application with which we can update and commit the various changes in the code stored in our github repository. Its Functionality might be limited but enough to carry out basic operations like edit,update & commit. Thank you.o",0 +@prastut Its good enough! :),0 +"Seems interesting and informative, Looking forward to it!",0 +"Please add what your talk will cover about MicroPython. It will be a good idea to add talk outline, see https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example.",0 +It is not clear from the description what you will be covering in your talk. Can you please add a talk outline? See https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example.,0 +Looks like you trying cram in a lot of things into a single talk. How about focusing on one of them instead?,0 +"While you are working on the content, it would be good to make a talk outline available in the talk description. Please see https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example.",0 +"The talk looks interesting. The LinkedIn link is broken, can you please fix it. + +Also it will be great if you can elaborate on the topics you have mentioned. For example, what do you mean by ""Usage or Proper keywords""? Also what do you mean by ""Proxy layer""?",0 +"The slides seem to be inaccessible, can you please fix that? Also is the PyUnit you are referring to, the unittest module that is part of the standard library?",0 +Looks interesting ,0 +Looks interesting ,0 +Looks interesting ,0 +Added the outline!,0 +Quite interesting .. ,0 +I have added the details. Please have a look at that.,0 +"Thanks! BTW, formatting using MarkDown will make it appear better.",0 +"Yes, pyunit is part of python library.",0 +"Thanks for letting me know, fixed the link + +those are the reasons this presentation is for but if you cant wait till i attach a presentation to this talk, you can always ping me on the side ",0 +"Making things a bit explicit, will increase the chances of your proposal getting selected. Also the talk selection happens before the slide upload deadline. So it is better to beef up the talk description.",0 +Is this talk about BDD in general or is it about a particular framework?,0 +"sure, will do",0 +I have read Kashif's code and discussed some technical aspects with him. It would definitely be useful to pick his mind through this talk. Bumped it up.,0 +This is mostly about BDD framework with python and selenium. We are focusing on front-end and back-end automation using python selenium where test cases are in BDD.,0 +That's very nice. ,0 +Please provide an outline of the workshop. See https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example.,0 +"It will great if you can break the topics into subtopics and provide an outline of the talk. See https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example. + +In my opinion, the talk would be interesting if the talk includes real world implementation issues, solutions tried, what worked or what did not, etc. Or how this was used to address a specific real world problem, like in pollution control, outcomes, improvements, etc.",0 +"Thanks for the details. Please be aware that the talk duration is 30 min + 10 min for questions. Rather than talking about many different things about Micropython it would be nice to focus on one aspect. For example you might just want to drop of the part three. + +In part one, you might just want to focus on those areas that are different in Micropython. For example it would be interesting to talk about Micropython's viper and inline assembler support, and other speed optimizations done in Micropython. + +In part two, not sure why you want to use ""few"" different boards. Wouldn't a single type board suffice? You might want to list out the demos you are planning to do.",0 +Looks Interesting,0 +Looks Interesting,0 +"Thanks for review, I changed it to ""beginner"". Topics which you suggested will discuss with interested folks or will propose a session during breakout which will focus on lifecycle management, maintenance, security and availability. ",0 +"I don't think that 30 min will be sufficient to talk about the entire internal architecture of Micropython. I think I can start by introducing the board and then starting from simple examples to various code optimization parts like using native code emitters and micropython's viper code emitters. +I said multiple boards because say if you have esp8266, you can't get the inline assembler functionality( the core is based on Xtensa ) . esp8266 is the cheapest micropython board that you can get online. just for Rs.200. I can cover those areas using pyboard. I am getting 4 pyboards next week. :) + +If I talk too much about the internals then I am not sure that how many of the audience can catch-up all those. It will be better to cover those areas through examples without opening the ""C"" part of it. + +I wish I could get more suggestions and comments here. + +Thank you",0 +Sounds interesting! Looking forward to your talk. :),0 +"After learning about Machine Learning, I am all hyped up about every field which deals with data and recommendation engines sound great. +",0 +Will be adding slide in few hours. :) ,0 +"I received an email saying Reviewer01 has left a comment, but I can not see it here after login.",0 +The framework is ready to use right now. However by the time the event is held I expect many more features to be added to the framework.,0 +"Why is this classified under Python 3k? There is nothing here that talks about 2 to 3 migration, or writing compatible code. May be ""Others"" will be appropriate.",0 +"Should this be classified under ""Network Programming""?",0 +"Should this be classified under ""Network Programming""?",0 +"""Data Visualization and Analytics"" might be a more appropriate category.",0 +"""Scientific Computing"" might be a more appropriate category.",0 +"""Scientific Computing"" might be a more appropriate category.",0 +"The ""Embedded Python"" category is for hardware, electronics, and interfacting. Please re-categorize to make sure your talk gets better visibility.",0 +"Changed to ""Embedded Python"". +Thanks for the suggestion.",0 +what is the problem solving ?? then next ... ,0 +"I am not sure if I am missing something here, but BDD is a development style / process not a ""framework"" in itself. Cucumber & Robot are BDD Frameworks. Please correct me if I am wrong. + +",0 +"You have good internet connection as a pre-requisite. + +Internet issues are common at conferences. You should plan to have things working locally, instead. ",0 +"As Vijay already pointed out, can you please make the slides publicly viewable? +Thanks!",0 +"I second Vijay's suggestion of beefing up the description. An outline with +finer detail on what you want to cover will go a long way! + +If you have slides/videos of any previous talks you have given, that would be +helpful too.",0 +"It should be manageable without internet as well. + +Just in reply to one of the query thru mail, I will plan to keep this talk as simple as possible to make beginners understand what is REST API and why it is important to test an API in any application first and then making them understand the concepts of testing REST API with the help of GET/POST/PUT/DELETE methods and will detail out the demo scenarios for testing an API and then will go ahead with the use of python libraries(Requests and Unittest) for testing the REST API's. + +Also by built-in features of Requests I mean to say how with the help of requests one can GET/POST the data from/to a service and how to validate the API response and how you define the headers/params needed to access the API's. + +Try to keep the talk as simple as possible for the Python Novice to understand + +Updated the Pre-requisite accordingly.",0 +"Hello Arthy, + +Thank you for proposing this talk. + +It is not clear which tool you are describing in the description. Is it an open +source tool that the audience will be able to use for their work? If not, what +are the take aways from your talk? Are there other tools like the ones you are +going to talk about? What are your take aways from building/using this tool? + + + +",0 +I had classified this as 3k since I've only tested the code on 3k. Now that you mention it it does fit the others category too. I'll ask an admin and change if allowed.,0 +"Could you please update your proposal with your slides, at least a preliminary outline of your talk. + +We would also need links to previous talks experience in public speaking etc. + +It's also to be noted that this talk was in draft mode and made public after deadline.",0 +Could you please upload the slides of your talks along with details of any previous experience giving talks or workshops etc.,0 +Can you please upload a preliminary outline of your talk slides? Something that can help reviewers.,0 +Nice ,0 +Nice ,0 +Excellent. .very comprehensive stuff. .Good luck ,0 +"Thank you for the proposal, looks like an interesting topic, I looked at the talk shared and it would be great if you can provide some details on the following questions: + +1. How different are you planning this talk to be from the one given at PyDelhi. Please share a concrete plan. +2. Until the example shared by you which talk about the deal codes and it's user, the talk looked fairly simple of How-Tos of various tools, which I will advice to restrain from. The example looked like it's more a porblem of grep's then why this elaborate setup. +3. Since you are one of the largest e-comm companies, it would great to get some insights on numbers, throughput and scale challenges. +4. Please list down the libraries you will be using to talk to various components like elastic-search, Kafka, elastic-alert, map-reduce etc etc. + +If not structured well, this talk will be too much in too little time.",0 +"You can update the description with the same, that would be great.",0 +"Hi, + +Please update the description with a proper outline of what the talk is going to be about. + +Can you talk about: + +1. Scale at which Apache Storm is being used. +2. Is the use-case mentioned by you a production use-case or ""How to get started with Apache Storm"". +3. What libraries are you planning to share like StreamParse, Pyleus or any other. Why you would choose one over the other ? +4. What kind of deployment strategies do you follow to deploy storm cluster like green/blue deployment strategy or something else ? +5. Since you are mentioning Big Data, will you also cover how Storm cluster can be tuned and configured beyond basic deployment ? +",0 +"Prerequisites, is what the audience should know before attending your talk.",0 +aah... I think in hurry I typed it in the wrong section. Apologies. I'll update the section accordingly Vijay Kumar,0 +"@akshayaurora +I have shared the link to my slides. Note that this is just my first draft. Looking forward to your feedback.",0 +"You might want to add more information, unless this is a joke. :-)",0 +"Well the description talks about Box0. It does not what you are going to cover in your talk. Please add an outline of your talk, see https://us.pycon.org/2015/speaking/proposal_advice/samples/SpacePug/ for an example.",0 +"If you have done previous talks on the subject at local user groups, please mention them in your proposal. ",0 +I have taken workshops/seminars previously in my university but not on the same subject. Will that be useful?,0 +Excellent stuff..,0 +Excellent stuff..,0 +"Hi Vijay, I think we do not use keywords like 'style' or automation 'process' in organizations as we QE's see everything as in every tool as a framework and that is the reason we used the word 'framework'. Also our perspective while presenting the session will be 'Automation' and not developing anything new and we already have implemented it and use it regularly for our Behaviour Driven automation in our team. You can refer the wiki of the same where the keyword 'framework' is used along with BDD many a times: https://en.wikipedia.org/wiki/Behavior-driven_development . Still, If you want we can change or remove the work 'framework' from the title.. +Let me know if you have any more questions apart from this.",0 +git now has bit more content on the talk and would fill up electronic circuit diagrams as well as data analysis results when we finalize our data analysis part of experiment in coming weeks.,0 +"Please fixup the section, so that the talk gets better visibility.",0 +"Please update the section, so that your get better visibility.",0 +You might want to include that under Speaker Info.,0 +I just thought that it would be a good idea to focus on the areas that made MicroPython special. I don't think Micropython does anything special when it comes to tokenizing and parsing (correct me if I am wrong.),0 +"Hi Akshay, + +I have just submitted to the reviewer the presentation abstract, Please check. + +https://docs.google.com/presentation/d/19hr8I7ZgdOT-uQI-7fHB1QQ8tRvSmg_HAY0V0RDLjH8/edit?usp=sharing + +I have also shared my blog in my profile. Otherwise a good speaker :)",0 +Surely I will update more details about this talk. This will give you a clear idea about the topic and also the takeaways.,0 +Added presentation link,0 +You are right. Lexical analyzer/ Lexer and tokenizer are functionally the same as the original Cpython. But the way Damien wrote these blocks are in a different way compared to the typical cpython implementation. ,0 +"OK. Didn't realize that. If you have a point to make, then fine.",0 +Looking forward to this.,0 +"Thanks for your comment. + + This talk is intended for beginners who wants to know how to get + started with Apache Storm for Real time Processing. I do use storm + to process the huge data that we get from multiple sources (Spouts) + +The use case that I mentioned (Sentiment Analysis) is just to motivate the attendees towards it. Processing the data (Tweets) that we get from Twitter will be one use case that I will be mentioning in my talk. + +I will be using Petrel Library so as to make it simple and easy to build and help others to understand better. + +And this will be a basic deployment. + + + + + ",0 +"Dear review team members, + +Thank you for sharing positive review about our outline talk. Appreciate it. + +Wish to share with you the paper and power presentation accompanying the talk have been added in the Content URLs section. We would love to hear your review on our paper. Wish to ask you whether it would be possible for PyCon India papers to get accepted in The Python Papers Journal (http://ojs.pythonpapers.org/index.php/tpp) + +Wish to share with you that we submitted papers in PyCon Singapore conference in 2009 and all of them were accepted and later published in the above mentioned Python Journal. We are submitting our paper to PyCon India 2016. Looking forward to your review. + +Regards, + +Manu Sheel Gupta",0 +"Dear review team members, + +We look forward to your review on the paper and presentation. + +Regards, + +Manu Sheel Gupta",0 +"Hi, Can you provide few code samples that you will be sharing, the description is too less to understand how the talk will be structured. +",0 +Please update the description.,0 +"Hey , thanks for taking interest in my proposal . + +About code samples : My talk targets beginners who might know how to code or might not . Considering this case i have tried to keep the code as minimal as possible but have focused a lot on **LIVE DEMO's** and **EXAMPLES** . + +here is an example of how i will explain topics : ( + +> this is just an example , i have not given full details here . In +> real talk it would be more graphical and interactive + +) + +**XOR** + +1. description + +2. a few properties of XOR + + 0 ⊕ 0=0 1 ⊕ 0=1 + 0 ⊕ 1=1 1 ⊕ 1=0 + +3. Bitwise XOR : python provide ^ operator to perform bitwise XOR on integers. It does this by first expressing those two integers in binary , and then performing XOR on their respective bits. Hence the name, bitwise XOR. + + 73 ⊕ 87 = 0b1001001 ⊕ 0b1010111 + + 1 0 0 1 0 0 1 (left) + = ⊕ ⊕ ⊕ ⊕ ⊕ ⊕ ⊕ + 1 0 1 0 1 1 1 (right) + = 0 0 1 1 1 1 0 + = 0b0011110 + = 30 + +4. One-time pads : explanation of one time pads . + +5. Attacks on One time pads : reuse of same key , crib drabbing . + +6. Live example : + +![Plain text][1] + +![cipher text][2] + +![Reused key and XOR of ciphertext][3] + + + [1]: https://s31.postimg.org/ep0y1mdi3/image.png + [2]: https://s32.postimg.org/etwhsq3xx/image.png + [3]: https://s31.postimg.org/qef1k5ox7/image.png + + +How the talk will be structured : the talk will proceed in same way as i have provided in description + +i will start with XOR ( explain what it is ? , implementation ? , attacks on it ) and will follow the below sequence + + 1. XOR + + 2. One TIme Pad + + 3. Ciphers : block ciphers , stream ciphers + + 4. TLS + + 5. Diffiew-Hellman Key exchange + + 6. Authenticity + + 7. Cryptographic Hash Functions + + 8. Password Storage ( brute force , dictionary attacks , salts , bcrypt + , scrypt ) + + 9. Public Key Cryptography + + 10. Key Generation + + 11. Signing ( RSA , chains of signatures , GPG Key Signing ) + +",0 +"@Kuldeep could you please upload the contents of your presentation? +Along with the links to any prior experience in giving a talk.",0 +"Could you please upload the slides of your talk, have you had any previous experience giving talks etc, can you post links to your experience in public talking if any.",0 +"Hello Akshay, I'm a regular speaker at conferences, few links are available above at Speaker Links. Please have a look !",0 +Seems interesting . I will surely attend this one ,0 +Looking forward to this one ,0 +Your comment was informative . I am excited for your talk ,0 +the contents are now added...the talk will showcase the power and possibilities with python. The code and the logic behind the whole circuit is not difficult to grasp.,0 +"Could you please upload your slides asap? + +The slides don't have to be detailed just a overview will do for now. + +We need you to upload the slides within the next 3 days to be able to consider it for selection.",0 +"@AkshayArora Presentation content is updated, although It will still be evolving till the last week.",0 +"Can you add timing for your talk, something like:: + +introduction: 0-2 minutes +Plyer: examples: 2-10 minutes +Pyjnius examples: 10-15 minutes +... + +This will help you structure your talk and stick to the time allotted to you.",0 +"Have forwarded your question about access to reviewer comments to people who manage the site. However, are you sure that you are logged in, and looking at the correct tab? There should be a Reviews tab to the right of the Comments tab.",0 +Update with Slide link,0 +"[Draft presentation for review][1] + + + [1]: https://github.com/jjaimon/conferences/blob/master/talks/PyCon%20BLR%202016/PyCon2016-iot-platform.pdf",0 +"I just got a mail stating, i need to reply for the reviewer's comment. here is the reply to the following comment. ""Thanks for your submission. Please provide more details, as it is difficult to judge from this what is being proposed beyond a basic introduction to app development with Kivy. Kivy has been around for a while, and many people have probably seen introductory talks. What are you going to demonstrate that is new, and why are you suited to making such a presentation."" + +@ Reviewer01 : +Thank you sir for your humble comment. yes, I will be covering the basics along with the development of small ping pong game. In latter part, we will be developing a small git interface application with which we can update and commit the various changes in the code stored in our github repository. Its Functionality might be limited but enough to carry out basic operations like edit,update & commit. Thank you.",0 +@vickysam sure. Please check the presentation at git address. It will be completed in coming time. We are working on performing experiments right now and then data will be processed using python.,0 +"Kindly, ignore last two comment, i didn't notice there is reviews tab to reply to the reviewers.",0 +I have updated the proposal and added a presentation about what the workshop will be about.,0 +"Hi, + +Can you please provide some concrete examples and problem statements, where you are using this library and the others failed. + + +Also, Curious to know are you one of the main authors for this library because the abstract is very similar to what the library documentation is : https://cryptography.io/en/latest/ ",0 +"No , i am not the main author of cryptography library . I just use that library in my work . About the description being similar to documentation , it is quite same because documentation fit my idea and what i want to present at the talk . + +Most of my criticism of other Python cryptographic packages has already been stated in Pycon 2014 . + +You can see them here : https://lwn.net/Articles/595790/ <- The state of crypto in Python + +Talk Video : http://pyvideo.org/video/2583/the-state-of-crypto-in-python + +Qualification of package contributors/code + +Jarret Raim : Raim is the cloud security product manager for Rackspace + +Paul Kehrer : Kehrer is a software developer for Rackspace working on the Barbican key management service for OpenStack + +Other contributors : https://github.com/alex",0 +Updated Description and Outline for the talk,0 +"Hi Konark, + +Though I have chosen MySQL as an exemplary name but yes the session will be around the various security features available for the database that an admin should deploy to make the instance highly secure. + +--megha",0 +"We are going through deployments this week, could not manage time. + +Please find the presentation link which I created for presenting in a meetup. + +https://docs.google.com/presentation/d/1Ng6PU8N3pr25ywVQcldCbr9x6YbYBzhi5oxA1CkHAfY/edit?usp=sharing",0 +"Hi, This is a nice topic to cover. Topics covered in the slides seem pretty exhaustive, please consider the content to match the talk time. +Can you add Python code snippets for the application and the Python bindings for AWS Lambda, this maybe useful to audience? ",0 +"You could add how Python contributed to building a distributed version control system. +You could also focus on certain aspects of Mercurial which will be compelling for developers to move away from other version control systems. +Also, bring other the architectural advantages in Mercurial that makes it stand out. If organisations want to host their own version control, can Mercurial be better? +",0 +"I was mainly targeting the audience who has less or no knowledge about such things. Either I have to target developers, or I have to start with the basic and then end with all these things which you suggested. I think the later one is better. Thanks for the suggestions, I will surely include them.",0 +"Hi Sankarshan +I will be using raw data and few corpus which come with NLTK. So no specific data-set to be downloaded. +",0 +"Wrote a blog article based on the proposed topic, please see http://www.bravegnu.org/blog/python-byte-code-hacks.html Let me know what you think.",0 +"Talk content: https://gist.github.com/manojpandey/41b90cba1fd62095e247d1b2448ef85b + +Most of it would be more of an interactive session, but I've added my thoughts in the gist above what I'd be discussing. I'm open to more ideas on improving it. Thanks !",0 +"Thank you so much for the comments and details, the content looks good. I would give the following suggestions: +1. Need to structure it better for a 40 minute slot. +2. Need to ensure the examples are showcased using Python libs.",0 +"> Thank you so much for the comments and details, the content looks good. I would give the following suggestions: 1. Need to structure it better for a 40 minute slot. 2. Need to ensure the examples are showcased using Python libs. + +1. about structuring the talk for 40 Minutes . I have been doing practice/ rehearsels with my slides and most of the time the talk comes to an end in 35 min . + +2. about ensuring that examples are showcased using python libs : as I said in my abstract "" This talk is aimed at programmers of any skill level that lack crypto knowledge. "" I will surely show examples / live demo with python libs but some examples are best explained if they are simple . + +P.S. i know the slides looks like those are too much , but trust me don't go on number of slides , they will be turned to next slides quickly . + +P.S. I will add some examples with python libs in my slides :) ",0 +"Around 40 slides including relevant code and version of packages will be uploaded soon. Few slides are uploaded, rest are in progress. ",0 +"Not sure why this is classified under ""Concurrency"". Concurrency is for topics related to Twisted, threading, asyncio, etc. It would be best to categorize it under ""Embedded Python"". Classifying it under the right category will improve the visibility of your talk.",0 +"I have received your comments that more details are needed +and I am working up a draft outline/slide set to convey that.",0 +"Added URL for Draft power point. + +There are lot of improvements in terms of fonts,color,snapshots and examples needs to be done. This is work in progress document.",0 +"The problem I will discuss is somewhat like: +Currently, OpenStack's end user stories for both command-line and application developer-consumers of OpenStack-based clouds is confusing, fractured, and inconsistent. This means that if a non-operator or OpenStack developer attempts to consume more than a single service from a deployed OpenStack system, they face an uphill battle. With a consumer application requiring potentially 22 individual python-* clients to install, each with different APIs and nuances, it becomes increasingly difficult to consume OpenStack clouds. The python-openstacksdk project proposes a new project with a single API namespace (""OpenStack"") that would provide users with a single point of entry and series of supporting functions/methods from which to build applications and tools. As a side effect of this consolidation, it becomes very easy to derive a unified CLI, such as OpenStack client, or specialized pre-service CLI tools. However, it is important that the definition of SDK -- the compilation of the APIs and developer functions -- and CLI tools stay separate as it is easy to conflate the idea of ""clients,"" which is the state we have today. +I hope I answer your question.",0 +"Dear review team members, + +Thank you so much for sharing feedback. Appreciate it. + +We have added 3 case studies and will be uploading the revised ppt by today morning. These case studies have been derived from our product implementations. + +We would be happy to make further additions and revisions if the review team feels the need. + +Thanks again, + +Manu Sheel Gupta",0 +"Dear review team members, + +Thank you so much for sharing feedback. Appreciate it. + +We have added 3 case studies and will be uploading the revised ppt by today morning. These case studies have been derived from our product implementations. + +We would be happy to make further additions and revisions if the review team feels the need. + +Thanks again, + +Manu Sheel Gupta",0 +I think I would want the focus on concurrency (see the changed title). I will not be discussing any embedded stuff.,0 +"Isn't the title misleading. Isn't the workshop just about Docker and Kubernatics? Django happens to be the example you might be taking, but the flow wouldn't change if you replace Django with Rails. Did I miss something? +",0 +"The workshop is NOT just about Docker and Kubernetes. Its more about Scaling Django with Kubernetes. Similar ideas can be applied to Rails. + +The talk is more of a demo to how you would start up with a sample runserver in django, to gunicorn, which later will be monitored using supervisor or any process manager, then eventually leading to container. Now when it comes to docker, how would you address issues of multiple containers, how would you go about securing them, what is the typical architecture for django in a cluster, so on and so forth. ",0 +"Docker is an interesting tools many Python developers would be interested to know about. I've looked at your notes and it looked like it doesn't cover some important topics are required even to move a simple webapp to Docker. Could you please see if you can try to include the following topics: + +- Introduction to volumes +- persisting data in containers +- Example to how to dockerize a simple python CRUD webapp with mysql/postgres database +- More emphasis on docker-compose as that would make it possible to manage multi-container apps easily",0 +"Hi, Plz help me where to upload the presentation.",0 +"Dear review team members, + +We have updated the content URL of the presentation and have added 3 case studies. We have shared slides about them from a product implementation perspective. We wish to share that we would be explaining the issues encountered and lessons learned as we go case by case. + +Looking forward to hearing your feedback. + +Regards, + +Manu Sheel Gupta +",0 +@konark - We have modified our talk basis of inputs provided by you :) let us know what you think of it now. ,0 +@konark - We have modified our talk basis of inputs provided by you :) let us know what you think of it now. ,0 +@konark - We have modified our talk basis of inputs provided by you :) let us know what you think of it now. ,0 +I will upload the presentation asap. I am currently incapable of doing so due to lack of communication facilities in Kashmir valley owing to limits put on Internet in the valley.,0 +Sure. We will include those suggestions in the workshop material. With respect to docker compose we want to keep the workshop neutral to docker compose and Kubernetes. So we have to talk about both. However we will not be able to cover everything in 2 to 3 hours. But participants can go back and follow the same material and finish the workshop. ,0 +"Dear review team members, + +We have added 2 presentations that we would be sharing with the audience before the session - + +1. Case Study - Make an in-app payment system using Python based Rest APIs and Cordova app framework. +2. Steps on how to create a hybrid mobile application. We'll be sharing with the audience the demo on using Python based Rest APIs in hybrid mobile applications that we have implemented for our clients and shared in the content presentation. + +Regards, + +Manu Sheel Gupta",0 +Apache storm ! How exactly can it help us Shaik asifullah,0 +Apache storm ! How exactly can it help us Shaik asifullah,0 +"Thanks Riyaz. Say you want to analyze the twitter data flowing in real time, and to process such a large flow of data, you use Apache Storm. Attend the talk, to know more.",0 +"@Sandeep Congratulations, Your talk got selected, will be eager to see Python in Health Monitoring :) ",0 +@vickysam: Thankyou. My team will be eager to meet yourself and share our experiences too :),0 +Let's catch up @ the Event. :),0 +Looking forward to it. ,0 +"Please add the presentation link in the Content URLs section, so that it is obvious to reviewers",0 +"After considering your comments, I have renamed the talk to be more generic, +created an initial set of slides that I've shared with you, and shifted the focus +to the ""why"" of architectural decisions. In the talk I'll discuss the use of +Pika/RabbitMQ, Pyramid/Zope, ZSQL, SQLAlchemy, RESTful principles, Python +decorators, AngularJs and websockets over the STOMP protocol. + +I will keep the mention of healthcare to a minimum, to make the talk useful +to anyone building a 500-1000 user all-day business-class web application.",0 +https://github.com/suman-d/AWSBoto3,0 +can you compare event driven architecture of python with popular frameworks/applications like nodejs/expressjs.,0 +can you compare event driven architecture of python with popular frameworks/applications like nodejs/expressjs.,0 +can you compare event driven architecture of python with popular frameworks/applications like nodejs/expressjs.,0 +can you compare event driven architecture of python with popular frameworks/applications like nodejs/expressjs.,0 +"Hey Akriti, I think it would be very interesting to compare with other frameworks. But, I am not very familiar with building web services using JS. +That being said, I still have a month's time, so would definitely try to include one or two slides on the comparison.",0 +Is it related to python Twisted framework??,0 +Go gensim :D,0 +Would be a wonderful experience for anyone interested in getting a hands-on experience in machine learning and natural language processing!,0 +"Hello Vijay, + I request you to add the instructions for setting up the project. Thanks!",0 +"Hello Mayank, + Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 +"Hello Vivek and Farhaan, + Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 +"Hello Saptak, Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 +"Hello Sharad, Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 +"Hello Karan, Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 +"Hello Lev, Please add the detailed steps to setup the developer environment for this project. Many Thanks!",0 +"The link is already there but in case you missed it , here you go, + +[How to set up Pagure for development ?][1] + +Happy Hacking! + + + [1]: https://docs.pagure.org/pagure/development.html# + ",0 +@ultimatecoder I will add the steps for creating the developer environment on Github for your kind reference.,0 +"@UltiateCoder. Thanks for the tip. Added env setup to the pre-reqs section. +",0 +"Hi Jaysinh, + + Setup instructions can be found in repo's Readme page. (https://github.com/pythonindia/wye/blob/development/README.md)",0 +"Hi @ultimatecoder, I've made the changes. ",0 +Hello UltimateCoder. I have already mentioned the link which has all the setup information for the project. The link is https://github.com/fossasia/open-event-orga-server/blob/development/README.md. ,0 +"Hi Arif, Please add instructions for creating developer environment and setting up the project.",0 +"Hello Brijraj, Please add information for setting up developer environment. Thanks!",0 +"Shyam is a student of mine. I am very proud for all his capabilities, skills and accomplishments. Good luck to you Shyam. God bless ! + +Kiran Kankipati",0 +looks interesting :),0 +Before you come to workshop please do as mentioned in https://github.com/container-workbook/docker-workshop#9-prerequisite-for-the-workshop,0 +"Is there a Docker container with everything at the exact versions you recommend, for easier installation? +",0 +"Hi Jeff, + +Installing from github develop into a virtualenv on a machine with BLAS is best. + +Regards +Lev",0 +"@rootmonk +Canbyou please share your email id, so that we can send you details. ",0 +"@Rishab + +Can you share your email id, so that we can send you further details. ",0 +"Hi Saurabh, + +My email id is rgoel0112@gmail.com + +Regards, +Rishab",0 +"Will you just dwell on the procedures and implementations of Apache Spark during the talk or the installation too? +",0 +Great session. ,0 +"I'm not able to attend PyCon this year. +I'm gone through your proposal i feel its quite interesting to me. I study and execute the example you gave in the proposal. I have a few questions: + +1) I need few real time examples and real time scenarios. +2) Where can i implement this ast module ? + + ",0 +This looks interesting!,0 +"The slides are distributed under CC-Attribution-ShareAlike. +",0 +"In view of this, it is more likely than not valuable to learn theano before you begin Keras on the grounds that most illustrations have guide calls to theano which are not covered up in APIs. Furthermore, being an analyst, you would love to be able to make new layers to try out new speculations. Theano gives you a chance. +Go to : [best essay writing service][1] + + + [1]: http://www.bestessaywritingservice.co/",1 +"You can easily create, develop, edit, improve and integrate mobile applications for ios and android without almost any coding/programming knowledge! Advanced http://appyresto.com app making service will help your ideas come true.",1 +"Regardless of the difficulty exhibited by my understudies' difference of familiarity and welfare, we figured out how to get past the semester with insignificant soul-pulverizing weariness. [Research Paper Help][1] This was expectant altogether by the large quantity of open source instructive equipment and apparatus nearby in the Python outer space + + + [1]: http://www.ordercollegepapers.com/",1 +"Thanks for the useful information. Frankly speaking, I haven’t heard of Python yet and it’s the first time I hear about this tool. I think that it can be very helpful for economic professionals and those working on finance modeling. It’s important to create an effective economic models that can bring an economy on a higher level. I think today American economy is quite stable but still there are people living through [quick loan][1] tools and who aren’t happy with their financial life. + + + [1]: http://quickandeasyloanservice.com/",1 +"Thanks a lot for telling about this helpful tool! To be honest, I don't know much about stock markets and I'm really new to investments. However, I consider investing my money because I want to be able to provide myself my future and I hope that I will not have a need to use [Installment Credits][1] for that. Thus, it's great that there are technology tools that help to understand stock markets much better, I think I definiletely have to try that! Thanks so much for the information provided! I'm sure it will be helpful to everyone making investments. + + + [1]: http://installmentcredits.com/",1 +"Notwithstanding the trouble displayed by my understudies' distinction of commonality and welfare, we made sense of how to move beyond the semester with immaterial soul-pummeling exhaustion. [My paper writer][1] .This was hopeful inside and out by the vast amount of open source informational hardware and mechanical assembly close-by in the Python space. + + + [1]: http://www.mypaperwriter.co.uk",1 +"Where reqs is the reaction and x is your response. Additionally could catch up with various reactions to a similar question utilizing the arbitrary library, or simply emphasizing through a predefined list. [Custom Essay Help][1]. In the event that you need it to gain from others inputs, you can compose that the PC will ask thus learning, and replicating a comparable response to that of the human utilizing above code. + + + [1]: http://www.essaymania.co.uk/",1 +"There's fairly no should be prepared scripting initial, a couple of the models are an indistinguishable. It’s regularly basically the sentence structure that contrasts, and in the meantime Python's linguistic structure maybe to some degree less hard to be prepared, I question it could require significantly greater investment to settle on up C/C++. The biggest change among C and C++ is the use of classifications. [Help with Essay][1]. There are two or three unique varieties; however that is no doubt the fundamental one. + + + [1]: http://www.shineessay.com/",1 +"Where reqs is the response and x is your reaction. Moreover could get up to speed with different responses to a comparative question using the subjective library, or essentially underscoring through a predefined list. If you require it to pick up from others inputs, [Can Someone Do My Assignment - Customassignment.com][1] you can make that the PC will ask in this way learning, and duplicating a tantamount reaction to that of the human using above code. + + + [1]: http://www.customassignment.com/do-my-assignment.html",1 +"The earth is going away server less where another person deals with running your code naturally at whatever point you need. Later on, I sophisticated the discussion to [Write My Assignment | BuyAssignmentService.com][1] adopts a well ordered strategy that gives the obliged foundation to comprehend the formula bringing about the present type of the discussion. + + + [1]: http://www.buyassignmentservice.com/write-my-assignment-for-me",1 +"Music can't be comprehended by a basic arrangement of equation. The largest part intriguing and testing part is delivering extraordinary music devoid of [Gethomeworkonline.com][1] encroaching the patent. This television shows how profound knowledge was utilized to create music. + + + [1]: http://www.gethomeworkonline.com/",1 +"Most machine learning procedures do play out some example acknowledgment work, in spite of the fact that it's important that most such frameworks don't store singular examples to ""match"" against. [website explainer video to explain][1]. All the more frequently, both machine learning and example acknowledgment frameworks endeavor to lessen the accumulation of preparing cases to a more straightforward shape, for example, if..Then rules or numerical equations. + + + [1]: http://www.demoduck.co.uk/explainer-videos-online/",1 +"The language provides a portion of the implicit answers for break down issues into. Purchase Essay Online ,The style of the dialect impacts how you'll presumably separate an issue. Terms like 'protest arranged' are methods for handling issues, you can do it in any programming language, + +",1 +"Network packet crafting tool how can i use it? Well You can use this Do My Assignment to having a wonderful assistant in writing and even you can get the guidelines too.",1 +"I have been working so long on Java And C++ both languages are similar but now I want to try python to make some New and interesting Software. I have such a New Ideas in the [assignment writing services][1] a Software that helps the student to make assignment but where can I find best resources to learn phyton. + + + [1]: https://www.assignmenttutor.co.uk/",1 +"Developers enjoy the variety plus quality of Python features though, it is not the best programming [buy custom essay][1] language,there are best features like, + Data structures + Classes + Flexible function calling syntax + Iterators + Nested functions + Kitchen-sink-included standard library + Great scientific libraries + Cool open source libraries Numpy, Cython, IPython, MatPlotLib + + + [1]: http://www.urgentessayhelp.co.uk/buy-essay/",1 +"I am expert in Programming and I Worked on my programming languages but and also I work as In [seo company Pakistan][1] now I want to learn phyton I have little bit knowledge of phyton programming but I want to be Expert in this suggest me best-Paid resources for Phyton programming. + + + [1]: http://www.found.com.pk/",1 +"Algorithms (or, at any rate, formal arrangements of standards) have been used to [Write My Custom Essay For Me Cheap][1] create music for quite a long time; the procedures used to plot voice-driving in Western counterpoint, for example, can regularly be reduced to algorithmic determinacy. + + + [1]: http://www.wewriteessay.co.uk/",1 +"The first generally used drone was a full-estimate retooling of the de Havilland DH82B ""Ruler Bee"" biplane, which was fitted out with [Buy coursework writing service][1] a radio and servo-worked controls in the secondary lounge. + + + [1]: http://www.premiumwritersclub.com/Coursework.php",1 +"I have dependably rather delighted in Eric Lippert's blog ""Breathtaking Adventures In Coding"". It's not awesome for remaining fully informed regarding the most recent advances however deals with a considerable measure of the complexities of C#/.NET. [Marketing Essay Writing Services Uk][1] An extraordinary site to sharpen your C# abilities. + + + [1]: https://www.customessayswriter.co.uk/marketing-essay-writing-service.php",1 +"It's intended to be an advantageous editorial manager and debugger. For altering python it's superior to WordPad yet easily proven wrong versus gvim. You can run a script as observe the outcomes in a shell rather than the cmd line or whatever that thing is in windows. [seo.services.land][1]. You can see the stack; set interferes with, check punctuation, and so forth to debug. You can open a module by name (utilizing the python seek way). + + + [1]: http://www.seoservicesland.com/",1 +"Furthermore could make up for lost time with different responses to a comparable question using the discretionary library, or just underscoring through a predefined list if you require it to pick up from others inputs, you can create that the PC will ask along these lines learning, [Can Someone Help For Me in Essay][1] duplicating a tantamount reaction to that of the human using above computer languages + + + [1]: http://www.mbaessayhelp.co.uk",1 +"I have to make a talk bot for an autonomous [Assignment doer uk][1] class . I don't know excessively about Python. I know the nuts and bolts. What I was considering accomplishing for the program is it to have a couple of characteristics: 1. A group of per-modified reactions to specific data sources. + + + [1]: http://www.assignmentdoer.co.uk/",1 +"Scapy is a authoritative interactive packet management tool, packet creator, network scanner, network detection tool, and packet sniffer. Note that Scapy is a very low-level tool [Write my essay uk][1] you cooperate with it using the Python programming language. + + + [1]: https://www.ukwritingexperts.co.uk/essay-writing.php",1 +"The discussion is expected to be a stroll through to empower gathering of people to outline profound learning calculations utilizing Theano and grow profound learning applications utilizing Keras, which is based on top of Theano. [Cipher Fast 8 Jacket Instylejackets][1] + + + [1]: http://www.instylejackets.com/product/fast-furious-8-villain-charlize-theron-jacket",1 +"Furthermore might conjure for lost time with completely different responses to a comparable question mistreatment the discretionary library, or simply underscoring through a predefined list if you need it to select up from others inputs, you'll produce that the laptop can raise on these lines learning, Essays Writing Service UK duplicating an equal reaction thereto of the human mistreatment higher than laptop languages.",1 +"Transfer is a more in attendance day system we're working here, and power parts of our portable site. It's be a truly clever examining process and the transmit [Pay for Essay Writing][1] group is doing marvelous work to complete some last details for a fundamental discharge. + + + [1]: http://www.bestassignmentservice.com/help-me-write-my-essay",1 +"no i don't think because those [essayleaks][1] which i use is good.python is also a good language. + + [1]: http://www.essayleaks.com/",1 +"The style of the idiom impacts however you may presumptively separate a difficulty. [Assignment Help UK][1] Terms like 'protest arranged' square measure ways for handling problems, you'll be able to the couple in any artificial language. + + + [1]: https://www.essayswritingservice.co.uk/assignment-writing.php",1 +"I have tried many CMS for creating website. Python is better web language than PHP. [buy essay UK][1] it is much more suitable for development of website. you can also use Django which can do most of your tasks. + + + [1]: http://www.urgentessayhelp.co.uk/buy-essay/",1 +"This is a great opportunity for everyone who wants to get experience in this direction. Thanks! +Also I looking for person who can help me [write my essay][1] about C++. Can someone help me? + + + [1]: http://www.essaytoday.net/",1 +"I want a 110 lb Latina with pure black hair and absolutely at all no morality. Lacking the ability to speak, and make sandwiches for me and bring me beer on command. She has 36DD breasts and a * a quarter from the bounce [Cick essay][1] could you. She has many fetishes and the need, they all have recorded on video. The only thing that you have is a smile and slutty purple eyeshadow. She has also no gag reflex + + + [1]: http://www.clickessay.com/",1 +"Is it possible to apply it to python? Thanks in advance! +Inquiry for technical [essays][1]. + + + [1]: http://pimion.com",1 +Yes. :),0 +"Python highlights a dynamic type system and programmed memory management and backings different programming ideal models, including [buy an assignment online][1] object-situated, basic, useful programming, and procedural styles. It has a huge and far reaching standard library. + + + [1]: http://www.assignmentninja.co.uk/buy-an-assignment-online",1 +"OpenStack started in 2010 as a joint project of Rackspace Hosting and NASA. Starting at 2016, it is overseen by the [Buy an Essay Online][1] OpenStack Foundation, a non-benefit corporate element built up in September 2012 to advance OpenStack software and its group. + + + [1]: http://www.wewriteessay.co.uk/buy-essay",1 +"Really a good job here done by the team of Pycon.org. I will recommend you to the [dissertation writing service][1]. + + + [1]: http://dissertationwritingservices.org/",1 +"This introduction depends on our participation in creation and conveying a vast level predict, [Master Paper Writers][1] framework which is being utilize live over all staff. + + + [1]: http://www.masterpaperwriters.com/",1 +"A venture is an examination task given to an substitute which for the most fraction require a bigger gauge of effort and more independent work. Read more at [Help with Myassignmentservice.com][1] + + + [1]: http://www.myassignmentservice.com/",1 +"They frame the cause for some astoundingly strong machine knowledge calculations like random timberlands and angle boost machines. Read more at [Assignment Service by Buyassignment.com][1] + + + [1]: http://www.buyassignment.com/",1 +"Ultimately this relies upon for your bot’s requirements and what makes maximum experience given the the time and effort you want to spend developing. Personally, [UK essays][1] I discover AIML to bulky to to construct out a totally useful bot and like RiveScript for simple bots + + + [1]: https://www.ukessaysexperts.co.uk/",1 +"In software engineering, you frequently hear the expression ""toning it down would be ideal"". As a rule, on the off chance that you can take care of an issue in less lines of code, the better. It will likely require you less investment to [marketing essay][1] comprehend a 200-line class than a 500-line class. + + + [1]: https://www.customessayswriter.co.uk/marketing-essay-writing-service.php",1 +"Scapy is a new manipulation tool for computer networks in python. It is one of the best network tool with extend features. Customer feedback and reviews about this tool are positive. Go through the reviews from [essay writing service reviews][1] to get more idea about it. + + + [1]: http://essaywriting-servicereviews.com/",1 +"Your provided resource is very helpful i recently switch for C language to python for [assignment writing service][1] + + + [1]: https://www.britishassignmentwriters.co.uk/",1 +"Commonly, a prescribed framework looks at a client profile to some reference qualities, and tries to foresee the ""rating"" that a client would provide for a thing they had not yet considered. [college assignment help][1]. These attributes might be from the data thing (the substance based approach) or the client's social condition (the community oriented separating approach). + + + [1]: http://www.australianessay.com/assignment-services-with-quality-writing",1 +"Generally speaking, the speed of your site greaterly affects client fulfillment than additional ""extravagant accessories"". It doesn't make a difference how extraordinary a site looks: [Essay writing service uk | Ukwritingexperts.co.uk][1] on the off chance that it stacks too gradually, clients will click away. + + + [1]: https://www.ukwritingexperts.co.uk",1 +"game programming is really getting fame among the developers and this will be the next level technology. IT students should concentrate on their studies as this might help them in learning more about game development and programming. Also they can look for [assignment writing online][1] in order to get their IT assignments done with unique contents. + + + [1]: https://www.britishassignmentshelp.co.uk",1 +"Bidirectional recurring neural nets explain promising outcome, as they aim to [write me an essay][1] imprison both contextual dependence between words through repetition and position-invariant semantics through complication. + + + [1]: http://www.needpaperhelp.com/write-my-college-essay",1 +"This place just gives instance of some areas that can source problems, and may rouse some thought when deceitful your app. [Essay service from theessayhelp.co.uk][1] + + + [1]: http://www.theessayhelp.co.uk",1 +"In deep knowledge systems, this is not the case as an alternative algorithm can [pay someone to write my essay][1] mechanically teach feature hierarchies, which symbolize objects in growing levels of concept. + + + [1]: http://www.midnightessays.com/help-me-write-essay",1 +"It has an extensive convention in neural networks explore, as the dataset is relatively small but still very difficult to [explainer videos][1] organize suitably. + + + [1]: http://www.seekclip.com/explainer-animated-videos/",1 +"There is always a way-out to incur less costs for something really valuable. Even [finding a qualified essay writer][1] might be much cheaper if you follow the instructions on this article. + + + [1]: http://%20http://www.cedargroveschool.com/finding-a-qualified-essay-writer-tips-for-beginners/",1 +"There is always a way-out to incur less costs for something really valuable. Even [finding a qualified essay writer][1] might be much cheaper if you follow the instructions on this article. + + + [1]: http://%20http://www.cedargroveschool.com/finding-a-qualified-essay-writer-tips-for-beginners/",1 +"Usually when developers are working on the Python so they must be enjoyed it during the projects and also learn the many skills because development is the very interesting field. Well, this post is very informative thanks, author you share a very nice post and I am a professional expert from best [assignment writing service][1]. We provide the high-quality writing services and also work on the development, softwares, marketing, and designing. If someone needs any types of assistance so they can take help with us. + + + [1]: http://www.assignmentace.co.uk/",1 +"I'm guessing you have not programmed much before. You might want to get someone to help you download and install Python and show you how to use the interpretor and how to save and run a simple program. If you can get someone to help you with [Ez Assignment Writing Help][1] that, you'll be up and running in an hour. Then it might take you a month before you can write programs that really do something interesting. Python is not a *fast* language so it is not good for things like graphics intensive games. But it is easy and fast to write most programs. + + + [1]: http://www.ezassignmenthelp.co.uk",1 +"On the off chance that you have a modest bunch of models and few points, then you could run the manual assessments in a sensible measure of time. Shading swing words in your particular area is a critical one to get right. [Dissertation editing online][1] In different circumstances manual reviews are not achievable. + + + [1]: http://www.dissertationtime.co.uk/editing-service",1 +"Machine learning via get better Gensim lesson is good but not for everyone as a writer of [Dissertation Service UK][1] I realize we need universities which have all kind of classes. + + + [1]: http://www.DissertationHouse.co.uk/",1 +"I need more description on workshop collaboration software I belongs to [Custom Essay Writing Company][1] and it is my first time that I am writing on programming language that’s why I am asking. + + + [1]: http://www.AOneEssays.net/",1 +"One surely understood issue with Dicker based forms is the compute of dialect particular circumstances requisite by your method on top of the official dialect picture. [Write My Essay][1] We've developed this by making a strong-minded information quantity for those conditions, and share that volume from work to fabricate. + + + [1]: http://www.helpinessays.com/someone-write-my-essay.html",1 +Please drop email to contact [at] pythonexpress [dot] [in] we can answer all queries.,0 +"Organize information bundles contain different data incorporate information, source address, goal address, variant, length, convention, and [custom assignment help][1] couple of different things relying upon the convention. + + + [1]: http://www.assignmentbay.co.uk/assignment-writing-service",1 +"Actually the Chatter bot the machine learning based dialogue engine which is build in platform Python is usually interesting and makes possible to generate responses based on some known conversations. So I hope developers enjoy this kind of work since I used to enjoy each bit of my development work in [buy essays online][1] and here it is well expressed too + + + [1]: http://www.buy-custom-essays-online.com/",1 +"I am a professional writer i need to study the python and the other computer language for the academic research paper work for my new client. Currently i am working with the [best essay writing service][1] . This is one among the top most online writing firm with well qualified writers. + + + [1]: http://essaywritersworld.com/",1 +"You should be comfortable with java before learning Hadoop technology. Hadoop having two parts- development plus admin. hadoop development is based on java. admin require good knowledge od database. map/reduce, HDFS, Hive, Pig, Mahout, Sqoop are main components of Hadoop. [Do Write My Essay][1] Data analyst require good to have in Pl/Sql, database, application domain specific knowledge, dataanalysis framework like hadoop etc. + + + [1]: http://www.writecheapessay.com",1 +"I am working with [dissertation writing services][1], I know the importance of python and other languages. I am interested in computer languages but I need to study more about python because it has good chance on this developing world. + + + [1]: http://best-uk-dissertation.com/",1 +"Catalysts communicated by exceptionally salt-tolerant living beings demonstrate numerous changes contrasted and salt-influenced partners including one-sided amino corrosive and lower α-helix content, bring down dissolvable openness and negative surface charge. Here, we demonstrate that halotolerance can be produced in a chemical exclusively by altering surface deposits. Normal plan of carbonic anhydrase II is attempted in three phases supplanting 18 buildups altogether, gem structures affirm changes are kept to surface deposits. +Ref: [cheap essay writing service][1] + + + [1]: https://essayservices.org",1 +"The article describe about the python applications.python applications can be written to be managed by Helix.this application used to convert the high volume of program to user understand format.this application is very much useful for all.thanks a lot for sharing such an important informations. i really like to read this article. [hearing aid service center Pathanamthitta][1] + + + [1]: http://shabdhaclinic.com/hearing-aid-&-speech-therapy",1 +"Thanks for sharing this informations.this is the new informations for me.the word2vect used to calculate the document similarity.the commonly used words are chosen by using the word2vect. this method used to identify easily to the documents.thanks a lot for sharing such an important article.its very very useful for me. [aluminium foil containers][1] + + + [1]: http://supremepackaginguae.com/aluminium-Container-suppliers.html",1 +"Thanku so much for sharing this article.here describe about the projects useful for me.as a college professor.this include the software and hardware based projects are doing to my students.this article is helpful for knowing more informations.i like to share this informations to my students.thanks a lot for sharing this post. [job oriented diploma courses][1] + + + [1]: http://collegesniper.com/course/diploma",1 +"NSE's website used to download the data and document directly.this is the new informations for me.i like to share this information to others.i am very happy to read this article.i hope you more useful articles.thanks a lot for sharing this article. [Plumbing Services Dubai][1] + + + [1]: https://daddyservices.com/Dubai/Plumbing-Services",1 +"This is the new informations for me. the python hacks related informations included here.as a software developer.this include informations are very much useful for me.this article help me to understand some new informations.i am erp developer, for more informations about include the website [ERP Development Company Dubai][1] + + + [1]: http://adeptsol.com/",1 +"Web development structure is better for improvement. Rails 4 presents various client confronting changes, and the digital book has been refreshed to match all the most recent changes and new accepted procedures in Rails as elaborated at an [Essay Writing Service][1] . While Django as an open source extend with a name (On account of a specific late motion picture that sounds cool) appears to be intriguing and is intended for information driven activities. + + + [1]: http://www.writingbunch.co.uk/",1 +"The heart of the expectation frameworks are the machine learning calculations. Python has solid support for machine learning calculations. The [www.researchpaperlabs.com][1] key bundle we will utilize is the scikit-learn bundle. This bundle is intense and empowers designers with insignificant machine learning knowledge to grow effective characterization frameworks. + + + [1]: http://www.researchpaperlabs.com/",0 +"I want to be able to open a website from python, I've tried every tutorial online and all the python sites with their ""urlib"" thing, but I can't seem to get any of the codes to work. +all I want to do is have a function where I type a ur like [Essay Writing Service][1] +l as an argument into the function and the program will open up IE, firefox chrome or w/e and display that website. + + + [1]: http://www.essaygala.com/",1 +"This introduction is about how to construct an adaptable expectation framework for close ongoing use utilizing Python. A client will enter his/her necessities utilizing Natural dialect. The framework will do a characteristic dialect preparing of the information content. Machine learning models will be utilized to foresee the required fields. This arrangement can be utilized for various utilize cases including specialist portions for Incident work seat , Recommendation administrations , and so forth. [Help with Research Paper][1] + + + [1]: http://www.researchpapergurus.com/",1 +"The expected takeaway from this discussion would be a greatly improved comprehension of what occurs in the background when a record is asked for from the plate and how one can think past customary methods for putting away information. [Do My Dissertation for Me][1] + + + [1]: http://www.donedissertations.co.uk/do-my-dissertation",1 +"debugger utilizes this way to deal with render traceback. Engineer can backpedal to any point and examine the variable. Great point. [Admission Essay Writing][1] + + + [1]: http://www.essaytiger.co.uk/admission-essay-writing",1 +"Framework is constructed utilizing mix of Natural Language Processing systems and machine learning methods with Python as the overwhelming dialect. [Professional Essay Writing Service][1] Takeaways from the discussion will incorporate what to search for in content grouping and how to assemble a real content classifier in Python. + + + [1]: http://www.groovyessays.com/",1 +"One thing we’ve struggled about while setting up a home office is space insufficiency. This becomes extreme if you want to bring in a computer desk to the same. L Shaped Computer desk",1 +"Well, there should be some entertainment in the school which catch the attention of students to school. If your class is so boring then a student will get fed up and will not concentrate in the class. The entertainment can only catch the attention of students to the school and one more thing is, [UK essay help][1] interest can only be developed in students by the teacher. If the teacher is frank with the students and share lots of different ideas and give funny interesting examples then the student start taking the interest. Discipline is also very necessary. + + + [1]: http://www.essaybliss.co.uk/",1 +"The dialect is Python. Pycharm is an IDE used to create Python code. There are others. + +More often than not ""word"" in an issue implies anything non-clear, [online assignment help uk][1] isolated by spaces from whatever else in the string. In Python, you can change over a string to a rundown of words basically: + + + [1]: http://www.assignmentmoz.co.uk/",1 +"The dialect is Python. Pycharm is an IDE used to create Python code. There are others. + +More often than not ""word"" in an issue implies anything non-clear, [online assignment help uk][1] isolated by spaces from whatever else in the string. In Python, you can change over a string to a rundown of words basically: + + + [1]: http://www.assignmentmoz.co.uk/",1 +"Actually, Python is the coding language and it is difficult to understand rather than to HTME, but we can learn this language with the help of a different kind of programming languages. And this kind of languages is taught in bachelor program so that learners can easily understand this language easily. Now this time have the opportunity to learn on the web where also to continue academic education just [enroll for non fake degrees - gain non fake college degrees][1] in any faculty easily. + + + [1]: http://www.degreeforlifeexperience.com/non-fake/",1 +"Eventually, this depends upon your bot’s necessities and what creates supreme practice given the time and exertion you want to devote developing. For myself, dissertation help services determine AIML to bulky to concept out the completely valuable bot.",1 +"Gensim is a machine learning bundle for normal dialect understanding. For instance, it can reveal to you the primary points of a site page. It has word2vec and doc2vec machine learning calculations. + +He is a specialist in common dialect preparing, is a Python and Java engineer. Animated Videos For Business Lev has broad experience working with money related foundations and is RaRe Technologies' chief of open source groups including gensim, an open source machine learning toolbox for understanding human dialect.",1 +"which seems to be more easy when it comes to operating python or C language? [Essay writing help][1] + + + [1]: https://www.papermatic.co.uk",1 +"Subsequent to acquainting Python with my classes in 2011, a non-registering partner requesting that I keep in touch with a few arranges that would empower her to acquaint Python with her classes. [Ghost Rider Costume Jacket][1] + + + [1]: http://www.celebsfit.com/ghost-rider-agents-of-shield-jacket",1 +"What you are asking approximately is public lending rights. Plr is a government funded scheme that can pay Assignment help UK authors around five½ pence on every occasion their books are loaned out. They do not depend each single loan from every library in the usa, of direction; the scheme is based totally on samples from selected public libraries. A distinct set of libraries is chosen every yr, and authors aren't advised in advance which libraries they're, to prevent manipulation of the service! Fee is made each february.",1 +"There is dependably an exit plan to bring about less expenses for something truly profitable. Notwithstanding finding a prestige chauffeurs may be significantly less expensive on the off chance that you take after the directions on this article.",1 +"There is always a way-out to incur less costs for something really valuable. Even finding a Download Youtube Videos online might be much cheaper if you follow the instructions on this article.",1 +"Great Information,it has lot for stuff Do MY Programming Assignment For Me which is informative.I will share the post with my friends.",1 +"This is really great work. Thank you for R Assignment Help sharing such a useful information here in the blog.",1 +"I loved the way you discuss the topic Solidworks Assignment Help great work thanks for the share Your informative post.",1 +"Science Channel’s are giving a complete knowledge to its viewers Make My SPSS Homework about every thing students write done dissertation on this subjects and show its importance.",1 +"Those who come to read your article Digital Marketing Course In Pakistan will find lots of helpful and informative tips",1 +"如果你想要像我这样的最好的内容,导师写作 只需要快速访问这个网站,因为它提供功能内容,谢谢",1 +"This is a very interesting post thanks for sharing the post and I hope every people learn many skills in this post. Well, I am a professional expert and I provide the [research paper writing services][1] for the students because it is the very complicated task for the students and their have no writing about the research paper. + + + [1]: http://essaywriting.com.pk/research-paper-writing/",1 +"John arnold is an academic writer of the Dissertation-Guidance.Can Someone Do My Exam Who writes quality academic papers for students to help them in accomplishing their goals.",1 +"The leading assignment help UK firm offers state Write My Medical Thesis of the art services to its clients with a promise of delivering all the required work well within the deadline.",1 +"Great Information, Help With Audit Assignment it has lot for stuff which is informative.I will share the post with my friends.",1 +"John arnold is an academic writer of the Statistics Assignment Help Dissertation-Guidance. Who writes quality academic papers for students to help them in accomplishing their goals.",1 +"Yes, learning English is a really important thing for everyone who wants to keep up with the times. That is why writing skills are so important too. Click the link [https://thrivingwriter.com/proofreading-service/][1] to know more about the modern specification of the text and learn how to keep them. Professional writers here will help you to update your text to the perfect level. Proofreading in the shortest time and editing is their hobby which they know better than anything. + + + [1]: https://thrivingwriter.com/proofreading-service/",1 +"Big data analytics inspect large quantity of data to expose hidden pattern, association and other imminent. [Buy Assignment][1] for college and university students, With today’s knowledge, it’s possible to investigate your data and get answer from it almost straight away – an effort that’s slower and less well-organized with more customary business intelligence solution. + + + [1]: http://www.readyassignment.co.uk/buy-assignment/",1 +"It's September as of now! PyCon India is not over 15 days away...24-25 September 2016. Not to overlook the workshop on 23 September 2016. [url=""http://www.idealjackets.com/product-category/dark-matter-series-leather-jacket-and-vest""]Roger Cross Coat[/url]",1 +"It's September as of now! PyCon India is not over 15 days away...24-25 September 2016. Not to overlook the workshop on 23 September 2016. [Roger Cross Coat][1] + + + [1]: http://www.idealjackets.com/product-category/dark-matter-series-leather-jacket-and-vest",1 +"Viruses had been the first laptop insects, initially designed with the [Essay Writers UK][1] aid of programmers to test the integrity of the software program code for sturdiness and compatibility. The internet modified matters a piece, the malicious hackers used this new medium inject their codes into regarded software flaws to contaminate heaps. Why? Due to the fact they might. Anti virus software program became created to delete these malicious virus codes . Subsequent got here the worm, a exclusive form of code to the virus, the av software program has a more difficult time choosing these out. Subsequent came the malicious program, unique once more from both the virus and bug as it assaults the av software in addition to the operating device, exploiting weaknesses inside. Trojans regularly create copies of themselves in other places and re-infect a just wiped clean computer on restarting. Av turned into no longer designed to cope with this sort of threat and the arrival of anti spyware to deal specifically with it became a should. + + + [1]: http://www.essayace.co.uk/",1 +"If you have interest towards machine language it will be very easy to study it. Hope this Gensim package will be a best tutorial guide for the begineers. There are so many other packages, get more about it from [Admission essay writing services][1] + + + [1]: http://essaysmaster.com/admission-essay-writing",1 +"Can I have a separate link to the Introduction to OpenCV? I'm a beginner in Sentiment Analysis and my assignment deadline is coming soon. I chose a distance learning course at Arizona State University from this list of top unis for distance learning https://essaydune.com/top-10-us-universities-for-getting-distance-education/ and can't pass the exams and all tasks. Please, help.",1 +"Can I have a separate link to the Introduction to OpenCV? I'm a beginner in Sentiment Analysis and my assignment deadline is coming soon. I chose a distance learning course at Arizona State University from this list of top unis for distance learning [https://essaydune.com/top-10-us-universities-for-getting-distance-education/][1] and can't pass the exams and all tasks. Please, help. + + + [1]: https://essaydune.com/top-10-us-universities-for-getting-distance-education/",1 +"Scapy is an effective intelligent parcel control program. It can produce or unravel bundles of a wide number of conventions, [British Essay Writing][1] send them on the wire, catch them, coordinate demands and answers, and a great deal more. + + + [1]: http://www.britishessaywriting.co.uk",1 +"I want to work with advancements that make designers lives simple, once in a while another item turns out that makes the procedures more less demanding, my employment is to convey that learning to devs and make our lives less difficult. Ashton from [http://payforessays.org][1] . + + + [1]: http://payforessays.org",1 +"As per my observation, the event has been ended. I am also an [android app developer at Branex][1]. could you please share the presentation of this event publicly? This will definably provide me a new professional experience for developing the Android mobile apps via the Kivy, a Cross-platform Python Framework for rapid app development instead of Java. + +Cheer, + +Robert Downey + + + [1]: https://branex.com/app-solutions/",1 +"In comparison to Java, Python projects Python projects are commonly 3-5 times shorter than proportionate Java programs. This distinction can be ascribed to Python's inherent abnormal state information sorts and its dynamic writing. For instance, a Python software engineer squanders no time pronouncing the sorts of contentions or factors, and Python's capable polymorphic rundown and word reference sorts, for which rich syntactic support is incorporated straight with the dialect, discover an utilization in practically every Python program. In view of the run-time writing, Python's run time must work harder than Java's. For instance, while assessing the expression a+b, it should first investigate the articles an and b to discover their sort, which is not known at arrange time. It then conjures the proper expansion operation, which might be an over-burden client characterized strategy. Java, then again, can play out a proficient number or skimming point expansion, however requires variable presentations for an and b, and does not permit over-burdening of the + administrator for examples of client characterized classes. I like Python language and completed so many [term papers][1] on it at university. + + + [1]: http://thetermpapers.net/",1 +"What are the requirements for Basic Python Programming Skills? I mean are these soft skills too? I need to investigate the topic and [write my college essay][1] on Natural Language Processing for Programming class at Ulster University. + + + [1]: http://essayforcollege.org/write-my-college-essay.html",1 +"Being a developer you need to always be upgraded about things python generator is one of the new addition for software engineers. With support and [Essay Help UK][1] by expert’s software engineer like Anand you can grasp thing easily and start working on the projects. + + + [1]: http://www.writing-victors.co.uk/essay-services/",1 +"Learning is a basic need of everyone, because without an education or lack of education, we cannot get a successful career, so that every individual is looking for getting an education for making their career successful and in these there are such a great options for getting an education, and even high school drop outs can also get their education done. As internet has made it quite easier for getting an assistance regarding any requirement, so that many students are getting their [dissertation help][1] through online resources for their academic writing programs and it is such a great way to get an assistance through using online technologies and it is the best way and it saves time and effort and many individuals are making the most of this online technology. Thanks for sharing such a useful information. I am looking forward to get more useful ways to get an assistance. + + + [1]: http://www.realdissertationhelp.co.uk/",1 +"this technology is great and It Will be very helpful for [cheap seo service][1] and It makes our work easier I was searching for the Best article about this technology and finally I found this article. + + + [1]: http://www.found.com.pk/",1 +"As with the practice of Reasoning Abstractly and Quantitatively, which was the focus of Part 1 of this series, the practice we will focus on in Part 2 also asks students to reason with mathematics. As I am teaching a class and working to integrate the mathematical practices, I think of these two practices together, [instant Essay writing service][1]. even though there are distinct differences. In this blog, we will look specifically at how to get students to Construct Viable Arguments and Critique the Reasoning of Others. I am sure that after you look at these examples, you will see how reasoning is used in two well-defined ways. + + + [1]: http://www.proessay.co.uk/",1 +"The functions and classes in the humanfriendly package can be used to make text interfaces more user friendly. Some example features: + +Parsing and formatting numbers, file sizes, pathnames and timespans in simple, human friendly formats. +Easy to use timers for long running operations, with human friendly formatting of the resulting timespans. +Prompting the user to select a choice from a list of options by typing the option’s number or a unique substring of the option. +Terminal interaction including text styling (ANSI escape sequences), user friendly rendering of usage messages and querying the terminal for its size. [Dissertation Services UK][1] + + + [1]: http://www.dissertationmill.co.uk",1 +"Well, if to speak of designing big programs, then here is my good advice for you. +Try not to outline a framework to be object oriented. Simply plan it consistently that is as decoupled as could be allowed. Will need to test your code and the more coupled it is, the harder that will be to do. +You simply begin composing it and you refactor a great deal. You begin perplexed of things like rundown perception and before long need to learn guide, channel, and lessen. On my open source venture which is an IO to a beast of a building program, I've completely rejected the input reader 4 times while leaving the information essentially the same. I've revised the yield the output one two times (taking a shot at a third). You do this since some new component is difficult to get working steadily due to all your code hacks, so you will re-write it with ideally a couple of lessons taught. Python is a real great [essay writer][1] programming language. + + + [1]: http://www.writemyessay24h.net/",1 +"Great reading so far! I didn't know much better about Workshop collaboration software before today. By the way, if you need writing on the same topic you can visit https://hitthegrade.com/ this anytime and order. Thank you so much and keep posting things like this.",1 +"Great reading so far! I didn't know much better about Workshop collaboration software before today. By the way, if you need writing on the same topic you can visit https://hitthegrade.com/ this anytime and order. Thank you so much and keep posting things like this.",1 +"Sorry to learn about your missing snake, this is dependably a troublesome pill to swallow! I would exhort hunting down your snake by tidying up your room. It is more probable that your snake is still in your room. Yes, it can for beyond any doubt fit under the entryway in the event that it is a child, yet its not likely that it would travel that far if there are sufficient [Online Dissertation Help UK][1] different spots for it to cover up. Your snake will be more dynamic around evening time, and may move so that is the point at which I'd do the greater part of the seeking. + + + [1]: http://www.dissertationhub.co.uk",1 +"Thank you for this , I'm glad I found this website on google. +[assignment writing service][1]  + + + [1]: http://myassignmenthelp.co.uk/assignment-writing-service.html",1 +"In the event that you've perused first experience with Python, you definitely realize that it's a standout amongst the most generally utilized programming dialects today, celebrated for its productivity and code meaningfulness [Do my assignment][1] As a programming dialect for information science, Python speaks to a trade off between R, which is intensely centered around information investigation and perception, and Java, which shapes the foundation of some huge scale applications. + + + [1]: http://www.assignmentcamp.co.uk/someone-write-my-assignment",1 +"This discussion will present us with various proposition of [assignment writer uk][1]. It's be a really sharp looking at process and the transmit gathering is doing wonderful work. + + + [1]: https://www.ukassignmentshelp.co.uk/",1 +"We always should be supportive and look to become a various think we need to become a supportive one in good deeds of life Learn Machine [Dissertation Writing Service UK][1] + + + [1]: http://www.dissertationcorp.co.uk/",1 +"This is really unique but we always should become a various think to do in a perfect way of life in order to maintain a useful think we need [Write My Dissertation][1] + + + [1]: http://www.thedissertationhouse.co.uk/",1 +"Sometime we always need to become a various think to do something better in our life but we should keep the good changes in our common life to become [Professional research paper][1] + + + [1]: http://www.proresearchpapers.com/",1 +"Designers appreciate the assortment in addition to nature of Python elements however, it is not the best programming purchase [essays tigers][1] language,there are best components like, Data structures Classes Flexible capacity calling grammar Iterators Nested capacities Kitchen-sink-included standard library Great logical libraries Cool open source libraries Numpy, Cython, IPython, MatPlotLib + + + [1]: http://www.essaystigers.co.uk",1 +"Composing a little C/C++ wrapper around Python, concealing the way that the application is really composed in Python (to make a custom order line interface; for dispersion purposes; or just to make it somewhat harder to figure out the application). + +[click here][1] + + + [1]: http://laustan.com/",1 +"I myself am new to web dev. I also just started using git, although it's fun, the learning curve is quite steep for me. +But I would gladly want to contribute in an open-source project :) and for your essay needs, be sure to visit bestwritingadvisor !",1 +"Hey! Deep learning is a cool thing when it comes to effective learning. But when speaking of the deep learning, it must include more problems and difficulties. Simple students face packs of college papers, tests, and other assignments... Fortunately, there are lots of resources that facilitate academic process. I have already found out about websites for students as I can't cope with all essays and other college papers independently and British Essay Writer can help me with it. I know that some students are cautious about essay writers online but believe me - it's a cool opportunity to receive professional essay, get high grades and avoid stresses!",1 +"The term static analysis is conflated, yet here we utilize it to mean an accumulation of calculations and strategies used to break down source code with a specific end goal to consequently discover bugs. The thought is comparable in soul to compiler notices, Writing Help By Assignment Empire yet to make that thought a stride further and discover bugs that are customarily discovered utilizing run-time debugging techniques such as testing.",1 +"You can compose a Telegram visit bot in any dialect you need. A portion of the fundamental alternatives separated from Python would be Java, PHP, or Ruby [write my research paper for me][1] On the off chance that you are more comfortable with an alternate abnormal state programming dialect, then you may want to utilize that rather, yet Python is a decent decision for a few reasons. + + + [1]: http://www.rushpapers.co.uk/",1 +"It isn't a smart thought to no end to come up when the client dispatches stuff.exe. Consider the possibility that it requires a long investment. [promotional video][1]. Perhaps your server is running moderate. Or, then again the client is on dial-up (those clients still exist). For sure if the whole web is down Chances are, your client will think stuff didn't run, so they will attempt to run it once more. What's more, once more. And after that they will get confounded and irritated. + + + [1]: http://www.vidwonders.com/",1 +"We assemble information from various online networking locales and clarify utilizing three annotators. At that point this information is encouraged into the profound learning model which is made by convolutional neural system and takes word2vec word embeddings as information. [Custom Dissertation Writing Service][1]  The model can group the information into two classifications with great measurements. + + + [1]: http://www.dissertationshouse.co.uk/",1 +"i really like this article please keep it up. cccam server",1 +"The discussion gives a fundamental prologue to Bokeh Python. A concise depiction to bokeh is given in the slides. The slides contains prologue to unique elements like Bokeh Server and Bokeh Flask. [Coursework Writing Service][1] This improves the dynamic interactability of Bokeh. Alongwith the slides I have arranged two ipython scratch pad. One has essential plotting in Bokeh , with information extricated from a csv document utilizing Pandas. Another clarifies an extremely helpful element of Bokeh known as Interactors + + + [1]: http://www.essaycorp.co.uk/coursework-writing-service/",1 +"coala gives a typical multiplatform interface to linting and settling all your code, paying little heed to the programming dialect you utilize. Its advantageous UI disposes of a considerable measure of regular undertakings for the designer. [Assignment Writing-Groovyessays][1] coala likewise encourages individuals entering the universe of open source by giving them important input on coding measures and organizing. Along these lines, more or less coala is a valuable reflection for static code examination that is pertinent to any content based dialect. + + + [1]: http://www.groovyessays.co.uk/assignment-writing-service/",1 +"I'm speculating you have not customized much some time recently. You might need to motivate somebody to enable you to download and introduce Python and demonstrate to you industry standards to utilize the translator and how to spare and run a straightforward program. In the event that you can motivate somebody to help you with [EssayChamp][1] that, you'll be up and running in 60 minutes. At that point it may take you a month prior to you can compose programs that truly accomplish something fascinating. Python is not a quick dialect so it is bad for things like illustrations concentrated amusements. Be that as it may, it is simple and quick to compose generally programs. + + + [1]: http://www.essaychamp.co.uk/",1 +"This is an incredibly instructive article of On time paper writing. I in like way concur with your post title and your really well illustrate your perspective. I am to an extraordinary degree cheerful to see this post. A commitment of gratefulness is all together for an offer with us. Keep it up and share the all the more most related post.",1 +"The writer has formed a unimaginable article of Custom Assignment. You made you show up and no exchange about. Without a doubt this undeniable truth that you can not battle with the fact of the matter is not serious, everything has its remarkable case. A devotion of appreciation is all together for this data.",1 +"I basically need to offer critical an obligation of appreciation is all together for this brilliant post of Reliable Essay Writing, quality article and will look a more unmistakable measure of your assorted spellbinding substance. Magnificent sharing!",1 +"there is the thing I think you should have to in Realtime microservices and Make them better are that Will be popular in people When the will this Kind of new technology [PPC service in Pakistan][1] with so many benefits. + + + [1]: http://www.found.com.pk/services/pay-per-click-management/",1 +"Big data or large data is something that cannot be done on small scale. It always was done on large scale.PySpark is an API used for a python-A programming language. To analysis big data we use apache-spark which is an open source and it is mainly used for big data. If you have data of your assignments and wanted to provide [assignment help][1] to students through big data then you can use apache-spark. + + + [1]: https://www.assignmenttutor.co.uk",1 +"All things considered, we as a whole revere the individuals who acknowledges the significance of shielding their oakley sunglasses cheap eyes from UV beams, however for this situation",1 +"Wayfarer ray ban sunglasses was composed by the American optical originator Raymond Stegeman from Ray-Ban and that has now turned out to be one of the style image of the entire world. This style of shades too has experienced an unpleasant time amid cheap ray bans the previous 60 years where a ton of different styles have gone ahead load up.",1 +"Feline eye ray ban sunglasses for Women then again have an upsweep at the external edges of the arms and it joins the casing front. This style of shades was promoted by superstars like Audrey Hepburn, Marilyn Monroe, Elizabeth Taylor and ray ban outlet Madonna since 1950's. It was worn by the most elegant women around the local area and its prominence brought considerably more up in the times of 70's",1 +"On the off Rolex watches chance that you have an adoration for the better things in life, you will love Rolex watches. On the off chance that you cherish the things that are known as materialistic trifles and have essentially the best quality around, you will love this marked timepiece.Is it accurate to say that you are searching for the ideal present for the extraordinary men throughout your life or notwithstanding for yourself? Furthermore, you can even buy knockoff looks for both men and ladies that are being sold for a small amount of the general. Rolex is one of the prestigious Swiss watches. Rolex and different prestigious uk replica watches marked timepieces go as one. watches were made in 1905 and have turns into a portion of the finest watches accessible that one can discover.",1 +"Tissot dependably remains replique montre de luxe consistent with its exemplary engineering. This T035.446.16.051.00 timepiece mirrors the tasteful look of customary workmanship through its lovely plan. The 39mm dark dial takes you back ever. The 28mm silver dial has dew-drops that infuse another and new thought in the wearers. The look of the timepiece is to such an extent that it moves the ladies to accomplish their fantasies. The a la mode and intense look of replique montre omega the watch is without a doubt hard to overlook. Added to this, the dark cowhide strap takes care of the demand of the age. Offering a hoisted style a reprieve, Tissot engineers this look for the individuals who welcome the normal magnificence. The brilliance of watchmaking is unmistakable through its bleeding edge innovation and strong files. The dial is encompassed by a silver montre rolex bezel that runs splendidly with the dark cowhide strap. With this http://www.repliquemontre1735.com watch, men's identity will get a nostalgic touch.",1 +"For any winter garments, Moncler, jazzy appearance by moncler utilizing light notwithstanding warm substance. It will be the most recent acclaimed, exceptional outline and very in vogue. When you got the thought, you can get that it truly is worth to possess. Gone ahead and work with us. You generally found what you might want. Red sewed Vest through Moncler Clothes with not one but rather two front side affixed wallets. The Vest offers focus section packed studs affixing proceeding into the high back of the shirt. Winter's Men and ladies coats gathering never showed up back notwithstanding moncler sale dependably take after the development in the main successive pies the young's tendency. Moncler by utilizing immaculate plan indicates basically the most one of a kind style and polished spruce up these months. Moncler jacken stylish to pick up each of the lights in the winter, Moncler at http://www.cheapmonclersale.co.uk materials is probably the critical matter texture, a strong Moncler is in all probability the sun's natural brilliance.",1 +"This is a great inspiring article.I am pretty much pleased with your good work.You put really very helpful information... Free music downloads for android",1 +"I read a article under the same title some time ago, but this articles quality is much, much better. How you do this.. voyance amour",1 +"I read a article under the same title some time ago, but this articles quality is much, much better. How you do this.. voyance amour",1 +"I have read your blog it is very helpful for me. I want to say thanks to you. I have bookmark your site for future updates. Le Quest Qingjian Realty 516 Units",1 +"دانلود قسمت 1 اول فصل دوم سریال شهرزاد, دانلود رایگان فصل اول و دوم سریال شهرزاد, دانلود سریال جدید شهرزاد , دانلود سریال شهرزاد با لینک مستقیم, دانلود فیلم های جدید و برتر, دانلود رایگان فیلم و سریال با لینک مستقیم دانلود قسمت 1 اول فصل دوم سریال شهرزاد",1 +"Such a nice blog and i appreciate your all efforts about your thoughts. it's really good work. well done.I would like to share something really helpful for education. [College Essay Help][1] + + + [1]: https://myassignmenthelp.com/essay-help/college-essays-help.html",1 +"I like this post,And I figure that they having a ton of fun to peruse this post,they might take a decent site to make an information,thanks for sharing it to me. dentist juarez mexico",1 +"It became indispensable set of tools after I learned about it from [buy esssay info][1] immediately! I used to work with Python Libraries and I am glad those tools appeared! + + + [1]: http://buyessay.info/",1 +"Furnished with cluster of valuable control and estimation apparatuses. This little yet effective Pocket Science Lab empowers you to perform different investigations and [Do My Homework][1] study an extensive variety of wonders. + + + [1]: http://www.homeworkclock.com/",1 +"I have read your blog it is very helpful for me. I want to say thanks to you. I have bookmark your site for future updates. me atelie",1 +"The Python Software Foundation (PSF) is a 501(c)(3) non-benefit organization that holds the protected innovation rights behind the Python programming dialect. We deal with the open source permitting [Essay Writers][1] for Python rendition 2.1 and later and claim and ensure the trademarks related with Python. + + + [1]: http://www.essaystigers.co.uk",1 +"This discussion will present us with various proposition of [Assignment Writers][1] . It's be a surely sharp searching at process and the transmit amassing is doing doing wonderful work. + + [1]: https://www.lawessayshelp.co.uk/law-assignment.php",1 +"There is a great book that helped me [make my thesis][1] and develop my own library in Python. Natural Language Toolkit (set of libraries and projects for typical NLP for English coded in the Python) saved my own project. + + + [1]: http://www.buythesisonline.org/write-my-thesis.php",1 +"A programming dialect like pycon is splendid for doing little projects like this as the projects are effectively changed to suit your necessities This is valid for pie diagrams, bar graphs and histograms. You can even make shapes (ie application frame as [Dissertation Writing Service UK][1] has) utilizing print proclamations and yielding to the printer when you have the Presentation agreeable to you. + + + [1]: http://www.dissertationhelpdeal.co.uk/",1 +"Get free gift cards online free keys generated online. you can find stmkeyscodes.net steam gift cards and wallet codes at retail stores across the world in a variety of denomination.",1 +"It sounds like you are attempting to keep running before you can walk. On the off chance that you don't know anything about programming (HTML is a record increase dialect and has nothing to do with programming) you ought to begin by picking up programming/python. [top paper service][1] When you know python you will have a more prominent comprehension of what (or in the event that) you would require Django/Flask and so forth. + + + [1]: http://www.toppaperservice.com",1 +"Django is a free and open source web application structure, written in Python, [toppaperservice][1] which takes after the model–view–controller building design it is kept up by the Django Software Foundation (DSF), an autonomous association built up as non-beneficial. + + + [1]: http://www.toppaperservice.com",1 +"This is really unique post for me to read about animal computer interaction. I am an experienced assignment writer as well as I work at [UK Assignment Help][1] agency and talking to machine is my favorite topic and I have written many thesis and research paper on it. now I'm working on Neural Networks in Machine Learning which is almost completed. + + + [1]: https://www.assignmenthelponweb.co.uk/",1 +"Rather than fighting against something that's already broken beyond repair, create something new that causes that thing to become irrelevant ([custom essay company][1]'s citation). This is precisely how paradigms change. + + + [1]: http://essaywriting.center",1 +"This talk will give us different recommendation of task essayist uk. It's be a truly sharp taking a gander at process and the transmit social affair is doing great work. [Buy Dissertation Online][1] + + + [1]: https://www.affordable-dissertation.co.uk/buy-dissertations-online/",1 +"The discussion expect some commonality or interest about high volume applications and general comprehension of grouping, apportioning and so forth. Some perusing of the accompanying connections may be useful yet is a bit much... [Dissertation Writing Service][1] + + + [1]: https://www.theacademicpapers.co.uk/dissertation-writing-services-uk.php",1 +"Greatful post! I added to bookmarks this page, keep this level up! [192.168.0.1][1] + + + [1]: http://19216801ip.com/",1 +"Thanks for this well and amazing post given here [Snapchat Login][1]. + + + [1]: https://snapchatonlinelogin.org",1 +"wow! we are as a programmer this is good news for us! becaus Python is one of the famous programming laguage people want to developed software in pathon we know pathon is really complicated programming diynamic laguage its not easy task for every programmer because of this weshoud take help such kind articles and videos as well, and we should do need more practice then may be we will understand this language expert programmer said about paython its very complicated then C++, C#.[Suicide Squad Leather Coat][1] + + + [1]: http://www.getmyleather.com/product/suicide-squad-joker-coat",1 +"Decorator charges can fluctuate contingent upon your area. Decorators in some cases include commission the item they are obtaining for you since we get the item at a lesser cost than if a standard customer strolled in. For the most part, that is the thing that you pay when you go to a furniture store and work with their decorator [Complete Seo Services][1] On the off chance that you employ an expert planner that is authorized (ASID or IIDA) hope to pay at least $75.00 and hour and they for the most part make commission on item also. The originator will work up an agreement for your particular needs. +Yes, decorators and creators will run shopping with you to help you, as a rule this is the point at which the planner charges by the hour. + + + [1]: http://www.seoservicesland.com",1 +"A great deal of companies that provide [write essays for me][1] services are scams, look out only for the best. + + + [1]: https://gradexy.com",1 +"Thanks for sharing nice post please do share [Pizza Hut hours][1] + + + [1]: http://usholidayhours.com/pizza-hut-hours-near-me/",1 +"Thanks for sharing please do share such post [McDonald's hours][1] + + + [1]: http://usholidayhours.com/mcdonalds-hours-near-me/",1 +"[Costco hours][1] + + +[Chase bank hours][2] + + +[KFC hours][3] + + + [1]: http://usholidayhours.com/costco-hours-near-me/ + [2]: http://usholidayhours.com/chase-bank-hours-near-me/ + [3]: http://usholidayhours.com/kfc-hours-near-me/",1 +"Relatively few individuals would utilize the words Python and Microsoft in a similar sentence. In any case, as a general rule there is parcel of Python advancement occurring at Microsoft, In this open talk, we will discuss Python Development focus on Azure, Python instruments for Visual Studio, [Essay Writing Services][1] different Python SDKs accessible for Azure administrations et cetera. To put it plainly, we will discuss everything that Microsoft is doing with Python. + + + [1]: http://www.assignmentgurus.co.uk/essay-writing-service/",1 +"May i know the procedure of improvement of foods grown from the ground in the plant? help me please...? + [writing assignment help in uk][1] (amid the germination of dust grain, a dust tube is formed)explain to me what is the ""generative core"" and ""vegetative core"" and how are the procedure? + + + [1]: http://www.assignmentmaster.co.uk/",1 +Check comment,0 +"Thanks, like your linkedin account. NVF seems to be worthy. I'll have a look at it. +[domyhomeworkonline.net][1] webmaster + + + [1]: http://domyhomeworkonline.net/",1 +"Ability of gaining knowledge of new things quick and easily is an tremendous talent of some human beings however there are approaches to growth mastering agility mainly for newly graduated college students who've taken Essay Writing Service UK for writing their essay.",1 +"Ability of gaining knowledge of new things quick and easily is an tremendous talent of some human beings however there are approaches to growth mastering agility mainly for newly graduated college students who've taken Essay Writing Service UK for writing their essay.",1 +"You need to probable pursue Data Science first, on the way to come up with the technical skills and experience.[Assignment Help][1] + + + [1]: https://www.lawessayshelp.co.uk/law-assignment.php",1 +"Thanks for sharing this post please do share such post [USPS hours][1] + + + [1]: http://uspstrackingdetails.com/usps-saturday-sunday-delivery-time/",1 +"Thanks for sharing please do sharing [USPS tracking][1] + + +[USPS hold mail][2] + + + [1]: http://uspstrackingdetails.com/usps-tracking/ + [2]: http://%20%20http://uspstrackingdetails.com/usps-hold-mail/",1 +"Thanks for sharing please do sharing [USPS change of Address][1] + + + [1]: http://uspstrackingdetails.com/usps-change-of-address/",1 +"Thanks for sharing please do sharing [USPS change of Address][1] + + +[USPS lost tracking Number][2] + + + [1]: http://uspstrackingdetails.com/usps-change-of-address/ + [2]: http://uspstrackingdetails.com/usps-lost-tracking-number/",1 +"Love what you're doing here guys, keep it up you also go here: http://www.kizigamesxl.com/",1 +"It’s viable to feature the predicted outcome for the target market As in, on the quilt of this presentation. [Buy Essay UK][1] + + + [1]: https://www.britishessaywritingservice.co.uk/buy-essay-uk.php",1 +"It’s viable to feature the predicted outcome for the target market As in, on the quilt of this presentation. [Buy Essay UK][1] + + + [1]: https://www.britishessaywritingservice.co.uk/buy-essay-uk.php",1 +"Heard about Sairam before. Really interesting young man. Hope new workshop would be interesting too, `cause I want to take a part in it too",1 From d5584bad77b50fe54320a1cef265bdf321081326 Mon Sep 17 00:00:00 2001 From: kracekumar Date: Thu, 29 Jun 2017 01:22:18 +0530 Subject: [PATCH 552/666] Upgrade django allauth --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ceb3961e..f998f0d6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,7 +26,7 @@ Pillow==2.9.0 # Auth # ------------------------------------------------- -django-allauth==0.24.0 +django-allauth==0.32.0 oauthlib==1.1.2 python-openid==2.2.5 requests==2.7.0 From f4a15730b29322a765399b24fbd21e416145fc2c Mon Sep 17 00:00:00 2001 From: Sumit Chahal Date: Wed, 6 Sep 2017 22:54:23 +0530 Subject: [PATCH 553/666] Add HTML title attribute with full datetime format So user can see the exact time (to the minute) when a proposal was created, modified, etc. Uses format "d M Y, H:i" (e.g. "05 Sep 2017, 23:07"). --- junction/templates/profiles/dashboard.html | 2 +- junction/templates/proposals/detail/base.html | 2 +- junction/templates/proposals/partials/proposal-list--items.html | 2 +- .../proposals/partials/proposal-list--review-items.html | 2 +- .../proposals/partials/proposal-list--selected-items.html | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/junction/templates/profiles/dashboard.html b/junction/templates/profiles/dashboard.html index f7fc351c..736b8fec 100644 --- a/junction/templates/profiles/dashboard.html +++ b/junction/templates/profiles/dashboard.html @@ -94,7 +94,7 @@

    {{ proposal.author.username }} {% endif %} |  - {{ proposal.created_at|date:"d M, Y" }} + {{ proposal.created_at|date:"d M, Y" }}

    diff --git a/junction/templates/proposals/detail/base.html b/junction/templates/proposals/detail/base.html index a72d88f4..c49a7cdb 100644 --- a/junction/templates/proposals/detail/base.html +++ b/junction/templates/proposals/detail/base.html @@ -205,7 +205,7 @@

    Reviewer Actions:

    Last Updated: - + diff --git a/junction/templates/proposals/partials/proposal-list--items.html b/junction/templates/proposals/partials/proposal-list--items.html index 7be08233..fd1787e2 100644 --- a/junction/templates/proposals/partials/proposal-list--items.html +++ b/junction/templates/proposals/partials/proposal-list--items.html @@ -60,7 +60,7 @@

    {{ proposal.author.username }} {% endif %} |  - {{ proposal.created_at|date:"d M, Y" }} + {{ proposal.created_at|date:"d M, Y" }}