示例#1
0
def logout(request):
    """Handles the "user.logout" URL and deletes the current session,
    thus logging the user out.

    Redirects to the "user.logout" redirection route.
    """
    if request.method == 'POST':
        try:
            CSRFSchema().to_python(request.params, State(request=request))
            request.current_user.logged_in = False
            request.session.delete()
            redirect(request, 'user.logout')
        except Invalid as e:
            return {
                'errors':
                e.error_dict,
                'crumbs': [{
                    'title': 'Logout',
                    'url': request.route_url('user.logout'),
                    'current': True
                }]
            }
    return {
        'crumbs': [{
            'title': 'Logout',
            'url': request.route_url('user.logout'),
            'current': True
        }]
    }
示例#2
0
def latinsquare_estimate(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(
        Experiment.id == request.matchdict['eid']).first()
    data_set = dbsession.query(DataSet).filter(
        and_(DataSet.id == request.matchdict['did'],
             DataSet.experiment_id == request.matchdict['eid'],
             DataSet.type == 'latinsquare')).first()
    if experiment and data_set:
        try:
            params = LatinSquareEstimateSchema().to_python(
                request.params,
                State(request=request,
                      dbsession=dbsession,
                      experiment=experiment))
            count = latinsquare_estimate_count(dbsession, params['source_a'],
                                               params['mode_a'],
                                               params['source_b'],
                                               params['mode_b'])
            if count is None:
                return {'count': ''}
            else:
                return {'count': count}
        except formencode.Invalid:
            return {'count': ''}
    else:
        raise HTTPNotFound()
示例#3
0
def reorder_page(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                                 Page.experiment == experiment)).first()
    else:
        page = None
    if experiment and page:
        try:
            params = ReorderSchema().to_python(request.params, State(request=request))
            with transaction.manager:
                visible_idx = 1
                for idx, qid in enumerate(params['item']):
                    question = dbsession.query(Question).filter(and_(Question.id == qid,
                                                                     Question.page == page)).first()
                    if question is not None:
                        dbsession.add(question.q_type)
                        question.order = idx
                        if question['frontend', 'visible'] and question['frontend', 'title']:
                            question['frontend', 'question_number'] = visible_idx
                            visible_idx = visible_idx + 1
            return {'status': 'ok'}
        except formencode.Invalid:
            return {'status': 'error'}
    else:
        raise HTTPNotFound()
示例#4
0
def data(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                             Page.experiment_id == request.matchdict['eid'])).first()
    if experiment and page:
        data_sets = dbsession.query(DataSet).filter(DataSet.experiment_id == experiment.id)
        if request.method == 'POST':
            try:
                schema = DataAttachmentSchema()
                mode = ''
                if 'data_set' in request.params and \
                        request.params['data_set'] in [str(ds.id) for ds in data_sets if ds.type == 'dataset']:
                    schema.add_field('data_items', formencode.validators.Int(not_empty=True))
                    mode = 'dataset'
                params = schema.to_python(request.params, State(request=request,
                                                                dbsession=dbsession,
                                                                experiment=experiment))
                with transaction.manager:
                    dbsession.add(page)
                    page.dataset_id = params['data_set']
                    if mode == 'dataset':
                        page['data'] = {'type': 'dataset',
                                        'item_count': params['data_items']}
                dbsession.add(experiment)
                dbsession.add(page)
                raise HTTPFound(request.route_url('experiment.page.data', eid=experiment.id, pid=page.id))
            except formencode.Invalid as e:
                return {'experiment': experiment,
                        'page': page,
                        'data_sets': data_sets,
                        'crumbs': [{'title': 'Experiments',
                                    'url': request.route_url('dashboard')},
                                   {'title': experiment.title,
                                    'url': request.route_url('experiment.view', eid=experiment.id)},
                                   {'title': 'Pages',
                                    'url': request.route_url('experiment.page', eid=experiment.id)},
                                   {'title': '%s (%s)' % (page.title, page.name)
                                    if page.title else 'No title (%s)' % page.name,
                                    'url': request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id)},
                                   {'title': 'Data',
                                    'url': request.route_url('experiment.page.data', eid=experiment.id, pid=page.id)}],
                        'errors': e.error_dict,
                        'values': request.params}
        return {'experiment': experiment,
                'page': page,
                'data_sets': data_sets,
                'crumbs': [{'title': 'Experiments',
                            'url': request.route_url('dashboard')},
                           {'title': experiment.title,
                            'url': request.route_url('experiment.view', eid=experiment.id)},
                           {'title': 'Pages',
                            'url': request.route_url('experiment.page', eid=experiment.id)},
                           {'title': '%s (%s)' % (page.title, page.name)
                            if page.title else 'No title (%s)' % page.name,
                            'url': request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id)},
                           {'title': 'Data',
                            'url': request.route_url('experiment.page.data', eid=experiment.id, pid=page.id)}]}
    else:
        raise HTTPNotFound()
示例#5
0
def delete(request):
    """Handles the "/users/{uid}/delete" URL, providing the form and backend
    functionality for deleting a :class:`~wte.models.User`. Also deletes all
    the data that is linked to that :class:`~wte.models.User`.
    """
    dbsession = DBSession()
    user = dbsession.query(User).filter(
        User.id == request.matchdict['uid']).first()
    if user:
        if user.allow('delete', request.current_user):
            if request.method == 'POST':
                try:
                    CSRFSchema().to_python(request.params,
                                           State(request=request))
                    with transaction.manager:
                        dbsession.delete(user)
                    request.session.flash('The account has been deleted',
                                          queue='info')
                    if request.current_user.has_permission('admin.users.view'):
                        raise HTTPSeeOther(request.route_url('users'))
                    else:
                        raise HTTPSeeOther(request.route_url('root'))
                except Invalid as e:
                    return {
                        'errors':
                        e.error_dict,
                        'user':
                        user,
                        'crumbs':
                        create_user_crumbs(
                            request,
                            [{
                                'title': user.display_name,
                                'url': request.route_url('user.view',
                                                         uid=user.id)
                            }, {
                                'title':
                                'Delete',
                                'url':
                                request.route_url('user.delete', uid=user.id)
                            }])
                    }
            return {
                'user':
                user,
                'crumbs':
                create_user_crumbs(
                    request,
                    [{
                        'title': user.display_name,
                        'url': request.route_url('user.view', uid=user.id)
                    }, {
                        'title': 'Delete',
                        'url': request.route_url('user.delete', uid=user.id)
                    }])
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
def new_part_task(request):
    """Handles the ``parts/{pid}/timed-tasks/new`` URL, providing the UI and
    backend for creating a new :class:`~wte.models.TimedTask`\ s for
    a given :class:`~wte.models.Part`.

    Requires that the user has "edit" rights on the
    :class:`~wte.models.Part`.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(
        Part.id == request.matchdict['pid']).first()
    if part:
        if part.allow('edit', request.current_user):
            crumbs = create_part_crumbs(request, part, {
                'title': 'Timed Actions',
                'url': request.current_route_url()
            })
            available_tasks = [('change_status', 'Change Status')]
            if request.method == 'POST':
                try:
                    params = NewTimedTaskSchema().to_python(
                        request.params, State(request=request))
                    with transaction.manager:
                        title = 'Unknown Task'
                        if params['name'] == 'change_status':
                            title = 'Change Status'
                        new_task = TimedTask(name=params['name'],
                                             part_id=part.id,
                                             title=title,
                                             status='new')
                        dbsession.add(new_task)
                    dbsession.add(part)
                    dbsession.add(new_task)
                    raise HTTPSeeOther(
                        request.route_url('part.timed_task.edit',
                                          pid=part.id,
                                          tid=new_task.id))
                except formencode.Invalid as e:
                    return {
                        'errors': e.error_dict,
                        'values': request.params,
                        'part': part,
                        'crumbs': crumbs,
                        'available_tasks': available_tasks,
                        'include_footer': True,
                        'help': ['user', 'teacher', 'timed_actions.html']
                    }
            return {
                'part': part,
                'crumbs': crumbs,
                'available_tasks': available_tasks,
                'include_footer': True,
                'help': ['user', 'teacher', 'timed_actions.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
示例#7
0
def settings(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                             Page.experiment_id == request.matchdict['eid'])).first()
    if experiment and page:
        if request.method == 'POST':
            try:
                params = PageSettingsSchema().to_python(request.params,
                                                        State(request=request,
                                                              dbsession=dbsession,
                                                              experiment=experiment,
                                                              page_id=request.matchdict['pid']))
                with transaction.manager:
                    dbsession.add(page)
                    page.name = params['name']
                    page.title = params['title']
                    page.styles = params['styles']
                    page.scripts = params['scripts']
                    page['number_questions'] = params['number_questions']
                dbsession.add(page)
                dbsession.add(experiment)
                raise HTTPFound(request.route_url('experiment.page.settings', eid=experiment.id, pid=page.id))
            except formencode.Invalid as e:
                return {'experiment': experiment,
                        'page': page,
                        'crumbs': [{'title': 'Experiments',
                                    'url': request.route_url('dashboard')},
                                   {'title': experiment.title,
                                    'url': request.route_url('experiment.view', eid=experiment.id)},
                                   {'title': 'Pages',
                                    'url': request.route_url('experiment.page', eid=experiment.id)},
                                   {'title': '%s (%s)' % (page.title, page.name)
                                    if page.title else 'No title (%s)' % page.name,
                                    'url': request.route_url('experiment.page.edit',
                                                             eid=experiment.id,
                                                             pid=page.id)},
                                   {'title': 'Settings',
                                    'url': request.route_url('experiment.page.settings',
                                                             eid=experiment.id,
                                                             pid=page.id)}],
                        'values': request.params,
                        'errors': e.error_dict}
        return {'experiment': experiment,
                'page': page,
                'crumbs': [{'title': 'Experiments',
                            'url': request.route_url('dashboard')},
                           {'title': experiment.title,
                            'url': request.route_url('experiment.view', eid=experiment.id)},
                           {'title': 'Pages',
                            'url': request.route_url('experiment.page', eid=experiment.id)},
                           {'title': '%s (%s)' % (page.title, page.name)
                            if page.title else 'No title (%s)' % page.name,
                            'url': request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id)},
                           {'title': 'Settings',
                            'url': request.route_url('experiment.page.settings', eid=experiment.id, pid=page.id)}]}
    else:
        raise HTTPNotFound()
示例#8
0
def login(request):
    """Handles the "user.login" URL, checking the submitted username and
    password against the stored :class:`~pywebtools.pyramid.auth.models.User` and setting the
    necessary session variables if the login is successful.

    Uses either the ``return_to`` parameter in the request to redirect on success or
    the "user.login" redirection route, with parameter replacement "{uid}" will be replaced
    with the logged in user's identifier.
    """
    dbsession = DBSession()
    if request.current_user.logged_in:
        if 'return_to' in request.params and request.params[
                'return_to'] != request.current_route_url():
            if '_default' in active_redirects and \
                    request.params['return_to'] != request.route_url(active_redirects['_default']):
                raise HTTPSeeOther(request.params['return_to'])
        redirect(request, 'user.login', uid=request.current_user.id)
    if request.method == 'POST':
        try:
            dbsession = DBSession()
            params = LoginSchema().to_python(
                request.params,
                State(dbsession=dbsession, request=request, user_class=User))
            user = dbsession.query(User).filter(
                User.email == params['email'].lower()).first()
            request.current_user = user
            request.current_user.logged_in = True
            request.session['uid'] = user.id
            request.session.new_csrf_token()
            if 'return_to' in request.params and request.params[
                    'return_to'] != request.current_route_url():
                if '_default' in active_redirects and \
                        request.params['return_to'] != request.route_url(active_redirects['_default']):
                    raise HTTPSeeOther(request.params['return_to'])
            redirect(request, 'user.login', uid=request.current_user.id)
        except Invalid as e:
            return {
                'errors':
                e.error_dict if e.error_dict else {
                    'email': e.msg,
                    'password': e.msg
                },
                'values':
                request.params,
                'crumbs': [{
                    'title': 'Login',
                    'url': request.route_url('user.login'),
                    'current': True
                }]
            }
    return {
        'crumbs': [{
            'title': 'Login',
            'url': request.route_url('user.login'),
            'current': True
        }]
    }
示例#9
0
def edit_question(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                                 Page.experiment == experiment)).first()
    else:
        page = None
    if page:
        question = dbsession.query(Question).filter(and_(Question.id == request.matchdict['qid'],
                                                         Question.page == page)).first()
    else:
        question = None
    if experiment and page and question:
        try:
            params = QuestionEditSchema(question['backend', 'fields']).to_python(request.params,
                                                                                 State(request=request,
                                                                                       dbsession=dbsession))
            with transaction.manager:
                dbsession.add(question)
                # Update question parameters
                for key, value in params.items():
                    if isinstance(value, list):
                        new_value = []
                        for sub_value in value:
                            if isinstance(sub_value, dict):
                                if len([v for v in sub_value.values() if v is None]) == 0:
                                    new_value.append(sub_value)
                            else:
                                if sub_value is not None:
                                    new_value.append(sub_value)
                        value = new_value
                    if key != 'csrf_token':
                        question[key] = value
                # Update all question numbering
                dbsession.add(page)
                visible_idx = 1
                for q in page.questions:
                    if q['frontend', 'visible'] and q['frontend', 'title']:
                        q['frontend', 'question_number'] = visible_idx
                        visible_idx = visible_idx + 1
            dbsession.add(experiment)
            dbsession.add(page)
            dbsession.add(question)
            data = render_to_response('ess:templates/page/edit_question.kajiki',
                                      {'experiment': experiment,
                                       'page': page,
                                       'question': question,
                                       'participant': Participant(id=-1)},
                                      request=request)
            return {'status': 'ok',
                    'fragment': data.body.decode('utf-8')}
        except formencode.Invalid as e:
            return {'status': 'error',
                    'errors': e.unpack_errors()}
    else:
        raise HTTPNotFound()
示例#10
0
def action(request):
    """Handles the ``/users/action`` URL, applying the given action to the
    list of selected users. Requires that the current
    :class:`~wte.models.User` has the "admin.users.view"
    :class:`~wte.models.Permission`.
    """
    dbsession = DBSession()
    try:
        query_params = []
        for param in ['q', 'status', 'start']:
            if param in request.params and request.params[param]:
                query_params.append((param, request.params[param]))
        params = ActionSchema().to_python(request.params,
                                          State(request=request))
        if params['action'] != 'delete' or params['confirm']:
            with transaction.manager:
                for user in dbsession.query(User).filter(
                        User.id.in_(params['user_id'])):
                    if params['action'] == 'validate':
                        if user.status == 'unconfirmed' and user.allow(
                                'edit', request.current_user):
                            user.status = 'active'
                    elif params['action'] == 'delete':
                        if user.allow('delete', request.current_user):
                            dbsession.delete(user)
                    elif params['action'] == 'password':
                        if user.status == 'active' and user.allow(
                                'edit', request.current_user):
                            token = TimeToken(
                                user.id, 'reset_password',
                                datetime.now() + timedelta(seconds=1200))
                            dbsession.add(token)
                            dbsession.flush()
                            if 'user.password_reset' in active_callbacks:
                                active_callbacks['user.password_reset'](
                                    request, user, token)
            raise HTTPSeeOther(request.route_url('users', _query=query_params))
        else:
            return {
                'params':
                params,
                'users':
                dbsession.query(User).filter(User.id.in_(params['user_id'])),
                'query_params':
                query_params,
                'crumbs':
                create_user_crumbs(request, [{
                    'title': 'Confirm',
                    'url': request.current_route_url()
                }])
            }
    except Invalid as e:
        print(e)
        request.session.flash(
            'Please select the action you wish to apply and the users to apply it to',
            queue='error')
        raise HTTPSeeOther(request.route_url('users', _query=query_params))
def import_experiment(request):
    if request.method == 'POST':
        try:
            params = ImportExperimentSchema().to_python(
                request.params, State(request=request))
            dbsession = DBSession()
            with transaction.manager:
                experiment, errors = ExperimentIOSchema(include_schemas=[s for s in all_io_schemas
                                                                         if s != ExperimentIOSchema]).\
                    loads(params['source'].file.read().decode('utf-8'))
                if errors:
                    raise formencode.Invalid(
                        '. '.join([
                            '%s: %s' % (e['source']['pointer'], e['detail'])
                            for e in errors['errors']
                        ]), None, None)
                for page in experiment.pages:
                    replace_questions(page, dbsession)
                experiment.owner = request.current_user
                experiment.external_id = uuid.uuid1().hex,
                experiment.status = 'develop'
                dbsession.add(experiment)
                dbsession.flush()
                for latin_square in experiment.latin_squares:
                    fix_latinsquare(latin_square, experiment.data_sets)
                for page in experiment.pages:
                    for transition in page.next:
                        fix_transition(transition, experiment.pages)
            dbsession.add(experiment)
            raise HTTPFound(
                request.route_url('experiment.view', eid=experiment.id))
        except formencode.Invalid as e:
            return {
                'crumbs': [{
                    'title': 'Experiments',
                    'url': request.route_url('dashboard')
                }, {
                    'title': 'Import',
                    'url': request.route_url('experiment.import')
                }],
                'errors': {
                    'source': str(e)
                },
                'values':
                request.params
            }
    return {
        'crumbs': [{
            'title': 'Experiments',
            'url': request.route_url('dashboard')
        }, {
            'title': 'Import',
            'url': request.route_url('experiment.import')
        }]
    }
示例#12
0
def delete(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                             Page.experiment_id == request.matchdict['eid'])).first()
    if experiment and page:
        if request.method == 'POST':
            try:
                DeleteSchema().to_python(request.params,
                                         State(request=request,
                                               dbsession=dbsession))
                with transaction.manager:
                    dbsession.add(experiment)
                    dbsession.add(page)
                    if experiment.start == page:
                        experiment.start = None
                    dbsession.delete(page)
                dbsession.add(experiment)
                raise HTTPFound(request.route_url('experiment.page', eid=experiment.id))
            except formencode.Invalid as e:
                return {'experiment': experiment,
                        'page': page,
                        'crumbs': [{'title': 'Experiments',
                                    'url': request.route_url('dashboard')},
                                   {'title': experiment.title,
                                    'url': request.route_url('experiment.view', eid=experiment.id)},
                                   {'title': 'Pages',
                                    'url': request.route_url('experiment.page', eid=experiment.id)},
                                   {'title': '%s (%s)' % (page.title, page.name)
                                    if page.title else 'No title (%s)' % page.name,
                                    'url': request.route_url('experiment.page.edit',
                                                             eid=experiment.id,
                                                             pid=page.id)},
                                   {'title': 'Delete',
                                    'url': request.route_url('experiment.page.delete',
                                                             eid=experiment.id,
                                                             pid=page.id)}],
                        'values': request.params,
                        'errors': e.error_dict}
        return {'experiment': experiment,
                'page': page,
                'crumbs': [{'title': 'Experiments',
                            'url': request.route_url('dashboard')},
                           {'title': experiment.title,
                            'url': request.route_url('experiment.view', eid=experiment.id)},
                           {'title': 'Pages',
                            'url': request.route_url('experiment.page', eid=experiment.id)},
                           {'title': '%s (%s)' % (page.title, page.name)
                            if page.title else 'No title (%s)' % page.name,
                            'url': request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id)},
                           {'title': 'Delete',
                            'url': request.route_url('experiment.page.delete', eid=experiment.id, pid=page.id)}]}
    else:
        raise HTTPNotFound()
def delete_part_task(request):
    """Handles the ``parts/{pid}/timed-tasks/{tid}/delete`` URL, providing the UI
    and backend for deleting an existing :class:`~wte.models.TimedTask` that
    belongs to a :class:`~wte.models.Part`.

    Requires that the user has "edit" rights on the
    :class:`~wte.models.Part`.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(
        Part.id == request.matchdict['pid']).first()
    task = dbsession.query(TimedTask).filter(
        TimedTask.id == request.matchdict['tid']).first()
    if part and task:
        if part.allow('edit', request.current_user):
            crumbs = create_part_crumbs(
                request, part,
                [{
                    'title': 'Timed Actions',
                    'url': request.route_url('part.timed_task', pid=part.id)
                }, {
                    'title': 'Delete',
                    'url': request.current_route_url
                }])
            if request.method == 'POST':
                try:
                    CSRFSchema().to_python(request.params,
                                           State(request=request))
                    dbsession = DBSession()
                    with transaction.manager:
                        dbsession.delete(task)
                    dbsession.add(part)
                    raise HTTPSeeOther(
                        request.route_url('part.timed_task', pid=part.id))
                except formencode.Invalid as e:
                    return {
                        'errors': e.error_dict,
                        'part': part,
                        'task': task,
                        'crumbs': crumbs,
                        'include_footer': True,
                        'help': ['user', 'teacher', 'timed_actions.html']
                    }
            return {
                'part': part,
                'task': task,
                'crumbs': crumbs,
                'include_footer': True,
                'help': ['user', 'teacher', 'timed_actions.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
示例#14
0
def import_page(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        if request.method == 'POST':
            try:
                params = ImportPageSchema().to_python(request.params, State(request=request,
                                                                            dbsession=dbsession))
                with transaction.manager:
                    dbsession.add(experiment)
                    page, errors = PageIOSchema(include_data=('questions', 'questions.q_type',
                                                              'questions.q_type.parent',
                                                              'questions.q_type.q_type_group',
                                                              'questions.q_type.q_type_group.parent',
                                                              'questions.q_type.parent.q_type_group',
                                                              'questions.q_type.parent.q_type_group.parent')).\
                        loads(params['source'].file.read().decode('utf-8'))
                    if errors:
                        raise formencode.Invalid('. '.join(['%s: %s' % (e['source']['pointer'], e['detail'])
                                                            for e in errors['errors']]), None, None)
                    dbsession.add(page)
                    replace_questions(page, dbsession)
                    page.experiment = experiment
                dbsession.add(experiment)
                dbsession.add(page)
                raise HTTPFound(request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id))
            except formencode.Invalid as e:
                return {'experiment': experiment,
                        'crumbs': [{'title': 'Experiments',
                                    'url': request.route_url('dashboard')},
                                   {'title': experiment.title,
                                    'url': request.route_url('experiment.view', eid=experiment.id)},
                                   {'title': 'Pages',
                                    'url': request.route_url('experiment.page', eid=experiment.id)},
                                   {'title': 'Import a Page',
                                    'url': request.route_url('experiment.page.import', eid=experiment.id)}],
                        'errors': {'source': str(e)},
                        'values': request.params}
        return {'experiment': experiment,
                'crumbs': [{'title': 'Experiments',
                            'url': request.route_url('dashboard')},
                           {'title': experiment.title,
                            'url': request.route_url('experiment.view', eid=experiment.id)},
                           {'title': 'Pages',
                            'url': request.route_url('experiment.page', eid=experiment.id)},
                           {'title': 'Import a Page',
                            'url': request.route_url('experiment.page.import', eid=experiment.id)}]}
    else:
        raise HTTPNotFound()
示例#15
0
def delete(request):
    """Handles the ``/parts/{pid}/assets/{aid}/delete`` URL,
    providing the UI and backend for deleting :class:`~wte.models.Asset`.

    Requires that the user has "edit" rights on the current :class:`~wte.models.Part`.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(
        Part.id == request.matchdict['pid']).first()
    asset = dbsession.query(Asset).join(Part.all_assets).\
        filter(and_(Asset.id == request.matchdict['aid'],
                    Part.id == request.matchdict['pid'])).first()
    if part and asset:
        if part.allow('edit', request.current_user):
            crumbs = create_part_crumbs(request, part, {
                'title': 'Delete Asset',
                'url': request.current_route_url()
            })
            if request.method == 'POST':
                try:
                    CSRFSchema().to_python(request.params,
                                           State(request=request))
                    dbsession = DBSession()
                    with transaction.manager:
                        dbsession.add(asset)
                        asset.parts = []
                        dbsession.delete(asset)
                    dbsession.add(part)
                    raise HTTPSeeOther(
                        request.route_url('part.view', pid=part.id))
                except formencode.Invalid as e:
                    return {
                        'errors': e.error_dict,
                        'part': part,
                        'asset': asset,
                        'crumbs': crumbs,
                        'help': ['user', 'teacher', 'asset', 'delete.html']
                    }
            return {
                'part': part,
                'asset': asset,
                'crumbs': crumbs,
                'help': ['user', 'teacher', 'asset', 'delete.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
示例#16
0
def export(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                             Page.experiment_id == request.matchdict['eid'])).first()
    if experiment and page:
        try:
            CSRFSchema().to_python(request.params, State(request=request))
            request.response.headers['Content-Disposition'] = 'attachment; filename="%s.json"' % page.name
            return PageIOSchema(include_data=('questions', 'questions.q_type', 'questions.q_type.parent',
                                              'questions.q_type.q_type_group', 'questions.q_type.q_type_group.parent',
                                              'questions.q_type.parent.q_type_group',
                                              'questions.q_type.parent.q_type_group.parent')).dump(page).data
        except formencode.Invalid:
            raise HTTPFound(request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id))
    else:
        raise HTTPNotFound()
示例#17
0
def data_item_edit(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(
        Experiment.id == request.matchdict['eid']).first()
    data_set = dbsession.query(DataSet).filter(
        and_(DataSet.id == request.matchdict['did'],
             DataSet.experiment_id == request.matchdict['eid'],
             DataSet.type == 'dataset')).first()
    data_item = dbsession.query(DataItem).filter(
        and_(DataItem.id == request.matchdict['diid'],
             DataItem.dataset_id == request.matchdict['did'])).first()
    if experiment and data_set and data_item:
        try:
            schema = DynamicSchema()
            schema.add_field('csrf_token', CSRFValidator())
            for column in data_set['columns']:
                schema.add_field(
                    column,
                    formencode.validators.UnicodeString(if_empty='',
                                                        if_missing=''))
            params = schema.to_python(request.params, State(request=request))
            with transaction.manager:
                dbsession.add(data_item)
                dbsession.add(data_set)
                data = {}
                for column in data_set['columns']:
                    data[column] = params[column]
                data_item['values'] = data
            dbsession.add(data_item)
            return {
                'status': 'ok',
                'id': data_item.id,
                'order': data_item.order,
                'values': data_item['values']
            }
        except formencode.Invalid as e:
            return {'status': 'error', 'errors': e.unpack_errors()}
        dbsession.add(experiment)
        dbsession.add(data_set)
        dbsession.add(data_item)
        raise HTTPFound(
            request.route_url('experiment.data.view',
                              eid=experiment.id,
                              did=data_set.id))
    else:
        raise HTTPNotFound()
示例#18
0
def create(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        if request.method == 'POST':
            try:
                params = CreatePageSchema().to_python(request.params, State(request=request,
                                                                            dbsession=dbsession,
                                                                            experiment=experiment))
                with transaction.manager:
                    page = Page(experiment=experiment,
                                name=params['name'],
                                title=params['title'],
                                styles='',
                                scripts='')
                    dbsession.add(page)
                    dbsession.add(experiment)
                    if experiment.start is None:
                        experiment.start = page
                dbsession.add(experiment)
                dbsession.add(page)
                raise HTTPFound(request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id))
            except formencode.Invalid as e:
                return {'experiment': experiment,
                        'crumbs': [{'title': 'Experiments',
                                    'url': request.route_url('dashboard')},
                                   {'title': experiment.title,
                                    'url': request.route_url('experiment.view', eid=experiment.id)},
                                   {'title': 'Pages',
                                    'url': request.route_url('experiment.page', eid=experiment.id)},
                                   {'title': 'Add a Page',
                                    'url': request.route_url('experiment.page.create', eid=experiment.id)}],
                        'errors': e.error_dict,
                        'values': request.params}
        return {'experiment': experiment,
                'crumbs': [{'title': 'Experiments',
                            'url': request.route_url('dashboard')},
                           {'title': experiment.title,
                            'url': request.route_url('experiment.view', eid=experiment.id)},
                           {'title': 'Pages',
                            'url': request.route_url('experiment.page', eid=experiment.id)},
                           {'title': 'Add a Page',
                            'url': request.route_url('experiment.page.create', eid=experiment.id)}]}
    else:
        raise HTTPNotFound()
示例#19
0
def check_answers(request):
    """Handles the "/parts/{pid}/quiz/check_answers" URL, checking whether a
    :class:`~wte.models.QuizAnswer` exists and if so, returning whether it was
    answered correctly and what the answer was.

    The response does not distinguish between initial or finally correct, but will return
    the last answer the user provided.
    """
    try:
        params = CheckAnswerSchema().to_python(request.params,
                                               State(request=request))
        dbsession = DBSession()
        quiz = dbsession.query(Quiz).filter(
            and_(Quiz.part_id == request.matchdict['pid'],
                 Quiz.name == params['quiz'])).first()
        if quiz:
            answer = dbsession.query(QuizAnswer).filter(
                and_(QuizAnswer.user_id == request.current_user.id,
                     QuizAnswer.quiz_id == quiz.id,
                     QuizAnswer.question == params['question'])).first()
            if answer:
                if answer.initial_correct:
                    return {
                        'status': 'correct',
                        'answer': json.loads(answer.initial_answer)
                    }
                elif answer.final_correct:
                    return {
                        'status': 'correct',
                        'answer': json.loads(answer.final_answer)
                    }
                elif answer.final_correct is None:
                    return {
                        'status': 'incorrect',
                        'answer': json.loads(answer.initial_answer)
                    }
                else:
                    return {
                        'status': 'incorrect',
                        'answer': json.loads(answer.final_answer)
                    }
        return {'status': 'unanswered'}
    except Invalid as e:
        return {'status': 'error', 'errors': e.error_dict}
示例#20
0
def set_answers(request):
    """Handles the "/parts/{pid}/quiz/set_answers" URL and stores the answers to a
    :class:`~wte.text_formatter.docutils_ext.QuizQuestion`.

    If no previous :class:`~wte.models.QuizAnswer` exists, creates one and sets
    the initial answers / correctness to the data supplied. If one exists,
    then sets the final answer / correctness and updates the attempts count.
    """
    try:
        dbsession = DBSession()
        part = dbsession.query(Part).filter(
            Part.id == request.matchdict['pid']).first()
        if part and part.has_role('student', request.current_user):
            params = SetAnswersSchema().to_python(request.params,
                                                  State(request=request))
            with transaction.manager:
                quiz = dbsession.query(Quiz).filter(
                    and_(Quiz.part_id == request.matchdict['pid'],
                         Quiz.name == params['quiz'])).first()
                if quiz:
                    answer = dbsession.query(QuizAnswer).filter(
                        and_(QuizAnswer.user_id == request.current_user.id,
                             QuizAnswer.quiz_id == quiz.id, QuizAnswer.question
                             == params['question'])).first()
                    if answer:
                        if not answer.initial_correct and not answer.final_correct:
                            answer.attempts = answer.attempts + 1
                            answer.final_answer = json.dumps(params['answer'])
                            answer.final_correct = params['correct']
                    else:
                        dbsession.add(
                            QuizAnswer(user_id=request.current_user.id,
                                       quiz=quiz,
                                       question=params['question'],
                                       initial_answer=json.dumps(
                                           params['answer']),
                                       initial_correct=params['correct'],
                                       final_answer=None,
                                       final_correct=None,
                                       attempts=1))
        return {}
    except Invalid as e:
        return {'errors': e.error_dict}
def create(request):
    if request.method == 'POST':
        try:
            params = CreateExperimentSchema().to_python(
                request.params, State(request=request))
            dbsession = DBSession()
            with transaction.manager:
                experiment = Experiment(title=params['title'],
                                        summary='',
                                        styles='',
                                        scripts='',
                                        status='develop',
                                        language='en',
                                        external_id=uuid.uuid1().hex,
                                        owned_by=request.current_user.id,
                                        public=False)
                dbsession.add(experiment)
            dbsession.add(experiment)
            raise HTTPFound(
                request.route_url('experiment.view', eid=experiment.id))
        except formencode.Invalid as e:
            return {
                'crumbs': [{
                    'title': 'Experiments',
                    'url': request.route_url('dashboard')
                }, {
                    'title': 'Create',
                    'url': request.route_url('experiment.create')
                }],
                'errors':
                e.error_dict,
                'values':
                request.params
            }
    return {
        'crumbs': [{
            'title': 'Experiments',
            'url': request.route_url('dashboard')
        }, {
            'title': 'Create',
            'url': request.route_url('experiment.create')
        }]
    }
示例#22
0
def add_question(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                                 Page.experiment == experiment)).first()
    else:
        page = None
    qtype = dbsession.query(QuestionType).filter(QuestionType.id == request.matchdict['qtid']).first()
    if experiment and page and qtype:
        try:
            params = AddQuestionSchema().to_python(request.params, State(request=request))
            with transaction.manager:
                dbsession.add(page)
                if params['order'] is None:
                    params['order'] = len(page.questions)
                question = Question(q_type=qtype,
                                    page=page,
                                    order=params['order'])
                if question['frontend', 'visible']:
                    visible_idx = [q['frontend', 'question_number']
                                   for q in page.questions
                                   if q['frontend', 'visible'] and
                                   q['frontend', 'title'] and
                                   q['frontend', 'question_number']]
                    if visible_idx:
                        visible_idx = max(visible_idx) + 1
                    else:
                        visible_idx = 1
                    question['frontend', 'question_number'] = visible_idx
                dbsession.add(question)
            dbsession.add(experiment)
            dbsession.add(page)
            dbsession.add(question)
            raise HTTPFound(request.route_url('experiment.page.edit',
                                              eid=experiment.id, pid=page.id,
                                              _anchor='question-%i' % question.id))
        except formencode.Invalid:
            raise HTTPFound(request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id))
    else:
        raise HTTPNotFound()
示例#23
0
def reorder_transition(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                                 Page.experiment == experiment)).first()
    else:
        page = None
    if experiment and page:
        try:
            params = ReorderSchema().to_python(request.params, State(request=request))
            with transaction.manager:
                for idx, tid in enumerate(params['item']):
                    transition = dbsession.query(Transition).filter(and_(Transition.id == tid,
                                                                         Transition.source == page)).first()
                    if transition is not None:
                        transition.order = idx
            return {'status': 'ok'}
        except formencode.Invalid:
            return {'status': 'error'}
    else:
        raise HTTPNotFound()
示例#24
0
def action(request):
    """Handles the ``parts/{pid}/users/action`` URL, loads the interface for changing
    :class:`~wte.models.User` registered for a :class:`~wte.models.Part`.

    Requires that the user has "users" rights on the
    :class:`~wte.models.Part`.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(Part.id == request.matchdict['pid']).first()
    if part:
        if part.allow('users', request.current_user):
            query_params = []
            for param in ['q', 'role', 'start']:
                if param in request.params and request.params[param]:
                    query_params.append((param, request.params[param]))
            try:
                params = ActionSchema().to_python(request.params,
                                                  State(request=request))
            except formencode.api.Invalid:
                request.session.flash('Please select the action you wish to apply ' +
                                      'and the users you wish to apply it to', queue='error')
                raise HTTPSeeOther(request.route_url('part.users', pid=part.id, _query=query_params))
            crumbs = create_part_crumbs(request,
                                        part,
                                        [{'title': 'Users',
                                         'url': request.route_url('part.users', pid=part.id)},
                                         {'title': 'Update',
                                          'url': request.current_route_url()}])
            users = dbsession.query(UserPartRole).filter(UserPartRole.id.in_(params['role_id'])).all()
            return {'part': part,
                    'params': params,
                    'query_params': query_params,
                    'users': users,
                    'crumbs': crumbs,
                    'help': ['user', 'teacher', 'module', 'users.html']}
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
示例#25
0
def data_reorder(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(
        Experiment.id == request.matchdict['eid']).first()
    data_set = dbsession.query(DataSet).filter(
        and_(DataSet.id == request.matchdict['did'],
             DataSet.experiment_id == request.matchdict['eid'],
             DataSet.type == 'dataset')).first()
    if experiment and data_set:
        try:
            params = ReorderSchema().to_python(request.params,
                                               State(request=request))
            with transaction.manager:
                for idx, qid in enumerate(params['item']):
                    item = dbsession.query(DataItem).filter(
                        and_(DataItem.id == qid,
                             DataItem.dataset_id == data_set.id)).first()
                    if item is not None:
                        item.order = idx
            return {'status': 'ok'}
        except formencode.Invalid:
            return {'status': 'error'}
    else:
        raise HTTPNotFound()
示例#26
0
def data_delete(request):
    mode = 'latinsquare' if 'latinsquare' in request.matched_route.name else 'dataset'
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(
        Experiment.id == request.matchdict['eid']).first()
    data_set = dbsession.query(DataSet).filter(
        and_(DataSet.id == request.matchdict['did'],
             DataSet.experiment_id == request.matchdict['eid'],
             DataSet.type == mode)).first()
    if experiment and data_set:
        try:
            CSRFSchema().to_python(request.params, State(request=request))
            with transaction.manager:
                dbsession.delete(data_set)
            dbsession.add(experiment)
            raise HTTPFound(
                request.route_url('experiment.%s' % mode, eid=experiment.id))
        except formencode.Invalid:
            raise HTTPFound(
                request.route_url('experiment.%s.view' % mode,
                                  eid=experiment.id,
                                  did=data_set.id))
    else:
        raise HTTPNotFound()
示例#27
0
def export_settings(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(
        Experiment.id == request.matchdict['eid']).first()
    if experiment:
        if request.method == 'POST':
            try:
                schema = ExportSchema()
                questions = [
                    str(q.id) for p in experiment.pages for q in p.questions
                    if q['frontend', 'generates_response']
                ]
                schema.add_field(
                    'question',
                    formencode.ForEach(
                        formencode.validators.OneOf(questions,
                                                    not_empty=True)))
                for data_set in experiment.data_sets:
                    schema.add_field(
                        'data_set_identifier_%s' % data_set.id,
                        formencode.validators.OneOf(
                            ['_id'] + [str(c) for c in data_set['columns']]))
                params = schema.to_python(request.params,
                                          State(request=request))

                def data_item_column_mapper(data_item):
                    if params['data_set_identifier_%s' %
                              data_item.dataset_id] == '_id':
                        return data_item.id
                    else:
                        return data_item['values'][params[
                            'data_set_identifier_%s' % data_item.dataset_id]]

                columns = set(['_participant'])
                if params['include_incomplete']:
                    query = dbsession.query(Participant).filter(
                        and_(Participant.experiment_id == experiment.id))
                    columns.add('_completed')
                else:
                    query = dbsession.query(Participant).filter(
                        and_(Participant.experiment_id == experiment.id,
                             Participant.completed == True))  # noqa: 712
                if params['include_useragent']:
                    columns.add('_user_agent.screen_size')
                    columns.add('_user_agent.string')
                for participant in query:
                    if params['include_useragent']:
                        if 'user_agent' in participant:
                            if 'input_types' in participant['user_agent']:
                                columns.update([
                                    '_user_agent.input_type.%s' % input_type
                                    for input_type in participant['user_agent']
                                    ['input_types']
                                ])
                    for answer in participant.answers:
                        if str(answer.question.id) not in params['question']:
                            continue
                        if 'response' not in answer or answer[
                                'response'] is None:
                            continue
                        column = '%s.%s' % (answer.question.page.name,
                                            answer.question['name'])
                        new_columns = []
                        if answer.question[
                                'frontend',
                                'display_as'] == 'select_simple_choice':
                            if answer.question['frontend', 'allow_other']:
                                if answer.question['frontend',
                                                   'allow_multiple']:
                                    if isinstance(
                                            answer['response']['response'],
                                            list):
                                        new_columns = [
                                            '%s.%s' % (column, a) for a in
                                            answer['response']['response']
                                        ]
                                    else:
                                        new_columns = [
                                            '%s.%s' %
                                            (column,
                                             answer['response']['response'])
                                        ]
                                    new_columns.append('%s.other_response' %
                                                       (column))
                                else:
                                    new_columns = [
                                        column,
                                        '%s.other_response' % column
                                    ]
                            else:
                                if answer.question['frontend',
                                                   'allow_multiple']:
                                    if isinstance(answer['response'], list):
                                        new_columns = [
                                            '%s.%s' % (column, a)
                                            for a in answer['response']
                                        ]
                                    else:
                                        new_columns = [
                                            '%s.%s' %
                                            (column, answer['response'])
                                        ]
                                else:
                                    new_columns = [column]
                            if answer.question['frontend',
                                               'randomise_answers']:
                                new_columns.append('%s.answer_order' % column)
                        elif answer.question[
                                'frontend',
                                'display_as'] == 'select_grid_choice':
                            for key, value in answer['response'].items():
                                sub_column = '%s.%s' % (column, key)
                                if answer.question['frontend',
                                                   'allow_multiple']:
                                    if isinstance(value, list):
                                        sub_column = [
                                            '%s.%s' % (sub_column, a)
                                            for a in value
                                        ]
                                    else:
                                        sub_column = [
                                            '%s.%s' % (sub_column, value)
                                        ]
                                else:
                                    sub_column = [sub_column]
                                new_columns.extend(sub_column)
                            if answer.question['frontend',
                                               'randomise_answers']:
                                new_columns.append('%s.answer_order' % column)
                            if answer.question['frontend',
                                               'randomise_questions']:
                                new_columns.append('%s.question_order' %
                                                   column)
                        elif answer.question['frontend',
                                             'display_as'] == 'ranking':
                            new_columns.extend([
                                '%s.%s' % (column, a['value'])
                                for a in answer.question['frontend', 'answers']
                            ])
                            if answer.question['frontend',
                                               'randomise_answers']:
                                new_columns.append('%s.answer_order' % column)
                        else:
                            if answer.question['frontend', 'allow_multiple']:
                                if isinstance(answer['response'], list):
                                    new_columns = [
                                        '%s.%s' % (column, a)
                                        for a in answer['response']
                                    ]
                                else:
                                    new_columns = [
                                        '%s.%s' % (column, answer['response'])
                                    ]
                            else:
                                new_columns = [column]
                        if answer.question.page.dataset_id is not None:
                            new_columns = [
                                '%s.%s' % (c, data_item_column_mapper(di))
                                for c in new_columns
                                for di in answer.question.page.data_set.items
                            ]
                        columns.update(new_columns)
                columns = list(columns)
                columns.sort(key=lambda k: k.split('.'))
                io = StringIO()
                writer = DictWriter(io,
                                    fieldnames=columns,
                                    restval=params['na_value'],
                                    extrasaction='ignore')
                writer.writeheader()
                for participant in query.order_by(Participant.id):
                    responses = {'_participant': participant.id}
                    if params['include_incomplete']:
                        responses['_completed'] = participant.completed
                    if params['include_useragent']:
                        if 'user_agent' in participant:
                            if 'input_types' in participant['user_agent']:
                                for column in columns:
                                    if column.startswith(
                                            '_user_agent.input_type.'):
                                        responses[column] = 0
                                for input_type in participant['user_agent'][
                                        'input_types']:
                                    responses['_user_agent.input_type.%s' %
                                              input_type] = 1
                            if 'screen_size' in participant['user_agent']:
                                responses[
                                    '_user_agent.screen_size'] = participant[
                                        'user_agent']['screen_size']
                            if 'user_agent' in participant['user_agent']:
                                responses['_user_agent.string'] = participant[
                                    'user_agent']['user_agent']
                    for answer in participant.answers:
                        if 'response' not in answer or answer[
                                'response'] is None:
                            continue
                        column = '%s.%s' % (answer.question.page.name,
                                            answer.question['name'])
                        if answer.question[
                                'frontend',
                                'display_as'] == 'select_simple_choice':
                            if answer.question['frontend', 'allow_other']:
                                if answer.question['frontend',
                                                   'allow_multiple']:
                                    for c in columns:
                                        if c.startswith(column):
                                            responses[c] = 0
                                    if isinstance(
                                            answer['response']['response'],
                                            list):
                                        for sub_answer in answer['response'][
                                                'response']:
                                            if answer.data_item_id is None:
                                                responses['%s.%s' %
                                                          (column,
                                                           sub_answer)] = 1
                                            else:
                                                responses['%s.%s.%s' % (
                                                    column, sub_answer,
                                                    data_item_column_mapper(
                                                        answer.data_item))] = 1
                                    else:
                                        if answer.data_item_id is None:
                                            responses['%s.%s' %
                                                      (column,
                                                       answer['response']
                                                       ['response'])] = 1
                                        else:
                                            responses['%s.%s.%s' % (
                                                column,
                                                answer['response']['response'],
                                                data_item_column_mapper(
                                                    answer.data_item))] = 1
                                    if answer['response']['other']:
                                        if answer.data_item_id is None:
                                            responses['%s.other_response' %
                                                      column] = answer[
                                                          'response']['other']
                                        else:
                                            responses['%s.other_response.%s' %
                                                      (column, data_item_column_mapper(answer.data_item))] = \
                                                answer['response']['other']
                                else:
                                    if answer.data_item_id is None:
                                        if isinstance(answer['response'],
                                                      dict):
                                            responses[column] = answer[
                                                'response']['response']
                                            if answer['response']['other']:
                                                responses[
                                                    '%s.other_response' %
                                                    column] = answer[
                                                        'response']['other']
                                        else:
                                            responses[column] = answer[
                                                'response']
                                    else:
                                        responses['%s.%s' % (column, data_item_column_mapper(answer.data_item))] = \
                                            answer['response']['response']
                                        if answer['response']['other']:
                                            responses['%s.other_response.%s' %
                                                      (column, data_item_column_mapper(answer.data_item))] = \
                                                answer['response']['other']
                            else:
                                if answer.question['frontend',
                                                   'allow_multiple']:
                                    for c in columns:
                                        if c.startswith(column):
                                            responses[c] = 0
                                    if isinstance(answer['response'], list):
                                        for sub_answer in answer['response']:
                                            if answer.data_item_id is None:
                                                responses['%s.%s' %
                                                          (column,
                                                           sub_answer)] = 1
                                            else:
                                                responses['%s.%s.%s' % (
                                                    column, sub_answer,
                                                    data_item_column_mapper(
                                                        answer.data_item))] = 1
                                    else:
                                        if answer.data_item_id is None:
                                            responses['%s.%s' %
                                                      (column,
                                                       answer['response'])] = 1
                                        else:
                                            responses[
                                                '%s.%s.%s' %
                                                (column, answer['response'],
                                                 data_item_column_mapper(
                                                     answer.data_item))] = 1
                                else:
                                    if answer.data_item_id is None:
                                        responses[column] = answer['response']
                                    else:
                                        responses['%s.%s' %
                                                  (column, data_item_column_mapper(answer.data_item))] = \
                                            answer['response']
                            if answer.question['frontend',
                                               'randomise_answers']:
                                responses['%s.answer_order' %
                                          column] = answer['answer_order']
                        elif answer.question[
                                'frontend',
                                'display_as'] == 'select_grid_choice':
                            for key, value in answer['response'].items():
                                sub_column = '%s.%s' % (column, key)
                                if answer.question['frontend',
                                                   'allow_multiple']:
                                    for c in columns:
                                        if c.startswith(sub_column):
                                            responses[c] = 0
                                    if isinstance(value, list):
                                        for sub_answer in value:
                                            if answer.data_item_id is None:
                                                responses['%s.%s' %
                                                          (sub_column,
                                                           sub_answer)] = 1
                                            else:
                                                responses['%s.%s.%s' % (
                                                    sub_column, sub_answer,
                                                    data_item_column_mapper(
                                                        answer.data_item))] = 1
                                    else:
                                        if answer.data_item_id is None:
                                            responses['%s.%s' %
                                                      (sub_column, value)] = 1
                                        else:
                                            responses[
                                                '%s.%s.%s' %
                                                (sub_column, value,
                                                 data_item_column_mapper(
                                                     answer.data_item))] = 1
                                else:
                                    if answer.data_item_id is None:
                                        responses[sub_column] = value
                                    else:
                                        responses[
                                            '%s.%s' %
                                            (sub_column,
                                             data_item_column_mapper(
                                                 answer.data_item))] = value
                            if answer.question['frontend',
                                               'randomise_answers']:
                                responses['%s.answer_order' %
                                          column] = answer['answer_order']
                            if answer.question['frontend',
                                               'randomise_questions']:
                                responses['%s.question_order' %
                                          column] = answer['question_order']
                        elif answer.question['frontend',
                                             'display_as'] == 'ranking':
                            for idx, sub_answer in enumerate(
                                    answer['response']):
                                if answer.data_item_id is None:
                                    responses['%s.%s' %
                                              (column, sub_answer)] = idx
                                else:
                                    responses['%s.%s.%s' %
                                              (column, sub_answer,
                                               data_item_column_mapper(
                                                   answer.data_item))] = idx
                            if answer.question['frontend',
                                               'randomise_answers']:
                                responses['%s.answer_order' %
                                          column] = answer['answer_order']
                        else:
                            if answer.question['frontend', 'allow_multiple']:
                                for c in columns:
                                    if c.startswith(column):
                                        responses[c] = 0
                                if isinstance(answer['response'], list):
                                    for sub_answer in answer['response']:
                                        if answer.data_item_id is None:
                                            responses['%s.%s' %
                                                      (column, sub_answer)] = 1
                                        else:
                                            responses[
                                                '%s.%s.%s' %
                                                (column, sub_answer,
                                                 data_item_column_mapper(
                                                     answer.data_item))] = 1
                                else:
                                    if answer.data_item_id is None:
                                        responses['%s.%s' %
                                                  (column,
                                                   answer['response'])] = 1
                                    else:
                                        responses['%s.%s.%s' %
                                                  (column, answer['response'],
                                                   data_item_column_mapper(
                                                       answer.data_item))] = 1
                            else:
                                if answer.data_item_id is None:
                                    responses[column] = answer['response']
                                else:
                                    responses['%s.%s' % (column, data_item_column_mapper(answer.data_item))] = \
                                        answer['response']
                    writer.writerow(responses)
                return Response(body=io.getvalue().encode('utf8'),
                                headers=[('Content-Type', 'text/csv'),
                                         ('Content-Disposition',
                                          'attachment; filename="%s.csv"' %
                                          experiment.title)])
            except formencode.Invalid as e:
                return {
                    'experiment':
                    experiment,
                    'values':
                    request.params,
                    'errors':
                    e.error_dict,
                    'crumbs': [{
                        'title': 'Experiments',
                        'url': request.route_url('dashboard')
                    }, {
                        'title':
                        experiment.title,
                        'url':
                        request.route_url('experiment.view', eid=experiment.id)
                    }, {
                        'title':
                        'Results',
                        'url':
                        request.route_url('experiment.results',
                                          eid=experiment.id)
                    }, {
                        'title':
                        'Export',
                        'url':
                        request.route_url('experiment.results.export',
                                          eid=experiment.id)
                    }]
                }
        return {
            'experiment':
            experiment,
            'crumbs': [{
                'title': 'Experiments',
                'url': request.route_url('dashboard')
            }, {
                'title':
                experiment.title,
                'url':
                request.route_url('experiment.view', eid=experiment.id)
            }, {
                'title':
                'Results',
                'url':
                request.route_url('experiment.results', eid=experiment.id)
            }, {
                'title':
                'Export',
                'url':
                request.route_url('experiment.results.export',
                                  eid=experiment.id)
            }]
        }
    else:
        raise HTTPNotFound()
示例#28
0
def reset(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(
        Experiment.id == request.matchdict['eid']).first()
    if experiment:
        if request.method == 'POST':
            try:
                ResetSchema().to_python(request.params, State(request=request))
                with transaction.manager:
                    dbsession.add(experiment)
                    experiment.participants = []
                dbsession.add(experiment)
                raise HTTPFound(
                    request.route_url('experiment.results', eid=experiment.id))
            except formencode.Invalid as e:
                return {
                    'experiment':
                    experiment,
                    'values':
                    request.params,
                    'errors':
                    e.error_dict,
                    'crumbs': [{
                        'title': 'Experiments',
                        'url': request.route_url('dashboard')
                    }, {
                        'title':
                        experiment.title,
                        'url':
                        request.route_url('experiment.view', eid=experiment.id)
                    }, {
                        'title':
                        'Results',
                        'url':
                        request.route_url('experiment.results',
                                          eid=experiment.id)
                    }, {
                        'title':
                        'Reset',
                        'url':
                        request.route_url('experiment.results.reset',
                                          eid=experiment.id)
                    }]
                }
        return {
            'experiment':
            experiment,
            'crumbs': [{
                'title': 'Experiments',
                'url': request.route_url('dashboard')
            }, {
                'title':
                experiment.title,
                'url':
                request.route_url('experiment.view', eid=experiment.id)
            }, {
                'title':
                'Results',
                'url':
                request.route_url('experiment.results', eid=experiment.id)
            }, {
                'title':
                'Clear',
                'url':
                request.route_url('experiment.results.reset',
                                  eid=experiment.id)
            }]
        }
    else:
        raise HTTPNotFound()
def edit_part_task(request):
    """Handles the ``parts/{pid}/timed-tasks/{tid}/edit`` URL, providing the UI
    and backend for editing an existing :class:`~wte.models.TimedTask` that
    belongs to a :class:`~wte.models.Part`.

    Requires that the user has "edit" rights on the
    :class:`~wte.models.Part`.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(
        Part.id == request.matchdict['pid']).first()
    task = dbsession.query(TimedTask).filter(
        TimedTask.id == request.matchdict['tid']).first()
    if part and task:
        if part.allow('edit', request.current_user):
            crumbs = create_part_crumbs(
                request, part,
                [{
                    'title': 'Timed Actions',
                    'url': request.route_url('part.timed_task', pid=part.id)
                }, {
                    'title': 'Edit',
                    'url': request.current_route_url
                }])
            if request.method == 'POST':
                try:
                    options = []
                    if task.name == 'change_status':
                        status = ['available', 'unavailable']
                        if part.type == 'module':
                            status.append('archived')
                        options.append(('target_status',
                                        formencode.validators.OneOf(status)))
                    params = EditTimedTaskSchema(options).to_python(
                        request.params, State(request=request))
                    dbsession = DBSession()
                    with transaction.manager:
                        dbsession.add(task)
                        task.timestamp = datetime.combine(
                            params['date'], params['time'])
                        if 'options' in params and params['options']:
                            task.options = params['options']
                            task.status = 'ready'
                    dbsession.add(part)
                    raise HTTPSeeOther(
                        request.route_url('part.timed_task', pid=part.id))
                except formencode.Invalid as e:
                    return {
                        'errors': e.error_dict,
                        'values': request.params,
                        'part': part,
                        'task': task,
                        'crumbs': crumbs,
                        'include_footer': True,
                        'help': ['user', 'teacher', 'timed_actions.html']
                    }
            return {
                'part': part,
                'task': task,
                'crumbs': crumbs,
                'include_footer': True,
                'help': ['user', 'teacher', 'timed_actions.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
示例#30
0
def permissions(request):
    """Handles the "/users/{uid}/permissions" URL, providing the form and
    backend functionality for setting the :class:`~wte.models.Permission` and
    :class:`~wte.models.PermissionGroup` that the :class:`~wte.models.User`
    belongs to.
    """
    dbsession = DBSession()
    user = dbsession.query(User).filter(
        User.id == request.matchdict['uid']).first()
    if user:
        permission_groups = dbsession.query(PermissionGroup).order_by(
            PermissionGroup.title)
        permissions = dbsession.query(Permission).order_by(Permission.title)
        if request.method == 'POST':
            try:
                CSRFSchema(allow_extra_fields=True).to_python(
                    request.params, State(request=request))
                with transaction.manager:
                    dbsession.add(user)
                    ids = request.params.getall('permission_group')
                    if ids:
                        user.permission_groups = dbsession.query(PermissionGroup).\
                            filter(PermissionGroup.id.in_(ids)).all()
                    else:
                        user.permission_groups = []
                    ids = request.params.getall('permission')
                    if ids:
                        user.permissions = dbsession.query(Permission).filter(
                            Permission.id.in_(ids)).all()
                    else:
                        user.permissions = []
                dbsession.add(user)
                dbsession.add(request.current_user)
                if request.current_user.has_permission('admin.users.view'):
                    raise HTTPSeeOther(request.route_url('users'))
                else:
                    raise HTTPSeeOther(
                        request.route_url('user.view', uid=user.id))
            except Invalid as e:
                return {
                    'errors':
                    e.error_dict,
                    'user':
                    user,
                    'permission_groups':
                    permission_groups,
                    'permissions':
                    permissions,
                    'crumbs':
                    create_user_crumbs(
                        request,
                        [{
                            'title': user.display_name,
                            'url': request.route_url('user.view', uid=user.id)
                        }, {
                            'title':
                            'Permissions',
                            'url':
                            request.route_url('user.permissions', uid=user.id)
                        }])
                }
        return {
            'user':
            user,
            'permission_groups':
            permission_groups,
            'permissions':
            permissions,
            'crumbs':
            create_user_crumbs(
                request,
                [{
                    'title': user.display_name,
                    'url': request.route_url('user.view', uid=user.id)
                }, {
                    'title': 'Permissions',
                    'url': request.route_url('user.permissions', uid=user.id)
                }])
        }
    else:
        raise HTTPNotFound()