Merged in [7644] from rjsparks@nostrum.com:

From rjsparks@nostrum.com:
  -  Fixed layout issue on schedule editing page in Chrome
  -  Fixed errant display of text in unscheduled group bar
     on the schedule editing page
  -  Changed the instruction text on the special requests
     field of the session request form
From rcross@amsl.com:
  - Improved scheduling of non-session items
  - Fixed issue with layout of the new notifications page
  - Fixed crash on notifications page
 - Legacy-Id: 7651
Note: SVN reference [7644] has been migrated to Git commit b8cfbf18e5
This commit is contained in:
Henrik Levkowetz 2014-04-25 15:45:54 +00:00
commit 3ac1856d09
8 changed files with 56 additions and 25 deletions

View file

@ -88,7 +88,7 @@ class MainTestCase(TestCase):
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
q = PyQuery(response.content)
self.assertEqual(q('#id_notification_list').html(),'ames,mars')
self.assertEqual(q('#id_notification_list').html(),'ames, mars')
# test that only changes since last notification show up
mars_group = Group.objects.get(acronym='mars')

View file

@ -14,7 +14,6 @@ from django.utils.functional import curry
from ietf.utils.mail import send_mail
from ietf.meeting.models import Meeting, Session, Room, TimeSlot, ScheduledSession, Schedule
from ietf.meeting.helpers import get_schedule
from ietf.group.models import Group, GroupEvent
from ietf.person.models import Person
from ietf.secr.meetings.blue_sheets import create_blue_sheets
@ -83,7 +82,7 @@ def build_timeslots(meeting,room=None):
location=room,
duration=t.duration)
def build_nonsession(meeting):
def build_nonsession(meeting,schedule):
'''
This function takes a meeting object and creates non-session records
for a new meeting, based on the last meeting
@ -94,7 +93,6 @@ def build_nonsession(meeting):
delta = meeting.date - last_meeting.date
system = Person.objects.get(name='(system)')
schedule = get_schedule(meeting)
for slot in TimeSlot.objects.filter(meeting=last_meeting,type__in=('break','reg','other','plenary')):
new_time = slot.time + delta
@ -118,6 +116,29 @@ def build_nonsession(meeting):
if session:
ScheduledSession.objects.create(schedule=schedule,session=session,timeslot=ts)
def check_nonsession(meeting,schedule):
'''
Ensure non-session timeslots exist and have appropriate ScheduledSession objects
for the specified schedule.
'''
slots = TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other','plenary'))
if not slots:
build_nonsession(meeting,schedule)
return None
scheduledsessions = slots.filter(type='plenary').first().scheduledsession_set.all()
if not scheduledsessions.filter(schedule=schedule):
source = scheduledsessions.first().schedule
copy_scheduledsessions(slots,source,schedule)
def copy_scheduledsessions(slots,source,target):
'''
Copy scheduledsession objects from source schedule to target schedule. Slots is
a queryset of slots
'''
for ss in ScheduledSession.objects.filter(schedule=source,timeslot__in=slots):
ScheduledSession.objects.create(schedule=target,session=ss.session,timeslot=ss.timeslot)
def get_last_meeting(meeting):
last_number = int(meeting.number) - 1
try:
@ -163,6 +184,7 @@ def send_notifications(meeting, groups, person):
count = 0
session_info = ''
data = [ (s,get_timeslot(s)) for s in sessions ]
data = [ (s,t) for s,t in data if t ]
for s,t in data:
count += 1
session_info += session_info_template.format(group.acronym,
@ -393,9 +415,7 @@ def non_session(request, meeting_id, schedule_name):
meeting = get_object_or_404(Meeting, number=meeting_id)
schedule = get_object_or_404(Schedule, meeting=meeting, name=schedule_name)
# if the Break/Registration records don't exist yet (new meeting) create them
if not TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other')):
build_nonsession(meeting)
check_nonsession(meeting,schedule)
slots = TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other','plenary')).order_by('-type__name','time')
@ -419,7 +439,7 @@ def non_session(request, meeting_id, schedule_name):
time=new_time,
duration=duration,
show_location=form.cleaned_data['show_location'])
# create a dummy Session object to hold materials
# NOTE: we're setting group to none here, but the set_room page will force user
# to pick a legitimate group
@ -436,10 +456,10 @@ def non_session(request, meeting_id, schedule_name):
# create association
ScheduledSession.objects.create(timeslot=timeslot,
session=session,
schedule=meeting.agenda)
schedule=schedule)
messages.success(request, 'Non-Sessions updated successfully')
return redirect('meetings_non_session', meeting_id=meeting_id, schedule_name=schedule.name)
return redirect('meetings_non_session', meeting_id=meeting_id, schedule_name=schedule_name)
else:
form = NonSessionForm(initial={'show_location':True})
@ -456,19 +476,22 @@ def non_session(request, meeting_id, schedule_name):
def non_session_delete(request, meeting_id, schedule_name, slot_id):
'''
This function deletes the non-session TimeSlot. For "other" and "plenary" timeslot types
we need to delete the corresponding Session object as well. Check for uploaded material
first.
This function deletes the non-session TimeSlot. For "other" and "plenary" timeslot
types we need to delete the corresponding Session object as well. Check for uploaded
material first. ScheduledSession objects get deleted as well.
'''
meeting = get_object_or_404(Meeting, number=meeting_id)
# schedule = get_object_or_404(Schedule, meeting=meeting, name=schedule_name)
slot = get_object_or_404(TimeSlot, id=slot_id)
if slot.type_id in ('other','plenary'):
session = get_session(slot,schedule=schedule)
if session and session.materials.exclude(states__slug='deleted'):
messages.error(request, 'Materials have already been uploaded for "%s". You must delete those before deleting the timeslot.' % slot.name)
return redirect('meetings_non_session', meeting_id=meeting_id, schedule_name=schedule_name)
scheduledsessions = slot.scheduledsession_set.filter(schedule__meeting=meeting)
session_objects = [ x.session for x in scheduledsessions ]
for session in session_objects:
if session.materials.exclude(states__slug='deleted'):
messages.error(request, 'Materials have already been uploaded for "%s". You must delete those before deleting the timeslot.' % slot.name)
return redirect('meetings_non_session', meeting_id=meeting_id, schedule_name=schedule_name)
else:
slot.sessions.all().delete()
Session.objects.filter(pk__in=[ x.pk for x in session_objects ]).delete()
slot.delete()
messages.success(request, 'Non-Session timeslot deleted successfully')
@ -480,6 +503,7 @@ def non_session_edit(request, meeting_id, schedule_name, slot_id):
'''
meeting = get_object_or_404(Meeting, number=meeting_id)
slot = get_object_or_404(TimeSlot, id=slot_id)
schedule = get_object_or_404(Schedule, meeting=meeting, name=schedule_name)
session = get_session(slot,schedule=schedule)
if request.method == 'POST':
@ -517,6 +541,7 @@ def non_session_edit(request, meeting_id, schedule_name, slot_id):
return render_to_response('meetings/non_session_edit.html', {
'meeting': meeting,
'form': form,
'schedule': schedule,
'slot': slot},
RequestContext(request, {}),
)

View file

@ -57,7 +57,7 @@
</td>
</tr>
<tr class="bg1">
<td valign="top">Special Requests:<br />&nbsp;<br />i.e. Meetecho, WebEx (please state which, and the reason needed), restrictions on meeting times / days, etc.</td>
<td valign="top">Special Requests:<br />&nbsp;<br />i.e. restrictions on meeting times / days, etc.</td>
<td>{{ form.comments.errors }}{{ form.comments }}</td>
</tr>
</table>

View file

@ -19,7 +19,7 @@
<form id="id_notification_form" action="." method="post">{% csrf_token %}
<p>Send email notifications to all groups that have been scheduled since the last
notification went out on {{ last_notice.time|date:"Y-m-d" }}:</p>
<p id="id_notification_list">{% if not groups %}(none){% endif %}{% for group in groups %}{{ group.acronym }}{% if not forloop.last %},{% endif %}{% endfor %}<p>
<p id="id_notification_list">{% if not groups %}(none){% endif %}{% for group in groups %}{{ group.acronym }}{% if not forloop.last %}, {% endif %}{% endfor %}<p>
<input type="submit" value="Send Now" name="submit" onclick="return window.confirm('Are you sure you want to send notifications?');">
</form>

View file

@ -12,14 +12,14 @@
});
$("select[id$='day']").change(function(){
var loadUrl = "/meetings/ajax/get-times/";
var loadUrl = "/secr/meetings/ajax/get-times/";
var url = window.location.pathname;
var parts = url.split("/");
var id = this.id;
var new_id = id.replace('day','time');
var sel = "#"+new_id;
var day = $(this).val();
loadUrl = loadUrl+parts[2]+"/"+day+"/";
loadUrl = loadUrl+parts[3]+"/"+day+"/";
$.getJSON(loadUrl,function(data) {
$(sel+" option").remove();
$.each(data,function(i,item) {

View file

@ -15,7 +15,7 @@
var ajax_load = "<p><h4 align='center'>Generating Proceedings. This may take a few minutes.</h3><img class='loading' src='{{ SECR_STATIC_URL }}img/ajax-loader.gif' alt='loading...' /></p>";
var url = window.location.pathname;
var parts = url.split("/");
var loadUrl = "/proceedings/ajax/generate-proceedings/" + parts[2] + "/";
var loadUrl = "/secr/proceedings/ajax/generate-proceedings/" + parts[2] + "/";
$("#private-functions").html(ajax_load).load(loadUrl);
});

View file

@ -701,6 +701,10 @@ table.actual_conflic3 {
background-repeat: no-repeat;
}
td.ourconflicts, td.theirconflicts {
white-space:nowrap;
}
/* ::-webkit-scrollbar{ */
/* width:3px; */
/* } */

View file

@ -1123,7 +1123,9 @@ Session.prototype.event_template = function() {
if(this.responsible_ad != undefined) {
area_mark = this.responsible_ad.area_mark;
if(area_mark == undefined) {
area_mark = "ad:" + this.responsible_ad.href;
// This doesn't seem to do the right thing
// area_mark = "ad:" + this.responsible_ad.href;
area_mark = "";
}
}