about summary refs log tree commit diff
"""Endpoints for publications"""
import json

from gn_libs.mysqldb import database_connection
from flask import (
    flash,
    request,
    redirect,
    Blueprint,
    render_template,
    current_app as app)

from uploader.flask_extensions import url_for
from uploader.authorisation import require_login
from uploader.route_utils import redirect_to_next

from .models import (
    delete_publications,
    update_publications,
    fetch_publication_by_id,
    create_new_publications,
    fetch_publication_phenotypes)

from .datatables import fetch_publications

pubbp = Blueprint("publications", __name__)


@pubbp.route("/", methods=["GET"])
@require_login
def index():
    """Index page for publications."""
    return render_template("publications/index.html")


@pubbp.route("/list", methods=["GET"])
@require_login
def list_publications():
    """Fetch publications that fulfill a specific search, or all of them, if
    there is no search term."""
    # request breakdown:
    # https://datatables.net/manual/server-side
    _page = int(request.args.get("draw"))
    _length = int(request.args.get("length") or '-1')
    _start = int(request.args.get("start") or '0')
    _search = request.args["search[value]"]
    with database_connection(app.config["SQL_URI"]) as conn:
        _publications, _current_rows, _totalfiltered, _totalrows = fetch_publications(
            conn,
            _search,
            offset=_start,
            limit=_length)

        return json.dumps({
            "draw": _page,
            "recordsTotal": _totalrows,
            "recordsFiltered": _totalfiltered,
            "publications": _publications,
            "status": "success"
        })


@pubbp.route("/view/<int:publication_id>", methods=["GET"])
@require_login
def view_publication(publication_id: int):
    """View more details on a particular publication."""
    with database_connection(app.config["SQL_URI"]) as conn:
        publication = fetch_publication_by_id(conn, publication_id)

        if not bool(publication):
            flash("Requested publication was not found!", "alert-warning")
            return redirect(url_for('publications.index'))

        return render_template(
            "publications/view-publication.html",
            publication=publication,
            linked_phenotypes=tuple(fetch_publication_phenotypes(
                conn, publication_id)))


@pubbp.route("/create", methods=["GET", "POST"])
@require_login
def create_publication():
    """Create a new publication."""
    _get_args = {
        key: request.args[key]
        for key in ("species_id", "population_id", "dataset_id", "return_to")
        if bool(request.args.get(key))
    }

    if request.method == "GET":
        return render_template(
            "publications/create-publication.html",
            get_args=_get_args)
    form = request.form
    authors = form.get("publication-authors").encode("utf8")
    if authors is None or authors == "":
        flash("The publication's author(s) MUST be provided!", "alert alert-danger")
        return redirect(url_for("publications.create"))

    with database_connection(app.config["SQL_URI"]) as conn:
        publications = create_new_publications(conn, ({
            "pubmed_id": form.get("pubmed-id") or None,
            "abstract": form.get("publication-abstract").encode("utf8") or None,
            "authors": authors,
            "title":  form.get("publication-title").encode("utf8") or None,
            "journal": form.get("publication-journal").encode("utf8") or None,
            "volume": form.get("publication-volume").encode("utf8") or None,
            "pages": form.get("publication-pages").encode("utf8") or None,
            "month": (form.get("publication-month") or "").encode("utf8").capitalize() or None,
            "year": form.get("publication-year").encode("utf8") or None
        },))
        flash("New publication created!", "alert alert-success")
        return redirect(url_for(
            request.args.get("return_to") or "publications.view_publication",
            publication_id=publications[0]["publication_id"],
            **_get_args))

    flash("Publication creation failed!", "alert alert-danger")
    app.logger.debug("Failed to create the new publication.", exc_info=True)
    return redirect(url_for("publications.create_publication"))


@pubbp.route("/edit/<int:publication_id>", methods=["GET", "POST"])
@require_login
def edit_publication(publication_id: int):
    """Edit a publication's details."""
    with database_connection(app.config["SQL_URI"]) as conn:
        if request.method == "GET":
            return render_template(
                "publications/edit-publication.html",
                publication=fetch_publication_by_id(conn, publication_id),
                linked_phenotypes=tuple(fetch_publication_phenotypes(
                    conn, publication_id)),
                publication_id=publication_id)

        form = request.form
        _pub = update_publications(conn, ({
            "publication_id": publication_id,
            "pubmed_id": form.get("pubmed-id") or None,
            "abstract": (form.get("publication-abstract") or "").encode("utf8") or None,
            "authors": (form.get("publication-authors") or "").encode("utf8"),
            "title":  (form.get("publication-title") or "").encode("utf8") or None,
            "journal": (form.get("publication-journal") or "").encode("utf8") or None,
            "volume": (form.get("publication-volume") or "").encode("utf8") or None,
            "pages": (form.get("publication-pages") or "").encode("utf8") or None,
            "month": (form.get("publication-month") or "").encode("utf8").capitalize() or None,
            "year": (form.get("publication-year") or "").encode("utf8") or None
        },))

        if not _pub:
            flash("There was an error updating the publication details.",
                  "alert-danger")
            return redirect(url_for(
                "publications.edit_publication", publication_id=publication_id))

        flash("Successfully updated the publication details.",
              "alert-success")
        return redirect_to_next({
            "uri": "publications.view_publication",
            "publication_id": publication_id
        })


@pubbp.route("/delete/<int:publication_id>", methods=["GET", "POST"])
@require_login
def delete_publication(publication_id: int):
    """Delete a particular publication."""
    with database_connection(app.config["SQL_URI"]) as conn:
        publication = fetch_publication_by_id(conn, publication_id)
        linked_phenotypes=tuple(fetch_publication_phenotypes(
            conn, publication_id))

        if not bool(publication):
            flash("Requested publication was not found!", "alert-warning")
            return redirect(url_for('publications.index'))

        if len(linked_phenotypes) > 0:
            flash("Cannot delete publication with linked phenotypes!",
                  "alert-warning")
            return redirect(url_for(
                "publications.view_publication",
                publication_id=publication_id))

        if request.method == "GET":
            return render_template(
                "publications/delete-publication.html",
                publication=publication,
                linked_phenotypes=linked_phenotypes,
                publication_id=publication_id)

        delete_publications(conn, (publication,))
        flash("Deleted the publication successfully.", "alert-success")
        return redirect(url_for("publications.index"))