Comprehensive how-to/FAQs for member's meetings
diff --git a/www/members/meeting-util.rb b/www/members/meeting-util.rb
index 0d7c87b..ab34ad5 100644
--- a/www/members/meeting-util.rb
+++ b/www/members/meeting-util.rb
@@ -1,9 +1,23 @@
# Utility methods and structs related to Member's Meetings
-# NOTE: Assumes 21st century
+# NOTE: Assumes 21st century '2*'
require 'json'
class MeetingUtil
RECORDS = 'https://svn.apache.org/repos/private/foundation/Meetings'
+ MEETING_FILES = { # Filename in meeting dir, or pathname to another tool
+ 'README.txt' => 'README For Meeting Process',
+ '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',
+ 'agenda.txt' => 'Official Meeting Agenda',
+ 'board_ballot.txt' => 'Official Board Candidate Ballots',
+ '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)'
+ }
+
# Calculate how many members required to attend first half for quorum
def self.calculate_quorum(mtg_dir)
begin
diff --git a/www/members/meeting.cgi b/www/members/meeting.cgi
new file mode 100755
index 0000000..8ac15ca
--- /dev/null
+++ b/www/members/meeting.cgi
@@ -0,0 +1,120 @@
+#!/usr/bin/env ruby
+PAGETITLE = "Member's Meeting Information" # Wvisible:meeting
+$LOAD_PATH.unshift '/srv/whimsy/lib'
+
+require 'whimsy/asf'
+require 'wunderbar/bootstrap'
+require 'date'
+require 'json'
+require 'wunderbar/jquery/stupidtable'
+require_relative 'meeting-util'
+
+# Output action links for meeting records, depending on if current or past
+def emit_meeting(meeting, active)
+ _div id: "meeting-#{meeting}"
+ _whimsy_panel_table(
+ title: "Meeting Details for #{meeting}",
+ helpblock: -> {
+ _p active ? "Live links to the upcoming meeting records/how-tos below." : "These are historical links to the past meeting's record."
+ }
+ ) do
+ _ul do
+ MeetingUtil::MEETING_FILES.each do |f, desc|
+ _li do # Note: cheezy path detection within MEETING_FILES
+ _a desc, href: f.include?('/') ? f : File.join(MeetingUtil::RECORDS, meeting, f)
+ end
+ end
+ end
+ end
+end
+
+# produce HTML
+_html do
+ _body? do
+ MEETINGS = ASF::SVN['Meetings']
+ 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')
+
+ ROSTER = "/roster/committer"
+ _whimsy_body(
+ title: PAGETITLE,
+ subtitle: 'Meeting How-Tos',
+ relatedtitle: 'More About Meetings',
+ related: {
+ 'https://www.apache.org/foundation/governance/meetings' => 'How Meetings & Voting Works',
+ '/members/proxy' => 'Assign A Proxy For Next Meeting',
+ '/members/non-participants' => 'Members Not Participating',
+ '/members/inactive' => 'Inactive Member Feedback Form',
+ MeetingUtil::RECORDS => 'Official Past Meeting Records'
+ },
+ helpblock: -> {
+ if today > meeting
+ _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
+ }
+ _a 'https://www.apache.org/foundation/bylaws.html#3.2', 'the bylaws.'
+ _ 'Stay tuned for a NOTICE email on members@ announcing the next meeting. The below information is about the '
+ _span.text_warning 'LAST'
+ _ " Member's meeting."
+ end
+ else
+ _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."
+ _ 'For more details, read on below, or see the links to the right.'
+ end
+ end
+ }
+ ) do
+ help, copypasta = MeetingUtil.is_user_proxied(cur_mtg_dir, $USER)
+ attendance = JSON.parse(IO.read(File.join(MEETINGS, 'attendance.json')))
+ _whimsy_panel("Your Details For Meeting #{meeting}", style: 'panel-info') do
+ # TODO: remind member to check their committer.:email_forward address is correct (where ballots are sent)
+ _p do
+ if help
+ _p help
+ if copypasta
+ _ul.bg_success do
+ copypasta.each do |copyline|
+ _pre copyline
+ end
+ end
+ end
+ else
+ _ 'You are neither a proxy for anyone else, nor do you appear to have assigned a proxy for your attendance.'
+ end
+ end
+ end
+
+ emit_meeting(meeting, meeting >= today)
+
+ _whimsy_panel("Member Meeting History", style: 'panel-info') do
+ all_mtg = Dir[File.join(MEETINGS, '19*'), File.join(MEETINGS, '2*')].sort
+ _p do
+ _ %{
+ The ASF has held #{all_mtg.count} Member's meetings in our
+ history. Some were Annual meetings, were we elect a new board;
+ a handful were Special mid-year meetings where we mostly just
+ elected new Members.
+ }
+ _ ' Remember, member meeting minutes are '
+ _span.text_warning 'private'
+ _ ' to the ASF. You can see your '
+ _a 'your own attendance history at meetings.', href: '/members/inactive#attendance'
+ _ul do
+ all_mtg.each do |mtg|
+ _li do
+ tmp = File.join(MeetingUtil::RECORDS, File.basename(mtg))
+ _a tmp, href: tmp
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end