Commits

Chris Mutel committed 6d14e56

Major improvements to web UI

Comments (0)

Files changed (8)

-# -*- coding: utf-8 -*
-from brightway2 import config, databases, methods, Database, Method
+# -*- coding: utf-8 -*-
+import base64
+from brightway2 import config, databases, methods, Database, Method, \
+    JsonWrapper
 from bw2analyzer import ContributionAnalysis
 from bw2calc import LCA
-from flask import Flask, url_for, render_template
-import base64
+from flask import Flask, url_for, render_template, request, redirect, abort
 import json
+import os
 
 app = Flask(__name__)
 
 
-def template_context():
-    return {
-        'blueprint_screen': url_for('static', filename="blueprint/screen.css"),
-        'blueprint_print': url_for('static', filename="blueprint/print.css"),
-        'blueprint_ie': url_for('static', filename="blueprint/ie.css"),
-    }
+@app.errorhandler(404)
+def page_not_found(e):
+    # Log error?
+    return render_template('404.html'), 404
+
+
+@app.errorhandler(500)
+def internal_error(e):
+    # Log error?
+    return render_template('500.html'), 500
 
 
 @app.route('/')
 def index():
-    context = template_context()
-    print context
-    return "Success"
+    context = {
+        'databases': databases,
+        'methods': methods,
+        'config': config
+        }
+    if config.is_temp_dir:
+        context["redirect"] = url_for(start_bw)
     return render_template("index.html", **context)
 
 
+@app.route('/error')
+def error_t():
+    abort(404)
+
+
 @app.route('/calculate/lca')
 @app.route('/calculate/lca/<process>/<method>')
 def lca(process=None, method=None):
-    context = template_context()
+    context = {}
     if process:
         method = eval(base64.urlsafe_b64decode(str(method)), None, None)
         process = eval(base64.urlsafe_b64decode(str(process)), None, None)
         return render_template("lca.html", **context)
     else:
         return "No parameters"
+
+import uuid
+
+
+def get_job_id():
+    return uuid.uuid4().hex
+
+
+@app.route('/start', methods=["GET", "POST"])
+def start_bw():
+    """Start Brightway"""
+    job_id = get_job_id()
+    if request.method == "GET":
+        pass
+    elif not request.form["confirm"] == "false":
+        return redirect(url_for(index) + "?temp_dir_ok=True")
+    # Starting Brightway
+    # If POST[action] = "get_biosphere":
+    set_job_status(job_id, {"action": "biosphere-import", "finished": False})
+    # Download file to disk
+    DatabaseImporter().importer(biosphere)
+    set_job_status(job_id, {"action": "biosphere-import", "finished": True})
+
+    # Step two
+    # Import IA methods
+    # Can also be from dropbox
+
+    # Step three
+    # Import Ecoinvent or other LCI database
+
+    # Step four
+    # There is no step four!
+    # Actually, there is: go to the normal homepage
+
+jobs_dir = config.request_dir("jobs")
+
+
+def set_job_status(job, status):
+    filepath = os.path.join(jobs_dir, "%s.json" % job)
+    JsonWrapper.dump(status, filepath)
+
+# Normal homepage:
+# Think of what should be here
+# At a minimum, a table of databases
+# and IA methods
+# A quick entry to LCA (define function units)
+
+# use werkzeug.utils.secure_filename to check uploaded file names
+# http://werkzeug.pocoo.org/docs/utils/
+
+# to send static files not from 'static': send_from_directory
+# http://flask.pocoo.org/docs/api/#flask.send_from_directory
+# http://stackoverflow.com/questions/9513072/more-than-one-static-path-in-local-flask-instance

bw2ui/web/static/img/llama.jpg

Added
New image

bw2ui/web/static/img/monster.jpg

Added
New image

bw2ui/web/templates/404.html

+{% extends "base.html" %}
+
+{% block extrahead %}<style type="text/css">
+body {
+	background-color: #736160;
+	}
+.errortext {
+		margin-top:13em
+}
+</style>{% endblock %}
+
+{% block body %}
+<div class="span-9"><img src="{{ url_for('static', filename="img/llama.jpg") }}"></div>
+<div class="push-1 span-12">
+	<div class="errortext">
+		<h1 style="color: white">404 - Page not found</h1>
+		<h2 style="color: white">We all get lost sometimes...</h2>
+	</div>
+</div>
+{% endblock %}

bw2ui/web/templates/500.html

+{% extends "base.html" %}
+
+{% block extrahead %}<style type="text/css">
+body {
+	background-color: #dcd8d5;
+	color: black !important
+	}
+.errortext {
+		margin-top:13em
+}
+</style>{% endblock %}
+
+{% block body %}
+<div class="span-9"><img src="{{ url_for('static', filename="img/monster.jpg") }}"></div>
+<div class="push-1 span-8">
+	<div class="errortext">
+		<h1>500 - Server Error</h1>
+		<h2>Something went wrong!</h2>
+	</div>
+</div>
+{% endblock %}

bw2ui/web/templates/base.html

 	<title>{% if title %}{{ title }}{% else %}Brightway2 Web UI{% endif %}</title>
 	<meta name="description" content="The web user interface for the Brightway2 LCA engine">
 	<meta name="viewport" content="width=device-width">
-	<link rel="stylesheet" href="{{ blueprint_screen }}" type="text/css" media="screen, projection">
-	<link rel="stylesheet" href="{{ blueprint_print }}" type="text/css" media="print">
-	<!--[if lt IE 8]><link rel="stylesheet" href="{{ blueprint_ie }}" type="text/css" media="screen, projection"><![endif]-->
+	<link rel="stylesheet" href="{{ url_for('static', filename="blueprint/screen.css") }}" type="text/css" media="screen, projection">
+	<link rel="stylesheet" href="{{ url_for('static', filename="blueprint/print.css") }}" type="text/css" media="print">
+	<!--[if lt IE 8]><link rel="stylesheet" href="{{ url_for('static', filename="blueprint/ie.css") }}" type="text/css" media="screen, projection"><![endif]-->
 	<script src="http://yui.yahooapis.com/3.7.3/build/yui/yui-min.js"></script>
 	<script src="http://d3js.org/d3.v2.min.js"></script>
 	{% block extrahead %}{% endblock %}
 </head>
-<body>
+<body class="yui3-skin-sam">
 	<div class="container">{% block body %}{% endblock %}</div>
 </body>
 </html>

bw2ui/web/templates/index.html

-{% extends 'base.html' %}
+{% extends "base.html" %}
+
+{% block body %}
+<h1>Brightway2 web</h1>
+<hr>
+<h3>Data directory is <i>{{ config.dir }}</i></h3>
+<div class="span-10">
+    <h2>Databases</h2>
+    <div id="db-table"></div>
+</div>
+<div class="span-14 last">
+    <h2>Impact assessment methods</h2>
+    <div id="ia-table"></div>
+</div>
+
+<script type="text/javascript">
+YUI().use('datatable-sort', 'datatable-scroll', function (Y) {
+    var inv_data = [
+        {% for db in databases.list %}{ name: "{{db}}", version: {{databases[db]["version"]}}, num: {{databases[db]["number"]}} }{% if loop.last %}{% else %},{% endif %}
+        {% endfor %}
+        ];
+
+    var db_table = new Y.DataTable({
+        columns: [
+            {key: "name", sortable: true}, 
+            {key: "version", sortable: true}, 
+            {key: "num", label: "# datasets", sortable: true}
+            ],
+        data: inv_data,
+        scrollable: true,
+        height: "200px"
+    });
+
+    db_table.render("#db-table");
+});
+
+YUI().use('datatable-sort', 'datatable-scroll', function (Y) {
+    var ia_data = [
+        {% for name in methods.list %}{ name: "{{ ' : '.join(name) }}", unit: "{{methods[name]["unit"]}}", num: {{methods[name]["num_cfs"]}} }{% if loop.last %}{% else %},{% endif %}
+        {% endfor %}
+        ];
+
+    var ia_table = new Y.DataTable({
+        columns: [
+            {key: "name", sortable: true}, 
+            {key: "unit", sortable: true}, 
+            {key: "num", label: "# CFs", sortable: true}
+            ],
+        data: ia_data,
+        scrollable: true,
+        height: "200px"
+    });
+
+    ia_table.render("#ia-table");
+});
+</script>
+
+{% endblock %}

bw2ui/web/templates/lca.html

+{% extends "base.html" %}
+
+{% block extrahead %}
+<style type="text/css">
+.cell {
+  border: solid 1px white;
+  font: 10px sans-serif;
+  line-height: 12px;
+  overflow: hidden;
+  position: absolute;
+  text-indent: 2px;
+}
+</style>
+{% endblock %}
+
+{% block body %}
+<h1>Brightway2 life cycle assessment report</h1>
+<hr>
+<div class="span-15 colborder">
+	<h2 style="margin-bottom: 0">Functional unit:</h2>
+	<ul style="margin-bottom: 0">
+		{% for name, amount, unit in fu %}
+		<li class="large" style="margin-bottom: 0; line-height: 1.2em">{{ name }}: {{ amount }} {{ unit }}</li>
+		{% endfor %}
+	</ul>
+	<h2 style="margin-bottom: 0">Impact assessment method:</h2>
+	<p class="large" style="margin-bottom: 0; line-height: 1.2em">{{ ia_method }}</p>
+</div>
+<div class="span-8 last">
+	<h2>Total score:</h2>
+	<p class="large"><span style="font-size: 2.5em; color:#000">{{ ia_score }}</span> {{ ia_unit }}</p>
+</div>
+<hr>
+<div id="chart"></div>
+<script type="text/javascript">
+	var width = 960,
+	    height = 400,
+	    color = d3.scale.category20();
+
+	var treemap = d3.layout.treemap()
+	    .size([width, height])
+	    .value(function(d) { return d.size; });
+
+	var div = d3.select("#chart").append("div")
+	    .style("position", "relative")
+	    .style("width", width + "px")
+	    .style("height", height + "px");
+
+	var treemap_data = {{ treemap_data|safe }};
+
+	div.data([treemap_data]).selectAll("div")
+	  .data(treemap.nodes)
+	.enter().append("div")
+	  .attr("class", "cell")
+	  .attr("title", function(d) { return d.children ? null : d.name; })
+	  .style("background", function(d) { return d.children ? color(d.name) : null; })
+	  .call(cell)
+	  .text(function(d) { return d.children ? null : d.name; });
+
+	function cell() {
+	  this
+	      .style("left", function(d) { return d.x + "px"; })
+	      .style("top", function(d) { return d.y + "px"; })
+	      .style("width", function(d) { return Math.max(0, d.dx - 1) + "px"; })
+	      .style("height", function(d) { return Math.max(0, d.dy - 1) + "px"; });
+	}
+</script>
+{% endblock %}