changeset 16:f89ad628f831

adding the renamed files
author sean
date Wed, 05 Aug 2015 13:33:15 +0200
parents 82d66f4488cd
children 09e3c38a7802
files modules/web_view/__init__.py modules/web_view/collect_issues.py modules/web_view/display_issues.py modules/web_view/display_issues_techintern.py modules/web_view/graph.html modules/web_view/roundup_content_data/__init__.py modules/web_view/roundup_content_data/tech_intern.db modules/web_view/roundup_content_data/test_reference.db modules/web_view/webview_template.py views/bottledash_view.tpl
diffstat 10 files changed, 1074 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/web_view/__init__.py	Wed Aug 05 13:33:15 2015 +0200
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+""" supplys the data needed to comunicate with the roundup-server,
+and the sqlite database. Represents the types of errors used in roundup.
+
+author: Sascha L. Teichmann <sascha.teichmann@intevation.de>
+author: Bernhard Reiter <bernhard@intevation.de>
+author: Sean Engelhardt <sean.engelhardt@intevation.de>
+
+(c) 2010,2015 by Intevation GmbH
+
+This is Free Software unter the terms of the
+GNU GENERAL PUBLIC LICENSE Version 3 or later.
+See http://www.gnu.org/licenses/gpl-3.0.txt for details
+"""
+import importlib
+
+def make_chart(chart_data_file, target_div_name):
+    mod = importlib.import_module("web_view." + chart_data_file)
+
+    return mod.get_chart(target_div_name)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/web_view/collect_issues.py	Wed Aug 05 13:33:15 2015 +0200
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+
+""" Fetch issues from a roundup-tracker and save them in a databse.
+
+author: Sascha L. Teichmann <sascha.teichmann@intevation.de>
+author: Bernhard Reiter <bernhard@intevation.de>
+author: Sean Engelhardt <sean.engelhardt@intevation.de>
+
+(c) 2010,2015 by Intevation GmbH
+
+This is Free Software unter the terms of the
+GNU GENERAL PUBLIC LICENSE Version 3 or later.
+See http://www.gnu.org/licenses/gpl-3.0.txt for details
+
+
+##USAGE EXAMPLE: ##
+
+BASE_URL_DEMO = "http://localhost:8917/demo/"
+SEARCH_URL_DEMO = "issue?@action=export_csv&@columns=title,priority&@filter=status&@pagesize=50&@startwith=0&status=-1,1,2,3,4,5,6,7"
+
+LOGIN_PARAMETERS_DEMO = (
+    ("__login_name", "demo"),
+    ("__login_password", "demo"),
+    ("@action", "Login"),
+    )
+
+save_stats_in_db(LOGIN_PARAMETERS_DEMO, BASE_URL_DEMO, rcd.DATABASE_DEMO, rcd.COLUMNS, rcd.CREATE_DB, rcd.INSERT_NEW, SEARCH_URL_DEMO)
+"""
+
+import http.cookiejar
+import urllib.parse
+import urllib.request
+import csv
+import io
+import sqlite3 as db
+import os
+import web_view.roundup_content_data as rcd
+
+
+CHECK_ROUNDUP_ORDER = "priority?@action=export_csv&@columns=id,order"
+CHECK_ROUNDUP_SEARCH_VALUES = "status?@action=export_csv&@columns=id&@filter=open&open=1"
+SEARCH_ROUNDUP = "issue?@action=export_csv&@columns=priority&@filter=status&@pagesize=500&@startwith=0&status=-1,{search_values}"
+
+
+def connect_to_server(params, baseurl):
+    enc_data = urllib.parse.urlencode(params).encode()
+    cj = http.cookiejar.CookieJar()
+    opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
+    req = urllib.request.Request(url=baseurl, data=enc_data)
+    opener.open(req)
+    return opener
+
+
+def get_csv_from_server(opener, roundup_url, sub_url):
+    csv_req = urllib.request.Request(url=roundup_url+sub_url)
+    f = opener.open(csv_req)
+    csv_reader = csv.DictReader(io.TextIOWrapper(f))
+    return csv_reader
+
+
+def set_search_paramters_on_URL(url, search_param_csv):
+
+    id_list = []
+
+    for row in search_param_csv:
+        id_list.append(row["id"])
+
+    new_url = url.format(search_values = ",".join(id_list))
+
+    return new_url
+
+
+def check_create_database(database_file, sql_create_db):
+    if not os.path.isfile(database_file):
+        con = None
+        cur = None
+        try:
+            con = db.connect(database_file)
+            cur = con.cursor()
+            try:
+                cur.execute(sql_create_db)
+                con.commit()
+                os.chmod(database_file, 0o644)
+            except:
+                con.rollback()
+                raise
+        finally:
+            if cur:
+                cur.close()
+            if con:
+                con.close()
+
+
+def issues_to_quantities(issue_csv, columns, orders_csv):
+
+    quantities = [0] * len(columns)
+    order_dict = {}
+
+    #convert the csv-dict reader to real dict
+    for row in orders_csv:
+        order_dict[row["id"]] = int(float(row["order"])) # int(float()) because the order-value is indeed "1.0, 2.0" etc
+
+    for issue in issue_csv:
+        priority = issue["priority"]
+
+        if priority.isdigit() == True :
+            quantities[order_dict[priority] -1 ] += 1
+
+    # print("quantities : " + str(quantities))
+
+    return quantities
+
+
+def save_issues_to_db(quantities, database_file, sql_create_db, sql_insert_in_db):
+    check_create_database(database_file, sql_create_db)
+
+    cur = None
+    con = None
+
+    try:
+        con = db.connect(database_file)
+        cur = con.cursor()
+        try:
+            cur.execute(sql_insert_in_db, quantities)
+            con.commit()
+        except:
+            con.rollback()
+            raise
+    finally:
+        if cur:
+            cur.close()
+        if con:
+            con.close()
+
+
+def save_stats_in_db(login_parmeters, baseurl, db_file, columns, sql_create_db, sql_insert_in_db, searchurl=False):
+    try:
+
+        opener = connect_to_server(login_parmeters, baseurl)
+
+        search_operators_csv = get_csv_from_server(opener, baseurl, CHECK_ROUNDUP_SEARCH_VALUES)
+        order_csv = get_csv_from_server(opener, baseurl, CHECK_ROUNDUP_ORDER)
+
+        if searchurl == False:
+            formated_search_url = set_search_paramters_on_URL(SEARCH_ROUNDUP, search_operators_csv)
+        else:
+            formated_search_url = searchurl
+
+        current_issues_csv = get_csv_from_server(opener, baseurl, formated_search_url)
+
+        opener.close()
+
+        quantities = issues_to_quantities(current_issues_csv, columns, order_csv)
+
+        save_issues_to_db(quantities, db_file, sql_create_db, sql_insert_in_db)
+
+    except urllib.error.URLError as e:
+        print("No Valid Connection to server : " + baseurl + "\nerror: " + str(e))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/web_view/display_issues.py	Wed Aug 05 13:33:15 2015 +0200
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+
+""" Display previously saved issues from a database on webpage via CGI.
+
+author: Sascha L. Teichmann <sascha.teichmann@intevation.de>
+author: Bernhard Reiter <bernhard@intevation.de>
+author: Sean Engelhardt <sean.engelhardt@intevation.de>
+
+(c) 2010,2015 by Intevation GmbH
+
+This is Free Software unter the terms of the
+GNU GENERAL PUBLIC LICENSE Version 3 or later.
+See http://www.gnu.org/licenses/gpl-3.0.txt for details
+
+
+##Usage Example: ##
+
+render_db_stats_as_html(rcd.DATABASE_DEMO, rcd.SELECT_ALL)
+"""
+
+import sqlite3 as db
+import cgitb, os, sys, inspect
+import web_view.roundup_content_data as rcd
+
+PATH = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+HTML_DATA = "graph.html"
+PATH_TO_HTML = PATH + "/" + HTML_DATA
+
+def make_js_object_string(array):
+    formated = []
+
+    for item in array:
+        formated.append("{points: " + str(item) + "}")
+
+    return ",".join(formated)
+
+
+def make_js_object_date(array):
+    formated = []
+
+    for item in array:
+        formated.append("{date : new Date('" + str(item) + "')}")
+
+    return ", ".join(formated)
+
+
+def get_webpage():
+
+    with open(PATH_TO_HTML, "r") as html_chart_file:
+        base_html_data = html_chart_file.read()
+
+    base_html_data = (base_html_data
+        .replace("var critical=[];", "var critical=[" + make_js_object_string(rcd.data_dict["critical"]) + "]")
+        .replace("var urgent=[];", "var urgent=[" + make_js_object_string(rcd.data_dict["urgent"]) + "]")
+        .replace("var bug=[];", "var bug=[" + make_js_object_string(rcd.data_dict["bug"]) + "]")
+        .replace("var feature=[];", "var feature=[" + make_js_object_string(rcd.data_dict["feature"]) + "]")
+        .replace("var wish=[];", "var wish=[" + make_js_object_string(rcd.data_dict["wish"]) + "]")
+        .replace("var timestamp=[];", "var timestamp=[" + make_js_object_date(rcd.data_dict["date"]) + "]"))
+
+    return base_html_data
+
+
+# def render_webpage(content):
+#     webpage_string = ""
+#     for line in content.split("\n"):
+#         print(line)
+
+
+def render_db_stats_as_html(db_file, sql_select):
+
+    con = None
+    cur = None
+
+    try:
+        con = db.connect(db_file)
+        cur = con.cursor()
+        cur.execute(sql_select)
+
+        for row in cur.fetchall():
+            rcd.data_dict["date"].append(row[0])
+            rcd.data_dict["critical"].append(row[1])
+            rcd.data_dict["urgent"].append(row[2])
+            rcd.data_dict["bug"].append(row[3])
+            rcd.data_dict["feature"].append(row[4])
+            rcd.data_dict["wish"].append(row[5])
+    finally:
+        if cur:
+            cur.close()
+        if con:
+            con.close()
+
+    # render_webpage(get_webpage())
+    # print(get_webpage())
+    return get_webpage()
+
+# cgitb.enable()
+# print("Content-Type: text/html")
+# print()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/web_view/display_issues_techintern.py	Wed Aug 05 13:33:15 2015 +0200
@@ -0,0 +1,32 @@
+#!/usr/bin/env python3
+
+""" Fetch issues from a roundup-tracker and save them in a databse.
+
+author: Sascha L. Teichmann <sascha.teichmann@intevation.de>
+author: Bernhard Reiter <bernhard@intevation.de>
+author: Sean Engelhardt <sean.engelhardt@intevation.de>
+
+(c) 2010,2015 by Intevation GmbH
+
+This is Free Software unter the terms of the
+GNU GENERAL PUBLIC LICENSE Version 3 or later.
+See http://www.gnu.org/licenses/gpl-3.0.txt for details
+"""
+
+import importlib
+
+def get_chart(target_div_name):
+    display = importlib.import_module("web_view.display_issues")
+    rcd = importlib.import_module("web_view.roundup_content_data")
+    # print(display_issues.render_db_stats_as_html(roundup_content_data.DATABASE_TECH_INTERN, roundup_content_data.SELECT_ALL))
+    # print (display.render_db_stats_as_html(rcd.DATABASE_TECH_INTERN, rcd.SELECT_ALL))
+    html_string = display.render_db_stats_as_html(rcd.DATABASE_TECH_INTERN, rcd.SELECT_ALL)
+
+    html_string = html_string.replace(
+        'var d3jsInjectionTarget="X";', 'var d3jsInjectionTarget="' + target_div_name + '";')
+
+    # print(html_string)
+
+    return html_string
+
+# get_chart();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/web_view/graph.html	Wed Aug 05 13:33:15 2015 +0200
@@ -0,0 +1,412 @@
+<style type = text/css>
+
+	* {
+		font-family: "Sans-serif";
+		font-size: 14px;
+	}
+
+	.svg div{
+			font: 10px;
+			text-align: right;
+			float: left;
+			display: block;
+			padding: 10px;
+			margin: 10px;
+			color: white;
+	}
+
+	.axis path,
+
+	.axis line {
+			fill: none;
+			stroke: lightgrey;
+			/*opacity: 0.7;*/
+			stroke-width: 1px;
+	}
+
+	.y.axis path {
+	  display: none;
+	}
+
+	.line {
+			fill: none;
+			stroke-width: 3px;
+			opacity: 1;
+	}
+
+	.line.critical {
+			stroke: red;
+	}
+
+	.line.critical.legend {
+			fill: red;
+	}
+
+	.line.urgent {
+			stroke: orange;
+	}
+
+	.line.urgent.legend {
+			fill: orange;
+	}
+
+	.line.bug {
+			stroke: violet;
+	}
+
+	.line.bug.legend {
+			fill: violet;
+	}
+
+	.line.feature {
+			stroke: chartreuse;
+			style: stroke-dasharray;
+	}
+
+	.line.feature.legend {
+			fill: chartreuse;
+	}
+
+	.line.wish {
+			stroke: blue;
+	}
+
+	.line.wish.legend {
+			fill: blue;
+	}
+
+	.grid .tick {
+			stroke: lightgrey;
+			/*opacity: 0.7;*/
+	}
+
+	.grid path {
+			stroke-width: 0;
+	}
+
+</style>
+
+<!-- <div id="content" style="display: inline-block"></div> -->
+<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
+<script type="text/javascript">
+
+	// window.onresize = function(){
+	// 	document.getElementsByClassName("chart")[0].innerHTML = "";
+	// 	makeChart();
+	// };
+
+	var d3jsInjectionTarget="X";
+
+	var critical=[];
+	var urgent=[];
+	var bug=[];
+	var feature=[];
+	var wish=[];
+	var timestamp=[];
+
+	// var critical=[
+	// 		{points: 4},
+	// 		{points: 12},
+	// 		{points: 8},
+	// 		{points: 2}
+	// 	]
+	//
+	// var urgent=[
+	// 		{points: 3},
+	// 		{points: 24},
+	// 		{points: 17},
+	// 		{points: 19}
+	// 	]
+	//
+	// var bug=[
+	// 		{points: 10},
+	// 		{points: 2},
+	// 		{points: 2},
+	// 		{points: 12}
+	// 	]
+	//
+	// var feature=[
+	// 		{points: 4},
+	// 		{points: 21},
+	// 		{points: 12},
+	// 		{points: 4}
+	// 	]
+	//
+	// var wish=[
+	// 		{points: 22},
+	// 		{points: 18},
+	// 		{points: 32},
+	// 		{points: 10}
+	// 	]
+	//
+	//
+	// var timestamp=[
+	// 		{date : new Date('2015-06-30T12:36:47')},
+	// 		{date : new Date('2015-07-01T12:37:26')},
+	// 		{date : new Date('2015-07-02T12:38:26')},
+	// 		{date : new Date('2015-07-03T12:39:26')}
+	// 	]
+
+	document.addEventListener("DOMContentLoaded", function(event) {
+		makeChart();
+	});
+
+	function assignIssueToDate(issueArray, dateArray){
+		a = [];
+		for (var i = 0; i < issueArray.length; i++) {
+			a.push({points: issueArray[i].points, date : dateArray[i].date});
+		}
+
+		return a;
+	}
+
+	function limitDatesOnXAxis(limit){
+		if (timestamp.length < limit){
+			return timestamp.length;
+		} else {
+			return limit;
+		}
+	}
+
+	function maxInObject( array ){
+		var maxVal = 0;
+		for (var i = 0; i < array.length; i++) {
+			if (maxVal < array[i].points){
+				maxVal = array[i].points;
+			}
+		}
+		return maxVal;
+	}
+
+
+	function getMaxIssues(){
+		maxIssuesOfAllArrays = [];
+		maxIssuesOfAllArrays.push(maxInObject(critical));
+		maxIssuesOfAllArrays.push(maxInObject(urgent));
+		maxIssuesOfAllArrays.push(maxInObject(bug));
+		maxIssuesOfAllArrays.push(maxInObject(feature));
+		maxIssuesOfAllArrays.push(maxInObject(wish));
+
+		return Math.max.apply(Math, maxIssuesOfAllArrays)+1;
+	}
+
+
+	function dayDifference(first, second) {
+		"use strict";
+		var difference = (second - first) / (1000 * 60 * 60 * 24);
+
+		// just to avoid the get thousands of lines... would look ugly.
+		if (difference > 60){
+			difference = 60;
+		}
+
+		return difference;
+	}
+
+
+	// function for the grid lines
+	function makeGrid(direction, orientation, ticknumber) {
+		return d3.svg.axis()
+			.scale(direction)
+			.orient(orientation)
+			.ticks( ticknumber );
+	}
+
+
+	//append a svg_path. pretty generic
+	function draw_line(svg, data_array, css_class, line_object, lineShape){
+		svg.append("path")
+			.datum(assignIssueToDate(data_array, timestamp))
+			.attr("class", css_class)
+			.style("stroke-dasharray", (lineShape))
+			.attr("d", line_object);
+	}
+
+
+	function makeLegend(svg, width){
+
+		var legend_distance = width+40;
+		var top_distance = 20;
+		var distance_steps = 50;
+
+
+		function set_propper_distance(steps){
+			top_distance += steps;
+			return top_distance;
+		}
+
+		function draw_legend_line(svg, width, Ypos, text, issues){
+			svg.append("svg:text")
+				.attr("class", "legend")
+				.attr("x", width-30	)
+				.attr("y", Ypos)
+				.text(text + ":");
+
+			svg.append("svg:text")
+				.attr("class", "legend")
+				.attr("x", width+35	)
+				.attr("y", Ypos)
+				.text(issues);
+
+			svg.append("rect")
+				.attr("class", "line " + text.toLowerCase() + " legend")
+				.attr("x", width-30)
+				.attr("y", Ypos-20)
+				.attr("width", 100)
+				.attr("height", 2);
+		}
+
+		draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Critical", critical[critical.length-1].points);
+		draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Urgent", urgent[urgent.length-1].points);
+		draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Bug", bug[bug.length-1].points);
+		draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Feature", feature[feature.length-1].points);
+		draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Wish", wish[wish.length-1].points);
+	}
+
+
+
+	//draw the chart
+	function makeChart(div_name){
+
+		//declaration
+		var sizeOfSystemBorders = 20;
+		// var margin = {top: 20, right: 100, bottom: 90, left: 60};
+		// var margin = {top: 0, right: 0, bottom: 0, left: 0}
+
+		var width = document.getElementsByClassName("chart")[0].clientWidth;
+		var height = document.getElementsByClassName("chart")[0].clientHeight;
+		// var	width = (document.documentElement.clientWidth-sizeOfSystemBorders) - margin.left - margin.right;
+		// var	height = (document.documentElement.clientHeight-sizeOfSystemBorders) - margin.top - margin.bottom;
+
+		var x = d3.time.scale()
+			.range([0, width]);
+
+		var y = d3.scale.linear()
+			.range([height, 0]);
+
+		var base_line = d3.svg.line()
+			.x(function(d) { return x(d.date); })
+			.y(function(d) { return y(d.points); });
+
+		//lines
+		var criticalLine = base_line;
+		var urgentLine = base_line;
+		var bugLine = base_line;
+		var featureLine = base_line;
+		var wishLine = base_line;
+		var timestampLine = base_line;
+
+
+		//set domain of y axis
+		var yDomain = [	];
+		yDomain[0] = 0;
+		yDomain[1] = getMaxIssues();
+		y.domain(d3.extent(yDomain, function(d){return d; }));
+
+		//set domain of y axis
+		x.domain(d3.extent(timestamp, function(d){return d.date; }));
+
+
+		var xAxis = d3.svg.axis()
+			.scale(x)
+			.orient("bottom")
+			.ticks(limitDatesOnXAxis(10))
+			.tickFormat(d3.time.format("%d.%m"));
+			// .tickFormat(d3.time.format("%d.%m:%H:%M"));
+			// .tickFormat(d3.time.format("%X"));
+			// .tickFormat(d3.time.format.iso);
+
+
+		var yAxis = d3.svg.axis()
+			.scale(y)
+			.orient("left");
+
+
+		var svg = d3.select("." + d3jsInjectionTarget)
+			.append("svg")
+			.attr("class", "svg")
+			// .attr("width", width)
+			// .attr("height", height)
+			.attr("width", width-20)
+			.attr("height", height-10)
+			.append("g")
+			// .attr("transform", "translate( +50,+0,+0,+0)");
+			.attr("transform", "translate(40 , 0)");
+
+
+		// creation
+
+
+		// Draw the x Grid lines
+		// svg.append("g")
+		// 	.attr("class", "grid")
+		// 	.attr("transform", "translate(0," + height + ")")
+		// 	.call(makeGrid(x, "bottom", timestamp.length)
+		// 		.tickSize(-height, 0, 0)
+		// 		.tickFormat("")
+		// 	);
+
+
+		// Draw the y Grid lines
+		svg.append("g")
+			.attr("class", "grid")
+			.call(makeGrid(y, "left", function(){return Math.min(getMaxIssues(), 10);}())
+				.tickSize(-width, 0, 0)
+				.tickFormat("")
+			);
+
+
+		// Draw the x-axis
+		svg.append("g")
+			.attr("class", "x axis")
+			// .attr("transform", "translate(0, " + 20-height + ")")
+			.call(xAxis)
+			.selectAll("text")
+			.style("text-anchor", "end")
+			// .attr("dx", "-.5em")
+			// .attr("dy", ".1em")
+			// .attr("transform", function() {
+			// 	return "rotate(-30)";
+			// });
+
+
+		// Draw the y-axis
+		svg.append("g")
+			.attr("class", "y axis")
+			.call(yAxis)
+			.append("text")
+			.attr("transform", "rotate(-90)")
+			.attr("y", 6)
+			.attr("dy", ".71em")
+			.style("text-anchor", "end");
+
+
+		// Text for y-axis
+		// svg.append("text")
+		// 	.attr("transform", "rotate(-90)")
+		// 	.attr("y", 10 - margin.left)
+		// 	.attr("x", 0 - (height / 2))
+		// 	.attr("dy", "1em")
+		// 	.style("text-anchor", "middle")
+		// 	.text("Issues");
+
+
+		//Titel und Legende
+		// svg.append("svg:text")
+		// 	.attr("class", "text")
+		// 	.attr("x", 10)
+		// 	.attr("y", -5)
+		// 	.text("Issues Nach Zeit");
+
+		draw_line(svg, wish, "line wish", wishLine, "0, 0");
+		draw_line(svg, feature, "line feature", featureLine, "3, 3");
+		draw_line(svg, bug, "line bug", bugLine, "7, 7");
+		draw_line(svg, urgent, "line urgent", urgentLine, "13, 13");
+		draw_line(svg, critical, "line critical", criticalLine, "17, 17");
+
+
+		// makeLegend(svg, width);
+	}
+
+
+</script>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/web_view/roundup_content_data/__init__.py	Wed Aug 05 13:33:15 2015 +0200
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+
+""" supplys the data needed to comunicate with the roundup-server,
+and the sqlite database. Represents the types of errors used in roundup.
+
+author: Sascha L. Teichmann <sascha.teichmann@intevation.de>
+author: Bernhard Reiter <bernhard@intevation.de>
+author: Sean Engelhardt <sean.engelhardt@intevation.de>
+
+(c) 2010,2015 by Intevation GmbH
+
+This is Free Software unter the terms of the
+GNU GENERAL PUBLIC LICENSE Version 3 or later.
+See http://www.gnu.org/licenses/gpl-3.0.txt for details
+"""
+
+import os
+
+#Add desired sqlite databases here
+DATABASE_REFERENCCE = os.path.dirname(os.path.realpath(__file__)) + "/test_reference.db"
+DATABASE_DEMO = os.path.dirname(os.path.realpath(__file__)) + "/demo.db"
+DATABASE_ERRORDB = os.path.dirname(os.path.realpath(__file__)) + "/errordatabase.db"
+DATABASE_TECH_INTERN = os.path.dirname(os.path.realpath(__file__)) + "/tech_intern.db"
+DATABASE_INT_TEST = os.path.dirname(os.path.realpath(__file__)) + "/int_test.db"
+
+COLUMNS= [
+    "critical", "urgent", "bug", "feature", "wish",
+]
+
+data_dict = {
+    "date": [],
+    "critical": [],
+    "urgent": [],
+    "bug": [],
+    "feature": [],
+    "wish": []
+}
+
+#SQL
+
+#DEMO System
+SELECT_ALL = """
+SELECT strftime("%Y-%m-%dT%H:%M:%S", timestamp),
+    critical,
+    urgent,
+    bug,
+    feature,
+    wish
+FROM issues
+ORDER BY timestamp
+"""
+
+
+CREATE_DB = """
+CREATE TABLE issues (
+    timestamp TIMESTAMP NOT NULL UNIQUE DEFAULT current_timestamp,
+    critical INTEGER NOT NULL DEFAULT 0,
+    urgent INTEGER NOT NULL DEFAULT 0,
+    bug INTEGER NOT NULL DEFAULT 0,
+    feature INTEGER NOT NULL DEFAULT 0,
+    wish INTEGER NOT NULL DEFAULT 0
+)
+"""
+
+
+INSERT_NEW = """
+    INSERT INTO issues (critical, urgent, bug, feature, wish)
+    VALUES (?, ?, ?, ?, ?)
+"""
+
+#Referecen DB:
+SELECT_ALL_REFERENCE = """
+SELECT strftime("%Y-%m-%dT%H:%M:%S", sample_time),
+    critical,
+    major,
+    crash,
+    normal,
+    minor,
+    wishlist
+FROM issues
+ORDER BY sample_time
+"""
\ No newline at end of file
Binary file modules/web_view/roundup_content_data/tech_intern.db has changed
Binary file modules/web_view/roundup_content_data/test_reference.db has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/web_view/webview_template.py	Wed Aug 05 13:33:15 2015 +0200
@@ -0,0 +1,62 @@
+#!/usr/bin/env python3
+
+""" Simple Template to use the Web-View Module
+
+author: Sean Engelhardt <sean.engelhardt@intevation.de>
+
+(c) 2010,2015 by Intevation GmbH
+
+This is Free Software unter the terms of the
+GNU GENERAL PUBLIC LICENSE Version 3 or later.
+See http://www.gnu.org/licenses/gpl-3.0.txt for details
+
+---
+How to write a web-view module?
+---
+
+declare a specific tile in the dash.conf. for example:
+
+---
+[tile5]
+type=d3js
+div_name=webview_test
+script=webview_template
+---
+(this will work for this file, see dash.conf for details)
+
+bottledash will look for a "get_chart(target_div_name)"-methode wich shall
+return valid HTML-code (as string!).
+
+the "target_div_name" is the "div_name" you delared in the dash.conf-file.
+In our case, "tile5" would be in the css-class "webview_test". You can use
+the "target_div_name" for dynamic DOM-Manipulations (like with d3js and jQuery)
+
+If you want to use a python import, please use "importlib" inside the
+get_chart-function.
+
+see <https://docs.python.org/3/library/importlib.html> for details
+
+To not try to import your own modules using the regular
+python import-keyword! You can however import every regular
+python-standard-library using the "import" keyword
+
+"""
+
+import importlib
+
+def get_chart(target_div_name):
+    html_string = """
+<style type = text/css>
+
+.%s {
+    color: red;
+}
+
+</style>
+
+<div id = "hello">
+    Hello World!
+</div>
+    """ % target_div_name
+
+    return html_string
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/views/bottledash_view.tpl	Wed Aug 05 13:33:15 2015 +0200
@@ -0,0 +1,209 @@
+<!-- This tempalte is a part of bottledash
+author: sean engelhardt >sean.engelhardt@intevation.de
+License: GNU GPL >= v2. See LICENSE for details. -->
+
+<%
+
+
+    import math, os, sys, subprocess, html.parser
+    from datetime import date
+
+    PATH = os.path.abspath(os.path.dirname(sys.argv[0]))
+    sys.path.append(PATH + "/modules")
+    import web_view
+
+    #################
+    # settings      #
+    #################
+
+    show_top_bar = settings["show_top_bar"]
+
+    #################
+    # date and time #
+    #################
+
+    today = date.today()
+    weekday = ("Montag", "Dienstag", "Mittwoch", "Donnerstag",
+                "Freitag", "Samstag", "Sonntag")[today.weekday()]
+    month_name = ("Januar", "Februar", "März", "Aprill", "Mai",
+                    "Juni", "Juli", "August", "September", "Oktober",
+                    "November", "Dezember")[today.month-1]
+
+    number_of_rows = 1
+
+    #################
+    # viewport size #
+    #################
+    vp_size = "17px"
+    #if len(tiles) <= 2:
+    #    vp_size = "6vw"
+    #elif len(tiles) >2 and len(tiles) <=4 :
+    #    vp_size = "5vw"
+    #elif len(tiles) >4 and len(tiles) <=6 :
+    #    vp_size = "4vw"
+    #elif len(tiles) >6 and len(tiles) <=8 :
+    #    vp_size = "3vw"
+    #end
+%>
+
+<script type="text/javascript">
+
+    var global_width;
+    var global_height;
+    var tile_width;
+    var tile_height;
+
+    var tiles = document.getElementsByClassName("tile");
+    var border_width = 1;
+    var space_between_tiles = 8;
+
+    var space_lr_borders;
+    var space_lr_margin;
+
+    function calc_tile_with(){
+        var tiles_per_row = Math.floor(tiles.length / {{number_of_rows}});
+        var distance = (space_between_tiles*2) + (border_width*2);
+        var tile_width = ((global_width / tiles_per_row ) - distance);
+        return tile_width;
+    }
+
+    function calc_tile_height(){
+        var distance = (space_between_tiles*2) + (border_width*2);
+        var tile_height = ((global_height / {{number_of_rows}} ) - distance);
+        return tile_height;
+    }
+
+    function resize_content(){
+        global_width = document.getElementById("content").clientWidth;
+        global_height = document.getElementById("content").clientHeight;
+
+
+        tile_width = calc_tile_with();
+        tile_height = calc_tile_height();
+
+        for(var tile = 0; tile < tiles.length; tile++){
+            tiles[tile].style.width= tile_width + 'px';
+            tiles[tile].style.height= tile_height + 'px';
+        }
+    }
+
+    window.onresize = function(){
+        resize_content();
+    }
+
+    document.addEventListener("DOMContentLoaded", function(event) {
+        resize_content();
+    });
+
+</script>
+
+<style>
+    *{
+        margin: 0 auto;
+        padding: 0 auto;
+        font-family: "Lucida Console", Monaco, monospace;
+    }
+
+    body {
+        overflow: hidden;
+    }
+
+    #wrapper{
+        background-color: #F2F2F2;
+        color: black;
+        min-width: 100%;
+        min-height: 100%;
+    }
+
+    #topbar{
+        min-width: auto;
+        padding-left: 8px;
+        padding-top: 8px;
+        padding-bottom: 8px;
+        /*height: 5%;*/
+        font-family: Arial, Helvetica, sans-serif;
+    }
+
+    #content{
+        min-width: 100%;
+        % if show_top_bar == "True":
+            height: 95%;
+        % else :
+            height: 100%;
+        %end
+    }
+
+    .tile{
+        float: left;
+        margin: 8px;
+        background-color: #FFFFFF;
+        border: 1px solid #999999;
+        border: none;
+        text-align:center;
+        vertical-align: middle;
+    }
+
+    .clear{
+        height: 0px;
+        clear: both;
+    }
+
+    /*tiles types*/
+
+    .statusmon{
+        color: white;
+        font-size: {{vp_size}};
+    }
+
+    .chart{
+        font-size: {{vp_size}};
+    }
+
+    .active{
+        border: 1px solid #00cc00;
+        background-color: #009900;
+    }
+
+    .dead{
+        border: 1px solid #cc0000;
+        background-color: #990000;
+    }
+
+</style>
+
+<div id = "wrapper">
+    % if show_top_bar == "True" :
+    <div id = "topbar">
+        <b>{{weekday}}</b> {{today.day}}. {{month_name}}
+    </div>
+    % end
+
+    <div id = "content">
+        <%
+            for tile in tiles :
+            type = ""
+            tile_content = ""
+            status = ""
+            if tile["type"] == "mon" :
+                type = "statusmon"
+                tile_content = tile["source"]
+                if tile["status"] == "up" :
+                    status = "active"
+                elif tile["status"] == "down" :
+                    status = "dead"
+                end
+            elif tile["type"] == "d3js" :
+                type = "chart"
+                status = tile["div_name"]
+                tile_content = web_view.make_chart(tile["script"], tile["div_name"])
+            end
+        %>
+
+        <div class = "tile {{type}} {{status}}">
+            {{!tile_content}}
+        </div>
+
+        % end
+
+    </div>
+</div>
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)