You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whimsical.apache.org by cu...@apache.org on 2020/02/03 17:31:44 UTC

[whimsy] branch master updated: Refactor, add some time links, use ics files for accurate times

This is an automated email from the ASF dual-hosted git repository.

curcuru pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/whimsy.git


The following commit(s) were added to refs/heads/master by this push:
     new 70e22cb  Refactor, add some time links, use ics files for accurate times
70e22cb is described below

commit 70e22cb2a3b1f906156a04e03fd63f1a8e14cf93
Author: Shane Curcuru <as...@shanecurcuru.org>
AuthorDate: Mon Feb 3 12:31:33 2020 -0500

    Refactor, add some time links, use ics files for accurate times
---
 www/members/meeting.cgi | 130 ++++++++++++++++++++++++++++--------------------
 1 file changed, 77 insertions(+), 53 deletions(-)

diff --git a/www/members/meeting.cgi b/www/members/meeting.cgi
index 48d8d70..1774871 100755
--- a/www/members/meeting.cgi
+++ b/www/members/meeting.cgi
@@ -9,6 +9,19 @@ require 'json'
 require 'wunderbar/jquery/stupidtable'
 require_relative 'meeting-util'
 FOUNDATION_SVN = 'https://svn.apache.org/repos/private/foundation/'
+DTFORMAT = '%A, %d %B %Y at %H:%M %z'
+TADFORMAT = '%Y%m%dT%H%M%S'
+
+# Return DateTime from DTSTART in an .ics file
+def ics2dtstart(f)
+  begin
+    tmp = IO.readlines(f).find{ |i| i =~ /DTSTART:/ }.split(':')[1].strip
+    return DateTime.parse(tmp)
+  rescue StandardError => e
+    puts "ics2dtstart #{e}"
+    return DateTime.new(1970,1,1) # An obvious error value 8-)
+  end
+end
 
 # Utility function for links, Note: cheezy path detection within MEETING_FILES
 def emit_link(cur_mtg_dir, f, desc)
@@ -16,33 +29,25 @@ def emit_link(cur_mtg_dir, f, desc)
 end
 
 # Output action links for meeting records, depending on if current or past
-def emit_meeting(cur_mtg_dir, meeting, active)
-  _div id: "meeting-#{meeting}"
-  _whimsy_panel("All Meeting Details for #{meeting}", style: 'panel-info') do 
-    num_members, quorum_need, num_proxies, attend_irc = MeetingUtil.calculate_quorum(cur_mtg_dir)
-    if num_members
-      if active
-        _p do
-          _ 'Currently, we will need '
-          _span.text_primary "#{attend_irc}" 
-          _ " Members attending the first half of the meeting on Tuesday and respond to Roll Call to reach quorum and continue the meeting."
-          _ " Calculation: Total voting members: #{num_members}, with one third for quorum: #{quorum_need}, minus previously submitted proxies: #{num_proxies}"
-        end
-      else
-        _p do
-          _ 'At the time of this past meeting, we had:'
-          _ul do
-            _li "#{num_members} eligible voting Members,"
-            _li "#{quorum_need} needed for quorum (one third),"
-            _li "#{num_proxies} proxy assignments available for the meeting,"
-            _li "And hoped that at least #{attend_irc} would attend the start of meeting."
-          end
-          attendees = File.readlines(File.join(cur_mtg_dir, 'attend'))
-          _ "By the end of the meeting, we had a total of #{attendees.count} Members participating (either via attending IRC, sending a proxy, or voting via email)"
+def emit_meeting(cur_mtg_dir, dt)
+  _div id: "meeting-#{dt.year}"
+  _whimsy_panel("All Meeting Details for #{dt.strftime(DTFORMAT)}", style: 'panel-info') do 
+    if Date.today > dt
+      _p do
+        _ 'At the time of this past meeting, we had:'
+        _ul do
+          _li "#{num_members} eligible voting Members,"
+          _li "#{quorum_need} needed for quorum (one third),"
+          _li "#{num_proxies} proxy assignments available for the meeting,"
+          _li "And hoped that at least #{attend_irc} would attend the start of meeting."
         end
+        attendees = File.readlines(File.join(cur_mtg_dir, 'attend'))
+        _ "By the end of the meeting, we had a total of #{attendees.count} Members participating (either via attending IRC, sending a proxy, or voting via email)"
       end
+      _p "These are historical links to the past meeting's record."
+    else
+      _p "Live links to the upcoming meeting records/ballots/how-tos are below."
     end
-    _p active ? "Live links to the upcoming meeting records/how-tos below." : "These are historical links to the past meeting's record."
     _ul do
       MeetingUtil::MEETING_FILES.each do |f, desc|
         _li do
@@ -60,57 +65,62 @@ _html do
     cur_mtg_dir = MeetingUtil.get_latest(MEETINGS).untaint
     meeting = File.basename(cur_mtg_dir)
     mtg_date = Date.parse(meeting)
-    today = Date.today.strftime('%Y%m%d')
-    begin
-      ics = IO.read(File.join(cur_mtg_dir, "ASF-members-#{mtg_date.strftime('%Y')}.ics"))
-    rescue StandardError => e
-      # Ensure we can't break rest of script
-      puts "ERROR: #{e}"
-      return 0, 0, 0, 0
-    end
-
+    today = Date.today
+    # Use ics files for accurate times; see create-meeting.rb
+    nom_date = ics2dtstart(File.join(cur_mtg_dir, "ASF-members-#{mtg_date.strftime('%Y')}-nominations-close.ics"))
+    m1_date = ics2dtstart(File.join(cur_mtg_dir, "ASF-members-#{mtg_date.strftime('%Y')}.ics"))
+    m2_date = ics2dtstart(File.join(cur_mtg_dir, "ASF-members-#{mtg_date.strftime('%Y')}-reconvene.ics"))
     ROSTER = "/roster/committer"
     _whimsy_body(
       title: PAGETITLE,
-      subtitle: 'Meeting How-Tos',
-      relatedtitle: 'More About Meetings',
+      subtitle: 'Member Meeting Overview',
+      relatedtitle: 'Meeting How-Tos',
       related: {
         'https://www.apache.org/foundation/governance/meetings' => 'How Meetings & Voting Works',
         'https://www.apache.org/foundation/governance/meetings#how-member-votes-are-tallied' => 'New Members Elected By Majority',
         'https://www.apache.org/foundation/governance/meetings#how-votes-for-the-board-are-tallied' => 'Board Seats Are Elected By STV',
         '/members/whatif' => 'Explore Past Board STV Results',
         '/members/proxy' => 'Assign A Proxy For Next Meeting',
-        '/members/non-participants' => 'Members Not Participating',
+        '/members/non-participants' => 'Members Not Participating Recntly',
         '/members/inactive' => 'Inactive Member Feedback Form',
-        MeetingUtil::RECORDS => 'Official Past Meeting Records'
+        MeetingUtil::RECORDS => 'Official Past Meeting Records',
+        'https://lists.apache.org/list.html?members@apache.org' => 'Read members@ List Archives'
       },
       helpblock: -> {
-        if today > meeting # Date is start of the two day meeting
+        if today > m2_date # Based on the reconvene date
           _p do
             _ %{
               The last Annual Member's Meeting was held #{mtg_date.strftime('%A, %d %B %Y')}.  Expect the 
-              next Member's meeting to be scheduled between 12 - 13 months after 
-              the previous meeting, as per 
+              next Member's meeting to be scheduled between 12 - 13 months after the previous meeting, as per 
             }
             _a 'https://www.apache.org/foundation/bylaws.html#3.2', 'the bylaws 3.2.'
-            _ 'Stay tuned for a NOTICE email on members@ announcing the next meeting.  The below information is about the '
-            _span.text_warning 'LAST'
+            _ 'Stay tuned for a [NOTICE] email on members@ announcing the next meeting.  The below information is about the '
+            _strong 'LAST'
             _ " Member's meeting."
           end
         else
+          _p %{
+            The Member's Meeting starts #{mtg_date.strftime(DTFORMAT)} as an online IRC meeting for about an hour.  We then recess for 48 hours while ballots are sent via email for voting. Results will be announced when we reconvene for about half an hour.
+          }
           _p do
-            _ "The next Member's Meeting will start on #{mtg_date.strftime('%A, %d %B %Y')}, as an online meeting on IRC, and will finish up two days later after voting via email is held."
             _ 'Please read below for a Timeline of Meeting activities and links to how you can take action, or see additional links to the right. '
-            _span.text_warning 'REMINDER: '
+            _strong 'REMINDER: '
             _ 'Nominations for the board or new members close 10 days before the meeting starts; no new names may be added after that date.'
           end
+          num_members, quorum_need, num_proxies, attend_irc = MeetingUtil.calculate_quorum(cur_mtg_dir)
+          _p do
+            _ 'Currently, we will need '
+            _span.text_primary "#{attend_irc}" 
+            _ " Members attending the first half of the meeting on Tuesday and respond to Roll Call to reach quorum and continue the meeting."
+            _ " Calculation: Total voting members: #{num_members}, with one third for quorum: #{quorum_need}, minus previously submitted proxies: #{num_proxies}"
+          end
         end
       }
     ) do
       help, copypasta = MeetingUtil.is_user_proxied(cur_mtg_dir, $USER)
       attendance = JSON.parse(IO.read(File.join(MEETINGS, 'attendance.json')))
       user = ASF::Person.find($USER)
-      _whimsy_panel("#{user.public_name} Details For Meeting #{meeting}", style: 'panel-primary') do
+      _whimsy_panel("#{user.public_name} - Personal Details For Meeting #{m1_date.strftime(DTFORMAT)}", style: 'panel-primary') do
         _p do
           if help
             _p help
@@ -122,18 +132,22 @@ _html do
               end
             end
           else
-            _ 'You are neither a proxy for anyone else, nor do you appear to have assigned a proxy for your attendance.'
+            _ 'You have not submitted a proxy - if you cannot attend the first half of the meeting, '
+            _a "please assign a proxy - it's easy!", href: '/members/proxy'
           end
         end
         _p do
           _span.text_warning 'REMINDER: '
-          _ "Ballots are sent to your official email address as found in members.txt, please double-check it is correct!"
+          _ "Voting ballots are sent to your official email address as found in members.txt, please double-check it is correct!"
           _a 'See members.txt', href: "#{FOUNDATION_SVN}members.txt"
         end
       end
 
-      _whimsy_panel("Timeline: Nomination Period (now until TEN DAYS before the meeting)", style: 'panel-default') do
+      _whimsy_panel("Timeline: Nomination Period (now until #{nom_date.strftime(DTFORMAT)})", style: 'panel-default') do
         _p do
+          _a href: "http://www.timeanddate.com/worldclock/fixedtime.html?iso=#{nom_date.strftime(TADFORMAT)}" do
+            _span.glyphicon.glyphicon_time ''
+          end
           _ 'Before the meeting, any Member may nominate people either for the Board, or as a New Member Candidate.  Much of this discussion happens on members@ mailing list.  Remember, all new nominated names must be checked into SVN 10 days before the meeting.'
           _ 'Also, you should submit a proxy if you might not attend the first half of the meeting.'
           _ul do
@@ -148,7 +162,10 @@ _html do
       
       _whimsy_panel("Timeline: Seconds Period (last ten days before meeting)", style: 'panel-default') do
         _p do
-          _ 'The 10 days before the meeting, you may add seconds to existing nomination files, but no new nominations are allowed.'
+          _a href: "http://www.timeanddate.com/worldclock/fixedtime.html?iso=#{nom_date.strftime(TADFORMAT)}" do
+            _span.glyphicon.glyphicon_time ''
+          end
+          _ 'The last 10 days before the meeting, you may add seconds to existing nomination files, but no new nominations are allowed.'
           _ 'Also, you can still submit a proxy if you might not attend the first half of the meeting.'
           _ul do
             ['nominated-members.txt', '/members/proxy.cgi'].each do |f|
@@ -160,11 +177,14 @@ _html do
         end
       end
       
-      _whimsy_panel("Timeline: First Half Of Meeting on IRC (at #{mtg_date.strftime('%A, %d %B %Y')})", style: 'panel-primary') do
+      _whimsy_panel("Timeline: First Half Of Meeting on IRC (at #{m1_date.strftime(DTFORMAT)})", style: 'panel-primary') do
         _p do
+          _a href: "http://www.timeanddate.com/worldclock/fixedtime.html?iso=#{m1_date.strftime(TADFORMAT)}" do
+            _span.glyphicon.glyphicon_time ''
+          end
           _ 'The Meeting itself starts on IRC - please be sure your client is setup ahead of time, and sign in with your Apache ID as nick if at all possible.'
           _ 'The #asfmembers channel is for the official meeting itself; please raise your hand if you have a formal question there.  Backchannel (jokes, comments, etc.) is on #asf channel.'
-          _ 'During the First Half of Meeting, the Chairman and various officers run through reports in the Agenda, which you can read ahead of time.'
+          _ 'During the First Half of Meeting, the Chairman and various officers run through reports in the Agenda.txt, which you can read ahead of time.'
           _ 'Expect the First Half to last about an hour; then the Chairman will call for a recess.'
           _ul do
             ['agenda.txt', 'README.txt', 'https://www.apache.org/foundation/governance/meetings'].each do |f|
@@ -189,8 +209,11 @@ _html do
         end
       end
       
-      _whimsy_panel("Timeline: Second Half Of Meeting (48 hours after #{mtg_date.strftime('%A, %d %B %Y')})", style: 'panel-primary') do
+      _whimsy_panel("Timeline: Second Half Of Meeting (at #{m2_date.strftime(DTFORMAT)})", style: 'panel-primary') do
         _p do
+          _a href: "http://www.timeanddate.com/worldclock/fixedtime.html?iso=#{m2_date.strftime(TADFORMAT)}" do
+            _span.glyphicon.glyphicon_time ''
+          end
           _ 'The Second Half Meeting is short - it\'s primarily announcing vote results and any last-minute announcements.  Members do not need to attend the second half; all results will be emailed or checked into SVN.'
           _ 'Various data files about the meeting will be checked in within a day after the meeting for historical records.'
           _ul do
@@ -220,8 +243,9 @@ _html do
       end
       
       # Most/all of these links should already be included above
-      emit_meeting(cur_mtg_dir, meeting, meeting >= today)
+      emit_meeting(cur_mtg_dir, m1_date)
       
+      _div id: "meeting-history"
       _whimsy_panel("Member Meeting History", style: 'panel-info') do
         all_mtg = Dir[File.join(MEETINGS, '19*'), File.join(MEETINGS, '2*')].sort
         _p do