From bff5795ed10c923f0e26781ed53ff04fd2284923 Mon Sep 17 00:00:00 2001 From: Gertjan van den Burg Date: Mon, 18 Mar 2019 18:30:21 +0000 Subject: Start work on admin panel --- annotate_change_v2.py | 3 ++- app/__init__.py | 8 +++++++- app/admin/__init__.py | 7 +++++++ app/admin/decorators.py | 21 +++++++++++++++++++++ app/admin/forms.py | 12 ++++++++++++ app/admin/routes.py | 42 +++++++++++++++++++++++++++++++++++++++++ app/templates/admin/assign.html | 34 +++++++++++++++++++++++++++++++++ app/templates/base.html | 3 +++ 8 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 app/admin/__init__.py create mode 100644 app/admin/decorators.py create mode 100644 app/admin/forms.py create mode 100644 app/admin/routes.py create mode 100644 app/templates/admin/assign.html diff --git a/annotate_change_v2.py b/annotate_change_v2.py index 65959cb..0aa4765 100644 --- a/annotate_change_v2.py +++ b/annotate_change_v2.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- -from app import create_app, db +from app import create_app, db, cli app = create_app() +cli.register(app) diff --git a/app/__init__.py b/app/__init__.py index 9908dd8..7bad100 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -14,7 +14,7 @@ from flask_mail import Mail from flask_migrate import Migrate from flask_sqlalchemy import SQLAlchemy -from .config import Config +from config import Config db = SQLAlchemy() migrate = Migrate() @@ -28,12 +28,14 @@ def create_app(config_class=Config): app = Flask(__name__) app.config.from_object(config_class) + # Initialize all extensions db.init_app(app) migrate.init_app(app, db) login.init_app(app) mail.init_app(app) bootstrap.init_app(app) + # Register all the blueprints from app.errors import bp as errors_bp app.register_blueprint(errors_bp) @@ -46,6 +48,10 @@ def create_app(config_class=Config): app.register_blueprint(main_bp) + from app.admin import bp as admin_bp + + app.register_blueprint(admin_bp) + if not app.debug: if app.config["MAIL_SERVER"]: auth = None diff --git a/app/admin/__init__.py b/app/admin/__init__.py new file mode 100644 index 0000000..737dcc6 --- /dev/null +++ b/app/admin/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- + +from flask import Blueprint + +bp = Blueprint("admin", __name__, url_prefix="/admin") + +from app.admin import routes diff --git a/app/admin/decorators.py b/app/admin/decorators.py new file mode 100644 index 0000000..f42b582 --- /dev/null +++ b/app/admin/decorators.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- + +from functools import wraps + +from flask import current_app, request +from flask_login import current_user +from flask_login.config import EXEMPT_METHODS + + +def admin_required(func): + @wraps(func) + def decorated_view(*args, **kwargs): + if request.method in EXEMPT_METHODS: + return func(*args, **kwargs) + elif current_app.config.get("LOGIN_DISABLED"): + return func(*args, **kwargs) + elif not current_user.is_admin: + return current_app.login_manager.unauthorized() + return func(*args, **kwargs) + + return decorated_view diff --git a/app/admin/forms.py b/app/admin/forms.py new file mode 100644 index 0000000..b33b1c6 --- /dev/null +++ b/app/admin/forms.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +from flask_wtf import FlaskForm + +from wtforms import StringField, PasswordField, BooleanField, SubmitField +from wtforms.validators import DataRequired, ValidationError, Email, EqualTo + + +class AdminAssignTaskForm(FlaskForm): + username = StringField("Username", validators=[DataRequired()]) + dataset = StringField("Dataset", validators=[DataRequired()]) + submit = SubmitField("Assign") diff --git a/app/admin/routes.py b/app/admin/routes.py new file mode 100644 index 0000000..1150f72 --- /dev/null +++ b/app/admin/routes.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- + +from flask import render_template, flash, redirect, url_for +from flask_login import login_required + +from app import db +from app.admin import bp +from app.admin.decorators import admin_required +from app.admin.forms import AdminAssignTaskForm +from app.models import User, Dataset, Task + + +@bp.route("/assign", methods=("GET", "POST")) +@login_required +@admin_required +def assign(): + form = AdminAssignTaskForm() + if form.validate_on_submit(): + user = User.query.filter_by(username=form.username.data).first() + if user is None: + flash("User does not exist.") + return redirect(url_for("admin.assign")) + dataset = Dataset.query.filter_by(name=form.dataset.data).first() + if dataset is None: + flash("Dataset does not exist.") + return redirect(url_for("admin.assign")) + + task = Task.query.filter_by( + annotator_id=user.id, dataset_id=dataset.id + ) + if not task is None: + flash("Task assignment already exists.") + return redirect(url_for("admin.assign")) + + task = Task(annotator_id=user.id, dataset_id=dataset.id) + db.session.add(task) + db.session.commit() + flash("Task registered successfully.") + tasks = Task.query.all() + return render_template( + "admin/assign.html", title="Assign Task", form=form, tasks=tasks + ) diff --git a/app/templates/admin/assign.html b/app/templates/admin/assign.html new file mode 100644 index 0000000..44c6bf7 --- /dev/null +++ b/app/templates/admin/assign.html @@ -0,0 +1,34 @@ +{% extends "base.html" %} +{% import 'bootstrap/wtf.html' as wtf %} + +{% block app_content %} +

Assign Task

+
+
+ {{ wtf.quick_form(form) }} +
+
+
+ + + + + + + + + + {% for task in tasks %} + + + + + + + + + {% endfor %} + +
User IDUsernameDataset IDDataset NameStatusCompleted On
{{ task.user_id }}{{ task.username }}{{ task.dataset_id }}{{ task.dataset_name }}{{ task.done }}{{ task.completed_on }}
+
+{% endblock %} diff --git a/app/templates/base.html b/app/templates/base.html index 8e51695..7713eef 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -24,6 +24,9 @@ {% if current_user.is_anonymous %}
  • Login
  • {% else %} + {% if current_user.is_admin %} +
  • Admin Panel
  • + {% endif %}
  • Logout
  • {% endif %} -- cgit v1.2.3