blob: a6afd74522c0bb8b8110634dc0676bc9789488ec [file] [log] [blame]
class Person < Vue
def initialize
@committer = {}
@response = nil
end
def render
# usage information for authenticated users (owner, secretary, etc.)
if @auth
_div.alert.alert_success 'Double click on a field in this color to edit.'
end
_h2 "#{@committer.id}@apache.org"
# Name
_PersonName person: self, edit: @edit
_div.row do
_div.name 'LDAP Create Date'
_div.value do
_ @committer.createTimestamp
end
end
# Personal URL
if @committer.urls || @auth
@committer.urls ||= []
_PersonUrls person: self, edit: @edit
end
# PMCs
noPMCsub = false
pmcs = @committer.pmcs
unless pmcs.empty?
_div.row do
_div.name 'PMCs'
_div.value do
_ul pmcs do |pmc|
_li {
_a pmc, href: "committee/#{pmc}"
if @committer.privateNosub
if @committer.privateNosub.include? pmc
noPMCsub = true
_b " (*)"
end
end
if @committer.chairOf.include? pmc
_ ' (chair)'
end
unless @committer.committees.include?(pmc)
_b ' (not in LDAP committee group)'
end
}
end
if noPMCsub
_br
_p {
_ '(*) could not find a subscription to the private@ mailing list for this PMC'
_br
_ 'Perhaps the subscription address is not listed in the LDAP record'
_br
_ '(Note that digest subscriptions are not currently included)'
}
end
end
end
end
# Committees
missingPMCs = false
committees = @committer.committees
unless committees.empty?
_div.row do
_div.name 'Committees'
_div.value do
noPMCsub = false
_ul committees do |pmc|
next if @committer.pmcs.include? pmc
missingPMCs = true
_li {
_a pmc, href: "committee/#{pmc}"
if @committer.chairOf.include? pmc
_ ' (chair)'
end
}
end
if missingPMCs
_ 'In LDAP committee group, but not on the corresponding PMC'
else
_ '(excludes PMCs listed above)'
end
end
end
end
# Committer
commit_list = @committer.committer
unless commit_list.all? {|pmc| committees.include? pmc}
_div.row do
_div.name 'Committer'
_div.value do
_ul commit_list do |pmc|
next if committees.include? pmc
_li {_a pmc, href: "committee/#{pmc}"}
end
end
end
end
# Groups
unless @committer.groups.empty?
_div.row do
_div.name 'Groups'
_div.value do
_ul @committer.groups do |group|
next if group == 'apldap'
if group == 'committers'
_li {_a group, href: "committer/"}
elsif group == 'member'
_li {_a group, href: "members"}
else
_li {_a group, href: "group/#{group}"}
end
if @committer.chairOf.length > 0 and not @committer.groups.include? 'pmc-chairs'
_ '[Missing: pmc-chairs]'
end
end
end
end
end
# Podlings
unless @committer.podlings.empty?
_div.row do
_div.name 'Podlings'
_div.value do
_ul @committer.podlings do |podlings|
_li {_a podlings, href: "ppmc/#{podlings}"}
end
end
end
end
# Non-PMCs
nonpmcs = @committer.nonpmcs
unless nonpmcs.empty?
_div.row do
_div.name 'non-PMCs'
_div.value do
_ul nonpmcs do |nonpmc|
_li {
_a nonpmc, href: "nonpmc/#{nonpmc}"
if @committer.nonPMCchairOf.include? nonpmc
_ ' (chair)'
end
}
end
end
end
end
# Email addresses
# always present
_PersonEmailForwards person: self, edit: @edit
# always present (even if an empty array)
_PersonEmailAlt person: self, edit: @edit
if @committer.email_other
_PersonEmailOther person: self # not editable
end
# Moderates
if @committer.moderates and @committer.moderates.keys().length > 0
_div.row do
_div.name 'Moderates'
_div.value do
_ul @committer.moderates.keys() do |list_name|
_li do
_a list_name, href: 'https://lists.apache.org/list.html?' +
list_name
_span " as "
_span @committer.moderates[list_name].join(', ')
end
end
_ "(last checked #{@committer.modtime})"
end
end
end
# subscriptions
if @committer.subscriptions
_div.row do
_div.name 'Subscriptions'
_div.value do
_ul @committer.subscriptions do |list_email|
_li do
_a list_email[0],
href: 'https://lists.apache.org/list.html?' + list_email[0]
_span " as "
_span list_email[1]
end
end
_ "(last checked #{@committer.subtime})"
end
end
end
# digests
if @committer.digests
_div.row do
_div.name 'Digest Subscriptions'
_div.value do
_ul @committer.digests do |list_email|
_li do
_a list_email[0],
href: 'https://lists.apache.org/list.html?' + list_email[0]
_span " as "
_span list_email[1]
end
end
_ "(last checked #{@committer.digtime})"
end
end
end
# PGP keys
if @committer.pgp || @auth
@committer.pgp ||= []
_PersonPgpKeys person: self, edit: @edit
end
# hosts
_div.row do
_div.name 'Host Access'
_div.value do
# pre avoids wrapping on hyphens and reduces number of lines on the page
_pre @committer.host.join(' ')
end
end
if @committer.inactive
_div.row do
_div.name 'Inactive (cannot login)'
_div.value @committer.inactive
end
end
# SSH keys
if @committer.ssh || @auth
@committer.ssh ||= []
_PersonSshKeys person: self, edit: @edit
end
# GitHub username
if @committer.githubUsername || @auth
@committer.githubUsername ||= []
_PersonGitHub person: self, edit: @edit
end
if @committer.member
_PersonMemberStatus person: self, edit: @edit
# Members.txt
if @committer.member.info
_PersonMemberText person: self, edit: @edit
end
if @committer.member.nomination
_div.row do
_div.name 'Nomination'
_div.value {_pre @committer.member.nomination}
end
end
end
# Forms on file (only present if env.user is a member)
if @committer.forms
_PersonForms person: self
end
# SpamAssassin score
_PersonSascore person: self, edit: @edit
# modal dialog for dry run results and errors
_div.modal.fade.wide_form tabindex: -1 do
_div.modal_dialog do
_div.modal_content do
_div.modal_header do
_button.close 'x', data_dismiss: 'modal'
_h4 @response_title
end
_div.modal_body do
_textarea value: @response, readonly: true
end
_div.modal_footer do
_button.btn.btn_default 'Close', data_dismiss: 'modal'
end
end
end
end
end
# initialize committer, determine if user is authorized to make
# changes, map Vue model to React model
def created()
@committer = @@committer
@auth = (@@auth.id == @@committer.id or @@auth.secretary or @@auth.root)
# map Vue model to React model
self.state = self['$data']
self.props = self['$props']
end
# on initial display, look for add editable rows, highlight them,
# and watch for double clicks on them
def mounted()
return unless @auth
Array(document.querySelectorAll('div.row[data-edit]')).each do |div|
div.addEventListener('dblclick', self.dblclick)
div.querySelector('div.name').classList.add 'bg-success'
end
end
# when a double click occurs, toggle the associated state
def dblclick(event)
row = event.currentTarget
if row.dataset.edit == @edit
@edit = nil
else
@edit = row.dataset.edit
end
window.getSelection().removeAllRanges()
end
# after update, register event listeners on forms
def updated()
Array(document.querySelectorAll('div[data-edit]')).each do |tr|
form = tr.querySelector('form')
if form
form.setAttribute 'data-action', tr.getAttribute('data-edit')
jQuery('input[type=submit],button', form).click(self.submit)
end
end
end
# submit form using AJAX
def submit(event)
event.preventDefault()
form = jQuery(event.currentTarget).closest('form')
target = event.target
# if (cancel) button is pressed, don't submit but remove @edit form
cancel_submit = target.getAttribute('data-cancel-submit')
if cancel_submit
# remove the edit buttons and return
@edit = nil
return
end
# serialize form
formData = form.serializeArray();
# add button if it has a value
if target and target.getAttribute('name') and target.getAttribute('value')
formData.push name: target.getAttribute('name'),
value: target.getAttribute('value')
end
# indicate dryrun is requested if option or control key is down
if event.altKey or event.ctrlKey
formData.unshift name: 'dryrun', value: true
end
# issue request
jQuery.ajax(
method: (form[0].method || 'GET').upcase(),
url: document.location.href + '/' + form[0].getAttribute('data-action'),
data: formData,
dataType: 'json',
success: ->(response) {
@committer = response.committer if response.committer
# turn off edit mode on this field
row = form.closest('.row')[0]
@edit = nil if row and row.dataset.edit == @edit
},
error: ->(response) {
json = response.responseJSON
if json.exception
@response_title = json.exception
@response = JSON.stringify(json, nil, 2)
jQuery('div.modal').modal('show')
else
alert response.statusText
end
},
complete: ->(response) do
json = response.responseJSON
# show results of dryrun
if formData[0] and formData[0].name == 'dryrun'
@response_title = 'Dry run results'
@response = JSON.stringify(json, nil, 2)
jQuery('div.modal').modal('show')
end
if json.error
@response_title = 'Error occurred'
@response = JSON.stringify(json, nil, 2)
jQuery('div.modal').modal('show')
elsif json.warn
alert json.warn
end
# reenable form for later reuse
jQuery('input, button', form).prop('disabled', false)
end
)
# disable input
jQuery('input, button', form).prop('disabled', true)
end
end