From 0f6e3f434eaff2ba3c90e1a99558b8ce1149daad Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Mon, 19 Sep 2016 19:06:22 +0000 Subject: [PATCH] Closed off the old paths for materials upload (redirecting some old entry points). Commit ready for merge. - Legacy-Id: 12000 --- ietf/meeting/views.py | 6 +- ietf/secr/meetings/views.py | 3 +- ietf/secr/proceedings/forms.py | 72 --- ietf/secr/proceedings/tests.py | 67 +-- ietf/secr/proceedings/urls.py | 16 +- ietf/secr/proceedings/views.py | 456 +----------------- .../includes/buttons_submit_back.html | 6 - ietf/secr/templates/includes/slides.html | 25 - .../templates/proceedings/edit_slide.html | 38 -- ietf/secr/templates/proceedings/main.html | 2 +- .../templates/proceedings/replace_slide.html | 38 -- ietf/secr/templates/proceedings/select.html | 45 +- .../proceedings/upload_presentation.html | 34 -- .../templates/proceedings/upload_unified.html | 116 ----- 14 files changed, 46 insertions(+), 878 deletions(-) delete mode 100644 ietf/secr/templates/includes/buttons_submit_back.html delete mode 100644 ietf/secr/templates/includes/slides.html delete mode 100755 ietf/secr/templates/proceedings/edit_slide.html delete mode 100755 ietf/secr/templates/proceedings/replace_slide.html delete mode 100644 ietf/secr/templates/proceedings/upload_presentation.html delete mode 100755 ietf/secr/templates/proceedings/upload_unified.html diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index fe465272d..6bbe5ce0d 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -20,7 +20,7 @@ from django import forms from django.shortcuts import render, redirect, get_object_or_404 from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, Http404 from django.contrib import messages -from django.core.urlresolvers import reverse +from django.core.urlresolvers import reverse,reverse_lazy from django.db.models import Min, Max from django.conf import settings from django.forms.models import modelform_factory, inlineformset_factory @@ -30,6 +30,7 @@ from django.utils.functional import curry from django.views.decorators.cache import cache_page from django.utils.text import slugify from django.views.decorators.csrf import ensure_csrf_cookie +from django.views.generic import RedirectView from django.template.defaultfilters import filesizeformat from ietf.doc.fields import SearchableDocumentsField @@ -1989,3 +1990,6 @@ def proceedings_overview(request, num=None): 'template': template, }) +class OldUploadRedirect(RedirectView): + def get_redirect_url(self, **kwargs): + return reverse_lazy('ietf.meeting.views.session_details',kwargs=self.kwargs) diff --git a/ietf/secr/meetings/views.py b/ietf/secr/meetings/views.py index c781c2876..ad47992f0 100644 --- a/ietf/secr/meetings/views.py +++ b/ietf/secr/meetings/views.py @@ -25,7 +25,8 @@ from ietf.secr.meetings.blue_sheets import create_blue_sheets from ietf.secr.meetings.forms import ( BaseMeetingRoomFormSet, MeetingModelForm, MeetingRoomForm, NewSessionForm, NonSessionEditForm, NonSessionForm, TimeSlotForm, UploadBlueSheetForm, get_next_slot ) -from ietf.secr.proceedings.views import build_choices, handle_upload_file +from ietf.secr.proceedings.views import build_choices +from ietf.secr.proceedings.utils import handle_upload_file from ietf.secr.sreq.forms import GroupSelectForm from ietf.secr.sreq.views import get_initial_session from ietf.secr.utils.meeting import get_session, get_timeslot diff --git a/ietf/secr/proceedings/forms.py b/ietf/secr/proceedings/forms.py index de4b48774..7243d4e10 100644 --- a/ietf/secr/proceedings/forms.py +++ b/ietf/secr/proceedings/forms.py @@ -1,11 +1,7 @@ -import os from django import forms -from django.conf import settings -from django.template.defaultfilters import filesizeformat from ietf.doc.models import Document -from ietf.name.models import DocTypeName from ietf.meeting.models import Session @@ -22,11 +18,6 @@ VALID_BLUESHEET_EXTENSIONS = ('.pdf','.jpg','.jpeg') # Forms #---------------------------------------------------------- -class EditSlideForm(forms.ModelForm): - class Meta: - model = Document - fields = ('title',) - class RecordingForm(forms.Form): external_url = forms.URLField(label='Url') session = forms.ModelChoiceField(queryset=Session.objects,empty_label='') @@ -46,66 +37,3 @@ class RecordingEditForm(forms.ModelForm): super(RecordingEditForm, self).__init__(*args, **kwargs) self.fields['external_url'].label='Url' -class ReplaceSlideForm(forms.ModelForm): - file = forms.FileField(label='Select File') - - class Meta: - model = Document - fields = ('title',) - - def clean_file(self): - file = self.cleaned_data.get('file') - ext = os.path.splitext(file.name)[1].lower() - if ext not in VALID_SLIDE_EXTENSIONS: - raise forms.ValidationError('Only these file types supported for presentation slides: %s' % ','.join(VALID_SLIDE_EXTENSIONS)) - if file._size > settings.SECR_MAX_UPLOAD_SIZE: - raise forms.ValidationError('Please keep filesize under %s. Current filesize %s' % (filesizeformat(settings.SECR_MAX_UPLOAD_SIZE), filesizeformat(file._size))) - return file - -class UnifiedUploadForm(forms.Form): - acronym = forms.CharField(widget=forms.HiddenInput()) - meeting_id = forms.CharField(widget=forms.HiddenInput()) - material_type = forms.ModelChoiceField(queryset=DocTypeName.objects.filter(slug__in=('minutes','agenda','slides','bluesheets')),empty_label=None) - slide_name = forms.CharField(label='Name of Presentation',max_length=255,required=False,help_text="For presentations only") - file = forms.FileField(label='Select File',help_text='
Note 1: You can only upload a presentation file in txt, pdf, doc, or ppt/pptx. System will not accept presentation files in any other format.

Note 2: All uploaded files will be available to the public immediately on the Preliminary Page. However, for the Proceedings, ppt/pptx files will be converted to html format and doc files will be converted to pdf format manually by the Secretariat staff.
') - - def clean_file(self): - file = self.cleaned_data['file'] - if file._size > settings.SECR_MAX_UPLOAD_SIZE: - raise forms.ValidationError('Please keep filesize under %s. Current filesize %s' % (filesizeformat(settings.SECR_MAX_UPLOAD_SIZE), filesizeformat(file._size))) - return file - - def clean(self): - super(UnifiedUploadForm, self).clean() - # if an invalid file type is supplied no file attribute will exist - if self.errors: - return self.cleaned_data - cleaned_data = self.cleaned_data - material_type = cleaned_data['material_type'] - slide_name = cleaned_data['slide_name'] - file = cleaned_data['file'] - ext = os.path.splitext(file.name)[1].lower() - - if material_type.slug == 'slides' and not slide_name: - raise forms.ValidationError('ERROR: Name of Presentaion cannot be blank') - - # only supporting PDFs per Alexa 04-05-2011 - #if material_type == 1 and not file_ext[1] == '.pdf': - # raise forms.ValidationError('Presentations must be a PDF file') - - # validate file extensions based on material type (slides,agenda,minutes,bluesheets) - # valid extensions per online documentation: meeting-materials.html - # 09-14-11 added ppt, pdf per Alexa - # 04-19-12 txt/html for agenda, +pdf for minutes per Russ - if material_type.slug == 'slides' and ext not in VALID_SLIDE_EXTENSIONS: - raise forms.ValidationError('Only these file types supported for presentation slides: %s' % ','.join(VALID_SLIDE_EXTENSIONS)) - if material_type.slug == 'agenda' and ext not in VALID_AGENDA_EXTENSIONS: - raise forms.ValidationError('Only these file types supported for agendas: %s' % ','.join(VALID_AGENDA_EXTENSIONS)) - if material_type.slug == 'minutes' and ext not in VALID_MINUTES_EXTENSIONS: - raise forms.ValidationError('Only these file types supported for minutes: %s' % ','.join(VALID_MINUTES_EXTENSIONS)) - if material_type.slug == 'bluesheets' and ext not in VALID_BLUESHEET_EXTENSIONS: - raise forms.ValidationError('Only these file types supported for bluesheets: %s' % ','.join(VALID_BLUESHEET_EXTENSIONS)) - - return cleaned_data - - diff --git a/ietf/secr/proceedings/tests.py b/ietf/secr/proceedings/tests.py index 62a347c13..448934fa2 100644 --- a/ietf/secr/proceedings/tests.py +++ b/ietf/secr/proceedings/tests.py @@ -2,20 +2,19 @@ import debug # pyflakes:ignore import os import shutil -from StringIO import StringIO - -from django.core.urlresolvers import reverse from django.conf import settings +from django.core.urlresolvers import reverse -from ietf.doc.models import Document from ietf.group.models import Group -from ietf.meeting.models import Meeting, Session +from ietf.meeting.models import Session from ietf.meeting.test_data import make_meeting_test_data from ietf.utils.test_data import make_test_data -from ietf.utils.test_utils import TestCase, unicontent +from ietf.utils.test_utils import TestCase from ietf.name.models import SessionStatusName -from ietf.secr.utils.meeting import get_proceedings_path +from ietf.meeting.factories import SessionFactory + +from ietf.secr.proceedings.proc_utils import create_proceedings SECR_USER='secretary' @@ -64,47 +63,23 @@ class RecordingTestCase(TestCase): self.assertEqual(response.status_code, 200) self.failUnless(external_url in response.content) - -class BluesheetTestCase(TestCase): +class OldProceedingsTestCase(TestCase): + ''' Ensure coverage of fragments of old proceedings generation until those are removed ''' def setUp(self): + self.session = SessionFactory(meeting__type_id='ietf') self.proceedings_dir = os.path.abspath("tmp-proceedings-dir") - if not os.path.exists(self.proceedings_dir): - os.mkdir(self.proceedings_dir) + + # This unintuitive bit is a consequence of the surprising implementation of meeting.get_materials_path self.saved_agenda_path = settings.AGENDA_PATH - settings.AGENDA_PATH = self.proceedings_dir - - self.interim_listing_dir = os.path.abspath("tmp-interim-listing-dir") - if not os.path.exists(self.interim_listing_dir): - os.mkdir(self.interim_listing_dir) - self.saved_secr_interim_listing_dir = settings.SECR_INTERIM_LISTING_DIR - settings.SECR_INTERIM_LISTING_DIR = self.interim_listing_dir - + settings.AGENDA_PATH= self.proceedings_dir + + target_path = self.session.meeting.get_materials_path() + if not os.path.exists(target_path): + os.makedirs(target_path) + def tearDown(self): - settings.AGENDA_PATH = self.saved_agenda_path shutil.rmtree(self.proceedings_dir) - settings.SECR_INTERIM_LISTING_DIR = self.saved_secr_interim_listing_dir - shutil.rmtree(self.interim_listing_dir) - - def test_upload(self): - make_meeting_test_data() - meeting = Meeting.objects.filter(type='interim',session__status='sched').first() - #self.assertTrue(meeting) - group = Group.objects.get(acronym='mars') - #Session.objects.create(meeting=meeting,group=group,requested_by_id=1,status_id='sched',type_id='session') - url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting.number,'acronym':'mars'}) - upfile = StringIO('dummy file') - upfile.name = "scan1.pdf" - self.client.login(username="marschairman", password="marschairman+password") - r = self.client.post(url, - dict(acronym='mars',meeting_id=meeting.id,material_type='bluesheets',file=upfile),follow=True) - self.assertEqual(r.status_code, 200) - doc = Document.objects.get(type='bluesheets') - self.failUnless(doc.external_url in unicontent(r)) - self.failUnless(os.path.exists(os.path.join(doc.get_file_path(),doc.external_url))) - # test that proceedings has bluesheets on it - path = get_proceedings_path(meeting,group) - self.failUnless(os.path.exists(path)) - with open(path) as f: - data = f.read() - self.failUnless(doc.external_url.encode('utf-8') in data) - + settings.AGENDA_PATH = self.saved_agenda_path + + def test_old_generate(self): + create_proceedings(self.session.meeting,self.session.group,is_final=True) diff --git a/ietf/secr/proceedings/urls.py b/ietf/secr/proceedings/urls.py index 56369142f..d931f8aa8 100644 --- a/ietf/secr/proceedings/urls.py +++ b/ietf/secr/proceedings/urls.py @@ -1,26 +1,16 @@ from django.conf.urls import patterns, url from django.conf import settings +from ietf.meeting.views import OldUploadRedirect urlpatterns = patterns('ietf.secr.proceedings.views', url(r'^$', 'main', name='proceedings'), url(r'^ajax/generate-proceedings/(?P\d{1,3})/$', 'ajax_generate_proceedings', name='proceedings_ajax_generate_proceedings'), - url(r'^ajax/order-slide/$', 'ajax_order_slide', name='proceedings_ajax_order_slide'), # special offline URL for testing proceedings build - url(r'^build/(?P\d{1,3}|interim-\d{4}-[A-Za-z0-9_\-\+]+)/(?P[-a-z0-9]+)/$', - 'build', name='proceedings_build'), - url(r'^delete/(?P[A-Za-z0-9._\-\+]+)/$', 'delete_material', name='proceedings_delete_material'), - url(r'^edit-slide/(?P[A-Za-z0-9._\-\+]+)/$', 'edit_slide', name='proceedings_edit_slide'), - url(r'^move-slide/(?P[A-Za-z0-9._\-\+]+)/(?P(up|down))/$', - 'move_slide', name='proceedings_move_slide'), url(r'^process-pdfs/(?P\d{1,3})/$', 'process_pdfs', name='proceedings_process_pdfs'), url(r'^progress-report/(?P\d{1,3})/$', 'progress_report', name='proceedings_progress_report'), - url(r'^replace-slide/(?P[A-Za-z0-9._\-\+]+)/$', 'replace_slide', name='proceedings_replace_slide'), url(r'^(?P\d{1,3})/$', 'select', name='proceedings_select'), url(r'^(?P\d{1,3})/recording/$', 'recording', name='proceedings_recording'), url(r'^(?P\d{1,3})/recording/edit/(?P[A-Za-z0-9_\-\+]+)$', 'recording_edit', name='proceedings_recording_edit'), - # NOTE: we have two entries here which both map to upload_unified, passing session_id or acronym - url(r'^(?P\d{1,3}|interim-\d{4}-[A-Za-z0-9_\-\+]+)/(?P\d{1,6})/$', - 'upload_unified', name='proceedings_upload_unified'), - url(r'^(?P\d{1,3}|interim-\d{4}-[A-Za-z0-9_\-\+]+)/%(acronym)s/$' % settings.URL_REGEXPS, - 'upload_unified', name='proceedings_upload_unified'), + url(r'^(?P\d{1,3}|interim-\d{4}-[A-Za-z0-9_\-\+]+)/%(acronym)s/$' % settings.URL_REGEXPS, + OldUploadRedirect.as_view()), ) diff --git a/ietf/secr/proceedings/views.py b/ietf/secr/proceedings/views.py index 7ddfad4e1..184c01846 100644 --- a/ietf/secr/proceedings/views.py +++ b/ietf/secr/proceedings/views.py @@ -8,31 +8,25 @@ import debug # pyflakes:ignore from django.conf import settings from django.contrib import messages -from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse from django.db.models import Max from django.http import HttpResponseRedirect from django.shortcuts import render_to_response, get_object_or_404, redirect from django.template import RequestContext -from django.utils.text import slugify -from ietf.secr.lib.template import jsonapi -from ietf.secr.sreq.forms import GroupSelectForm -from ietf.secr.utils.decorators import check_permissions, sec_only -from ietf.secr.utils.document import get_full_path -from ietf.secr.utils.group import get_my_groups, groups_by_session -from ietf.secr.utils.meeting import get_materials, get_timeslot, get_proceedings_path, get_proceedings_url -from ietf.doc.models import Document, DocAlias, DocEvent, State, NewRevisionDocEvent +from ietf.secr.utils.decorators import sec_only +from ietf.secr.utils.group import get_my_groups +from ietf.secr.utils.meeting import get_timeslot, get_proceedings_url +from ietf.doc.models import Document, DocEvent from ietf.group.models import Group from ietf.person.models import Person from ietf.ietfauth.utils import has_role, role_required -from ietf.meeting.models import Meeting, Session, TimeSlot, SchedTimeSessAssignment +from ietf.meeting.models import Meeting, Session, TimeSlot -from ietf.secr.proceedings.forms import EditSlideForm, RecordingForm, RecordingEditForm, ReplaceSlideForm, UnifiedUploadForm +from ietf.secr.proceedings.forms import RecordingForm, RecordingEditForm from ietf.secr.proceedings.proc_utils import ( gen_acknowledgement, gen_agenda, gen_areas, gen_attendees, gen_group_pages, gen_index, gen_irtf, gen_overview, gen_plenaries, gen_progress, gen_research, gen_training, create_proceedings, create_recording ) -from ietf.secr.proceedings.utils import handle_upload_file from ietf.utils.log import log # ------------------------------------------------- @@ -226,132 +220,10 @@ def ajax_generate_proceedings(request, meeting_num): RequestContext(request,{}), ) -@jsonapi -def ajax_order_slide(request): - ''' - Ajax function to change the order of presentation slides. - This function expects a POST request with the following parameters - order: new order of slide, 0 based - slide_name: slide primary key (name) - ''' - if request.method != 'POST' or not request.POST: - return { 'success' : False, 'error' : 'No data submitted or not POST' } - slide_name = request.POST.get('slide_name',None) - order = request.POST.get('order',None) - slide = get_object_or_404(Document, name=slide_name) - - # get all the slides for this session - session = slide.session_set.all()[0] - qs = session.materials.exclude(states__slug='deleted').filter(type='slides').order_by('order') - - # move slide and reorder list - slides = list(qs) - index = slides.index(slide) - slides.pop(index) - slides.insert(int(order),slide) - for ord,item in enumerate(slides,start=1): - if item.order != ord: - item.order = ord - item.save() - - return {'success':True,'order':order,'slide':slide_name} - # -------------------------------------------------- # STANDARD VIEW FUNCTIONS # -------------------------------------------------- -@role_required('Secretariat') -def build(request,meeting_num,acronym): - ''' - This is a utility or test view. It simply rebuilds the proceedings html for the specified - meeting / group. - ''' - meeting = Meeting.objects.get(number=meeting_num) - group = get_object_or_404(Group,acronym=acronym) - create_proceedings(meeting,group,is_final=True) - - messages.success(request,'proceedings.html was rebuilt') - url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting_num,'acronym':acronym}) - return HttpResponseRedirect(url) - -@check_permissions -def delete_material(request,slide_id): - ''' - This view handles deleting meeting materials. We don't actually delete the - document object but set the state to deleted and add a 'deleted' DocEvent. - ''' - doc = get_object_or_404(Document, name=slide_id) - # derive other objects - session = doc.session_set.all()[0] - meeting = session.meeting - group = session.group - - path = get_full_path(doc) - if path and os.path.exists(path): - os.remove(path) - - # leave it related - #session.materials.remove(doc) - - state = State.objects.get(type=doc.type,slug='deleted') - doc.set_state(state) - - # create deleted_document - e = DocEvent.objects.create(doc=doc, - by=request.user.person, - type='deleted', - desc="State set to deleted") - - doc.save_with_history([e]) - - create_proceedings(meeting,group) - - messages.success(request,'The material was deleted successfully') - if group.type.slug in ('wg','rg'): - url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting.number,'acronym':group.acronym}) - else: - url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting.number,'session_id':session.id}) - - return HttpResponseRedirect(url) - -@check_permissions -def edit_slide(request, slide_id): - ''' - This view allows the user to edit the name of a slide. - ''' - slide = get_object_or_404(Document, name=slide_id) - # derive other objects - session = slide.session_set.all()[0] - meeting = session.meeting - group = session.group - - if group.type.slug in ('wg','rg'): - url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting.number,'acronym':group.acronym}) - else: - url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting.number,'session_id':session.id}) - - if request.method == 'POST': # If the form has been submitted... - button_text = request.POST.get('submit', '') - if button_text == 'Cancel': - return HttpResponseRedirect(url) - - form = EditSlideForm(request.POST, instance=slide) # A form bound to the POST data - if form.is_valid(): - form.save() - - # rebuild proceedings.html - create_proceedings(meeting,group) - return HttpResponseRedirect(url) - else: - form = EditSlideForm(instance=slide) - - return render_to_response('proceedings/edit_slide.html',{ - 'group': group, - 'meeting':meeting, - 'slide':slide, - 'form':form}, - RequestContext(request, {}), - ) @role_required(*AUTHORIZED_ROLES) def main(request): @@ -391,42 +263,6 @@ def main(request): RequestContext(request,{}), ) -@check_permissions -def move_slide(request, slide_id, direction): - ''' - This view will re-order slides. In addition to meeting, group and slide IDs it takes - a direction argument which is a string [up|down]. - ''' - slide = get_object_or_404(Document, name=slide_id) - - # derive other objects - session = slide.session_set.all()[0] - meeting = session.meeting - group = session.group - qs = session.materials.exclude(states__slug='deleted').filter(type='slides').order_by('order') - - # if direction is up and we aren't already the first slide - if direction == 'up' and slide_id != str(qs[0].pk): - index = find_index(slide_id, qs) - slide_before = qs[index-1] - slide_before.order, slide.order = slide.order, slide_before.order - slide.save() - slide_before.save() - - # if direction is down, more than one slide and we aren't already the last slide - if direction == 'down' and qs.count() > 1 and slide_id != str(qs[qs.count()-1].pk): - index = find_index(slide_id, qs) - slide_after = qs[index+1] - slide_after.order, slide.order = slide.order, slide_after.order - slide.save() - slide_after.save() - - if group.type.slug in ('wg','rg'): - url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting.number,'acronym':group.acronym}) - else: - url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting.number,'session_id':session.id}) - return HttpResponseRedirect(url) - @sec_only def process_pdfs(request, meeting_num): ''' @@ -554,88 +390,14 @@ def recording_edit(request, meeting_num, name): RequestContext(request, {}), ) -@check_permissions -def replace_slide(request, slide_id): - ''' - This view allows the user to upload a new file to replace a slide. - ''' - slide = get_object_or_404(Document, name=slide_id) - # derive other objects - session = slide.session_set.all()[0] - meeting = session.meeting - group = session.group - - if group.type.slug in ('wg','rg'): - url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting.number,'acronym':group.acronym}) - else: - url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting.number,'session_id':session.id}) - - if request.method == 'POST': # If the form has been submitted... - button_text = request.POST.get('submit', '') - if button_text == 'Cancel': - return HttpResponseRedirect(url) - - form = ReplaceSlideForm(request.POST,request.FILES,instance=slide) # A form bound to the POST data - if form.is_valid(): - new_slide = form.save(commit=False) - new_slide.time = datetime.datetime.now() - - file = request.FILES[request.FILES.keys()[0]] - file_ext = os.path.splitext(file.name)[1] - disk_filename = new_slide.name + file_ext - handle_upload_file(file,disk_filename,meeting,'slides') - - new_slide.external_url = disk_filename - - # create DocEvent uploaded - e = DocEvent.objects.create(doc=slide, - by=request.user.person, - type='uploaded', - desc="Uploaded") - new_slide.save_with_history([e]) - - post_process(new_slide) - - # rebuild proceedings.html - create_proceedings(meeting,group) - - return HttpResponseRedirect(url) - else: - form = ReplaceSlideForm(instance=slide) - - return render_to_response('proceedings/replace_slide.html',{ - 'group': group, - 'meeting':meeting, - 'slide':slide, - 'form':form}, - RequestContext(request, {}), - ) - -@role_required(*AUTHORIZED_ROLES) +# TODO - should probably rename this since it's not selecting groups anymore +@role_required('Secretariat') def select(request, meeting_num): ''' - A screen to select which group you want to upload material for. Users of this view area - Secretariat staff and community (WG Chairs, ADs, etc). Only those groups with sessions - scheduled for the given meeting will appear in drop-downs. For Group and IRTF selects, the - value will be group.acronym to use in pretty URLs. Since Training sessions have no acronym - we'll use the session id. + Provide the secretariat only functions related to meeting materials management ''' - if request.method == 'POST': - if request.POST.get('group',None): - redirect_url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting_num,'acronym':request.POST['group']}) - return HttpResponseRedirect(redirect_url) - else: - messages.error(request, 'No Group selected') - meeting = get_object_or_404(Meeting, number=meeting_num) - user = request.user - try: - person = user.person - except ObjectDoesNotExist: - messages.warning(request, 'The account %s is not associated with any groups. If you have multiple Datatracker accounts you may try another or report a problem to ietf-action@ietf.org' % request.user) - return HttpResponseRedirect(reverse('proceedings')) - groups_session, groups_no_session = groups_by_session(user, meeting) proceedings_url = get_proceedings_url(meeting) # get the time proceedings were generated @@ -645,57 +407,13 @@ def select(request, meeting_num): else: last_run = None - # initialize group form - wgs = filter(lambda x: x.type_id in ('wg','ag','team'),groups_session) - group_form = GroupSelectForm(choices=build_choices(wgs)) - - # intialize IRTF form, only show if user is sec or irtf chair - if has_role(user,'Secretariat') or person.role_set.filter(name__slug='chair',group__type__slug__in=('irtf','rg')): - rgs = filter(lambda x: x.type_id == 'rg',groups_session) - irtf_form = GroupSelectForm(choices=build_choices(rgs)) - else: - irtf_form = None - - # initialize Training form, this select widget needs to have a session id, because - # it's utilmately the session that we associate material with - other_groups = filter(lambda x: x.type_id not in ('wg','ag','rg'),groups_session) - if other_groups: - add_choices = [] - sessions = Session.objects.filter(meeting=meeting,group__in=other_groups) - for session in sessions: - if session.name.lower().find('plenary') != -1: - continue - if session.name: - name = (session.name[:75] + '..') if len(session.name) > 75 else session.name - add_choices.append((session.id,name)) - else: - add_choices.append((session.id,session.group.name)) - choices = sorted(add_choices,key=lambda x: x[1]) - training_form = GroupSelectForm(choices=choices) - else: - training_form = None - - # iniialize plenary form - if has_role(user,['Secretariat','IETF Chair','IETF Trust Chair','IAB Chair','IAOC Chair','IAD']): - ss = SchedTimeSessAssignment.objects.filter(schedule=meeting.agenda,timeslot__type='plenary') - choices = [ (i.session.id, i.session.name) for i in sorted(ss,key=lambda x: x.session.name) ] - plenary_form = GroupSelectForm(choices=choices) - else: - plenary_form = None - # count PowerPoint files waiting to be converted - if has_role(user,'Secretariat'): - ppt = Document.objects.filter(session__meeting=meeting,type='slides',external_url__endswith='.ppt').exclude(states__slug='deleted') - pptx = Document.objects.filter(session__meeting=meeting,type='slides',external_url__endswith='.pptx').exclude(states__slug='deleted') - ppt_count = ppt.count() + pptx.count() - else: - ppt_count = 0 + # TODO : This should look at SessionPresentation instead + ppt = Document.objects.filter(session__meeting=meeting,type='slides',external_url__endswith='.ppt').exclude(states__slug='deleted') + pptx = Document.objects.filter(session__meeting=meeting,type='slides',external_url__endswith='.pptx').exclude(states__slug='deleted') + ppt_count = ppt.count() + pptx.count() return render_to_response('proceedings/select.html', { - 'group_form': group_form, - 'irtf_form': irtf_form, - 'training_form': training_form, - 'plenary_form': plenary_form, 'meeting': meeting, 'last_run': last_run, 'proceedings_url': proceedings_url, @@ -703,151 +421,3 @@ def select(request, meeting_num): RequestContext(request,{}), ) -@check_permissions -def upload_unified(request, meeting_num, acronym=None, session_id=None): - ''' - This view is the main view for uploading / re-ordering material for regular and interim - meetings. There are two urls.py entries which map to this view. The acronym_id option is used - most often for groups of regular and interim meetings. session_id is used for uploading - material for Training sessions (where group is not a unique identifier). We could have used - session_id all the time but this makes for an ugly URL which most of the time would be - avoided by using acronym. - ''' - def redirection_back(meeting, group): - if meeting.type.slug == 'interim': - url = reverse('proceedings') - else: - url = reverse('proceedings_select', kwargs={'meeting_num':meeting.number}) - return HttpResponseRedirect(url) - - meeting = get_object_or_404(Meeting, number=meeting_num) - now = datetime.datetime.now() - if acronym: - group = get_object_or_404(Group, acronym=acronym) - sessions = Session.objects.filter(meeting=meeting,group=group) - if not sessions.exists(): - meeting_name = "IETF %s"%meeting.number if meeting.number.isdigit() else meeting.number - messages.warning(request, 'There does not seem to be a %s session in %s.' % (group.acronym, meeting_name)) - return redirection_back(meeting, group) - session = sessions[0] - session_name = '' - elif session_id: - session = get_object_or_404(Session, id=int(session_id)) - sessions = [session] - group = session.group - session_name = session.name - - if request.method == 'POST': - button_text = request.POST.get('submit','') - if button_text == 'Back': - return redirection_back(meeting, group) - form = UnifiedUploadForm(request.POST,request.FILES) - if form.is_valid(): - material_type = form.cleaned_data['material_type'] - slide_name = form.cleaned_data['slide_name'] - - file = request.FILES[request.FILES.keys()[0]] - file_ext = os.path.splitext(file.name)[1] - - # set the filename - if meeting.type.slug == 'ietf': - filename = '%s-%s-%s' % (material_type.slug,meeting.number,group.acronym) - elif meeting.type.slug == 'interim': - filename = '%s-%s' % (material_type.slug,meeting.number) - - # NonSession material, use short name for shorter URLs - if session.short: - filename += "-%s" % session.short - elif session_name: - filename += "-%s" % slugify(session_name) - # -------------------------------- - - if material_type.slug == 'slides': - order_num = get_next_order_num(session) - slide_num = get_next_slide_num(session) - filename += "-%s" % slide_num - - disk_filename = filename + file_ext - - # create the Document object, in the case of slides the name will always be unique - # so you'll get a new object, agenda and minutes will reuse doc object if it exists - doc, created = Document.objects.get_or_create(type=material_type, - group=group, - name=filename) - doc.external_url = disk_filename - doc.time = now - if created: - doc.rev = '1' - else: - doc.rev = str(int(doc.rev) + 1) - if material_type.slug == 'slides': - doc.order=order_num - if slide_name: - doc.title = slide_name - else: - doc.title = doc.name - else: - doc.title = '%s for %s at %s' % (material_type.slug.capitalize(), group.acronym.upper(), meeting) - - DocAlias.objects.get_or_create(name=doc.name, document=doc) - - handle_upload_file(file,disk_filename,meeting,material_type.slug) - - # set Doc state - if doc.type.slug=='slides': - doc.set_state(State.objects.get(type=doc.type,slug='archived')) - doc.set_state(State.objects.get(type='reuse_policy',slug='single')) - else: - doc.set_state(State.objects.get(type=doc.type,slug='active')) - - # create session relationship, per Henrik we should associate documents to all sessions - # for the current meeting (until tools support different materials for diff sessions) - for s in sessions: - try: - sp = s.sessionpresentation_set.get(document=doc) - sp.rev = doc.rev - sp.save() - except ObjectDoesNotExist: - s.sessionpresentation_set.create(document=doc,rev=doc.rev) - - # create NewRevisionDocEvent instead of uploaded, per Ole - e = NewRevisionDocEvent.objects.create(type='new_revision', - by=request.user.person, - doc=doc, - rev=doc.rev, - desc='New revision available') - - doc.save_with_history([e]) - - post_process(doc) - create_proceedings(meeting,group) - messages.success(request,'File uploaded sucessfully') - - else: - form = UnifiedUploadForm(initial={'meeting_id':meeting.id,'acronym':group.acronym,'material_type':'slides'}) - - materials = get_materials(group,meeting) - - # gather DocEvents - # include deleted material to catch deleted doc events - #docs = session.materials.all() - # Don't report on draft DocEvents since the secr/materials app isn't managing them - docs = session.materials.exclude(type='draft') - docevents = DocEvent.objects.filter(doc__in=docs) - - path = get_proceedings_path(meeting,group) - if os.path.exists(path): - proceedings_url = get_proceedings_url(meeting,group) - else: - proceedings_url = '' - - return render_to_response('proceedings/upload_unified.html', { - 'docevents': docevents, - 'meeting': meeting, - 'group': group, - 'materials': materials, - 'form': form, - 'session_name': session_name, # for Tutorials, etc - 'proceedings_url': proceedings_url}, - RequestContext(request, {}), - ) diff --git a/ietf/secr/templates/includes/buttons_submit_back.html b/ietf/secr/templates/includes/buttons_submit_back.html deleted file mode 100644 index 9b3810731..000000000 --- a/ietf/secr/templates/includes/buttons_submit_back.html +++ /dev/null @@ -1,6 +0,0 @@ -
-
    -
  • -
  • -
-
diff --git a/ietf/secr/templates/includes/slides.html b/ietf/secr/templates/includes/slides.html deleted file mode 100644 index 71146bef6..000000000 --- a/ietf/secr/templates/includes/slides.html +++ /dev/null @@ -1,25 +0,0 @@ -{% load ams_filters %} - - - - - - - - - - - - - {% for slide in materials.slides %} - - - - - - - - - {% endfor %} - -
SlideFilenameEditReplaceDelete
{{ slide.title }}{{ slide.external_url }}{% if slide.external_url|is_ppt %} *{% endif %}EditReplaceDelete
diff --git a/ietf/secr/templates/proceedings/edit_slide.html b/ietf/secr/templates/proceedings/edit_slide.html deleted file mode 100755 index 2dde4a153..000000000 --- a/ietf/secr/templates/proceedings/edit_slide.html +++ /dev/null @@ -1,38 +0,0 @@ -{% extends "base_site.html" %} -{% load staticfiles %} -{% block title %}Edit Slide{% endblock %} - -{% block extrahead %}{{ block.super }} - -{% endblock %} - -{% block breadcrumbs %}{{ block.super }} - {% if meeting.type_id == "interim" %} - » Proceedings - » {{ meeting }} - » {{ slide.title }} - {% else %} - » Proceedings - » Select - » {{ group.acronym }} - » {{ slide.title }} - {% endif %} - -{% endblock %} - -{% block content %} - -
-

Working Group - {{ group.acronym }}

-

Edit Slide:

-
{% csrf_token %} - - {{ form.as_table }} -
- - {% include "includes/buttons_save_cancel.html" %} - -
-
- -{% endblock %} diff --git a/ietf/secr/templates/proceedings/main.html b/ietf/secr/templates/proceedings/main.html index 88d2064e8..8cc612110 100644 --- a/ietf/secr/templates/proceedings/main.html +++ b/ietf/secr/templates/proceedings/main.html @@ -54,7 +54,7 @@ {{ meeting.group.acronym }} - {{ meeting.date }} + {{ meeting.date }} {% endfor %} diff --git a/ietf/secr/templates/proceedings/replace_slide.html b/ietf/secr/templates/proceedings/replace_slide.html deleted file mode 100755 index 8dc27f8aa..000000000 --- a/ietf/secr/templates/proceedings/replace_slide.html +++ /dev/null @@ -1,38 +0,0 @@ -{% extends "base_site.html" %} -{% load staticfiles %} -{% block title %}Replace Slide{% endblock %} - -{% block extrahead %}{{ block.super }} - -{% endblock %} - -{% block breadcrumbs %}{{ block.super }} - {% if meeting.type_id == "interim" %} - » Proceedings - » {{ meeting }} - » {{ slide.title }} - {% else %} - » Proceedings - » Select - » {{ group.acronym }} - » {{ slide.title }} - {% endif %} - -{% endblock %} - -{% block content %} - -
-

Working Group - {{ group.acronym }}

-

Replace Slide:

-
{% csrf_token %} - - {{ form.as_table }} -
- - {% include "includes/buttons_save_cancel.html" %} - -
-
- -{% endblock %} diff --git a/ietf/secr/templates/proceedings/select.html b/ietf/secr/templates/proceedings/select.html index a22e66eaa..64b4ffcaf 100755 --- a/ietf/secr/templates/proceedings/select.html +++ b/ietf/secr/templates/proceedings/select.html @@ -29,7 +29,7 @@ {% block breadcrumbs %}{{ block.super }} » Proceedings - » {{ meeting.number }} - Select Group + » {{ meeting.number }} {% endblock %} {% block instructions %} @@ -39,49 +39,7 @@ {% block content %}
-

IETF {{ meeting.number }} - Upload Material

- - {% if user|has_role:"Secretariat" %} - {% endif %}
diff --git a/ietf/secr/templates/proceedings/upload_presentation.html b/ietf/secr/templates/proceedings/upload_presentation.html deleted file mode 100644 index 760ac4ef4..000000000 --- a/ietf/secr/templates/proceedings/upload_presentation.html +++ /dev/null @@ -1,34 +0,0 @@ -{% extends "base_site.html" %} -{% load staticfiles %} -{% block title %}Proceedings - Upload Presentations {% endblock %} - -{% block extrahead %}{{ block.super }} - -{% endblock %} - -{% block breadcrumbs %}{{ block.super }} - » Proceedings - » {{ meeting.meeting_num }} - » Convert Material - » Upload Presentation -{% endblock %} - -{% block content %} -
-
{% csrf_token %} -

Proceedings - Upload (HTML-Zipped) Presentation : {{ slide.group_name }}

-

For Presentation : {{ slide.slide_name }}

- - {{ upload_presentation.as_table }} -
-
-
    -
  • - -
-
-
-
- -{% endblock %} - diff --git a/ietf/secr/templates/proceedings/upload_unified.html b/ietf/secr/templates/proceedings/upload_unified.html deleted file mode 100755 index 3f318b76c..000000000 --- a/ietf/secr/templates/proceedings/upload_unified.html +++ /dev/null @@ -1,116 +0,0 @@ -{% extends "base_site.html" %} -{% load ietf_filters %} -{% load staticfiles %} -{% block title %}Proceedings{% endblock %} - -{% block extrastyle %}{{ block.super }} - -{% endblock %} - -{% block extrahead %}{{ block.super }} - - -{% endblock %} - -{% block breadcrumbs %}{{ block.super }} - - {% if meeting.type_id == "interim" %} - » Proceedings - » {{ meeting }} - {% else %} - » Proceedings - » {{ meeting }} - » {% if session_name %}{{ session_name }}{% else %}{{ group.acronym }}{% endif %} - {% endif %} - -{% endblock %} - -{% block content %} - -
-

{{ meeting }} - Upload Material - {% if session_name %}{{ session_name }}{% else %}Group: {{ group.acronym }}{% endif %} -

- - - - - - - - - - - {% if proceedings_url %} - - - {% else %} - - - {% endif %} - - - - {% if materials.minutes %} - - - - {% else %} - - - - {% endif %} - - - {% if materials.agenda %} - - - - {% else %} - - - - {% endif %} - - {% if materials.bluesheets %} - {% for item in materials.bluesheets %} - - - - - - {% endfor %} - {% endif %} - -
TypeFilenameDelete
Proceedingsproceedings.htmlProceedingsProceedings not yet generated
Minutes{{ materials.minutes.external_url }}DeleteMinutes(not uploaded)
Agenda{{ materials.agenda.external_url }}DeleteAgenda(not uploaded)
Bluesheet{{ item.external_url }}{% if user|has_role:"Secretariat" %}Delete{% endif %}
- - - - -
- -{% if docevents %} -
-
- {% include "includes/docevents.html" %} -
-{% endif %} - -{% endblock %} - -{% block footer-extras %} - {% include "includes/upload_footer.html" %} -{% endblock %}