| # |
| # Action items. Link to PMC reports when possible, highlight missing |
| # action item status updates. |
| # |
| |
| class ActionItems < Vue |
| def initialize |
| @disabled = false |
| end |
| |
| def render |
| first = true |
| |
| updates = Pending.status.keys() |
| |
| _section.flexbox do |
| _pre.report do |
| @@item.actions.each do |action| |
| |
| # skip actions that don't match the filter |
| if @@filter |
| match = true |
| for key in @@filter |
| match &&= (action[key] == @@filter[key]) |
| end |
| next unless match |
| end |
| |
| # space between items and add help info on top |
| if first |
| unless @@filter or Minutes.complete |
| _p.alert_info 'Click on Status to update' |
| end |
| |
| first = false |
| else |
| _ "\n" |
| end |
| |
| # action owner and text |
| _ "* #{action.owner}: #{action.text}\n " |
| |
| if action.pmc and not (@@filter and @@filter.title) |
| _ '[ ' |
| |
| # if there is an associated PMC and that PMC is on this month's |
| # agenda, link to the current report, if reporting this month |
| item = Agenda.find(action.pmc) |
| if item |
| _Link text: action.pmc, class: item.color, href: item.href |
| elsif action.pmc |
| _span.blank action.pmc |
| end |
| |
| # link to the original report |
| if action.date |
| _ ' ' |
| agenda = "board_agenda_#{action.date.gsub('-', '_')}.txt" |
| if Server.agendas.include? agenda |
| _a action.date, |
| href: "../#{action.date}/#{action.pmc.gsub(/\W/, '-')}" |
| else |
| _a action.date, href: |
| '/board/minutes/' + |
| action.pmc.gsub(/\W/, '_') + |
| "#minutes_#{action.date.gsub('-', '_')}" |
| end |
| end |
| _ " ]\n " |
| |
| elsif action.date |
| _ "[ #{action.date} ]\n " |
| end |
| |
| # launch edit dialog when there is a click on the status |
| options = {on: {click: self.updateStatus}, class: ['clickable']} |
| options = {} if Minutes.complete |
| options.attrs = {} |
| |
| # copy action properties to data attributes |
| for name in action |
| options.attrs["data-#{name}"] = action[name] |
| end |
| |
| # include pending updates |
| pending = Pending.find_status(action) |
| options.attrs['data-status'] = pending.status if pending |
| |
| Vue.createElement('span', options) do |
| # highlight missing action item status updates |
| if pending |
| _span "Status: " |
| pending.status.split("\n").each do |line| |
| match = line.match(/^( *)(.*)/) |
| _span match[1] |
| _em.commented "#{match[2]}\n" |
| end |
| elsif action.status == '' |
| _span.missing 'Status:' |
| _ "\n" |
| else |
| _Text raw: "Status: #{action.status}\n", filters: [hotlink] |
| end |
| end |
| end |
| |
| if first |
| _p {_em 'Empty'} |
| end |
| end |
| |
| if not first |
| # Update action item (hidden form) |
| _ModalDialog id: 'updateStatusForm', color: 'commented' do |
| _h4 'Update Action Item' |
| |
| _p do |
| _span "#@owner: #@text" |
| if @pmc |
| _ ' [ ' |
| _span " #@pmc" if @pmc |
| _span " #@date" if @date |
| _ ' ]' |
| end |
| end |
| |
| _textarea ref: 'statusText', label: 'Status:', value: @status, rows: 5 |
| |
| _button.btn_default 'Cancel', data_dismiss: 'modal', |
| disabled: @disabled |
| _button.btn_primary 'Save', onClick: self.save, |
| disabled: @disabled || (@baseline == @status) |
| end |
| end |
| end |
| |
| # Action Items Captured During the Meeting |
| if @@item.title == 'Action Items' |
| captured = [] |
| Minutes.actions.each do |action| |
| if @@filter |
| match = true |
| for key in @@filter |
| match &&= (action[key] == @@filter[key]) |
| end |
| next unless match |
| end |
| |
| captured << action |
| end |
| |
| unless captured.empty? |
| _section do |
| _h3 'Action Items Captured During the Meeting' |
| _pre.comment captured do |action| |
| # skip actions that don't match the filter |
| if @@filter |
| match = true |
| for key in @@filter |
| match &&= (action[key] == @@filter[key]) |
| end |
| next unless match |
| end |
| |
| _ "* #{action.owner}: #{action.text.gsub("\n", "\n ")}\n" |
| _ " [ " |
| if action.item |
| _Link text: action.item.title, href: action.item.href, |
| class: action.item.color |
| end |
| _ " #{Agenda.title} ]\n\n" |
| end |
| end |
| end |
| end |
| end |
| |
| # autofocus on action status in update action form |
| def mounted() |
| jQuery('#updateStatusForm').on 'shown.bs.modal' do |
| ~statusText.focus() |
| end |
| end |
| |
| # launch update status form when status text is clicked |
| def updateStatus(event) |
| parent = event.target.parentNode |
| |
| # construct action from data attributes |
| action = {} |
| for i in 0...parent.attributes.length |
| attr = parent.attributes[i] |
| action[attr.name[5..-1]] = attr.value if attr.name.start_with? 'data-' |
| end |
| |
| # unindent action |
| action.status.gsub!(/\n {14}/, "\n") |
| |
| # set baseline to current value |
| action.baseline = action.status |
| |
| # show dialog |
| jQuery('#updateStatusForm').modal(:show) |
| |
| # update state |
| self.setState(action) |
| end |
| |
| # when save button is pushed, post update and dismiss modal when complete |
| def save(event) |
| data = { |
| agenda: Agenda.file, |
| owner: @owner, |
| text: @text, |
| pmc: @pmc, |
| date: @date, |
| status: @status |
| } |
| |
| @disabled = true |
| post 'status', data do |pending| |
| jQuery(~updateStatusForm).modal(:hide) |
| @disabled = false |
| Pending.load pending |
| end |
| end |
| end |