|
51 | 51 | from ietf.group.models import Group |
52 | 52 | from ietf.group.utils import can_manage_session_materials, can_manage_some_groups, can_manage_group |
53 | 53 | from ietf.person.models import Person |
54 | | -from ietf.ietfauth.utils import role_required, has_role |
| 54 | +from ietf.ietfauth.utils import role_required, has_role, user_is_person |
55 | 55 | from ietf.mailtrigger.utils import gather_address_lists |
56 | 56 | from ietf.meeting.models import Meeting, Session, Schedule, FloorPlan, SessionPresentation, TimeSlot, SlideSubmission |
57 | 57 | from ietf.meeting.models import SessionStatusName, SchedulingEvent, SchedTimeSessAssignment |
@@ -374,7 +374,7 @@ def __init__(self, schedule, new_owner, *args, **kwargs): |
374 | 374 | counter += 1 |
375 | 375 |
|
376 | 376 | self.fields['name'].initial = name_suggestion |
377 | | - self.fields['name'].label = "Name of new schedule" |
| 377 | + self.fields['name'].label = "Name of new agenda" |
378 | 378 |
|
379 | 379 | def clean_name(self): |
380 | 380 | name = self.cleaned_data.get('name') |
@@ -697,6 +697,8 @@ def cubehelix(i, total, hue=1.2, start_angle=0.5): |
697 | 697 | 'meeting': meeting, |
698 | 698 | 'schedule': schedule, |
699 | 699 | 'can_edit': can_edit, |
| 700 | + 'can_edit_properties': can_edit or secretariat, |
| 701 | + 'secretariat': secretariat, |
700 | 702 | 'js_data': json.dumps(js_data, indent=2), |
701 | 703 | 'days': days, |
702 | 704 | 'room_labels': room_labels, |
@@ -777,64 +779,86 @@ def edit_schedule(request, num=None, owner=None, name=None): |
777 | 779 | "assignments": assignments, |
778 | 780 | "show_inline": set(["txt","htm","html"]), |
779 | 781 | "hide_menu": True, |
| 782 | + "can_edit_properties": can_edit or secretariat, |
780 | 783 | }) |
781 | 784 |
|
782 | 785 |
|
783 | | -############################################################################## |
784 | | -# show the properties associated with a schedule (visible, public) |
785 | | -# |
786 | | -SchedulePropertiesForm = modelform_factory(Schedule, fields=('name','visible', 'public')) |
787 | | - |
788 | | -# The meeing urls.py won't allow empy num, owmer, or name values |
| 786 | +SchedulePropertiesForm = modelform_factory(Schedule, fields=['name', 'notes', 'visible', 'public']) |
789 | 787 |
|
790 | 788 | @role_required('Area Director','Secretariat') |
791 | | -def edit_schedule_properties(request, num=None, owner=None, name=None): |
| 789 | +def edit_schedule_properties(request, num, owner, name): |
792 | 790 | meeting = get_meeting(num) |
793 | 791 | person = get_person_by_email(owner) |
794 | 792 | schedule = get_schedule_by_name(meeting, person, name) |
795 | 793 | if schedule is None: |
796 | | - raise Http404("No meeting information for meeting %s owner %s schedule %s available" % (num, owner, name)) |
| 794 | + raise Http404("No agenda information for meeting %s owner %s schedule %s available" % (num, owner, name)) |
797 | 795 |
|
798 | | - cansee, canedit, secretariat = schedule_permissions(meeting, schedule, request.user) |
| 796 | + can_see, can_edit, secretariat = schedule_permissions(meeting, schedule, request.user) |
799 | 797 |
|
800 | | - if not (canedit or has_role(request.user,'Secretariat')): |
| 798 | + can_edit_properties = can_edit or secretariat |
| 799 | + |
| 800 | + if not can_edit_properties: |
801 | 801 | return HttpResponseForbidden("You may not edit this schedule") |
| 802 | + |
| 803 | + if request.method == 'POST': |
| 804 | + form = SchedulePropertiesForm(instance=schedule, data=request.POST) |
| 805 | + if form.is_valid(): |
| 806 | + form.save() |
| 807 | + return redirect('ietf.meeting.views.edit_schedule', num=num, owner=owner, name=name) |
802 | 808 | else: |
803 | | - if request.method == 'POST': |
804 | | - form = SchedulePropertiesForm(instance=schedule,data=request.POST) |
805 | | - if form.is_valid(): |
806 | | - form.save() |
807 | | - return HttpResponseRedirect(reverse('ietf.meeting.views.list_schedules',kwargs={'num': num})) |
808 | | - else: |
809 | | - form = SchedulePropertiesForm(instance=schedule) |
810 | | - return render(request, "meeting/properties_edit.html", |
811 | | - {"schedule":schedule, |
812 | | - "form":form, |
813 | | - "meeting":meeting, |
814 | | - }) |
| 809 | + form = SchedulePropertiesForm(instance=schedule) |
815 | 810 |
|
816 | | -############################################################################## |
817 | | -# show list of schedules. |
818 | | -# |
| 811 | + return render(request, "meeting/properties_edit.html", { |
| 812 | + "schedule": schedule, |
| 813 | + "form": form, |
| 814 | + "meeting": meeting, |
| 815 | + }) |
819 | 816 |
|
820 | | -@role_required('Area Director','Secretariat') |
821 | | -def list_schedules(request, num=None ): |
822 | 817 |
|
| 818 | +nat_sort_re = re.compile('([0-9]+)') |
| 819 | +def natural_sort_key(s): # from https://stackoverflow.com/questions/4836710/is-there-a-built-in-function-for-string-natural-sort |
| 820 | + return [int(text) if text.isdecimal() else text.lower() for text in nat_sort_re.split(s)] |
| 821 | + |
| 822 | +@role_required('Area Director','Secretariat') |
| 823 | +def list_schedules(request, num): |
823 | 824 | meeting = get_meeting(num) |
824 | | - user = request.user |
825 | 825 |
|
826 | | - schedules = meeting.schedule_set |
827 | | - if not has_role(user, 'Secretariat'): |
828 | | - schedules = schedules.filter(visible = True) | schedules.filter(owner = user.person) |
| 826 | + schedules = Schedule.objects.filter(meeting=meeting).prefetch_related('owner').order_by('owner', '-name', '-public').distinct() |
| 827 | + if not has_role(request.user, 'Secretariat'): |
| 828 | + schedules = schedules.filter(Q(visible=True) | Q(owner=request.user.person)) |
| 829 | + |
| 830 | + official_schedules = [] |
| 831 | + own_schedules = [] |
| 832 | + other_public_schedules = [] |
| 833 | + other_private_schedules = [] |
829 | 834 |
|
830 | | - schedules = schedules.order_by('owner', 'name') |
| 835 | + is_secretariat = has_role(request.user, 'Secretariat') |
831 | 836 |
|
832 | | - schedules = sorted(list(schedules),key=lambda x:not x.is_official) |
| 837 | + for s in schedules: |
| 838 | + s.can_edit_properties = is_secretariat or user_is_person(request.user, s.owner) |
833 | 839 |
|
834 | | - return render(request, "meeting/schedule_list.html", |
835 | | - {"meeting": meeting, |
836 | | - "schedules": schedules, |
837 | | - }) |
| 840 | + if s.pk == meeting.schedule_id: |
| 841 | + official_schedules.append(s) |
| 842 | + elif user_is_person(request.user, s.owner): |
| 843 | + own_schedules.append(s) |
| 844 | + elif s.public: |
| 845 | + other_public_schedules.append(s) |
| 846 | + else: |
| 847 | + other_private_schedules.append(s) |
| 848 | + |
| 849 | + schedule_groups = [ |
| 850 | + ("Official Agenda", official_schedules), |
| 851 | + ("Own Draft Agendas", own_schedules), |
| 852 | + ("Other Draft Agendas", other_public_schedules), |
| 853 | + ("Other Private Draft Agendas", other_private_schedules), |
| 854 | + ] |
| 855 | + |
| 856 | + schedule_groups = [(label, sorted(l, reverse=True, key=lambda s: natural_sort_key(s.name))) for label, l in schedule_groups if l] |
| 857 | + |
| 858 | + return render(request, "meeting/schedule_list.html", { |
| 859 | + 'meeting': meeting, |
| 860 | + 'schedule_groups': schedule_groups, |
| 861 | + }) |
838 | 862 |
|
839 | 863 | @ensure_csrf_cookie |
840 | 864 | def agenda(request, num=None, name=None, base=None, ext=None, owner=None, utc=""): |
|
0 commit comments