Changed the layer at which json files are parsed
Updated dataset database model Updated create and edit function to use data list instead of file
This commit is contained in:
		@@ -5,12 +5,13 @@ from ..tools.forms import get_dataset_choices, get_time_options, send_errors_to_
 | 
			
		||||
from ..tools.data import check_is_json, validate_json
 | 
			
		||||
from ..tools.test import  answer_options, get_correct_answers
 | 
			
		||||
 | 
			
		||||
from flask import Blueprint, jsonify, render_template, redirect, request, session
 | 
			
		||||
from flask import abort, Blueprint, jsonify, render_template, redirect, request, send_file, session
 | 
			
		||||
from flask.helpers import flash, url_for
 | 
			
		||||
from flask_login import current_user, login_required
 | 
			
		||||
 | 
			
		||||
from datetime import date, datetime
 | 
			
		||||
from json import loads
 | 
			
		||||
from os import path
 | 
			
		||||
import secrets
 | 
			
		||||
 | 
			
		||||
admin = Blueprint(
 | 
			
		||||
@@ -207,10 +208,13 @@ def _questions():
 | 
			
		||||
        if form.validate_on_submit():
 | 
			
		||||
            upload = form.data_file.data
 | 
			
		||||
            if not check_is_json(upload): return jsonify({'error': 'Invalid file. Please upload a JSON file.'}), 400
 | 
			
		||||
            if not validate_json(upload): return jsonify({'error': 'The data in the file is invalid.'}), 400
 | 
			
		||||
            upload.stream.seek(0)
 | 
			
		||||
            data = loads(upload.read())
 | 
			
		||||
            if not validate_json(data=data): return jsonify({'error': 'The data in the file is invalid.'}), 400
 | 
			
		||||
            new_dataset = Dataset()
 | 
			
		||||
            new_dataset.set_name(request.form.get('name'))
 | 
			
		||||
            success, message = new_dataset.create(
 | 
			
		||||
                upload = upload,
 | 
			
		||||
                data = data,
 | 
			
		||||
                default = request.form.get('default')
 | 
			
		||||
            )
 | 
			
		||||
            if success: return jsonify({'success': message}), 200
 | 
			
		||||
@@ -220,18 +224,25 @@ def _questions():
 | 
			
		||||
    data = Dataset.query.all()
 | 
			
		||||
    return render_template('/admin/settings/questions.html', form=form, data=data)
 | 
			
		||||
 | 
			
		||||
@admin.route('/settings/questions/edit/', methods=['POST'])
 | 
			
		||||
@admin.route('/settings/questions/delete/', methods=['POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
def _edit_questions():
 | 
			
		||||
    id = request.get_json()['id']
 | 
			
		||||
    action = request.get_json()['action']
 | 
			
		||||
    if action not in ['defailt', 'delete']: return jsonify({'error': 'Invalid action.'}), 400
 | 
			
		||||
    if not action == 'delete': return jsonify({'error': 'Invalid action.'}), 400
 | 
			
		||||
    dataset = Dataset.query.filter_by(id=id).first()
 | 
			
		||||
    if action == 'delete': success, message = dataset.delete()
 | 
			
		||||
    elif action == 'default': success, message = dataset.make_default()
 | 
			
		||||
    if success: return jsonify({'success': message}), 200
 | 
			
		||||
    return jsonify({'error': message}), 400
 | 
			
		||||
 | 
			
		||||
@admin.route('/settings/questions/download/<string:id>/')
 | 
			
		||||
@login_required
 | 
			
		||||
def _download(id:str):
 | 
			
		||||
    dataset = Dataset.query.filter_by(id=id).first()
 | 
			
		||||
    if not dataset: return abort(404)
 | 
			
		||||
    data_path = path.abspath(dataset.get_file())
 | 
			
		||||
    return send_file(data_path, as_attachment=True, attachment_filename=f'{dataset.get_name()}.json')
 | 
			
		||||
 | 
			
		||||
@admin.route('/tests/<string:filter>/', methods=['GET'])
 | 
			
		||||
@admin.route('/tests/', methods=['GET'])
 | 
			
		||||
@login_required
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
from ..extensions import db
 | 
			
		||||
from ..tools.encryption import decrypt, encrypt
 | 
			
		||||
from ..tools.logs import write
 | 
			
		||||
 | 
			
		||||
from flask import flash
 | 
			
		||||
@@ -7,7 +8,7 @@ from flask_login import current_user
 | 
			
		||||
from werkzeug.utils import secure_filename
 | 
			
		||||
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
from json import dump, loads
 | 
			
		||||
from json import dump
 | 
			
		||||
from os import path, remove
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
from uuid import uuid4
 | 
			
		||||
@@ -15,13 +16,16 @@ from uuid import uuid4
 | 
			
		||||
class Dataset(db.Model):
 | 
			
		||||
 | 
			
		||||
    id = db.Column(db.String(36), primary_key=True)
 | 
			
		||||
    name = db.Column(db.String(128), nullable=False)
 | 
			
		||||
    tests = db.relationship('Test', backref='dataset')
 | 
			
		||||
    creator_id = db.Column(db.String(36), db.ForeignKey('user.id'))
 | 
			
		||||
    date = db.Column(db.DateTime, nullable=False)
 | 
			
		||||
    default = db.Column(db.Boolean, default=False, nullable=True)
 | 
			
		||||
    accessed = db.Column(db.DateTime, nullable=True)
 | 
			
		||||
    locked = db.Column(db.Boolean, default=False, nullable=True)
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return f'<Dataset {self.id}> was added.'
 | 
			
		||||
        return f'<Dataset {self.id}>.'
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def generate_id(self): raise AttributeError('generate_id is not a readable attribute.')
 | 
			
		||||
@@ -29,6 +33,14 @@ class Dataset(db.Model):
 | 
			
		||||
    generate_id.setter
 | 
			
		||||
    def generate_id(self): self.id = uuid4().hex
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def set_name(self): raise AttributeError('set_name is not a readable attribute.')
 | 
			
		||||
    
 | 
			
		||||
    set_name.setter
 | 
			
		||||
    def set_name(self, name:str): self.name = encrypt(name)
 | 
			
		||||
    
 | 
			
		||||
    def get_name(self): return decrypt(self.name)
 | 
			
		||||
 | 
			
		||||
    def make_default(self):
 | 
			
		||||
        for dataset in Dataset.query.all():
 | 
			
		||||
            dataset.default = False
 | 
			
		||||
@@ -43,7 +55,7 @@ class Dataset(db.Model):
 | 
			
		||||
            message = 'Cannot delete the default dataset.'
 | 
			
		||||
            flash(message, 'error')
 | 
			
		||||
            return False, message
 | 
			
		||||
        if Dataset.query.all().count() == 1:
 | 
			
		||||
        if Dataset.query.count() == 1:
 | 
			
		||||
            message = 'Cannot delete the only dataset.'
 | 
			
		||||
            flash(message, 'error')
 | 
			
		||||
            return False, message
 | 
			
		||||
@@ -56,23 +68,19 @@ class Dataset(db.Model):
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
        return True, 'Dataset deleted.'
 | 
			
		||||
    
 | 
			
		||||
    def create(self, upload, default:bool=False):
 | 
			
		||||
    def create(self, data:list, default:bool=False):
 | 
			
		||||
        self.generate_id()
 | 
			
		||||
        timestamp = datetime.now()
 | 
			
		||||
        filename = secure_filename('.'.join([self.id,'json']))
 | 
			
		||||
        data = Path(app.config.get('DATA'))
 | 
			
		||||
        file_path = path.join(data, 'questions', filename)
 | 
			
		||||
        upload.stream.seek(0)
 | 
			
		||||
        questions = loads(upload.read())
 | 
			
		||||
        file_path = self.get_file()
 | 
			
		||||
        with open(file_path, 'w') as file:
 | 
			
		||||
            dump(questions, file, indent=2)
 | 
			
		||||
            dump(data, file, indent=2)
 | 
			
		||||
        self.date = timestamp
 | 
			
		||||
        self.creator = current_user
 | 
			
		||||
        if default: self.make_default()
 | 
			
		||||
        write('system.log', f'New dataset {self.id} added by {current_user.get_username()}.')
 | 
			
		||||
        write('system.log', f'New dataset {self.get_name()} added by {current_user.get_username()}.')
 | 
			
		||||
        db.session.add(self)
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
        return True, 'Dataset uploaded.'
 | 
			
		||||
        return True, 'Dataset created.'
 | 
			
		||||
 | 
			
		||||
    def check_file(self):
 | 
			
		||||
        filename = secure_filename('.'.join([self.id,'json']))
 | 
			
		||||
@@ -85,4 +93,16 @@ class Dataset(db.Model):
 | 
			
		||||
        filename = secure_filename('.'.join([self.id,'json']))
 | 
			
		||||
        data = Path(app.config.get('DATA'))
 | 
			
		||||
        file_path = path.join(data, 'questions', filename)
 | 
			
		||||
        return file_path
 | 
			
		||||
        return file_path
 | 
			
		||||
    
 | 
			
		||||
    def update(self, data:list=None, default:bool=False):
 | 
			
		||||
        self.date = datetime.now()
 | 
			
		||||
        if default: self.make_default()
 | 
			
		||||
        file_path = self.get_file()
 | 
			
		||||
        with open(file_path, 'w') as file:
 | 
			
		||||
            dump(data, file, indent=2)
 | 
			
		||||
        write('system.log', f'Dataset {self.id} edited by {current_user.get_username()}.')
 | 
			
		||||
        flash(f'Dataset {self.name} successfully edited.', 'success')
 | 
			
		||||
        db.session.add(self)
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
        return True, 'Dataset successfully edited.'
 | 
			
		||||
		Reference in New Issue
	
	Block a user