Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions fireworks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
__version__ = "1.9.8"
FW_INSTALL_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

import warnings
warnings.filterwarnings("ignore", message="numpy.dtype size changed")
warnings.filterwarnings("ignore", message="numpy.ndarray size changed")

# These imports allow a much simpler import of core Fireworks functionality.
# E.g., you can now do "from fireworks import Firework", instead of from
# "fireworks.core.firework import Firework".
Expand Down
55 changes: 35 additions & 20 deletions fireworks/flask_site/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,20 @@
from fireworks.utilities.fw_serializers import DATETIME_HANDLER
from fireworks.utilities.fw_utilities import get_fw_logger

from flask import Blueprint
tmpl_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
stat_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static')
main_bp = Blueprint('fw_webgui_main', __name__, template_folder=tmpl_dir, static_folder=stat_dir)


app = Flask(__name__)


# Allow application to run under a service prefix url
if os.environ.get("FW_APPLICATION_ROOT"):
app.config["APPLICATION_ROOT"] = os.environ.get("FW_APPLICATION_ROOT")


app.use_reloader = True
app.secret_key = os.environ.get("FWAPP_SECRET_KEY", os.urandom(24))

Expand Down Expand Up @@ -87,23 +100,23 @@ def _addq_WF(q):
return {"$and": [q, app.BASE_Q_WF, session.get("wf_filt", {}), filt_from_fw]}


@app.template_filter("datetime")
@main_bp.app_template_filter("datetime")
def datetime(value):
import datetime as dt

date = dt.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")
return date.strftime("%m/%d/%Y")


@app.template_filter("pluralize")
@main_bp.template_filter("pluralize")
def pluralize(number, singular="", plural="s"):
if number == 1:
return singular
else:
return plural


@app.route("/")
@main_bp.route("/")
@requires_auth
def home():
fw_querystr = request.args.get("fw_query")
Expand Down Expand Up @@ -153,7 +166,7 @@ def home():
return render_template("home.html", **locals())


@app.route("/fw/<int:fw_id>/details")
@main_bp.route("/fw/<int:fw_id>/details")
@requires_auth
def get_fw_details(fw_id):
# just fill out whatever attributse you want to see per step, then edit the handlebars template in
Expand All @@ -166,7 +179,7 @@ def get_fw_details(fw_id):
return jsonify(fw)


@app.route("/fw/<int:fw_id>")
@main_bp.route("/fw/<int:fw_id>")
@requires_auth
def fw_details(fw_id):
try:
Expand All @@ -178,7 +191,7 @@ def fw_details(fw_id):
return render_template("fw_details.html", **locals())


@app.route("/wf/<int:wf_id>/json")
@main_bp.route("/wf/<int:wf_id>/json")
@requires_auth
def workflow_json(wf_id):
try:
Expand Down Expand Up @@ -208,7 +221,7 @@ def workflow_json(wf_id):
return jsonify(nodes_and_edges)


@app.route("/wf/<int:wf_id>")
@main_bp.route("/wf/<int:wf_id>")
@requires_auth
def wf_details(wf_id):
try:
Expand All @@ -221,9 +234,9 @@ def wf_details(wf_id):
return render_template("wf_details.html", **locals())


@app.route("/fw/", defaults={"state": "total"})
@app.route("/fw/<state>/", defaults={"sorting_key": "_id", "sorting_order": "DESCENDING"})
@app.route("/fw/<state>/<sorting_key>/<sorting_order>/")
@main_bp.route("/fw/", defaults={"state": "total"})
@main_bp.route("/fw/<state>/", defaults={"sorting_key": "_id", "sorting_order": "DESCENDING"})
@main_bp.route("/fw/<state>/<sorting_key>/<sorting_order>/")
@requires_auth
def fw_state(state, sorting_key="_id", sorting_order="DESCENDING"):
if sorting_order == "ASCENDING":
Expand Down Expand Up @@ -253,9 +266,9 @@ def fw_state(state, sorting_key="_id", sorting_order="DESCENDING"):
return render_template("fw_state.html", **locals())


@app.route("/wf/", defaults={"state": "total"})
@app.route("/wf/<state>/", defaults={"sorting_key": "_id", "sorting_order": "DESCENDING"})
@app.route("/wf/<state>/<sorting_key>/<sorting_order>/")
@main_bp.route("/wf/", defaults={"state": "total"})
@main_bp.route("/wf/<state>/", defaults={"sorting_key": "_id", "sorting_order": "DESCENDING"})
@main_bp.route("/wf/<state>/<sorting_key>/<sorting_order>/")
@requires_auth
def wf_state(state, sorting_key="_id", sorting_order="DESCENDING"):
if sorting_order == "ASCENDING":
Expand All @@ -281,8 +294,8 @@ def wf_state(state, sorting_key="_id", sorting_order="DESCENDING"):
return render_template("wf_state.html", **locals())


@app.route("/wf/metadata/<key>/<value>/", defaults={"state": "total"})
@app.route("/wf/metadata/<key>/<value>/<state>/")
@main_bp.route("/wf/metadata/<key>/<value>/", defaults={"state": "total"})
@main_bp.route("/wf/metadata/<key>/<value>/<state>/")
@requires_auth
def wf_metadata_find(key, value, state):
db = app.lp.workflows
Expand Down Expand Up @@ -314,9 +327,9 @@ def wf_metadata_find(key, value, state):
return render_template("wf_metadata.html", **locals())


@app.route("/report/", defaults={"interval": "months", "num_intervals": 6})
@app.route("/report/<interval>/", defaults={"num_intervals": 6})
@app.route("/report/<interval>/<num_intervals>/")
@main_bp.route("/report/", defaults={"interval": "months", "num_intervals": 6})
@main_bp.route("/report/<interval>/", defaults={"num_intervals": 6})
@main_bp.route("/report/<interval>/<num_intervals>/")
@requires_auth
def report(interval, num_intervals):
num_intervals = int(num_intervals)
Expand All @@ -341,7 +354,7 @@ def report(interval, num_intervals):
return render_template("report.html", **locals())


@app.route("/dashboard/")
@main_bp.route("/dashboard/")
@requires_auth
def dashboard():
PLOTTING = False
Expand Down Expand Up @@ -375,7 +388,7 @@ def parse_querystr(querystr, coll):
return d


@app.route("/reports/<coll>/<interval>/<num_intervals>/fig.png")
@main_bp.route("/reports/<coll>/<interval>/<num_intervals>/fig.png")
def simple(coll, interval, num_intervals):
from io import BytesIO

Expand All @@ -391,6 +404,8 @@ def simple(coll, interval, num_intervals):
response.headers["Content-Type"] = "image/png"
return response

app.register_blueprint(main_bp, url_prefix=app.config["APPLICATION_ROOT"])


if __name__ == "__main__":
app.run(debug=True, port=8080)
137 changes: 68 additions & 69 deletions fireworks/flask_site/static/js/wf_cyto.js
Original file line number Diff line number Diff line change
@@ -1,79 +1,78 @@
$(document).ready(function() {
var options = {
name: 'dagre',
name: 'dagre',

// dagre algo options, uses default value on undefined
nodeSep: undefined, // the separation between adjacent nodes in the same rank
edgeSep: undefined, // the separation between adjacent edges in the same rank
rankSep: undefined, // the separation between adjacent nodes in the same rank
rankDir: 'TB', // 'TB' for top to bottom flow, 'LR' for left to right
minLen: function( edge ){ return 1; }, // number of ranks to keep between the source and target of the edge
edgeWeight: function( edge ){ return 1; }, // higher weight edges are generally made shorter and straighter than lower weight edges
// dagre algo options, uses default value on undefined
nodeSep: undefined, // the separation between adjacent nodes in the same rank
edgeSep: undefined, // the separation between adjacent edges in the same rank
rankSep: undefined, // the separation between adjacent nodes in the same rank
rankDir: 'TB', // 'TB' for top to bottom flow, 'LR' for left to right
minLen: function( edge ){ return 1; }, // number of ranks to keep between the source and target of the edge
edgeWeight: function( edge ){ return 1; }, // higher weight edges are generally made shorter and straighter than lower weight edges

// general layout options
fit: true, // whether to fit to viewport
padding: 30, // fit padding
animate: false, // whether to transition the node positions
animationDuration: 500, // duration of animation in ms if enabled
boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
ready: function(){}, // on layoutready
stop: function(){} // on layoutstop
};
$.getJSON("/wf/"+ $("#wf_id").html()+ "/json", function(result){
// general layout options
fit: true, // whether to fit to viewport
padding: 30, // fit padding
animate: false, // whether to transition the node positions
animationDuration: 500, // duration of animation in ms if enabled
boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
ready: function(){}, // on layoutready
stop: function(){} // on layoutstop
};
var wf_json = window.location.pathname + "/json";
$.getJSON(wf_json, function(result){
var cy = cytoscape({
container: document.getElementById('cy'),
style: cytoscape.stylesheet()
.selector('node')
.css({
'content': 'data(name)',
'text-valign': 'center',
'width':'data(width)',
'shape':'rectangle',
'color': 'white',
'background-color' : 'data(state)',
'text-outline-width': 1,
'font-family': "Open Sans, sans-serif",
'font-size': 14,
'text-outline-color': '#888'
})
.selector('edge')
.css({
'target-arrow-shape': 'triangle'
})
.selector(':selected')
.css({
'background-color': 'black',
'line-color': 'black',
'target-arrow-color': 'black',
'source-arrow-color': 'black'
})
.selector('.faded')
.css({
'opacity': 0.25,
'text-opacity': 0
}),
elements: {
nodes:result.nodes,
edges:result.edges,
},
ready: function() {
window.cy = this;
cy.layout(options);
cy.panzoom();
}
});
$('#json').JSONView('collapse')
var source = $("#job-details").html();
var template = Handlebars.compile(source);
cy.on("click", 'node', function(evt) {
$.getJSON("/fw/" + this.data('id') + "/details", function(result) {
container: document.getElementById('cy'),
style: cytoscape.stylesheet()
.selector('node')
.css({
'content': 'data(name)',
'text-valign': 'center',
'width':'data(width)',
'shape':'rectangle',
'color': 'white',
'background-color' : 'data(state)',
'text-outline-width': 1,
'font-family': "Open Sans, sans-serif",
'font-size': 14,
'text-outline-color': '#888'
})
.selector('edge')
.css({
'target-arrow-shape': 'triangle'
})
.selector(':selected')
.css({
'background-color': 'black',
'line-color': 'black',
'target-arrow-color': 'black',
'source-arrow-color': 'black'
})
.selector('.faded')
.css({
'opacity': 0.25,
'text-opacity': 0
}),
elements: {
nodes:result.nodes,
edges:result.edges,
},
ready: function() {
window.cy = this;
cy.layout(options);
cy.panzoom();
}
});
$('#json').JSONView('collapse')
var source = $("#job-details").html();
var template = Handlebars.compile(source);
cy.on("click", 'node', function(evt) {
var path = window.location.pathname.split('/');
var root = path.splice(0, path.length-2).join('/');
$.getJSON(root + "/fw/" + this.data('id') + "/details", function(result) {
$("#job-details-target").html(template(result));
});
});

});




});
});
10 changes: 5 additions & 5 deletions fireworks/flask_site/templates/base.html
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/bootstrap.css') }}">
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/flat-ui.css') }}">
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/styles.css') }}">
<link rel="stylesheet" type="text/css" href="{{ url_for('fw_webgui_main.static', filename='css/bootstrap.css') }}">
<link rel="stylesheet" type="text/css" href="{{ url_for('fw_webgui_main.static', filename='css/flat-ui.css') }}">
<link rel="stylesheet" type="text/css" href="{{ url_for('fw_webgui_main.static', filename='css/styles.css') }}">
{% block morehead %}{% endblock %}
<title>{% block title %}{% endblock %}</title>
</head>


<body>
<div class="container">
<a href="/" >
<img class="brand" src="{{ url_for('static', filename='images/fw-logo.png') }}"></img>
<a href="{{ url_for('fw_webgui_main.home') }}" >
<img class="brand" src="{{ url_for('fw_webgui_main.static', filename='images/fw-logo.png') }}"></img>
</a>
</div>
<hr class="myhrline">
Expand Down
16 changes: 8 additions & 8 deletions fireworks/flask_site/templates/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ <h2>Fireworks</h2>
{% if PLOTTING %}
<div class="report_images">
<div class="imgContainer">
<a href="/report/hours/24"><img src="/reports/fireworks/hours/24/fig.png" width="450px"></a>
<a href="{{ url_for('fw_webgui_main.home') }}report/hours/24"><img src="{{ url_for('fw_webgui_main.home') }}reports/fireworks/hours/24/fig.png" width="450px"></a>
</div>
<div class="imgContainer">
<a href="/report/days/30"><img src="/reports/fireworks/days/30/fig.png" width="450px"></a>
<a href="{{ url_for('fw_webgui_main.home') }}report/days/30"><img src="{{ url_for('fw_webgui_main.home') }}reports/fireworks/days/30/fig.png" width="450px"></a>
</div>
</div>
<div class="report_images">
<div class="imgContainer">
<a href="/report/months/12"><img src="/reports/fireworks/months/12/fig.png" width="450px"></a>
<a href="{{ url_for('fw_webgui_main.home') }}report/months/12"><img src="{{ url_for('fw_webgui_main.home') }}reports/fireworks/months/12/fig.png" width="450px"></a>
</div>
<div class="imgContainer">
<a href="/report/years/10"><img src="/reports/fireworks/years/10/fig.png" width="450px"></a>
<a href="{{ url_for('fw_webgui_main.home') }}report/years/10"><img src="{{ url_for('fw_webgui_main.home') }}reports/fireworks/years/10/fig.png" width="450px"></a>
</div>
</div>
{% else %}
Expand All @@ -30,18 +30,18 @@ <h2>Workflows</h2>
{% if PLOTTING %}
<div class="report_images">
<div class="imgContainer">
<a href="/report/hours/24"><img src="/reports/workflows/hours/24/fig.png" width="450px"></a>
<a href="{{ url_for('fw_webgui_main.home') }}report/hours/24"><img src="{{ url_for('fw_webgui_main.home') }}reports/workflows/hours/24/fig.png" width="450px"></a>
</div>
<div class="imgContainer">
<a href="/report/days/30"><img src="/reports/workflows/days/30/fig.png" width="450px"></a>
<a href="{{ url_for('fw_webgui_main.home') }}report/days/30"><img src="{{ url_for('fw_webgui_main.home') }}reports/workflows/days/30/fig.png" width="450px"></a>
</div>
</div>
<div class="report_images">
<div class="imgContainer">
<a href="/report/months/12"><img src="/reports/workflows/months/12/fig.png" width="450px"></a>
<a href="{{ url_for('fw_webgui_main.home') }}report/months/12"><img src="{{ url_for('fw_webgui_main.home') }}reports/workflows/months/12/fig.png" width="450px"></a>
</div>
<div class="imgContainer">
<a href="/report/years/10"><img src="/reports/workflows/years/10/fig.png" width="450px"></a>
<a href="{{ url_for('fw_webgui_main.home') }}report/years/10"><img src="{{ url_for('fw_webgui_main.home') }}reports/workflows/years/10/fig.png" width="450px"></a>
</div>
</div>
{% else %}
Expand Down
Loading