diff --git a/.gitignore b/.gitignore index ab2bb66..56830bc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ settings_local.py *.sqlite3 pip-log.txt *.pyc +*~ diff --git a/apps/profiles/models.py b/apps/profiles/models.py index 772a6ca..507c137 100644 --- a/apps/profiles/models.py +++ b/apps/profiles/models.py @@ -4,6 +4,7 @@ from tagging.fields import TagField from tagging.models import Tag from tagging_autocomplete.models import TagAutocompleteField +from timezones.zones import PRETTY_TIMEZONE_CHOICES from timezones.fields import TimeZoneField class Profile(models.Model): @@ -13,8 +14,8 @@ class Profile(models.Model): gchat = models.CharField("Google Chat", max_length=20, null=True, blank=True) phone = models.CharField("Phone number", max_length=20, null=True, blank=True) is_available = models.BooleanField("Available now") - timezone = TimeZoneField() - + timezone = TimeZoneField(choices=sorted(PRETTY_TIMEZONE_CHOICES, + key=lambda x: (int(x[1][4:9]), x[1]))) skills = models.ManyToManyField('Skill', blank=True) def __unicode__(self): return unicode(self.user) diff --git a/apps/profiles/urls.py b/apps/profiles/urls.py index d1c9b90..1e758fa 100644 --- a/apps/profiles/urls.py +++ b/apps/profiles/urls.py @@ -7,8 +7,8 @@ name='ajax_toggle_availability'), url(r'^set_availability/(?P\d)/$', 'set_availability', name='set_availability'), - url(r'^skills/(?P\w+)/$', 'list_profiles_by_skill', + url(r'^skills/(?P[-.\w]+)/$', 'list_profiles_by_skill', name='list_profiles_by_skill'), - url(r'^(?P\w+)/$', 'view_profile', name='view_profile'), + url(r'^(?P[-.\w]+)/$', 'view_profile', name='view_profile'), url(r'^(?P\d+)/skill/(?P\d+)/(?P\w+)/$', 'ajax_view', name='ajax-view'), ) diff --git a/apps/search/views.py b/apps/search/views.py index 2e32ff1..10555f4 100644 --- a/apps/search/views.py +++ b/apps/search/views.py @@ -14,12 +14,12 @@ def search(request): try: qs = [list(chain(*[skill.profile_set.all() for skill in Skill.objects.filter(name__contains=tag_clean(qry))])) for qry in query_list] results = list(set(qs[0]).intersection(*qs)) - except Exception as e: + except Exception, e: results = None else: try: results = list(chain(Skill.objects.get(name__contains=query_list[0]).profile_set.all())) - except Exception as e: + except Exception, e: if e.__class__ == Skill.MultipleObjectsReturned: results = list(chain(*[skill.profile_set.all() for skill in Skill.objects.filter(name__contains=query_list[0])])) else: diff --git a/manage.py b/manage.py old mode 100644 new mode 100755 diff --git a/media/schedule/css/images/ui-bg_flat_30_cccccc_40x100.png b/media/schedule/css/images/ui-bg_flat_30_cccccc_40x100.png new file mode 100644 index 0000000..5473aff Binary files /dev/null and b/media/schedule/css/images/ui-bg_flat_30_cccccc_40x100.png differ diff --git a/media/schedule/css/images/ui-bg_flat_50_5c5c5c_40x100.png b/media/schedule/css/images/ui-bg_flat_50_5c5c5c_40x100.png new file mode 100644 index 0000000..5950a8d Binary files /dev/null and b/media/schedule/css/images/ui-bg_flat_50_5c5c5c_40x100.png differ diff --git a/media/schedule/css/images/ui-bg_glass_20_555555_1x400.png b/media/schedule/css/images/ui-bg_glass_20_555555_1x400.png new file mode 100644 index 0000000..1ad224a Binary files /dev/null and b/media/schedule/css/images/ui-bg_glass_20_555555_1x400.png differ diff --git a/media/schedule/css/images/ui-bg_glass_40_0078a3_1x400.png b/media/schedule/css/images/ui-bg_glass_40_0078a3_1x400.png new file mode 100644 index 0000000..ee65c73 Binary files /dev/null and b/media/schedule/css/images/ui-bg_glass_40_0078a3_1x400.png differ diff --git a/media/schedule/css/images/ui-bg_glass_40_ffc73d_1x400.png b/media/schedule/css/images/ui-bg_glass_40_ffc73d_1x400.png new file mode 100644 index 0000000..35ec0d9 Binary files /dev/null and b/media/schedule/css/images/ui-bg_glass_40_ffc73d_1x400.png differ diff --git a/media/schedule/css/images/ui-bg_gloss-wave_25_333333_500x100.png b/media/schedule/css/images/ui-bg_gloss-wave_25_333333_500x100.png new file mode 100644 index 0000000..b1b03b6 Binary files /dev/null and b/media/schedule/css/images/ui-bg_gloss-wave_25_333333_500x100.png differ diff --git a/media/schedule/css/images/ui-bg_highlight-soft_80_eeeeee_1x100.png b/media/schedule/css/images/ui-bg_highlight-soft_80_eeeeee_1x100.png new file mode 100644 index 0000000..e56eefd Binary files /dev/null and b/media/schedule/css/images/ui-bg_highlight-soft_80_eeeeee_1x100.png differ diff --git a/media/schedule/css/images/ui-bg_inset-soft_25_000000_1x100.png b/media/schedule/css/images/ui-bg_inset-soft_25_000000_1x100.png new file mode 100644 index 0000000..3525eb9 Binary files /dev/null and b/media/schedule/css/images/ui-bg_inset-soft_25_000000_1x100.png differ diff --git a/media/schedule/css/images/ui-bg_inset-soft_30_f58400_1x100.png b/media/schedule/css/images/ui-bg_inset-soft_30_f58400_1x100.png new file mode 100644 index 0000000..2b6a9f9 Binary files /dev/null and b/media/schedule/css/images/ui-bg_inset-soft_30_f58400_1x100.png differ diff --git a/media/schedule/css/images/ui-icons_222222_256x240.png b/media/schedule/css/images/ui-icons_222222_256x240.png new file mode 100644 index 0000000..b273ff1 Binary files /dev/null and b/media/schedule/css/images/ui-icons_222222_256x240.png differ diff --git a/media/schedule/css/images/ui-icons_4b8e0b_256x240.png b/media/schedule/css/images/ui-icons_4b8e0b_256x240.png new file mode 100644 index 0000000..3bdb67b Binary files /dev/null and b/media/schedule/css/images/ui-icons_4b8e0b_256x240.png differ diff --git a/media/schedule/css/images/ui-icons_a83300_256x240.png b/media/schedule/css/images/ui-icons_a83300_256x240.png new file mode 100644 index 0000000..95993ea Binary files /dev/null and b/media/schedule/css/images/ui-icons_a83300_256x240.png differ diff --git a/media/schedule/css/images/ui-icons_cccccc_256x240.png b/media/schedule/css/images/ui-icons_cccccc_256x240.png new file mode 100644 index 0000000..9254e05 Binary files /dev/null and b/media/schedule/css/images/ui-icons_cccccc_256x240.png differ diff --git a/media/schedule/css/images/ui-icons_ffffff_256x240.png b/media/schedule/css/images/ui-icons_ffffff_256x240.png new file mode 100644 index 0000000..42f8f99 Binary files /dev/null and b/media/schedule/css/images/ui-icons_ffffff_256x240.png differ diff --git a/media/schedule/css/jquery.tooltip.css b/media/schedule/css/jquery.tooltip.css new file mode 100644 index 0000000..77d0357 --- /dev/null +++ b/media/schedule/css/jquery.tooltip.css @@ -0,0 +1,9 @@ +#tooltip { + position: absolute; + z-index: 3000; + border: 1px solid #111; + background-color: #eee; + padding: 5px; + opacity: 0.85; +} +#tooltip h3, #tooltip div { margin: 0; } diff --git a/settings.py b/settings.py index 579be30..fae9b97 100644 --- a/settings.py +++ b/settings.py @@ -106,7 +106,7 @@ # Uncomment the next line to enable the admin: 'django.contrib.admin', - # third-party apps: + # third-party apps: (see deploy/requirements.txt) 'ajax_select', 'django_extensions', 'schedule', diff --git a/settings_local.copy b/settings_local.copy index 1a6b296..ca69148 100644 --- a/settings_local.copy +++ b/settings_local.copy @@ -40,7 +40,7 @@ INSTALLED_APPS = ( # Uncomment the next line to enable the admin: 'django.contrib.admin', - # third-party apps: + # third-party apps: (see deploy/requirements.txt) 'ajax_select', 'django_extensions', 'schedule', diff --git a/templates/profiles/view_profile.html b/templates/profiles/view_profile.html index 38bdbe3..2cb6538 100644 --- a/templates/profiles/view_profile.html +++ b/templates/profiles/view_profile.html @@ -21,6 +21,8 @@

{% if display_full_profile %} {% with user.get_profile as profile %} +

{{ user.username }}

{{ profile.skype }} {% if profile.skype %} My status @@ -40,7 +42,7 @@

Holds office hours for:

{% for skill in user.get_profile.skills.all %}
  • {{ skill }}
  • {% empty %} -
  • {{ user.username }} has not listed his skills
  • +
  • {{ user.username }} has not listed any skills
  • {% endfor %}
    diff --git a/templates/schedule/event_form_base.html b/templates/schedule/event_form_base.html index 53d3cef..5c2d0d8 100644 --- a/templates/schedule/event_form_base.html +++ b/templates/schedule/event_form_base.html @@ -7,12 +7,20 @@ $(function() { $("#id_start_0").datepicker({ dateFormat: $.datepicker.ATOM, + changeMonth: true, + changeYear: true, + minDate: new Date(), onSelect: function(dateText,inst){ $("#id_end_0").val(dateText); } // automagically set end to the same date }); - $("#id_end_0").datepicker({dateFormat: $.datepicker.ATOM}); + $("#id_end_0").css({visibility: "hidden"}); $("#id_start_1").timePicker(); $("#id_end_1").timePicker(); - $("#id_end_recurring_period").datepicker({dateFormat: $.datepicker.ATOM}); + $("#id_end_recurring_period").datepicker({ + dateFormat: $.datepicker.ATOM, + changeMonth: true, + changeYear: true, + minDate: new Date() + }); var oldTime = $.timePicker("#id_start_1").getTime(); $("#id_start_1").change(function() { if ($("#id_end_1").val()) { // Only update when second input has a value. diff --git a/templates/upcoming_office_hour.html b/templates/upcoming_office_hour.html index fc57bb0..b579317 100644 --- a/templates/upcoming_office_hour.html +++ b/templates/upcoming_office_hour.html @@ -2,7 +2,13 @@
    {% with office_hour.event.creator as user %}

    {{ user.username }}

    -

    From {{ office_hour.event.start }} to {{ office_hour.event.end }}

    + {% if office_hour.start.date == office_hour.end.date %} +

    {{ office_hour.start.date }} + from {{ office_hour.start.time }} + to {{ office_hour.end.time }}

    + {% else %} +

    From {{ office_hour.start }} to {{ office_hour.end }}

    + {% endif %}
    • {{ user.get_profile.skills.all|join:"
    • " }}
    {% endwith %}
    diff --git a/views.py b/views.py index 3759878..6e85971 100644 --- a/views.py +++ b/views.py @@ -23,7 +23,15 @@ def site_index(request, template_name='index.html'): users = set(list(users_available_now) + users_holding_office_hours_now) future = Period(events=events, start=datetime.now(), end=datetime.now() + timedelta(days=MAX_FUTURE_DAYS)) - upcoming_office_hours = future.get_occurrences() + upcoming_office_hours = [] + already_saw = {} + for i in future.get_occurrences(): + if len(upcoming_office_hours) >= MAX_FUTURE_OFFICE_HOURS: + break + if already_saw.get(i.event.creator): + continue + upcoming_office_hours.append(i) + already_saw[i.event.creator] = 1 upcoming_office_hours = upcoming_office_hours[:MAX_FUTURE_OFFICE_HOURS] return direct_to_template(request, template_name, locals())