Changeset - ecabf31e54b9
[Not reviewed]
0 6 0
Christopher Neugebauer - 8 years ago 2016-07-09 13:14:31
_@chrisjrn.com
Assorted fixes (#47)

* Invokes the site tree fix from previous fixes.

* Adds a disclaimer noting that previous years’ accounts have not been carried over.

Fixes #43

* Adds proposal type to the proposal summary page.

Fixes #40

* Adds travel/accommodation assistance to the proposals page, but makes it only visible to speakers in the proposal, or review managers.

Fixes #41.
Fixes #42.

* Reduces a lot of the whitespace in the header and footer.

Fixes #44

* Proposals review page now shows information for every speaker on a proposal.

Fixes #45

* Makes sure that non_field_errors are displayed by forms.

Fixes #37
6 files changed with 77 insertions and 12 deletions:
0 comments (0 inline, 0 general)
pinaxcon/monkey_patch.py
Show inline comments
 
from django.conf import settings
 
from django.core.mail import EmailMultiAlternatives
 
from functools import wraps
 

	
 

	
 
class MonkeyPatchMiddleware(object):
 
    ''' Ensures that our monkey patching only gets called after it is safe to do so.'''
 

	
 
    def process_request(self, request):
 
        do_monkey_patch()
 

	
 

	
 
def do_monkey_patch():
 
    patch_speaker_profile_form()
 
    patch_accounts_to_send_bcc()
 
    fix_sitetree_check_access_500s()
 

	
 
    # Remove this function from existence
 
    global do_monkey_patch
 
    do_monkey_patch = lambda: None
 

	
 

	
 
def patch_speaker_profile_form():
 
    ''' Replaces textarea widgets with markdown editors. '''
 

	
 
    import widgets
 
    from symposion.speakers.forms import SpeakerForm
 

	
 
    fields = SpeakerForm.base_fields
 
    fields["biography"].widget = widgets.AceMarkdownEditor()
 
    fields["experience"].widget = widgets.AceMarkdownEditor()
 
    fields["accessibility"].widget = widgets.AceMarkdownEditor()
 

	
 

	
 
def patch_accounts_to_send_bcc():
 
    ''' Patches django-user-accounts' email functions to send a BCC e-mail to
 
    the default BCC e-mail address. '''
 

	
 
    from account import hooks
 

	
 
    # django-user-accounts always uses send_mail like:
 
    # send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, to)
 

	
 
    if hasattr(settings, "ENVELOPE_BCC_LIST"):
 
        bcc_email = settings.ENVELOPE_BCC_LIST
 
    else:
 
        bcc_email = None
 

	
 
    def send_mail(subject, message, from_email, to):
 
        email = EmailMultiAlternatives(
 
            subject,
 
            message,
 
            from_email,
 
            to,
 
            bcc=bcc_email,
 
        )
 
        email.send()
 

	
 
    hooks.send_mail = send_mail
 

	
 

	
 
def fix_sitetree_check_access_500s():
 
    ''' django-sitetree has a bug: https://github.com/idlesign/django-sitetree/pull/167/files
 
    -- it swallows the cause of all 500 errors. This swallows KeyErrors from
 
    the failing function. '''
 

	
 
    from sitetree.sitetreeapp import SiteTree
 

	
 
    old_check_access = SiteTree.check_access
 

	
 
    @wraps(SiteTree.check_access)
 
    def check_access(self, *a, **k):
 
        try:
 
            return old_check_access(self, *a, **k)
 
        except KeyError:
 
            return False
 

	
 
    SiteTree.check_access = check_access
pinaxcon/templates/_form_snippet.html
Show inline comments
 
{% load lca2017_tags %}
 

	
 
{% if form.non_field_errors %}
 
  {{ form.non_field_errors }}
 
  <br/>
 
{% endif %}
 

	
 
{% for field in form %}
 
  {% if not field.is_hidden %}
 
    <div class="fieldWrapper">
 
      <div>
 
        {% classname field.field.widget as widget %}
 
        {% if widget != "CheckboxInput" %}
 
          <h4><label for="{{ field.id_for_label }}">{{ field.label }}</label></h4>
 
          {{ field.errors }}
 
          {{ field }}
 
        {% else %}
 
          <label for="{{ field.id_for_label }}"><strong>{{ field.label }}</strong></label>
 
          {{ field }}
 
          {{ field.errors }}
 
        {% endif %}
 
      </div>
 

	
 
      {% if field.help_text %}
 
        <span class="help_text">{{ field.help_text|safe }}</span>
 
      {% endif %}
 

	
 
      <p></p>
 
    </div>
 
  {% endif %}
 
{% endfor %}
pinaxcon/templates/account/login.html
Show inline comments
 
{% extends "utility_page.html" %}
 

	
 
{% load account_tags %}
 
{% load i18n %}
 
{% load bootstrap %}
 

	
 
{% block head_title %}{% trans "Log in" %}{% endblock %}
 
{% block page_title %}{% trans "Log in to an existing account" %}{% endblock %}
 

	
 
{% block utility_body %}
 

	
 
  {% if ACCOUNT_OPEN_SIGNUP %}
 
      <p class="login-signup">
 
              {% trans "Don't have an account?" %}  <strong><a href="{% urlnext 'account_signup' %}">{% trans "Sign up" %}</a></strong>
 
      </p>
 
  {% endif %}
 
      <p>
 
        {% trans "Accounts from previous years have not been carried over to this site." %}
 
        {% trans "You will need to create a new account for this year's site." %}
 
      </p>
 

	
 
            <form method="POST" action="{% url "account_login" %}" autocapitalize="off" {% if form.is_multipart %} enctype="multipart/form-data"{% endif %}>
 
                {% csrf_token %}
 
                <fieldset>
 
                  {% include "_form_snippet.html" with form=form %}
 

	
 
                  {% if redirect_field_value %}
 
                      <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
 
                  {% endif %}
 
                  <button type="submit" class="btn btn-primary">{% trans "Log in" %}</button>
 
                  <a href="{% url "account_password_reset" %}" class="btn btn-link">{% trans "Forgot your password?" %}</a>
 
                </fieldset>
 
            </form>
 
{% endblock %}
 

	
 
{% block scripts %}
 
    {{ block.super }}
 
    <script type="text/javascript">
 
        $(document).ready(function() {
 
            $('#id_username').focus();
 
        });
 
    </script>
 
{% endblock %}
pinaxcon/templates/symposion/proposals/_proposal_fields.html
Show inline comments
 
{% load i18n %}
 
{% load lca2017_tags %}
 

	
 
    <h4>{% trans "Submitted by" %}</h4>
 
    <p>{{ proposal.speaker }}</p>
 

	
 
    <h4>{% trans "Proposal Type" %}</h4>
 
    <p>{{ proposal.kind.name|capfirst }}</p>
 

	
 
    <h4>{% trans "Target Audience" %}</h4>
 
    <p>{{ proposal.get_target_audience_display }}&nbsp;</p>
 

	
 
    {% if proposal.additional_speakers.all %}
 
        <h4>{% trans "Additional Speakers" %}</h4>
 
        <ul>
 
            {% for speaker in proposal.additional_speakers.all %}
 
                <li>
 
                    {% if speaker.user %}
 
                        <strong>{{ speaker.name }}</strong> &lt;{{ speaker.email }}&gt;
 
                    {% else %}
 
                        {{ speaker.email }} ({% trans "Invitation Sent" %})
 
                    {% endif %}
 
                </li>
 
            {% endfor %}
 
        </ul>
 
        <p></p>
 
    {% endif %}
 

	
 
    <h4>{% trans "Abstract" %}</h4>
 
    <div class="abstract">{{ proposal.abstract_html|safe }}&nbsp;</div>
 

	
 
    <h4>{% trans "Private Abstract" %}</h4>
 
    <div class="private_abstract">{{ proposal.private_abstract_html|safe }}&nbsp;</div>
 

	
 
    <h4>{% trans "Project" %}</h4>
 
    <p>{{ proposal.project|safe }}&nbsp;</p>
 

	
 
    <h4>{% trans "Project URL" %}</h4>
 
    <p><a href="{{ proposal.project_url|safe }}">{{ proposal.project_url|safe }}</a>&nbsp;</p>
 

	
 
    <h4>{% trans "Video URL" %}</h4>
 
    <p><a href="{{ proposal.video_url|safe }}">{{ proposal.video_url|safe }}</a>&nbsp;</p>
 

	
 
    <h4>{% trans "Special Requirements" %}</h4>
 
    <div class="special_requirements">{{ proposal.technical_requirements_html|safe }}</div>
 

	
 
    <h4>{% trans "Speaker Bio" %}</h4>
 
    <div class="biography">{{ proposal.speaker.biography_html|safe }}&nbsp;</div>
 
    {% for speaker in proposal.speakers %}
 
      <h4>{% trans "Speaker:" %} {{ speaker.name }}</h4>
 
      <h5>{% trans "Biography" %}</h5>
 

	
 
      <div class="biography">{{ proposal.speaker.biography_html|safe }}&nbsp;</div>
 

	
 
      <h5>{% trans "Experience" %}</h5>
 
      <div class="biography">{{ proposal.speaker.experience_html|safe }}&nbsp;</div>
 
    {% endfor %}
 

	
 
    {% if can_manage_proposal or request.user.speaker_profile in proposal.speakers %}
 

	
 
    <h4>{% trans "Speaker Experience" %}</h4>
 
    <div class="biography">{{ proposal.speaker.experience_html|safe }}&nbsp;</div>
 
      <h4>{% trans "Assistance required?" %}</h4>
 
      <br />
 
      <table>
 
        <tr>
 
          <th></th>
 
          <th>{% trans "Travel" %}</th>
 
          <th>{% trans "Accommodation" %}</th>
 
        </tr>
 
        {% for speaker in proposal.speakers %}
 
          <tr>
 
            <td>{{ speaker.name }}</td>
 
            <td>{{ speaker.travel_assistance }}</td>
 
            <td>{{ speaker.accommodation_assistance }}</td>
 
          </tr>
 
        {% endfor %}
 
      </table>
 
      <br />
 

	
 
      {% if proposal.speaker.accessibility_html %}
 
        <h4>{% trans "Speaker Accessibility Requirements" %}</h4>
 
        {% for speaker in proposal.speakers %}
 
          {% if speaker.accessibility_html %}
 
            <h5>{{ speaker.name }}</h5>
 
            <div class="biography">{{ speaker.accessibility_html|safe }}&nbsp;</div>
 
          {% endif %}
 
        {% endfor %}
 
      {% endif %}
 

	
 
    {% endif %}
 

	
 
    <h4>{% trans "Speaker Accessibility Requirements" %}</h4>
 
    <div class="biography">{{ proposal.speaker.accessibility_html|safe }}&nbsp;</div>
 

	
 
    <h4>{% trans "Documents" %}</h4>
 
    <div>
 
        {% if proposal.supporting_documents.exists %}
 
            <table class="table table-striped">
 
                {% for document in proposal.supporting_documents.all %}
 
                    <tr>
 
                        <td><a href="{{ document.download_url }}">{{ document.description }}</a></td>
 
                        <td>
 
                        <form style="margin: 0;" method="post" action="{% url "proposal_document_delete" document.pk %}">
 
                            {% csrf_token %}
 
                            <button type="submit" class="btn btn-xs">delete</button>
 
                        </form>
 
                    </td>
 
                    </tr>
 
                {% endfor %}
 
            </table>
 
        {% else %}
 
            <p>No supporting documents attached to this proposal.</p>
 
        {% endif %}
 
    </div>
 

	
 
    <h4>{% trans "Recording Release" %}</h4>
 
    <p>{{ proposal.recording_release }}&nbsp;</p>
 

	
 
    <h4>{% trans "Materials Release" %}</h4>
 
    <p>{{ proposal.materials_release }}&nbsp;</p>
pinaxcon/templatetags/lca2017_tags.py
Show inline comments
 
from django import template
 
register = template.Library()
 

	
 
@register.assignment_tag()
 
def classname(ob):
 
    return ob.__class__.__name__
 

	
 
@register.simple_tag(takes_context=True)
 
def can_manage(context, proposal):
 
    return proposal_permission(context, "manage", proposal)
 

	
 
@register.simple_tag(takes_context=True)
 
def can_review(context, proposal):
 
    return proposal_permission(context, "review", proposal)
 

	
 
def proposal_permission(context, permname, proposal):
 
    slug = proposal.kind.section.slug
 
    perm = "reviews.can_%s_%s" % (permname, slug)
 
    return context.request.user.has_perm(perm)
static/src/lca2017/css/app.css
Show inline comments
...
 
@@ -1282,288 +1282,292 @@ table.alt tr:not(:last-of-type) {
 
  margin-top: 50px;
 
  margin-top: 3.125rem;
 
}
 

	
 
.l-header--logo {
 
  display: inline-block;
 
  width: 65%;
 
}
 

	
 
.l-header--logo > svg {
 
  display: block;
 
  width: 100%;
 
  height: 100%;
 
}
 

	
 
.l-header--logo > a {
 
  border: 0;
 
}
 

	
 
.l-header--menu-opener {
 
  float: right;
 
  width: 22px;
 
  height: 22px;
 
  position: relative;
 
  -ms-flex-item-align: start;
 
  align-self: flex-start;
 
  border: 0;
 
  z-index: 101;
 
}
 

	
 
.l-header--menu-opener:after, .l-header--menu-opener:before {
 
  transition: all 300ms ease-in-out;
 
  content: '';
 
  width: 100%;
 
  height: 4.4px;
 
  display: block;
 
  position: absolute;
 
  left: 0;
 
  transform-origin: center;
 
  background-color: #0c486c;
 
}
 

	
 
.l-header--menu-opener:before {
 
  top: 0;
 
  box-shadow: 0 8.8px #0c486c;
 
}
 

	
 
.l-header--menu-opener:after {
 
  bottom: 0;
 
}
 

	
 
.l-header--menu-opener.is-active:before {
 
  transform: translateY(8.8px) rotate(45deg);
 
  box-shadow: 0 8.8px rgba(12, 72, 108, 0);
 
}
 

	
 
.l-header--menu-opener.is-active:after {
 
  transform: translateY(-8.8px) rotate(-45deg);
 
}
 

	
 
.l-header--links {
 
  height: 100%;
 
  -ms-flex-item-align: start;
 
  align-self: flex-start;
 
  display: none;
 
  list-style: none;
 
  white-space: nowrap;
 
}
 

	
 
.l-header--nav {
 
  display: inline-block;
 
  margin-right: 10px;
 
  margin-right: 0.625rem;
 
  vertical-align: top;
 
  position: relative;
 
}
 

	
 
.l-header--nav:hover > .menu-dropdown {
 
  display: block;
 
}
 

	
 
.l-header--nav > a {
 
  vertical-align: top;
 
  border: 0;
 
  font-size: 0.8em;
 
}
 

	
 
@media (min-width: 25em) {
 
  .l-header--logo {
 
    width: 200px;
 
    margin-right: 2.5rem;
 
  }
 
}
 

	
 
@media (min-width: 48em) {
 
  .l-header {
 
    margin-top: 6.25rem;
 
    /*margin-top: 6.25rem;  /* issue #44. We don't like this. */
 
  }
 
  .l-header--menu-opener {
 
    display: none !important;
 
  }
 
  .l-header--links {
 
    display: inline-block;
 
  }
 
  .l-header--logo {
 
    width: 255px;
 
  }
 
}
 

	
 
@media (min-width: 64em) {
 
  .l-header--logo {
 
    width: 300px;
 
  }
 
  .l-header--nav {
 
    margin-right: 1.25rem;
 
  }
 
}
 

	
 
.l-speaker-page {
 
  margin-top: 60px;
 
  margin-top: 3.75rem;
 
}
 

	
 
.l-speaker-page--portrait {
 
  width: 100%;
 
}
 

	
 
@media (min-width: 48em) {
 
  .l-speaker-page {
 
    -ms-flex-wrap: nowrap;
 
    flex-wrap: nowrap;
 
    margin-top: 5rem;
 
  }
 
  .l-speaker-page--content *:first-child {
 
    margin-top: 0;
 
  }
 
  .l-speaker-page--portrait {
 
    width: auto;
 
  }
 
}
 

	
 
.l-footer {
 
  display: -ms-flexbox;
 
  display: flex;
 
  -ms-flex-align: center;
 
  align-items: center;
 
  -ms-flex-wrap: wrap;
 
  flex-wrap: wrap;
 
  -ms-flex-direction: column;
 
  flex-direction: column;
 
  margin-top: 100px;
 
  margin-top: 6.25rem;
 
  margin-top: 3.25rem;
 
  padding: 50px 40px;
 
  padding: 3.125rem 40px;
 
  width: 100%;
 
}
 

	
 
.l-footer--logos {
 
  display: -ms-flexbox;
 
  display: flex;
 
  -ms-flex-wrap: wrap;
 
  flex-wrap: wrap;
 
  -ms-flex-pack: distribute;
 
  justify-content: space-around;
 
  margin-top: 20px;
 
  margin-top: 1.25rem;
 
}
 

	
 
.l-footer--logo {
 
  max-width: 100%;
 
  -ms-flex-preferred-size: 45%;
 
  flex-basis: 45%;
 
}
 

	
 
.l-footer--logo > svg {
 
  display: block;
 
  width: 100%;
 
  height: 100%;
 
}
 

	
 
.l-footer__alt {
 
  background-color: #0c486c;
 
  color: white;
 
}
 

	
 
@media (min-width: 48em) {
 
  .l-footer {
 
    padding: 6.25rem 70px;
 
    /*padding: 6.25rem 70px; /* issue #44 too much padding */
 
    padding: 3.25rem 70px;
 
    -ms-flex-direction: row;
 
    flex-direction: row;
 
    -ms-flex-pack: justify;
 
    justify-content: space-between;
 
  }
 
  .l-footer--logos {
 
    margin-top: 0;
 
  }
 
}
 

	
 
@media (min-width: 64em) {
 
  .l-footer {
 
    padding: 6.25rem 160px;
 
    /*padding: 6.25rem 160px; */
 
    padding: 3.25rem 160px;
 
  }
 
}
 

	
 
@media (min-width: 80em) {
 
  .l-footer {
 
    padding: 6.25rem 200px;
 
    /*padding: 6.25rem 200px;*/
 
    padding: 3.25rem 200px;
 
  }
 
  .l-footer--logo {
 
    margin-bottom: 0;
 
    -ms-flex-preferred-size: auto;
 
    flex-basis: auto;
 
  }
 
}
 

	
 
@media (min-width: 1946px) {
 
  .l-footer {
 
    padding: 6.25rem auto;
 
    padding: 3.25rem auto;
 
    /*padding: 6.25rem auto;*/
 
  }
 
}
 

	
 
.l-content-page {
 
  margin-top: 80px;
 
  margin-top: 5rem;
 
}
 

	
 
.l-content-page--image {
 
  height: 200px;
 
  width: 100%;
 
  margin: 7vw 0;
 
  background-size: cover;
 
  background-position: center;
 
}
 

	
 
@media (min-width: 48em) {
 
  .l-content-page--image {
 
    height: 350px;
 
  }
 
}
 

	
 
@media (min-width: 64em) {
 
  .l-content-page--image {
 
    height: 500px;
 
  }
 
}
 

	
 
@media (min-width: 80em) {
 
  .l-content-page--image {
 
    height: 600px;
 
  }
 
}
 

	
 
.l-404 {
 
  margin-top: 80px;
 
  margin-top: 5rem;
 
}
 

	
 
@media (min-width: 64em) {
 
  .l-404--content {
 
    max-width: 50%;
 
  }
 
}
 

	
 
.styleguide > .black {
 
  background-color: black;
 
  padding: 20px;
 
}
 

	
 
/* ------------------------------------------------------------------------------------------------
 

	
 
Shame
 
=====
 

	
 
1. 	If it’s a hack, it goes in shame.css.
 
2. 	Document all hacks fully:
 
  a. 	What part of the codebase does it relate to?
 
  b. 	Why was this needed?
 
  c. 	How does this fix it?
 
  d. 	How might you fix it properly, given more time?
 
3. 	Do not blame the developer; if they explained why they had to do it then their reasons are
 
probably (hopefully) valid.
 
4. 	Try and clean shame.css up when you have some down time.
 

	
 
via: http://csswizardry.com/2013/04/shame-css/
 

	
 
------------------------------------------------------------------------------------------------ */
 

	
 
/*# sourceMappingURL=maps/app.css.map */
0 comments (0 inline, 0 general)