|
|
|
# this is a web interface for simple edits to configuration or editing data
|
|
|
|
# for particular bureaus
|
|
|
|
import configparser
|
|
|
|
import inspect
|
|
|
|
import os
|
|
|
|
|
|
|
|
from bottle import Bottle, request, static_file
|
|
|
|
import mako
|
|
|
|
|
|
|
|
class IhrApp(Bottle):
|
|
|
|
def __init__(self):
|
|
|
|
super(IhrApp, self).__init__()
|
|
|
|
self.name = "IHR App"
|
|
|
|
self.route("/", callback=self.index)
|
|
|
|
self.route("/config/<bureau>", callback=self.bureau_config)
|
|
|
|
self.route("/config/<bureau>", callback=self.bureau_config, method="POST")
|
|
|
|
self.route("/log/<bureau>", callback=self.bureau_log)
|
|
|
|
self.route('/static/<path:path>', callback=self.static)
|
|
|
|
self.bureaus = []
|
|
|
|
self.views = {}
|
|
|
|
mpath = inspect.getfile(self.__class__)
|
|
|
|
self.tdir = os.path.dirname(mpath)
|
|
|
|
|
|
|
|
def index(self):
|
|
|
|
# return a list of active bureaus with links
|
|
|
|
# TODO: allow (de)activation of non-essential bureaus
|
|
|
|
templfile = os.path.join(self.tdir, "web_index.html")
|
|
|
|
out = """
|
|
|
|
<h3>The Screenless Office</h3>
|
|
|
|
<h4><em>Web Manager</em></h4>
|
|
|
|
<ul>
|
|
|
|
"""
|
|
|
|
|
|
|
|
for bureau in self.bureaus:
|
|
|
|
out += '<li>{0}:<ul>\n'.format(bureau)
|
|
|
|
out += '<li><a href="/config/{0}">{0} config</a></li>\n'.format(bureau)
|
|
|
|
out += '<li><a href="/log/{0}">{0} logs</a></li>\n'.format(bureau)
|
|
|
|
if bureau in self.views:
|
|
|
|
for view in self.views[bureau]:
|
|
|
|
out += '<li><a href="/{0}/{1}">{1}</a></li>\n'.format(bureau, view)
|
|
|
|
|
|
|
|
out += '</ul></li>'
|
|
|
|
|
|
|
|
out += '<li><a href="/config/printers">Printers</a></li>\n'
|
|
|
|
out += '<li><a href="/config/mgmt">Management</a></li>\n'
|
|
|
|
|
|
|
|
out += "</ul>"
|
|
|
|
|
|
|
|
return out
|
|
|
|
|
|
|
|
def bureau_config(self, bureau):
|
|
|
|
# parse the config and make it into a form
|
|
|
|
# TODO: add a little html snippet with cfg file docs
|
|
|
|
templfile = os.path.join(self.tdir, "web_config.html")
|
|
|
|
template = mako.template.Template(filename=templfile, input_encoding='utf-8')
|
|
|
|
basedir = os.path.expanduser("~/.screenless")
|
|
|
|
|
|
|
|
msg = ""
|
|
|
|
|
|
|
|
if bureau == "mgmt":
|
|
|
|
cfgfile = "mgmt.ini"
|
|
|
|
mode = "ini"
|
|
|
|
elif bureau == "printers":
|
|
|
|
cfgfile = "printers.cfg"
|
|
|
|
mode = "ini"
|
|
|
|
else:
|
|
|
|
cfgfile = bureau + ".yml"
|
|
|
|
mode = "yaml"
|
|
|
|
cfgfile = os.path.join(basedir, cfgfile)
|
|
|
|
if request.method == "POST":
|
|
|
|
with open(cfgfile, "w") as cfg:
|
|
|
|
cfg.write(request.forms.get("cfgdata"))
|
|
|
|
# TODO: tell the bureau to restart / reload
|
|
|
|
msg = "Modified config file saved!"
|
|
|
|
|
|
|
|
#parse and show the config as a form
|
|
|
|
with open(cfgfile) as cfg:
|
|
|
|
cfgdata = cfg.read()
|
|
|
|
return template.render_unicode(msg=msg, bureau=bureau, cfgfile=cfgfile, mode=mode, cfgdata=cfgdata)
|
|
|
|
|
|
|
|
def bureau_log(self, bureau):
|
|
|
|
# display the current log file for a bureau
|
|
|
|
msg = ""
|
|
|
|
templfile = os.path.join(self.tdir, "web_logview.html")
|
|
|
|
template = mako.template.Template(filename=templfile, input_encoding='utf-8')
|
|
|
|
|
|
|
|
basedir = os.path.expanduser("~/.screenless")
|
|
|
|
logfile = bureau + ".log"
|
|
|
|
logfile = os.path.join(basedir, logfile)
|
|
|
|
with open(logfile) as log:
|
|
|
|
logdata = log.read()
|
|
|
|
|
|
|
|
return template.render_unicode(msg=msg, bureau=bureau, logdata=logdata)
|
|
|
|
|
|
|
|
def register_bureau(self, bureau):
|
|
|
|
if not(bureau in self.bureaus):
|
|
|
|
self.bureaus.append(bureau)
|
|
|
|
|
|
|
|
def register_webview(self, prefix, view, callback):
|
|
|
|
#TODO: add description
|
|
|
|
if prefix in self.views:
|
|
|
|
self.views[prefix].append(view)
|
|
|
|
else:
|
|
|
|
self.views[prefix] = [view]
|
|
|
|
def wrapped_cb():
|
|
|
|
# bottle uses a fancy MultiDict but we just want the simple version
|
|
|
|
return callback(dict(request.forms.items()))
|
|
|
|
self.route("/" + prefix + "/" + view, callback=wrapped_cb)
|
|
|
|
self.route("/" + prefix + "/" + view, callback=wrapped_cb, method="POST")
|
|
|
|
|
|
|
|
def register_crud(self, data):
|
|
|
|
# adds callbacks for crud operations on a database
|
|
|
|
pass
|
|
|
|
|
|
|
|
def static(self, path):
|
|
|
|
root_path = os.path.join(self.tdir, "web_static")
|
|
|
|
return static_file(path, root=root_path)
|
|
|
|
|
|
|
|
|