#!/usr/bin/python
"""
a python + javascript based ganttproject publisher
TODO: internazionalization
FIXME: xml.dom.minidom can't read files with entities
@version:2.01
@author: Baruffaldi Paolo
@requires: Apache webserver, python
"""
import cgi, os, time
import cgitb;cgitb.enable()
import xml.dom.minidom, urllib
import config
def ctags_read(txt):
diz={}
for x in txt.splitlines():
if len(x) >1 and x.strip()[0] == "@":
a,b = x.strip().split(":",1)
diz[a[1:]] = b
return diz
CONF = config.configuration()
CONF.update(ctags_read(__doc__))
def parametri():
"""
variables sent by user
"""
form = cgi.FieldStorage()
diz = {
"position":"summary",
"actions":None,
}
for x in form.keys():
diz[x] = form[x].value
return diz
def multidiz(dizionari,valori):
diz = {}
for x in valori:
for y in dizionari:
diz[x] = dizionari[y].get(x)
if diz[x]:
break
return diz
def remote_cache():
"""
copy remote files in project's directory
TODO: scrivere log su file
FIXME: with some configurations it doesn't works
"""
for some_url,local_name in CONF["remote_cache"]:
try:
opener = urllib.FancyURLopener(CONF["proxies"])
f = opener.open(some_url)
testo = f.read()
f.close()
filehandle.close()
nuovo = open(CONF["dir_progetti"]+"/"+local_name,"wb")
nuovo.write(testo)
nuovo.close()
except:
pass
def mask4js(testo):
"""
@param testo: StringType
@return: StringType
"""
return (testo or "").replace('"','\\"')
def main():
"""
"""
you = parametri()
you["Content-type"]='Content-type: text/html\n\n'
### what to do
if you["actions"]:
actions_log = do_actions()
### what to see
if you["position"] == "summary":
remote_cache()
html2go =page_browse_objects()
elif you["position"] == "view":
if you.get("type") in ("gan","planner"):
myobj = Ganttobj(CONF["dir_progetti"]+"/"+you["project"]+"."+you["type"])
diz = {"$JS_CONFIGURATION":
"<script>\n"+myobj.gan2js()+"\n</script>",
"$TOP_BAR_EXTRA":"""<input type='button' value='↑'
onclick='window.location.href="ganttweb.py"'>
"""
}
else:
diz = {"$JS_CONFIGURATION":
"<script>\n"+leggi_testo(CONF["dir_progetti"]+you["project"]+".js")+"\n</script>",
# """
# <script src="%(url_progetti)s""" % CONF\
# +"""%(project)s.js">
# </script>
# """ % you,
"$TOP_BAR_EXTRA":"""<input type='button' value='↑'
onclick='window.location.href="ganttweb.py"'>
"""
}
html2go = page_gantt_chart(diz)
else:
html2go = "[WRONG POSITION] %(position)s" % you
print you["Content-type"]
print html2go
def do_actions(you):
return []
def css():
return """<style>
.title {
text-align:left;
color:white;
background-color:#8888ff;
font-weight:bolder;
}
.viewlink{
text-align:center;
border:solid 3px #8888cc;
}
.subtitle {
text-align:center;
font-style:italic;
background-color:#aaaaff;
font-weight:bolder;
}
.chapter {
border:solid 1px #ccccff;
margin-top:10px;
border-width:1px 5px 15px 1px;
padding:10px;
}
.para {
padding-left:20px;
margin-top:10px;
border:dotted 1px #ccccff;
border-width:0px 1px 1px 0px;
}
</style>
"""
def page_gantt_chart(diz):
"""
this is a very simple sample
"""
w_you_want = open(CONF["path_html_template"],"r")
testo= w_you_want.read()
w_you_want.close()
for k in diz.keys():
testo = testo.replace(k,diz[k])
return testo
def page_browse_objects():
html = """
<html>
<head>
<title>Gantt.summary</title>
</head>
<body>"""+ css()+ """
<div id='top_bar'><b><a href='ganttweb.py'>Ganttproject@web</a></b> - Ver. %(version)s</div>
<div style='height:40;background-color:#eee;'>
</div>
<div align='right'>
<a href="%(url_help)s" lang='en'>help</a>
</div>
<br>
%(prologo)s
<br>
<table width="100%%" id="table_summary" class='chapter'>
<tr>
<th lang='en'>project name</th>
<th lang='en'>view</th>
<th lang='en'>info</th>
<th lang='en'>resources</th>
</tr>
""" % CONF
for nome in os.listdir(CONF["dir_progetti"]):
if len(nome)>2 and "." in nome:
nome_breve, estensione = nome.split(".",1)
diz_riga={"nomefile":nome_breve,"est":estensione}
if estensione in ("gan","planner"):
xfile = Ganttobj(CONF["dir_progetti"]+nome_breve+"."+estensione)
diz_riga["titolo"]=xfile.project.getAttribute("name") or ""
diz_riga["azienda"]=xfile.project.getAttribute("company") or ""
else:
diz_riga["titolo"]=diz_riga["nomefile"]
diz_riga["azienda"]="<span style='color:#cccccc;'>[file javascript]</span>"
diz_riga["url_progetti"]=CONF["url_progetti"]
html+="""
<tr>
<td class='title'>
%(titolo)s</td>
<td class='viewlink'><a href='?position=view&type=%(est)s&project=%(nomefile)s'>.:</a>
</td>
<td class='subtitle'>
<div align='left'>
<span lang='en'>company</span>:%(azienda)s
</div>
</td>
<td class='subtitle'>
<div align='left'>
<span lang='en'>filename</span>:<a href='%(url_progetti)s/%(nomefile)s.%(est)s'>%(nomefile)s.%(est)s</a>
</dib>
</td>
</tr>""" % diz_riga
html+="""</table>
</body>
</html>
"""
return html
def anno_mese_giorno(stringa):
"""
gg/mm/yyyy
yyyy/mm/gg
yyyymmgg
yyyymmgghhmmss
20050904T000000Z
"""
separatore = "/"
if not(separatore in stringa):
separatore = "-"
if not(separatore in stringa):
if len(stringa)==8 or len(stringa)==14 or len(stringa) == 16:
anno=stringa[:4]
mese=stringa[4:6]
giorno = stringa[6:8]
return [int(anno),int(mese),int(giorno)]
return [2005,01,01] #
giorno, mese, anno = stringa.split(separatore)
if len(anno) < 4:
anno, giorno = giorno, anno
return [int(anno),int(mese),int(giorno)]
def gan2js(tizio):
"""
@param tizio: ElementObject (<project>)
@return: StrinType
"""
data_minima = [9999, 99, 99]
time_data_massima = 0
for attivita in tizio.getElementsByTagName("task"):
anno, mese, giorno = anno_mese_giorno( attivita.getAttribute("start") )
data_minima =min( [anno,mese,giorno],data_minima)
if tizio.getAttribute("mrproject-version") =="2":
attr_duration = int(attivita.getAttribute("duration") or 0)/3600
else:
attr_duration = attivita.getAttribute("duration")
time_data_massima = max(
time.mktime([anno,mese,giorno + int(attr_duration),0,0,0,0,0,0]),
time_data_massima)
time_data_minima= time.mktime([data_minima[0],data_minima[1],data_minima[2],0,0,0,0,0,0])
range_giorni = (time_data_massima - time_data_minima) / (24*60*60)
try:
descrizione = tizio.getElementsByTagName("description")[0].firstChild.nodeValue.replace("\n"," ")
except:
descrizione = ""
txt = """
var PROGETTO = {
name:"%s",
description:"%s",
company:"%s",
color:"%s"}
var MARGINE_SINISTRO = 220;
var MARGINE_ALTO = 90;
var RANGE_GIORNI = %s;
var ALTEZZA_ATTIVITA = 30; //minimo 10
var LARGHEZZA_GIORNO = 50; //minimo 12
var ETICHETTE_GIORNI = ["Dom","Lun","Mar","Mer","Gio","Ven","Sab"];
var ETICHETTE_MESI = ["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"];
var GIORNO0 = new Date(%s,%s,%s);
""" % (mask4js(tizio.getAttribute("name") or ""),
mask4js(descrizione),
mask4js(tizio.getAttribute("company") or ""),
tizio.getElementsByTagName("tasks")[0].getAttribute("color") or "#6666ff;",
range_giorni,
data_minima[0], data_minima[1]-1, data_minima[2],
)
txt+="""var ATTIVITA = new Array(
"""
righe_attivita = []
for attivita in tizio.getElementsByTagName("task"):
if tizio.getAttribute("mrproject-version") =="2":
time_data_attivita = anno_mese_giorno(attivita.getAttribute("work-start"))
else:
time_data_attivita = anno_mese_giorno(attivita.getAttribute("start"))
time_data_attivita.extend([0,0,0,0,0,0])
time_data_attivita = time.mktime(time_data_attivita)
diz_att = {"start_n":(time_data_attivita - time_data_minima) / (24*60*60)}
for x in ["name","color"]:
diz_att[x] = attivita.getAttribute(x) or ""
diz_att["duration"] = int(attivita.getAttribute("duration") or 0)
if tizio.getAttribute("mrproject-version") =="2":
time_data_fine = anno_mese_giorno(attivita.getAttribute("end"))
time_data_fine.extend([0,0,0,0,0,0])
time_data_fine = time.mktime(time_data_fine)
diz_att["duration"] = (time_data_fine - time_data_attivita) / (24*60*60)
tag_note =attivita.getElementsByTagName("notes")
diz_att["childs"] = len(attivita.getElementsByTagName("task")) or 0
if tag_note and tag_note[0].parentNode == attivita:
diz_att["notes"] = dom_inside_text(tag_note[0]).replace('\n','\\n')
else:
diz_att["notes"]=""
for x in ["name","notes","color"]:
diz_att[x] = mask4js(diz_att[x])
righe_attivita.append("""{name:"%(name)s",start_n:%(start_n)s,duration:%(duration)s,color:"%(color)s",notes:"%(notes)s",childs:%(childs)s}
""" % diz_att)
txt+=",\n".join(righe_attivita)+"""
);
"""
txt+= """var RISORSE = new Array(
"""
righe_risorse = []
for risorsa in tizio.getElementsByTagName("resource"):
diz_ris = {}
for x in ["id","name","function","contacts","phone"]:
diz_ris[x] = mask4js(risorsa.getAttribute(x))
righe_risorse.append("""{id:"%(id)s",name:"%(name)s",funz:"%(function)s",contacts:"%(contacts)s",phone:"%(phone)s"}""" % diz_ris)
txt+=",\n".join(righe_risorse)+"""
);
"""
return txt
class Ganttobj:
def __init__(self,src=None):
inside_dom = xml.dom.minidom.parse(src)
self.project = inside_dom.documentElement
def gan2js(self):
return gan2js(self.project)
def dom_inside_text(elemento,do_strip=True):
"""
read all the text inside
"""
if elemento.nodeType == elemento.TEXT_NODE:
if do_strip:
return elemento.nodeValue.strip()
else:
return elemento.nodeValue
txt = ""
for elementino in elemento.childNodes:
txt+="\n"+dom_inside_text(elementino)
return txt
def leggi_testo(nomefile):
x = open(nomefile,"r")
txt = x.read()
x.close()
return txt
if __name__ == "__main__":
main()
|