This is an automated email from the ASF dual-hosted git repository.
rubys 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 51136af move meeting-util to lib/whimsy
51136af is described below
commit 51136af09f206a954692464b4c392771f57f2a79
Author: Sam Ruby <[email protected]>
AuthorDate: Wed Mar 23 15:07:44 2022 -0400
move meeting-util to lib/whimsy
---
lib/whimsy/asf/meeting-util.rb | 223 ++++++++++++++++++++++++++++++++++++++
www/members/board-nominations.cgi | 4 +-
www/members/inactive.cgi | 10 +-
www/members/list-traffic.cgi | 4 +-
www/members/meeting-util.rb | 221 -------------------------------------
www/members/meeting.cgi | 26 ++---
www/members/nominations.cgi | 4 +-
www/members/non-participants.cgi | 10 +-
www/members/proxy.cgi | 10 +-
9 files changed, 257 insertions(+), 255 deletions(-)
diff --git a/lib/whimsy/asf/meeting-util.rb b/lib/whimsy/asf/meeting-util.rb
new file mode 100644
index 0000000..3376875
--- /dev/null
+++ b/lib/whimsy/asf/meeting-util.rb
@@ -0,0 +1,223 @@
+#!/usr/bin/env ruby
+# Utility methods and structs related to Member's Meetings
+# NOTE: Assumes 21st century '2*'
+$LOAD_PATH.unshift '/srv/whimsy/lib' if __FILE__ == $PROGRAM_NAME
+require 'whimsy/asf'
+require 'json'
+
+module ASF
+ class MeetingUtil
+ RECORDS = ASF::SVN.svnurl!('Meetings')
+ 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',
+ 'nomination_of_members.txt' => 'How To Nominate A New Member',
+ '/members/proxy.cgi' => 'How To Submit A Proxy/Check Your Proxies',
+ 'https://www.apache.org/foundation/governance/meetings' => 'How Voting
Via Email Works',
+ 'agenda.txt' => 'Official Meeting Agenda',
+ 'board_ballot.txt' => 'Official Board Candidate Ballots',
+ 'nominated-members.txt' => 'Official New Member Nominees/Seconds',
+ 'proxies' => 'Official List Of Meeting Proxies',
+ 'record' => 'Official List Of Voting Members',
+ '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'
+ }
+
+ # Calculate how many members required to attend first half for quorum
+ def self.calculate_quorum(mtg_dir)
+ begin
+ begin
+ num_members = File.read(File.join(mtg_dir, 'record')).each_line.count
+ rescue
+ num_members = ASF::Member.list.length - ASF::Member.status.length
+ end
+ quorum_need = (num_members + 2) / 3
+ num_proxies = Dir[File.join(mtg_dir, 'proxies-received', '*')].count
+ attend_irc = quorum_need - num_proxies
+ rescue StandardError => e
+ # Ensure we can't break rest of script
+ puts "ERROR: #{e}"
+ return 0, 0, 0, 0
+ end
+ return num_members, quorum_need, num_proxies, attend_irc
+ end
+
+ # get list of proxy volunteers
+ def self.getVolunteers(mtg_dir)
+ lines = IO.read(File.join(mtg_dir, 'proxies'))
+ # 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
+ # @return nil otherwise
+ def self.is_user_proxied(mtg_dir, id)
+ user = ASF::Person.find(id)
+ lines = IO.read(File.join(mtg_dir, 'proxies'))
+ proxylist = lines.scan(/\s\s(.{25})(.*?)\((.*?)\)/) # [["Shane Curcuru
", "David Fisher ", "wave"], ...]
+ help = nil
+ copypasta = [] # theiravailid | Their Name in Rolls (proxy)
+ begin
+ proxylist.each do |arr|
+ if user.cn == arr[0].strip
+ copypasta << "#{arr[2].ljust(12)} | #{arr[1].strip} (proxy)"
+ elsif user.id == arr[2]
+ help = "NOTE: You have already submitted a proxy form for
#{arr[0].strip} to mark your attendance (be sure they know to mark you at Roll
Call)! "
+ end
+ end
+ rescue StandardError => e
+ (help ||= "") << "ERROR, could not read LDAP, proxy data may not be
correct: #{e.message}"
+ end
+ if copypasta.empty?
+ return help
+ else
+ (help ||= "") << "During the meeting, to mark your proxies'
attendance, AFTER the 2. Roll Call is called, you may copy/paste the below
lines to mark your and your proxies attendance."
+ copypasta.unshift("#{user.id.ljust(12)} | #{user.cn}")
+ return help, copypasta
+ end
+ 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')))
+ end
+
+ # Parse all memapp-received.txt files to get better set of names
+ # @see whimsy/www/members/attendance-xcheck.cgi
+ def self.read_memapps(dir)
+ memapps = Hash.new('unknown')
+ Dir[File.join(dir, '*', 'memapp-received.txt')].each do |received|
+ meeting = File.basename(File.dirname(received))
+ next if meeting.include? 'template'
+ text = File.read(received)
+ list = text.scan(/(.+)\s<(.*)@.*>.*Yes/i)
+ if list.empty?
+ list = text.scan(/^(?:no\s*)*(?:yes\s+)+(\w\S*)\s+(.*)\s*/)
+ else
+ # reverse order of id name type files
+ list.each {|a| a[0], a[1] = a[1], a[0] }
+ end
+ list.each { |itm| memapps[itm[1].strip] = [itm[0], meeting] }
+ end
+ return memapps
+ end
+
+ # Annotate the attendance.json file with cohorts by id
+ # This allows easy use by other tools
+ def self.annotate_attendance(dir)
+ attendance = JSON.parse(IO.read(File.join(dir, 'attendance.json')))
+ memapps = read_memapps(dir)
+ iclas = ASF::ICLA.preload
+ memapp_map = JSON.parse(IO.read(File.join(dir, 'memapp-map.json')))
+ attendance['cohorts'] = {}
+ attendance['unmatched'] = []
+ attendance['members'].each do |date, ary|
+ next unless date.start_with? '20' # exclude 'active'
+ ary.each do |nam|
+ found = iclas.select{|i| i.icla.legal_name == nam}
+ found = iclas.select{|i| i.icla.name == nam} if found.empty?
+ if found.empty?
+ if memapps.has_key?(nam)
+ attendance['cohorts'][memapps[nam][0]] = date
+ elsif memapp_map.has_key?(nam)
+ attendance['cohorts'][memapp_map[nam]] = date
+ else
+ attendance['unmatched'] << nam
+ end
+ else
+ attendance['cohorts'][found[0].icla.id] = date
+ end
+ end
+ end
+ File.open(File.join(dir, 'attendance-cohorts.json'), 'w') do |f| # Do
not overwrite blindly; manual copy if desired
+ f.puts JSON.pretty_generate(attendance)
+ end
+ end
+
+ # Precompute matrix and dates from attendance
+ def self.get_attend_matrices(dir)
+ attendance = MeetingUtil.get_attendance(dir)
+
+ # extract and format dates
+ dates = attendance['dates'].sort.
+ map {|date| Date.parse(date).strftime('%Y-%b')}
+
+ # compute mappings of names to ids
+ members = ASF::Member.list
+ active = Hash[members.select {|_id, data| not data['status']}]
+ nameMap = Hash[members.map {|id, data| [id, data[:name]]}]
+ idMap = Hash[nameMap.to_a.map(&:reverse)]
+
+ # analyze attendance
+ matrix = attendance['matrix'].map do |name, meetings|
+ id = idMap[name]
+ next unless id and active[id]
+
+ # exclude 'active entry'
+ data = meetings.select {|key, value| key.start_with? '20'}.
+ sort.reverse.map(&:last)
+
+ first = data.length
+ missed = (data.index {|datum| datum != '-'} || data.length)
+
+ [id, name, first, missed]
+ end
+
+ return attendance, matrix.compact, dates, nameMap
+ end
+
+ # return a function to determine the current status of a member by id
+ def self.current_status(cur_mtg_dir)
+ proxies = Dir["#{cur_mtg_dir}/proxies-received/*"].
+ map {|file| File.basename(file, '.*')}
+
+ _tag,emeritus = ASF::SVN.getlisting('emeritus-requests-received')
+ emeritus.map! {|file| File.basename(file, '.*')}
+
+ lambda do |id|
+ if emeritus.include? id
+ 'Emeritus request received'
+ elsif proxies.include? id
+ 'Proxy received'
+ else
+ 'No response'
+ end
+ end
+ end
+
+ # return the current status of all inactive members
+ def self.tracker(meetingsMissed)
+ cur_mtg_dir = MeetingUtil.get_latest(ASF::SVN['Meetings'])
+ current_status = self.current_status(cur_mtg_dir)
+
+ _attendance, matrix, _dates, _nameMap =
MeetingUtil.get_attend_matrices(MEETINGS)
+ inactive = matrix.select do |id, _name, _first, missed|
+ id and missed >= meetingsMissed
+ end
+
+ Hash[inactive.map {|id, name, _first, missed|
+ [id, {'name' => name, 'missed' => missed, 'status' =>
current_status[id]}]
+ }]
+ end
+ end
+end
+
+# ## ### #### ##### ######
+# Main method for command line use
+if __FILE__ == $PROGRAM_NAME
+ dir = ARGV[0]
+ dir ||= '.'
+ ASF::MeetingUtil.annotate_attendance(dir)
+ puts "DONE, check attendance-cohorts.json"
+end
diff --git a/www/members/board-nominations.cgi
b/www/members/board-nominations.cgi
index f9b7529..b6742e3 100755
--- a/www/members/board-nominations.cgi
+++ b/www/members/board-nominations.cgi
@@ -7,7 +7,7 @@ require 'mail'
require 'wunderbar/bootstrap'
require 'whimsy/asf'
require 'whimsy/asf/member-files'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
# link to members private-arch
MBOX = 'https://mail-search.apache.org/members/private-arch/members/'
@@ -92,7 +92,7 @@ _html do
_ 'Entries are highlighted if they are not present in both lists.'
}
) do
- cur_mtg_dir = File.basename(MeetingUtil.get_latest(MEETINGS))
+ cur_mtg_dir = File.basename(ASF::MeetingUtil.get_latest(MEETINGS))
nominations, emails = setup_data
_div.flexbox do
_div.flexitem do
diff --git a/www/members/inactive.cgi b/www/members/inactive.cgi
index 276c856..01b32de 100755
--- a/www/members/inactive.cgi
+++ b/www/members/inactive.cgi
@@ -7,7 +7,7 @@ require 'wunderbar/bootstrap'
require 'date'
require 'json'
require 'tmpdir'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
# produce HTML
_html do
@@ -29,8 +29,8 @@ _html do
end
_body? do
MEETINGS = ASF::SVN['Meetings']
- attendance = MeetingUtil.get_attendance(MEETINGS)
- latest = MeetingUtil.get_latest(MEETINGS)
+ attendance = ASF::MeetingUtil.get_attendance(MEETINGS)
+ latest = ASF::MeetingUtil.get_latest(MEETINGS)
@user ||= $USER
@meetingsMissed = (@meetingsMissed || 3).to_i
@@ -62,7 +62,7 @@ _html do
begin
tracker = JSON.parse(IO.read(File.join(latest, 'non-participants.json')))
rescue Errno::ENOENT => err
- tracker = MeetingUtil.tracker(@meetingsMissed)
+ tracker = ASF::MeetingUtil.tracker(@meetingsMissed)
end
# determine user's name as found in members.txt
@@ -84,7 +84,7 @@ _html do
'/members/proxy' => 'Assign A Proxy For Next Meeting',
'/members/non-participants' => 'Members Not Participating',
ASF::SVN.svnpath!('foundation','members.txt') => 'See Official
Members.txt File',
- MeetingUtil::RECORDS => 'Official Past Meeting Records'
+ ASF::MeetingUtil::RECORDS => 'Official Past Meeting Records'
},
helpblock: -> {
_p "This page shows your personal attendance record at past Member's
meetings, as of meeting #{latest}."
diff --git a/www/members/list-traffic.cgi b/www/members/list-traffic.cgi
index 59024c8..6fc9519 100755
--- a/www/members/list-traffic.cgi
+++ b/www/members/list-traffic.cgi
@@ -10,7 +10,7 @@ require 'whimsy/asf/agenda'
require 'date'
require 'mail'
require '../../tools/mboxhdr2csv.rb'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
user = ASF::Person.new($USER)
unless user.asf_member?
@@ -180,7 +180,7 @@ _html do
}
) do
months = Dir["#{SRV_MAIL}/*"].map {|path|
File.basename(path)}.grep(/^\d+$/)
- attendance = MeetingUtil.get_attendance(ASF::SVN['Meetings'])
+ attendance = ASF::MeetingUtil.get_attendance(ASF::SVN['Meetings'])
style_cohorts(attendance) if attendance.has_key?('cohorts') # Allow to
fail silently if data missing
# if ENV['QUERY_STRING'].include? 'Clear-Cache-No-Really'
# _p do # Danger, Will Robinson!
diff --git a/www/members/meeting-util.rb b/www/members/meeting-util.rb
deleted file mode 100644
index da6eae5..0000000
--- a/www/members/meeting-util.rb
+++ /dev/null
@@ -1,221 +0,0 @@
-#!/usr/bin/env ruby
-# Utility methods and structs related to Member's Meetings
-# NOTE: Assumes 21st century '2*'
-$LOAD_PATH.unshift '/srv/whimsy/lib'
-require 'whimsy/asf'
-require 'json'
-
-class MeetingUtil
- RECORDS = ASF::SVN.svnurl!('Meetings')
- 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',
- 'nomination_of_members.txt' => 'How To Nominate A New Member',
- '/members/proxy.cgi' => 'How To Submit A Proxy/Check Your Proxies',
- 'https://www.apache.org/foundation/governance/meetings' => 'How Voting Via
Email Works',
- 'agenda.txt' => 'Official Meeting Agenda',
- 'board_ballot.txt' => 'Official Board Candidate Ballots',
- 'nominated-members.txt' => 'Official New Member Nominees/Seconds',
- 'proxies' => 'Official List Of Meeting Proxies',
- 'record' => 'Official List Of Voting Members',
- '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'
- }
-
- # Calculate how many members required to attend first half for quorum
- def self.calculate_quorum(mtg_dir)
- begin
- begin
- num_members = File.read(File.join(mtg_dir, 'record')).each_line.count
- rescue
- num_members = ASF::Member.list.length - ASF::Member.status.length
- end
- quorum_need = (num_members + 2) / 3
- num_proxies = Dir[File.join(mtg_dir, 'proxies-received', '*')].count
- attend_irc = quorum_need - num_proxies
- rescue StandardError => e
- # Ensure we can't break rest of script
- puts "ERROR: #{e}"
- return 0, 0, 0, 0
- end
- return num_members, quorum_need, num_proxies, attend_irc
- end
-
- # get list of proxy volunteers
- def self.getVolunteers(mtg_dir)
- lines = IO.read(File.join(mtg_dir, 'proxies'))
- # 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
- # @return nil otherwise
- def self.is_user_proxied(mtg_dir, id)
- user = ASF::Person.find(id)
- lines = IO.read(File.join(mtg_dir, 'proxies'))
- proxylist = lines.scan(/\s\s(.{25})(.*?)\((.*?)\)/) # [["Shane Curcuru
", "David Fisher ", "wave"], ...]
- help = nil
- copypasta = [] # theiravailid | Their Name in Rolls (proxy)
- begin
- proxylist.each do |arr|
- if user.cn == arr[0].strip
- copypasta << "#{arr[2].ljust(12)} | #{arr[1].strip} (proxy)"
- elsif user.id == arr[2]
- help = "NOTE: You have already submitted a proxy form for
#{arr[0].strip} to mark your attendance (be sure they know to mark you at Roll
Call)! "
- end
- end
- rescue StandardError => e
- (help ||= "") << "ERROR, could not read LDAP, proxy data may not be
correct: #{e.message}"
- end
- if copypasta.empty?
- return help
- else
- (help ||= "") << "During the meeting, to mark your proxies' attendance,
AFTER the 2. Roll Call is called, you may copy/paste the below lines to mark
your and your proxies attendance."
- copypasta.unshift("#{user.id.ljust(12)} | #{user.cn}")
- return help, copypasta
- end
- 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')))
- end
-
- # Parse all memapp-received.txt files to get better set of names
- # @see whimsy/www/members/attendance-xcheck.cgi
- def self.read_memapps(dir)
- memapps = Hash.new('unknown')
- Dir[File.join(dir, '*', 'memapp-received.txt')].each do |received|
- meeting = File.basename(File.dirname(received))
- next if meeting.include? 'template'
- text = File.read(received)
- list = text.scan(/(.+)\s<(.*)@.*>.*Yes/i)
- if list.empty?
- list = text.scan(/^(?:no\s*)*(?:yes\s+)+(\w\S*)\s+(.*)\s*/)
- else
- # reverse order of id name type files
- list.each {|a| a[0], a[1] = a[1], a[0] }
- end
- list.each { |itm| memapps[itm[1].strip] = [itm[0], meeting] }
- end
- return memapps
- end
-
- # Annotate the attendance.json file with cohorts by id
- # This allows easy use by other tools
- def self.annotate_attendance(dir)
- attendance = JSON.parse(IO.read(File.join(dir, 'attendance.json')))
- memapps = read_memapps(dir)
- iclas = ASF::ICLA.preload
- memapp_map = JSON.parse(IO.read(File.join(dir, 'memapp-map.json')))
- attendance['cohorts'] = {}
- attendance['unmatched'] = []
- attendance['members'].each do |date, ary|
- next unless date.start_with? '20' # exclude 'active'
- ary.each do |nam|
- found = iclas.select{|i| i.icla.legal_name == nam}
- found = iclas.select{|i| i.icla.name == nam} if found.empty?
- if found.empty?
- if memapps.has_key?(nam)
- attendance['cohorts'][memapps[nam][0]] = date
- elsif memapp_map.has_key?(nam)
- attendance['cohorts'][memapp_map[nam]] = date
- else
- attendance['unmatched'] << nam
- end
- else
- attendance['cohorts'][found[0].icla.id] = date
- end
- end
- end
- File.open(File.join(dir, 'attendance-cohorts.json'), 'w') do |f| # Do not
overwrite blindly; manual copy if desired
- f.puts JSON.pretty_generate(attendance)
- end
- end
-
- # Precompute matrix and dates from attendance
- def self.get_attend_matrices(dir)
- attendance = MeetingUtil.get_attendance(dir)
-
- # extract and format dates
- dates = attendance['dates'].sort.
- map {|date| Date.parse(date).strftime('%Y-%b')}
-
- # compute mappings of names to ids
- members = ASF::Member.list
- active = Hash[members.select {|_id, data| not data['status']}]
- nameMap = Hash[members.map {|id, data| [id, data[:name]]}]
- idMap = Hash[nameMap.to_a.map(&:reverse)]
-
- # analyze attendance
- matrix = attendance['matrix'].map do |name, meetings|
- id = idMap[name]
- next unless id and active[id]
-
- # exclude 'active entry'
- data = meetings.select {|key, value| key.start_with? '20'}.
- sort.reverse.map(&:last)
-
- first = data.length
- missed = (data.index {|datum| datum != '-'} || data.length)
-
- [id, name, first, missed]
- end
-
- return attendance, matrix.compact, dates, nameMap
- end
-
- # return a function to determine the current status of a member by id
- def self.current_status(cur_mtg_dir)
- proxies = Dir["#{cur_mtg_dir}/proxies-received/*"].
- map {|file| File.basename(file, '.*')}
-
- _tag,emeritus = ASF::SVN.getlisting('emeritus-requests-received')
- emeritus.map! {|file| File.basename(file, '.*')}
-
- lambda do |id|
- if emeritus.include? id
- 'Emeritus request received'
- elsif proxies.include? id
- 'Proxy received'
- else
- 'No response'
- end
- end
- end
-
- # return the current status of all inactive members
- def self.tracker(meetingsMissed)
- cur_mtg_dir = MeetingUtil.get_latest(ASF::SVN['Meetings'])
- current_status = self.current_status(cur_mtg_dir)
-
- _attendance, matrix, _dates, _nameMap =
MeetingUtil.get_attend_matrices(MEETINGS)
- inactive = matrix.select do |id, _name, _first, missed|
- id and missed >= meetingsMissed
- end
-
- Hash[inactive.map {|id, name, _first, missed|
- [id, {'name' => name, 'missed' => missed, 'status' =>
current_status[id]}]
- }]
- end
-end
-
-# ## ### #### ##### ######
-# Main method for command line use
-if __FILE__ == $PROGRAM_NAME
- dir = ARGV[0]
- dir ||= '.'
- MeetingUtil.annotate_attendance(dir)
- puts "DONE, check attendance-cohorts.json"
-end
diff --git a/www/members/meeting.cgi b/www/members/meeting.cgi
index b95211b..d1813cc 100755
--- a/www/members/meeting.cgi
+++ b/www/members/meeting.cgi
@@ -7,7 +7,7 @@ require 'wunderbar/bootstrap'
require 'date'
require 'json'
require 'wunderbar/jquery/stupidtable'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
DTFORMAT = '%A, %d %B %Y at %H:%M %z'
TADFORMAT = '%Y%m%dT%H%M%S'
ERROR_DATE = DateTime.new(1970, 1, 1) # An obvious error value 8-)
@@ -57,7 +57,7 @@ def emit_meeting(cur_mtg_dir, svn_mtg_dir, dt, num_members,
quorum_need, num_pro
_p "Live links to the upcoming meeting records/ballots/how-tos are
below."
end
_ul do
- MeetingUtil::MEETING_FILES.each do |f, desc|
+ ASF::MeetingUtil::MEETING_FILES.each do |f, desc|
_li do
emit_link(svn_mtg_dir, f, desc)
end
@@ -70,13 +70,13 @@ end
_html do
_body? do
MEETINGS = ASF::SVN['Meetings']
- cur_mtg_dir = MeetingUtil.get_latest(MEETINGS)
+ cur_mtg_dir = ASF::MeetingUtil.get_latest(MEETINGS)
meeting = File.basename(cur_mtg_dir)
- svn_mtg_dir = File.join(MeetingUtil::RECORDS, meeting)
+ svn_mtg_dir = File.join(ASF::MeetingUtil::RECORDS, meeting)
mtg_date = Date.parse(meeting)
today = Date.today
# Calculate quorum
- num_members, quorum_need, num_proxies, attend_irc =
MeetingUtil.calculate_quorum(cur_mtg_dir)
+ num_members, quorum_need, num_proxies, attend_irc =
ASF::MeetingUtil.calculate_quorum(cur_mtg_dir)
# 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"))
@@ -94,7 +94,7 @@ _html do
'/members/whatif' => 'Explore Past Board STV Results',
'/members/non-participants' => 'Members Not Participating Recntly',
'/members/inactive' => 'Inactive Member Feedback Form',
- MeetingUtil::RECORDS => 'Official Past Meeting Records',
+ ASF::MeetingUtil::RECORDS => 'Official Past Meeting Records',
'https://lists.apache.org/[email protected]' => 'Read
members@ List Archives'
},
helpblock: -> {
@@ -148,7 +148,7 @@ _html do
end
}
) do
- help, copypasta = MeetingUtil.is_user_proxied(cur_mtg_dir, $USER)
+ help, copypasta = ASF::MeetingUtil.is_user_proxied(cur_mtg_dir, $USER)
# attendance = JSON.parse(IO.read(File.join(MEETINGS,
'attendance.json')))
user = ASF::Person.find($USER)
_div id: 'personal'
@@ -187,7 +187,7 @@ _html do
_ul do
['nomination_of_board.txt', 'nomination_of_members.txt',
'/members/proxy.cgi'].each do |f|
_li do
- emit_link(svn_mtg_dir, f, MeetingUtil::MEETING_FILES[f])
+ emit_link(svn_mtg_dir, f, ASF::MeetingUtil::MEETING_FILES[f])
end
end
end
@@ -206,7 +206,7 @@ _html do
_ul do
['nominated-members.txt', '/members/proxy.cgi'].each do |f|
_li do
- emit_link(svn_mtg_dir, f, MeetingUtil::MEETING_FILES[f])
+ emit_link(svn_mtg_dir, f, ASF::MeetingUtil::MEETING_FILES[f])
end
end
end
@@ -234,13 +234,13 @@ _html do
_ ' channel.'
_br
_ 'During the First Half of Meeting, the Board Chair will do Roll
call - please see instructions on how to mark present: '
- emit_link(svn_mtg_dir, 'README.txt',
MeetingUtil::MEETING_FILES['README.txt'])
+ emit_link(svn_mtg_dir, 'README.txt',
ASF::MeetingUtil::MEETING_FILES['README.txt'])
_ 'Once a quorum is reached, the Board Chair will lead the meeting,
with various officers presenting their reports in the Agenda.txt, which you can
read ahead of time.'
_ 'Expect the First Half to last about an hour; then the Board Chair
will call for a recess. Remember: there is no voting in IRC.'
_ul do
['agenda.txt', 'README.txt',
'https://www.apache.org/foundation/governance/meetings'].each do |f|
_li do
- emit_link(svn_mtg_dir, f, MeetingUtil::MEETING_FILES[f])
+ emit_link(svn_mtg_dir, f, ASF::MeetingUtil::MEETING_FILES[f])
end
end
end
@@ -280,7 +280,7 @@ _html do
_ul do
['record', 'attend', 'voter-tally', 'raw_board_votes.txt',
'raw-irc-log'].each do |f|
_li do
- emit_link(svn_mtg_dir, f, MeetingUtil::MEETING_FILES[f])
+ emit_link(svn_mtg_dir, f, ASF::MeetingUtil::MEETING_FILES[f])
end
end
_li do
@@ -331,7 +331,7 @@ _html do
_ul do
all_mtg.each do |mtg|
_li do
- tmp = File.join(MeetingUtil::RECORDS, File.basename(mtg))
+ tmp = File.join(ASF::MeetingUtil::RECORDS, File.basename(mtg))
_a tmp, href: tmp
end
end
diff --git a/www/members/nominations.cgi b/www/members/nominations.cgi
index 76d18cf..66c3484 100755
--- a/www/members/nominations.cgi
+++ b/www/members/nominations.cgi
@@ -7,7 +7,7 @@ require 'mail'
require 'wunderbar/bootstrap'
require 'whimsy/asf'
require 'whimsy/asf/member-files'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
# link to members private-arch
MBOX = 'https://mail-search.apache.org/members/private-arch/members/'
@@ -93,7 +93,7 @@ _html do
_ 'Entries are highlighted if they are not present in both lists.'
}
) do
- cur_mtg_dir = File.basename(MeetingUtil.get_latest(MEETINGS))
+ cur_mtg_dir = File.basename(ASF::MeetingUtil.get_latest(MEETINGS))
nominations, emails = setup_data
_div.flexbox do
_div.flexitem do
diff --git a/www/members/non-participants.cgi b/www/members/non-participants.cgi
index bec9235..a263069 100755
--- a/www/members/non-participants.cgi
+++ b/www/members/non-participants.cgi
@@ -7,17 +7,17 @@ require 'wunderbar/bootstrap'
require 'date'
require 'json'
require 'wunderbar/jquery/stupidtable'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
# Find latest meeting and check if it's in the future yet
MEETINGS = ASF::SVN['Meetings']
-cur_mtg_dir = MeetingUtil.get_latest(MEETINGS)
+cur_mtg_dir = ASF::MeetingUtil.get_latest(MEETINGS)
meeting = File.basename(cur_mtg_dir)
today = Date.today.strftime('%Y%m%d')
# look for recent activity if there is an upcoming meeting
if meeting > today
- current_status = MeetingUtil.current_status(cur_mtg_dir)
+ current_status = ASF::MeetingUtil.current_status(cur_mtg_dir)
else
current_status = lambda {'No response'}
end
@@ -31,7 +31,7 @@ end
# produce HTML
_html do
_body? do
- attendance, matrix, dates, nameMap =
MeetingUtil.get_attend_matrices(MEETINGS)
+ attendance, matrix, dates, nameMap =
ASF::MeetingUtil.get_attend_matrices(MEETINGS)
_whimsy_body(
title: PAGETITLE,
subtitle: 'Select A Date:',
@@ -126,5 +126,5 @@ _html do
end
_json do
- MeetingUtil.tracker((@meetingsMissed || 3).to_i)
+ ASF::MeetingUtil.tracker((@meetingsMissed || 3).to_i)
end
diff --git a/www/members/proxy.cgi b/www/members/proxy.cgi
index ec7e053..20d28af 100755
--- a/www/members/proxy.cgi
+++ b/www/members/proxy.cgi
@@ -8,7 +8,7 @@ require 'wunderbar/bootstrap'
require 'wunderbar/jquery'
require 'date'
require 'tmpdir'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
# Emit basic instructions and details on quorum
def emit_instructions(today, cur_mtg_dir, meeting)
@@ -68,7 +68,7 @@ def emit_instructions(today, cur_mtg_dir, meeting)
_ ' file. The great majority of proxies assigned are for attendance only;
not for voting.'
end
end
- num_members, quorum_need, num_proxies, attend_irc =
MeetingUtil.calculate_quorum(cur_mtg_dir)
+ num_members, quorum_need, num_proxies, attend_irc =
ASF::MeetingUtil.calculate_quorum(cur_mtg_dir)
if num_members
_p do
_ 'Currently, we must have '
@@ -81,7 +81,7 @@ end
# Emit meeting data and form for user to select a proxy - GET
def emit_form(cur_mtg_dir, meeting, volunteers, disabled)
- help, copypasta = MeetingUtil.is_user_proxied(cur_mtg_dir, $USER)
+ help, copypasta = ASF::MeetingUtil.is_user_proxied(cur_mtg_dir, $USER)
user_is_proxy = help && copypasta
_whimsy_panel(user_is_proxy ? "You Are Proxying For Others" : "Select A
Proxy For Upcoming Meeting", style: 'panel-success') do
_div do
@@ -292,7 +292,7 @@ _html do
_body? do
# Find latest meeting and check if it's in the future yet
MEETINGS = ASF::SVN['Meetings']
- cur_mtg_dir = MeetingUtil.get_latest(MEETINGS)
+ cur_mtg_dir = ASF::MeetingUtil.get_latest(MEETINGS)
meeting = File.basename(cur_mtg_dir)
today = Date.today.strftime('%Y%m%d')
_whimsy_body(
@@ -310,7 +310,7 @@ _html do
}
) do
if _.get?
- emit_form(cur_mtg_dir, meeting,
MeetingUtil::getVolunteers(cur_mtg_dir), today > meeting)
+ emit_form(cur_mtg_dir, meeting,
ASF::MeetingUtil::getVolunteers(cur_mtg_dir), today > meeting)
else # POST
emit_post(cur_mtg_dir, meeting, _)
end