Skip to content

Commit

Permalink
Changes to allow upload of bluesheets in materials upload page. Prima…
Browse files Browse the repository at this point in the history
…rily for use with Interim meetings. Commit ready for merge.

 - Legacy-Id: 8861
  • Loading branch information
rpcross committed Jan 12, 2015
2 parents f90e802 + e686c5c commit 40efbf4
Show file tree
Hide file tree
Showing 13 changed files with 659 additions and 66 deletions.
10 changes: 5 additions & 5 deletions ietf/doc/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ def get_file_path(self):

if self.type_id == "draft":
return settings.INTERNET_DRAFT_PATH
elif self.type_id in ("agenda", "minutes", "slides") and self.meeting_related():
meeting = self.name.split("-")[1]
return os.path.join(settings.AGENDA_PATH, meeting, self.type_id) + "/"
elif self.type_id in ("agenda", "minutes", "slides", "bluesheets") and self.meeting_related():
meeting = self.session_set.first().meeting
return os.path.join(meeting.get_materials_path(), self.type_id) + "/"
elif self.type_id == "charter":
return settings.CHARTER_PATH
elif self.type_id == "conflrev":
Expand Down Expand Up @@ -186,7 +186,7 @@ def active_ballot(self):
return None

def meeting_related(self):
if self.type_id in ("agenda","minutes",):
if self.type_id in ("agenda","minutes","bluesheets"):
return (self.name.split("-")[1] == "interim"
or (self.session_set.exists() if isinstance(self, Document) else self.doc.session_set.exists()))
elif self.type_id in ("slides",):
Expand Down Expand Up @@ -286,7 +286,7 @@ def get_absolute_url(self):
name = self.name
if self.type_id == "draft" and self.get_state_slug() == "rfc":
name = self.canonical_name()
elif self.type_id in ('slides','agenda','minutes'):
elif self.type_id in ('slides','agenda','minutes','bluesheets'):
session = self.session_set.first()
if session:
meeting = session.meeting
Expand Down
13 changes: 13 additions & 0 deletions ietf/meeting/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ def get_ietf_monday(cls):
date = cls.objects.all().filter(type="ietf").order_by('-date')[0].date
return date + datetime.timedelta(days=-date.weekday(), weeks=1)

def get_materials_path(self):
path = ''
if self.type_id == 'ietf':
path = os.path.join(settings.AGENDA_PATH,self.number)
elif self.type_id == 'interim':
path = os.path.join(settings.AGENDA_PATH,
'interim',
self.date.strftime('%Y'),
self.date.strftime('%m'),
self.date.strftime('%d'),
self.session_set.all()[0].group.acronym)
return path

# the various dates are currently computed
def get_submission_start_date(self):
return self.date + datetime.timedelta(days=settings.SUBMISSION_START_DAYS)
Expand Down
43 changes: 43 additions & 0 deletions ietf/name/fixtures/names.json
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,16 @@
"desc": ""
}
},
{
"pk": "bluesheets",
"model": "name.doctypename",
"fields": {
"order": 0,
"used": true,
"name": "Bluesheets",
"desc": ""
}
},
{
"pk": "uploaded",
"model": "name.draftsubmissionstatename",
Expand Down Expand Up @@ -1905,6 +1915,13 @@
"label": "Recording State"
}
},
{
"pk": "bluesheets",
"model": "doc.statetype",
"fields": {
"label": "Bluesheet State"
}
},
{
"pk": 81,
"model": "doc.state",
Expand Down Expand Up @@ -3800,6 +3817,32 @@
"desc": "The RFC status changes have been abandoned"
}
},
{
"pk": 137,
"model": "doc.state",
"fields": {
"used": true,
"name": "Active",
"next_states": [],
"slug": "active",
"type": "bluesheets",
"order": 0,
"desc": ""
}
},
{
"pk": 138,
"model": "doc.state",
"fields": {
"used": true,
"name": "Deleted",
"next_states": [],
"slug": "deleted",
"type": "bluesheets",
"order": 1,
"desc": ""
}
},
{
"pk": 5,
"model": "doc.ballottype",
Expand Down
471 changes: 471 additions & 0 deletions ietf/name/migrations/0030_add_doctype.py

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions ietf/secr/proceedings/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
VALID_SLIDE_EXTENSIONS = ('.doc','.docx','.pdf','.ppt','.pptx','.txt','.zip')
VALID_MINUTES_EXTENSIONS = ('.txt','.html','.htm','.pdf')
VALID_AGENDA_EXTENSIONS = ('.txt','.html','.htm')
VALID_BLUESHEET_EXTENSIONS = ('.pdf','.jpg','.jpeg')

#----------------------------------------------------------
# Forms
Expand Down Expand Up @@ -100,7 +101,7 @@ def clean_file(self):
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(name__in=('minutes','agenda','slides')),empty_label=None)
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='<div id="id_file_help">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.<br><br>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.</div>')

Expand Down Expand Up @@ -128,7 +129,7 @@ def clean(self):
#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 (presentation,agenda,minutes)
# 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
Expand All @@ -138,7 +139,9 @@ def clean(self):
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


32 changes: 18 additions & 14 deletions ietf/secr/proceedings/proc_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def create_recording(session,meeting,group,url):
desc='New revision available',
time=doc.time)
session.sessionpresentation_set.add(SessionPresentation(session=session,document=doc,rev=doc.rev))

def mycomp(timeslot):
'''
This takes a timeslot object and returns a key to sort by the area acronym or None
Expand Down Expand Up @@ -330,20 +330,24 @@ def create_proceedings(meeting, group, is_final=False):
updated_list = ['RFC %s' % get_rfc_num(x.source) for x in rdocs.filter(relationship='updates')]
if updated_list:
rfc.msg += 'updated by ' + ','.join(updated_list)
# ----------------------------------------------------------------------
# check for blue sheets
pattern = os.path.join(meeting_root,'bluesheets','bluesheets-%s-%s-*' % (meeting.number,group.acronym.lower()))
files = glob.glob(pattern)
bluesheets = []
for name in files:
basename = os.path.basename(name)
obj = {'name': basename,
'url': url_root + "bluesheets/" + basename}
bluesheets.append(obj)
bluesheets = sorted(bluesheets, key = lambda x: x['name'])
# ----------------------------------------------------------------------
else:
drafts = rfcs = bluesheets = None
drafts = rfcs = None

# ----------------------------------------------------------------------
# check for blue sheets
if meeting.number.startswith('interim'):
pattern = os.path.join(meeting_root,'bluesheets','bluesheets-%s*' % (meeting.number))
else:
pattern = os.path.join(meeting_root,'bluesheets','bluesheets-%s-%s-*' % (meeting.number,group.acronym.lower()))
files = glob.glob(pattern)
bluesheets = []
for name in files:
basename = os.path.basename(name)
obj = {'name': basename,
'url': url_root + "bluesheets/" + basename}
bluesheets.append(obj)
bluesheets = sorted(bluesheets, key = lambda x: x['name'])


# the simplest way to display the charter is to place it in a <pre> block
# however, because this forces a fixed-width font, different than the rest of
Expand Down
47 changes: 46 additions & 1 deletion ietf/secr/proceedings/tests.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import debug # pyflakes:ignore
import os
import shutil

from StringIO import StringIO

from django.core.urlresolvers import reverse
from django.conf import settings

from ietf.doc.models import Document
from ietf.group.models import Group
from ietf.meeting.models import Meeting, 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

from ietf.secr.utils.meeting import get_proceedings_path

SECR_USER='secretary'

class MainTestCase(TestCase):
Expand Down Expand Up @@ -45,4 +53,41 @@ def test_post(self):
url = reverse('proceedings_recording_edit', kwargs={'meeting_num':meeting.number,'name':doc.name})
response = self.client.post(url,dict(external_url=external_url),follow=True)
self.assertEqual(response.status_code, 200)
self.failUnless(external_url in response.content)
self.failUnless(external_url in response.content)

class BluesheetTestCase(TestCase):
def setUp(self):
self.proceedings_dir = os.path.abspath("tmp-proceedings-dir")
os.mkdir(self.proceedings_dir)
settings.AGENDA_PATH = self.proceedings_dir

self.interim_listing_dir = os.path.abspath("tmp-interim-listing-dir")
os.mkdir(self.interim_listing_dir)
settings.SECR_INTERIM_LISTING_DIR = self.interim_listing_dir

def tearDown(self):
shutil.rmtree(self.proceedings_dir)
shutil.rmtree(self.interim_listing_dir)

def test_upload(self):
make_test_data()
meeting = Meeting.objects.filter(type='interim').first()
group = Group.objects.get(acronym='mars')
Session.objects.create(meeting=meeting,group=group,requested_by_id=1,status_id='sched')
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 r.content)
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 in data)

48 changes: 16 additions & 32 deletions ietf/secr/proceedings/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@
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_upload_root, get_materials, get_timeslot
from ietf.secr.utils.meeting import get_upload_root, get_materials, get_timeslot, get_proceedings_path, get_proceedings_url
from ietf.doc.models import Document, DocAlias, DocEvent, State, NewRevisionDocEvent
from ietf.group.models import Group
from ietf.ietfauth.utils import has_role, role_required
from ietf.meeting.models import Meeting, Session, TimeSlot, ScheduledSession, SessionPresentation
from ietf.secr.proceedings.forms import EditSlideForm, InterimMeetingForm, RecordingForm, RecordingEditForm, ReplaceSlideForm, UnifiedUploadForm
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_interim_directory, create_recording )
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_interim_directory,
create_recording )

from ietf.secr.proceedings.models import InterimMeeting # proxy model

Expand Down Expand Up @@ -137,27 +138,6 @@ def get_next_order_num(session):

return max_order + 1 if max_order else 1

# --- These could be properties/methods on meeting
def get_proceedings_path(meeting,group):
if meeting.type_id == 'ietf':
path = os.path.join(get_upload_root(meeting),group.acronym + '.html')
elif meeting.type_id == 'interim':
path = os.path.join(get_upload_root(meeting),'proceedings.html')
return path

def get_proceedings_url(meeting,group=None):
if meeting.type_id == 'ietf':
url = "%sproceedings/%s/" % (settings.MEDIA_URL,meeting.number)
if group:
url = url + "%s.html" % group.acronym

elif meeting.type_id == 'interim':
url = "%sproceedings/interim/%s/%s/proceedings.html" % (
settings.MEDIA_URL,
meeting.date.strftime('%Y/%m/%d'),
group.acronym)
return url

def handle_upload_file(file,filename,meeting,subdir):
'''
This function takes a file object, a filename and a meeting object and subdir as string.
Expand All @@ -173,6 +153,8 @@ def handle_upload_file(file,filename,meeting,subdir):
os.mkdir(path)
else:
path = os.path.join(get_upload_root(meeting),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'):
Expand Down Expand Up @@ -324,7 +306,7 @@ def build(request,meeting_num,acronym):
meeting = Meeting.objects.get(number=meeting_num)
group = get_object_or_404(Group,acronym=acronym)

create_proceedings(meeting,group)
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})
Expand Down Expand Up @@ -877,8 +859,8 @@ def redirection_back(meeting, group):
session = sessions[0]
session_name = ''
elif session_id:
sessions = None
session = get_object_or_404(Session, id=int(session_id))
sessions = [session]
group = session.group
session_name = session.name

Expand Down Expand Up @@ -945,11 +927,13 @@ def redirection_back(meeting, group):

# create session relationship, per Henrik we should associate documents to all sessions
# for the current meeting (until tools support different materials for diff sessions)
if sessions:
for s in sessions:
s.sessionpresentation_set.add(SessionPresentation(session=s,document=doc,rev=doc.rev))
else:
session.sessionpresentation_set.add(SessionPresentation(session=session,document=doc,rev=doc.rev))
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
NewRevisionDocEvent.objects.create(type='new_revision',
Expand Down
4 changes: 1 addition & 3 deletions ietf/secr/rolodex/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def add(request):

# search to see if contact already exists
name = form.cleaned_data['name']
results = Person.objects.filter(name=name)
results = Alias.objects.filter(name=name)
if not results:
return HttpResponseRedirect('../add-proceed/')

Expand Down Expand Up @@ -236,11 +236,9 @@ def search(request):
#kwargs['email__address__istartswith'] = email
kwargs['person__email__address__istartswith'] = email
if id:
#kwargs['id'] = id
kwargs['person__id'] = id
# perform query
if kwargs:
#qs = Person.objects.filter(**kwargs)
qs = Alias.objects.filter(**kwargs).distinct()

results = qs.order_by('name')
Expand Down
6 changes: 3 additions & 3 deletions ietf/secr/templates/proceedings/proceedings.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ <h3>Technical Advisor(s)</h3>
<br /><br /></td></tr></table>

<h3>Recordings:</h3>
{% if materials.record %}
{% if materials.recording %}
<ul>
{% for record in materials.record %}
<li><a href="{{ record.href }}" target="_blank">{{ record.title }}</a></li>
{% for recording in materials.recording %}
<li><a href="{{ recording.href }}" target="_blank">{{ recording.title }}</a></li>
{% endfor %}
</ul>
{% else %}
Expand Down
Loading

0 comments on commit 40efbf4

Please sign in to comment.