示例#1
0
def delete_task():
    data = json.loads(request.data)
    task_id = data['taskId']

    db.connect()
    submissions = db.select_columns('submissions', ['name'], ['task'],
                                    [task_id])

    if submissions:
        db.close()
        return error('Cannot delete this task!' +
                     '<br>Students have already made submissions')

    task_path = db.select_columns('task_attachments', ['path'], ['task'],
                                  [task_id])
    if task_path:
        file_upload = FileUpload(filename=task_path[0][0])
        file_upload.remove_file()

    db.delete_rows('tasks', ['id'], [task_id])
    db.delete_rows('task_attachments', ['task'], [task_id])
    db.delete_rows('task_criteria', ['task'], [task_id])
    db.delete_rows('allowed_files', ['task'], [task_id])
    db.delete_rows('submission_types', ['task'], [task_id])

    db.close()
    return jsonify({'status': 'ok', "message": "Task deleted"})
示例#2
0
def delete_material():
    data = json.loads(request.data)
    material_id = data['materialId']

    db.connect()

    material_path = db.select_columns('material_attachments', ['path'],
                                      ['material'], [material_id])
    if material_path:
        file_upload = FileUpload(filename=material_path[0][0])
        file_upload.remove_file()

    db.delete_rows('materials', ['id'], [material_id])
    db.delete_rows('material_attachments', ['material'], [material_id])
    db.close()
    return jsonify({'status': 'ok', "message": "Material deleted"})
示例#3
0
def build_student_submission(student_id, task_id):
    res = db.select_columns(
        'submissions', ['name', 'path', 'text', 'date_modified', 'status'],
        ['student', 'task'], [student_id, task_id])
    # Account for no submission and a text based submission (no path)
    if not res:
        return {}
    submission = {
        'name': res[0][0],
        'date_modified': timestamp_to_string(res[0][3], True),
        'status': {
            'id': res[0][4]
        },
        'file': None,
        'text': None
    }

    task = build_task(task_id)
    if 'file' in task['sub_method']['name']:
        submission['file'] = FileUpload(filename=res[0][1])
    else:
        submission['text'] = res[0][2]

    res = db.select_columns('request_statuses', ['name'], ['id'],
                            [submission['status']['id']])
    submission['status']['name'] = res[0][0]
    if 'approval' in task['mark_method']['name']:
        submission['mark_method'] = 'approval'
    else:
        submission['mark_method'] = 'mark'
    return submission
def allowed_file_access(filename):
    ''' Check if a file access should be permitted '''

    if 'user' not in session:
        raise KeyError('Not logged in')
    if not is_at_least_role(UserRole.STUDENT):
        # public users shouldn't have access to any file uploads
        return False
    if is_at_least_role(UserRole.STAFF):
        # allow staff to have access to anything
        return True

    # students should only have access to files they have submitted
    # or files in tasks within courses they are part of
    # or material files within courses they are part of
    # as long as the task and/or material is marked as visible

    try:
        name = FileUpload(filename=filename).get_name()
    except LookupError as e:
        if config.DEBUG:
            print(f'Request file: {e}')
        abort(404)
    db.connect()
    submitted_file = db.select_columns('submissions', ['path'],
                                       ['student', 'path'],
                                       [session['id'], name])
    task_files = queries.get_allowed_task_attachments(session['id'])
    materials = queries.get_allowed_material_attachments(session['id'])
    db.close()
    if submitted_file or (task_files and name in task_files) or \
       (materials and name in materials):
        return True
    else:
        return False
示例#5
0
def view_submission():
    student_id = request.args.get('submissions', None, type=int)
    if student_id is None:
        abort(400)
    db.connect()
    student_info = db.select_columns('users', ['name', 'email'], ['id'],
                                     [student_id])
    if not len(student_info):
        db.close()
        abort(404)

    # get tasks for this student
    tasks = []
    student_tasks = queries.get_student_submissions(student_id)
    for task in student_tasks:

        submit_date_text = timestamp_to_string(task[4], True)

        file_url = None
        if task[3]:
            file_url = FileUpload(filename=task[3]).get_url()

        status = get_sub_status(student_id, task[0])
        if 'approval' in task[2]:
            tasks.append((task[1], submit_date_text, status, file_url, task[0],
                          student_id))

        else:
            criteria = db.select_columns('task_criteria', ['id', 'max_mark'],
                                         ['task'], [task[0]])

            staff_mark = 0
            total_max_mark = 0
            for c in criteria:
                total_max_mark += c[1]
                mark = db.select_columns('marks', ['mark'],
                                         ['criteria', 'student', 'marker'],
                                         [c[0], student_id, session['id']])
                if len(mark) != 0:
                    staff_mark += mark[0][0]
                else:
                    staff_mark = -1
            if staff_mark <= 0:
                staff_mark = '- '
            tasks.append((task[1], submit_date_text,
                          str(staff_mark) + '/' + str(total_max_mark),
                          file_url, task[0], student_id))

    db.close()
    zid = student_info[0][1].split('@')[0]
    heading = f'Submissions - {student_info[0][0]} ({zid})'
    return render_template('submission_staff.html',
                           heading=heading,
                           title=heading,
                           submissions=tasks)
示例#6
0
def upload_enroll_file():
    try:
        enroll_file = FileUpload(req=request)
    except KeyError:
        return error('Could not find a file to upload')

    if enroll_file.get_extention() != '.csv':
        return error('File type must be in .csv format')

    if enroll_file.get_size() > config.MAX_FILE_SIZE:
        return error(
            f'File exceeds the maximum size of {config.MAX_FILE_SIZE} MB')
    enroll_file.commit()
    db.connect()
    error_string = update_from_file(enroll_file.get_path(),
                                    session['current_co'], 'student')
    db.close()
    enroll_file.remove_file()
    if error_string != "":
        return error(error_string)
    return jsonify({'status': 'ok'})
示例#7
0
def build_task(task_id):
    'Assumes you already have a database connection open'
    res = db.select_columns('tasks', [
        'deadline', 'marking_method', 'visible', 'course_offering',
        'word_limit', 'name', 'description', 'submission_method', 'word_limit',
        'size_limit'
    ], ['id'], [task_id])
    if not res:
        return None

    task = {
        'id': task_id,
        'deadline': res[0][0],
        'pretty_deadline': timestamp_to_string(res[0][0], True),
        'mark_method': {
            'id': res[0][1]
        },
        'sub_method': {
            'id': res[0][7]
        },
        'visible': res[0][2],
        'offering': res[0][3],
        'word_limit': res[0][4],
        'name': res[0][5],
        'description': res[0][6],
        'text_limit': res[0][8],
        'file_limit': res[0][9],
        'attachment': None,
        'accepted_files': queries.get_tasks_accepted_files(task_id)
    }
    res = queries.get_general_task_info(task_id)
    task['course_name'] = res[0][0]

    res = db.select_columns('marking_methods', ['name'], ['id'],
                            [task['mark_method']['id']])
    task['mark_method']['name'] = res[0][0]

    res = db.select_columns('submission_methods', ['name'], ['id'],
                            [task['sub_method']['id']])
    task['sub_method']['name'] = res[0][0]

    res = db.select_columns('task_attachments', ['path'], ['task'], [task_id])
    if res:
        task['attachment'] = FileUpload(filename=res[0][0])
    return task
示例#8
0
def manage_course_offerings():

    data = {}
    if request.method == 'POST':
        data = json.loads(request.data)
        if 'table' in data:
            if data['table'] == 'update_account_types':
                db.connect()
                if not re.match(config.EMAIL_FORMAT, data['email']):
                    db.close()
                    return error(f"""Invalid email address<br>
                        {config.EMAIL_FORMAT_ERROR}""")
                update_account_type(data['email'], data['name'],
                                    data['account_type'],
                                    session['current_co'])
                db.close()

            if data['table'] == 'materials':
                db.connect()
                db.update_rows('materials', [data['type']], ['visible'],
                               ['id'], [data['id']])
                db.close()

            if data['table'] == 'tasks':
                db.connect()
                db.update_rows('tasks', [data['type']], ['visible'], ['id'],
                               [data['id']])
                db.close()
        return jsonify({'status': 'ok'})

    co = 1
    if 'current_co' in session:
        co = session['current_co']
    else:
        session['current_co'] = co
        # maybe default to whatever course is in the current session
    db.connect()
    course_offerings = queries.get_course_offering_details()
    co_map, courses, sessions = split_co(course_offerings)
    materials_query = db.select_columns('materials', ['id', 'name', 'visible'],
                                        ['course_offering'], [co])
    materials = []
    for material in materials_query:
        attachments = []
        attachments_query = db.select_columns('material_attachments', ['path'],
                                              ['material'], [material[0]])
        for x in attachments_query:
            attachments.append(FileUpload(filename=x[0]))
        materials.append((material[0], material[1], attachments, material[2]))
    tasks = []
    task_query = db.select_columns('tasks',
                                   ['id', 'name', 'deadline', 'visible'],
                                   ['course_offering'], [co])
    task_ids = []
    task_query.sort(key=lambda x: x[2])
    for task in task_query:
        attachments = []
        attachments_query = db.select_columns('task_attachments', ['path'],
                                              ['task'], [task[0]])
        for x in attachments_query:
            attachments.append(FileUpload(filename=x[0]))

        print_date = timestamp_to_string(task[2])
        tasks.append((task[0], task[1], print_date, attachments, task[3]))
        task_ids.append(task[0])
    enrollments = []
    enrollments_query = queries.get_student_enrollments(co)
    for student in enrollments_query:
        zid = student[2].split('@')[0]
        if student[3] is not None:
            enrollments.append(
                (student[1], zid, student[2], student[3], student[0]))
        else:
            enrollments.append(
                (student[1], zid, student[2], 'No topic', student[0]))

    # for material file upload
    file_types = db.select_columns('file_types', ['name'])
    file_types = list(map(lambda x: x[0], file_types))
    allowed_file_types = ','.join(file_types)
    account_types = get_all_account_types()
    accepted_account_types = [('student', account_types['student']),
                              ('admin', account_types['course_admin'])]
    sessions_list = sessions[co_map[co]['course']]
    enrollments.sort(key=lambda x: zid_sort(x[1]))
    db.close()
    return render_template('manage_courses.html',
                           title='Manage Courses',
                           heading='Manage Courses',
                           materials=materials,
                           tasks=tasks,
                           enrollments=enrollments,
                           courses=courses,
                           sessions=sessions_list,
                           co_map=co_map,
                           default_co=co,
                           max_file_size=config.MAX_FILE_SIZE,
                           accepted_files=allowed_file_types,
                           task_ids=task_ids)
示例#9
0
def upload_material():
    try:
        fields = [
            'file-label', 'file-name', 'course-offering', 'old-material-id',
            'delete-old-file'
        ]
        file_label, file_name, course_offering, old_material_id, \
            delete_old_file = \
            get_fields(request.form, fields,
                       optional=['word-limit', 'file-name'],
                       ints=['course-offering'])
    except ValueError as e:
        return e.args[0]

    try:
        old_material_id = int(old_material_id)
    except ValueError as e:
        old_material_id = None

    # check if no file when there should be one
    if file_name == '' and \
            (delete_old_file == 'true' or old_material_id is None):
        return error('File is required!')
    db.connect()
    # check if course offering is valid
    res = db.select_columns('course_offerings', ['id'], ['id'],
                            [course_offering])
    if not len(res):
        db.close()
        return error('Cannot attach material to unknown course offering')

    # check if material with same label exists in course
    res = db.select_columns('materials', ['id'], ['name', 'course_offering'],
                            [file_label, course_offering])
    if len(res) and old_material_id != res[0][0]:
        db.close()
        return error('An item with that label already exists in this course')

    # otherwise, we can insert the material into the course
    if len(file_name):
        try:
            sent_file = FileUpload(req=request)
        except KeyError:
            db.close()
            return error('Could not find a file to upload')
        res = db.select_columns('file_types', ['name'])
        file_types = list(map(lambda x: x[0], res))
        if sent_file.get_extention() not in file_types:
            db.close()
            accept_files = ', '.join(file_types)
            return error(f'Accepted file types are: {accept_files}')
        if sent_file.get_size() > config.MAX_FILE_SIZE:
            sent_file.remove_file()
            db.close()
            return error(
                f'File exceeds the maximum size of {config.MAX_FILE_SIZE} MB')
        sent_file.commit()

    if delete_old_file == 'true':
        old = db.select_columns('material_attachments', ['path'], ['material'],
                                [old_material_id])
        if old:
            db.delete_rows('material_attachments', ['material'],
                           [old_material_id])
            try:
                prev_submission = FileUpload(filename=old[0][0])
                prev_submission.remove_file()
            except LookupError:
                # If the file doesn't exists don't worry as we are deleting
                # the attachment anyway
                pass

    if old_material_id is not None:
        # update existing material entries
        db.update_rows('materials', [file_label], ['name'], ['id'],
                       [old_material_id])
        db.update_rows('materials', [file_label], ['name'], ['id'],
                       [old_material_id])
        if delete_old_file == 'true':
            db.insert_single(
                'material_attachments',
                [old_material_id, sent_file.get_name()], ['material', 'path'])
    else:
        # add material and file path to db
        db.insert_single('materials', [course_offering, file_label, 0],
                         ['course_offering', 'name', 'visible'])
        res = db.select_columns('materials', ['id'],
                                ['name', 'course_offering'],
                                [file_label, course_offering])
        db.insert_single('material_attachments',
                         [res[0][0], sent_file.get_name()],
                         ['material', 'path'])
    db.close()
    return jsonify({'status': 'ok'})
def create():
    course_id = request.args.get('course_offering_id', None, type=int)
    if request.method == 'GET':
        if course_id is None:
            abort(400)
        db.connect()
        res = db.select_columns('course_offerings', ['id'], ['id'],
                                [course_id])
        if not len(res):
            db.close()
            abort(404)
        file_types = db.select_columns('file_types', ['name'])
        file_types = list(map(lambda x: x[0], file_types))
        allowed_file_types = ','.join(file_types)

        heading = 'Create Task'
        default_fields = {
            'task-name': '',
            'deadline': '',
            'task-description': '',
            'submission-type': 'text',
            'word-limit': '',
            'maximum-file-size': '',
            'accepted-file-type': '',
            'marking-method': 'accept',
            'criteria': [],
            'task_attachments': []
        }

        # if updating old task then load old task data
        old_task_id = request.args.get('update', None, type=int)
        if old_task_id is not None:
            res = queries.get_past_task_data(old_task_id)
            if res is not None:
                res = res[0]
                heading = 'Edit Task'

                # basic task details
                default_fields['task-name'] = res[0]
                time_format = '%d/%m/%Y %H:%M'
                due_date = datetime.fromtimestamp(res[1])
                default_fields['deadline'] = due_date.strftime(time_format)
                default_fields['task-description'] = res[2]

                attachments = db.select_columns('task_attachments', ['path'],
                                                ['task'], [old_task_id])
                for r in attachments:
                    file = [FileUpload(filename=r[0])]
                    default_fields['task_attachments'] = file

                # submission method specific
                if res[3] == 'text submission':
                    default_fields['word-limit'] = res[4]
                else:
                    default_fields['submission-type'] = 'file'
                    default_fields['maximum-file-size'] = int(res[5])
                    default_fields['accepted-file-type'] = res[6]

                # marking method specifics
                if res[7] == 'requires mark':
                    default_fields['marking-method'] = 'criteria'
                    crit = db.select_columns('task_criteria',
                                             ['name, max_mark'], ['task'],
                                             [old_task_id])
                    if crit is not None:
                        default_fields['criteria'] = crit

        db.close()
        if default_fields['maximum-file-size'] == '':
            default_fields['maximum-file-size'] = 5
        if default_fields['accepted-file-type'] == '':
            default_fields['accepted-file-type'] = '.pdf'
        return render_template('create_task.html',
                               heading=heading,
                               title=heading,
                               file_types=file_types,
                               course_id=course_id,
                               max_file_size=config.MAX_FILE_SIZE,
                               max_word_limit=config.MAX_WORD_LIMIT,
                               accepted_file_types=allowed_file_types,
                               old_task_id=old_task_id,
                               default_fields=default_fields)

    try:
        fields = [
            'task-name', 'deadline', 'task-description', 'submission-type',
            'word-limit', 'maximum-file-size', 'accepted-file-type',
            'marking-method', 'num-criteria', 'course-id', 'file-name',
            'old_task_id', 'delete_old_attachment'
        ]
        task_name, deadline, task_description, submission_type, \
            word_limit, max_file_size, accepted_ftype, marking_method, \
            num_criteria, course_id, file_name, old_task_id, \
            delete_old_attachment = \
            get_fields(request.form, fields,
                       optional=['word-limit', 'file-name'],
                       ints=['maximum-file-size', 'num-criteria',
                             'word-limit', 'course-id',
                             'delete_old_attachment'])
    except ValueError as e:
        return e.args[0]

    try:
        old_task_id = int(old_task_id)
    except ValueError as e:
        old_task_id = None

    try:
        deadline = datetime.strptime(deadline, '%d/%m/%Y %H:%M').timestamp()
    except ValueError:
        return error('Invalid date format for deadline!')

    if submission_type == 'file':
        max_size = config.MAX_FILE_SIZE
        if not (1 <= max_file_size <= max_size):
            return error(
                f'Maximum file size must be between 1 and {max_size}!')
    elif submission_type == 'text':
        try:
            word_limit = get_fields(request.form, ['word-limit'],
                                    ints=['word-limit'])[0]
        except ValueError as e:
            return e.args[0]
        max_word_limit = config.MAX_WORD_LIMIT
        if not (1 <= word_limit <= max_word_limit):
            return error(f'Word limit must be between 1 and {max_word_limit}!')
    else:
        return error('Unknown submission type!')

    if marking_method == 'criteria':
        if num_criteria < 1:
            return error('At least one marking criterion is required!')
        else:
            criteria = [f'criteria-{i}' for i in range(1, num_criteria + 1)]
            marks = [f'maximum-mark-{i}' for i in range(1, num_criteria + 1)]
            try:
                criteria = get_fields(request.form, criteria)
                marks = get_fields(request.form, marks, ints=marks)
            except ValueError as e:
                return e.args[0]

        if sum([mark for mark in marks]) != 100:
            return error('Marks must add to 100!')
    elif marking_method != 'accept':
        return error('Unknown marking method!')

    db.connect()
    res = db.select_columns('course_offerings', ['id'], ['id'], [course_id])
    if not len(res):
        db.close()
        return error('Cannot create task for unknown course!')
    res = db.select_columns('tasks', ['id', 'name'],
                            ['name', 'course_offering'],
                            [task_name, course_id])
    if len(res) and res[0][0] != old_task_id:
        db.close()
        return error('A task with that name already exists in this course!')

    # retrieve some foreign keys for insertion
    res = db.select_columns('file_types', ['id'], ['name'], [accepted_ftype])
    if not len(res):
        db.close()
        return error('Invalid or unsupported file type!')
    file_type_id = res[0][0]

    # upload file if present
    sent_file = None
    if len(file_name):
        try:
            sent_file = FileUpload(req=request)
        except KeyError:
            db.close()
            return error('Could not find a file to upload')

        res = db.select_columns('file_types', ['name'])
        file_types = list(map(lambda x: x[0], res))
        if sent_file.get_extention() not in file_types:
            db.close()
            accept_files = ', '.join(file_types)
            return error(f'Accepted file types are: {accept_files}')
        if sent_file.get_size() > config.MAX_FILE_SIZE:
            sent_file.remove_file()
            db.close()
            return error(
                f'File exceeds the maximum size of {config.MAX_FILE_SIZE} MB')
        sent_file.commit()

    if (len(file_name) and old_task_id is not None) or delete_old_attachment:
        old = db.select_columns('task_attachments', ['path'], ['task'],
                                [old_task_id])
        if old:
            db.delete_rows('task_attachments', ['task'], [old_task_id])
            try:
                prev_submission = FileUpload(filename=old[0][0])
                prev_submission.remove_file()
            except LookupError:
                # If the file doesn't exists don't worry as we are deleting
                # the attachment anyway
                pass

    res = db.select_columns('submission_methods', ['id'], ['name'],
                            ['{} submission'.format(submission_type)])
    submission_method_id = res[0][0]
    marking_method = 'approval' if marking_method == 'accept' else 'mark'
    res = db.select_columns('marking_methods', ['id'], ['name'],
                            ['requires {}'.format(marking_method)])
    mark_method_id = res[0][0]

    # commit task
    if old_task_id is not None:
        # update an existing task
        db.update_rows('tasks', [
            task_name, course_id, deadline, task_description, max_file_size,
            submission_method_id, mark_method_id, word_limit
        ], [
            'name', 'course_offering', 'deadline', 'description', 'size_limit',
            'submission_method', 'marking_method', 'word_limit'
        ], ['id'], [old_task_id])
    else:
        # add a new task`
        db.insert_single('tasks', [
            task_name, course_id, deadline, task_description, max_file_size, 0,
            submission_method_id, mark_method_id, word_limit
        ], [
            'name', 'course_offering', 'deadline', 'description', 'size_limit',
            'visible', 'submission_method', 'marking_method', 'word_limit'
        ])

    res = db.select_columns('tasks', ['id'], ['name', 'course_offering'],
                            [task_name, course_id])
    task_id = res[0][0]

    if sent_file:
        db.insert_single('task_attachments',
                         [task_id, sent_file.get_name()], ['task', 'path'])

    # delete old entries in other tables
    if old_task_id is not None:
        db.delete_rows('submission_types', ['task'], [old_task_id])

        res = db.select_columns('task_criteria', ['id'], ['task'],
                                [old_task_id])
        for r in res:
            db.delete_rows('marks', ['criteria'], [r[0]])
        db.delete_rows('task_criteria', ['task'], [old_task_id])

    # commit accepted file type
    db.insert_single('submission_types', [file_type_id, task_id],
                     ['file_type', 'task'])

    # commit marking criteria
    marking_criteria = []
    if marking_method == 'approval':
        marking_criteria.append(
            ('task_criteria', [task_id, 'Approval',
                               100], ['task', 'name', 'max_mark']))
    else:
        for i in range(len(criteria)):
            marking_criteria.append(
                ('task_criteria', [task_id, criteria[i],
                                   marks[i]], ['task', 'name', 'max_mark']))
    db.insert_multiple(marking_criteria)

    db.close()
    return jsonify({'status': 'ok'})
示例#11
0
def submit_file_task():
    task_id = request.form.get('task', -1)
    db.connect()
    res = db.select_columns('tasks', [
        'deadline', 'marking_method', 'visible', 'course_offering',
        'size_limit'
    ], ['id'], [task_id])
    if not res:
        db.close()
        return error("Task not found")

    task = build_task(task_id)
    res = db.select_columns('enrollments', ['user'],
                            ['user', 'course_offering'],
                            [session['id'], task['offering']])
    if not res:
        db.close()
        return error("User not enrolled in task's course")

    if not request.form.get('certify', 'false') == 'true':
        db.close()
        return error("You must certify this is all your own work")

    if datetime.now().timestamp() >= task['deadline']:
        db.close()
        return error("Submissions closed!<br>You can no longer submit")

    if task['mark_method']['name'] == 'requires approval':
        res = db.select_columns('request_statuses', ['id'], ['name'],
                                ['pending'])
    elif task['mark_method']['name'] == 'requires mark':
        res = db.select_columns('request_statuses', ['id'], ['name'],
                                ['pending mark'])
    pending_status_id = res[0][0]

    try:
        sent_file = FileUpload(req=request)
    except KeyError:
        db.close()
        return error("You must supply a file for submission")

    if sent_file.get_extention() not in task['accepted_files']:
        db.close()
        accept_files = ', '.join([f[1:] for f in task['accepted_files']])
        return error(f"File must be formatted as {accept_files}")
    if sent_file.get_size() > task['file_limit']:
        sent_file.remove_file()
        db.close()
        return error(
            f'File exceeds the maximum size of {task["file_limit"]} MB')

    sent_file.commit()
    res = db.select_columns('submissions', ['path'], ['student', 'task'],
                            [session['id'], task['id']])
    if res:
        db.delete_rows('submissions', ['student', 'task'],
                       [session['id'], task['id']])
        # If the file doesn't exists don't worry as we are deleting
        # the submission anyway
        try:
            prev_submission = FileUpload(filename=res[0][0])
            prev_submission.remove_file()
        except LookupError:
            pass

    db.insert_single('submissions', [
        session['id'], task['id'],
        sent_file.get_original_name(),
        str(sent_file.get_name()),
        datetime.now().timestamp(), pending_status_id
    ], ['student', 'task', 'name', 'path', 'date_modified', 'status'])
    db.close()
    return jsonify({'status': 'ok'})
示例#12
0
def student_dashboard():
    db.connect()
    all_materials = queries.get_user_materials(session['id'])

    cur_materials = []
    for material in all_materials:
        # now = datetime.now().timestamp()
        # if now < material[2] or now > material[3]:
        # if we wanted to split current, previous or
        # future we would do the above line
        attachments = []
        attachments_query = db.select_columns(
            'material_attachments', ['path'], ['material'], [material[0]]
        )
        for x in attachments_query:
            attachments.append(FileUpload(filename=x[0]))
        cur_materials.append((material[1], attachments, material[4]))

    assessor = -1
    supervisor = -1
    markers = queries.get_user_ass_sup(session['id'])
    if len(markers) > 0:
        assessor = markers[0][0]
        supervisor = markers[0][1]

    tasks = []
    my_tasks = queries.get_user_tasks(session['id'])
    for task in my_tasks:
        status = get_sub_status(session['id'], task[0])
        if 'approval' in task[3]:
            tasks.append((
                task[2], task[1], status, '-', '-',
                task[0], task[4]
            ))
        else:
            criteria = db.select_columns(
                'task_criteria', ['id', 'max_mark'], ['task'], [task[0]]
            )
            total_max_mark = 0
            supervisor_mark = 0
            assessor_mark = 0
            for c in criteria:
                total_max_mark += c[1]
                if assessor is not None and assessor != -1:
                    mark = db.select_columns(
                        'marks', ['mark'],
                        ['criteria', 'student', 'marker'],
                        [c[0], session['id'], assessor]
                    )
                    if len(mark) != 0:
                        assessor_mark += mark[0][0]
                    else:
                        assessor_mark = -1
                if supervisor is not None and supervisor != -1:
                    mark = db.select_columns(
                        'marks', ['mark'],
                        ['criteria', 'student', 'marker'],
                        [c[0], session['id'], supervisor]
                    )
                    if len(mark) != 0:
                        supervisor_mark += mark[0][0]
                    else:
                        supervisor_mark = -1
            if supervisor_mark <= 0:
                supervisor_mark = '-'
            if assessor_mark <= 0:
                assessor_mark = '-'
            tasks.append((
                task[2], task[1], status, supervisor_mark, assessor_mark,
                task[0], task[4]
            ))

    # get info about selected topic and assigned supervisor/assessor
    try:
        sup = db.select_columns('users', ['name', 'email'],
                                ['id'], [supervisor])[0]
        has_sup = True
    except IndexError:
        sup = 'Not assigned'  # should not happen anyway
        has_sup = False
    try:
        assess = db.select_columns('users', ['name', 'email'],
                                   ['id'], [assessor])[0]
        has_assess = True
    except IndexError:
        assess = 'Not assigned'
        has_assess = False
    try:
        topic = queries.get_student_topic(session['id'])[0][0]
        has_topic = True
    except IndexError:
        topic = 'You have not selected a topic yet.'
        has_topic = False
    topic_info = {
        'has_topic': has_topic,
        'topic': topic,
        'supervisor': sup,
        'assessor': assess,
        'has_supervisor': has_sup,
        'has_assessor': has_assess
    }

    tasks.sort(key=lambda x: (x[0], x[6]))
    db.close()
    return render_template('home_student.html',
                           heading='My Dashboard',
                           title='My Dashboard',
                           materials=cur_materials,
                           tasks=tasks,
                           topic_info=topic_info)