You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whimsical.apache.org by Sam Ruby <ru...@apache.org> on 2016/02/15 21:39:30 UTC

[whimsy.git] [1/1] Commit dbbb2b5: start to split things up into more manageable bits

Commit dbbb2b5fbf68651e50d65a3ea1258404da75aa00:
    start to split things up into more manageable bits


Branch: refs/heads/master
Author: Sam Ruby <ru...@intertwingly.net>
Committer: Sam Ruby <ru...@intertwingly.net>
Pusher: rubys <ru...@apache.org>

------------------------------------------------------------
www/roster/views/app.js.rb                                   | +++++ -
www/roster/views/committee.html.rb                           | + -
www/roster/views/pmc/committers.js.rb                        | +++++++++ 
www/roster/views/pmc/confirm.js.rb                           | ++++++++++ 
www/roster/views/pmc/main.js.rb                              | +++++++++++ 
www/roster/views/pmc/pmc.js.rb                               | ++++++++++++ 
------------------------------------------------------------
438 changes: 436 additions, 2 deletions.
------------------------------------------------------------


diff --git a/www/roster/views/app.js.rb b/www/roster/views/app.js.rb
index 1e0f4f3..7cfc5f9 100644
--- a/www/roster/views/app.js.rb
+++ b/www/roster/views/app.js.rb
@@ -1,5 +1,9 @@
 require_relative 'polyfill'
 
-require_relative 'committee'
+require_relative 'pmc/main'
+require_relative 'pmc/pmc'
+require_relative 'pmc/committers'
+require_relative 'pmc/confirm'
+
 require_relative 'committer'
 require_relative 'committerSearch'
diff --git a/www/roster/views/committee.html.rb b/www/roster/views/committee.html.rb
index b65989c..4891738 100644
--- a/www/roster/views/committee.html.rb
+++ b/www/roster/views/committee.html.rb
@@ -17,6 +17,6 @@
 
   _script src: 'app.js'
   _.render '#main' do
-    _Committee committee: @committee, auth: @auth
+    _PMC committee: @committee, auth: @auth
   end
 end
diff --git a/www/roster/views/pmc/committers.js.rb b/www/roster/views/pmc/committers.js.rb
new file mode 100644
index 0000000..f079330
--- /dev/null
+++ b/www/roster/views/pmc/committers.js.rb
@@ -0,0 +1,134 @@
+#
+# Committers on the PMC
+#
+
+class PMCCommitters < React
+  def render
+    if @@committee.committers.keys().all? {|id| @@committee.roster[id]}
+      _p 'All committers are members of the PMC'
+    else
+      _h2 'Committers'
+      _table.table.table_hover do
+        _thead do
+          _tr do
+            _th 'id'
+            _th 'public name'
+          end
+        end
+
+        _tbody do
+          @committers.each do |person|
+            next if @@committee.roster[person.id]
+            _PMCCommitter auth: @@auth, person: person, committee: @@committee
+          end
+
+          if @@auth
+            _tr onDoubleClick: self.select do
+              _td((@state == :open ? '' : "\u2795"), colspan: 3)
+            end
+          end
+        end
+      end
+
+      if @state == :open
+        _div.search_box do
+          _CommitterSearch add: self.add
+        end
+      end
+    end
+  end
+
+  # update props on initial load
+  def componentWillMount()
+    self.componentWillReceiveProps()
+  end
+
+  # compute list of committers
+  def componentWillReceiveProps()
+    committers = []
+    
+    for id in @@committee.committers
+      committers << {id: id, name: @@committee.committers[id]}
+    end
+
+    @committers = committers.sort_by {|person| person.name}
+  end
+
+  # open search box
+  def select()
+    return unless @@auth
+    window.getSelection().removeAllRanges()
+    @state = ( @state == :open ? :closed : :open )
+  end
+
+  # add a person to the displayed list of committers
+  def add(person)
+    person.date = 'pending'
+    @committers << person
+    @state = :closed
+  end
+end
+
+#
+# Show a committer
+#
+
+class PMCCommitter < React
+  def initialize
+    @state = :closed
+  end
+
+  def render
+    _tr onDoubleClick: self.select do
+      _td {_a @@person.id, href: "committer/#{@@person.id}"}
+      _td @@person.name
+
+      if @state == :open
+        _td data_id: @@person.id do 
+          if @@person.date == 'pending'
+            _button.btn.btn_primary 'Add as a committer only',
+              data_action: 'add commit', 
+              data_target: '#confirm', data_toggle: 'modal',
+              data_confirmation: "Grant #{@@person.name} committer access?"
+
+            _button.btn.btn_success 'Add as a committer and to the PMC',
+              data_action: 'add pmc commit', 
+              data_target: '#confirm', data_toggle: 'modal',
+              data_confirmation: "Add #{@@person.name} to the " +
+                 "#{@@committee.display_name} PMC and grant committer access?"
+          else
+            _button.btn.btn_warning 'Remove as Committer',
+              data_action: 'remove commit', 
+              data_target: '#confirm', data_toggle: 'modal',
+              data_confirmation: "Remove #{@@person.name} as a Committer?"
+
+            _button.btn.btn_primary 'Add to PMC',
+              data_action: 'add pmc', 
+              data_target: '#confirm', data_toggle: 'modal',
+              data_confirmation: "Add #{@@person.name} to the " +
+                "#{@@committee.display_name} PMC?"
+          end
+        end
+      else
+        _td ''
+      end
+    end
+  end
+
+  # update props on initial load
+  def componentWillMount()
+    self.componentWillReceiveProps()
+  end
+
+  # automatically open pending entries
+  def componentWillReceiveProps()
+    @state = :open if @@person.date == 'pending'
+  end
+
+  # toggle display of buttons
+  def select()
+    return unless @@auth
+    window.getSelection().removeAllRanges()
+    @state = ( @state == :open ? :closed : :open )
+  end
+end
diff --git a/www/roster/views/pmc/confirm.js.rb b/www/roster/views/pmc/confirm.js.rb
new file mode 100644
index 0000000..11a496e
--- /dev/null
+++ b/www/roster/views/pmc/confirm.js.rb
@@ -0,0 +1,73 @@
+#
+# Confirmation dialog
+#
+
+class PMCConfirm < React
+  def initialize
+    @text = 'text'
+    @color = 'btn-default'
+    @button = 'OK'
+  end
+
+  def render
+    _div.modal.fade.confirm! tabindex: -1 do
+      _div.modal_dialog do
+        _div.modal_content do
+          _div.modal_header.bg_info do
+            _button.close 'x', data_dismiss: 'modal'
+            _h4.modal_title 'Confirm Request'
+          end
+
+          _div.modal_body do
+            _p @text
+          end
+
+          _div.modal_footer do
+            _button.btn.btn_default 'Cancel', data_dismiss:"modal"
+            _button.btn @button, class: @color, onClick: self.post
+          end
+        end
+      end
+    end
+  end
+
+  def componentDidMount()
+    jQuery('#confirm').on('show.bs.modal') do |event|
+      button = event.relatedTarget
+      @id = button.parentNode.dataset.id
+      @action = button.dataset.action
+      @text = button.dataset.confirmation
+      @color = button.classList[1]
+      @button = button.textContent
+    end
+  end
+
+  def post()
+    # parse action extracted from the button
+    targets = @action.split(' ')
+    action = targets.shift()
+
+    # construct arguments to fetch
+    args = {
+      method: 'post',
+      credentials: 'include',
+      headers: {'Content-Type' => 'application/json'},
+      body: {pmc: @@pmc, id: @id, action: action, targets: targets}.inspect
+    }
+
+    fetch('actions/committee', args).then {|response|
+      content_type = response.headers.get('content-type') || ''
+      if response.status == 200 and content_type.include? 'json'
+        response.json().then do |json|
+          @@update.call(json)
+        end
+      else
+        alert "#{response.status} #{response.statusText}"
+      end
+      jQuery('#confirm').modal(:hide)
+    }.catch {|error|
+      alert errror
+      jQuery('#confirm').modal(:hide)
+    }
+  end
+end
diff --git a/www/roster/views/pmc/main.js.rb b/www/roster/views/pmc/main.js.rb
new file mode 100644
index 0000000..b96a550
--- /dev/null
+++ b/www/roster/views/pmc/main.js.rb
@@ -0,0 +1,44 @@
+#
+# Show a PMC
+#
+
+class PMC < React
+  def render
+    auth = (@@auth.id == @committee.chair or @@auth.secretary or @@auth.root)
+
+    # header
+    _h1 do
+      _a @committee.display_name, href: @committee.site
+      _small " established #{@committee.established}" if @committee.established
+    end
+
+    _p @committee.description
+
+    if auth
+      _div.alert.alert_success 'Double click on a row to edit.  ' +
+        "Double click on \u2795 to add."
+    end
+
+    # main content
+    _PMCMembers auth: auth, committee: @committee
+    _PMCCommitters auth: auth, committee: @committee
+
+    # hidden form
+    _PMCConfirm pmc: @committee.id, update: self.update if auth
+  end
+
+  # capture committee on initial load
+  def componentWillMount()
+    @committee = @@committee
+  end
+
+  # capture committee on subsequent loads
+  def componentWillReceiveProps()
+    @committee = @@committee
+  end
+
+  # update committee from conformation form
+  def update(committee)
+    @committee = committee
+  end
+end
diff --git a/www/roster/views/pmc/pmc.js.rb b/www/roster/views/pmc/pmc.js.rb
new file mode 100644
index 0000000..136d3d5
--- /dev/null
+++ b/www/roster/views/pmc/pmc.js.rb
@@ -0,0 +1,179 @@
+#
+# Show PMC members
+#
+
+class PMCMembers < React
+  def initialize
+    @state = :closed
+  end
+
+  def render
+    _h2 'PMC'
+    _table.table.table_hover do
+      _thead do
+        _tr do
+          _th 'id'
+          _th 'public name'
+          _th 'starting date'
+        end
+      end
+
+      _tbody do
+        @roster.each do |person|
+          _PMCMember auth: @@auth, person: person, committee: @@committee
+        end
+
+        if @@auth
+          _tr onDoubleClick: self.select do
+            _td((@state == :open ? '' : "\u2795"), colspan: 4)
+          end
+        end
+      end
+    end
+
+   if @state == :open
+     _div.search_box do
+       _CommitterSearch add: self.add
+     end
+   end
+  end
+
+  # update props on initial load
+  def componentWillMount()
+    self.componentWillReceiveProps()
+  end
+
+  # compute roster
+  def componentWillReceiveProps()
+    roster = []
+    
+    for id in @@committee.roster
+      person = @@committee.roster[id]
+      person.id = id
+      roster << person
+    end
+
+    for id in @@committee.ldap
+      person = @@committee.roster[id]
+      if person
+        person.ldap = true
+      else
+        roster << {id: id, name: @@committee.ldap[id], ldap: true}
+      end
+    end
+
+    @roster = roster.sort_by {|person| person.name}
+  end
+
+  # open search box
+  def select()
+    return unless @@auth
+    window.getSelection().removeAllRanges()
+    @state = ( @state == :open ? :closed : :open )
+  end
+
+  # add a person to the displayed list of PMC members
+  def add(person)
+    person.date = 'pending'
+    @roster << person
+    @state = :closed
+  end
+end
+
+#
+# Show a member of the PMC
+#
+
+class PMCMember < React
+  def initialize
+    @state = :closed
+  end
+
+  def render
+    _tr onDoubleClick: self.select do
+      _td {_a @@person.id, href: "committer/#{@@person.id}"}
+      _td @@person.name
+      _td @@person.date
+
+      if @state == :open
+        _td data_id: @@person.id do 
+          if @@person.date == 'pending'
+            _button.btn.btn_primary 'Add as a committer and to the PMC',
+              # not added yet
+              data_action: 'add pmc commit',
+              data_target: '#confirm', data_toggle: 'modal',
+              data_confirmation: "Add #{@@person.name} to the " +
+                "#{@@committee.display_name} PMC and grant committer access?"
+
+            _button.btn.btn_warning 'Add to PMC only', data_target: '#confirm',
+              data_action: 'add pmc', data_toggle: 'modal',
+              data_confirmation: "Add #{@@person.name} to the " +
+                "#{@@committee.display_name} PMC?"
+          elsif not @@person.date
+            # in LDAP but not in committee-info.txt
+            _button.btn.btn_warning 'Remove from LDAP',
+              data_action: 'remove pmc', 
+              data_target: '#confirm', data_toggle: 'modal',
+              data_confirmation: "Remove #{@@person.name} from LDAP?"
+
+            _button.btn.btn_success 'Add to committee_info.txt',
+              disabled: true,
+              data_confirmation: "Add to #{@@person.name} committee_info.txt"
+          elsif not @@person.ldap
+             # in committee-info.txt but not in ldap
+            _button.btn.btn_success 'Add to LDAP',
+              data_action: 'add pmc', 
+              data_target: '#confirm', data_toggle: 'modal',
+              data_confirmation: "Add #{@@person.name} to LDAP?"
+
+            _button.btn.btn_warning 'Remove from committee_info.txt',
+              disabled: true,
+              data_confirmation: 
+                "Remove #{@@person.name} from committee_info.txt?"
+          else
+            # in both LDAP and committee-info.txt
+            _button.btn.btn_warning 'Remove from PMC',
+              data_action: 'remove pmc commit', 
+              data_target: '#confirm', data_toggle: 'modal',
+              data_confirmation: "Remove #{@@person.name} from the " +
+                "#{@@committee.display_name} PMC?"
+
+            if not @@committee.committers[@@person.id]
+              _button.btn.btn_primary 'Add as a committer',
+                data_action: 'add commit', 
+                data_target: '#confirm', data_toggle: 'modal',
+                data_confirmation: "Grant #{@@person.name} committer access?"
+            end
+          end
+        end
+      elsif not @@person.date
+        _td.issue 'not in committee_info.txt'
+      elsif not @@person.ldap
+        _td.issue 'not in LDAP'
+      elsif not @@committee.committers[@@person.id]
+        _td.issue 'not in committer list'
+      elsif @@person.id == @@committee.chair
+        _td.chair 'chair'
+      else
+        _td ''
+      end
+    end
+  end
+
+  # update props on initial load
+  def componentWillMount()
+    self.componentWillReceiveProps()
+  end
+
+  # automatically open pending entries
+  def componentWillReceiveProps()
+    @state = :open if @@person.date == 'pending'
+  end
+
+  # toggle display of buttons
+  def select()
+    return unless @@auth
+    window.getSelection().removeAllRanges()
+    @state = ( @state == :open ? :closed : :open )
+  end
+end