Merged in [11778] from rjsparks@nostrum.com:
Enabled and refined document_main view for bluesheets. Improved migration for 95 and 96 bluesheets, adding DocAlias and DocEvent creation. Added bluesheet upload to the session details view. Moved a function out of secr/proceedings/views into its own util.py file to allow reusing it in other modules without introducing circular imports. - Legacy-Id: 11811 Note: SVN reference [11778] has been migrated to Git commit 0611444b36bc071e8db068a093cc1ad93bb69659
This commit is contained in:
parent
3fee46cafb
commit
6f05b23837
|
@ -521,7 +521,7 @@ def document_main(request, name, rev=None):
|
|||
|
||||
# TODO : Add "recording", and "bluesheets" here when those documents are appropriately
|
||||
# created and content is made available on disk
|
||||
if doc.type_id in ("slides", "agenda", "minutes"):
|
||||
if doc.type_id in ("slides", "agenda", "minutes", "bluesheets",):
|
||||
can_manage_material = can_manage_materials(request.user, doc.group)
|
||||
presentations = doc.future_presentations()
|
||||
if doc.meeting_related():
|
||||
|
@ -540,7 +540,7 @@ def document_main(request, name, rev=None):
|
|||
for g in globs:
|
||||
extension = os.path.splitext(g)[1]
|
||||
t = os.path.splitext(g)[1].lstrip(".")
|
||||
url = doc.href()
|
||||
url = doc.get_absolute_url() if doc.type_id=='bluesheets' else doc.href()
|
||||
urlbase, urlext = os.path.splitext(url)
|
||||
if not url.endswith("/") and not url.endswith(extension):
|
||||
url = urlbase + extension
|
||||
|
|
|
@ -12,6 +12,7 @@ def official_time(session):
|
|||
|
||||
def forward(apps, schema_editor):
|
||||
Document = apps.get_model('doc','Document')
|
||||
NewRevisionDocEvent = apps.get_model('doc','NewRevisionDocEvent')
|
||||
State = apps.get_model('doc','State')
|
||||
Group = apps.get_model('group','Group')
|
||||
Meeting = apps.get_model('meeting', 'Meeting')
|
||||
|
@ -46,12 +47,14 @@ def forward(apps, schema_editor):
|
|||
doc = Document.objects.create(
|
||||
name=bs[n][:-4],
|
||||
type_id='bluesheets',
|
||||
title='Bluesheets IETF%d : %s : %s ' % (num,acronym,official_time(sess[n]).timeslot.time.strftime('%a %H:%M')),
|
||||
title='Bluesheets IETF%d : %s : %s' % (num,acronym,official_time(sess[n]).timeslot.time.strftime('%a %H:%M')),
|
||||
group=group,
|
||||
rev='00',
|
||||
external_url=bs[n],
|
||||
)
|
||||
doc.states.add(active)
|
||||
doc.docalias_set.create(name=doc.name)
|
||||
NewRevisionDocEvent.objects.create(doc=doc,time=doc.time,by_id=1,type='new_revision',desc='New revision available: %s'%doc.rev,rev=doc.rev)
|
||||
sess[n].sessionpresentation_set.create(document=doc,rev='00')
|
||||
|
||||
def reverse(apps, schema_editor):
|
||||
|
|
|
@ -12,6 +12,7 @@ from django.conf import settings
|
|||
from django.contrib.auth.models import User
|
||||
|
||||
from pyquery import PyQuery
|
||||
from StringIO import StringIO
|
||||
|
||||
from ietf.doc.models import Document
|
||||
from ietf.group.models import Group
|
||||
|
@ -1198,3 +1199,45 @@ 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):
|
||||
def test_upload_blusheets(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.assertFalse(session.sessionpresentation_set.exists())
|
||||
test_file = StringIO('this is some text for a test')
|
||||
test_file.name = "not_really.pdf"
|
||||
r = self.client.post(url,dict(file=test_file))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
bs_doc = session.sessionpresentation_set.filter(document__type_id='bluesheets').first().document
|
||||
self.assertEqual(bs_doc.rev,'00')
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(q("div.alert"))
|
||||
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))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
bs_doc = Document.objects.get(pk=bs_doc.pk)
|
||||
self.assertEqual(bs_doc.rev,'01')
|
||||
|
||||
def test_upload_bluesheets_interim(self):
|
||||
session=SessionFactory(meeting__type_id='interim')
|
||||
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.assertFalse(session.sessionpresentation_set.exists())
|
||||
test_file = StringIO('this is some text for a test')
|
||||
test_file.name = "not_really.pdf"
|
||||
r = self.client.post(url,dict(file=test_file))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
bs_doc = session.sessionpresentation_set.filter(document__type_id='bluesheets').first().document
|
||||
self.assertEqual(bs_doc.rev,'00')
|
||||
|
|
|
@ -9,6 +9,7 @@ from ietf.meeting import ajax
|
|||
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),
|
||||
]
|
||||
|
||||
type_ietf_only_patterns = [
|
||||
|
|
|
@ -51,6 +51,8 @@ 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
|
||||
from ietf.utils.pdf import pdf_pages
|
||||
|
@ -1085,6 +1087,67 @@ def add_session_drafts(request, session_id, num):
|
|||
'form': form,
|
||||
})
|
||||
|
||||
class UploadBlueSheetForm(forms.Form):
|
||||
file = forms.FileField(label='Bluesheet scan to upload')
|
||||
|
||||
@role_required('Secretariat')
|
||||
def upload_session_bluesheets(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)
|
||||
|
||||
session_number = None
|
||||
sessions = get_sessions(session.meeting.number,session.group.acronym)
|
||||
if len(sessions) > 1:
|
||||
session_number = 1 + sessions.index(session)
|
||||
|
||||
bluesheet_sp = session.sessionpresentation_set.filter(document__type='bluesheets').first()
|
||||
|
||||
if request.method == 'POST':
|
||||
form = UploadBlueSheetForm(request.POST,request.FILES)
|
||||
if form.is_valid():
|
||||
file = request.FILES['file']
|
||||
_, ext = os.path.splitext(file.name)
|
||||
if bluesheet_sp:
|
||||
doc = bluesheet_sp.document
|
||||
doc.rev = '%02d' % (int(doc.rev)+1)
|
||||
else:
|
||||
sess_time = session.official_timeslotassignment().timeslot.time
|
||||
if session.meeting.type_id=='ietf':
|
||||
name = 'bluesheets-%s-%s-%s' % (session.meeting.number,
|
||||
session.group.acronym,
|
||||
sess_time.strftime("%Y%m%d%H%M"))
|
||||
title = 'Bluesheets IETF%s: %s : %s' % (session.meeting.number,
|
||||
session.group.acronym,
|
||||
sess_time.strftime("%a %H:%M"))
|
||||
else:
|
||||
name = 'bluesheets-%s-%s' % (session.meeting.number, sess_time.strftime("%Y%m%d%H%M"))
|
||||
title = 'Bluesheets %s: %s' % (session.meeting.number, sess_time.strftime("%a %H:%M"))
|
||||
doc = Document.objects.create(
|
||||
name = name,
|
||||
type_id = 'bluesheets',
|
||||
title = title,
|
||||
group = session.group,
|
||||
rev = '00',
|
||||
)
|
||||
doc.states.add(State.objects.get(type_id='bluesheets',slug='active'))
|
||||
doc.docalias_set.create(name=doc.name)
|
||||
session.sessionpresentation_set.create(document=doc,rev='00')
|
||||
filename = '%s-%s%s'% ( doc.name, doc.rev, ext)
|
||||
doc.external_url = filename
|
||||
doc.save()
|
||||
NewRevisionDocEvent.objects.create(doc=doc,time=doc.time,by=Person.objects.get(name='(System)'),type='new_revision',desc='New revision available: %s'%doc.rev,rev=doc.rev)
|
||||
handle_upload_file(file, filename, session.meeting, 'bluesheets')
|
||||
return redirect('ietf.meeting.views.session_details',num=num,acronym=session.group.acronym)
|
||||
else:
|
||||
form = UploadBlueSheetForm()
|
||||
|
||||
return render(request, "meeting/upload_session_bluesheets.html",
|
||||
{'session': session,
|
||||
'session_number': session_number,
|
||||
'bluesheet_sp' : bluesheet_sp,
|
||||
'form': form,
|
||||
})
|
||||
|
||||
@role_required('Secretariat')
|
||||
def make_schedule_official(request, num, owner, name):
|
||||
|
||||
|
|
39
ietf/secr/proceedings/utils.py
Normal file
39
ietf/secr/proceedings/utils.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
import glob
|
||||
import os
|
||||
|
||||
import debug # pyflakes:ignore
|
||||
|
||||
def handle_upload_file(file,filename,meeting,subdir):
|
||||
'''
|
||||
This function takes a file object, a filename and a meeting object and subdir as string.
|
||||
It saves the file to the appropriate directory, get_materials_path() + subdir.
|
||||
If the file is a zip file, it creates a new directory in 'slides', which is the basename of the
|
||||
zip file and unzips the file in the new directory.
|
||||
'''
|
||||
base, extension = os.path.splitext(filename)
|
||||
|
||||
if extension == '.zip':
|
||||
path = os.path.join(meeting.get_materials_path(),subdir,base)
|
||||
if not os.path.exists(path):
|
||||
os.mkdir(path)
|
||||
else:
|
||||
path = os.path.join(meeting.get_materials_path(),subdir)
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
# agendas and minutes can only have one file instance so delete file if it already exists
|
||||
if subdir in ('agenda','minutes'):
|
||||
old_files = glob.glob(os.path.join(path,base) + '.*')
|
||||
for f in old_files:
|
||||
os.remove(f)
|
||||
|
||||
destination = open(os.path.join(path,filename), 'wb+')
|
||||
for chunk in file.chunks():
|
||||
destination.write(chunk)
|
||||
destination.close()
|
||||
|
||||
# unzip zipfile
|
||||
if extension == '.zip':
|
||||
os.chdir(path)
|
||||
os.system('unzip %s' % filename)
|
||||
|
|
@ -31,6 +31,7 @@ from ietf.secr.proceedings.forms import EditSlideForm, RecordingForm, RecordingE
|
|||
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
|
||||
|
||||
# -------------------------------------------------
|
||||
|
@ -138,40 +139,6 @@ def get_next_order_num(session):
|
|||
|
||||
return max_order + 1 if max_order else 1
|
||||
|
||||
def handle_upload_file(file,filename,meeting,subdir):
|
||||
'''
|
||||
This function takes a file object, a filename and a meeting object and subdir as string.
|
||||
It saves the file to the appropriate directory, get_materials_path() + subdir.
|
||||
If the file is a zip file, it creates a new directory in 'slides', which is the basename of the
|
||||
zip file and unzips the file in the new directory.
|
||||
'''
|
||||
base, extension = os.path.splitext(filename)
|
||||
|
||||
if extension == '.zip':
|
||||
path = os.path.join(meeting.get_materials_path(),subdir,base)
|
||||
if not os.path.exists(path):
|
||||
os.mkdir(path)
|
||||
else:
|
||||
path = os.path.join(meeting.get_materials_path(),subdir)
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
# agendas and minutes can only have one file instance so delete file if it already exists
|
||||
if subdir in ('agenda','minutes'):
|
||||
old_files = glob.glob(os.path.join(path,base) + '.*')
|
||||
for f in old_files:
|
||||
os.remove(f)
|
||||
|
||||
destination = open(os.path.join(path,filename), 'wb+')
|
||||
for chunk in file.chunks():
|
||||
destination.write(chunk)
|
||||
destination.close()
|
||||
|
||||
# unzip zipfile
|
||||
if extension == '.zip':
|
||||
os.chdir(path)
|
||||
os.system('unzip %s' % filename)
|
||||
|
||||
def parsedate(d):
|
||||
'''
|
||||
This function takes a date object and returns a tuple of year,month,day
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
<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 %}
|
||||
|
|
30
ietf/templates/meeting/upload_session_bluesheets.html
Normal file
30
ietf/templates/meeting/upload_session_bluesheets.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin staticfiles bootstrap3 %}
|
||||
|
||||
{% block title %}Upload 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>
|
||||
{% 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 %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">Upload</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in a new issue