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

sebb 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 053e45a9 Get nomination close time from ICS file
053e45a9 is described below

commit 053e45a9897c1a286aa51a90c3d9a5e2d20500ef
Author: Sebb <[email protected]>
AuthorDate: Sun Feb 26 01:28:10 2023 +0000

    Get nomination close time from ICS file
---
 lib/whimsy/asf/meeting-util.rb     | 39 +++++++++++++++++++++++++++++++++++++-
 www/members/board-nominate.cgi     | 23 ++++++++++++++++------
 www/members/member_nominations.cgi | 22 ++++++++++++++++-----
 3 files changed, 72 insertions(+), 12 deletions(-)

diff --git a/lib/whimsy/asf/meeting-util.rb b/lib/whimsy/asf/meeting-util.rb
index a3138a04..f0324d20 100644
--- a/lib/whimsy/asf/meeting-util.rb
+++ b/lib/whimsy/asf/meeting-util.rb
@@ -4,10 +4,12 @@
 $LOAD_PATH.unshift '/srv/whimsy/lib' if __FILE__ == $PROGRAM_NAME
 require 'whimsy/asf'
 require 'json'
+require 'date'
 
 module ASF
   class MeetingUtil
     RECORDS = ASF::SVN.svnurl!('Meetings')
+    VCAL_EVENTS_FILENAME = 'ASF-members-meeting.ics'
     MEETING_FILES = { # Filename in meeting dir, pathname to another deployed 
tool, or URL
       'README.txt' => 'README For Meeting Process And Roll Call',
       'nomination_of_board.txt' => 'How To Nominate Someone For Board',
@@ -22,7 +24,8 @@ module ASF
       'attend' => 'Official List Of Meeting Attendees (afterwards)',
       'voter-tally' => 'Official List Of Who Voted (afterwards)',
       'raw_board_votes.txt' => 'Official List Of Votes For Board (afterwards)',
-      'raw-irc-log' => 'ASFBot logs all postings on #asfmembers during meeting'
+      'raw-irc-log' => 'ASFBot logs all postings on #asfmembers during meeting 
(afterwards)',
+      VCAL_EVENTS_FILENAME => 'VCAL events file: ASF Members Meeting; 
Nominations close; Polls close'
     }
 
     # Calculate how many members required to attend first half for quorum
@@ -51,6 +54,7 @@ module ASF
       # split by ---- underlines, then by blank lines; pick second para and 
drop leading spaces
       lines.split(/^-----------/)[1].split(/\n\n/)[1].scan(/^\ 
+(\S.*$)/).flatten
     end
+
     # Get info about current users's proxying
     # @return "help text", ["id | name (proxy)", ...] if they are a proxy for 
other(s)
     # @return "You have already submitted a proxy form" to someone else
@@ -86,14 +90,17 @@ module ASF
     def self.get_latest_completed(mtg_root, sentinel='raw-irc-log')
       return Dir[File.join(mtg_root, '2*')].select {|d| File.exist? 
File.join(d, sentinel) }.max
     end
+
     # Get the latest available Meetings dir
     def self.get_latest(mtg_root)
       return Dir[File.join(mtg_root, '2*')].max
     end
+
     # Get the second latest available Meetings dir
     def self.get_previous(mtg_root)
       return Dir[File.join(mtg_root, '2*')].sort[-2]
     end
+
     # Read attendance.json file
     def self.get_attendance(mtg_root)
       return JSON.parse(IO.read(File.join(mtg_root, 'attendance.json')))
@@ -202,6 +209,11 @@ module ASF
       end
     end
 
+    # return the dir containing the latest meeting files
+    def self.latest_meeting_dir
+      MeetingUtil.get_latest(ASF::SVN['Meetings'])
+    end
+
     # return the current status of all inactive members
     def self.tracker(meetingsMissed)
       meetings = ASF::SVN['Meetings']
@@ -223,6 +235,31 @@ module ASF
         }]
       }]
     end
+
+    # get the times from the VCAL events file
+    # returns: nominations close, polls close, meeting starts as seconds since 
epoch
+    def self.get_invite_times
+      times = {}
+      File.readlines(File.join(latest_meeting_dir, 
VCAL_EVENTS_FILENAME)).slice_before(/^BEGIN:VEVENT/).drop(1).each do |ev|
+        uid = nil
+        dtstart = nil
+        ev.each do |line|
+          case line
+            when /^UID:(.+)/
+              uid = $1.chomp.sub(/-?\d{4}/, '')
+            when /^DTSTART;TZID=(.+):(.+)/
+              tz = $1
+              if tz == 'UTC'
+                dtstart = DateTime.iso8601($2.chomp).to_time.to_i
+              else
+                raise ArgumentError.new("Cannot parse #{line.chomp} in 
#{VCAL_EVENTS_FILENAME}")
+              end
+          end
+        end
+        times[uid] = dtstart
+      end
+      return [times['asf-members-nominations-close'], 
times['asf-members-polls-close'], times['asf-members']]
+    end
   end
 end
 
diff --git a/www/members/board-nominate.cgi b/www/members/board-nominate.cgi
index ae4713e8..a351b110 100755
--- a/www/members/board-nominate.cgi
+++ b/www/members/board-nominate.cgi
@@ -9,6 +9,9 @@ require 'whimsy/asf'
 require 'whimsy/asf/forms'
 require 'whimsy/asf/member-files'
 require 'whimsy/asf/wunderbar_updates'
+require 'whimsy/asf/meeting-util'
+
+nomclosed = Time.now.to_i > ASF::MeetingUtil.get_invite_times.first
 
 def emit_form(title, prev_data)
   _whimsy_panel(title, style: 'panel-success') do
@@ -45,7 +48,6 @@ def validate_form(formdata: {})
   return 'OK'
 end
 
-
 # Handle submission (checkout user's apacheid.json, write form data, checkin 
file)
 # @return true if we think it succeeded; false in all other cases
 def process_form(formdata: {}, wunderbar: {})
@@ -88,15 +90,24 @@ _html do
           of the nomination to the members list.
           There is currently no support for updating an existing entry.
         }
-        _p 'Nominations are now closed!'
       }
     ) do
 
+      if nomclosed
+        _h1 'Nominations are now closed!' 
+      end
+
       _div id: 'nomination-form' do
-        if false # _.post?
-          submission = _whimsy_params2formdata(params)
-          valid = validate_form(formdata: submission)
-          if valid == 'OK'
+        if _.post?
+          unless nomclosed
+            submission = _whimsy_params2formdata(params)
+            valid = validate_form(formdata: submission)
+          end
+          if nomclosed
+            _div.alert.alert_warning role: 'alert' do
+              _p "Nominations have closed"
+            end
+          elsif valid == 'OK'
             if process_form(formdata: submission, wunderbar: _)
               _p.lead "Thanks for Using This Form!"
             else
diff --git a/www/members/member_nominations.cgi 
b/www/members/member_nominations.cgi
index ae5b49e8..7898f946 100755
--- a/www/members/member_nominations.cgi
+++ b/www/members/member_nominations.cgi
@@ -9,6 +9,9 @@ require 'whimsy/asf'
 require 'whimsy/asf/forms'
 require 'whimsy/asf/member-files'
 require 'whimsy/asf/wunderbar_updates'
+require 'whimsy/asf/meeting-util'
+
+nomclosed = Time.now.to_i > ASF::MeetingUtil.get_invite_times.first
 
 def emit_form(title, prev_data)
   _whimsy_panel(title, style: 'panel-success') do
@@ -88,15 +91,24 @@ _html do
           of the nomination to the members list.
           There is currently no support for updating an existing entry.
         }
-        _p 'Nominations are now closed!'
       }
     ) do
 
+      if nomclosed
+        _h1 'Nominations are now closed!' 
+      end
+
       _div id: 'nomination-form' do
-        if false # _.post?
-          submission = _whimsy_params2formdata(params)
-          valid = validate_form(formdata: submission)
-          if valid == 'OK'
+        if _.post?
+          unless nomclosed
+            submission = _whimsy_params2formdata(params)
+            valid = validate_form(formdata: submission)
+          end
+          if nomclosed
+            _div.alert.alert_warning role: 'alert' do
+              _p "Nominations have closed"
+            end
+          elsif valid == 'OK'
             if process_form(formdata: submission, wunderbar: _)
               _p.lead "Thanks for Using This Form!"
             else

Reply via email to