From 4801d6efdae4df43b2b0c9980d7db582d076ab67 Mon Sep 17 00:00:00 2001 From: Ryan Cross Date: Tue, 21 Feb 2023 17:49:54 -0800 Subject: [PATCH 1/3] feat: move IETF Activity reports from external text based to HTML pages --- ietf/bin/report_id_activity | 22 ---- ietf/bin/report_progress_report | 24 ---- ietf/iesg/tests.py | 8 +- ietf/iesg/urls.py | 3 +- ietf/iesg/views.py | 49 +++++++- ietf/meeting/tests_views.py | 8 +- ietf/meeting/urls.py | 2 +- ietf/meeting/views.py | 12 +- ietf/secr/proceedings/proc_utils.py | 4 +- ietf/secr/proceedings/reports.py | 106 ------------------ ietf/secr/proceedings/tests_reports.py | 36 ------ .../proceedings/report_id_activity.txt | 21 ---- .../proceedings/report_progress_report.txt | 48 -------- ietf/templates/iesg/ietf_activity_report.html | 25 +++++ ...gress_report.html => activity_report.html} | 36 +++--- .../meeting/proceedings/introduction.html | 2 +- .../meeting/proceedings_activity_report.html | 18 +++ 17 files changed, 126 insertions(+), 298 deletions(-) delete mode 100755 ietf/bin/report_id_activity delete mode 100755 ietf/bin/report_progress_report delete mode 100644 ietf/secr/proceedings/reports.py delete mode 100644 ietf/secr/proceedings/tests_reports.py delete mode 100644 ietf/secr/templates/proceedings/report_id_activity.txt delete mode 100644 ietf/secr/templates/proceedings/report_progress_report.txt create mode 100644 ietf/templates/iesg/ietf_activity_report.html rename ietf/templates/meeting/{proceedings_progress_report.html => activity_report.html} (71%) create mode 100644 ietf/templates/meeting/proceedings_activity_report.html diff --git a/ietf/bin/report_id_activity b/ietf/bin/report_id_activity deleted file mode 100755 index 7fb8ad88ed..0000000000 --- a/ietf/bin/report_id_activity +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -*- Python -*- -# - -# This script requires that the proper virtual python environment has been -# invoked before start - -# Set PYTHONPATH and load environment variables for standalone script ----------------- -import os, sys -basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")) -sys.path = [ basedir ] + sys.path -os.environ["DJANGO_SETTINGS_MODULE"] = "ietf.settings" - -import django -django.setup() -# ------------------------------------------------------------------------------------- - -from ietf.secr.proceedings.reports import report_id_activity - -print(report_id_activity(sys.argv[1], sys.argv[2]), end='') - diff --git a/ietf/bin/report_progress_report b/ietf/bin/report_progress_report deleted file mode 100755 index 9d1dad6186..0000000000 --- a/ietf/bin/report_progress_report +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -*- Python -*- -# - -# This script requires that the proper virtual python environment has been -# invoked before start - -# Set PYTHONPATH and load environment variables for standalone script ----------------- -import os, sys -basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")) -sys.path = [ basedir ] + sys.path -os.environ["DJANGO_SETTINGS_MODULE"] = "ietf.settings" - -import django -django.setup() -# ------------------------------------------------------------------------------------- - -from ietf.secr.proceedings.reports import report_progress_report - -# handle unicode characters before attempting to print -output = report_progress_report(sys.argv[1], sys.argv[2]) -output = output.replace(chr(160),' ') # replace NO-BREAK SPACE with space -print(output, end='') diff --git a/ietf/iesg/tests.py b/ietf/iesg/tests.py index 5ecb4ed9de..a070c44e91 100644 --- a/ietf/iesg/tests.py +++ b/ietf/iesg/tests.py @@ -96,6 +96,12 @@ def test_photos(self): ads = Role.objects.filter(group__type='area', group__state='active', name_id='ad') self.assertEqual(len(q('.photo')), ads.count()) + def test_ietf_activity(self): + url = urlreverse("ietf.iesg.views.ietf_activity") + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + + class IESGAgendaTests(TestCase): def setUp(self): super().setUp() @@ -542,4 +548,4 @@ def test_reschedule(self): self.assertTrue(draft.latest_event(TelechatDocEvent, "scheduled_for_telechat")) self.assertEqual(draft.latest_event(TelechatDocEvent, "scheduled_for_telechat").telechat_date, d) self.assertTrue(not draft.latest_event(TelechatDocEvent, "scheduled_for_telechat").returning_item) - self.assertEqual(draft.docevent_set.count(), events_before + 1) \ No newline at end of file + self.assertEqual(draft.docevent_set.count(), events_before + 1) diff --git a/ietf/iesg/urls.py b/ietf/iesg/urls.py index fa6f3dbf73..7cf06cc6c6 100644 --- a/ietf/iesg/urls.py +++ b/ietf/iesg/urls.py @@ -55,6 +55,7 @@ url(r'^past/documents/$', views.past_documents), url(r'^agenda/telechat-(?:%(date)s-)?docs.tgz' % settings.URL_REGEXPS, views.telechat_docs_tarfile), url(r'^discusses/$', views.discusses), + url(r'^ietf-activity/$', views.ietf_activity), url(r'^milestones/$', views.milestones_needing_review), url(r'^photos/$', views.photos), -] \ No newline at end of file +] diff --git a/ietf/iesg/views.py b/ietf/iesg/views.py index 5334e8a85f..638fb8934e 100644 --- a/ietf/iesg/views.py +++ b/ietf/iesg/views.py @@ -41,9 +41,11 @@ import os import tarfile import time +from dateutil import relativedelta from django import forms from django.conf import settings +from django.core.exceptions import ValidationError from django.db import models from django.http import HttpResponse from django.shortcuts import render, redirect @@ -62,6 +64,7 @@ from ietf.iesg.utils import telechat_page_count from ietf.ietfauth.utils import has_role, role_required, user_is_person from ietf.person.models import Person +from ietf.secr.proceedings.proc_utils import get_activity_stats from ietf.doc.utils_search import fill_in_document_table_attributes, fill_in_telechat_date from ietf.utils.timezone import date_today, datetime_from_date @@ -528,4 +531,48 @@ def photos(request): role.last_initial = role.person.last_name()[0] return render(request, 'iesg/photos.html', {'group_type': 'IESG', 'role': '', 'roles': roles }) - \ No newline at end of file +def month_choices(): + choices = [(str(n).zfill(2), str(n).zfill(2)) for n in range(1, 13)] + choices.insert(0, ('', 'Select Month...')) + return choices + +def year_choices(): + this_year = datetime.date.today().year + choices = [(str(n), str(n)) for n in range(this_year, 2009, -1)] + choices.insert(0, ('', 'Select Year...')) + return choices + +class ActivityForm(forms.Form): + month = forms.ChoiceField(choices=month_choices, required=False) + year = forms.ChoiceField(choices=year_choices, required=False) + + def clean(self): + super().clean() + month = self.cleaned_data['month'] + year = self.cleaned_data['year'] + if not (month.isdigit() and year.isdigit()): + raise ValidationError('Must select a month and a year') + + return self.cleaned_data + +def ietf_activity(request): + # default date range for last month + today = datetime.date.today() + first_day_this_month = today + relativedelta.relativedelta(day=1) + edate = first_day_this_month - relativedelta.relativedelta(days=1) + sdate = edate + relativedelta.relativedelta(day=1) + if request.method == 'GET': + form = ActivityForm(request.GET) + if form.is_valid(): + month = form.cleaned_data['month'] + year = form.cleaned_data['year'] + sdate = datetime.date(int(year), int(month), 1) + next_month = sdate + relativedelta.relativedelta(months=1) + edate = next_month - relativedelta.relativedelta(days=1) + + # always pass back an unbound form to avoid annoying is-valid styling + form = ActivityForm() + context = get_activity_stats(sdate, edate) + context['is_monthly_report'] = True + context['form'] = form + return render(request, "iesg/ietf_activity_report.html", context) diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index 9c27531872..4b7153d465 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -7444,7 +7444,7 @@ def test_proceedings(self): ) self.assertNotEqual( pq('a[href="{}"]'.format( - urlreverse('ietf.meeting.views.proceedings_progress_report', kwargs=dict(num=meeting.number))) + urlreverse('ietf.meeting.views.proceedings_activity_report', kwargs=dict(num=meeting.number))) ), [], 'Should have a link to activity report', @@ -7610,14 +7610,14 @@ def test_proceedings_overview(self, mock): response = self.client.get(url) self.assertContains(response, 'The Internet Engineering Task Force') - def test_proceedings_progress_report(self): + def test_proceedings_activity_report(self): make_meeting_test_data() MeetingFactory(type_id='ietf', date=datetime.date(2016,4,3), number="96") MeetingFactory(type_id='ietf', date=datetime.date(2016,7,14), number="97") - url = urlreverse('ietf.meeting.views.proceedings_progress_report',kwargs={'num':97}) + url = urlreverse('ietf.meeting.views.proceedings_activity_report',kwargs={'num':97}) response = self.client.get(url) - self.assertContains(response, 'Progress Report') + self.assertContains(response, 'Activity Report') def test_feed(self): meeting = make_meeting_test_data() diff --git a/ietf/meeting/urls.py b/ietf/meeting/urls.py index 3beb23b0be..db9b481d76 100644 --- a/ietf/meeting/urls.py +++ b/ietf/meeting/urls.py @@ -92,7 +92,7 @@ def get_redirect_url(self, *args, **kwargs): url(r'^proceedings/acknowledgements/$', views.proceedings_acknowledgements), url(r'^proceedings/attendees/$', views.proceedings_attendees), url(r'^proceedings/overview/$', views.proceedings_overview), - url(r'^proceedings/progress-report/$', views.proceedings_progress_report), + url(r'^proceedings/activity-report/$', views.proceedings_activity_report), url(r'^proceedings/materials/$', views_proceedings.material_details), url(r'^proceedings/materials/(?P[a-z_]+)/$', views_proceedings.edit_material), url(r'^proceedings/materials/(?P[a-z_]+)/new/$', views_proceedings.upload_material), diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 0ba61d3faf..9637b5c3f4 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -84,7 +84,7 @@ from ietf.meeting.utils import new_doc_for_session, write_doc_for_session from ietf.message.utils import infer_message from ietf.name.models import SlideSubmissionStatusName, ProceedingsMaterialTypeName, SessionPurposeName -from ietf.secr.proceedings.proc_utils import (get_progress_stats, post_process, import_audio_files, +from ietf.secr.proceedings.proc_utils import (get_activity_stats, post_process, import_audio_files, create_recording) from ietf.utils import markdown from ietf.utils.decorators import require_api_key @@ -3431,7 +3431,6 @@ def interim_request_edit(request, number): "form": form, "formset": formset}) -@cache_page(60*60) def past(request): '''List of past meetings''' today = timezone.now() @@ -3799,9 +3798,8 @@ def proceedings_overview(request, num=None): 'template': template, }) -@cache_page( 60 * 60 ) -def proceedings_progress_report(request, num=None): - '''Display Progress Report (stats since last meeting)''' +def proceedings_activity_report(request, num=None): + '''Display Activity Report (stats since last meeting)''' if not (num and num.isdigit()): raise Http404 meeting = get_meeting(num) @@ -3809,9 +3807,9 @@ def proceedings_progress_report(request, num=None): return HttpResponseRedirect(f'{settings.PROCEEDINGS_V1_BASE_URL.format(meeting=meeting)}/progress-report.html') sdate = meeting.previous_meeting().date edate = meeting.date - context = get_progress_stats(sdate,edate) + context = get_activity_stats(sdate,edate) context['meeting'] = meeting - return render(request, "meeting/proceedings_progress_report.html", context) + return render(request, "meeting/proceedings_activity_report.html", context) class OldUploadRedirect(RedirectView): def get_redirect_url(self, **kwargs): diff --git a/ietf/secr/proceedings/proc_utils.py b/ietf/secr/proceedings/proc_utils.py index c9734534d7..bcba9bfa30 100644 --- a/ietf/secr/proceedings/proc_utils.py +++ b/ietf/secr/proceedings/proc_utils.py @@ -199,10 +199,10 @@ def send_audio_import_warning(unmatched_files): # End Recording Functions # ------------------------------------------------- -def get_progress_stats(sdate, edate): +def get_activity_stats(sdate, edate): ''' This function takes a date range and produces a dictionary of statistics / objects for - use in a progress report. Generally the end date will be the date of the last meeting + use in an activity report. Generally the end date will be the date of the last meeting and the start date will be the date of the meeting before that. Data between midnight UTC on the specified dates are included in the stats. diff --git a/ietf/secr/proceedings/reports.py b/ietf/secr/proceedings/reports.py deleted file mode 100644 index fd360774b1..0000000000 --- a/ietf/secr/proceedings/reports.py +++ /dev/null @@ -1,106 +0,0 @@ -import datetime - -from django.template.loader import render_to_string -from django.utils import timezone - -from ietf.meeting.models import Meeting -from ietf.doc.models import DocEvent, Document -from ietf.secr.proceedings.proc_utils import get_progress_stats -from ietf.utils.timezone import datetime_from_date - - -def report_id_activity(start,end): - - # get previous meeting - meeting = Meeting.objects.filter(date__lt=timezone.now(),type='ietf').order_by('-date')[0] - syear,smonth,sday = start.split('-') - eyear,emonth,eday = end.split('-') - sdate = datetime_from_date(datetime.date(int(syear),int(smonth),int(sday)), meeting.tz()) - edate = datetime_from_date(datetime.date(int(eyear),int(emonth),int(eday)), meeting.tz()) - - #queryset = Document.objects.filter(type='draft').annotate(start_date=Min('docevent__time')) - new_docs = Document.objects.filter(type='draft').filter(docevent__type='new_revision', - docevent__newrevisiondocevent__rev='00', - docevent__time__gte=sdate, - docevent__time__lte=edate) - new = new_docs.count() - updated = 0 - updated_more = 0 - for d in new_docs: - updates = d.docevent_set.filter(type='new_revision',time__gte=sdate,time__lte=edate).count() - if updates > 1: - updated += 1 - if updates > 2: - updated_more +=1 - - # calculate total documents updated, not counting new, rev=00 - result = set() - events = DocEvent.objects.filter(doc__type='draft',time__gte=sdate,time__lte=edate) - for e in events.filter(type='new_revision').exclude(newrevisiondocevent__rev='00'): - result.add(e.doc) - total_updated = len(result) - - # calculate sent last call - last_call = events.filter(type='sent_last_call').count() - - # calculate approved - approved = events.filter(type='iesg_approved').count() - - # get 4 weeks - monday = datetime_from_date(Meeting.get_current_meeting().get_ietf_monday(), meeting.tz()) - cutoff = monday + datetime.timedelta(days=3) - ff1_date = cutoff - datetime.timedelta(days=28) - #ff2_date = cutoff - datetime.timedelta(days=21) - #ff3_date = cutoff - datetime.timedelta(days=14) - #ff4_date = cutoff - datetime.timedelta(days=7) - - ff_docs = Document.objects.filter(type='draft').filter(docevent__type='new_revision', - docevent__newrevisiondocevent__rev='00', - docevent__time__gte=ff1_date, - docevent__time__lte=cutoff) - ff_new_count = ff_docs.count() - ff_new_percent = format(ff_new_count / float(new),'.0%') - - # calculate total documents updated in final four weeks, not counting new, rev=00 - result = set() - events = DocEvent.objects.filter(doc__type='draft',time__gte=ff1_date,time__lte=cutoff) - for e in events.filter(type='new_revision').exclude(newrevisiondocevent__rev='00'): - result.add(e.doc) - ff_update_count = len(result) - ff_update_percent = format(ff_update_count / float(total_updated),'.0%') - - #aug_docs = augment_with_start_time(new_docs) - ''' - ff1_new = aug_docs.filter(start_date__gte=ff1_date,start_date__lt=ff2_date) - ff2_new = aug_docs.filter(start_date__gte=ff2_date,start_date__lt=ff3_date) - ff3_new = aug_docs.filter(start_date__gte=ff3_date,start_date__lt=ff4_date) - ff4_new = aug_docs.filter(start_date__gte=ff4_date,start_date__lt=edate) - ff_new_iD = ff1_new + ff2_new + ff3_new + ff4_new - ''' - context = {'meeting':meeting, - 'new':new, - 'updated':updated, - 'updated_more':updated_more, - 'total_updated':total_updated, - 'last_call':last_call, - 'approved':approved, - 'ff_new_count':ff_new_count, - 'ff_new_percent':ff_new_percent, - 'ff_update_count':ff_update_count, - 'ff_update_percent':ff_update_percent} - - report = render_to_string('proceedings/report_id_activity.txt', context) - - return report - -def report_progress_report(start_date,end_date): - syear,smonth,sday = start_date.split('-') - eyear,emonth,eday = end_date.split('-') - sdate = datetime.datetime(int(syear),int(smonth),int(sday)) - edate = datetime.datetime(int(eyear),int(emonth),int(eday)) - - context = get_progress_stats(sdate,edate) - - report = render_to_string('proceedings/report_progress_report.txt', context) - - return report diff --git a/ietf/secr/proceedings/tests_reports.py b/ietf/secr/proceedings/tests_reports.py deleted file mode 100644 index 034dbe5fa5..0000000000 --- a/ietf/secr/proceedings/tests_reports.py +++ /dev/null @@ -1,36 +0,0 @@ -import datetime -import debug # pyflakes:ignore - -from django.utils import timezone - -from ietf.doc.factories import DocumentFactory,NewRevisionDocEventFactory -from ietf.secr.proceedings.reports import report_id_activity, report_progress_report -from ietf.utils.test_utils import TestCase -from ietf.meeting.factories import MeetingFactory - -class ReportsTestCase(TestCase): - - def test_report_id_activity(self): - - today = timezone.now() - yesterday = today - datetime.timedelta(days=1) - last_quarter = today - datetime.timedelta(days=3*30) - next_week = today+datetime.timedelta(days=7) - - m1 = MeetingFactory(type_id='ietf',date=last_quarter) - m2 = MeetingFactory(type_id='ietf',date=next_week,number=int(m1.number)+1) - - doc = DocumentFactory(type_id='draft',time=yesterday,rev="00") - NewRevisionDocEventFactory(doc=doc,time=today,rev="01") - result = report_id_activity(m1.date.strftime("%Y-%m-%d"),m2.date.strftime("%Y-%m-%d")) - self.assertTrue('IETF Activity since last IETF Meeting' in result) - - def test_report_progress_report(self): - today = timezone.now() - last_quarter = today - datetime.timedelta(days=3*30) - next_week = today+datetime.timedelta(days=7) - - m1 = MeetingFactory(type_id='ietf',date=last_quarter) - m2 = MeetingFactory(type_id='ietf',date=next_week,number=int(m1.number)+1) - result = report_progress_report(m1.date.strftime('%Y-%m-%d'),m2.date.strftime('%Y-%m-%d')) - self.assertTrue('IETF Activity since last IETF Meeting' in result) diff --git a/ietf/secr/templates/proceedings/report_id_activity.txt b/ietf/secr/templates/proceedings/report_id_activity.txt deleted file mode 100644 index 6f2aaf097a..0000000000 --- a/ietf/secr/templates/proceedings/report_id_activity.txt +++ /dev/null @@ -1,21 +0,0 @@ -IETF Activity since last IETF Meeting --------------------- - -IETF Activity since last IETF Meeting ({{ meeting.city }}) - -{{ new|stringformat:"3s" }} New I-Ds ({{ updated }} of which were updated, some ({{ updated_more }}) more than once) -{{ total_updated|stringformat:"3s" }} I-Ds were updated (Some more than once) -{{ last_call|stringformat:"3s" }} I-Ds Last Called -{{ approved|stringformat:"3s" }} I-Ds approved for publication - -In the final 4 weeks before meeting - -{{ ff_new_count|stringformat:"3s" }} New I-Ds were received - {{ ff_new_percent }} of total newbies since last meeting -{{ ff_update_count|stringformat:"3s" }} I-Ds were updated - {{ ff_update_percent }} of total updated since last meeting - - Week1 0 % - Week2 0 % - Week3 0 % - Week4 0 % - -The IESG Secretary. diff --git a/ietf/secr/templates/proceedings/report_progress_report.txt b/ietf/secr/templates/proceedings/report_progress_report.txt deleted file mode 100644 index 8c3d87548e..0000000000 --- a/ietf/secr/templates/proceedings/report_progress_report.txt +++ /dev/null @@ -1,48 +0,0 @@ -{% load ams_filters %} - IETF Activity since last IETF Meeting - {{ start_date }} to {{ end_date }} - - 1) {{ action_events.count }} IESG Protocol and Document Actions this period -{% for event in action_events %} - {{ event.doc.title }} ({{ event.doc.intended_std_level }}) -{% endfor %} - - 2) {{ lc_events.count }} IESG Last Calls issued to the IETF this period -{% for event in lc_events %} - {{ event.doc.title }} - {{ event.doc.file_tag|safe }} ({{ event.doc.intended_std_level }}) -{% endfor %} - - 3) {{ new_groups.count }} New Working Group(s) formed this period - {% for group in new_groups %} - {{ group }} ({{ group.acronym }}) - {% endfor %} - - 4) {{ concluded_groups.count }} Working Group(s) concluded this period - {% for group in concluded_groups %} - {{ group }} ({{ group.acronym }}) - {% endfor %} - - 5) {{ new_docs|length }} new or revised Internet-Drafts this period - - (o - Revised Internet-Draft; + - New Internet-Draft) - - WG I-D Title - ------- ------------------------------------------ - {% for doc in new_docs %} - ({{ doc.group.acronym|stringformat:"8s" }}) {% if doc.rev == "00" %} + {% else %} o {% endif %}{{ doc.title }} - {{ doc.file_tag|safe }} - {% endfor %} - - 6) {{ rfcs.count }} RFC(s) produced this period - - S - Standard; PS - Proposed Standard; DS - Draft Standard; - B - Best Current Practices; E - Experimental; I - Informational - - RFC Stat WG Published Title -------- -- ---------- ---------- ----------------------------------------- -{% for event in rfcs %} -{{ event.doc.canonical_name|upper }} {{ event.doc.intended_std_level.name|abbr_status|stringformat:"2s" }} ({{ event.doc.group.acronym|stringformat:"8s" }}) {{ event.time|date:"M d" }} {{ event.doc.title }} -{% endfor %} - - {{ counts.std }} Standards Track; {{ counts.bcp }} BCP; {{ counts.exp }} Experimental; {{ counts.inf }} Informational diff --git a/ietf/templates/iesg/ietf_activity_report.html b/ietf/templates/iesg/ietf_activity_report.html new file mode 100644 index 0000000000..32bf9dc456 --- /dev/null +++ b/ietf/templates/iesg/ietf_activity_report.html @@ -0,0 +1,25 @@ +{% extends "base.html" %} +{% load ams_filters ietf_filters django_bootstrap5 %} +{% block title %}IETF Activity Report{% endblock %} +{% block content %} +

IETF Activity Report

+

{{ sdate|date:"F Y" }}

+ +
+
+
+ {% bootstrap_field form.month show_label=True layout="inline" %} +
+
+ {% bootstrap_field form.year layout="inline" %} +
+
+ +
+
+
+ +

Draft Activity

+ {% include "meeting/activity_report.html" %} + +{% endblock %} \ No newline at end of file diff --git a/ietf/templates/meeting/proceedings_progress_report.html b/ietf/templates/meeting/activity_report.html similarity index 71% rename from ietf/templates/meeting/proceedings_progress_report.html rename to ietf/templates/meeting/activity_report.html index a51fb01e6c..28ca2494c1 100644 --- a/ietf/templates/meeting/proceedings_progress_report.html +++ b/ietf/templates/meeting/activity_report.html @@ -1,15 +1,4 @@ -{% extends "base.html" %} -{% load ams_filters ietf_filters %} -{% block title %}IETF {{ meeting.number }} Proceedings - Progress Report{% endblock %} -{% block content %} -

- - IETF {{ meeting.number }} proceedings - -

-

IETF Progress Report

-

{{ sdate|date:"d-F-y" }} to {{ edate|date:"d-F-y" }}

+ {% load ams_filters ietf_filters %}
  • {{ actions_count }} IESG Protocol and Document Actions this period
  • {{ last_calls_count }} IESG Last Calls issued to the IETF this period
  • @@ -17,15 +6,17 @@

    {{ sdate|date:"d-F-y" }} to {{ edate|date:"d-F-y" }}

    {{ new_drafts_count|stringformat:"3s" }} New I-Ds ({{ new_drafts_updated_count }} of which were updated, some ({{ new_drafts_updated_more_count }}) more than once)
  • {{ updated_drafts_count|stringformat:"3s" }} I-Ds were updated (Some more than once)
  • -
  • -

    In the final 4 weeks before meeting

    -
  • -
  • - {{ ffw_new_count|stringformat:"3s" }} New I-Ds were received - {{ ffw_new_percent }} of total newbies since last meeting -
  • -
  • - {{ ffw_update_count|stringformat:"3s" }} I-Ds were updated - {{ ffw_update_percent }} of total updated since last meeting -
  • + {% if not is_monthly_report %} +
  • +

    In the final 4 weeks before meeting

    +
  • +
  • + {{ ffw_new_count|stringformat:"3s" }} New I-Ds were received - {{ ffw_new_percent }} of total newbies since last meeting +
  • +
  • + {{ ffw_update_count|stringformat:"3s" }} I-Ds were updated - {{ ffw_update_percent }} of total updated since last meeting +
  • + {% endif %}

{{ new_groups.count }} New Working Group(s) formed this period

    @@ -66,5 +57,4 @@

    {{ rfcs.count }} RFCs published this period

    {% endfor %} {% endif %} - -{% endblock %} \ No newline at end of file + \ No newline at end of file diff --git a/ietf/templates/meeting/proceedings/introduction.html b/ietf/templates/meeting/proceedings/introduction.html index 2e409ccf06..9f6f9af002 100644 --- a/ietf/templates/meeting/proceedings/introduction.html +++ b/ietf/templates/meeting/proceedings/introduction.html @@ -14,7 +14,7 @@ Meeting Agenda
    Important Dates diff --git a/ietf/templates/meeting/proceedings_activity_report.html b/ietf/templates/meeting/proceedings_activity_report.html new file mode 100644 index 0000000000..dd5b082bf5 --- /dev/null +++ b/ietf/templates/meeting/proceedings_activity_report.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} +{% load ams_filters ietf_filters cache %} +{% block title %}IETF {{ meeting.number }} Proceedings - Activity Report{% endblock %} +{% block content %} + {% cache 3600 proceedings_activity_report meeting.number %} +

    + + IETF {{ meeting.number }} proceedings + +

    +

    IETF Activity Report

    +

    {{ sdate|date:"d-F-y" }} to {{ edate|date:"d-F-y" }}

    + + {% include "meeting/activity_report.html" %} + + {% endcache %} +{% endblock %} \ No newline at end of file From e59bbbb9c74a5a49d0ac93affbe9e40075ed8a17 Mon Sep 17 00:00:00 2001 From: Ryan Cross Date: Thu, 23 Feb 2023 10:58:58 -0800 Subject: [PATCH 2/3] fix: use date_today(), fix fencepost problem --- ietf/iesg/views.py | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/ietf/iesg/views.py b/ietf/iesg/views.py index 638fb8934e..5d4fa2f2fa 100644 --- a/ietf/iesg/views.py +++ b/ietf/iesg/views.py @@ -45,7 +45,6 @@ from django import forms from django.conf import settings -from django.core.exceptions import ValidationError from django.db import models from django.http import HttpResponse from django.shortcuts import render, redirect @@ -533,45 +532,32 @@ def photos(request): def month_choices(): choices = [(str(n).zfill(2), str(n).zfill(2)) for n in range(1, 13)] - choices.insert(0, ('', 'Select Month...')) return choices def year_choices(): - this_year = datetime.date.today().year + this_year = date_today().year choices = [(str(n), str(n)) for n in range(this_year, 2009, -1)] - choices.insert(0, ('', 'Select Year...')) return choices class ActivityForm(forms.Form): - month = forms.ChoiceField(choices=month_choices, required=False) - year = forms.ChoiceField(choices=year_choices, required=False) - - def clean(self): - super().clean() - month = self.cleaned_data['month'] - year = self.cleaned_data['year'] - if not (month.isdigit() and year.isdigit()): - raise ValidationError('Must select a month and a year') - - return self.cleaned_data + month = forms.ChoiceField(choices=month_choices, help_text='Month', required=True) + year = forms.ChoiceField(choices=year_choices, help_text='Year', required=True) def ietf_activity(request): # default date range for last month - today = datetime.date.today() - first_day_this_month = today + relativedelta.relativedelta(day=1) - edate = first_day_this_month - relativedelta.relativedelta(days=1) - sdate = edate + relativedelta.relativedelta(day=1) + today = date_today() + edate = today.replace(day=1) + sdate = (edate - datetime.timedelta(days=1)).replace(day=1) if request.method == 'GET': form = ActivityForm(request.GET) if form.is_valid(): month = form.cleaned_data['month'] year = form.cleaned_data['year'] sdate = datetime.date(int(year), int(month), 1) - next_month = sdate + relativedelta.relativedelta(months=1) - edate = next_month - relativedelta.relativedelta(days=1) + edate = sdate + relativedelta.relativedelta(months=1) # always pass back an unbound form to avoid annoying is-valid styling - form = ActivityForm() + form = ActivityForm(initial={'month': str(sdate.month).zfill(2), 'year': sdate.year}) context = get_activity_stats(sdate, edate) context['is_monthly_report'] = True context['form'] = form From 9d762819d13b996da3059a05ea5ccfbe026e3947 Mon Sep 17 00:00:00 2001 From: Ryan Cross Date: Mon, 27 Feb 2023 14:12:57 -0800 Subject: [PATCH 3/3] fix: use is_meeting_report template variable instead of is_monthly_report --- ietf/iesg/views.py | 1 - ietf/meeting/views.py | 1 + ietf/templates/meeting/activity_report.html | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ietf/iesg/views.py b/ietf/iesg/views.py index 5d4fa2f2fa..15675a8327 100644 --- a/ietf/iesg/views.py +++ b/ietf/iesg/views.py @@ -559,6 +559,5 @@ def ietf_activity(request): # always pass back an unbound form to avoid annoying is-valid styling form = ActivityForm(initial={'month': str(sdate.month).zfill(2), 'year': sdate.year}) context = get_activity_stats(sdate, edate) - context['is_monthly_report'] = True context['form'] = form return render(request, "iesg/ietf_activity_report.html", context) diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index bffa17f0de..c18b9be5c7 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -3809,6 +3809,7 @@ def proceedings_activity_report(request, num=None): edate = meeting.date context = get_activity_stats(sdate,edate) context['meeting'] = meeting + context['is_meeting_report'] = True return render(request, "meeting/proceedings_activity_report.html", context) class OldUploadRedirect(RedirectView): diff --git a/ietf/templates/meeting/activity_report.html b/ietf/templates/meeting/activity_report.html index bfd1afe219..1552bb4682 100644 --- a/ietf/templates/meeting/activity_report.html +++ b/ietf/templates/meeting/activity_report.html @@ -6,7 +6,7 @@ {{ new_drafts_count|stringformat:"3s" }} New I-Ds ({{ new_drafts_updated_count }} of which were updated, some ({{ new_drafts_updated_more_count }}) more than once)
  • {{ updated_drafts_count|stringformat:"3s" }} I-Ds were updated (Some more than once)
  • - {% if not is_monthly_report %} + {% if is_meeting_report %}
  • In the final 4 weeks before meeting