|
78 | 78 | from ietf.meeting.utils import data_for_meetings_overview |
79 | 79 | from ietf.meeting.utils import preprocess_constraints_for_meeting_schedule_editor |
80 | 80 | from ietf.meeting.utils import diff_meeting_schedules, prefetch_schedule_diff_objects |
| 81 | +from ietf.meeting.utils import swap_meeting_schedule_timeslot_assignments |
81 | 82 | from ietf.message.utils import infer_message |
82 | 83 | from ietf.secr.proceedings.utils import handle_upload_file |
83 | 84 | from ietf.secr.proceedings.proc_utils import (get_progress_stats, post_process, import_audio_files, |
@@ -432,6 +433,10 @@ def copy_meeting_schedule(request, num, owner, name): |
432 | 433 | }) |
433 | 434 |
|
434 | 435 |
|
| 436 | +class SwapDaysForm(forms.Form): |
| 437 | + source_day = forms.DateField(required=True) |
| 438 | + target_day = forms.DateField(required=True) |
| 439 | + |
435 | 440 | @ensure_csrf_cookie |
436 | 441 | def edit_meeting_schedule(request, num=None, owner=None, name=None): |
437 | 442 | meeting = get_meeting(num) |
@@ -547,12 +552,13 @@ def prepare_sessions_for_display(sessions): |
547 | 552 | s.is_tombstone = s.current_status in tombstone_states |
548 | 553 |
|
549 | 554 |
|
550 | | - if request.method == 'POST': # handle ajax requests |
| 555 | + if request.method == 'POST': |
551 | 556 | if not can_edit: |
552 | 557 | return HttpResponseForbidden("Can't edit this schedule") |
553 | 558 |
|
554 | 559 | action = request.POST.get('action') |
555 | 560 |
|
| 561 | + # handle ajax requests |
556 | 562 | if action == 'assign' and request.POST.get('session', '').isdigit() and request.POST.get('timeslot', '').isdigit(): |
557 | 563 | session = get_object_or_404(sessions, pk=request.POST['session']) |
558 | 564 | timeslot = get_object_or_404(timeslots_qs, pk=request.POST['timeslot']) |
@@ -605,7 +611,22 @@ def prepare_sessions_for_display(sessions): |
605 | 611 |
|
606 | 612 | return JsonResponse({'success': True}) |
607 | 613 |
|
608 | | - return HttpResponse("Invalid parameters", status_code=400) |
| 614 | + elif action == 'swapdays': |
| 615 | + # updating the client side is a bit complicated, so just |
| 616 | + # do a full refresh |
| 617 | + |
| 618 | + swap_days_form = SwapDaysForm(request.POST) |
| 619 | + if not swap_days_form.is_valid(): |
| 620 | + return HttpResponse("Invalid swap: {}".format(swap_days_form.errors), status=400) |
| 621 | + |
| 622 | + source_day = swap_days_form.cleaned_data['source_day'] |
| 623 | + target_day = swap_days_form.cleaned_data['target_day'] |
| 624 | + |
| 625 | + swap_meeting_schedule_timeslot_assignments(schedule, [ts for ts in timeslots_qs if ts.time.date() == source_day], [ts for ts in timeslots_qs if ts.time.date() == target_day], target_day - source_day) |
| 626 | + |
| 627 | + return HttpResponseRedirect(request.get_full_path()) |
| 628 | + |
| 629 | + return HttpResponse("Invalid parameters", status=400) |
609 | 630 |
|
610 | 631 | # prepare timeslot layout |
611 | 632 |
|
@@ -688,20 +709,12 @@ def cubehelix(i, total, hue=1.2, start_angle=0.5): |
688 | 709 | p.scheduling_color = "rgb({}, {}, {})".format(*tuple(int(round(x * 255)) for x in rgb_color)) |
689 | 710 | p.light_scheduling_color = "rgb({}, {}, {})".format(*tuple(int(round((0.9 + 0.1 * x) * 255)) for x in rgb_color)) |
690 | 711 |
|
691 | | - js_data = { |
692 | | - 'can_edit': can_edit, |
693 | | - 'urls': { |
694 | | - 'assign': request.get_full_path() |
695 | | - } |
696 | | - } |
697 | | - |
698 | 712 | return render(request, "meeting/edit_meeting_schedule.html", { |
699 | 713 | 'meeting': meeting, |
700 | 714 | 'schedule': schedule, |
701 | 715 | 'can_edit': can_edit, |
702 | 716 | 'can_edit_properties': can_edit or secretariat, |
703 | 717 | 'secretariat': secretariat, |
704 | | - 'js_data': json.dumps(js_data, indent=2), |
705 | 718 | 'days': days, |
706 | 719 | 'room_labels': room_labels, |
707 | 720 | 'timeslot_groups': sorted((d, list(sorted(t_groups))) for d, t_groups in timeslot_groups.items()), |
|
0 commit comments