Пример #1
0
  render() {
    return (
      <label htmlFor="selected-moderator">
        <strong className="ModeratedGrading__FinalGraderSelectMenuLabelText">
          {I18n.t('Grader that determines final grade')}
        </strong>

        <select
          className="ModeratedGrading__FinalGraderSelectMenu"
          id="selected-moderator"
          name="final_grader_id"
          onChange={this.handleSelectFinalGrader}
          value={this.state.selectedValue}
        >
          {this.state.selectedValue === '' && (
            <option key="select-grader" value="">
              {I18n.t('Select Grader')}
            </option>
          )}

          {this.props.availableModerators.map(user => (
            <option key={user.id} value={user.id}>
              {user.name}
            </option>
          ))}
        </select>
      </label>
    )
  }
function availableGradersText(maxGraderCount) {
  if (maxGraderCount === 1) {
    return I18n.t('There is currently 1 available grader')
  }

  return I18n.t('There are currently %{maxGraderCount} available graders', {maxGraderCount})
}
Пример #3
0
 renderTokenInput = () => {
   if (this.props.disabled) {
     return (
       <DisabledTokenInput tokens={_.pluck(this.props.tokens, 'name')} ref="DisabledTokenInput" />
     )
   }
   const ariaLabel = I18n.t(
     'Add students by searching by name, course section or group.' +
       ' After entering text, navigate results by using the down arrow key.' +
       ' Select a result by using the Enter key.'
   )
   return (
     <div>
       <div id="ic-tokeninput-description" className="screenreader-only">
         {I18n.t(
           'Use this list to remove assigned students. Add new students with combo box after list.'
         )}
       </div>
       <TokenInput
         menuContent={this.optionsForMenu()}
         selected={this.props.tokens}
         onFocus={this.handleFocus}
         onInput={this.handleInput}
         onSelect={this.handleTokenAdd}
         tokenAriaFunc={this.overrideTokenAriaLabel}
         onRemove={this.handleTokenRemove}
         combobox-aria-label={ariaLabel}
         value
         showListOnFocus={!this.props.disabled}
         ref="TokenInput"
       />
     </div>
   )
 }
Пример #4
0
 function updateRemoveLinkAltText(fileInput) {
   var altText = I18n.t("remove empty attachment");
   if(fileInput.val()){
     var filename = fileInput.val().replace(/^.*?([^\\\/]*)$/, '$1');
     altText = I18n.t("remove %{filename}", {filename: filename})
   }
   fileInput.parent().find('img').attr("alt", altText)
 }
Пример #5
0
  initializeDateGroups() {
    const assignments = _.flatten(this.assignmentGroups.map(ag => ag.get('assignments').models))
    const dated = _.select(assignments, a => a.dueAt())
    const undated = _.difference(assignments, dated)
    const past = []
    const overdue = []
    const upcoming = []
    _.each(dated, a => {
      if (new Date() < Date.parse(a.dueAt())) return upcoming.push(a)

      const isOverdue = a.allowedToSubmit() && a.withoutGradedSubmission()
      // only handles observer observing one student, this needs to change to handle multiple users in the future
      const canHaveOverdueAssignment =
        !ENV.current_user_has_been_observer_in_this_course ||
        (ENV.observed_student_ids && ENV.observed_student_ids.length) === 1

      if (isOverdue && canHaveOverdueAssignment) return overdue.push(a)
      past.push(a)
    })

    const overdue_group = new AssignmentGroup({
      id: 'overdue',
      name: I18n.t('overdue_assignments', 'Overdue Assignments'),
      assignments: overdue
    })
    const upcoming_group = new AssignmentGroup({
      id: 'upcoming',
      name: I18n.t('upcoming_assignments', 'Upcoming Assignments'),
      assignments: upcoming
    })
    const undated_group = new AssignmentGroup({
      id: 'undated',
      name: I18n.t('undated_assignments', 'Undated Assignments'),
      assignments: undated
    })
    const past_group = new AssignmentGroup({
      id: 'past',
      name: I18n.t('past_assignments', 'Past Assignments'),
      assignments: past
    })

    const sorted_groups = this._sortGroups(overdue_group, upcoming_group, undated_group, past_group)

    this.groupedByAG = this.assignmentGroups.models
    this.groupedByDate = sorted_groups

    return this.setAssignmentGroups()
  }
Пример #6
0
  render() {
    return (
      <div
        className="Container__DueDateRow-item"
        role="region"
        aria-label={I18n.t('Due Date Set')}
        data-row-key={this.props.rowKey}
      >
        {this.removeLinkIfNeeded()}
        <DueDateTokenWrapper
          tokens={this.tokenizedOverrides()}
          disabled={this.props.inputsDisabled}
          handleTokenAdd={this.props.handleTokenAdd}
          handleTokenRemove={this.props.handleTokenRemove}
          potentialOptions={this.props.validDropdownOptions}
          rowKey={this.props.rowKey}
          defaultSectionNamer={this.props.defaultSectionNamer}
          currentlySearching={this.props.currentlySearching}
          allStudentsFetched={this.props.allStudentsFetched}
        />

        <DueDateCalendars
          dates={this.props.dates}
          disabled={this.props.inputsDisabled}
          rowKey={this.props.rowKey}
          overrides={this.props.overrides}
          replaceDate={this.props.replaceDate}
          sections={this.props.sections}
          dueDatesReadonly={this.props.dueDatesReadonly}
          availabilityDatesReadonly={this.props.availabilityDatesReadonly}
        />
        {this.renderClosedGradingPeriodNotification()}
      </div>
    )
  }
Пример #7
0
  promptText = () => {
    if (this.currentlySearching()) {
      return I18n.t('Searching')
    }

    if (
      (this.state.userInput.length < this.MINIMUM_SEARCH_LENGTH &&
        !this.props.allStudentsFetched) ||
      this.hidingValidMatches()
    ) {
      return I18n.t('Continue typing to find additional sections or students.')
    }

    if (_.isEmpty(this.filteredTags())) {
      return I18n.t('No results found')
    }
  }
Пример #8
0
 renderToggle() {
   ReactDOM.render(
     <RadioInputGroup
       description={<ScreenReaderContent>{I18n.t('Show By')}</ScreenReaderContent>}
       size="medium"
       name="show_by"
       variant="toggle"
       defaultValue={this.showByDate() ? 'date' : 'type'}
       onChange={this.toggleShowBy.bind(this)}
     >
       <RadioInput id="show_by_date" label={I18n.t('Show by Date')} value="date" context="off" />
       <RadioInput id="show_by_type" label={I18n.t('Show by Type')} value="type" context="off" />
     </RadioInputGroup>
     ,
     this.el
   )
 }
Пример #9
0
 render() {
   return (
     <div className="DueDateRow__RemoveRow">
       <button
         className="Button Button--link"
         onClick={this.props.handleClick}
         ref="removeRowIcon"
         href="#"
         title={I18n.t('Remove These Dates')}
         aria-label={I18n.t('Remove These Dates')}
         type="button"
       >
         <i className="icon-x" role="presentation" />
       </button>
     </div>
   )
 }
Пример #10
0
 $.each(uploadedAttachmentIds.split(","), function(index, id) {
   if (id.length > 0) {
     var ext = $("#uploaded_files .file_" + id + " .name").text().split('.').pop().toLowerCase();
     if ($.inArray(ext, ENV.SUBMIT_ASSIGNMENT.ALLOWED_EXTENSIONS) < 0) {
       badExt = true;
       $.flashError(I18n.t('#errors.wrong_file_extension', 'The file you selected with extension "%{extension}", is not authorized for submission', {extension: ext}));
     }
   }
 });
Пример #11
0
 $("#media_media_recording_submission").mediaComment('create', 'any', function(id, type) {
   $("#submit_media_recording_form .submit_button").attr('disabled', false).text(I18n.t('buttons.submit_assignment', "Submit Assignment"));
   $("#submit_media_recording_form .media_comment_id").val(id);
   $("#submit_media_recording_form .media_comment_type").val(type);
   $("#media_media_recording_submission_holder").children().hide();
   $("#media_media_recording_ready").show();
   $("#media_comment_submit_button").attr('disabled', false);
   $("#media_media_recording_thumbnail").attr('id', 'media_comment_' + id);
 });
Пример #12
0
 $(".submit_assignment_link").click(function(event, skipConfirmation) {
   event.preventDefault();
   var late = $(this).hasClass('late');
   var now = new Date();
   if(late && !skipConfirmation) {
     var result;
     if($(".resubmit_link").length > 0) {
       result = confirm(I18n.t('messages.now_overdue', "This assignment is now overdue.  Any new submissions will be marked as late.  Continue anyway?"));
     } else {
       result = confirm(I18n.t('messages.overdue', "This assignment is overdue.  Do you still want to submit it?"));
     }
     if(!result) { return; }
   }
   $("#submit_assignment").show();
   $(".submit_assignment_link").hide();
   $("html,body").scrollTo($("#submit_assignment"));
   createSubmitAssignmentTabs();
   homeworkSubmissionLtiContainer.loadExternalTools();
   $("#submit_assignment_tabs li").first().focus();
 });
Пример #13
0
  headerOption = (heading, set) => {
    const headerText = {
      student: I18n.t('Student'),
      course_section: I18n.t('Course Section'),
      group: I18n.t('Group'),
      conditional_release: I18n.t('Mastery Paths')
    }[heading]

    const canSelect = heading === 'conditional_release'
    return (
      <ComboboxOption
        isFocusable={canSelect}
        className="ic-tokeninput-header"
        value={heading}
        key={heading}
        set_props={set}
      >
        {headerText}
      </ComboboxOption>
    )
  }
 // load external tools and populate 'More' tab with the returned tools
 loadExternalTools() {
   if (this.externalToolCollection.length > 0) {
     $('.submit_from_external_tool_option')
       .parent()
       .show() // display the 'More' tab
     this.toolsForm.find('ul.tools').empty()
     this.externalToolCollection.forEach(tool => {
       this.addToolToMoreList(tool)
     })
   } else {
     return this.toolsForm.find('ul.tools li').text(I18n.t('no_tools_found', 'No tools found'))
   }
 }
Пример #15
0
 render() {
   return (
     <div
       className="ic-Form-control"
       data-row-identifier={this.rowIdentifier()}
       onKeyDown={this.suppressKeys}
     >
       <div id="assign-to-label" className="ic-Label" title="Assign to" aria-label="Assign to">
         {I18n.t('Assign to')}
       </div>
       {this.renderTokenInput()}
     </div>
   )
 }
  generateMessages(newValue, eventType) {
    if (newValue === '' && eventType !== 'blur') {
      return []
    } else if (newValue === '0' || newValue === '') {
      return [{text: I18n.t('Must have at least 1 grader'), type: 'error'}]
    }

    const current = parseInt(newValue, 10)
    if (current > this.props.maxGraderCount) {
      return [{text: availableGradersText(this.props.maxGraderCount), type: 'hint'}]
    }

    return []
  }
Пример #17
0
  $("#submit_google_doc_form").submit(function() {
    // make sure we have a document selected
    if (!$("#submit_google_doc_form").find("input[name='google_doc[document_id]']").val()){
      return false
    }

    $("#uploading_google_doc_message").dialog({
      title: I18n.t('titles.uploading', "Uploading Submission"),
      modal: true,
      overlay: {
        backgroundColor: "#000",
        opacity: 0.7
      }
    });
  });
Пример #18
0
 $(document).ready(function() {
   $("#submit_media_recording_form .submit_button").attr('disabled', true).text(I18n.t('messages.record_before_submitting', "Record Before Submitting"));
   $("#media_media_recording_submission_holder .record_media_comment_link").click(function(event) {
     event.preventDefault();
     $("#media_media_recording_submission").mediaComment('create', 'any', function(id, type) {
       $("#submit_media_recording_form .submit_button").attr('disabled', false).text(I18n.t('buttons.submit_assignment', "Submit Assignment"));
       $("#submit_media_recording_form .media_comment_id").val(id);
       $("#submit_media_recording_form .media_comment_type").val(type);
       $("#media_media_recording_submission_holder").children().hide();
       $("#media_media_recording_ready").show();
       $("#media_comment_submit_button").attr('disabled', false);
       $("#media_media_recording_thumbnail").attr('id', 'media_comment_' + id);
     });
   });
 });
  render() {
    return (
      <fieldset>
        <div className={`form-column-${direction('left')}`}>{I18n.t('Moderated Grading')}</div>
        <div className="ModeratedGrading__Container">
          <div className="border border-trbl border-round">
            <ModeratedGradingCheckbox
              checked={this.state.moderatedGradingChecked}
              gradedSubmissionsExist={this.props.gradedSubmissionsExist}
              isGroupAssignment={this.props.isGroupAssignment}
              isPeerReviewAssignment={this.props.isPeerReviewAssignment}
              onChange={this.handleModeratedGradingChange}
            />

            {this.state.moderatedGradingChecked && (
              <div className="ModeratedGrading__Content">
                <GraderCountNumberInput
                  currentGraderCount={this.props.currentGraderCount}
                  maxGraderCount={this.props.maxGraderCount}
                  locale={this.props.locale}
                />

                <GraderCommentVisibilityCheckbox
                  checked={this.props.graderCommentsVisibleToGraders}
                  onChange={this.props.onGraderCommentsVisibleToGradersChange}
                />

                <FinalGraderSelectMenu
                  availableModerators={this.props.availableModerators}
                  finalGraderID={this.props.finalGraderID}
                />

                <GraderNamesVisibleToFinalGraderCheckbox
                  checked={this.props.graderNamesVisibleToFinalGrader}
                />
              </div>
            )}
          </div>
        </div>
      </fieldset>
    )
  }
Пример #20
0
 function uploadFileFromUrl() {
   const preflightUrl = $("#homework_file_url").attr('href');
   const preflightData = {
     url: $("#external_tool_url").val(),
     name: $("#external_tool_filename").val(),
     content_type: $("#external_tool_content_type").val()
   };
   const uploadPromise = uploadFile(preflightUrl, preflightData, null)
     .then((attachment) => {
       $("#external_tool_submission_type").val('online_upload');
       $("#external_tool_file_id").val(attachment.id);
       $tools.submit();
     })
     .catch((error) => {
       console.log(error);
       $tools.find(".submit").text(I18n.t('file_retrieval_error', "Retrieving File Failed"));
       $.flashError(I18n.t("invalid_file_retrieval", "There was a problem retrieving the file sent from this tool."));
     });
   $tools.disableWhileLoading(uploadPromise, {buttons: {'.submit': I18n.t('getting_file', 'Retrieving File...')}});
   return uploadPromise;
 };
 render() {
   const label = (
     <strong className="ModeratedGrading__GraderCountInputLabelText">
       {I18n.t('Number of graders')}
     </strong>
   )
   return (
     <div className="ModeratedGrading__GraderCountInputContainer">
       <NumberInput
         value={this.state.graderCount.toString()}
         label={label}
         locale={this.props.locale}
         max={this.props.maxGraderCount.toString()}
         messages={this.state.messages}
         min="1"
         name="grader_count"
         onChange={e => { if (e.type !== 'blur') this.handleNumberInputChange(e.target.value)}}
         onBlur={e => this.handleNumberInputBlur(e.target.value)}
         showArrows={false}
         width="5rem"
       />
     </div>
   )
 }
Пример #22
0
 .catch((error) => {
   console.log(error);
   $tools.find(".submit").text(I18n.t('file_retrieval_error', "Retrieving File Failed"));
   $.flashError(I18n.t("invalid_file_retrieval", "There was a problem retrieving the file sent from this tool."));
 });
Пример #23
0
 ).focus(function () {
   $(this).height(tabHelperHeight + 'px')
   var joke = document.createTextNode(I18n.t('Q: What goes black, white, black, white?  A: A panda rolling down a hill.'))
   this.appendChild(joke)
 }).blur(function () {
Пример #24
0
 dialogCancelHandler: function(event, ui) {
   var r = confirm(I18n.t("Are you sure you want to cancel? Changes you made may not be saved."));
   if (r == false){
     event.preventDefault();
   }
 }
Пример #25
0
 error: function(data) {
   submissionForm.find("button[type='submit']").text(I18n.t('messages.submit_failed', "Submit Failed, please try again"));
   submissionForm.find("button").attr('disabled', false);
 }
Пример #26
0
 $(window).on('beforeunload', function(e) {
   if($("#submit_assignment:visible").length > 0 && !submitting) {
     e.returnValue = I18n.t('messages.not_submitted_yet', "You haven't finished submitting your assignment.  You still need to click \"Submit\" to finish turning it in.  Do you want to leave this page anyway?");
     return e.returnValue;
   }
 });
Пример #27
0
 beforeUnloadHandler: function(e) {
   return (e.returnValue = I18n.t("Changes you made may not be saved."));
 },
Пример #28
0
    submissionForm.submit(function(event) {
      var self = this;
      var $turnitin = $(this).find(".turnitin_pledge");
      var $vericite = $(this).find(".vericite_pledge");
      if($("#external_tool_submission_type").val() == "online_url_to_file") {
        event.preventDefault();
        event.stopPropagation();
        uploadFileFromUrl();
        return;
      }

      if (!verifyPledgeIsChecked($turnitin)) {
        event.preventDefault()
        event.stopPropagation()
        return false;
      }

      if (!verifyPledgeIsChecked($vericite)) {
        event.preventDefault()
        event.stopPropagation()
        return false;
      }

      var valid = !$(this).is('#submit_online_text_entry_form') || $(this).validateForm({
        object_name: 'submission',
        required: ['body']
      });
      if (!valid) return false;

      $(this).find("button[type='submit']").text(I18n.t('messages.submitting', "Submitting..."));
      $(this).find("button").attr('disabled', true);
      if($(this).attr('id') == 'submit_online_upload_form') {
        event.preventDefault() && event.stopPropagation();
        var fileElements = $(this).find('input[type=file]:visible').filter(function() {
          return $(this).val() !== '';
        });

        var emptyFiles = $(this).find('input[type=file]:visible').filter(function() {
          return this.files[0] && this.files[0].size === 0;
        });

        var uploadedAttachmentIds = $(this).find('#submission_attachment_ids').val();

        var reenableSubmitButton = function () {
          $(self).find('button[type=submit]')
              .text(I18n.t('#button.submit_assignment', 'Submit Assignment'))
              .prop('disabled', false);
        };

        // warn user if they haven't uploaded any files
        if (fileElements.length === 0 && uploadedAttachmentIds === '') {
          $.flashError(I18n.t('#errors.no_attached_file', 'You must attach at least one file to this assignment'));
          reenableSubmitButton();
          return false;
        }

        // throw error if the user tries to upload an empty file
        // to prevent S3 from erroring
        if (emptyFiles.length) {
          $.flashError(I18n.t('Attached files must be greater than 0 bytes'));
          reenableSubmitButton();
          return false;
        }

        // If there are restrictions on file type, don't accept submission if the file extension is not allowed
        if(ENV.SUBMIT_ASSIGNMENT.ALLOWED_EXTENSIONS.length > 0) {
          var subButton = $(this).find('button[type=submit]');
          var badExt = false;
          $.each(uploadedAttachmentIds.split(","), function(index, id) {
            if (id.length > 0) {
              var ext = $("#uploaded_files .file_" + id + " .name").text().split('.').pop().toLowerCase();
              if ($.inArray(ext, ENV.SUBMIT_ASSIGNMENT.ALLOWED_EXTENSIONS) < 0) {
                badExt = true;
                $.flashError(I18n.t('#errors.wrong_file_extension', 'The file you selected with extension "%{extension}", is not authorized for submission', {extension: ext}));
              }
            }
          });
          if(badExt) {
            subButton
              .text(I18n.t('#button.submit_assignment', 'Submit Assignment'))
              .prop('disabled', false);
            return false;
          }
        }

        $.ajaxJSONPreparedFiles.call(this, {
          handle_files: function(attachments, data) {
            var ids = (data['submission[attachment_ids]'] || "").split(",");
            for(var idx in attachments) {
              ids.push(attachments[idx].id);
            }
            data['submission[attachment_ids]'] = ids.join(",");
            return data;
          },
          context_code: $("#submit_assignment").data('context_code'),
          asset_string: $("#submit_assignment").data('asset_string'),
          intent: "submit",
          file_elements: fileElements,
          formData: $(this).getFormData(),
          formDataTarget: 'url',
          url: $(this).attr('action'),
          success: function(data) {
            submitting = true;
            window.location = window.location.href.replace(/\#$/g, "").replace(window.location.hash, "");
          },
          error: function(data) {
            submissionForm.find("button[type='submit']").text(I18n.t('messages.submit_failed', "Submit Failed, please try again"));
            submissionForm.find("button").attr('disabled', false);
          }
        });
      } else {
        submitting = true;
      }
    });
Пример #29
0
    //  Everyone v Everyone Else
    // --------------------------

    defaultSectionNamer(sectionID){
      if (sectionID !== this.props.defaultSectionId) return null

      var onlyDefaultSectionChosen = _.isEqual(this.chosenSectionIds(), [sectionID])
      var noSectionsChosen = _.isEmpty(this.chosenSectionIds())

      var noGroupsChosen = _.isEmpty(this.chosenGroupIds())
      var noStudentsChosen = _.isEmpty(this.chosenStudentIds())

      var defaultSectionOrNoSectionChosen = onlyDefaultSectionChosen || noSectionsChosen

      if ( defaultSectionOrNoSectionChosen && noStudentsChosen && noGroupsChosen) {
        return I18n.t("Everyone")
      }
      return I18n.t("Everyone Else")
    },

    addStudentIfInClosedPeriod(gradingPeriodsHelper, students, dueDate, studentID) {
      const student = this.state.students[studentID]

      if (student && gradingPeriodsHelper.isDateInClosedGradingPeriod(dueDate)) {
        students = students.concat(student)
      }

      return students
    },

    studentsInClosedPeriods() {
Пример #30
0
 var reenableSubmitButton = function () {
   $(self).find('button[type=submit]')
       .text(I18n.t('#button.submit_assignment', 'Submit Assignment'))
       .prop('disabled', false);
 };