Beispiel #1
0
    def get_schema(self, handler):
        runtime = None
        names_and_descriptions = None

        # Treat as module-protected. pylint: disable=protected-access
        try:
            runtime = _get_runtime(handler.app_context)
            tool_configs = runtime.get_tool_configs()
            names_and_descriptions = sorted([(tool.name, tool.description)
                                             for tool in tool_configs.values()
                                             ])
        except:  # Broad on purpose. pylint: disable=bare-except
            pass

        if not names_and_descriptions:
            return self.unavailable_schema(
                'No LTI tools available. Either they have not been configured, '
                'or the configuration contains syntax errors.')

        reg = schema_fields.FieldRegistry(self.name())
        reg.add_property(
            schema_fields.SchemaField(
                'tool',
                'Tool',
                'string',
                optional=True,
                select_data=names_and_descriptions,
                description='The LTI tool you '
                'wish to embed. If you do not see your tool, you first need to '
                'configure the LTI tools for your course.'))
        reg.add_property(
            schema_fields.SchemaField(
                fields.RESOURCE_LINK_ID,
                'Resource Link ID',
                'string',
                extra_schema_dict_values={
                    'value': runtime.get_default_resource_link_id()
                },
                description=
                'The resource_link_id you wish to transmit to the LTI '
                'provider. Different providers attach different meanings to this '
                'value; consult your LTI provider to determine the correct value '
                'here. By default, we use the course URL slug.'))
        reg.add_property(
            schema_fields.SchemaField(
                'width',
                'Width',
                'integer',
                extra_schema_dict_values={'value': self._DEFAULT_WIDTH},
                description='The width of the rendered LTI tool, in pixels'))
        reg.add_property(
            schema_fields.SchemaField(
                'height',
                'Height',
                'integer',
                extra_schema_dict_values={'value': self._DEFAULT_HEIGHT},
                description='The height of the rendered LTI tool, in pixels'))
        reg.add_property(
            schema_fields.SchemaField(
                'extra_fields',
                'Extra Fields',
                'text',
                optional=True,
                description=
                'YAML of optional fields to transmit in the LTI launch '
                'request. See the LTI spec at '
                'http://www.imsglobal.org/lti/index.html for the lists of '
                'supported fields.'))

        return reg
Beispiel #2
0
    def setUp(self):
        super(StructureRecursionTests, self).setUp()
        parent = schema_fields.FieldRegistry('parent_dict_title')
        child = parent.add_sub_registry('child_dict_name', 'child_dict_title')

        simple_array_type = schema_fields.SchemaField(
            'simple_array_type_name', 'simple_array_type_title', 'type1')
        parent.add_property(
            schema_fields.FieldArray('simple_array_prop_name',
                                     'simple_array_prop_label',
                                     item_type=simple_array_type))

        complex_array_type = schema_fields.FieldRegistry(
            'complex_array_type_title')
        array_child = complex_array_type.add_sub_registry(
            'complex_array_child_name', 'array_child_title')

        parent.add_property(
            schema_fields.FieldArray('complex_array_prop_name',
                                     'complex_array_prop_label',
                                     item_type=complex_array_type))
        parent.add_property(
            schema_fields.SchemaField('parent_prop', 'X', 'type2'))
        child.add_property(
            schema_fields.SchemaField('child_prop', 'X', 'type3'))
        complex_array_type.add_property(
            schema_fields.SchemaField('complex_array_type_prop', 'X', 'type4'))
        array_child.add_property(
            schema_fields.SchemaField('array_child_p1', 'X', 'type5'))
        array_child.add_property(
            schema_fields.SchemaField('array_child_p2', 'X', 'type6'))
        self.schema = parent

        self.entity = {
            "parent_prop":
            "parent_prop_value",
            "child_dict_name": {
                "child_prop": "child_prop_value"
            },
            "simple_array_prop_name": [
                "simple_array_prop_value_000", "simple_array_prop_value_001",
                "simple_array_prop_value_002"
            ],
            "complex_array_prop_name": [{
                "complex_array_type_prop": "complex_array_prop_value_000",
                "complex_array_child_name": {
                    "array_child_p1": "array_child_p1_value_000",
                    "array_child_p2": "array_child_p2_value_000"
                }
            }, {
                "complex_array_type_prop": "complex_array_prop_value_001",
                "complex_array_child_name": {
                    "array_child_p1": "array_child_p1_value_001",
                    "array_child_p2": "array_child_p2_value_001"
                }
            }, {
                "complex_array_type_prop": "complex_array_prop_value_002",
                "complex_array_child_name": {
                    "array_child_p1": "array_child_p1_value_002",
                    "array_child_p2": "array_child_p2_value_002"
                }
            }]
        }
Beispiel #3
0
def generate_displayable_asset_rest_handler_schema():
    schema = schema_fields.FieldRegistry('Asset', description='Asset')
    add_asset_handler_display_field(schema)
    add_asset_handler_base_fields(schema)
    return schema
Beispiel #4
0
class TextAssetRESTHandler(BaseRESTHandler):
    """REST endpoints for text assets."""

    ERROR_MESSAGE_UNEDITABLE = (
        'Error: contents are not text and cannot be edited.')
    REQUIRED_MODULES = [
        'inputex-hidden',
        'inputex-textarea',
    ]
    SCHEMA = schema_fields.FieldRegistry('Edit asset',
                                         description='Text Asset')
    SCHEMA.add_property(
        schema_fields.SchemaField(
            'contents',
            'Contents',
            'text',
        ))
    SCHEMA.add_property(
        schema_fields.SchemaField(
            'is_text',
            'Is Text',
            'boolean',
            hidden=True,
        ))
    SCHEMA.add_property(
        schema_fields.SchemaField(
            'readonly',
            'ReadOnly',
            'boolean',
            hidden=True,
        ))
    URI = '/rest/assets/text'
    XSRF_TOKEN_NAME = 'manage-text-asset'

    def delete(self):
        """Handles the delete verb."""
        assert self.app_context.is_editable_fs()
        filename = self.request.get('key')

        if not (filename and self.assert_xsrf_token_or_fail(
                self.request, self.XSRF_TOKEN_NAME, {'key': filename})):
            return

        if not FilesRights.can_delete(self):
            transforms.send_json_response(self, 401, 'Access denied.',
                                          {'key': filename})
            return

        if not _is_asset_in_allowed_bases(filename):
            transforms.send_json_response(self, 400, 'Malformed request.',
                                          {'key': filename})
            return

        self.app_context.fs.impl.delete(
            os.path.join(appengine_config.BUNDLE_ROOT, filename))
        transforms.send_json_response(self, 200, 'Done.')

    def get(self):
        """Handles the get verb."""
        assert FilesRights.can_edit(self)
        filename = self.request.get('key')
        assert filename
        asset = self.app_context.fs.impl.get(
            os.path.join(appengine_config.BUNDLE_ROOT, filename))
        assert asset

        contents = asset.read()
        is_text = is_text_payload(contents)
        if not is_text:
            contents = self.ERROR_MESSAGE_UNEDITABLE
        json_message = 'Success.' if is_text else self.ERROR_MESSAGE_UNEDITABLE

        json_payload = {
            'contents': contents,
            'is_text': is_text,
            'readonly': is_readonly_asset(asset),
        }
        transforms.send_json_response(
            self,
            200,
            json_message,
            payload_dict=json_payload,
            xsrf_token=XsrfTokenManager.create_xsrf_token(
                self.XSRF_TOKEN_NAME))

    def put(self):
        """Handles the put verb."""
        assert self.app_context.is_editable_fs()
        request = self.request.get('request')
        assert request
        request = transforms.loads(request)
        payload = transforms.loads(request.get('payload'))
        filename = request.get('key')

        if not (filename and self.assert_xsrf_token_or_fail(
                request, self.XSRF_TOKEN_NAME, {'key': filename})):
            return

        if not FilesRights.can_edit(self):
            transforms.send_json_response(self, 401, 'Access denied.',
                                          {'key': filename})
            return

        if not _is_asset_in_allowed_bases(filename):
            transforms.send_json_response(self, 400, 'Malformed request.',
                                          {'key': filename})
            return

        self.app_context.fs.impl.put(
            os.path.join(appengine_config.BUNDLE_ROOT, filename),
            vfs.string_to_stream(unicode(payload.get('contents'))))
        transforms.send_json_response(self, 200, 'Saved.')
Beispiel #5
0
    def test_mc_question_schema(self):
        """The multiple choice question schema is a good end-to-end example."""
        mc_question = schema_fields.FieldRegistry(
            'MC Question',
            extra_schema_dict_values={'className': 'mc-question'})

        mc_question.add_property(
            schema_fields.SchemaField('question', 'Question', 'string'))

        choice_type = schema_fields.FieldRegistry(
            'choice', extra_schema_dict_values={'className': 'mc-choice'})
        choice_type.add_property(
            schema_fields.SchemaField('text', 'Text', 'string'))
        choice_type.add_property(
            schema_fields.SchemaField('score', 'Score', 'string'))
        choice_type.add_property(
            schema_fields.SchemaField('feedback', 'Feedback', 'string'))

        choices_array = schema_fields.FieldArray('choices',
                                                 'Choices',
                                                 item_type=choice_type)

        mc_question.add_property(choices_array)

        expected = """
{
  "type":"object",
  "id":"MCQuestion",
  "properties":{
    "question":{"type":"string"},
    "choices":{
      "items":{
        "type":"object",
        "id":"choice",
        "properties":{
          "text":{"type":"string"},
          "score":{"type":"string"},
          "feedback":{"type":"string"}
        }
      },
      "type":"array"
    }
  }
}
"""
        self.assert_json_schema_value(expected, mc_question)

        expected = """
[
  [["title"],"MCQuestion"],
  [["_inputex"],{"className":"mc-question"}],
  [["properties","question","_inputex"],{"label":"Question"}],
  [["properties","choices","_inputex"],{"label":"Choices"}],
  [["properties","choices","items","title"],"choice"],
  [["properties","choices","items","_inputex"],{"className":"mc-choice"}],
  [["properties","choices","items","properties","text","_inputex"],{
    "label":"Text"
  }],
  [["properties","choices","items","properties","score","_inputex"],{
    "label":"Score"
  }],
  [["properties","choices","items","properties","feedback","_inputex"],{
    "label":"Feedback"
  }]
 ]
"""
        self.assert_schema_dict_value(expected, mc_question)
 def get_schema(cls):
     ret = schema_fields.FieldRegistry(
         'Availability',
         'Course Availability Settings',
         extra_schema_dict_values={
             'className': ('inputEx-Group new-form-layout hidden-header '
                           'availability-manager')
         })
     ret.add_property(
         schema_fields.SchemaField(
             'course_availability',
             'Course Availability',
             'string',
             description='This sets the availability of the course for '
             'registered and unregistered students.',
             i18n=False,
             optional=True,
             select_data=[(p, p.replace('_', ' ').title())
                          for p in courses.COURSE_AVAILABILITY_POLICIES]))
     element_settings = schema_fields.FieldRegistry(
         'Element Settings',
         'Availability settings for course elements',
         extra_schema_dict_values={'className': 'content-element'})
     element_settings.add_property(
         schema_fields.SchemaField('type',
                                   'Element Kind',
                                   'string',
                                   i18n=False,
                                   optional=True,
                                   editable=False,
                                   hidden=True))
     element_settings.add_property(
         schema_fields.SchemaField('id',
                                   'Element Key',
                                   'string',
                                   i18n=False,
                                   optional=True,
                                   editable=False,
                                   hidden=True))
     element_settings.add_property(
         schema_fields.SchemaField('indent',
                                   'Indent',
                                   'boolean',
                                   i18n=False,
                                   optional=True,
                                   editable=False,
                                   hidden=True))
     element_settings.add_property(
         schema_fields.SchemaField(
             'name',
             'Course Outline',
             'string',
             i18n=False,
             optional=True,
             editable=False,
             extra_schema_dict_values={'className': 'title'}))
     element_settings.add_property(
         schema_fields.SchemaField(
             'shown_when_unavailable',
             'Shown When Private',
             'boolean',
             description=services.help_urls.make_learn_more_message(
                 messages.AVAILABILITY_SHOWN_WHEN_UNAVAILABLE_DESCRIPTION,
                 'course:availability:shown_when_unavailable'),
             i18n=False,
             optional=True,
             extra_schema_dict_values={'className': 'shown'}))
     element_settings.add_property(
         schema_fields.SchemaField(
             'availability',
             'Availability',
             'string',
             description=services.help_urls.make_learn_more_message(
                 messages.AVAILABILITY_AVAILABILITY_DESCRIPTION,
                 'course:availability:availability'),
             i18n=False,
             optional=True,
             select_data=courses.AVAILABILITY_SELECT_DATA,
             extra_schema_dict_values={'className': 'availability'}))
     ret.add_property(
         schema_fields.FieldArray(
             'element_settings',
             'Content Availability',
             item_type=element_settings,
             optional=True,
             extra_schema_dict_values={'className':
                                       'content-availability'}))
     ret.add_property(
         schema_fields.SchemaField(
             'whitelist',
             'Students Allowed to Register',
             'text',
             description=
             'Only students with email addresses in this list may '
             'register for the course.  Separate addresses with any combination '
             'of commas, spaces, or separate lines.',
             i18n=False,
             optional=True))
     return ret
Beispiel #7
0
    def get_schema(cls, app_context, log, source_context):
        """Override default entity-based schema to reflect our upgrades.

        In the entity, labels are stored as a single string property,
        rather than an arraylist of string or integer for backward
        compatibility.  Current (2014-12-05) usage is that the 'labels'
        property is a stringified representation of a list of IDs
        to LabelEntity.  On export, we convert the string to an array
        of string to permit easier correlation from student labels to
        exported LabelEntity items.

        We provide external references to labels in preference to simply
        resolving the labels, because of potential data bloat (minor) and
        to avoid any future complications due to expansion of the role
        of labels (as was seen when labels-as-language-indicator was
        added).

        Args:
          app_context: Standard CB application context object
          log: a catch_and_log object for reporting any exceptions.
             Not used here, but useful for data source types that are
             dynamically generated, rather than statically coded.
        Returns:
          A JSON schema describing contents.  A dict as produced by
          FieldRegistry.get_json_schema_dict().
        """
        clazz = cls.get_entity_class()
        if source_context.send_uncensored_pii_data:
            registry = entity_transforms.get_schema_for_entity_unsafe(clazz)
            registry.add_property(schema_fields.SchemaField(
                'email', 'Email', 'string',
                optional=True,
                description='Email address for this Student.'))
        else:
            registry = entity_transforms.get_schema_for_entity(clazz)
        ret = registry.get_json_schema_dict()['properties']

        # Scores are deprecated now that regularized scores are available
        # in StudentAggregation data source.
        if 'scores' in ret:
            del ret['scores']

        # We are replacing the labels string with a version that shows
        # labels as separate items so that the amount of insanity
        # required in BigQuery SQL is minimized.
        ret['labels'] = schema_fields.FieldArray(
          'labels', 'Labels',
          description='Labels on students',
          item_type=schema_fields.SchemaField(
            'label', 'Label', 'string',
            description='ID of a LabelEntity applied to a student')
          ).get_json_schema_dict()

        # If a course owner has allowed some or all portions of
        # 'additional_fields', convert from a flat string into an array
        # of name/value pairs
        if 'additional_fields' in ret:
            additional_field = schema_fields.FieldRegistry('additional_field')
            additional_field.add_property(schema_fields.SchemaField(
                'name', 'Name', 'string',
                description='HTML form field name.  Not necessarily unique.'))
            additional_field.add_property(schema_fields.SchemaField(
                'value', 'Value', 'string',
                description='HTML form field value.'))
            ret['additional_fields'] = schema_fields.FieldArray(
                'additional_fields', 'Additional Fields',
                item_type=additional_field,
                description='List of name/value pairs entered on the '
                'course registration form.  Note that for names are not '
                'necessarily unique.  E.g., a group of checkboxes for '
                '"select all reasons you are taking this course" may well '
                'all have the same name.').get_json_schema_dict()
        return ret
    def get_schema(cls):
        activity = schema_fields.FieldRegistry('activity')
        activity.add_property(
            schema_fields.SchemaField(
                'action',
                'Action',
                'string',
                description='A short string indicating the nature of the event, '
                'such as "enter", "exit", "submit_assessment", "check_answer"')
        )
        activity.add_property(
            schema_fields.SchemaField(
                'timestamp',
                'Timestamp',
                'timestamp',
                description='Timestamp when the event occurred'))

        page_view = schema_fields.FieldRegistry('page_view')
        page_view.add_property(
            schema_fields.SchemaField(
                'name',
                'Name',
                'string',
                description='Name of the kind of page being shown.  This is a '
                'short string, such as "unit", "lesson", "enroll", "unenroll", '
                'etc.  The full list of these can be found in '
                'coursebuilder/modules/analytics/student_events.py.'))
        page_view.add_property(
            schema_fields.SchemaField(
                'item_id',
                'Item ID',
                'string',
                optional=True,
                description='Identity of the kind of page in question, if '
                'the page may have more than one instance.  E.g., units and '
                'lessons have IDs; the forum, enroll and unenroll pages do not.'
            ))
        page_view.add_property(
            schema_fields.SchemaField(
                'start',
                'Start',
                'timestamp',
                description='Timestamp when the page was entered.'))
        page_view.add_property(
            schema_fields.SchemaField(
                'end',
                'End',
                'timestamp',
                optional=True,
                description='Timestamp when the page was exited.  '
                'Note that this field may be blank if we are missing '
                'the exit event.  Also note that this field may be '
                'extremely misleading - users may leave the page open while '
                'doing other things.  You should arrange to clip this value '
                'at some reasonable maximum, and impute either the average '
                'or the median value when this field is blank.'))
        page_view.add_property(
            schema_fields.FieldArray('activities',
                                     'Activities',
                                     item_type=activity))

        page_views = schema_fields.FieldArray(
            'page_views',
            'Page Views',
            item_type=page_view,
            description='User activity events for this student, grouped by '
            'page enter/exit.')
        return page_views
Beispiel #9
0
 def get_schema(self, unused_handler):
     reg = schema_fields.FieldRegistry(YouTube.name())
     reg.add_property(schema_fields.SchemaField(
         'videoid', 'Video ID', 'string',
         description=messages.VIDEO_ID_DESCRIPTION))
     return reg
Beispiel #10
0
 def get_schema(cls, *args, **kwargs):
     reg = schema_fields.FieldRegistry(
         'Bogus', description='bogus')
     reg.add_property(schema_fields.SchemaField(
         'bogus', 'Bogus', 'integer', description='Fake schema'))
     return reg.get_json_schema_dict()['properties']
Beispiel #11
0
 def get_schema(cls, unused_app_context, unused_catch_and_log,
                unused_source_context):
     reg = schema_fields.FieldRegistry(
         'Raw Student Answers',
         description='Raw data of answers to all uses of all graded '
         'questions (excludes self-check non-graded questions in lessons) '
         'in the course.')
     reg.add_property(
         schema_fields.SchemaField(
             'user_id',
             'User ID',
             'string',
             description='ID of the student providing this answer.'))
     reg.add_property(
         schema_fields.SchemaField(
             'user_name',
             'User Name',
             'string',
             description='Name of the student providing this answer.'))
     reg.add_property(
         schema_fields.SchemaField(
             'user_email',
             'User Email',
             'string',
             description=
             'Email address of the student providing this answer.'))
     reg.add_property(
         schema_fields.SchemaField(
             'unit_id',
             'Unit ID',
             'string',
             description='ID of unit or assessment for this score.'))
     reg.add_property(
         schema_fields.SchemaField(
             'lesson_id',
             'Lesson ID',
             'string',
             optional=True,
             description='ID of lesson for this score.'))
     reg.add_property(
         schema_fields.SchemaField(
             'sequence',
             'Sequence',
             'integer',
             description='0-based order within containing assessment/lesson.'
         ))
     reg.add_property(
         schema_fields.SchemaField(
             'question_id',
             'Question ID',
             'string',
             description='ID of question.  Key to models.QuestionDAO'))
     reg.add_property(
         schema_fields.SchemaField(
             'question_type',
             'Question Type',
             'string',
             description=
             'Kind of question.  E.g., "SaQuestion" or "McQuestion" '
             'for single-answer and multiple-choice, respectively.'))
     reg.add_property(
         schema_fields.SchemaField(
             'timestamp',
             'Question ID',
             'integer',
             description='Seconds since 1970-01-01 in GMT when answer given.'
         ))
     choice_type = schema_fields.SchemaField(
         'answer',
         'Answer',
         'string',
         description='An answer to the question')
     reg.add_property(
         schema_fields.FieldArray(
             'answers',
             'Answers',
             item_type=choice_type,
             description='The answer from the student.  Note that '
             'this may be an array for questions permitting multiple answers.'
         ))
     reg.add_property(
         schema_fields.SchemaField(
             'score',
             'Score',
             'number',
             description='Value from the Question indicating the score for '
             'this answer or set of answers.'))
     reg.add_property(
         schema_fields.SchemaField(
             'weighted_score',
             'Weighted Score',
             'number',
             description='Question score, multiplied by weights in '
             'containing Question Group, Assessment, etc.'))
     reg.add_property(
         schema_fields.SchemaField(
             'tallied',
             'Tallied',
             'boolean',
             description=
             'Whether the score counts towards the overall grade.  '
             'Lessons by default do not contribute to course score, but may '
             'be marked as graded.'))
     return reg.get_json_schema_dict()['properties']
Beispiel #12
0
    def get_schema(cls, course, key):
        units = course.get_units()

        # Note GcbRte relies on the structure of this schema. Do not change
        # without checking the dependency.
        unit_list = []
        for unit in units:
            if unit.type == 'U':
                unit_list.append(
                    (unit.unit_id,
                     cgi.escape(display_unit_title(unit, course.app_context))))

        lesson_data = cls.get_data_dict(course, key)
        has_video_id = bool(lesson_data.get('video'))

        lesson = schema_fields.FieldRegistry(
            'Lesson', description='Lesson', extra_schema_dict_values={
                'className': 'inputEx-Group new-form-layout'})
        lesson.add_property(schema_fields.SchemaField(
            'key', 'ID', 'string', editable=False,
            extra_schema_dict_values={'className': 'inputEx-Field keyHolder'},
            hidden=True))
        lesson.add_property(schema_fields.SchemaField(
            'title', 'Title', 'string', extra_schema_dict_values={
                'className': 'inputEx-Field title-holder'}))
        lesson.add_property(schema_fields.SchemaField(
            'unit_id', 'Parent Unit', 'string', i18n=False,
            select_data=unit_list))
        lesson.add_property(schema_fields.SchemaField(
            'video', 'Video ID', 'string', hidden=not has_video_id,
            optional=True, description=messages.LESSON_VIDEO_ID_DESCRIPTION))
        lesson.add_property(schema_fields.SchemaField(
            'scored', 'Scored', 'string', optional=True, i18n=False,
            description=messages.LESSON_SCORED_DESCRIPTION,
            select_data=[
                ('scored', 'Questions are scored'),
                ('not_scored', 'Questions only give feedback')]))
        lesson.add_property(schema_fields.SchemaField(
            'objectives', 'Lesson Body', 'html', optional=True,
            description=messages.LESSON_OBJECTIVES_DESCRIPTION,
            extra_schema_dict_values={
                'supportCustomTags': tags.CAN_USE_DYNAMIC_TAGS.value}))
        lesson.add_property(schema_fields.SchemaField(
            'notes', 'Notes', 'string', optional=True,
            description=messages.LESSON_NOTES_DESCRIPTION))
        lesson.add_property(schema_fields.SchemaField(
            'auto_index', 'Auto Number', 'boolean',
            description=messages.LESSON_AUTO_INDEX_DESCRIPTION))
        lesson.add_property(schema_fields.SchemaField(
            'activity_title', 'Activity Title', 'string', optional=True,
            description=messages.LESSON_ACTIVITY_TITLE_DESCRIPTION))
        lesson.add_property(schema_fields.SchemaField(
            'activity_listed', 'Activity Listed', 'boolean', optional=True,
            description=messages.LESSON_ACTIVITY_LISTED_DESCRIPTION))
        lesson.add_property(schema_fields.SchemaField(
            'activity', 'Activity', 'text', optional=True,
            description=str(messages.LESSON_ACTIVITY_DESCRIPTION),
            extra_schema_dict_values={
                'className': 'inputEx-Field activityHolder'}))
        lesson.add_property(schema_fields.SchemaField(
            'manual_progress', 'Manual Progress', 'boolean', optional=True,
            description=messages.LESSON_MANUAL_PROGRESS_DESCRIPTION))
        lesson.add_property(schema_fields.SchemaField(
            'is_draft', 'Status', 'boolean',
            select_data=[(True, DRAFT_TEXT), (False, PUBLISHED_TEXT)],
            extra_schema_dict_values={
                'className': 'split-from-main-group'}))
        return lesson
Beispiel #13
0
    def get_schema(cls, course, key):
        reg = schema_fields.FieldRegistry('Assessment',
            extra_schema_dict_values={
                'className': 'inputEx-Group new-form-layout'})

        # Course level settings.
        course_opts = cls._generate_common_schema(
            'Assessment Config', hidden_header=True)
        course_opts.add_property(schema_fields.SchemaField(
            'weight', 'Weight', 'number',
            description=str(messages.ASSESSMENT_WEIGHT_DESCRIPTION),
            i18n=False, optional=True))
        course_opts.add_property(schema_fields.SchemaField(
            'content', 'Assessment Content (JavaScript)', 'text', optional=True,
            description=str(messages.ASSESSMENT_CONTENT_DESCRIPTION),
            extra_schema_dict_values={'className': 'inputEx-Field content'}))
        course_opts.add_property(schema_fields.SchemaField(
            'html_content', 'Assessment Content', 'html', optional=True,
            extra_schema_dict_values={
                'supportCustomTags': tags.CAN_USE_DYNAMIC_TAGS.value,
                'excludedCustomTags': tags.EditorBlacklists.ASSESSMENT_SCOPE,
                'className': 'inputEx-Field html-content'}))
        course_opts.add_property(schema_fields.SchemaField(
            'html_check_answers', '"Check Answers" Buttons', 'boolean',
            description=str(messages.CHECK_ANSWERS_DESCRIPTION),
            extra_schema_dict_values={
                'className': 'inputEx-Field assessment-editor-check-answers'},
            optional=True))
        course_opts.add_property(schema_fields.SchemaField(
            workflow_key(courses.SUBMISSION_DUE_DATE_KEY),
            'Submission Due Date', 'string', optional=True,
            description=str(messages.DUE_DATE_FORMAT_DESCRIPTION)))
        course_opts.add_property(schema_fields.SchemaField(
            workflow_key(courses.GRADER_KEY), 'Grading Method', 'string',
            select_data=ALLOWED_GRADERS_NAMES.items()))
        reg.add_sub_registry('assessment', 'Assessment Config',
                             registry=course_opts)

        review_opts = reg.add_sub_registry('review_opts', 'Peer review',
            description=str(messages.ASSESSMENT_DETAILS_DESCRIPTION),
            extra_schema_dict_values={'id': 'peer-review-group'})

        if len(courses.ALLOWED_MATCHERS_NAMES) > 1:
            review_opts.add_property(schema_fields.SchemaField(
                workflow_key(courses.MATCHER_KEY), 'Review Matcher', 'string',
                optional=True,
                select_data=courses.ALLOWED_MATCHERS_NAMES.items()))

        review_opts.add_property(schema_fields.SchemaField(
            'review_form', 'Reviewer Feedback Form (JavaScript)', 'text',
            optional=True,
            description=str(messages.REVIEWER_FEEDBACK_FORM_DESCRIPTION),
            extra_schema_dict_values={
                'className': 'inputEx-Field review-form'}))
        review_opts.add_property(schema_fields.SchemaField(
            'html_review_form', 'Reviewer Feedback Form', 'html',
            optional=True,
            description=str(messages.REVIEWER_FEEDBACK_FORM_HTML_DESCRIPTION),
            extra_schema_dict_values={
                'supportCustomTags': tags.CAN_USE_DYNAMIC_TAGS.value,
                'excludedCustomTags': tags.EditorBlacklists.ASSESSMENT_SCOPE,
                'className': 'inputEx-Field html-review-form'}))
        review_opts.add_property(schema_fields.SchemaField(
            workflow_key(courses.REVIEW_DUE_DATE_KEY),
            'Review Due Date', 'string', optional=True,
            description=str(messages.REVIEW_DUE_DATE_FORMAT_DESCRIPTION)))
        review_opts.add_property(schema_fields.SchemaField(
            workflow_key(courses.REVIEW_MIN_COUNT_KEY),
            'Review Min Count', 'integer', optional=True,
            description=str(messages.REVIEW_MIN_COUNT_DESCRIPTION)))
        review_opts.add_property(schema_fields.SchemaField(
            workflow_key(courses.REVIEW_WINDOW_MINS_KEY),
            'Review Window Timeout', 'integer', optional=True,
            description=str(messages.REVIEW_TIMEOUT_IN_MINUTES)))
        return reg
Beispiel #14
0
    def get_schema(cls, course, key):
        """Get the InputEx schema for the short answer question editor."""
        sa_question = schema_fields.FieldRegistry(
            'Short Answer Question',
            description='short answer question',
            extra_schema_dict_values={'className': 'sa-container'})

        sa_question.add_property(schema_fields.SchemaField(
            'version', '', 'string', optional=True, hidden=True))
        sa_question.add_property(schema_fields.SchemaField(
            'description', 'Description', 'string', optional=True,
            extra_schema_dict_values={'className': 'sa-description'},
            description=messages.QUESTION_DESCRIPTION))
        sa_question.add_property(schema_fields.SchemaField(
            'question', 'Question', 'html', optional=True,
            extra_schema_dict_values={
                'supportCustomTags': tags.CAN_USE_DYNAMIC_TAGS.value,
                'excludedCustomTags': TAGS_EXCLUDED_FROM_QUESTIONS,
                'className': 'sa-question'}))
        sa_question.add_property(schema_fields.SchemaField(
            'hint', 'Hint', 'html', optional=True,
            extra_schema_dict_values={'className': 'sa-hint'}))
        sa_question.add_property(schema_fields.SchemaField(
            'defaultFeedback', 'Feedback', 'html', optional=True,
            extra_schema_dict_values={
                'supportCustomTags': tags.CAN_USE_DYNAMIC_TAGS.value,
                'excludedCustomTags': TAGS_EXCLUDED_FROM_QUESTIONS,
                'className': 'sa-feedback'},
            description=messages.INCORRECT_ANSWER_FEEDBACK))

        sa_question.add_property(schema_fields.SchemaField(
            'rows', 'Rows', 'string', optional=True, i18n=False,
            extra_schema_dict_values={
                'className': 'sa-rows',
                'value': SaQuestionConstants.DEFAULT_HEIGHT_ROWS
            },
            description=messages.INPUT_FIELD_HEIGHT_DESCRIPTION))
        sa_question.add_property(schema_fields.SchemaField(
            'columns', 'Columns', 'string', optional=True, i18n=False,
            extra_schema_dict_values={
                'className': 'sa-columns',
                'value': SaQuestionConstants.DEFAULT_WIDTH_COLUMNS
            },
            description=messages.INPUT_FIELD_WIDTH_DESCRIPTION))

        grader_type = schema_fields.FieldRegistry(
            'Answer',
            extra_schema_dict_values={'className': 'sa-grader'})
        grader_type.add_property(schema_fields.SchemaField(
            'score', 'Score', 'string',
            description=messages.SHORT_ANSWER_SCORE_DESCRIPTION,
            extra_schema_dict_values={
                'className': 'sa-grader-score',
                'value': '1.0',
            }, i18n=False, optional=True))
        grader_type.add_property(schema_fields.SchemaField(
            'matcher', 'Grading', 'string', optional=True, i18n=False,
            select_data=cls.GRADER_TYPES,
            extra_schema_dict_values={'className': 'sa-grader-score'}))
        grader_type.add_property(schema_fields.SchemaField(
            'response', 'Response', 'string', optional=True,
            extra_schema_dict_values={'className': 'sa-grader-text'}))
        grader_type.add_property(schema_fields.SchemaField(
            'feedback', 'Feedback', 'html', optional=True,
            extra_schema_dict_values={
                'supportCustomTags': tags.CAN_USE_DYNAMIC_TAGS.value,
                'excludedCustomTags': TAGS_EXCLUDED_FROM_QUESTIONS,
                'className': 'sa-grader-feedback'}))

        graders_array = schema_fields.FieldArray(
            'graders', '', item_type=grader_type,
            extra_schema_dict_values={
                'className': 'sa-grader-container',
                'listAddLabel': 'Add an answer',
                'listRemoveLabel': 'Delete this answer'})

        sa_question.add_property(graders_array)

        return sa_question
def get_criteria_editor_schema(course):
    criterion_type = schema_fields.FieldRegistry(
        'Criterion',
        extra_schema_dict_values={'className': 'settings-list-item'})

    select_data = [('default', '-- Select requirement --'),
                   ('', '-- Custom criterion --')]
    for unit in course.get_assessment_list():
        select_data.append(
            (unit.unit_id, unit.title +
             (' [Peer Graded]' if course.needs_human_grader(unit) else '')))

    criterion_type.add_property(
        schema_fields.SchemaField(
            'assessment_id',
            'Requirement',
            'string',
            optional=True,
            # The JS will only reveal the following description
            # for peer-graded assessments
            description='When specifying a peer graded assessment as criterion, '
            'the student should complete both the assessment '
            'and the minimum of peer reviews.',
            select_data=select_data,
            extra_schema_dict_values={
                'className': 'inputEx-Field assessment-dropdown'
            }))

    criterion_type.add_property(
        schema_fields.SchemaField(
            'pass_percent',
            'Passing Percentage',
            'string',
            optional=True,
            extra_schema_dict_values={'className': 'pass-percent'}))

    select_data = [('', '-- Select criterion method--')
                   ] + [(x, x) for x in custom_criteria.registration_table]
    criterion_type.add_property(
        schema_fields.SchemaField(
            'custom_criteria',
            'Custom Criterion',
            'string',
            optional=True,
            select_data=select_data,
            extra_schema_dict_values={'className': 'custom-criteria'}))

    is_peer_assessment_table = {}
    for unit in course.get_assessment_list():
        is_peer_assessment_table[unit.unit_id] = (
            True if course.needs_human_grader(unit) else False)

    return schema_fields.FieldArray(
        'certificate_criteria',
        'Certificate Criteria',
        item_type=criterion_type,
        description='Certificate award criteria. Add the criteria which '
        'students must meet to be awarded a certificate of completion. '
        'In order to receive a certificate, '
        'the student must meet all the criteria.',
        extra_schema_dict_values={
            'is_peer_assessment_table': is_peer_assessment_table,
            'className': 'settings-list',
            'listAddLabel': 'Add a criterion',
            'listRemoveLabel': 'Delete criterion'
        })
Beispiel #16
0
 def get_schema(self, unused_handler):
     """Get the schema for the tag's attributes using schema_fields."""
     reg = schema_fields.FieldRegistry('Unimplemented Custom Tag')
     return reg
Beispiel #17
0
    def get_schema(cls, app_context=None):
        cluster_schema = schema_fields.FieldRegistry(
            'Cluster Definition',
            description='cluster definition',
            extra_schema_dict_values={'className': 'cluster-container'})
        cluster_schema.add_property(
            schema_fields.SchemaField('version',
                                      '',
                                      'string',
                                      optional=True,
                                      hidden=True))
        cluster_schema.add_property(
            schema_fields.SchemaField(
                'name',
                'Name',
                'string',
                optional=False,
                extra_schema_dict_values={'className': 'cluster-name'}))
        cluster_schema.add_property(
            schema_fields.SchemaField(
                'description',
                'Description',
                'string',
                optional=True,
                extra_schema_dict_values={'className': 'cluster-description'}))

        dimension = schema_fields.FieldRegistry(
            'Dimension', extra_schema_dict_values={'className': 'cluster-dim'})

        to_select = []
        dim_types = {}
        if app_context:
            dimensions = get_possible_dimensions(app_context)
            for dim in dimensions:
                select_id = cls.pack_id(dim[DIM_ID], dim[DIM_TYPE])
                to_select.append((select_id, dim['name']))
                dim_types[select_id] = dim[DIM_TYPE]

        dimension.add_property(
            schema_fields.SchemaField(
                DIM_ID,
                'Dimension Name',
                'string',
                i18n=False,
                extra_schema_dict_values={'className': 'dim-name'},
                select_data=to_select))
        # Only description for the first dimension. All the descriptions
        # are in the cluster_rest.js file.
        dimension.add_property(
            schema_fields.SchemaField(
                DIM_LOW,
                'Minimum number of visits to the page',
                'string',
                i18n=False,
                optional=True,
                extra_schema_dict_values={'className': 'dim-range-low'}))
        dimension.add_property(
            schema_fields.SchemaField(
                DIM_HIGH,
                'Maximum number of visits to the page',
                'string',
                i18n=False,
                optional=True,
                extra_schema_dict_values={'className': 'dim-range-high'}))

        dimension_array = schema_fields.FieldArray(
            'vector',
            '',
            item_type=dimension,
            description='Dimensions of the cluster. Add a new dimension '
            'for each criteria the student has to acomplish to be '
            'included in the cluster',
            extra_schema_dict_values={
                'className': 'cluster-dim-container',
                'listAddLabel': 'Add a dimension',
                'listRemoveLabel': 'Delete dimension',
                'dim_types': dim_types,
                'types_info': cls.TYPES_INFO
            })

        cluster_schema.add_property(dimension_array)

        return cluster_schema
Beispiel #18
0
def _create_hook_registry():
    reg = schema_fields.FieldRegistry('Html Hook', description='Html Hook')
    reg.add_property(schema_fields.SchemaField(
        'hook_content', 'HTML Hook Content', 'html',
        optional=True))
    return reg