From 8c82fef683a83e56df961b27438a326e9ce7f26b Mon Sep 17 00:00:00 2001 From: Ryan Cross <rcross@amsl.com> Date: Sat, 31 Oct 2015 09:00:15 +0000 Subject: [PATCH] Add more information to Secretariat session recordings view. Commit ready for merge - Legacy-Id: 10348 --- ietf/meeting/models.py | 3 ++ ietf/secr/proceedings/tests.py | 18 ++++--- ietf/secr/proceedings/views.py | 25 ++++++++-- ietf/secr/static/secr/css/custom.css | 4 ++ .../secr/templates/proceedings/recording.html | 50 +++++++++++++------ 5 files changed, 76 insertions(+), 24 deletions(-) diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index cadf19421..0629d9155 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -928,6 +928,9 @@ class Session(models.Model): def minutes(self): return self.get_material("minutes", only_one=True) + def recordings(self): + return list(self.get_material("recording", only_one=False)) + def slides(self): return list(self.get_material("slides", only_one=False)) diff --git a/ietf/secr/proceedings/tests.py b/ietf/secr/proceedings/tests.py index 640d43188..90438fc89 100644 --- a/ietf/secr/proceedings/tests.py +++ b/ietf/secr/proceedings/tests.py @@ -14,6 +14,7 @@ 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.name.models import SessionStatusName from ietf.secr.utils.meeting import get_proceedings_path SECR_USER='secretary' @@ -27,19 +28,23 @@ class MainTestCase(TestCase): response = self.client.get(url) self.assertEqual(response.status_code, 200) + class RecordingTestCase(TestCase): def test_page(self): - make_test_data() - meeting = Meeting.objects.first() + meeting = make_meeting_test_data() url = reverse('proceedings_recording', kwargs={'meeting_num':meeting.number}) self.client.login(username="secretary", password="secretary+password") response = self.client.get(url) self.assertEqual(response.status_code, 200) + def test_post(self): - make_meeting_test_data() - meeting = Meeting.objects.first() + meeting = make_meeting_test_data() group = Group.objects.get(acronym='mars') - session = Session.objects.filter(meeting=meeting,group=group,status__in=('sched','schedw')).first() + session = Session.objects.filter(meeting=meeting,group=group).first() + # explicitly set to scheduled for this test + status = SessionStatusName.objects.get(slug='sched') + session.status = status + session.save() url = reverse('proceedings_recording', kwargs={'meeting_num':meeting.number}) data = dict(group=group.acronym,external_url='http://youtube.com/xyz',session=session.pk) self.client.login(username="secretary", password="secretary+password") @@ -54,7 +59,8 @@ class RecordingTestCase(TestCase): 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) - + + class BluesheetTestCase(TestCase): def setUp(self): self.proceedings_dir = os.path.abspath("tmp-proceedings-dir") diff --git a/ietf/secr/proceedings/views.py b/ietf/secr/proceedings/views.py index 4ab2ef51f..db1ce6e73 100644 --- a/ietf/secr/proceedings/views.py +++ b/ietf/secr/proceedings/views.py @@ -75,6 +75,21 @@ def get_doc_filename(doc): # TODO we might want to choose from among multiple files using some logic return files[0] +def get_unmatched_recordings(meeting): + ''' + Returns a list of recording filenames that haven't been matched to a session + ''' + unmatched_recordings = [] + path = os.path.join(settings.MEETING_RECORDINGS_DIR,'ietf{}'.format(meeting.number)) + try: + files = os.listdir(path) + except OSError: + files = [] + for file in files: + if not Document.objects.filter(external_url__endswith=file).exists(): + unmatched_recordings.append(file) + return unmatched_recordings + def get_extras(meeting): ''' Gather "extras" which are one off groups. ie iab-wcit(86) @@ -608,10 +623,13 @@ def progress_report(request, meeting_num): @role_required('Secretariat') def recording(request, meeting_num): ''' - Enter Session recording info. Creates Document and associates it with Session + Enter Session recording info. Creates Document and associates it with Session. + For auditing purposes, lists all scheduled sessions and associated recordings, if + any. Also lists those audio recording files which haven't been matched to a + session. ''' meeting = get_object_or_404(Meeting, number=meeting_num) - recordings = Document.objects.filter(name__startswith='recording-{}'.format(meeting.number),states__slug='active').order_by('group__acronym') + sessions = meeting.session_set.filter(type='session',status='sched').order_by('group__acronym') if request.method == 'POST': form = RecordingForm(request.POST) @@ -638,7 +656,8 @@ def recording(request, meeting_num): return render_to_response('proceedings/recording.html',{ 'meeting':meeting, 'form':form, - 'recordings':recordings}, + 'sessions':sessions, + 'unmatched_recordings': get_unmatched_recordings(meeting)}, RequestContext(request, {}), ) diff --git a/ietf/secr/static/secr/css/custom.css b/ietf/secr/static/secr/css/custom.css index 76b284ae6..5d609f24b 100644 --- a/ietf/secr/static/secr/css/custom.css +++ b/ietf/secr/static/secr/css/custom.css @@ -583,6 +583,10 @@ td.hidden { display: none; } +td.document-name { + white-space: nowrap; +} + /* ========================================================================== Role Tool ========================================================================== */ diff --git a/ietf/secr/templates/proceedings/recording.html b/ietf/secr/templates/proceedings/recording.html index 56c39c8e7..3918eee04 100755 --- a/ietf/secr/templates/proceedings/recording.html +++ b/ietf/secr/templates/proceedings/recording.html @@ -43,9 +43,9 @@ </div> <!-- button-group --> </form> + <div class="inline-related"> - <h2>{{ meeting }} - Recordings - </h2> + <h2>{{ meeting }} - Recordings</h2> <table class="center"> <thead> <tr> @@ -57,27 +57,47 @@ </tr> </thead> <tbody> - {% for record in recordings %} + {% for session in sessions %} <tr> - <td>{{ record.group.acronym }}</td> - <td>{{ record.session_set.first.official_scheduledsession.timeslot.time|date:"m-d H:i" }}</td> - <td>{{ record.name }}</td> - <td><a href="{{ record.href }}">{{ record.href }}</a></td> - <td><a href="{% url "proceedings_recording_edit" meeting_num=meeting.number name=record.name %}">Edit</a></td> + <td>{{ session.group.acronym }}</td> + <td>{{ session.official_timeslotassignment.timeslot.time|date:"m-d H:i" }}</td> + {% if session.recordings %} + <td class="document-name" >{{ session.recordings.0.name }}</td> + <td><a href="{{ session.recordings.first.href }}">{{ session.recordings.0.href }}</a></td> + <td><a href="{% url "proceedings_recording_edit" meeting_num=meeting.number name=session.recordings.0.name %}">Edit</a></td> + {% else %} + <td></td> + <td></td> + <td></td> + {% endif %} </tr> {% endfor %} </tbody> </table> - </div> <!-- inline-group --> + + {% if unmatched_recordings %} + <div class="inline-related"> + <h2>Unmatched Recording Files</h2> + <table class="center"> + <thead> + <tr> + <th>Filename</th> + </tr> + </thead> + <tbody> + {% for file in unmatched_recordings %} + <tr> + <td>{{ file }}</td> + </tr> + {% endfor %} + </tbody> + </table> + </div> <!-- inline-group --> + {% endif %} + </div> <!-- module --> -{% if docevents %} - <br> - <div class="module interim-container"> - {% include "includes/docevents.html" %} - </div> -{% endif %} {% endblock %}