You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whimsical.apache.org by cu...@apache.org on 2019/05/26 01:06:36 UTC

[whimsy] branch master updated (dab7d9a -> 59196ff)

This is an automated email from the ASF dual-hosted git repository.

curcuru pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/whimsy.git.


    from dab7d9a  Remove erroneous file (see officers/surveys.cgi)
     new 4dd16ab  Add metehods and fix several bugs/doc updates
     new 59196ff  Switch back to symbols; fix loading/display methods; update sample data

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 lib/whimsy/asf/forms.rb  |  48 ++++++++++++---
 www/officers/surveys.cgi | 148 ++++++++++++++++++++++++++++-------------------
 2 files changed, 128 insertions(+), 68 deletions(-)


[whimsy] 02/02: Switch back to symbols; fix loading/display methods; update sample data

Posted by cu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

curcuru pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/whimsy.git

commit 59196ff9797a935d129a3fc2c07260bb877d8ced
Author: Shane Curcuru <as...@shanecurcuru.org>
AuthorDate: Sat May 25 21:06:28 2019 -0400

    Switch back to symbols; fix loading/display methods; update sample data
---
 www/officers/surveys.cgi | 148 ++++++++++++++++++++++++++++-------------------
 1 file changed, 87 insertions(+), 61 deletions(-)

diff --git a/www/officers/surveys.cgi b/www/officers/surveys.cgi
index 443e62f..e927eff 100755
--- a/www/officers/surveys.cgi
+++ b/www/officers/surveys.cgi
@@ -1,5 +1,7 @@
 #!/usr/bin/env ruby
 PAGETITLE = "Whimsy Member and Officer Surveys" # Wvisible:members
+# survey_layout is read from JSON and displayed
+# Submissions are tracked by user login, and svn ci into a survey_data JSON
 $LOAD_PATH.unshift '/srv/whimsy/lib'
 
 require 'wunderbar'
@@ -7,16 +9,16 @@ require 'wunderbar/bootstrap'
 require 'wunderbar/jquery'
 require 'wunderbar/markdown'
 require 'whimsy/asf'
-require 'whimsy/asf/forms2'
+require 'whimsy/asf/forms'
 require 'whimsy/asf/rack'
 require 'json'
 require 'cgi'
 
 FOUNDATION_SVN = ASF::SVN['foundation'] # TODO check pathing
-SURVEY = 'survey'
+SURVEY = :survey
 SURVEYS_DIR = 'surveys'
-ERRORS = 'errors'
-PARAMS = 'params'
+ERRORS = :errors
+PARAMS = :params
 
 # Convenience method to display alerts
 def display_alert(lead: 'Error', body: '', type: 'alert-danger')
@@ -29,46 +31,40 @@ end
 # Emit HTML for a survey form, or display any errors
 # Currently, user can only submit a survey once
 def display_survey(survey_layout)
+  survey_layout[:dataroot] ? dataroot = survey_layout[:dataroot] : dataroot = 'foundation' # TODO this default is a bit of a hack
+  survey_layout[:datafile] ? datafile = survey_layout[:datafile] : datafile = ''
   if survey_layout.has_key?(ERRORS)
-    display_alert(lead: "Unable to read survey layout!", body: "#{survey_layout[ERRORS]}\n\nPlease check your query string params: #{survey_layout[PARAMS]} or check to see if the survey data is valid: #{survey_file}", type: 'alert-warning')
-  end
-  dataroot = survey_layout['dataroot']
-  datafile = survey_layout['datafile']
-  survey_file = "#{dataroot} /#{SURVEYS_DIR}/ #{datafile}"
-  if dataroot && datafile
-    survey_file = File.join(ASF::SVN[survey_layout['dataroot']], SURVEYS_DIR, datafile)
-    if File.file?(survey_file)
+    display_alert(lead: "Warning: could not find survey layout!", body: "#{survey_layout[ERRORS]}")
+    # Continue loading the DEFAULT_SURVEY which provides more help
+  elsif File.file?(survey_file)
+    survey_file = File.join(ASF::SVN[dataroot], SURVEYS_DIR, datafile)
+    survey_data = {}
+    begin
+      survey_data = JSON.parse(File.read(survey_file), :symbolize_names => true)
       # Check if the user has already submitted this survey
-      survey_data = {}
-      begin
-        survey_data = JSON.parse(File.read(survey_file))
-        if survey_data.has_key?($USER)
-          display_alert(lead: 'User already submitted survey', body: "You appear to have already submitted this survey (#{query}) once; if needed, edit the survey.json in SVN.")
-          # return # TODO should we bail or continue?
-        end
-      rescue StandardError => e
-        display_alert(lead: 'Error reading survey data file', body: "**ERROR:#{__method__}(#{query}) #{e.message}**\n\n    #{e.backtrace[0]}")
+      if survey_data.has_key?($USER.to_sym)
+        display_alert(lead: 'User already submitted survey!', body: "You appear to have already submitted this survey (#{query}) once; if needed, edit the survey.json in SVN.")
         # return # TODO should we bail or continue?
       end
-    else
-      display_alert(lead: "Unable to read survey data!", body: "#{survey_layout[ERRORS]}\n\nPlease check your query string params: #{survey_layout[PARAMS]} or check to see if the survey data is valid: #{survey_file}")
+    rescue StandardError => e
+      display_alert(lead: 'Error parsing survey layout!', body: "**ERROR:#{__method__}(#{query}) #{e.message}**\n\n    #{e.backtrace[0]}")
       # return # TODO should we bail or continue?
     end
   else
-    display_alert(lead: "Unable to read survey layout!", body: "#{survey_layout[ERRORS]}\n\nPlease check your query string params: #{survey_layout[PARAMS]} or check to see if the survey data is valid: #{survey_file}")
+    display_alert(lead: "Warning: could not find survey data!", body: "#{survey_layout[ERRORS]}\n\nPlease check your query string params: #{survey_layout[PARAMS]} or check to see if the survey data file is valid: #{survey_file}")
     # return # TODO should we bail or continue?
   end
 
-  # Emit the survey if no errors found
-  _whimsy_panel("#{survey_layout[SURVEY]['form']['title']}", style: 'panel-success') do
+  # Emit the survey, or the default one which provides more help
+  _whimsy_panel("#{survey_layout[SURVEY][:form][:title]}", style: 'panel-success') do
     _form.form_horizontal method: 'post' do
-      survey_layout[SURVEY]['form']['fields'].each do |field|
-        _whimsy_field_chooser(field) # DEBUG: How do properly pass this hash thru?
+      survey_layout[SURVEY][:form][:fields].each do |field|
+        _whimsy_field_chooser(field)
       end
       _div.col_sm_offset_3.col_sm_9 do
-        _span.text_info survey_layout[SURVEY]['form']['buttonhelp']
+        _span.text_info survey_layout[SURVEY][:form][:buttonhelp]
         _br
-        _input.btn.btn_default type: 'submit', value: survey_layout[SURVEY]['form']['buttontext']
+        _input.btn.btn_default type: 'submit', value: survey_layout[SURVEY][:form][:buttontext]
       end
     end
   end
@@ -84,7 +80,7 @@ end
 # Handle submission (checkout user's apacheid.json, write form data, checkin file)
 # @return true if we think it succeeded; false in all other cases
 def submit_survey(formdata: {})
-  fn = "#{survey_layout['datafile']}.json".untaint # TODO: check path/file here
+  fn = "#{formdata[:datafile]}.json".untaint # TODO: check path/file here
   submission_data = JSON.pretty_generate(formdata) + "\n"
   _div.well do
     _p.lead "Submitting your survey data to: #{fn}"
@@ -96,44 +92,71 @@ def submit_survey(formdata: {})
 end
 
 DEFAULT_SURVEY = {
-  'title' => 'Apache Whimsy Survey Tool',
-  'subtitle' => 'Survey Help Page',
-  'related' => {
+  title: 'Apache Whimsy Survey Tool',
+  subtitle: 'Survey Help Page',
+  related: {
     "committers/tools.cgi" => "All Whimsy Committer-wide Tools",
     "https://github.com/apache/whimsy/blob/master/www/" => "See Whimsy Source Code",
     "mailto:dev@whimsical.apache.org?subject=[FEEDBACK] Survey Tool" => "Email Feedback To dev@whimsical"
   },
-  'helpblock' => %q(The Whimsy Survey tool allows you to use an SVN-backed `survey.json` file to capture survey answers from Apache committers (all answers associated with apacheid and a commit.)
+  helpblock: %q(The Whimsy Survey tool allows you to use an SVN-backed `survey.json` file to capture survey answers from Apache committers (all answers associated with apacheid and a commit.)
 **If you are reading this**, then the survey you attempted to view has not be configured yet - sorry!
 For now, see the code for more help, or contact dev@whimsical for questions.
   ),
-  'dataroot' => '',
-  'datafile' => '',
-  'submitpass' => 'This *markdown-able* message would be displayed after a successful svn commit of survey data.',
-  'submitfail' => 'This *markdown-able* message would be displayed after a **FAILED** svn commit of survey data.',
-  'form' => {
-    'title' => 'Survey Form Title',
-    'buttonhelp' => 'This sample survey won\'t work, but you can still press Submit below!',
-    'buttontext' => 'Submit',
-    'fields' => [
+  dataroot: '',
+  datafile: '',
+  submitpass: 'This *markdown-able* message would be displayed after a successful svn commit of survey data.',
+  submitfail: 'This *markdown-able* message would be displayed after a **FAILED** svn commit of survey data.',
+  form: {
+    title: 'Survey Form Title',
+    buttonhelp: 'This sample survey won\'t work, but you can still press Submit below!',
+    buttontext: 'Submit',
+    fields: [
+      {
+        name: 'field1',
+        type: 'text',
+        label: 'This field is:',
+        helptext: 'This text would explain the field1 (optional)'
+      },
+      {
+        name: 'field2',
+        type: 'text',
+        rows: '3',
+        label: 'This is multiline:',
+        helptext: 'This text would explain the field2 (optional)'
+      },
+      {
+        name: 'subhead',
+        type: 'subhead',
+        label: 'This is a form separator'
+      },
+      {
+        name: 'field4',
+        type: 'select',
+        label: 'Select some values',
+        helptext: 'This text would explain why you should select many values (required)',
+        multiple: true,
+        options: ['First', 'Second', 'Penultimate', 'Last place']
+      },
       {
-        'name' => 'field1',
-        'type' => 'text',
-        'label' => 'This field is:',
-        'helptext' => 'This text would explain the field1 (optional)'
+        name: 'field5',
+        type: 'radio',
+        label: 'Radiobuttons:',
+        helptext: 'Please tune in the radio (optional)',
+        options: ['99.8', '100.0', '100.2', '100.4']
       },
       {
-        'name' => 'field2',
-        'type' => 'text',
-        'rows' => '3',
-        'label' => 'This is multiline:',
-        'helptext' => 'This text would explain the field2 (optional)'
+        name: 'field6',
+        type: 'checkbox',
+        label: 'Checkboxes:',
+        helptext: 'Check one, check them all, have fun! (optional)',
+        options: ['Abbot', 'Costello', 'Marx', 'Three Stooges']
       }
     ]
   }
 }
 # Return survey layout hash from QUERY_STRING
-# @return {} of form layout data for survey; or a default layout of help
+# @return {} of form layout data for survey; or a default layout of help with ERRORS also set
 # Note: does not validate that the survey has a place to store data; only that the layout exists
 def get_survey_layout(query)
   params = {}
@@ -143,14 +166,16 @@ def get_survey_layout(query)
   end
   data = {}
   data[PARAMS] = params
+  filename = File.join(FOUNDATION_SVN, SURVEYS_DIR, "#{params[SURVEY]}.json") # TODO FIXME
   begin
-    data[SURVEY] = JSON.parse(File.read(File.join(FOUNDATION_SVN, SURVEYS_DIR, "#{params[SURVEY]}.json").untaint)) # TODO: Security, ensure user should have access
+    data[SURVEY] = JSON.parse(File.read(filename).untaint) # TODO: Security, ensure user should have access
   rescue StandardError => e
     data[ERRORS] = "**ERROR:#{__method__}(#{query}) #{e.message}**\n\n    #{e.backtrace.join("\n    ")}"
   end
   # Fallback if not successfully read, so we can display something (even if it won't work to submit)
   if not data.has_key?(SURVEY)
     data[SURVEY] = DEFAULT_SURVEY
+    data[ERRORS] = "Could not read survey layout: #{filename}\n\nPlease check your query string params: #{params}; displaying help form below instead."
   end
   return data
 end
@@ -166,20 +191,21 @@ _html do
     query_string = ENV['QUERY_STRING']
     survey_layout = get_survey_layout(query_string)
     _whimsy_body(
-      title: survey_layout[SURVEY]['title'],
-      subtitle: survey_layout[SURVEY]['subtitle'],
-      related: survey_layout[SURVEY]['related'],
+      title: survey_layout[SURVEY][:title],
+      subtitle: survey_layout[SURVEY][:subtitle],
+      related: survey_layout[SURVEY][:related],
       helpblock: -> {
-        _markdown survey_layout[SURVEY]['helpblock']
+        _markdown survey_layout[SURVEY][:helpblock]
      }
     ) do
       # Display data to the user, depending if we're GET (a blank survey) or POST (show SVN checkin results)
       if _.post?
         formdata = _whimsy_params2formdata(_.params)
+        formdata[:datafile] = survey_layout[SURVEY][:datafile] # Also pass thru datafile from layout
         if validate_survey(formdata: formdata) && submit_survey(formdata: formdata)
-            display_alert(lead: 'Survey Submitted', body: survey_layout[SURVEY]['submitpass'], type: 'alert-success')
+            display_alert(lead: 'Survey Submitted', body: survey_layout[SURVEY][:submitpass], type: 'alert-success')
           else
-            display_alert(lead: 'Submission Failed', body: survey_layout[SURVEY]['submitfail'])
+            display_alert(lead: 'Submission Failed', body: survey_layout[SURVEY][:submitfail])
         end
       else # if _.post?
         display_survey(survey_layout)


[whimsy] 01/02: Add metehods and fix several bugs/doc updates

Posted by cu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

curcuru pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/whimsy.git

commit 4dd16abad4e358e8f0ac6661d0ff2473fbe27967
Author: Shane Curcuru <as...@shanecurcuru.org>
AuthorDate: Sat May 25 21:04:44 2019 -0400

    Add metehods and fix several bugs/doc updates
---
 lib/whimsy/asf/forms.rb | 48 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 41 insertions(+), 7 deletions(-)

diff --git a/lib/whimsy/asf/forms.rb b/lib/whimsy/asf/forms.rb
index fdb26bc..2889417 100644
--- a/lib/whimsy/asf/forms.rb
+++ b/lib/whimsy/asf/forms.rb
@@ -4,6 +4,25 @@ require 'wunderbar/markdown'
 # Define common page features for whimsy tools using bootstrap styles
 class Wunderbar::HtmlMarkup
 
+  # Emit a form control based on a hash of options with a type:
+  def _whimsy_field_chooser(**args)
+    case args[:type]
+    when 'subhead'
+      _whimsy_forms_subhead label: args[:label]
+    when 'text'
+      _whimsy_forms_input args
+    when 'textarea'
+      args[:rows] ||= '3'
+      _whimsy_forms_input args
+    when 'select'
+      _whimsy_forms_select args
+    when 'radio', 'checkbox'
+      _whimsy_forms_checkradio args
+    else
+      _div "#{__method__}(#{args[:type]}) TODO: Error condition?"
+    end
+  end
+
   # Utility function to add icons after form controls
   def _whimsy_forms_iconlink(**args)
     if args[:iconlink]
@@ -37,6 +56,14 @@ class Wunderbar::HtmlMarkup
     end
   end
 
+  # Display a subheader separator between sections of a form
+  # @param text string to display
+  def _whimsy_forms_subhead(label: 'Form Section')
+    _div.form_group do
+      _label.col_sm_offset_3.col_sm_9.strong.text_left label
+    end
+  end
+  
   # Display a single input control within a form; or if rows, then a textarea
   # @param name required string ID of control's label/id
   def _whimsy_forms_input(**args)
@@ -60,12 +87,13 @@ class Wunderbar::HtmlMarkup
   # Display an optionlist control within a form
   # @param name required string ID of control's label/id
   # @param options required ['value'] or {"value" => 'Label for value'} of all selectable values
-  # @param values required 'value' or ['value'] or {"value" => 'Label for value'} of all selected values
+  # @param values 'value' or ['value'] or {"value" => 'Label for value'} of all selected values
   # @param placeholder Currently displayed text if passed (not selectable)
   def _whimsy_forms_select(**args)
     return unless args[:name]
-    return unless args[:values]
+    return unless args[:options]
     args[:label] ||= 'Select value(s)'
+    args[:values] ||= []
     args[:id] = args[:name]
     args[:aria_describedby] = "#{args[:name]}_help" if args[:helptext]
     _whimsy_control_wrapper(args) do 
@@ -104,12 +132,9 @@ class Wunderbar::HtmlMarkup
     end
   end
 
-  CHECKBOX = 'checkbox'
-  RADIO = 'radio'
-
   # Display a list of radio or checkbox controls
   # @param name required string ID of control's label/id
-  # @param type required CHECKBOX|RADIO
+  # @param type required FORM_CHECKBOX|FORM_RADIO
   # @param options required ['value'...] or {"value" => 'Label for value'} of all values
   # @param selected optional 'value' or ['value'...] of all selected values
   def _whimsy_forms_checkradio(**args)
@@ -121,7 +146,6 @@ class Wunderbar::HtmlMarkup
     args[:aria_describedby] = "#{args[:name]}_help" if args[:helptext]
     args[:selected] = [args[:selected]] if args[:selected].kind_of?(String)
     _whimsy_control_wrapper(args) do 
-
       # Construct list of all :options; mark any that are in :selected 
       if args[:options].kind_of?(Array)
         args[:options].each do |val|
@@ -141,4 +165,14 @@ class Wunderbar::HtmlMarkup
     end
   end
 
+  # Gather POST form data into submission Hash
+  # @returns {field: 'string', field2: ['array', 'only for', 'multivalue'] ...}
+  def _whimsy_params2formdata(params)
+    formdata = {}
+    params.each do |k,v|
+      v && (v.length == 1) ? formdata[k] = v[0] : formdata[k] = v
+    end
+    return formdata
+  end
+
 end