# Copyright (c) 2022 The Regents of the University of Michigan
# All rights reserved.
# This software is licensed under the BSD 3-Clause License.
import flask_login
from flask import abort, render_template, request
from jinja2.exceptions import TemplateNotFound
from signac_dashboard.module import Module
[docs]class Notes(Module):
"""Displays a text box that is synced to the job document.
The contents of the text box are saved to :code:`job.document['notes']`.
The Notes module can be used to annotate a large data space with tags or
human-readable descriptions for post-processing, parsing, or searching.
:param context: Supports :code:`'JobContext'`.
:type context: str
:param key: Document key to display and update (default: :code:`'notes'`).
:type key: str
"""
_supported_contexts = {"JobContext"}
def __init__(
self,
name="Notes",
context="JobContext",
template="cards/notes.html",
key="notes",
**kwargs,
):
super().__init__(
name=name,
context=context,
template=template,
**kwargs,
)
self.key = key
def get_cards(self, job):
note_text = job.document.get(self.key, "")
return [
{
"name": self.name,
"content": render_template(
self.template, note_text=note_text, jobid=job._id
),
}
]
def register(self, dashboard):
# Register routes
@dashboard.app.route("/module/notes/update", methods=["POST"])
@flask_login.login_required
def notes_update():
note_text = request.form.get("note_text")
jobid = request.form.get("jobid")
job = dashboard.project.open_job(id=jobid)
job.document[self.key] = note_text
return "Saved."
@dashboard.app.route("/module/notes/<path:filename>")
@flask_login.login_required
def notes_asset(filename):
path = f"notes/{filename}"
try:
return render_template(path)
except TemplateNotFound:
abort(404, "The file requested does not exist.")
# Register assets
assets = ["js/notes.js"]
for asset_file in assets:
dashboard.register_module_asset(
{
"file": f"templates/notes/{asset_file}",
"url": f"/module/notes/{asset_file}",
}
)