Jump to content

User:Another Article/workflowstudyclient.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
$(document).ready(function(){
  mw.loader.using( ['oojs-ui', 'mediawiki.util'] ).done( function () {
    $( "#pt-mytalk" ).before(
          $( "<li>" ).append( $( "<a>" )
            .text( "0 Q's" )
            .css( {
              "background-color": "lightgray",
              "color": "white",
              "border-radius": "2px",
              "padding": "0.12em 0.25em 0.12em",
              "cursor": "pointer",
              "font-weight": "bold",
              "transition": "background-color 0.5s"
            } )
            .attr("id", "survey_question_count")
          )
          .attr( "id", "pt-notifications-survey" )
        );
    var already_open = false;

    function update_after_submit(remaining_count)
    {
      if (remaining_count === 0)
      {
        $('#survey_question_count').text("Thx!");
        $('#pt-notifications-survey').unbind("click");
        $('#survey_question_count').css('background-color', 'lightgray');
      }
      else
      {
        $('#survey_question_count').text(remaining_count + " Q's");
      }
    }

      // Subclass ProcessDialog.
    function ProcessDialog( config ) {
      ProcessDialog.super.call( this, config );
    }
    OO.inheritClass( ProcessDialog, OO.ui.ProcessDialog );

    ProcessDialog.static.title = 'Edit Questions';
    ProcessDialog.static.actions = [
      { modes: ['beginning', 'middle', 'end', 'single'], action: 'submit', label: 'Submit', flags: [ 'primary', 'constructive' ] },
      { modes: ['beginning', 'middle', 'end', 'single'], label: 'Cancel', flags: 'safe' },
      { modes: ['middle', 'end'], action: 'prev', label: 'Previous' },
      { modes: ['beginning', 'middle'], action: 'next', label: 'Next' },
    ];

    ProcessDialog.prototype._get_diff_url = function(rev_id){
      return "https://en.wikipedia.org/w/index.php?diff=prev&oldid=" + rev_id;
    };

    ProcessDialog.prototype._get_prompt = function(data_entry){
        var d = new Date(data_entry['timestamp']);
        var time_stamp_string = d.toLocaleDateString() + " " + d.toLocaleTimeString();
        return new OO.ui.LabelWidget( {
          label: new OO.ui.HtmlSnippet(
            '<table style="width:100%"\
            <tr>\
                <th style="vertical-align:top"> Title: </th>\
                <td id="edit_title" >' + data_entry['title'] + '</td>\
            </tr>\
            <tr>\
                <th style="vertical-align:top"> Comment: </th>\
                <td id="edit_comment" >' + data_entry['comment'] + '</td>\
            </tr>\
            <tr>\
                <th style="vertical-align:top"> Edit time: </th>\
                <td id="edit_time" >' + time_stamp_string + '</td>\
            </tr>\
            <tr>\
                <th style="vertical-align:top"> Diff Link: </th>\
                <td id="edit_diff" >\
                <a id="edit_diff_link" href="' + this._get_diff_url(data_entry['revid']) + '" target="_blank">'+ data_entry['title'] +'</a> </td>\
            </tr>\
            </table>'
          )
        } );

    };

    ProcessDialog.prototype._get_panel = function (data_entry){
        if (data_entry['type'] == 'time')
        {
            return this._get_time_panel(data_entry)
        }
        else if (data_entry['type'] == 'process')
        {
            return this._get_process_panel(data_entry)
        }
        else if (data_entry['type'] == 'consent')
        {
            return this._get_consent_panel(data_entry)
        }
    }

    ProcessDialog.prototype._get_time_panel = function (data_entry){
      var prompt = this._get_prompt(data_entry)

      // Time allocated for edit
      var time_spent = new OO.ui.NumberInputWidget( {
        min: 0,
      } );
      time_spent.$element.width("33%")

      // Units being used
      var option1 = new OO.ui.ButtonOptionWidget( {
          data: 1,
          label: 'Seconds',
      } );
      var option2 = new OO.ui.ButtonOptionWidget( {
          data: 60,
          label: 'Minutes',
      } );
      var option3 = new OO.ui.ButtonOptionWidget( {
          data: 60*60,
          label: 'Hours',
      } );
      var time_units = new OO.ui.ButtonSelectWidget( {
          items: [ option1, option2, option3 ],
          tabindex: 2
      } );
      time_units.selectItem(option2);

      var work_type = new OO.ui.TextInputWidget( {
        rows: 3,
        multiline: true,
      } );

      var work_steps = new OO.ui.TextInputWidget( {
        rows: 3,
        multiline: true,
      } );

      var dont_ask = new OO.ui.CheckboxInputWidget({
        selected: false
      })
      // Putting all of the elements together
      var fieldset = new OO.ui.FieldsetLayout( {
      } );
      fieldset.addItems( [
          new OO.ui.FieldLayout( prompt, {
            label: 'All questions are with respect to the following edit.',
            align: 'top'
          } ),
          new OO.ui.FieldLayout( work_steps, {
              label: 'Describe all activities (both on-wiki and off-wiki) that contributed to this edit. These can range from editing the wiki-text to getting a book from the library.',
              align: 'top',
              help: 'This can include a description of how you found this article,\
                     the background research you had to do, any people you had to\
                     talk to, or anything else that you think led to this edit.'
          } ),
          new OO.ui.FieldLayout( work_type, {
              label: 'Describe the type of activity you were doing, e.g. copy-editing, revising section, adding illustrations.',
              align: 'top',
              help: 'Some examples would include: copy editing, creating new content,\
                     fact checking, wikifying, cleanup, adding illustrations, coordinating, etc.',
          } ),
          new OO.ui.FieldLayout( time_spent, {
              label: 'How much time did you spend working on this edit?',
              align: 'top',
              help: 'Estimate the amount of time that went into this edit\
                     as you did everything you described in the first question.'
          } ),
          new OO.ui.FieldLayout( time_units, {
            align:'right'
          }),
          new OO.ui.FieldLayout( dont_ask, {
            label: 'I don\'t feel like answering this one',
            align:'inline'
          }),
      ] );

      survey_questions = [];
      survey_questions['type'] = 'time';
      survey_questions['revid'] = data_entry['revid'];
      survey_questions['time_spent'] = time_spent;
      survey_questions['time_units'] = time_units;
      survey_questions['work_type'] = work_type;
      survey_questions['work_steps'] = work_steps;
      survey_questions['dont_ask'] = dont_ask;

      panel = new OO.ui.PanelLayout({
        expanded: false,
        framed: false,
        padded: true,
        $content: $(fieldset.$element),
        data: survey_questions
      });

      //panel.$element.append(fieldset.$element);
      return panel
    }

    ProcessDialog.prototype._get_process_panel = function (data_entry){
      var prompt = this._get_prompt(data_entry)

      var arrival_desc = new OO.ui.TextInputWidget( {
        rows: 4,
        multiline: true,
      } );

      var edit_motivation = new OO.ui.TextInputWidget( {
        rows: 4,
        multiline: true,
      } );

      var dont_ask = new OO.ui.CheckboxInputWidget({
        selected: false
      })
      // Putting all of the elements together
      var fieldset = new OO.ui.FieldsetLayout( {
      } );
      fieldset.addItems( [
          new OO.ui.FieldLayout( prompt, {
            label: 'All questions are with respect to the following edit.',
            align: 'top'
          } ),
          new OO.ui.FieldLayout( arrival_desc, {
              label: 'Describe how you got to this article.',
              align: 'top',
              help: 'Did you stumble upon it from personal interest? Did you \
                     find it as part of a project? Did someone ask you to look\
                     at it?'
          } ),
          new OO.ui.FieldLayout( edit_motivation, {
              label: 'What prompted you to make this specific edit?',
              align: 'top',
              help: 'Why was it important to you that this edit be made?'
          } ),
          new OO.ui.FieldLayout( dont_ask, {
            label: 'I don\'t feel like answering this one',
            align:'inline'
          }),
      ] );

      survey_questions = [];
      survey_questions['type'] = 'process';
      survey_questions['revid'] = data_entry['revid'];
      survey_questions['arrival_desc'] = arrival_desc;
      survey_questions['edit_motivation'] = edit_motivation;
      survey_questions['dont_ask'] = dont_ask;

      panel = new OO.ui.PanelLayout({
        expanded: false,
        framed: false,
        padded: true,
        $content: $(fieldset.$element),
        data: survey_questions
      });

      return panel
    }

    ProcessDialog.prototype._get_consent_prompt = function(data_entry){
        var d = new Date(data_entry['timestamp']);
        var time_stamp_string = d.toLocaleDateString() + " " + d.toLocaleTimeString();
        return new OO.ui.LabelWidget( {
          label: new OO.ui.HtmlSnippet(
            `<h1 id="consent-form">Consent form</h1>
<p>Thank you for enabling our survey! But first, we ask that you read the following information and ask any questions you may have before agreeing to participate.</p>
<h3 id="purpose-and-procedure">Purpose and Procedure</h3>
<p>We are working to better understand the process through which Wikipedians contribute to Wikipedia. We would like to hear about the process you use as you contribute and invite you to participate in this study. If you agree to participate our survey will be integrated into your Wikipedia experience. As you go about your normal activities the survey will occasionally notify you that we have a question about some of your recent contributions. Each set of questions should take less than 5 minutes to answer and we will never ask you more than 5 question sets in a day. The survey period will last for two weeks.</p>
<h3 id="contacts-and-questions">Contacts and Questions</h3>
<p>This survey is being conducted for research by the Grouplens Research Lab in the Computer Science and Engineering Department at the University of Minnesota. If you have any questions about this study, please feel free to contact the researchers at schir101@umn.edu. For general information about GroupLens, please visit our website at grouplens.org. If you have any questions or concerns regarding this study and would like to talk to someone other than the researchers, you are encouraged to contact the Research Subjects' Advocate Line, D528 Mayo, 420 Delaware St. Southeast, Minneapolis, MN 55455; (612) 625-1650.</p>
<h3 id="confidentiality">Confidentiality</h3>
<p>Your participation in this study will be kept private and your off-line identity will never be recorded. If at any point in the future you wish to withdraw your responses from this study you may contact us and they will be removed.</p>
<p>You may volunteer to have your responses publicly released for the benefit of other community members and researchers. If you choose to do so your responses and their associated revision id will be included in the publicly released data set. Note that while this will not include your username explicitly, it will be possible to recover your username from this data. If at any point in the future you wish to withdraw your responses from this public data set they will be removed from our hosted data set, although we will not be able to remove them from copies we do not control.</p>
<h3 id="participation-is-voluntary">Participation is Voluntary</h3>
<p>Participation in this study is voluntary. Your decision whether or not to participate will not affect your relationship with the University of Minnesota. If you decide to participate, you are free to not answer any question or withdraw at any time without affecting this relationship.</p>
<h3 id="statement-of-consent">Statement of Consent</h3>
<p>After reading the above passage, please select whether you consent to participate or not:<br />`
          )
        } );

    };

    ProcessDialog.prototype._get_consent_panel = function (data_entry){
        var prompt = this._get_consent_prompt(data_entry)

        var consent = new OO.ui.CheckboxInputWidget({
          selected: false
        })
        var make_public = new OO.ui.CheckboxInputWidget({
          selected: false
        })
        // Putting all of the elements together
        var fieldset = new OO.ui.FieldsetLayout( {
        } );
        fieldset.addItems( [
            new OO.ui.FieldLayout( prompt, {
              align: 'top'
            } ),
            new OO.ui.FieldLayout( consent, {
              label: 'I agree to participate',
              align:'inline'
            }),
            new OO.ui.FieldLayout( make_public, {
              label: 'I would like my responses released publicly so other researchers and community members can benefit from them.',
              align:'inline'
            }),
        ] );

        survey_questions = [];
        survey_questions['type'] = 'consent';
        survey_questions['consent'] = consent;
        survey_questions['make_public'] = make_public;

        panel = new OO.ui.PanelLayout({
          expanded: false,
          framed: false,
          padded: true,
          $content: $(fieldset.$element),
          data: survey_questions
        });

        return panel
    }

    ProcessDialog.prototype._send_data_from_stack_layout = function(stackLayout)
    {
      var count = 0;
      var panels = stackLayout.getItems();
      for(var i=panels.length - 1; i >= 0 ; i--)
      {
        var datum = this._get_data_from_panel(panels[i]);
        if (undefined !== datum)
        {
          $.post( "https://triton.grouplens.org:8000/api/v0.1/submit", datum);
          count++;
          this.data.splice(i,1);
        }
      }
      return count;
    }

    ProcessDialog.prototype._get_data_from_panel = function(panel)
    {
      survey_items = panel.data;
      if (survey_items['type'] == 'time')
      {
          return this._get_data_from_time_panel(survey_items)
      }
      else if (survey_items['type'] == 'process')
      {
          return this._get_data_from_process_panel(survey_items)
      }
      else if (survey_items['type'] == 'consent')
      {
          return this._get_data_from_consent_panel(survey_items)
      }
    };

    ProcessDialog.prototype._get_data_from_process_panel = function(survey_items)
    {
        revid = survey_items['revid'];
        arrival_desc = survey_items['arrival_desc'].value;
        edit_motivation = survey_items['edit_motivation'].value;
        dont_ask = survey_items['dont_ask'].isSelected();
        if ("" !== arrival_desc || "" !== edit_motivation || dont_ask)
        {
          return { type: 'process',
                  revid: revid,
                  arrival_desc: arrival_desc,
                  edit_motivation: edit_motivation,
                  dont_ask: dont_ask,
                 };
        }
        else
        {
          return undefined;
        }
    }

    ProcessDialog.prototype._get_data_from_time_panel = function(survey_items)
    {
        revid = survey_items['revid'];
        time_spent = survey_items['time_spent'].input.value;
        time_units = survey_items['time_units'].getSelectedItem().data;
        work_type = survey_items['work_type'].value;
        work_steps = survey_items['work_steps'].value;
        dont_ask = survey_items['dont_ask'].isSelected();
        if ("" !== time_spent || dont_ask)
        {
          return { type: 'time',
                  revid: revid,
                  time: time_spent * time_units,
                  work_type: work_type,
                  steps: work_steps,
                  dont_ask: dont_ask,
                 };
        }
        else
        {
          return undefined;
        }
    }

    ProcessDialog.prototype._get_data_from_consent_panel = function(survey_items)
    {
        agreed = survey_items['consent'].isSelected();
        make_public = survey_items['make_public'].isSelected();
        return { type: 'consent',
                 agreed: agreed,
                 make_public: make_public,
                 username: username
               };
    }

    ProcessDialog.prototype.initialize = function () {
      ProcessDialog.super.prototype.initialize.apply( this, arguments );

      this.current_element = 0;

      this.stackLayout= new OO.ui.StackLayout( )
      for(var i=0; i < this.data.length; i++)
      {
        panel = this._get_panel(this.data[i]);
        this.stackLayout.addItems([panel]);
      }
      this.$body.append( this.stackLayout.$element );
    };

    // Set up the initial mode of the window ('edit', in this example.)
    ProcessDialog.prototype.getSetupProcess = function ( data ) {
      return ProcessDialog.super.prototype.getSetupProcess.call( this, data )
      .next( function () {
        if (this.data.length > 1)
        {
          this.actions.setMode( 'beginning' );
        }
        else
        {
          this.actions.setMode( 'single' )
        }
      }, this );
    };

    // Use the getActionProcess() method to set the modes and displayed item.
    ProcessDialog.prototype.getActionProcess = function ( action ) {

      if ((action === 'prev') && (this.current_element > 0))
      {
        this.current_element--;
        this.stackLayout.setItem(this.stackLayout.items[this.current_element]);
      }
      else if ((action === 'next') && (this.current_element < this.stackLayout.getItems().length-1))
      {
        this.current_element++;
        this.stackLayout.setItem(this.stackLayout.items[this.current_element]);
      }
      else if (action === 'submit')
      {
        this._send_data_from_stack_layout(this.stackLayout);
        update_after_submit(this.data.length);
        this.close()
      }

      if (this.current_element === 0)
      {
        this.actions.setMode('beginning');
      }
      else if (this.current_element == this.stackLayout.getItems().length-1)
      {
        this.actions.setMode('end');
      }
      else
      {
        this.actions.setMode('middle');
      }
      return ProcessDialog.super.prototype.getActionProcess.call( this, action );
    };

    // Get dialog height.
    ProcessDialog.prototype.getBodyHeight = function () {
      var height = 0;
      var index;
      for (index = 0; this.stackLayout.items.length > index; index++){
        var temp = this.stackLayout.items[index].$element.outerHeight(true);
        if (temp > height)
        {
          height = temp;
        }
      }
      return height + 20;
    };

    ProcessDialog.prototype.teardown = function(data){
      already_open = false;
      return ProcessDialog.super.prototype.teardown.call( this, data )
    };

    function show_survey(event)
    {
      if (!already_open)
      {
        already_open = true;
        // Create and append the window manager.
        var windowManager = new OO.ui.WindowManager();
        $( 'body' ).append( windowManager.$element );

        // Create a new dialog window.
        var processDialog = new ProcessDialog( {
          size: 'large',
          data: event.data.data,
        } );

        // Add windows to window manager using the addWindows() method.
        windowManager.addWindows( [ processDialog ] );

        // Open the window.
        windowManager.openWindow( processDialog );
      }
    }
    var username = mw.config.get( 'wgUserName' ).replace(" ", "_");
    $.getJSON('https://triton.grouplens.org:8000/api/v0.1/prompts?username=' + username, function(question_data) {
      if (question_data.length > 0)
      {
        $('#survey_question_count').text(question_data.length  + " Q's");
        $('#pt-notifications-survey').click({data: question_data}, show_survey);
        $('#survey_question_count').css('background-color', 'green');
      }
    })
  })
})