(somewhat bumpy) merge forward from proceedings/6.31.1.dev0
- Legacy-Id: 11992
This commit is contained in:
commit
02ee5dc5d7
|
@ -60,7 +60,7 @@ class DocumentInfo(models.Model):
|
|||
abstract = models.TextField(blank=True)
|
||||
rev = models.CharField(verbose_name="revision", max_length=16, blank=True)
|
||||
pages = models.IntegerField(blank=True, null=True)
|
||||
order = models.IntegerField(default=1, blank=True)
|
||||
order = models.IntegerField(default=1, blank=True) # This is probably obviated by SessionPresentaion.order
|
||||
intended_std_level = models.ForeignKey(IntendedStdLevelName, verbose_name="Intended standardization level", blank=True, null=True)
|
||||
std_level = models.ForeignKey(StdLevelName, verbose_name="Standardization level", blank=True, null=True)
|
||||
ad = models.ForeignKey(Person, verbose_name="area director", related_name='ad_%(class)s_set', blank=True, null=True)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('meeting', '0036_add_order_to_sessionpresentation'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='sessionpresentation',
|
||||
options={'ordering': ('order',)},
|
||||
),
|
||||
]
|
|
@ -963,6 +963,7 @@ class SessionPresentation(models.Model):
|
|||
|
||||
class Meta:
|
||||
db_table = 'meeting_session_materials'
|
||||
ordering = ('order',)
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s -> %s-%s" % (self.session, self.document.name, self.rev)
|
||||
|
@ -1005,7 +1006,7 @@ class Session(models.Model):
|
|||
for d in l:
|
||||
d.meeting_related = lambda: True
|
||||
else:
|
||||
l = self.materials.filter(type=material_type).exclude(states__type=material_type, states__slug='deleted').order_by("order")
|
||||
l = self.materials.filter(type=material_type).exclude(states__type=material_type, states__slug='deleted').order_by('sessionpresentation__order')
|
||||
|
||||
if only_one:
|
||||
if l:
|
||||
|
|
|
@ -1271,7 +1271,7 @@ class FinalizeProceedingsTests(TestCase):
|
|||
self.assertEqual(meeting.proceedings_final,True)
|
||||
self.assertEqual(meeting.session_set.filter(group__acronym="mars").first().sessionpresentation_set.filter(document__type="draft").first().rev,'00')
|
||||
|
||||
class BluesheetsTests(TestCase):
|
||||
class MaterialsTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.materials_dir = os.path.abspath(settings.TEST_MATERIALS_DIR)
|
||||
|
@ -1284,14 +1284,14 @@ class BluesheetsTests(TestCase):
|
|||
settings.AGENDA_PATH = self.saved_agenda_path
|
||||
shutil.rmtree(self.materials_dir)
|
||||
|
||||
def test_upload_blusheets(self):
|
||||
def test_upload_bluesheets(self):
|
||||
session = SessionFactory(meeting__type_id='ietf')
|
||||
url = urlreverse('ietf.meeting.views.upload_session_bluesheets',kwargs={'num':session.meeting.number,'session_id':session.id})
|
||||
login_testing_unauthorized(self,"secretary",url)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertFalse(q("div.alert"))
|
||||
self.assertTrue('Upload' in unicode(q("title")))
|
||||
self.assertFalse(session.sessionpresentation_set.exists())
|
||||
test_file = StringIO('this is some text for a test')
|
||||
test_file.name = "not_really.pdf"
|
||||
|
@ -1302,7 +1302,7 @@ class BluesheetsTests(TestCase):
|
|||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(q("div.alert"))
|
||||
self.assertTrue('Revise' in unicode(q("title")))
|
||||
test_file = StringIO('this is some different text for a test')
|
||||
test_file.name = "also_not_really.pdf"
|
||||
r = self.client.post(url,dict(file=test_file))
|
||||
|
@ -1317,7 +1317,7 @@ class BluesheetsTests(TestCase):
|
|||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertFalse(q("div.alert"))
|
||||
self.assertTrue('Upload' in unicode(q("title")))
|
||||
self.assertFalse(session.sessionpresentation_set.exists())
|
||||
test_file = StringIO('this is some text for a test')
|
||||
test_file.name = "not_really.pdf"
|
||||
|
@ -1325,3 +1325,129 @@ class BluesheetsTests(TestCase):
|
|||
self.assertEqual(r.status_code, 302)
|
||||
bs_doc = session.sessionpresentation_set.filter(document__type_id='bluesheets').first().document
|
||||
self.assertEqual(bs_doc.rev,'00')
|
||||
|
||||
def test_upload_minutes_agenda(self):
|
||||
for doctype in ('minutes','agenda'):
|
||||
session = SessionFactory(meeting__type_id='ietf')
|
||||
if doctype == 'minutes':
|
||||
url = urlreverse('ietf.meeting.views.upload_session_minutes',kwargs={'num':session.meeting.number,'session_id':session.id})
|
||||
else:
|
||||
url = urlreverse('ietf.meeting.views.upload_session_agenda',kwargs={'num':session.meeting.number,'session_id':session.id})
|
||||
self.client.logout()
|
||||
login_testing_unauthorized(self,"secretary",url)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue('Upload' in unicode(q("Title")))
|
||||
self.assertFalse(session.sessionpresentation_set.exists())
|
||||
self.assertFalse(q('form input[type="checkbox"]'))
|
||||
|
||||
session2 = SessionFactory(meeting=session.meeting,group=session.group)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(q('form input[type="checkbox"]'))
|
||||
|
||||
test_file = StringIO('this is some text for a test')
|
||||
test_file.name = "not_really.json"
|
||||
r = self.client.post(url,dict(file=test_file))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(q('form .has-error'))
|
||||
|
||||
test_file = StringIO('this is some text for a test'*1510000)
|
||||
test_file.name = "not_really.pdf"
|
||||
r = self.client.post(url,dict(file=test_file))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(q('form .has-error'))
|
||||
|
||||
test_file = StringIO('this is some text for a test')
|
||||
test_file.name = "not_really.txt"
|
||||
r = self.client.post(url,dict(file=test_file,apply_to_all=False))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
doc = session.sessionpresentation_set.filter(document__type_id=doctype).first().document
|
||||
self.assertEqual(doc.rev,'00')
|
||||
self.assertFalse(session2.sessionpresentation_set.filter(document__type_id=doctype))
|
||||
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue('Revise' in unicode(q("Title")))
|
||||
test_file = StringIO('this is some different text for a test')
|
||||
test_file.name = "also_not_really.txt"
|
||||
r = self.client.post(url,dict(file=test_file,apply_to_all=True))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
doc = Document.objects.get(pk=doc.pk)
|
||||
self.assertEqual(doc.rev,'01')
|
||||
self.assertTrue(session2.sessionpresentation_set.filter(document__type_id=doctype))
|
||||
|
||||
def test_upload_minutes_agenda_interim(self):
|
||||
session=SessionFactory(meeting__type_id='interim')
|
||||
for doctype in ('minutes','agenda'):
|
||||
if doctype=='minutes':
|
||||
url = urlreverse('ietf.meeting.views.upload_session_minutes',kwargs={'num':session.meeting.number,'session_id':session.id})
|
||||
else:
|
||||
url = urlreverse('ietf.meeting.views.upload_session_agenda',kwargs={'num':session.meeting.number,'session_id':session.id})
|
||||
self.client.logout()
|
||||
login_testing_unauthorized(self,"secretary",url)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue('Upload' in unicode(q("title")))
|
||||
self.assertFalse(session.sessionpresentation_set.filter(document__type_id=doctype))
|
||||
test_file = StringIO('this is some text for a test')
|
||||
test_file.name = "not_really.txt"
|
||||
r = self.client.post(url,dict(file=test_file))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
doc = session.sessionpresentation_set.filter(document__type_id=doctype).first().document
|
||||
self.assertEqual(doc.rev,'00')
|
||||
|
||||
def test_upload_slides(self):
|
||||
|
||||
session1 = SessionFactory(meeting__type_id='ietf')
|
||||
session2 = SessionFactory(meeting=session1.meeting,group=session1.group)
|
||||
url = urlreverse('ietf.meeting.views.upload_session_slides',kwargs={'num':session1.meeting.number,'session_id':session1.id})
|
||||
login_testing_unauthorized(self,"secretary",url)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue('Upload' in unicode(q("title")))
|
||||
self.assertFalse(session1.sessionpresentation_set.filter(document__type_id='slides'))
|
||||
test_file = StringIO('this is not really a slide')
|
||||
test_file.name = 'not_really.txt'
|
||||
r = self.client.post(url,dict(file=test_file,title='a test slide file',apply_to_all=True))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
self.assertEqual(session1.sessionpresentation_set.count(),1)
|
||||
self.assertEqual(session2.sessionpresentation_set.count(),1)
|
||||
sp = session2.sessionpresentation_set.first()
|
||||
self.assertEqual(sp.document.name, 'slides-%s-%s-a-test-slide-file' % (session1.meeting.number,session1.group.acronym ) )
|
||||
self.assertEqual(sp.order,1)
|
||||
|
||||
url = urlreverse('ietf.meeting.views.upload_session_slides',kwargs={'num':session2.meeting.number,'session_id':session2.id})
|
||||
test_file = StringIO('some other thing still not slidelike')
|
||||
test_file.name = 'also_not_really.txt'
|
||||
r = self.client.post(url,dict(file=test_file,title='a different slide file',apply_to_all=False))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
self.assertEqual(session1.sessionpresentation_set.count(),1)
|
||||
self.assertEqual(session2.sessionpresentation_set.count(),2)
|
||||
sp = session2.sessionpresentation_set.get(document__name__endswith='-a-different-slide-file')
|
||||
self.assertEqual(sp.order,2)
|
||||
self.assertEqual(sp.rev,u'00')
|
||||
self.assertEqual(sp.document.rev,u'00')
|
||||
|
||||
url = urlreverse('ietf.meeting.views.upload_session_slides',kwargs={'num':session2.meeting.number,'session_id':session2.id,'name':session2.sessionpresentation_set.get(order=2).document.name})
|
||||
r = self.client.get(url)
|
||||
self.assertTrue(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue('Revise' in unicode(q("title")))
|
||||
test_file = StringIO('new content for the second slide deck')
|
||||
test_file.name = 'doesnotmatter.txt'
|
||||
r = self.client.post(url,dict(file=test_file,title='rename the presentation',apply_to_all=False))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
self.assertEqual(session1.sessionpresentation_set.count(),1)
|
||||
self.assertEqual(session2.sessionpresentation_set.count(),2)
|
||||
sp = session2.sessionpresentation_set.get(order=2)
|
||||
self.assertEqual(sp.rev,u'01')
|
||||
self.assertEqual(sp.document.rev,u'01')
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@ safe_for_all_meeting_types = [
|
|||
url(r'^session/(?P<acronym>[-a-z0-9]+)/?$', views.session_details),
|
||||
url(r'^session/(?P<session_id>\d+)/drafts$', views.add_session_drafts),
|
||||
url(r'^session/(?P<session_id>\d+)/bluesheets$', views.upload_session_bluesheets),
|
||||
url(r'^session/(?P<session_id>\d+)/minutes$', views.upload_session_minutes),
|
||||
url(r'^session/(?P<session_id>\d+)/agenda$', views.upload_session_agenda),
|
||||
url(r'^session/(?P<session_id>\d+)/slides(?:/%(name)s)?$' % settings.URL_REGEXPS, views.upload_session_slides),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -28,7 +28,9 @@ from django.forms import ModelForm
|
|||
from django.template.loader import render_to_string
|
||||
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.template.defaultfilters import filesizeformat
|
||||
|
||||
from ietf.doc.fields import SearchableDocumentsField
|
||||
from ietf.doc.models import Document, State, DocEvent, NewRevisionDocEvent
|
||||
|
@ -52,7 +54,6 @@ from ietf.meeting.helpers import send_interim_cancellation_notice
|
|||
from ietf.meeting.helpers import send_interim_approval_request
|
||||
from ietf.meeting.helpers import send_interim_announcement_request
|
||||
from ietf.meeting.utils import finalize
|
||||
from ietf.person.models import Person
|
||||
from ietf.secr.proceedings.utils import handle_upload_file
|
||||
from ietf.utils.mail import send_mail_message
|
||||
from ietf.utils.pipe import pipe
|
||||
|
@ -1011,10 +1012,9 @@ def session_details(request, num, acronym ):
|
|||
if not sessions:
|
||||
raise Http404
|
||||
|
||||
type_counter = Counter()
|
||||
|
||||
for session in sessions:
|
||||
|
||||
session.type_counter = Counter()
|
||||
ss = session.timeslotassignments.filter(schedule=meeting.agenda).order_by('timeslot__time')
|
||||
if ss:
|
||||
session.time = ', '.join(x.timeslot.time.strftime("%A %b-%d-%Y %H%M") for x in ss)
|
||||
|
@ -1033,10 +1033,7 @@ def session_details(request, num, acronym ):
|
|||
# TODO FIXME Deleted materials shouldn't be in the sessionpresentation_set
|
||||
for qs in [session.filtered_artifacts,session.filtered_slides,session.filtered_drafts]:
|
||||
qs = [p for p in qs if p.document.get_state_slug(p.document.type_id)!='deleted']
|
||||
type_counter.update([p.document.type.slug for p in qs])
|
||||
|
||||
#session.filtered_sessionpresentation_set = [p for p in session.sessionpresentation_set.all() if p.document.get_state_slug(p.document.type_id)!='deleted']
|
||||
#type_counter.update([p.document.type.slug for p in session.filtered_sessionpresentation_set])
|
||||
session.type_counter.update([p.document.type.slug for p in qs])
|
||||
|
||||
can_manage = can_manage_materials(request.user, Group.objects.get(acronym=acronym))
|
||||
|
||||
|
@ -1045,7 +1042,6 @@ def session_details(request, num, acronym ):
|
|||
'meeting' :meeting ,
|
||||
'acronym' :acronym,
|
||||
'can_manage_materials' : can_manage,
|
||||
'type_counter': type_counter,
|
||||
})
|
||||
|
||||
class SessionDraftsForm(forms.Form):
|
||||
|
@ -1119,6 +1115,8 @@ def upload_session_bluesheets(request, session_id, num):
|
|||
if bluesheet_sp:
|
||||
doc = bluesheet_sp.document
|
||||
doc.rev = '%02d' % (int(doc.rev)+1)
|
||||
bluesheet_sp.rev = doc.rev
|
||||
bluesheet_sp.save()
|
||||
else:
|
||||
sess_time = session.official_timeslotassignment().timeslot.time
|
||||
if session.meeting.type_id=='ietf':
|
||||
|
@ -1143,7 +1141,7 @@ def upload_session_bluesheets(request, session_id, num):
|
|||
session.sessionpresentation_set.create(document=doc,rev='00')
|
||||
filename = '%s-%s%s'% ( doc.name, doc.rev, ext)
|
||||
doc.external_url = filename
|
||||
e = NewRevisionDocEvent.objects.create(doc=doc, by=Person.objects.get(name='(System)'),type='new_revision',desc='New revision available: %s'%doc.rev,rev=doc.rev)
|
||||
e = NewRevisionDocEvent.objects.create(doc=doc,by=request.user.person,type='new_revision',desc='New revision available: %s'%doc.rev,rev=doc.rev)
|
||||
doc.save_with_history([e])
|
||||
handle_upload_file(file, filename, session.meeting, 'bluesheets')
|
||||
return redirect('ietf.meeting.views.session_details',num=num,acronym=session.group.acronym)
|
||||
|
@ -1157,6 +1155,301 @@ def upload_session_bluesheets(request, session_id, num):
|
|||
'form': form,
|
||||
})
|
||||
|
||||
VALID_MINUTES_EXTENSIONS = ('.txt','.html','.htm','.pdf')
|
||||
# FIXME: This form validation code (based on the secretariat upload code) only looks at filename extensions
|
||||
# It should look at the contents of the files instead.
|
||||
class UploadMinutesForm(forms.Form):
|
||||
file = forms.FileField(label='Minutes file to upload. Note that you can only upload minutes in txt, html, or pdf formats.')
|
||||
apply_to_all = forms.BooleanField(label='Apply to all group sessions at this meeting',initial=True,required=False)
|
||||
|
||||
def __init__(self, num_sessions, *args, **kwargs):
|
||||
super(UploadMinutesForm, self).__init__(*args, **kwargs)
|
||||
if num_sessions<2:
|
||||
self.fields.pop('apply_to_all')
|
||||
|
||||
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. Requested upload size is %s' % (filesizeformat(settings.SECR_MAX_UPLOAD_SIZE),filesizeformat(file._size)))
|
||||
if os.path.splitext(file.name)[1].lower() not in VALID_MINUTES_EXTENSIONS:
|
||||
raise forms.ValidationError('Only these file types supported for minutes: %s' % ','.join(VALID_MINUTES_EXTENSIONS))
|
||||
return file
|
||||
|
||||
def upload_session_minutes(request, session_id, num):
|
||||
# num is redundant, but we're dragging it along an artifact of where we are in the current URL structure
|
||||
session = get_object_or_404(Session,pk=session_id)
|
||||
|
||||
if not session.can_manage_materials(request.user):
|
||||
return HttpResponseForbidden("You don't have permission to upload minutes for this session.")
|
||||
if session.is_material_submission_cutoff() and not has_role(request.user, "Secretariat"):
|
||||
return HttpResponseForbidden("The materials cutoff for this session has passed. Contact the secretariat for further action.")
|
||||
|
||||
session_number = None
|
||||
sessions = get_sessions(session.meeting.number,session.group.acronym)
|
||||
num_sessions = len(sessions)
|
||||
if len(sessions) > 1:
|
||||
session_number = 1 + sessions.index(session)
|
||||
|
||||
minutes_sp = session.sessionpresentation_set.filter(document__type='minutes').first()
|
||||
|
||||
if request.method == 'POST':
|
||||
form = UploadMinutesForm(num_sessions,request.POST,request.FILES)
|
||||
if form.is_valid():
|
||||
file = request.FILES['file']
|
||||
_, ext = os.path.splitext(file.name)
|
||||
apply_to_all = True
|
||||
if num_sessions > 1:
|
||||
apply_to_all = form.cleaned_data['apply_to_all']
|
||||
if minutes_sp:
|
||||
doc = minutes_sp.document
|
||||
doc.rev = '%02d' % (int(doc.rev)+1)
|
||||
minutes_sp.rev = doc.rev
|
||||
minutes_sp.save()
|
||||
else:
|
||||
sess_time = session.official_timeslotassignment().timeslot.time
|
||||
if session.meeting.type_id=='ietf':
|
||||
name = 'minutes-%s-%s' % (session.meeting.number,
|
||||
session.group.acronym)
|
||||
title = 'Minutes IETF%s: %s' % (session.meeting.number,
|
||||
session.group.acronym)
|
||||
if not apply_to_all:
|
||||
name += '-%s' % (sess_time.strftime("%Y%m%d%H%M"),)
|
||||
title += ': %s' % (sess_time.strftime("%a %H:%M"),)
|
||||
else:
|
||||
name = 'minutes-%s-%s' % (session.meeting.number, sess_time.strftime("%Y%m%d%H%M"))
|
||||
title = 'Minutes %s: %s' % (session.meeting.number, sess_time.strftime("%a %H:%M"))
|
||||
doc = Document.objects.create(
|
||||
name = name,
|
||||
type_id = 'minutes',
|
||||
title = title,
|
||||
group = session.group,
|
||||
rev = '00',
|
||||
)
|
||||
doc.states.add(State.objects.get(type_id='minutes',slug='active'))
|
||||
doc.docalias_set.create(name=doc.name)
|
||||
session.sessionpresentation_set.create(document=doc,rev='00')
|
||||
if apply_to_all:
|
||||
for other_session in sessions:
|
||||
if other_session != session:
|
||||
other_session.sessionpresentation_set.filter(document__type='minutes').delete()
|
||||
other_session.sessionpresentation_set.create(document=doc,rev=doc.rev)
|
||||
filename = '%s-%s%s'% ( doc.name, doc.rev, ext)
|
||||
doc.external_url = filename
|
||||
e = NewRevisionDocEvent.objects.create(doc=doc,time=doc.time,by=request.user.person,type='new_revision',desc='New revision available: %s'%doc.rev,rev=doc.rev)
|
||||
doc.save_with_history([e])
|
||||
# The way this function builds the filename it will never trigger the file delete in handle_file_upload.
|
||||
handle_upload_file(file, filename, session.meeting, 'minutes')
|
||||
return redirect('ietf.meeting.views.session_details',num=num,acronym=session.group.acronym)
|
||||
else:
|
||||
form = UploadMinutesForm(num_sessions)
|
||||
|
||||
return render(request, "meeting/upload_session_minutes.html",
|
||||
{'session': session,
|
||||
'session_number': session_number,
|
||||
'minutes_sp' : minutes_sp,
|
||||
'form': form,
|
||||
})
|
||||
|
||||
VALID_AGENDA_EXTENSIONS = ('.txt','.html','.htm',)
|
||||
# FIXME: This form validation code (based on the secretariat upload code) only looks at filename extensions
|
||||
# It should look at the contents of the files instead.
|
||||
class UploadAgendaForm(forms.Form):
|
||||
file = forms.FileField(label='Agenda file to upload. Note that you can only upload agendas in txt or html formats.')
|
||||
apply_to_all = forms.BooleanField(label='Apply to all group sessions at this meeting',initial=True,required=False)
|
||||
|
||||
def __init__(self, num_sessions, *args, **kwargs):
|
||||
super(UploadAgendaForm, self).__init__(*args, **kwargs)
|
||||
if num_sessions<2:
|
||||
self.fields.pop('apply_to_all')
|
||||
|
||||
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. Requested upload size is %s' % (filesizeformat(settings.SECR_MAX_UPLOAD_SIZE),filesizeformat(file._size)))
|
||||
if os.path.splitext(file.name)[1].lower() not in VALID_AGENDA_EXTENSIONS:
|
||||
raise forms.ValidationError('Only these file types supported for agendas: %s' % ','.join(VALID_AGENDA_EXTENSIONS))
|
||||
return file
|
||||
|
||||
def upload_session_agenda(request, session_id, num):
|
||||
# num is redundant, but we're dragging it along an artifact of where we are in the current URL structure
|
||||
session = get_object_or_404(Session,pk=session_id)
|
||||
|
||||
if not session.can_manage_materials(request.user):
|
||||
return HttpResponseForbidden("You don't have permission to upload an agenda for this session.")
|
||||
if session.is_material_submission_cutoff() and not has_role(request.user, "Secretariat"):
|
||||
return HttpResponseForbidden("The materials cutoff for this session has passed. Contact the secretariat for further action.")
|
||||
|
||||
session_number = None
|
||||
sessions = get_sessions(session.meeting.number,session.group.acronym)
|
||||
num_sessions = len(sessions)
|
||||
if len(sessions) > 1:
|
||||
session_number = 1 + sessions.index(session)
|
||||
|
||||
agenda_sp = session.sessionpresentation_set.filter(document__type='agenda').first()
|
||||
|
||||
if request.method == 'POST':
|
||||
form = UploadAgendaForm(num_sessions,request.POST,request.FILES)
|
||||
if form.is_valid():
|
||||
file = request.FILES['file']
|
||||
_, ext = os.path.splitext(file.name)
|
||||
apply_to_all = True
|
||||
if num_sessions > 1:
|
||||
apply_to_all = form.cleaned_data['apply_to_all']
|
||||
if agenda_sp:
|
||||
doc = agenda_sp.document
|
||||
doc.rev = '%02d' % (int(doc.rev)+1)
|
||||
agenda_sp.rev = doc.rev
|
||||
agenda_sp.save()
|
||||
else:
|
||||
sess_time = session.official_timeslotassignment().timeslot.time
|
||||
if session.meeting.type_id=='ietf':
|
||||
name = 'agenda-%s-%s' % (session.meeting.number,
|
||||
session.group.acronym)
|
||||
title = 'Agenda IETF%s: %s' % (session.meeting.number,
|
||||
session.group.acronym)
|
||||
if not apply_to_all:
|
||||
name += '-%s' % (sess_time.strftime("%Y%m%d%H%M"),)
|
||||
title += ': %s' % (sess_time.strftime("%a %H:%M"),)
|
||||
else:
|
||||
name = 'agenda-%s-%s' % (session.meeting.number, sess_time.strftime("%Y%m%d%H%M"))
|
||||
title = 'Agenda %s: %s' % (session.meeting.number, sess_time.strftime("%a %H:%M"))
|
||||
doc = Document.objects.create(
|
||||
name = name,
|
||||
type_id = 'agenda',
|
||||
title = title,
|
||||
group = session.group,
|
||||
rev = '00',
|
||||
)
|
||||
doc.states.add(State.objects.get(type_id='agenda',slug='active'))
|
||||
doc.docalias_set.create(name=doc.name)
|
||||
session.sessionpresentation_set.create(document=doc,rev='00')
|
||||
if apply_to_all:
|
||||
for other_session in sessions:
|
||||
if other_session != session:
|
||||
other_session.sessionpresentation_set.filter(document__type='agenda').delete()
|
||||
other_session.sessionpresentation_set.create(document=doc,rev=doc.rev)
|
||||
filename = '%s-%s%s'% ( doc.name, doc.rev, ext)
|
||||
doc.external_url = filename
|
||||
e = NewRevisionDocEvent.objects.create(doc=doc,time=doc.time,by=request.user.person,type='new_revision',desc='New revision available: %s'%doc.rev,rev=doc.rev)
|
||||
doc.save_with_history([e])
|
||||
# The way this function builds the filename it will never trigger the file delete in handle_file_upload.
|
||||
handle_upload_file(file, filename, session.meeting, 'agenda')
|
||||
return redirect('ietf.meeting.views.session_details',num=num,acronym=session.group.acronym)
|
||||
else:
|
||||
form = UploadAgendaForm(num_sessions)
|
||||
|
||||
return render(request, "meeting/upload_session_agenda.html",
|
||||
{'session': session,
|
||||
'session_number': session_number,
|
||||
'agenda_sp' : agenda_sp,
|
||||
'form': form,
|
||||
})
|
||||
|
||||
VALID_SLIDE_EXTENSIONS = ('.doc','.docx','.pdf','.ppt','.pptx','.txt') # Note the removal of .zip
|
||||
# FIXME: This form validation code (based on the secretariat upload code) only looks at filename extensions
|
||||
# It should look at the contents of the files instead.
|
||||
class UploadSlidesForm(forms.Form):
|
||||
title = forms.CharField(max_length=255)
|
||||
file = forms.FileField(label='Slides file to upload.')
|
||||
apply_to_all = forms.BooleanField(label='Apply to all group sessions at this meeting',initial=True,required=False)
|
||||
|
||||
def __init__(self, num_sessions, *args, **kwargs):
|
||||
super(UploadSlidesForm, self).__init__(*args, **kwargs)
|
||||
if num_sessions<2:
|
||||
self.fields.pop('apply_to_all')
|
||||
|
||||
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. Requested upload size is %s' % (filesizeformat(settings.SECR_MAX_UPLOAD_SIZE),filesizeformat(file._size)))
|
||||
if os.path.splitext(file.name)[1].lower() not in VALID_SLIDE_EXTENSIONS:
|
||||
raise forms.ValidationError('Only these file types supported for slides: %s' % ','.join(VALID_SLIDE_EXTENSIONS))
|
||||
return file
|
||||
|
||||
def upload_session_slides(request, session_id, num, name):
|
||||
# num is redundant, but we're dragging it along an artifact of where we are in the current URL structure
|
||||
session = get_object_or_404(Session,pk=session_id)
|
||||
if not session.can_manage_materials(request.user):
|
||||
return HttpResponseForbidden("You don't have permission to upload slides for this session.")
|
||||
if session.is_material_submission_cutoff() and not has_role(request.user, "Secretariat"):
|
||||
return HttpResponseForbidden("The materials cutoff for this session has passed. Contact the secretariat for further action.")
|
||||
|
||||
session_number = None
|
||||
sessions = get_sessions(session.meeting.number,session.group.acronym)
|
||||
num_sessions = len(sessions)
|
||||
if len(sessions) > 1:
|
||||
session_number = 1 + sessions.index(session)
|
||||
|
||||
slides = None
|
||||
slides_sp = None
|
||||
if name:
|
||||
slides = Document.objects.filter(name=name).first()
|
||||
if not (slides and slides.type_id=='slides'):
|
||||
raise Http404
|
||||
slides_sp = session.sessionpresentation_set.filter(document=slides).first()
|
||||
|
||||
if request.method == 'POST':
|
||||
form = UploadSlidesForm(num_sessions,request.POST,request.FILES)
|
||||
if form.is_valid():
|
||||
file = request.FILES['file']
|
||||
_, ext = os.path.splitext(file.name)
|
||||
apply_to_all = True
|
||||
if num_sessions > 1:
|
||||
apply_to_all = form.cleaned_data['apply_to_all']
|
||||
if slides_sp:
|
||||
doc = slides_sp.document
|
||||
doc.rev = '%02d' % (int(doc.rev)+1)
|
||||
doc.title = form.cleaned_data['title']
|
||||
slides_sp.rev = doc.rev
|
||||
slides_sp.save()
|
||||
else:
|
||||
title = form.cleaned_data['title']
|
||||
sess_time = session.official_timeslotassignment().timeslot.time
|
||||
if session.meeting.type_id=='ietf':
|
||||
name = 'slides-%s-%s' % (session.meeting.number,
|
||||
session.group.acronym)
|
||||
if not apply_to_all:
|
||||
name += '-%s' % (sess_time.strftime("%Y%m%d%H%M"),)
|
||||
else:
|
||||
name = 'slides-%s-%s' % (session.meeting.number, sess_time.strftime("%Y%m%d%H%M"))
|
||||
name = name + '-' + slugify(title)
|
||||
doc = Document.objects.create(
|
||||
name = name,
|
||||
type_id = 'slides',
|
||||
title = title,
|
||||
group = session.group,
|
||||
rev = '00',
|
||||
)
|
||||
doc.states.add(State.objects.get(type_id='slides',slug='active'))
|
||||
doc.states.add(State.objects.get(type_id='reuse_policy',slug='single'))
|
||||
doc.docalias_set.create(name=doc.name)
|
||||
max_order = session.sessionpresentation_set.filter(document__type='slides').aggregate(Max('order'))['order__max'] or 0
|
||||
session.sessionpresentation_set.create(document=doc,rev=doc.rev,order=max_order+1)
|
||||
if apply_to_all:
|
||||
for other_session in sessions:
|
||||
if other_session != session:
|
||||
max_order = other_session.sessionpresentation_set.filter(document__type='slides').aggregate(Max('order'))['order__max'] or 0
|
||||
other_session.sessionpresentation_set.create(document=doc,rev=doc.rev,order=max_order+1)
|
||||
filename = '%s-%s%s'% ( doc.name, doc.rev, ext)
|
||||
doc.external_url = filename
|
||||
e = NewRevisionDocEvent.objects.create(doc=doc,time=doc.time,by=request.user.person,type='new_revision',desc='New revision available: %s'%doc.rev,rev=doc.rev)
|
||||
doc.save_with_history([e])
|
||||
# The way this function builds the filename it will never trigger the file delete in handle_file_upload.
|
||||
handle_upload_file(file, filename, session.meeting, 'slides')
|
||||
return redirect('ietf.meeting.views.session_details',num=num,acronym=session.group.acronym)
|
||||
else:
|
||||
initial = {}
|
||||
if slides:
|
||||
initial = {'title':slides.title}
|
||||
form = UploadSlidesForm(num_sessions, initial=initial)
|
||||
|
||||
return render(request, "meeting/upload_session_slides.html",
|
||||
{'session': session,
|
||||
'session_number': session_number,
|
||||
'slides_sp' : slides_sp,
|
||||
'form': form,
|
||||
})
|
||||
|
||||
@role_required('Secretariat')
|
||||
def make_schedule_official(request, num, owner, name):
|
||||
|
||||
|
|
|
@ -12,95 +12,115 @@
|
|||
<h2>{% if sessions|length > 1 %}Session {{ forloop.counter }} : {% endif %}{{ session.time }}{% if session.name %} : {{ session.name }}{% endif %}</h2>
|
||||
{% if session.agenda_note %}<h3>{{session.agenda_note}}</h3>{% endif %}
|
||||
|
||||
{% if can_manage_materials %}
|
||||
{% if session.status.slug == 'sched' or session.status.slug == 'schedw' %}
|
||||
<div class="buttonlist">
|
||||
{% if meeting.type.slug == 'interim' and user|has_role:"Secretariat" %}
|
||||
<a class="btn btn-default" href="{% url 'ietf.meeting.views.interim_request_details' number=meeting.number %}">Meeting Details</a>
|
||||
{% endif %}
|
||||
<a class="btn btn-default" href="{% url 'ietf.secr.proceedings.views.upload_unified' meeting_num=session.meeting.number acronym=session.group.acronym %}">
|
||||
Upload/Edit materials
|
||||
</a>
|
||||
<a class="btn btn-default" href="{% url 'ietf.meeting.views.add_session_drafts' session_id=session.pk num=session.meeting.number %}">
|
||||
Link additional drafts to session
|
||||
</a>
|
||||
{% if user|has_role:"Secretariat" %}
|
||||
<a class="btn btn-default" href="{% url 'ietf.meeting.views.upload_session_bluesheets' session_id=session.pk num=session.meeting.number %}">Upload Bluesheets</a>
|
||||
{% endif %}
|
||||
{% if not type_counter.agenda %}
|
||||
<span class="label label-warning">This session does not yet have an agenda</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if can_manage_materials %}
|
||||
{% if session.status.slug == 'sched' or session.status.slug == 'schedw' %}
|
||||
<div class="buttonlist">
|
||||
{% if meeting.type.slug == 'interim' and user|has_role:"Secretariat" %}
|
||||
<a class="btn btn-default" href="{% url 'ietf.meeting.views.interim_request_details' number=meeting.number %}">Meeting Details</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if not session.type_counter.agenda %}
|
||||
<span class="label label-warning">This session does not yet have an agenda</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if session.filtered_artifacts %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Artifacts</div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-condensed table-striped">
|
||||
{% for pres in session.filtered_artifacts %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if pres.rev %}
|
||||
{% url 'doc_view' name=pres.document.name rev=pres.rev as url %}
|
||||
{% else %}
|
||||
{% url 'doc_view' name=pres.document.name as url %}
|
||||
{% endif %}
|
||||
<a href="{{url}}">{{pres.document.title}} ({{ pres.document.name }}{% if pres.rev %}-{{ pres.rev }}{% endif %})
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Artifacts</div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-condensed table-striped">
|
||||
{% for pres in session.filtered_artifacts %}
|
||||
<tr>
|
||||
{% if pres.rev %}
|
||||
{% url 'doc_view' name=pres.document.name rev=pres.rev as url %}
|
||||
{% else %}
|
||||
{% url 'doc_view' name=pres.document.name as url %}
|
||||
{% endif %}
|
||||
<td>
|
||||
<a href="{{url}}">{{pres.document.title}} ({{ pres.document.name }}{% if pres.rev %}-{{ pres.rev }}{% endif %})</a>
|
||||
</td>
|
||||
{% if user|has_role:"Secretariat" or can_manage_materials %}
|
||||
<td class="col-md-2">
|
||||
{% if pres.document.type.slug == 'minutes' %}
|
||||
{% url 'ietf.meeting.views.upload_session_minutes' session_id=session.pk num=session.meeting.number as upload_url %}
|
||||
{% elif pres.document.type.slug == 'agenda' %}
|
||||
{% url 'ietf.meeting.views.upload_session_agenda' session_id=session.pk num=session.meeting.number as upload_url %}
|
||||
{% else %}
|
||||
{% url 'ietf.meeting.views.upload_session_bluesheets' session_id=session.pk num=session.meeting.number as upload_url %}
|
||||
{% endif %}
|
||||
{% if pres.document.type.slug != 'bluesheets' or user|has_role:"Secretariat" %}
|
||||
<a class="btn btn-default btn-sm pull-right" href="{{upload_url}}">Upload Revision</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% if can_manage_materials %}
|
||||
{% if not session.type_counter.agenda %}
|
||||
<a class="btn btn-default pull-right" href="{% url 'ietf.meeting.views.upload_session_agenda' session_id=session.pk num=session.meeting.number %}">Upload Agenda</a>
|
||||
{% endif %}
|
||||
{% if not session.type_counter.minutes %}
|
||||
<a class="btn btn-default pull-right" href="{% url 'ietf.meeting.views.upload_session_minutes' session_id=session.pk num=session.meeting.number %}">Upload Minutes</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if session.filtered_slides %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Slides</div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-condensed table-striped">
|
||||
{% for pres in session.filtered_slides %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if pres.rev %}
|
||||
{% url 'doc_view' name=pres.document.name rev=pres.rev as url %}
|
||||
{% else %}
|
||||
{% url 'doc_view' name=pres.document.name as url %}
|
||||
{% endif %}
|
||||
<a href="{{url}}">{{pres.document.title}} ({{ pres.document.name }}{% if pres.rev %}-{{ pres.rev }}{% endif %})
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% if user|has_role:"Secretariat" and not session.type_counter.bluesheets %}
|
||||
<a class="btn btn-default pull-right" href="{% url 'ietf.meeting.views.upload_session_bluesheets' session_id=session.pk num=session.meeting.number %}">Upload Bluesheets</a>
|
||||
{% endif %}
|
||||
{% if session.filtered_drafts %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Drafts</div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-condensed table-striped">
|
||||
{% for pres in session.filtered_drafts %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if pres.rev %}
|
||||
{% url 'doc_view' name=pres.document.name rev=pres.rev as url %}
|
||||
{% else %}
|
||||
{% url 'doc_view' name=pres.document.name as url %}
|
||||
{% endif %}
|
||||
<a href="{{url}}">{{pres.document.title}} ({{ pres.document.name }}{% if pres.rev %}-{{ pres.rev }}{% endif %})
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Slides</div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-condensed table-striped">
|
||||
{% for pres in session.filtered_slides %}
|
||||
<tr>
|
||||
{% if pres.rev %}
|
||||
{% url 'doc_view' name=pres.document.name rev=pres.rev as url %}
|
||||
{% else %}
|
||||
{% url 'doc_view' name=pres.document.name as url %}
|
||||
{% endif %}
|
||||
<td>
|
||||
<a href="{{url}}">{{pres.document.title}} ({{ pres.document.name }}{% if pres.rev %}-{{ pres.rev }}{% endif %}) </a>
|
||||
</td>
|
||||
{% if can_manage_materials %}
|
||||
<td class="col-md-2">
|
||||
<a class="btn btn-default btn-sm pull-right" href="{% url 'ietf.meeting.views.upload_session_slides' session_id=session.pk num=session.meeting.number name=pres.document.name %}">Upload Revision</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% if can_manage_materials %}
|
||||
<a class="btn btn-default pull-right" href="{% url 'ietf.meeting.views.upload_session_slides' session_id=session.pk num=session.meeting.number %}">Upload New Slides</a>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Drafts
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-condensed table-striped">
|
||||
{% for pres in session.filtered_drafts %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if pres.rev %}
|
||||
{% url 'doc_view' name=pres.document.name rev=pres.rev as url %}
|
||||
{% else %}
|
||||
{% url 'doc_view' name=pres.document.name as url %}
|
||||
{% endif %}
|
||||
<a href="{{url}}">{{pres.document.title}} ({{ pres.document.name }}{% if pres.rev %}-{{ pres.rev }}{% endif %})</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% if can_manage_materials %}
|
||||
<a class="btn btn-default pull-right" href="{% url 'ietf.meeting.views.add_session_drafts' session_id=session.pk num=session.meeting.number %}">
|
||||
Link additional drafts to session
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
22
ietf/templates/meeting/upload_session_agenda.html
Normal file
22
ietf/templates/meeting/upload_session_agenda.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin staticfiles bootstrap3 %}
|
||||
|
||||
{% block title %}{% if agenda_sp %}Revise{% else %}Upload{% endif %} Agenda for {{ session.meeting }} : {{ session.group.acronym }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
|
||||
<h1>{% if agenda_sp %}Revise{% else %}Upload{% endif %} Agenda for {{ session.meeting }} : {{ session.group.acronym }}{% if session.name %} : {{session.name}}{% endif %}</h1>
|
||||
{% if session_number %}<h2> Session {{session_number}} : {{session.official_timeslotassignment.timeslot.time|date:"D M-d-Y Hi"}}</h2>{% endif %}
|
||||
|
||||
<form enctype="multipart/form-data" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">Upload</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
|
||||
|
||||
{% endblock %}
|
|
@ -2,22 +2,14 @@
|
|||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin staticfiles bootstrap3 %}
|
||||
|
||||
{% block title %}Upload Bluesheets for {{ session.meeting }} : {{ session.group.acronym }}{% endblock %}
|
||||
{% block title %}{% if bluesheet_sp %}Revise{% else %}Upload{% endif %} Bluesheets for {{ session.meeting }} : {{ session.group.acronym }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
|
||||
<h1>Upload Bluesheets for {{ session.meeting }} : {{ session.group.acronym }}{% if session.name %} : {{session.name}}{% endif %}</h1>
|
||||
<h1>{% if bluesheet_sp %}Revise{% else %}Upload{% endif %} Bluesheets for {{ session.meeting }} : {{ session.group.acronym }}{% if session.name %} : {{session.name}}{% endif %}</h1>
|
||||
{% if session_number %}<h2> Session {{session_number}} : {{session.official_timeslotassignment.timeslot.time|date:"D M-d-Y Hi"}}</h2>{% endif %}
|
||||
|
||||
{% if bluesheet_sp %}
|
||||
<div class="alert alert-warning">
|
||||
Bluesheets have alrady been uploaded for this session.
|
||||
See <a href="{% url 'ietf.doc.views_doc.document_main' name=bluesheet_sp.document.name %}">{{bluesheet_sp.document.name}}-{{bluesheet_sp.document.rev}}</a>.
|
||||
Continue with this upload to provide an updated version of that document.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form enctype="multipart/form-data" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
|
|
22
ietf/templates/meeting/upload_session_minutes.html
Normal file
22
ietf/templates/meeting/upload_session_minutes.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin staticfiles bootstrap3 %}
|
||||
|
||||
{% block title %}{% if minutes_sp %}Revise{% else %}Upload{% endif %} Minutes for {{ session.meeting }} : {{ session.group.acronym }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
|
||||
<h1>{% if minutes_sp %}Revise{% else %}Upload{% endif %} Minutes for {{ session.meeting }} : {{ session.group.acronym }}{% if session.name %} : {{session.name}}{% endif %}</h1>
|
||||
{% if session_number %}<h2> Session {{session_number}} : {{session.official_timeslotassignment.timeslot.time|date:"D M-d-Y Hi"}}</h2>{% endif %}
|
||||
|
||||
<form enctype="multipart/form-data" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">Upload</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
|
||||
|
||||
{% endblock %}
|
23
ietf/templates/meeting/upload_session_slides.html
Normal file
23
ietf/templates/meeting/upload_session_slides.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin staticfiles bootstrap3 %}
|
||||
|
||||
{% block title %}{% if slides_sp %}Revise{% else %}Upload New{% endif %} Slides for {{ session.meeting }} : {{ session.group.acronym }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
|
||||
<h1>{% if slides_sp %}Revise{% else %}Upload New{% endif %} Slides for {{ session.meeting }} : {{ session.group.acronym }}{% if session.name %} : {{session.name}}{% endif %}</h1>
|
||||
{% if session_number %}<h2> Session {{session_number}} : {{session.official_timeslotassignment.timeslot.time|date:"D M-d-Y Hi"}}</h2>{% endif %}
|
||||
{% if slides_sp %}<h3>{{slides_sp.document.name}}</h3>{% endif %}
|
||||
|
||||
<form enctype="multipart/form-data" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">Upload</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in a new issue