une semaine déconnectée; un meilleur glasnost
This commit is contained in:
parent
8469dd56a5
commit
347a8fdf1a
|
@ -13,3 +13,4 @@ tmp-system
|
|||
tmp-tests
|
||||
root-system
|
||||
root-tests
|
||||
talTranslations.py
|
||||
|
|
7
Makefile
7
Makefile
|
@ -129,6 +129,7 @@ archive: dist-clean
|
|||
clean:
|
||||
rm -rf tmp-system tmp-tests
|
||||
rm -rf root-tests root-system
|
||||
rm -f talTranslations.py
|
||||
|
||||
config: config.in
|
||||
cat $^ | sed -e "s/^glasnost = .*/glasnost = $(GLASNOST)/g" \
|
||||
|
@ -347,11 +348,15 @@ mo: po/glasnost-web/de.po \
|
|||
msgfmt --statistics -c -v -o locale/fr/LC_MESSAGES/glasnost-web.mo po/glasnost-web/fr.po
|
||||
msgfmt --statistics -c -v -o locale/sv/LC_MESSAGES/glasnost-web.mo po/glasnost-web/sv.po
|
||||
|
||||
talTranslations.py: templates/
|
||||
./talGettext.py templates/ > talTranslations.py
|
||||
|
||||
po: glasnost-web/ \
|
||||
shared/common/ \
|
||||
shared/proxy/ \
|
||||
shared/server/ \
|
||||
shared/web/
|
||||
shared/web/ \
|
||||
talTranslations.py
|
||||
|
||||
cp po/glasnost-web/de.po po/glasnost-web/de.pox
|
||||
cp po/glasnost-web/es.po po/glasnost-web/es.pox
|
||||
|
|
|
@ -27,27 +27,21 @@ plane - Plane
|
|||
- Quality: ****
|
||||
- Inspiration: default skin of Plane <http://www.plane.org>
|
||||
|
||||
lightbulb - Lightbulb
|
||||
---------------------
|
||||
|
||||
- Colours: black on light blue; blues for decoration
|
||||
- Navigation: one level, vertical, bottom-left
|
||||
- Quality: ** (original but not for production use)
|
||||
|
||||
macfly - macfly
|
||||
---------------
|
||||
|
||||
- Colours: black on orange; red/brown for misc elements
|
||||
- Navigation: one level, vertical, right
|
||||
- Quality: ****
|
||||
- Inspiration: colour scheme from an example of CSS use (lost url)
|
||||
- Inspiration: design idea and colour scheme from an example of CSS use
|
||||
<http://www.projectseven.com/grafitti/jan2003/macfly/index.htm>
|
||||
|
||||
watercolor - Water Color
|
||||
------------------------
|
||||
|
||||
- Colours: black on light blue; shades of blue
|
||||
- Navigation: one level, vertical, top right
|
||||
- Quality: ** (nice but lots of styles needed by Glasnost are not yet done)
|
||||
- Quality: ****
|
||||
- Inspiration: some watercolor metacity theme elements
|
||||
|
||||
|
||||
|
@ -65,6 +59,7 @@ artus - artus (current version)
|
|||
-------------------------------
|
||||
|
||||
- ARTUS (Code Lutin customer)
|
||||
- Based on entrouvert2; should be removed
|
||||
|
||||
bxlug - BxLUG
|
||||
-------------
|
||||
|
@ -72,10 +67,25 @@ bxlug - BxLUG
|
|||
- Bruxelles Linux User Group
|
||||
- http://www.bxlug.be
|
||||
|
||||
codelutin.org - Code Lutin.org
|
||||
------------------------------
|
||||
|
||||
- Code Lutin
|
||||
- http://www.codelutin.org
|
||||
|
||||
crans - CRANS
|
||||
-------------
|
||||
|
||||
- Cachan / Réseau @ Normale Sup'
|
||||
- http://assoce.crans.org
|
||||
- FIXME: /images/crans_banner.png missing
|
||||
|
||||
easter-eggs - Easter-eggs
|
||||
-------------------------
|
||||
|
||||
- Proposal for http://www.easter-eggs.org
|
||||
- Lacks several styles to be really used
|
||||
- Bad coding style in CSS files
|
||||
|
||||
entrouvert.be - entrouvert.be
|
||||
-----------------------------
|
||||
|
@ -102,6 +112,7 @@ libre-entreprise - Libre-entreprise
|
|||
-----------------------------------
|
||||
|
||||
- http://www.libre-entreprise.org and http://www.libre-entreprise.com
|
||||
- TODO: add login button
|
||||
|
||||
rap - R.A.P. Belgique
|
||||
---------------------
|
||||
|
@ -110,28 +121,59 @@ rap - R.A.P. Belgique
|
|||
- http://www.antipub.be
|
||||
|
||||
|
||||
------
|
||||
Others
|
||||
------
|
||||
|
||||
lightbulb - Lightbulb
|
||||
---------------------
|
||||
|
||||
- Colours: black on light blue; blues for decoration
|
||||
- Navigation: one level, vertical, bottom-left
|
||||
- hardcodes to many things
|
||||
|
||||
wretched - Wretched of the Earth
|
||||
--------------------------------
|
||||
|
||||
- Colours: black on red
|
||||
- lacks many styles
|
||||
|
||||
|
||||
--------
|
||||
Unsorted
|
||||
--------
|
||||
|
||||
- chambon.raviart - Chambon.Raviart
|
||||
[REMOVE]
|
||||
- codelutin - Code Lutin
|
||||
- codelutin.org - Code Lutin.org
|
||||
- crans - CRANS
|
||||
[REMOVE]
|
||||
- cuisine - Cuisine (site pour les examples)
|
||||
[REMOVE] [or modify to remove hardcoded strings]
|
||||
- cyborg - Cyborg
|
||||
- eclova - Eclova
|
||||
[REMOVE] [or modify to be generic]
|
||||
- entrouvert - entr'ouvert (first version)
|
||||
[REMOVE]
|
||||
- entrouvert2 - entr'ouvert (current version)
|
||||
[hardcodes some strings]
|
||||
- fsfeurope - FSF (~europe)
|
||||
[REMOVE]
|
||||
- glasnost - Glasnost
|
||||
[REMOVE] [or modify to get in shape]
|
||||
- glasnost2 - Glasnost 2
|
||||
[default for now; should rename and remove background image]
|
||||
- i3c - i3c
|
||||
[nice one; should sort]
|
||||
- in3activa - in3activa
|
||||
[REMOVE]
|
||||
- linuxdays - Luxembourg LinuxDays
|
||||
[REMOVE] [despite nice colour scheme]
|
||||
- pel-infini - infini (assoc brest)
|
||||
[REMOVE]
|
||||
- theridion - Theridion (new)
|
||||
[REMOVE]
|
||||
- upthings - upthings
|
||||
[REMOVE]
|
||||
- vecam - Vecam
|
||||
- wretched - Wretched of the Earth
|
||||
[REMOVE] [template now in metis]
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ WebDirectoryPath = %(webdir)s
|
|||
|
||||
[Mail]
|
||||
# Email address to use when no admin has been defined in Glasnost
|
||||
Admin = root@localhost
|
||||
# website to show in emails sent to new people
|
||||
Website = http://localhost
|
||||
# Host name and port of the SMTP server
|
||||
|
|
|
@ -66,7 +66,7 @@ def monthTupleJS(year = 0, month = 0):
|
|||
if (year, month, d) == today:
|
||||
more = ' id="today"'
|
||||
date = '%s-%02d-%02d' % (year, month, cal[i][j])
|
||||
cal[i][j] = """<a href="#" onclick="selectDay('%s')"%s>%s</a>""" % \
|
||||
cal[i][j] = '<a href="#" onclick="selectDay(\'%s\')"%s>%s</a>' % \
|
||||
(date, more, cal[i][j])
|
||||
return cal
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ class Application(applications.Application):
|
|||
if session is not None:
|
||||
getProxyForServerRole('sessions').setSession(session,
|
||||
context.getVar('virtualHost').defaultDispatcherId)
|
||||
except faults.MissingItem:
|
||||
except (faults.MissingItem, faults.UnknownServerId):
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
if req.caching:
|
||||
|
@ -184,14 +184,9 @@ class Application(applications.Application):
|
|||
req.cancel()
|
||||
raise
|
||||
|
||||
t1 = context.getVar('t1')
|
||||
open('/tmp/webbench', 'a+').write('%f %s\n' % (
|
||||
time.time() - t1, req.unparsed_uri))
|
||||
return result
|
||||
|
||||
def handler(self, req):
|
||||
t1 = time.time()
|
||||
|
||||
# Use direct access to _req for speed.
|
||||
try:
|
||||
_req = req._req
|
||||
|
@ -227,6 +222,7 @@ class Application(applications.Application):
|
|||
dispatcherId = None,
|
||||
fallbackTemplatesDirectoryPath = None,
|
||||
function = None,
|
||||
htmlHeaders = [],
|
||||
httpHostName = None,
|
||||
httpLocalPath = None,
|
||||
# The HTTP path, without the httpScriptDirectoryPath prefix.
|
||||
|
@ -249,7 +245,6 @@ class Application(applications.Application):
|
|||
session = None,
|
||||
sessionToken = None,
|
||||
sessionTokenInCookie = 0, # Was the sessionToken stored in the url?
|
||||
t1 = t1,
|
||||
talEngine = None,
|
||||
templateDirectoryName = None,
|
||||
templatesDirectoryPath = None,
|
||||
|
@ -352,9 +347,6 @@ class Application(applications.Application):
|
|||
virtualHostsWeb = getWebForServerRole('virtualhosts')
|
||||
try:
|
||||
virtualHost = virtualHostsWeb.getObjectByHostName(httpHostName)
|
||||
except faults.MissingItem:
|
||||
try:
|
||||
virtualHost = virtualHostsWeb.getDefaultVirtualHost()
|
||||
except faults.MissingItem:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
|
@ -757,8 +749,6 @@ class Application(applications.Application):
|
|||
data = zbuf.getvalue()
|
||||
req.headers_out['Content-Encoding'] = 'gzip'
|
||||
t1 = context.getVar('t1')
|
||||
if not t1:
|
||||
t1 = time.time()
|
||||
if lastModTime:
|
||||
req.headers_out['Last-Modified'] = time.strftime(
|
||||
'%a, %d %b %Y %H:%M:%S GMT', lastModTime)
|
||||
|
@ -770,9 +760,6 @@ class Application(applications.Application):
|
|||
t = time.strptime(req.headers_in['If-Modified-Since'][:25],
|
||||
'%a, %d %b %Y %H:%M:%S')
|
||||
if lastModTime <= t:
|
||||
open('/tmp/webbench', 'a+').write(
|
||||
'%f %s (static, not mod)\n' % (
|
||||
time.time() - t1, req.unparsed_uri))
|
||||
return HTTP_NOT_MODIFIED
|
||||
except KeyError:
|
||||
pass
|
||||
|
@ -785,8 +772,6 @@ class Application(applications.Application):
|
|||
except IOError:
|
||||
# the user probably cancelled the request
|
||||
return OK
|
||||
open('/tmp/webbench', 'a+').write('%f %s (static)\n' % (
|
||||
time.time() - t1, req.unparsed_uri))
|
||||
return OK
|
||||
|
||||
def parseHttpPath(self, remaining):
|
||||
|
@ -857,8 +842,11 @@ class Application(applications.Application):
|
|||
return None
|
||||
if not 'pagenames' in context.getVar('knownRoles'):
|
||||
return None
|
||||
try:
|
||||
objectId = getWebForServerRole('pagenames').getIdByName(
|
||||
remaining[0])
|
||||
except faults.UnknownServerId:
|
||||
return None
|
||||
if not objectId:
|
||||
return None
|
||||
context.setVar('dispatcherId',
|
||||
|
@ -1113,15 +1101,13 @@ class RequestCache:
|
|||
context.getVar('varDirectoryPath'), 'webcache')
|
||||
self.cacheFilePath = os.path.join(
|
||||
self.cacheDirectoryPath,
|
||||
self.getCacheFileName(self.unparsed_uri, language))
|
||||
self.getCacheFileName(language))
|
||||
self.cacheFilePathDepends = os.path.join(
|
||||
self.cacheDirectoryPath,
|
||||
self.getCacheFileName(self.unparsed_uri, language)
|
||||
+ '.depends')
|
||||
self.getCacheFileName(language) + '.depends')
|
||||
self.cacheFilePathMimeType = os.path.join(
|
||||
self.cacheDirectoryPath,
|
||||
self.getCacheFileName(self.unparsed_uri, language)
|
||||
+ '.mimetype')
|
||||
self.getCacheFileName(language) + '.mimetype')
|
||||
self.depends = []
|
||||
|
||||
def cancel(self):
|
||||
|
@ -1189,8 +1175,13 @@ class RequestCache:
|
|||
mimeType = 'text/html'
|
||||
return cachePage, mimeType
|
||||
|
||||
def getCacheFileName(self, uri, language):
|
||||
return binascii.hexlify(md5.new(uri + language).digest())
|
||||
def getCacheFileName(self, language):
|
||||
if self.headers_in.has_key('Host'):
|
||||
hostName = self.headers_in['Host']
|
||||
else:
|
||||
hostName = ''
|
||||
uri = self.unparsed_uri
|
||||
return binascii.hexlify(md5.new(hostName + uri + language).digest())
|
||||
|
||||
def getExpires(self):
|
||||
try:
|
||||
|
@ -1240,12 +1231,13 @@ def handler(req):
|
|||
# those are legitimate and should be raised to modpython handler
|
||||
raise
|
||||
except Exception, e:
|
||||
if not commonTools.getConfig('Misc', 'SendTalkBackTo'):
|
||||
raise
|
||||
import traceback
|
||||
import smtplib
|
||||
f = cStringIO.StringIO()
|
||||
traceback.print_exc(file = f)
|
||||
f = f.getvalue()
|
||||
|
||||
if commonTools.getConfig('Misc', 'SendTalkBackTo'):
|
||||
import smtplib
|
||||
message = """Subject: [%(host)s] Glasnost Talkback
|
||||
|
||||
Version: %(version)s
|
||||
|
@ -1257,14 +1249,18 @@ Url: %(url)s
|
|||
%(traceback)s
|
||||
""" % { 'time': time.ctime(),
|
||||
'host': socket.getfqdn(),
|
||||
'traceback': f.getvalue(),
|
||||
'traceback': f,
|
||||
'version': glasnost.versionNumber,
|
||||
'url': req.unparsed_uri}
|
||||
server = smtplib.SMTP('localhost')
|
||||
try:
|
||||
server.sendmail(
|
||||
commonTools.getConfig('Misc', 'AdminEmailAddress'),
|
||||
commonTools.getConfig('Misc', 'AdminEmailAddress',
|
||||
default = 'root@localhost'),
|
||||
commonTools.getConfig('Misc', 'SendTalkBackTo'),
|
||||
message)
|
||||
except:
|
||||
pass
|
||||
raise
|
||||
return result
|
||||
|
||||
|
@ -1279,6 +1275,7 @@ if webTools.getConfig('Profiling', 'false') == 'true':
|
|||
globals(), locals())
|
||||
except SystemExit:
|
||||
pass
|
||||
prof.dump_stats('/tmp/glasnost-web-%s.prof'%os.path.split(req.filename)[1])
|
||||
prof.dump_stats('/tmp/glasnost-web-%s.prof' % \
|
||||
os.path.split(req.filename)[1])
|
||||
return result
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
font-weight: bold;
|
||||
background-color: #ffffd1;
|
||||
z-index: 1000;
|
||||
margin: 2.5em 0 0 2em;
|
||||
}
|
||||
|
||||
ul.tooltip {
|
||||
|
|
|
@ -141,14 +141,6 @@ table.spip th {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.odd {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.even {
|
||||
background-color: #fafafa; /* very light grey */
|
||||
}
|
||||
|
||||
table.rst td,
|
||||
table.objects-table td,
|
||||
table.spip td {
|
||||
|
@ -252,7 +244,6 @@ p#powered-by-glasnost a {
|
|||
}
|
||||
|
||||
.error-message {
|
||||
text-align: center;
|
||||
color: red;
|
||||
display: block;
|
||||
}
|
||||
|
|
|
@ -1,202 +1,100 @@
|
|||
addEvent(window, "load", makeBalloonHelp);
|
||||
|
||||
var CURRENT_BALLOON_HELP;
|
||||
var onLabels = 0;
|
||||
document.getElementsByClassName = function ( class_name ) {
|
||||
var all_obj, ret_obj = new Array(), j = 0, strict = 0;
|
||||
if ( document.getElementsByClassName.arguments.length > 1 )
|
||||
strict = ( document.getElementsByClassName.arguments[1] ? 1 : 0 );
|
||||
if ( document.all )
|
||||
all_obj = document.all;
|
||||
else if ( document.getElementsByTagName && !document.all )
|
||||
all_obj = document.getElementsByTagName ( "*" );
|
||||
for ( i = 0; i < all_obj.length; i++ ) {
|
||||
if ( ( ' ' + all_obj[i].getAttribute("class") + ' ').toLowerCase().match(
|
||||
new RegExp ( ( strict ? '^ ' + class_name + ' $' :
|
||||
'^.* ' + class_name + ' .*$' ).toLowerCase(),'g' ) ) ) {
|
||||
ret_obj[j++] = all_obj[i];
|
||||
}
|
||||
}
|
||||
return ret_obj;
|
||||
}
|
||||
|
||||
var previousBalloon;
|
||||
var currentBalloon;
|
||||
var timeoutId;
|
||||
var timeoutIdPrevious;
|
||||
|
||||
function makeBalloonHelp() {
|
||||
if (!document.createElement) return;
|
||||
var tagsHelp = new Array('tr', 'div');
|
||||
for (var i=0; i<tagsHelp.length; i++) {
|
||||
var tags = document.getElementsByTagName(tagsHelp[i]);
|
||||
for (var tagi=0; tagi<tags.length; tagi++) {
|
||||
tag = tags[tagi];
|
||||
if (tag.className.indexOf('row') > -1) {
|
||||
processElemForm(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uls = document.getElementsByTagName("ul");
|
||||
for (var uli=0; uli<uls.length; uli++) {
|
||||
ul = uls[uli];
|
||||
if (ul.nodeName == "UL" && ul.className == "appointment-details") {
|
||||
processAppointment(ul);
|
||||
}
|
||||
var tags = document.getElementsByClassName('tooltip');
|
||||
for (var i=0; i<tags.length; i++) {
|
||||
tag = tags[i];
|
||||
if (tag.id.substring(0, 3) != 'for' ) continue;
|
||||
tag.style.display = 'none';
|
||||
tag.style.visibility = 'visible';
|
||||
parentTag = document.getElementById(tag.id.substring(4, tag.id.length));
|
||||
if (! parentTag) continue;
|
||||
if (parentTag.childNodes.length == 1 &&
|
||||
parentTag.childNodes[0].nodeType != 3)
|
||||
parentTag = parentTag.childNodes[0]
|
||||
parentTag.balloonHelp = tag;
|
||||
addEvent(parentTag, "mouseover", showBalloonHelp);
|
||||
addEvent(parentTag, "focus", showBalloonHelp);
|
||||
addEvent(parentTag, "mouseout", hideBalloonHelp);
|
||||
addEvent(parentTag, "blur", hideBalloonHelp);
|
||||
addEvent(parentTag, "keydown", hideBalloonHelp);
|
||||
}
|
||||
}
|
||||
|
||||
function prepareTag(elem, text) {
|
||||
addEvent(elem, "mouseover", showBalloonHelp);
|
||||
addEvent(elem, "mouseout", hideBalloonHelp);
|
||||
addEvent(elem, "focus", showBalloonHelp);
|
||||
addEvent(elem, "blur", hideBalloonHelp);
|
||||
addEvent(elem, "keydown", hideBalloonHelp);
|
||||
elem.setAttribute("balloon-help", text);
|
||||
}
|
||||
|
||||
function processElemForm(elem) {
|
||||
if (!elem.childNodes || elem.childNodes.length == 0) return;
|
||||
var s = "";
|
||||
for (var itemi=0;itemi<elem.childNodes.length;itemi++) {
|
||||
var item = elem.childNodes[itemi];
|
||||
if (item.nodeType == 3) continue;
|
||||
if (item.className.indexOf("field-description") > -1) {
|
||||
s = item.innerHTML;
|
||||
if (onLabels == 1) {
|
||||
t = 0;
|
||||
while (elem.childNodes[t].nodeType == 3) t++;
|
||||
item = elem.childNodes[t];
|
||||
if (item.childNodes[0].nodeType != 3) {
|
||||
item = item.childNodes[0];
|
||||
}
|
||||
prepareTag(item, s);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (item.className.indexOf("field-value") > -1 ||
|
||||
item.className.indexOf("cell") > -1) {
|
||||
if (s == "") continue;
|
||||
var tagsArray = new Array('select', 'textarea', 'input');
|
||||
for (var i=0; i<tagsArray.length; i++) {
|
||||
tags = item.getElementsByTagName(tagsArray[i]);
|
||||
for (var tagi=0; tagi<tags.length; tagi++) {
|
||||
tag = tags[tagi];
|
||||
prepareTag(tag, s);
|
||||
}
|
||||
if ( tags.length > 0 ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processAppointment(elem) {
|
||||
if (!elem.childNodes || elem.childNodes.length == 0) return;
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
/* Utility functions */
|
||||
|
||||
function addEvent(obj, evType, fn) {
|
||||
/* adds an eventListener for browsers which support it
|
||||
Written by Scott Andrew: nice one, Scott */
|
||||
/* adds an eventListener for browsers which support it.
|
||||
Derived from snippet by Scott Andrew */
|
||||
if (obj.addEventListener) {
|
||||
obj.addEventListener(evType, fn, true);
|
||||
return true;
|
||||
} else if (obj.attachEvent) {
|
||||
var r = obj.attachEvent("on"+evType, fn);
|
||||
return r;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (obj.attachEvent)
|
||||
return obj.attachEvent("on"+evType, fn);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function showBalloonHelp(e) {
|
||||
if (!document.getElementsByTagName) return;
|
||||
if (window.event && window.event.srcElement) {
|
||||
el = window.event.srcElement
|
||||
} else if (e && e.target) {
|
||||
el = e.target
|
||||
}
|
||||
if (!el) return;
|
||||
if (el.nodeType == 3) {
|
||||
// lnk is a textnode -- ascend parents until we hit an input
|
||||
el = getParent(el, "INPUT");
|
||||
|
||||
while (! el.balloonHelp ) {
|
||||
el = el.parentNode;
|
||||
}
|
||||
if (!el) return;
|
||||
balloonHelp = el.getAttribute("balloon-help");
|
||||
tag = el.balloonHelp;
|
||||
|
||||
if (CURRENT_BALLOON_HELP) hideBalloonHelp(e);
|
||||
if (currentBalloon && tag != currentBalloon)
|
||||
hideBalloonHelp();
|
||||
|
||||
var d = document.createElement("div");
|
||||
d.className = "balloon-help";
|
||||
tnt = document.createTextNode(balloonHelp);
|
||||
pat = document.createElement("p");
|
||||
pat.appendChild(tnt);
|
||||
d.appendChild(pat);
|
||||
if (tag == previousBalloon)
|
||||
return;
|
||||
|
||||
STD_WIDTH = 300;
|
||||
w = balloonHelp.length * 10;
|
||||
if (w > STD_WIDTH) {
|
||||
w = STD_WIDTH;
|
||||
}
|
||||
|
||||
d.style.width = w + 'px';
|
||||
|
||||
mx = findPosX(el);
|
||||
my = findPosY(el);
|
||||
|
||||
d.style.left = (mx+15) + 'px';
|
||||
d.style.top = (my+25) + 'px';
|
||||
|
||||
if (document.body && document.body.offsetWidth && ((mx+w) > document.body.offsetWidth)) {
|
||||
d.style.left = (document.body.offsetWidth - w - 20) + "px";
|
||||
}
|
||||
|
||||
document.getElementsByTagName("body")[0].appendChild(d);
|
||||
|
||||
CURRENT_BALLOON_HELP = d;
|
||||
tag.style.display = 'block';
|
||||
|
||||
currentBalloon = tag;
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout('hideBalloonHelp()', 3000);
|
||||
}
|
||||
|
||||
function hideBalloonHelp(e) {
|
||||
if (!document.getElementsByTagName) return;
|
||||
if (CURRENT_BALLOON_HELP) {
|
||||
document.getElementsByTagName("body")[0].removeChild(CURRENT_BALLOON_HELP);
|
||||
CURRENT_BALLOON_HELP = null;
|
||||
if (currentBalloon) {
|
||||
currentBalloon.style.display = 'none';
|
||||
previousBalloon = currentBalloon;
|
||||
currentBalloon = null;
|
||||
clearTimeout(timeoutIdPrevious);
|
||||
timeoutIdPrevious = setTimeout('clearPrevious()', 5000);
|
||||
}
|
||||
}
|
||||
|
||||
// Add an eventListener to browsers that can do it somehow.
|
||||
// Originally by the amazing Scott Andrew.
|
||||
function addEvent(obj, evType, fn) {
|
||||
if (obj.addEventListener) {
|
||||
obj.addEventListener(evType, fn, true);
|
||||
return true;
|
||||
} else if (obj.attachEvent) {
|
||||
var r = obj.attachEvent("on"+evType, fn);
|
||||
return r;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getParent(el, pTagName) {
|
||||
if (el == null) return null;
|
||||
|
||||
if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())
|
||||
// Gecko bug, supposed to be uppercase
|
||||
return el;
|
||||
|
||||
return getParent(el.parentNode, pTagName);
|
||||
}
|
||||
|
||||
function findPosX(obj)
|
||||
{
|
||||
var curleft = 0;
|
||||
if (obj.offsetParent) {
|
||||
while (obj.offsetParent) {
|
||||
curleft += obj.offsetLeft
|
||||
obj = obj.offsetParent;
|
||||
}
|
||||
}
|
||||
else if (obj.x)
|
||||
curleft += obj.x;
|
||||
return curleft;
|
||||
}
|
||||
|
||||
function findPosY(obj)
|
||||
{
|
||||
var curtop = 0;
|
||||
if (obj.offsetParent) {
|
||||
while (obj.offsetParent) {
|
||||
curtop += obj.offsetTop
|
||||
obj = obj.offsetParent;
|
||||
}
|
||||
}
|
||||
else if (obj.y)
|
||||
curtop += obj.y;
|
||||
return curtop;
|
||||
function clearPrevious(e) {
|
||||
previousBalloon = null;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,22 +84,26 @@ def index():
|
|||
import re
|
||||
for article in articles.values():
|
||||
if article.format == 'spip':
|
||||
links = [x[10:].strip() for x in re.findall(r'->article +\d+', article.body)]
|
||||
links = [x[10:].strip() for x in re.findall(r'->article +\d+',
|
||||
article.body)]
|
||||
for l in links:
|
||||
id = '%s/articles/%s' % (dispatcherId, l)
|
||||
d[id] = 1
|
||||
links = [x[8:].strip() for x in re.findall(r'->alias +[\w\-_]+', article.body)]
|
||||
links = [x[8:].strip() for x in re.findall(r'->alias +[\w\-_]+',
|
||||
article.body)]
|
||||
for l in links:
|
||||
if not pagenames.has_key(l):
|
||||
print 'Wrong pagename: %s' % l
|
||||
continue
|
||||
d[pagenames[l]] = 1
|
||||
elif article.format == 'rst':
|
||||
links = [x[10:].strip() for x in re.findall(r'<article +\d+', article.body)]
|
||||
links = [x[10:].strip() for x in re.findall(r'<article +\d+',
|
||||
article.body)]
|
||||
for l in links:
|
||||
id = '%s/articles/%s' % (dispatcherId, l)
|
||||
d[id] = 1
|
||||
links = [x[8:].strip() for x in re.findall(r'<alias +[\w\-_]+', article.body)]
|
||||
links = [x[8:].strip() for x in re.findall(r'<alias +[\w\-_]+',
|
||||
article.body)]
|
||||
for l in links:
|
||||
if not pagenames.has_key(l):
|
||||
# print 'Wrong pagename: %s' % l
|
||||
|
|
13
make-system
13
make-system
|
@ -9,7 +9,7 @@ then
|
|||
fi
|
||||
|
||||
echo "Installing glasnost://system environment in root-system/"
|
||||
make config-system install \
|
||||
rm config && make config config-system install \
|
||||
GLASNOST=glasnost-system PORT=8500 \
|
||||
PREFIX=`pwd`/root-system/usr/local \
|
||||
VARPREFIX=`pwd`/root-system/var/lib/ \
|
||||
|
@ -18,7 +18,16 @@ make config-system install \
|
|||
SERVER_USER=`id -u` SERVER_GROUP=`id -u` \
|
||||
WEB_USER=`id -u` WEB_GROUP=`id -u` &> /dev/null
|
||||
|
||||
$ROOT_SBIN/glasnost-system-ctl start
|
||||
SERVERS="Dispatcher ArticlesServer AuthenticationServer \
|
||||
AuthenticationLoginPasswordServer CardsServer DataflowsServer \
|
||||
GroupsServer PeopleServer VirtualHostsServer UploadFilesServer \
|
||||
PageNamesServer TranslationsServer"
|
||||
echo "Starting Glasnost servers..."
|
||||
for SERVER in $SERVERS
|
||||
do
|
||||
$ROOT_SBIN/glasnost-system-ctl start-one $SERVER
|
||||
done
|
||||
|
||||
(cd tmp-system && ./generate-system.py) < /dev/null
|
||||
$ROOT_SBIN/glasnost-system-ctl stop
|
||||
|
||||
|
|
14
make-tests
14
make-tests
|
@ -8,7 +8,7 @@ fi
|
|||
|
||||
echo "Installing test environment in root-tests/"
|
||||
rm -rf root-tests && mkdir root-tests 2> /dev/null
|
||||
make config-tests install \
|
||||
rm config && make config config-tests install \
|
||||
GLASNOST=glasnost-tests PORT=8500 \
|
||||
PREFIX=`pwd`/root-tests/usr/local \
|
||||
VARPREFIX=`pwd`/root-tests/var/lib/ \
|
||||
|
@ -17,7 +17,15 @@ make config-tests install \
|
|||
SERVER_USER=`id -u` SERVER_GROUP=`id -u` \
|
||||
WEB_USER=`id -u` WEB_GROUP=`id -u` &> /dev/null
|
||||
|
||||
root-tests/usr/local/sbin/glasnost-tests-ctl start
|
||||
(cd tmp-tests && ./launch.py $1)
|
||||
SERVERS="Dispatcher ArticlesServer AtomsServer AuthenticationServer \
|
||||
AuthenticationLoginPasswordServer CardsServer DataflowsServer \
|
||||
GroupsServer PeopleServer VirtualHostsServer"
|
||||
echo "Starting Glasnost servers..."
|
||||
for SERVER in $SERVERS
|
||||
do
|
||||
root-tests/usr/local/sbin/glasnost-tests-ctl start-one $SERVER
|
||||
done
|
||||
|
||||
(cd tmp-tests && python ./tests.py)
|
||||
root-tests/usr/local/sbin/glasnost-tests-ctl stop
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -174,6 +174,9 @@ class AppointmentsServer(AppointmentsCommonMixin, ObjectsServer):
|
|||
|
||||
def addObjectXmlRpc(self, objectImport):
|
||||
objectId = ObjectsServer.addObjectXmlRpc(self, objectImport)
|
||||
return objectId
|
||||
|
||||
# TODO: proper notification email
|
||||
virtualServerId = context.getVar('applicationId')
|
||||
virtualServer = self.getVirtualServer(virtualServerId)
|
||||
object = virtualServer.loadObjectCore(objectId)
|
||||
|
|
|
@ -74,7 +74,9 @@ class VcfParser(saxlib.XMLReader) :
|
|||
if m :
|
||||
vobjname = m.group(1)
|
||||
if self._handle_namespaces:
|
||||
self._cont_handler.startElementNS((EMPTY_NAMESPACE,vobjname),vobjname,AttributesNSImpl({},{}))
|
||||
self._cont_handler.startElementNS(
|
||||
(EMPTY_NAMESPACE, vobjname),
|
||||
vobjname, AttributesNSImpl({}, {}))
|
||||
else:
|
||||
self._cont_handler.startElement(vobjname,AttributesImpl({}))
|
||||
|
||||
|
@ -83,7 +85,8 @@ class VcfParser(saxlib.XMLReader) :
|
|||
if m :
|
||||
vobjname = m.group(1)
|
||||
if self._handle_namespaces:
|
||||
self._cont_handler.endElementNS((EMPTY_NAMESPACE,vobjname),vobjname)
|
||||
self._cont_handler.endElementNS(
|
||||
(EMPTY_NAMESPACE, vobjname), vobjname)
|
||||
else:
|
||||
self._cont_handler.endElement(vobjname)
|
||||
else :
|
||||
|
@ -113,13 +116,15 @@ class VcfParser(saxlib.XMLReader) :
|
|||
attrs[(EMPTY_NAMESPACE,'x-name')] = propname
|
||||
propname = 'extension'
|
||||
|
||||
propvalue = unicode(to_xml_string(propvalue,'iso-8859-1'),'UTF-8')
|
||||
# <=> to the above line, but doesn't work with python
|
||||
# versions <2.0
|
||||
#propvalue = unicode(propvalue,'iso-8859-1')
|
||||
self._cont_handler.startElementNS((EMPTY_NAMESPACE,propname),propname,AttributesNSImpl(attrs,qnames))
|
||||
propvalue = unicode(propvalue, 'iso-8859-1')
|
||||
|
||||
self._cont_handler.startElementNS(
|
||||
(EMPTY_NAMESPACE, propname),
|
||||
propname, AttributesNSImpl(attrs, qnames))
|
||||
self._cont_handler.characters(propvalue)
|
||||
self._cont_handler.endElementNS((EMPTY_NAMESPACE,propname),propname)
|
||||
self._cont_handler.endElementNS(
|
||||
(EMPTY_NAMESPACE, propname),
|
||||
propname)
|
||||
data = nextLine
|
||||
file.close()
|
||||
|
||||
|
@ -128,20 +133,23 @@ class VcfParser(saxlib.XMLReader) :
|
|||
return self._handle_namespaces
|
||||
elif name == saxlib.feature_namespace_prefixes:
|
||||
return 0
|
||||
raise saxlib.SAXNotRecognizedException("Feature '%s' not recognized" % name)
|
||||
raise saxlib.SAXNotRecognizedException(
|
||||
"Feature '%s' not recognized" % name)
|
||||
|
||||
def setFeature(self, name, value):
|
||||
if name == saxlib.feature_namespaces:
|
||||
self._handle_namespaces = value
|
||||
else:
|
||||
raise saxlib.SAXNotRecognizedException("Feature '%s' not recognized" % name)
|
||||
raise saxlib.SAXNotRecognizedException(
|
||||
"Feature '%s' not recognized" % name)
|
||||
|
||||
def getProperty(self, name):
|
||||
if name == saxlib.property_lexical_handler:
|
||||
return self._lex_handler
|
||||
elif name == saxlib.property_declaration_handler:
|
||||
return self._decl_handler
|
||||
raise saxlib.SAXNotRecognizedException("Property '%s' not recognized" % name)
|
||||
raise saxlib.SAXNotRecognizedException(
|
||||
"Property '%s' not recognized" % name)
|
||||
|
||||
def setProperty(self, name, value):
|
||||
if name == saxlib.property_lexical_handler:
|
||||
|
@ -149,73 +157,6 @@ class VcfParser(saxlib.XMLReader) :
|
|||
elif name == saxlib.property_declaration_handler:
|
||||
self._decl_handler = value
|
||||
else:
|
||||
raise saxlib.SAXNotRecognizedException("Property '%s' not recognized" % name)
|
||||
raise saxlib.SAXNotRecognizedException(
|
||||
"Property '%s' not recognized" % name)
|
||||
|
||||
xslt = '''<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
|
||||
<xsl:output method="text" encoding="ISO-8859-1"/>
|
||||
<xsl:strip-space elements='*'/>
|
||||
|
||||
<xsl:template match='/VCALENDAR'>BEGIN:VCALENDAR
|
||||
<xsl:apply-templates/>END:VCALENDAR
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match='VEVENT'>BEGIN:VEVENT
|
||||
<xsl:apply-templates/>END:VEVENT
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match='VTODO'>BEGIN:VTODO
|
||||
<xsl:apply-templates/>END:VTODO
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match='*[text()]'>
|
||||
<xsl:choose>
|
||||
<xsl:when test='name()="extension"'>
|
||||
<xsl:value-of select='@x-name'/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select='name()'/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:apply-templates select='@*[name()!="x-name"]'/>:<xsl:value-of select='text()'/><xsl:text>
|
||||
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match='@*'>;<xsl:value-of select='name()'/>=<xsl:value-of select='.'/></xsl:template>
|
||||
|
||||
</xsl:transform>'''
|
||||
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
# VCalendar file to DOM
|
||||
def load_vcal_to_dom(uri) :
|
||||
parser=VcfParser()
|
||||
reader = Sax2.Reader(0, 0, None, Sax2.XmlDomGenerator, parser)
|
||||
return reader.fromUri(uri)
|
||||
|
||||
# DOM to VCalendar file
|
||||
def write_dom_to_vcal(doc, uri):
|
||||
new_api = 0
|
||||
try:
|
||||
from Ft.Xml.Xslt.Processor import Processor
|
||||
try:
|
||||
from Ft.Xml.InputSource import InputSourceFactory,InputSource
|
||||
except:
|
||||
new_api = 1
|
||||
except:
|
||||
from xml.xslt.Processor import Processor
|
||||
processor = Processor()
|
||||
if not new_api:
|
||||
processor.appendStylesheetString(xslt)
|
||||
result = processor.runNode(doc,1,{},None)
|
||||
else:
|
||||
self.inputsourcefactory = InputSourceFactory()
|
||||
self.processor.appendStylesheet(self.inputsourcefactory.fromString(
|
||||
xslt, 'dummy'))
|
||||
dom = self.processor.execute(doc,InputSource(None,"dummy"), 1, {},
|
||||
None)
|
||||
file = open(uri, 'w')
|
||||
file.write(result)
|
||||
file.close()
|
||||
|
|
|
@ -163,7 +163,7 @@ class AuthenticationLoginPasswordVirtualServer(AdministrableVirtualServer):
|
|||
del self.authentications
|
||||
self.markCoreAsDirty()
|
||||
return
|
||||
raise faults.WrongLogin(partialAccount[0])
|
||||
raise faults.WrongLogin(authenticationObject.login)
|
||||
|
||||
def emailAdminsForNewUser(self, object, authenticationObject):
|
||||
virtualServerId = context.getVar('applicationId')
|
||||
|
@ -209,12 +209,14 @@ For more information about this user, please see:
|
|||
def emailPasswordToUser(self, object, authenticationObject):
|
||||
emailAddress = getEmailForObject(object)
|
||||
if not emailAddress:
|
||||
print 'Not sending because no email address'
|
||||
return
|
||||
|
||||
if not self.getServer().getAdminCore().stockPasswordsInClearText:
|
||||
# TODO: mail user explaining we can generate a new password for
|
||||
# him and provide him with an url with a token (so that others
|
||||
# can't force password changes)
|
||||
print 'Not sending because passwords are not in plain text'
|
||||
return
|
||||
|
||||
toAddress = [emailAddress]
|
||||
|
@ -290,14 +292,20 @@ The Glasnost administrator - %(fromAddress)s
|
|||
result.append((userId, cleanedAuthObject.exportToXmlRpc()))
|
||||
return result
|
||||
|
||||
def getAccountUserId(self, authenticationObject):
|
||||
if not self.getServer().isAdmin():
|
||||
raise faults.UserAccessDenied()
|
||||
def getAccountUserIdPrivate(self, authenticationObject):
|
||||
if self.authentications is not None:
|
||||
for userId, authObject in self.authentications.items():
|
||||
if authObject.login == authenticationObject.login:
|
||||
return userId
|
||||
return ''
|
||||
|
||||
def getAccountUserId(self, authenticationObject):
|
||||
if not self.getServer().isAdmin():
|
||||
raise faults.UserAccessDenied()
|
||||
userId = self.getAccountUserIdPrivate(authenticationObject)
|
||||
if not userId:
|
||||
raise faults.WrongLogin(authenticationObject.login)
|
||||
return userId
|
||||
|
||||
def getAdminEmailAddresses(self, stopAsap = 0):
|
||||
virtualServerId = context.getVar('applicationId')
|
||||
|
@ -370,7 +378,7 @@ class AuthenticationLoginPasswordServer(
|
|||
authenticationObject = commonTools.importThing(authenticationDict)
|
||||
virtualServerId = context.getVar('applicationId')
|
||||
virtualServer = self.getVirtualServer(virtualServerId)
|
||||
userId = virtualServer.getAccountUserId(authenticationObject)
|
||||
userId = virtualServer.getAccountUserIdPrivate(authenticationObject)
|
||||
userObject = getObject(userId)
|
||||
virtualServer.emailPasswordToUser(userObject, authenticationObject)
|
||||
|
||||
|
|
|
@ -395,3 +395,4 @@ dispatcher = Dispatcher()
|
|||
|
||||
if __name__ == "__main__":
|
||||
dispatcher.launch(applicationName, applicationRole)
|
||||
|
||||
|
|
|
@ -115,8 +115,7 @@ class VirtualHost(ObjectServerMixin, VirtualHostCommon):
|
|||
def modify(self, changes, givenSlotNames = None):
|
||||
objectsByHostName = self.getServer().virtualServer.objectsByHostName
|
||||
hostName = self.hostName
|
||||
ObjectServerMixin.modify(
|
||||
self, changes, givenSlotNames = givenSlotNames)
|
||||
ObjectServerMixin.modify(self, changes, givenSlotNames = givenSlotNames)
|
||||
if self.hostName != hostName:
|
||||
if hostName is not None:
|
||||
del objectsByHostName[hostName]
|
||||
|
@ -229,13 +228,6 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
|
|||
def exportVirtualServer(self, virtualServerId, exportDirectoryPath):
|
||||
return None
|
||||
|
||||
def getDefaultVirtualHost(self):
|
||||
virtualServerId = context.getVar('applicationId')
|
||||
virtualServer = self.getVirtualServer(virtualServerId)
|
||||
if not virtualServer.admin.defaultVirtualHostId:
|
||||
raise faults.MissingItem('default virtual host')
|
||||
return self.getObjectXmlRpc(self.admin.defaultVirtualHostId)
|
||||
|
||||
def getHostNameXmlRpc(self):
|
||||
"""Return the url of the virtual server."""
|
||||
|
||||
|
@ -250,27 +242,37 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
|
|||
raise faults.MissingItem(dispatcherId)
|
||||
|
||||
def getObjectByHostName(self, hostName):
|
||||
"""Return the first virtual host with the given host name."""
|
||||
"""Return the virtual host with the given host name."""
|
||||
|
||||
virtualServerId = context.getVar('applicationId')
|
||||
virtualServer = self.getVirtualServer(virtualServerId)
|
||||
askedHostName = hostName
|
||||
if not virtualServer.objectsByHostName:
|
||||
# The is no virtual host defined. Create one with the requested
|
||||
# There is no virtual host defined. Create one with the requested
|
||||
# host name.
|
||||
object = commonTools.newThing(
|
||||
'object', 'virtualhosts.VirtualHost')
|
||||
object = commonTools.newThing('object', 'virtualhosts.VirtualHost')
|
||||
object.title = 'Glasnost'
|
||||
object.hostName = hostName
|
||||
object.defaultDispatcherId = 'glasnost://%s' % hostName
|
||||
object.language = 'en'
|
||||
self.addObjectXmlRpc(object.exportToXmlRpc())
|
||||
if not virtualServer.objectsByHostName.has_key(hostName):
|
||||
for k in virtualServer.objectsByHostName.keys():
|
||||
if fnmatch(hostName, k):
|
||||
# hostNames, without eventual www.
|
||||
hostNames = virtualServer.objectsByHostName.keys()
|
||||
hostNames.sort(lambda x,y: -cmp(len(x), len(y)))
|
||||
for k in hostNames:
|
||||
if fnmatch(hostName, '*.'+k):
|
||||
hostName = k
|
||||
break
|
||||
else:
|
||||
if not virtualServer.admin.defaultVirtualHostId:
|
||||
raise faults.MissingItem(hostName)
|
||||
try:
|
||||
object = virtualServer.objects[
|
||||
virtualServer.admin.defaultVirtualHostId]
|
||||
except KeyError:
|
||||
raise faults.MissingItem(hostName)
|
||||
return object
|
||||
object = virtualServer.objectsByHostName[hostName]
|
||||
return object
|
||||
|
||||
|
@ -292,14 +294,18 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
|
|||
return 0
|
||||
|
||||
def hasHostNameXmlRpc(self, hostName):
|
||||
# note that this method may return false while getObjectByHostName
|
||||
# returns something
|
||||
virtualServerId = context.getVar('applicationId')
|
||||
virtualServer = self.getVirtualServer(virtualServerId)
|
||||
hostName = iso8859_15(hostName)
|
||||
if virtualServer.objectsByHostName.has_key(hostName):
|
||||
return 1
|
||||
for k in virtualServer.objectsByHostName.keys():
|
||||
if fnmatch(hostName, k):
|
||||
return 1
|
||||
#hostNames = virtualServer.objectsByHostName.keys()
|
||||
#hostNames.sort(lambda x,y: -cmp(len(x), len(y)))
|
||||
#for k in hostNames:
|
||||
# if fnmatch(hostName, '*.'+k):
|
||||
# return 1
|
||||
return 0
|
||||
|
||||
def importVirtualServer(self, virtualServerId, importDirectoryPath):
|
||||
|
@ -317,8 +323,6 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
|
|||
def registerPublicMethods(self):
|
||||
ObjectsServer.registerPublicMethods(self)
|
||||
self.registerPublicMethod('getHostName', self.getHostNameXmlRpc)
|
||||
self.registerPublicMethod('getDefaultVirtualHost',
|
||||
self.getDefaultVirtualHost)
|
||||
self.registerPublicMethod('getObjectByHostName',
|
||||
self.getObjectByHostNameXmlRpc)
|
||||
self.registerPublicMethod('getObjectIdByHostName',
|
||||
|
@ -375,7 +379,7 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
|
|||
def updateApacheVHost(self, object):
|
||||
"""Update the apache virtual host configuration.
|
||||
|
||||
Get the apache config template from the vistual host server data
|
||||
Get the apache config template from the virtual host server data
|
||||
directory.
|
||||
Create the apache vhost files and fill them to add the given object as
|
||||
a new virtual host.
|
||||
|
@ -395,7 +399,7 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
|
|||
created.
|
||||
|
||||
*IOError*:
|
||||
The vhost file cannot be writen, or the templace config file cannot
|
||||
The vhost file cannot be written, or the template config file cannot
|
||||
be read.
|
||||
|
||||
"""
|
||||
|
|
|
@ -77,6 +77,7 @@ class AppointmentCommon(ObjectCommon):
|
|||
creationTime_kindName = 'CreationTime'
|
||||
|
||||
end = None
|
||||
end_kind_stateInViewMode = 'read-only/hidden-if-empty'
|
||||
end_kindName = 'Time'
|
||||
|
||||
participantsSet = None
|
||||
|
@ -112,34 +113,42 @@ class AppointmentCommon(ObjectCommon):
|
|||
result = ''
|
||||
return result
|
||||
|
||||
def getLabel(self):
|
||||
def getLabel(self, withDate = 0, withHour = 0):
|
||||
title = self.getTitle()
|
||||
if title is None:
|
||||
return ''
|
||||
hourTime = self.getBeginningHourAndMinute()
|
||||
if hourTime:
|
||||
when = '%s %s' % (
|
||||
time.strftime('%d/%m/%Y', time.localtime(self.start)),
|
||||
hourTime)
|
||||
else:
|
||||
when = time.strftime('%d/%m/%Y', time.localtime(self.start))
|
||||
dateTime = self.getDateTime(withDate, withHour)
|
||||
if dateTime:
|
||||
return '%s - %s' % (dateTime, title)
|
||||
return title
|
||||
|
||||
return '%s - %s' % (when, title)
|
||||
def getDateTime(self, withDate = 0, withHour = 0):
|
||||
hourTime = ''
|
||||
if withHour:
|
||||
hourTime = self.getBeginningHourAndMinute()
|
||||
|
||||
date = ''
|
||||
if withDate:
|
||||
date = time.strftime('%d/%m/%Y', time.localtime(self.start))
|
||||
|
||||
if not date and not hourTime:
|
||||
return ''
|
||||
return ' '.join([date, hourTime])
|
||||
|
||||
def getTitle(self):
|
||||
return self.title
|
||||
|
||||
def getBeginningHourAndMinute(self):
|
||||
"""Returns a string with the start time of the appointment (or None
|
||||
if no time set)"""
|
||||
"""Returns a string with the start time of the appointment (or an empty
|
||||
string if no time set)"""
|
||||
hour = '%02d:%02d' % time.localtime(self.start)[3:5]
|
||||
if hour == '00:00' and not self.end:
|
||||
return None
|
||||
return ''
|
||||
if self.end:
|
||||
hourEnd = '%02d:%02d' % time.localtime(self.end)[3:5]
|
||||
if hour == '00:00' and self.end - self.start < 86400 and \
|
||||
hourEnd == '23:59':
|
||||
return None
|
||||
return ''
|
||||
return hour
|
||||
|
||||
def getEndHourAndMinute(self):
|
||||
|
|
|
@ -98,6 +98,7 @@ class VirtualHostCommon(ObjectCommon):
|
|||
hostName_kind_isTranslatable = 0
|
||||
hostName_kind_label = N_('Web Host Name')
|
||||
hostName_kind_widget_size = 40
|
||||
hostName_kind_widgetName = 'Url'
|
||||
hostName_kindName = 'String'
|
||||
|
||||
modificationTime = None
|
||||
|
@ -109,6 +110,9 @@ class VirtualHostCommon(ObjectCommon):
|
|||
|
||||
serverRole = 'virtualhosts'
|
||||
|
||||
# TODO: everything so that it is editable by user
|
||||
showTooltips = 0 # FIXME: default should be true
|
||||
|
||||
templateDirectoryName = 'glasnost2'
|
||||
templateDirectoryName_kind_balloonHelp = N_(
|
||||
'Select the template (skin) to use for this host.')
|
||||
|
|
|
@ -138,6 +138,7 @@ class BaseThing:
|
|||
thingCategory = 'other'
|
||||
thingCategory_kind_importExport = 'private'
|
||||
thingCategory_kind_isRequiredInEditMode = 1
|
||||
thingCategory_kind_isTranslatable = 0
|
||||
thingCategory_kind_label = N_('Internal Category')
|
||||
thingCategory_kind_stateInEditMode = 'hidden'
|
||||
thingCategory_kind_stateInViewMode = 'hidden'
|
||||
|
@ -146,6 +147,7 @@ class BaseThing:
|
|||
thingName = None
|
||||
thingName_kind_importExport = 'private'
|
||||
thingName_kind_isRequiredInEditMode = 1
|
||||
thingName_kind_isTranslatable = 0
|
||||
thingName_kind_label = N_('Internal Name')
|
||||
thingName_kind_stateInEditMode = 'hidden'
|
||||
thingName_kind_stateInViewMode = 'hidden'
|
||||
|
|
|
@ -455,6 +455,19 @@ class aliasUrl(rootUrl):
|
|||
action = ''
|
||||
return '%s%s%s' % (path, self.alias, action)
|
||||
|
||||
class fileUrl(rootUrl):
|
||||
filename = None
|
||||
|
||||
def __init__(self, filename):
|
||||
rootUrl.__init__(self)
|
||||
self.filename = filename
|
||||
|
||||
def getPath(self, **keywords):
|
||||
path = rootUrl.getPath(self, **keywords)
|
||||
if path[-1] == '/' and self.filename[0] == '/':
|
||||
path = path[:-1]
|
||||
return path + self.filename
|
||||
|
||||
|
||||
class idUrl(rootUrl):
|
||||
action = None
|
||||
|
|
|
@ -400,13 +400,21 @@ def _callServer(serverAccessor, functionName, arguments):
|
|||
serverProxy = serverAccessor['serverProxy']
|
||||
try:
|
||||
result = apply(getattr(serverProxy, functionName), arguments)
|
||||
except socket.gaierror, exception:
|
||||
if exception[0] == -3: # Temporary failure in name resolution
|
||||
raise faults.UnknownDispatcherInId(serverAccessor['serverId'])
|
||||
raise
|
||||
except socket.error, exception:
|
||||
if exception[0] == 'host not found':
|
||||
if exception[0] == 'host not found': # FIXME: looks dubious
|
||||
raise faults.UnknownDispatcherInId(serverAccessor['serverId'])
|
||||
if exception[0] == 111:
|
||||
# Connection refused.
|
||||
# Connection refused
|
||||
raise faults.UnknownDispatcherInId(serverAccessor['serverId'])
|
||||
raise
|
||||
except socket.gaierror, exception:
|
||||
if exception[0] == -3:
|
||||
raise
|
||||
raise
|
||||
except xmlrpclib.ProtocolError, exception:
|
||||
if exception.errcode == 406:
|
||||
# Protocol Error: 406 Not Acceptable.
|
||||
|
|
|
@ -1160,8 +1160,7 @@ class ObjectsProxy(ObjectsCommonMixin, AdministrableProxyMixin, Proxy):
|
|||
multiCall = multiCall)
|
||||
|
||||
def getObjectLabelsTranslated(
|
||||
self, objectIds, destinationLanguages,
|
||||
serverId = None):
|
||||
self, objectIds, destinationLanguages, serverId = None):
|
||||
"""Get the objects labels in the specified languages.
|
||||
|
||||
Keyword Arguments:
|
||||
|
@ -1193,8 +1192,10 @@ class ObjectsProxy(ObjectsCommonMixin, AdministrableProxyMixin, Proxy):
|
|||
|
||||
multiCall = MultiCall()
|
||||
for objectId in objectIds:
|
||||
self.getObjectLabelAndLanguage(
|
||||
objectId, multiCall = multiCall)
|
||||
try:
|
||||
self.getObjectLabelAndLanguage(objectId, multiCall = multiCall)
|
||||
except faults.UnknownDispatcherInId:
|
||||
objectIds.remove(objectId)
|
||||
lazyLabelsAndLanguages = multiCall.call()
|
||||
labelsAndLanguages = {}
|
||||
for i in range(len(objectIds)):
|
||||
|
|
|
@ -90,15 +90,6 @@ class VirtualHostsProxy(VirtualHostsCommonMixin, ObjectsProxy):
|
|||
'canModifyObject',
|
||||
[serverId, getApplicationToken(), userToken, objectId])
|
||||
|
||||
def getDefaultVirtualHost(self, serverId = None):
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
serverId = self.getServerId(serverId = serverId)
|
||||
return callServer(
|
||||
serverId,
|
||||
'getDefaultVirtualHost',
|
||||
[serverId, getApplicationToken(), userToken],
|
||||
resultHandler = self.getObject_handleResult)
|
||||
|
||||
def getObjectByHostName(self, hostName, serverId = None):
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
|
||||
|
|
|
@ -109,6 +109,15 @@ class Appointment(ObjectWebMixin, Appointment):
|
|||
group = groupsProxy.getObject(admin.categoriesGroupId)
|
||||
return group.membersSet
|
||||
|
||||
def getLabelTranslated(self, destinationLanguages = None, multiCall = None,
|
||||
withDate = 0, withHour = 0):
|
||||
label = ObjectWebMixin.getLabelTranslated(self, destinationLanguages,
|
||||
multiCall)
|
||||
dateTime = self.getDateTime(withDate, withHour)
|
||||
if dateTime:
|
||||
return '%s - %s' % (dateTime, label)
|
||||
return label
|
||||
|
||||
def getSlotNames(self, parentSlot = None):
|
||||
slotNames = _Appointment.getSlotNames(self, parentSlot = parentSlot)
|
||||
admin = self.getWeb().getAdmin()
|
||||
|
@ -148,12 +157,11 @@ DTEND:%sT235900""" % (date, date) )
|
|||
|
||||
s.append('END:VEVENT\n')
|
||||
return '\n'.join(s)
|
||||
|
||||
register(Appointment)
|
||||
|
||||
|
||||
def weekNumberToDate(year, weekNumber):
|
||||
jan4thSecs = time.mktime((year, 1, 4, 0, 0, 0, 0, 0, time.localtime()[-1]))
|
||||
jan4thSecs = time.mktime((year, 1, 4, 0, 0, 0, 0, 0, 0))
|
||||
secondsSinceJan4th = jan4thSecs + (weekNumber-1)*7*24*60*60
|
||||
weekTuple = time.localtime(secondsSinceJan4th)
|
||||
daysToAdd = - weekTuple[6]
|
||||
|
@ -163,14 +171,14 @@ def weekNumberToDate(year, weekNumber):
|
|||
|
||||
|
||||
def dateToWeekNumber(year, month, day):
|
||||
janFirstSecs = time.mktime((year, 1, 1, 0, 0, 0, 0, 0, time.localtime()[-1]))
|
||||
janFirstSecs = time.mktime((year, 1, 1, 0, 0, 0, 0, 0, 0))
|
||||
janFirstTuple = time.localtime(janFirstSecs)
|
||||
if janFirstTuple[6] < 4:
|
||||
week0Secs = janFirstSecs - janFirstTuple[6]*24*60*60
|
||||
else:
|
||||
week0Secs = janFirstSecs + (7-janFirstTuple[6])*24*60*60
|
||||
|
||||
secondsSinceEpoch = time.mktime((year, month, day, 0, 0, 0, 0, 0, time.localtime()[-1]))
|
||||
secondsSinceEpoch = time.mktime((year, month, day, 0, 0, 0, 0, 0, 0))
|
||||
diffSecs = secondsSinceEpoch - week0Secs
|
||||
weekNumber, mod = divmod(diffSecs, 7*24*60*60)
|
||||
weekNumber = int(weekNumber) + 1
|
||||
|
@ -184,7 +192,42 @@ def dateToWeekNumber(year, month, day):
|
|||
class AppointmentsWeb(ObjectsWebMixin, AppointmentsProxy):
|
||||
|
||||
def agenda(self):
|
||||
return ObjectsWebMixin.viewAll(self)
|
||||
now = time.time()
|
||||
objects = self.getObjects().values()
|
||||
|
||||
pastObjects = [x for x in objects if x.start < now]
|
||||
pastObjects.sort(lambda x,y: -cmp(x.start, y.start))
|
||||
|
||||
futureObjects = [x for x in objects if x.start > now]
|
||||
futureObjects.sort(lambda x,y: cmp(x.start, y.start))
|
||||
|
||||
layout = X.array()
|
||||
|
||||
if futureObjects:
|
||||
table = X.table(_class = 'objects-table')
|
||||
table += X.tr(
|
||||
X.th(_('Date')),
|
||||
X.th(_('Label')))
|
||||
for object in futureObjects:
|
||||
table += X.tr(
|
||||
X.td(object.getDateTime(withDate = 1, withHour = 1)),
|
||||
X.td(X.objectHypertextLabel(object.id)))
|
||||
layout += X.h2(_('Future events'))
|
||||
layout += table
|
||||
|
||||
if pastObjects:
|
||||
table = X.table(_class = 'objects-table')
|
||||
table += X.tr(
|
||||
X.th(_('Date')),
|
||||
X.th(_('Label')))
|
||||
for object in pastObjects:
|
||||
table += X.tr(
|
||||
X.td(object.getDateTime(withDate = 1, withHour = 1)),
|
||||
X.td(X.objectHypertextLabel(object.id)))
|
||||
layout += X.h2(_('Past events'))
|
||||
layout += table
|
||||
|
||||
return writePageLayout(layout, _('Agenda'))
|
||||
agenda.isPublicForWeb = 1
|
||||
|
||||
def day(self, year, month, day):
|
||||
|
@ -246,7 +289,7 @@ class AppointmentsWeb(ObjectsWebMixin, AppointmentsProxy):
|
|||
ul = X.ul()
|
||||
hourAppointments.sort(lambda x,y: cmp(x.start, y.start))
|
||||
for d in hourAppointments:
|
||||
ul += X.li(X.a(href = X.idUrl(d.id))(d.getLabel()))
|
||||
ul += X.li(X.a(href = X.idUrl(d.id))(d.getLabelTranslated()))
|
||||
hourContent += ul
|
||||
className = ''
|
||||
if len(hourAppointments):
|
||||
|
@ -471,10 +514,11 @@ class AppointmentsWeb(ObjectsWebMixin, AppointmentsProxy):
|
|||
className += ' busy'
|
||||
app = dayAppointments[0]
|
||||
dayContent = X.a(href = X.idUrl(app.id),
|
||||
title = app.getLabel())(dayLabel)
|
||||
title = app.getLabelTranslated(withHour = 1))(
|
||||
dayLabel)
|
||||
else:
|
||||
className += ' busy'
|
||||
title = ', '.join([x.getLabel() for x in dayAppointments])
|
||||
title = ', '.join([x.getLabelTranslated() for x in dayAppointments])
|
||||
dayContent = X.a(
|
||||
href = '/%s/day/%d/%d/%d' % (
|
||||
self.serverRole, year, month, d),
|
||||
|
@ -578,7 +622,7 @@ class AppointmentsWeb(ObjectsWebMixin, AppointmentsProxy):
|
|||
disp, role, id = splitObjectId(d.id)
|
||||
idAttribute = 'appointment-%s-%s' % (disp, id)
|
||||
li += X.a(href = X.idUrl(d.id), id = idAttribute)(
|
||||
d.getLabel())
|
||||
d.getLabelTranslated(withHour = 1))
|
||||
details = X.ul(_class = 'appointment-details tooltip',
|
||||
id = 'for-' + idAttribute)
|
||||
start = d.getBeginningHourAndMinute()
|
||||
|
@ -589,7 +633,9 @@ class AppointmentsWeb(ObjectsWebMixin, AppointmentsProxy):
|
|||
if d.body:
|
||||
details += X.li(d.body)
|
||||
hasDetails = 1
|
||||
if hasDetails:
|
||||
if hasDetails and \
|
||||
context.getVar('virtualHost').showTooltips:
|
||||
webTools.addContextualHeader('tooltips.js')
|
||||
li += details
|
||||
ul += li
|
||||
dayContent += ul
|
||||
|
@ -639,7 +685,7 @@ class AppointmentsWeb(ObjectsWebMixin, AppointmentsProxy):
|
|||
ul += X.li(monthLink)
|
||||
if not 'year' in exclude:
|
||||
ul += X.li(yearLink)
|
||||
return ul
|
||||
return X.array(ul, self.getViewAllButtonsBarLayout())
|
||||
|
||||
def submitAddObject(self, object, **keywords):
|
||||
result = ObjectsWebMixin.submitAddObject(self, object, **keywords)
|
||||
|
|
|
@ -69,8 +69,7 @@ class Article(ObjectWebMixin, Article):
|
|||
body_kind_widget_preview = 1
|
||||
body_kind_widgetName = 'TextArea'
|
||||
|
||||
editionTime_kind_defaultValue = 'now'
|
||||
editionTime_kind_stateInEditMode = 'read-only'
|
||||
editionTime_kind_stateInEditMode = 'hidden'
|
||||
editionTime_kind_widget_fieldLabel = N_('Edition Time')
|
||||
editionTime_kind_widgetName = 'InputText'
|
||||
|
||||
|
@ -187,7 +186,8 @@ class Article(ObjectWebMixin, Article):
|
|||
if 'body' in slotNames:
|
||||
slotNames.remove('body')
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
if not userToken or context.getVar('useCompactLayout', default = 0):
|
||||
if context.getVar('useCompactLayout', default = 0) or \
|
||||
not self.getWeb().canModifyObject(self.id):
|
||||
for slotName in (
|
||||
'authorsSet', 'creationTime', 'editionTime', 'format',
|
||||
'lastEditorId', 'modificationTime', 'readersSet', 'title',
|
||||
|
|
|
@ -185,7 +185,8 @@ class AuthenticationLibertyAllianceWeb(WebMixin,
|
|||
del keywords['tokenId']
|
||||
|
||||
from Provider.ServiceProvider import ServiceProvider
|
||||
sp = ServiceProvider('localhost', 8089, 8090, SOAPEndpoint = 'http://localhost/soapEndPoint.html')
|
||||
sp = ServiceProvider('localhost', 8089, 8090,
|
||||
SOAPEndpoint = 'http://localhost/soapEndPoint.html')
|
||||
authnResponse = sp.getAuthnResponseFromEmbeddedUrl(keywords)
|
||||
|
||||
authWeb = getWebForServerRole('authentication')
|
||||
|
@ -207,7 +208,8 @@ class AuthenticationLibertyAllianceWeb(WebMixin,
|
|||
keywords = {}
|
||||
|
||||
from Provider.ServiceProvider import ServiceProvider
|
||||
sp = ServiceProvider('localhost', 8089, 8090, SOAPEndpoint = 'http://localhost/soapEndPoint.html')
|
||||
sp = ServiceProvider('localhost', 8089, 8090,
|
||||
SOAPEndpoint = 'http://localhost/soapEndPoint.html')
|
||||
authnRequest = sp.getNewAuthnRequest()
|
||||
embeddedAuthnRequest = authnRequest.exportToEmbeddedUrl()
|
||||
response = idpUrl+'?'+embeddedAuthnRequest
|
||||
|
|
|
@ -77,11 +77,14 @@ class AccountLoginPassword(BaseObjectWebMixin, AccountLoginPassword):
|
|||
def getEditLayoutSlotNames(self, fields, parentSlot = None):
|
||||
slotNames = BaseObjectWebMixin.getEditLayoutSlotNames(self,
|
||||
fields, parentSlot = parentSlot)
|
||||
if context.getVar('authMode') != 'login':
|
||||
slotNames.remove('password')
|
||||
return slotNames
|
||||
register(AccountLoginPassword)
|
||||
|
||||
class LoginAccountLoginPassword(BaseObjectWebMixin, AccountLoginPassword):
|
||||
login_kind_balloonHelp = N_('Enter the username you use on this site.')
|
||||
password_kind_balloonHelp = N_('Enter your password.')
|
||||
register(LoginAccountLoginPassword)
|
||||
|
||||
class ChangingPassword(BaseObjectWebMixin, ObjectCommon):
|
||||
id_kindName = None
|
||||
|
@ -123,6 +126,7 @@ class ChangingPassword(BaseObjectWebMixin, ObjectCommon):
|
|||
return slotNames
|
||||
|
||||
|
||||
|
||||
class ChangingUserPassword(BaseObjectWebMixin, ObjectCommon):
|
||||
id_kindName = None
|
||||
language_kindName = None
|
||||
|
@ -284,6 +288,8 @@ class AuthenticationLoginPasswordWeb(WebMixin,
|
|||
changePassword.isPublicForWeb = 1
|
||||
|
||||
def changePasswordSubmit(self, **keywords):
|
||||
if not context.getVar('userToken'):
|
||||
return accessForbidden()
|
||||
admin = self.getAdmin()
|
||||
if not admin.userCanChoosePassword:
|
||||
return accessForbidden(dontAskForLogin = 1)
|
||||
|
@ -322,7 +328,7 @@ class AuthenticationLoginPasswordWeb(WebMixin,
|
|||
|
||||
return success(
|
||||
_('The password has been modified successfully.'),
|
||||
X.url('/'))
|
||||
X.rootUrl())
|
||||
changePasswordSubmit.isPublicForWeb = 1
|
||||
|
||||
|
||||
|
@ -468,12 +474,11 @@ class AuthenticationLoginPasswordWeb(WebMixin,
|
|||
req.headers_out['Pragma'] = 'no-cache'
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
authObject = self.newAuthenticationObject()
|
||||
authObject = LoginAccountLoginPassword()
|
||||
if not again:
|
||||
authObject.initFields(keywords)
|
||||
authObject.repairFields(keywords)
|
||||
context.push(_level = 'index', layoutMode = 'edit',
|
||||
authMode = 'login')
|
||||
context.push(_level = 'index', layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
if access == 'forbidden':
|
||||
|
@ -575,8 +580,7 @@ class AuthenticationLoginPasswordWeb(WebMixin,
|
|||
authObject.repairFields(keywords)
|
||||
|
||||
|
||||
context.push(_level = 'index', layoutMode = 'edit',
|
||||
authMode = 'newAccount')
|
||||
context.push(_level = 'index', layoutMode = 'edit')
|
||||
|
||||
try:
|
||||
layout = X.array()
|
||||
|
@ -584,17 +588,6 @@ class AuthenticationLoginPasswordWeb(WebMixin,
|
|||
method = 'post')
|
||||
layout += form
|
||||
|
||||
#context.push(_level = 'edit', layoutMode = 'edit')
|
||||
|
||||
#widget = slot.getWidget()
|
||||
#form += widget.getModelPageBodyLayout(userCardSlot, keywords)
|
||||
|
||||
#slot = slots.Root(authObject)
|
||||
#widget = slot.getWidget()
|
||||
#form += widget.getModelPageBodyLayout(slot, keywords)
|
||||
|
||||
#context.pull()
|
||||
|
||||
form += userCardObject.getEditLayout(
|
||||
keywords, parentSlot = userCardSlot)
|
||||
form += authObject.getEditLayout(keywords)
|
||||
|
|
|
@ -269,7 +269,8 @@ class ForumsWeb(ObjectsWebMixin, ForumsProxy):
|
|||
comment.title))
|
||||
tr += X.td(align = "center")(comment.nbReplies)
|
||||
if comment.authorId:
|
||||
tr += X.td(align = "center")(X.objectHypertextLabel(comment.authorId))
|
||||
tr += X.td(align = "center")(
|
||||
X.objectHypertextLabel(comment.authorId))
|
||||
elif comment.name:
|
||||
tr += X.td(align = "center")(comment.name)
|
||||
else:
|
||||
|
|
|
@ -89,13 +89,18 @@ class BaseObjectWebMixin(things.ThingMixin):
|
|||
self.repairFields(fields)
|
||||
return self.getCompactViewLayout(fields, parentSlot = None)
|
||||
|
||||
def getLabelTranslated(self, destinationLanguages, multiCall = None):
|
||||
def getLabelTranslated(self, destinationLanguages = None, multiCall = None):
|
||||
translationsProxy = getProxyForServerRole('translations')
|
||||
if translationsProxy:
|
||||
if not destinationLanguages:
|
||||
destinationLanguages = context.getVar('destinationLanguages')
|
||||
try:
|
||||
return translationsProxy.getTranslation(
|
||||
self.getLabel(), self.getId(), 'self.getLabel()',
|
||||
self.getLabelLanguage(), destinationLanguages,
|
||||
multiCall = multiCall)
|
||||
except faults.UnknownStringDigest:
|
||||
return self.getLabel()
|
||||
else:
|
||||
return self.getLabel()
|
||||
|
||||
|
@ -106,7 +111,9 @@ class BaseObjectWebMixin(things.ThingMixin):
|
|||
slotNames = things.ThingMixin.getViewLayoutSlotNames(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
if not userToken or context.getVar('useCompactLayout', default = 0):
|
||||
|
||||
if context.getVar('useCompactLayout', default = 0) or (
|
||||
self.id and not self.getWeb().canModifyObject(self.id)):
|
||||
slotNames = slotNames[:]
|
||||
for slotName in ('language',):
|
||||
if slotName in slotNames:
|
||||
|
@ -466,7 +473,10 @@ class ObjectsWebMixin(WebMixin):
|
|||
lazyLabels = objectIds # fastest way to get a list of same len
|
||||
for objectId, lazyLabel in zip(objectIds, lazyLabels):
|
||||
if translationsProxy:
|
||||
try:
|
||||
label = lazyLabel()
|
||||
except faults.UnknownStringDigest:
|
||||
label = partialObjects[objectId].getLabel()
|
||||
else:
|
||||
label = partialObjects[objectId].getLabel()
|
||||
partialObject = partialObjects[objectId]
|
||||
|
@ -588,7 +598,10 @@ class ObjectsWebMixin(WebMixin):
|
|||
object.getLabelTranslated(
|
||||
readLanguages, multiCall = labelsMultiCall)
|
||||
for id, lazyLabel in zip(ids, labelsMultiCall.call()):
|
||||
try:
|
||||
labels[id] = lazyLabel()
|
||||
except faults.UnknownStringDigest:
|
||||
labels[id] = objects[id].getLabel()
|
||||
ids.sort(lambda id1, id2, labels = labels:
|
||||
locale.strcoll(labels[id1], labels[id2]))
|
||||
return ids
|
||||
|
@ -664,6 +677,17 @@ class ObjectsWebMixin(WebMixin):
|
|||
def getViewOtherActionButtonsBarLayout(self, object, fields):
|
||||
return None
|
||||
|
||||
def id(self, id):
|
||||
if not self.hasObject(id):
|
||||
return pageNotFound()
|
||||
if not self.canGetObject(id):
|
||||
return accessForbidden()
|
||||
object = self.getObject(id)
|
||||
return writePageLayout(
|
||||
X.p(id),
|
||||
_('Id for "%s"') % object.getLabel())
|
||||
id.isPublicForWeb = 1
|
||||
|
||||
image = download
|
||||
image.isPublicForWeb = 1
|
||||
|
||||
|
|
|
@ -275,7 +275,8 @@ class VoteMixin(ObjectWebMixin):
|
|||
electionId_kind_hasToMakeFieldFromValue = 0
|
||||
electionId_kind_hasToRepairField = 0
|
||||
electionId_kind_hasToSubmitField = 0
|
||||
electionId_kind_stateInEditMode = 'read-only'
|
||||
electionId_kind_stateInEditMode = 'hidden'
|
||||
electionId_kind_stateInViewMode = 'hidden'
|
||||
electionId_kindName = 'Id'
|
||||
electionId_kind_serverRoles = ['elections']
|
||||
electionId_kind_widget_fieldLabel = N_('Election')
|
||||
|
@ -865,6 +866,8 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
|
|||
if voterId and voterId == userId and electionsWeb.canVote(electionId):
|
||||
layout += X.buttonStandalone(
|
||||
'edit',X.idUrl(id, 'edit').add('electionId', electionId))
|
||||
layout += X.buttonStandalone(
|
||||
_('Go to election'), X.idUrl(electionId))
|
||||
return writePageLayout(
|
||||
layout, '%s - %s' % (_(self.objectNameCapitalized), label))
|
||||
view.isPublicForWeb = 1
|
||||
|
|
|
@ -133,7 +133,8 @@ def getMonthLayout(year, month, baseUrl, objects, startSlot, endSlot = None):
|
|||
((getattr(x, endSlot) is None and
|
||||
getattr(x, startSlot) >= timeStart ) or \
|
||||
getattr(x, endSlot) >= timeStart)]
|
||||
dayObjects.sort(lambda x,y: cmp(getattr(x, startSlot), getattr(y, startSlot)))
|
||||
dayObjects.sort(lambda x,y: cmp(getattr(x, startSlot),
|
||||
getattr(y, startSlot)))
|
||||
if len(dayObjects):
|
||||
ul = X.ul()
|
||||
for d in dayObjects:
|
||||
|
|
|
@ -688,6 +688,7 @@ def writePageLayout(layout, title, canCache = 1):
|
|||
#os.chdir(context.getVar('webDirectoryPath'))
|
||||
os.chdir( context.getVar('templatesDirectoryPath') )
|
||||
|
||||
dict['contextualHeaders'] = '\n'.join(context.getVar('htmlHeaders'))
|
||||
dict['body'] = layout.getAsXml()
|
||||
|
||||
fileName = context.getVar('templateFileName')
|
||||
|
@ -987,10 +988,7 @@ def processTALFile(fileName, file = None, xtal = None, **keywords):
|
|||
for k, v in dict.items():
|
||||
engine.locals[k] = v
|
||||
|
||||
t1 = context.getVar('t1')
|
||||
interp = TALInterpreter(program, macros, engine, stream=req, wrap=80)
|
||||
open('/tmp/webbench', 'a+').write(' %f (before interp())\n' % (
|
||||
time.time() - t1))
|
||||
try:
|
||||
interp()
|
||||
except TALError:
|
||||
|
@ -1000,8 +998,6 @@ def processTALFile(fileName, file = None, xtal = None, **keywords):
|
|||
exception = traceback.format_exception_only(
|
||||
info[0], info[1])[0].strip()
|
||||
writePageException(exception)
|
||||
open('/tmp/webbench', 'a+').write(' %f (after interp())\n' % (
|
||||
time.time() - t1))
|
||||
|
||||
if req.caching:
|
||||
req.closeCachePage()
|
||||
|
|
|
@ -55,6 +55,7 @@ except ImportError:
|
|||
|
||||
import glasnost.common.context as context
|
||||
import glasnost.common.tools_new as commonTools
|
||||
import glasnost.common.xhtmlgenerator as X
|
||||
|
||||
|
||||
def debugInfos():
|
||||
|
@ -137,3 +138,15 @@ def getConfig(value, default = None, vars = None, raw = 0):
|
|||
default = commonTools.getConfig('Misc', value, default, vars, raw),
|
||||
vars = vars, raw = raw)
|
||||
|
||||
def addContextualHeader(htmlLine):
|
||||
knownLines = {
|
||||
'tooltips.js':
|
||||
'<script src="%s" type="text/javascript"></script>' % \
|
||||
X.fileUrl('/javascript/tooltips.js'),
|
||||
}
|
||||
if htmlLine in knownLines.keys():
|
||||
htmlLine = knownLines[htmlLine]
|
||||
contextualHeaders = context.getVar('htmlHeaders')
|
||||
if not htmlLine in contextualHeaders:
|
||||
contextualHeaders.append(htmlLine)
|
||||
|
||||
|
|
|
@ -142,6 +142,9 @@ class WidgetMixin(things.ThingMixin):
|
|||
# We have to enclose the field value in a tag with class 'cell' but we
|
||||
# want a nice markup so we can't simply <div class="cell"> v </div> and
|
||||
# go away with this.
|
||||
if self.isInForm() and context.getVar('virtualHost').showTooltips:
|
||||
webTools.addContextualHeader('tooltips.js')
|
||||
|
||||
return X.enclose(self.getHtmlValue(slot, fields, **keywords),
|
||||
_class = 'cell')
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
# TODO: support attr-translate
|
||||
|
||||
import os
|
||||
import sgmllib
|
||||
import sys
|
||||
|
||||
directory = sys.argv[1]
|
||||
|
||||
translations = {}
|
||||
|
||||
class ParserForTranslations(sgmllib.SGMLParser):
|
||||
def __init__(self, body):
|
||||
sgmllib.SGMLParser.__init__(self)
|
||||
self.translation = 0
|
||||
self.feed(body)
|
||||
|
||||
def handle_data(self, data):
|
||||
if not self.translation:
|
||||
return
|
||||
self.translation = 0
|
||||
translations[data.strip()] = None
|
||||
|
||||
def unknown_starttag(self, tag, attrs):
|
||||
attrs = [x for x in attrs if x[0] == 'tal:translate' and not x[1]]
|
||||
if not attrs:
|
||||
return
|
||||
self.translation = 1
|
||||
|
||||
|
||||
for root, dir, files in os.walk(directory):
|
||||
for file in files:
|
||||
if not file.endswith('.tal') and not file.endswith('.html'):
|
||||
continue
|
||||
file = os.path.join(root, file)
|
||||
ParserForTranslations(open(file).read())
|
||||
|
||||
for t in translations.keys():
|
||||
print '_("""%s""")' % t
|
||||
|
||||
|
||||
|
|
@ -10,8 +10,8 @@
|
|||
<title metal:define-slot="title">Théridion - [title]</title>
|
||||
<link rel="stylesheet" href="/css/april.css" tal:reroot="href" />
|
||||
<link rel="home" href="/" tal:reroot="href" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script src="/javascript/tooltips.js" tal:reroot="src" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body id="entrouvert-april-org">
|
||||
|
|
|
@ -6,6 +6,8 @@ body {
|
|||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
font-family: sans-serif;
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
|
||||
div#header {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -12,8 +12,8 @@
|
|||
<link rel="stylesheet" type="text/css" href="/css/artus-default.css" tal:reroot="href" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/artus.css" tal:reroot="href" />
|
||||
<link rel="stylesheet" type="text/css" media="print" href="/css/artus-print.css" tal:reroot="href" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script src="/javascript/tooltips.js" tal:reroot="src" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -12,8 +12,8 @@
|
|||
<link rel="home" href="/" tal:reroot="href" />
|
||||
<link rel="icon" href="/images/bxlug-favicon.ico" tal:reroot="href" />
|
||||
<link rel="shortcut icon" href="/images/bxlug-favicon.ico" tal:reroot="href" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script src="/javascript/tooltips.js" tal:reroot="src" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -13,8 +13,8 @@
|
|||
<link rel="stylesheet" type="text/css" href="/entrouvert/entrouvert2.css" tal:reroot="href" />
|
||||
<link rel="stylesheet" type="text/css" media="print" href="/entrouvert/entrouvert2-print.css" tal:reroot="href" />
|
||||
<link rel="home" href="/" tal:reroot="href" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script src="/javascript/tooltips.js" tal:reroot="src" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -21,8 +21,9 @@ http://www.codelutin.com
|
|||
<link rel="stylesheet" href="/css/codelutin.org.css" tal:reroot="href" />
|
||||
<link rel="home" href="/" tal:reroot="href" />
|
||||
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script src="/javascript/tooltips.js" tal:reroot="src" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -61,7 +62,7 @@ http://www.codelutin.com
|
|||
<tr metal:use-macro="macro.tal/treemenu"/>
|
||||
</div>
|
||||
|
||||
<tr tal:condition="not user"
|
||||
<tr tal:condition="not user" tal:on-error="nothing"
|
||||
tal:repeat="role [GlasnostServerRole('tasks'), GlasnostServerRole('appointments')]">
|
||||
<td><img tal:reroot="src" src="/images/arbopics/arb0.png" width="10" height="22" /></td>
|
||||
<td><img tal:reroot="src" src="/images/arbopics/arb-.png" width="15" height="22" /></td>
|
||||
|
|
|
@ -4,7 +4,8 @@ body {
|
|||
font-family: Verdana, Arial, Georgia, Geneva, sans-serif;
|
||||
background-image: url(/images/lutin-background.png);
|
||||
background-repeat: no-repeat;
|
||||
background-color : #FFFFFF;
|
||||
background-color : white;
|
||||
color: black;
|
||||
margin: 0;
|
||||
padding:0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -26,8 +26,9 @@ http://www.codelutin.com
|
|||
<link rel="stylesheet" href="/css/codelutin/global.css" tal:reroot="href" />
|
||||
<link rel="home" href="/" tal:reroot="href" />
|
||||
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script src="/javascript/tooltips.js" tal:reroot="src" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -46,7 +47,7 @@ http://www.codelutin.com
|
|||
<tr metal:use-macro="macro.tal/treemenu"/>
|
||||
</div>
|
||||
|
||||
<tr tal:condition="not user"
|
||||
<tr tal:condition="not user" tal:on-error="nothing"
|
||||
tal:repeat="role [GlasnostServerRole('tasks'), GlasnostServerRole('appointments')]">
|
||||
<td class="menuitemdebut"></td>
|
||||
<td class="menuitemmilieu">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -10,8 +10,8 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/crans.css" tal:reroot="href"/>
|
||||
<link rel="home" href="/" tal:reroot="href" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script src="/javascript/tooltips.js" tal:reroot="src" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body bgcolor="white" text="black" topmargin="0" leftmargin="0" marginwidth="0" marginheight="0">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -10,8 +10,8 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/cuisine.css" tal:reroot="href" />
|
||||
<link rel="home" href="/" tal:reroot="href" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script src="/javascript/tooltips.js" tal:reroot="src" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
xmlns:metal="http://xml.zope.org/namespaces/metal"
|
||||
metal:define-macro="master">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<title metal:define-slot="title">[title]</title>
|
||||
<link rel="stylesheet" href="/css/cyborg.css" tal:reroot="href" />
|
||||
<link rel="author" href="mailto:fpeters@entrouvert.be" title="Auteur" />
|
||||
<link rel="home" href="/" tal:reroot="href" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script src="/javascript/tooltips.js" tal:reroot="src" type="text/javascript"></script>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<title metal:define-slot="title">[title]</title>
|
||||
<link rel="stylesheet" href="/css/cyborg.css" tal:reroot="href" />
|
||||
<link rel="author" href="mailto:fpeters@entrouvert.be" title="Auteur" />
|
||||
<link rel="home" href="/" tal:reroot="href" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<h3 tal:content="comment.title">titre</h3>
|
||||
<span class="comment-author">By <span tal:replace="GlasnostObject(comment.authorId)" tal:on-error="'Anonymous'"/></span>
|
||||
<div class="comment" tal:content="structure parseSpip(comment.body)" />
|
||||
<a tal:attributes="href roleUrl('post', sourceId=comment.id, nextUri=currentURI)" tal:translate="fr">Répondre</a>
|
||||
<a tal:attributes="href roleUrl('post', sourceId=comment.id, nextUri=currentURI)" tal:translate="">Reply</a>
|
||||
<div class="comment-block" tal:condition="comments" tal:repeat="c comments" tal:content="structure template('comment.tal', comment=c)" />
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<p metal:define-macro="poweredBy" id="powered-by-glasnost"><a tal:attributes="href aboutUrl">Powered by Glasnost</a></p>
|
||||
<p metal:define-macro="poweredBy" id="powered-by-glasnost"><a tal:attributes="href aboutUrl">Glasnost</a></p>
|
||||
|
||||
<span metal:define-macro="breadCrumb"
|
||||
tal:define="objectPath getPathToObject(currentObject)"
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
metal:use-macro="StandardLookAndFeel.html/master">
|
||||
<head>
|
||||
<title metal:fill-slot="title" tal:content="str(virtualHost) + ' - ' + title">title</title>
|
||||
<meta metal:fill-slot="contextualHeaders" tal:replace="structure contextualHeaders" />
|
||||
</head>
|
||||
<body>
|
||||
<div metal:fill-slot="main" tal:omit-tag="">
|
||||
<h1 tal:condition="title" tal:content="title">the title goes here</h1>
|
||||
<span tal:replace="structure body" />
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -11,6 +11,8 @@
|
|||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/demo04.css" media="all"/>
|
||||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/print.css" media="print" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -42,7 +44,7 @@
|
|||
<li><a id="link-forum" href="/forums" tal:translate="">Forums</a></li>
|
||||
<li><a id="link-vote" href="/elections" tal:translate="">Elections</a></li>
|
||||
<li><a id="link-file" href="/uploadfiles" tal:translate="">Files</a></li>
|
||||
<li><a id="link-calendar" href="/appointments" tal:translate="fr">Calendrier</a></li>
|
||||
<li><a id="link-calendar" href="/appointments" tal:translate="">Calendar</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -9,10 +9,11 @@
|
|||
<title metal:define-slot="title">Website title</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link rel="home" href="/" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/eeorg/basicstyle.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/basicstyle.css" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<style type="text/css" media="screen">
|
||||
<!--
|
||||
@import url("/css/eeorg/style.css");
|
||||
@import url("/css/style.css");
|
||||
-->
|
||||
</style>
|
||||
</head>
|
||||
|
|
|
@ -40,3 +40,9 @@ ul.nav2 {
|
|||
img {
|
||||
border: 0;
|
||||
}
|
||||
.tooltip {
|
||||
display: none;
|
||||
}
|
||||
.error-message {
|
||||
color: red;
|
||||
}
|
||||
|
|
|
@ -94,3 +94,6 @@ li.c { margin-top: 1.5em; padding-top: 0.3em; list-style-type: none; border-top:
|
|||
div.copyleft { text-align: center; font-size: 0.7em; margin-top: 4em; }
|
||||
|
||||
.center { text-align: center; }
|
||||
|
||||
div.preview { border: 1px dotted #036; margin-left: 2em; padding: 0;}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -10,14 +10,14 @@
|
|||
<title metal:define-slot="title">[title]</title>
|
||||
<link tal:reroot="href" rel="stylesheet" href="/css/eclova.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="header">
|
||||
<h1>Eclova</h1>
|
||||
<h1 tal:content="str(virtualHost)">title</h1>
|
||||
<h2> </h2> <!-- no motto yet -->
|
||||
</div>
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ html, body {
|
|||
#footer {
|
||||
font-size: 70%;
|
||||
text-align: right;
|
||||
padding: 2px 10px 0 0;
|
||||
padding: 2px 10px 10px 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
<title metal:define-slot="title">[title]</title>
|
||||
<link tal:reroot="href" rel="stylesheet" href="/css/entrouvert.be.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -15,8 +15,8 @@
|
|||
<!--<link tal:reroot="href" rel="author" href="mailto:info@theridion.com" title="Auteur" />
|
||||
<link tal:reroot="href" rel="icon" href="/theridion/favicon.png" type="image/png" />-->
|
||||
<link rel="shortcut icon" href="/images/entrouvert.com-favicon.ico" tal:reroot="href" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -10,8 +10,8 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/entrouvert1.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body bgcolor="white" text="black" topmargin="0" leftmargin="0" marginwidth="0"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -14,8 +14,8 @@
|
|||
<link tal:reroot="href" rel="stylesheet" type="text/css" media="print" href="/css/entrouvert2-print.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<link rel="shortcut icon" href="/images/entrouvert.com-favicon.ico" tal:reroot="href" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
<title metal:define-slot="title">[title]</title>
|
||||
<link tal:reroot="href" rel="stylesheet" href="/css/fsfeurope.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
body {
|
||||
background: white;
|
||||
color: black;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: sans-serif;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -10,8 +10,8 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/glasnost.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/balloonHelp.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -11,8 +11,8 @@
|
|||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/entrouvert1.css" />
|
||||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/glasnost1.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -11,8 +11,8 @@
|
|||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/glasnost2.css" />
|
||||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/calendar.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/balloonHelp.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<title metal:define-slot="title">[title]</title>
|
||||
<link tal:reroot="href" rel="stylesheet" href="/css/i3c.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script type="text/javascript">
|
||||
function goRubric(form) {
|
||||
|
@ -18,13 +19,12 @@ function goRubric(form) {
|
|||
return false;
|
||||
}
|
||||
</script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body id="glasnost-i3c">
|
||||
|
||||
<div id="header">
|
||||
<h1><a href="/" tal:reroot="href">I3C - Internet Créatif, Coopératif, Citoyen</a></h1>
|
||||
<h1><a tal:attributes="href rootUrl()" tal:content="str(virtualHost)">title</a></h1>
|
||||
|
||||
<p class="glasnost-cmd">
|
||||
<span metal:use-macro="buttons.tal/preferences" />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -10,8 +10,8 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/in3activa.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -10,6 +10,7 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/calendar.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<style tal:condition="user" type="text/css" media="screen">
|
||||
<!--
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
<title metal:define-slot="title">Page title will be here</title>
|
||||
<link tal:reroot="href" rel="stylesheet" href="/css/libre-entreprise.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body id="libre-entreprise-com">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -10,8 +10,8 @@
|
|||
<title metal:define-slot="title">[title]</title>
|
||||
<link tal:reroot="href" rel="stylesheet" href="/css/lightbulb.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -10,8 +10,8 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/linuxdays.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -9,8 +9,8 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<title metal:define-slot="title">[title]</title>
|
||||
<link tal:reroot="href" href="/css/macfly.css" rel="stylesheet" type="text/css">
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/balloonHelp.js" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -32,11 +32,13 @@
|
|||
<span metal:use-macro="buttons.tal/gotoObjects" />
|
||||
<span metal:use-macro="buttons.tal/newObject" />
|
||||
|
||||
<!--
|
||||
<ul tal:define="languages getPossibleLanguagesLabelAndUrl(notSelf = 1)"
|
||||
tal:condition="languages">
|
||||
<li tal:repeat="l languages"><a
|
||||
tal:attributes="href l[2]" tal:content="l[1]">language</a></li>
|
||||
</ul>
|
||||
-->
|
||||
|
||||
</div>
|
||||
<!-- Main Content -->
|
||||
|
|
|
@ -145,14 +145,15 @@ hr {
|
|||
height: 1px;
|
||||
}
|
||||
|
||||
span.error,
|
||||
div.error {
|
||||
/* Class for error indication in forms */
|
||||
div.error .label {
|
||||
color: #800;
|
||||
}
|
||||
|
||||
span.error-message {
|
||||
background: #ffce7b;
|
||||
border: 1px dashed red;
|
||||
padding: 0.5em;
|
||||
margin: 0;
|
||||
width: 74%;
|
||||
padding: 0 1em;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.calendar-week-full,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -10,8 +10,8 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/pel-infini.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -10,31 +10,34 @@
|
|||
<title metal:define-slot="title">[title]</title>
|
||||
<link tal:reroot="href" rel="stylesheet" href="/css/plane.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
<!--
|
||||
<script tal:reroot="src" src="/javascript/htmlarea/htmlarea.js" type="text/javascript"></script>
|
||||
<script tal:reroot="src" src="/javascript/htmlarea/htmlarea-lang-en.js" type="text/javascript"></script>
|
||||
<script tal:reroot="src" src="/javascript/htmlarea/dialog.js" type="text/javascript"></script>
|
||||
-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="top">
|
||||
<div class="searchBox">
|
||||
<div id="top">
|
||||
<div id="searchBox">
|
||||
<form id="searchForm" tal:attributes="action roleUrl('search', 'go')">
|
||||
<input id="search" name="terms" size="20"/>
|
||||
<input tal:attr-translate="value" type="submit" class="button" value="Search"/>
|
||||
</form>
|
||||
</div>
|
||||
<a href="/" tal:reroot="href"><img tal:reroot="src" src="/images/glasnost-plane.png" alt="Glasnost" class="logo"/></a>
|
||||
<h1 tal:content="str(virtualHost)">website title</h1>
|
||||
<!-- <a href="/" tal:reroot="href"><img tal:reroot="src" src="/images/glasnost-plane.png" alt="Glasnost" class="logo"/></a>-->
|
||||
</div>
|
||||
|
||||
<div class="tabs">
|
||||
<div id="tabs">
|
||||
<a href="/" tal:reroot="href" tal:translate="">Home</a>
|
||||
<div metal:use-macro="nav.tal/aBlockOneLevelAllObjects" />
|
||||
</div>
|
||||
|
||||
<div class="personalBar">
|
||||
<div id="personalBar">
|
||||
<a class="button user" tal:condition="user" tal:attributes="href user.getUrl()" tal:content="user">userName</a>
|
||||
<span tal:condition="not user" tal:translate="">You are not logged in</span>
|
||||
<span metal:use-macro="buttons.tal/login" />
|
||||
|
@ -44,7 +47,7 @@
|
|||
<span metal:use-macro="buttons.tal/about" />
|
||||
</div>
|
||||
|
||||
<div class="pathBar" tal:condition="fileName.startswith('index') or currentObject"
|
||||
<div id="pathBar" tal:condition="fileName.startswith('index') or currentObject"
|
||||
tal:define="breadCrumbPrefix 'Vous êtes ici: '">
|
||||
<span metal:use-macro="misc.tal/breadCrumb" />
|
||||
</div>
|
||||
|
@ -64,7 +67,7 @@
|
|||
|
||||
</div> <!-- end of main-content -->
|
||||
|
||||
<div class="footer">
|
||||
<div id="footer">
|
||||
<a href="http://glasnost.entrouvert.org">Glasnost</a>
|
||||
</div> <!-- end of footer -->
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ hr {
|
|||
color: #8cacbb;
|
||||
}
|
||||
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: black;
|
||||
clear: left;
|
||||
|
@ -51,6 +50,15 @@ h1, h2, h3, h4, h5, h6 {
|
|||
border-bottom: 1px solid #8cacbb;
|
||||
}
|
||||
|
||||
div#top h1 {
|
||||
border: 0;
|
||||
font-size: 300%;
|
||||
letter-spacing: 0.1em;
|
||||
color: #8cacbb;
|
||||
padding: 0.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 160%;
|
||||
}
|
||||
|
@ -186,7 +194,8 @@ pre {
|
|||
color: black;
|
||||
background-color: #dee7ec;
|
||||
}
|
||||
div.top {
|
||||
|
||||
div#top {
|
||||
/* Top section */
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
@ -199,7 +208,7 @@ div.top {
|
|||
}
|
||||
|
||||
|
||||
div.searchBox {
|
||||
div#searchBox {
|
||||
/*searchbox style and positioning */
|
||||
color: black;
|
||||
float: right;
|
||||
|
@ -215,7 +224,7 @@ input.searchButton {
|
|||
margin-bottom: 1px ! important;
|
||||
}
|
||||
|
||||
div.tabs {
|
||||
div#tabs {
|
||||
/* Navigational tabs */
|
||||
border-collapse: collapse;
|
||||
border-bottom-color: #8cacbb;
|
||||
|
@ -225,7 +234,7 @@ div.tabs {
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.tabs a {
|
||||
div#tabs a {
|
||||
/* The normal, unselected tabs. They are all links */
|
||||
border-color: #8cacbb;
|
||||
border-width: 1px;
|
||||
|
@ -238,7 +247,7 @@ div.tabs a {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
div.tabs a.selected {
|
||||
div#tabs a.selected {
|
||||
/* The selected tab. There's only one of this */
|
||||
background: #dee7ec;
|
||||
border: 1px solid #8cacbb;
|
||||
|
@ -247,14 +256,14 @@ div.tabs a.selected {
|
|||
font-weight: normal;
|
||||
}
|
||||
|
||||
div.tabs a:hover {
|
||||
div#tabs a:hover {
|
||||
background: #dee7ec;
|
||||
border-color: #8cacbb;
|
||||
border-bottom-color: #dee7ec;
|
||||
color: #436976;
|
||||
}
|
||||
|
||||
div.personalBar {
|
||||
div#personalBar {
|
||||
/* Bar with personalized menu (user preferences, favorites etc) */
|
||||
background: #dee7ec;
|
||||
border-bottom-color: #8cacbb;
|
||||
|
@ -266,23 +275,23 @@ div.personalBar {
|
|||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
div.personalBar a.button {
|
||||
div#personalBar a.button {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.personalBar a {
|
||||
div#personalBar a {
|
||||
text-decoration: none;
|
||||
color: #436976;
|
||||
font-weight: normal;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
div.personalBar img {
|
||||
div#personalBar img {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
div.pathBar {
|
||||
div#pathBar {
|
||||
/* The path bar, including breadcrumbs and add to favorites */
|
||||
border-bottom-color: #8cacbb;
|
||||
border-bottom-style: solid;
|
||||
|
@ -292,17 +301,17 @@ div.pathBar {
|
|||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
div.pathBar a {
|
||||
div#pathBar a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
div.top, div.tabs, div.personalBar, div.pathBar {
|
||||
div#top, div#tabs, div#personalBar, div#pathBar {
|
||||
font-size: 60%;
|
||||
}
|
||||
|
||||
|
||||
.footer {
|
||||
#footer {
|
||||
background: #dee7ec;
|
||||
border-top: 1px solid #8cacbb;
|
||||
border-bottom: 1px solid #8cacbb;
|
||||
|
@ -451,7 +460,7 @@ span.error-message {
|
|||
font: bold smaller sans-serif;
|
||||
}
|
||||
|
||||
div.personalBar a.button, a.button {
|
||||
div#personalBar a.button, a.button {
|
||||
padding-left: 18px;
|
||||
background: url("/images/item.png") 8px 40% no-repeat;
|
||||
}
|
||||
|
@ -461,7 +470,7 @@ input[type="submit"] {
|
|||
background: white url("/images/submit.png") 5px 40% no-repeat;
|
||||
}
|
||||
|
||||
div.personalBar a.user {
|
||||
div#personalBar a.user {
|
||||
padding-left: 12px;
|
||||
background: url("/images/user.png") left top no-repeat;
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
<title metal:define-slot="title">[title]</title>
|
||||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/rap.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/glasnostTooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body id="antipub-be">
|
||||
|
|
|
@ -5,6 +5,7 @@ html, body {
|
|||
margin: 0;
|
||||
font-family: sans-serif;
|
||||
background: white url('/images/fingerprint.png') fixed 80% 65% no-repeat;
|
||||
color: black;
|
||||
}
|
||||
|
||||
div#header {
|
||||
|
@ -212,18 +213,11 @@ div.error-message {
|
|||
background-color: #ffce7b;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: 0;
|
||||
margin: 0.5em 0em;
|
||||
padding: 0.5em 0em;
|
||||
}
|
||||
|
||||
fieldset select {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
fieldset input {
|
||||
margin-left: 1em;
|
||||
span.error-message {
|
||||
display: block;
|
||||
color: red;
|
||||
font-size: 80%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
form {
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
<title metal:define-slot="title">[title]</title>
|
||||
<link tal:reroot="href" rel="stylesheet" href="/css/september.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -35,7 +35,7 @@
|
|||
</div>
|
||||
|
||||
<hr />
|
||||
<a href="/" tal:reroot="href" tal:translate="fr">Retour au sommaire</a>
|
||||
<a href="/" tal:reroot="href" tal:translate="">Back to home</a>
|
||||
<hr />
|
||||
|
||||
<span metal:use-macro="buttons.tal/preferences" />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -9,6 +9,7 @@
|
|||
<title metal:define-slot="title">Website title</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link rel="stylesheet" title="Default" href="/css/skelblue.css" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">
|
||||
|
@ -24,14 +25,8 @@
|
|||
</ul>
|
||||
|
||||
<div id="commands" tal:condition="userToken">
|
||||
<h2>Commandes</h2>
|
||||
<ul>
|
||||
<li class="role" tal:repeat="role [x for x in getServerRoles() if canGetObjects(x)]">
|
||||
<span tal:content="role.label">type</span> :
|
||||
<a tal:attributes="href role.url" tal:translate="">Go</a>
|
||||
<a tal:condition="canAddObject(role)" tal:attributes="href role.urlNew" tal:translate="">Add</a></li>
|
||||
<li><a href="/login/logout" tal:translate="">Exit</a></li>
|
||||
</ul>
|
||||
<h2 tal:translate="">Navigation</h2>
|
||||
<ul metal:use-macro="nav.tal/ulRoles" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -54,6 +49,7 @@
|
|||
<div id="footer">
|
||||
<span metal:use-macro="buttons.tal/newAccount">new account</span>
|
||||
<span metal:use-macro="buttons.tal/login">login</span>
|
||||
<span metal:use-macro="buttons.tal/logout">login</span>
|
||||
<span metal:use-macro="buttons.tal/about">about</span>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@import url("/css/calendar.css");
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
font-family: sans-serif;
|
||||
|
@ -8,7 +10,7 @@ a:link {
|
|||
}
|
||||
|
||||
a:visited {
|
||||
color: #c00;
|
||||
color: #008;
|
||||
}
|
||||
|
||||
div#header h1 {
|
||||
|
@ -49,6 +51,7 @@ div#navigation li a:hover {
|
|||
|
||||
div#navigation h2 {
|
||||
margin: 1em 0.5em 0.1em -0.5em;
|
||||
padding: 0 0.2em;
|
||||
font-size: 100%;
|
||||
border: 1px outset #ccf;
|
||||
background: #00a;
|
||||
|
@ -121,6 +124,7 @@ div.row .tooltip {
|
|||
font-style: italic;
|
||||
font-size: smaller;
|
||||
margin-left: 2em;
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.row .cell {
|
||||
|
@ -257,3 +261,13 @@ hr {
|
|||
height: 1px;
|
||||
}
|
||||
|
||||
div.balloon-help {
|
||||
display: none;
|
||||
}
|
||||
|
||||
pre {
|
||||
border: 1px solid #ccf;
|
||||
background: #ddf;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
<link rel="author" href="mailto:info@theridion.com" title="Auteur" />
|
||||
<link tal:reroot="href" rel="icon" href="/images/favicon.png" type="image/png" />
|
||||
<link tal:reroot="href" rel="alternate" type="application/rss+xml" title="RSS" href="http://www.theridion.com/rubrics/2/rss" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
<!--<style
|
||||
tal:content="'#logoGnu { -moz-binding: url(%s);}' % roleUrl('xbl', 'glasnost#menu')"></style>-->
|
||||
|
||||
|
@ -77,7 +77,7 @@
|
|||
</div>
|
||||
|
||||
<div tal:condition="not fileName.startswith('index')">
|
||||
<h2 id="homeLink"><a accesskey="1" href="/" tal:reroot="href" tal:translate="fr">Retour au sommaire</a></h2>
|
||||
<h2 id="homeLink"><a accesskey="1" href="/" tal:reroot="href" tal:translate="">Back to home</a></h2>
|
||||
</div>
|
||||
|
||||
</div> <!-- end of nav -->
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -10,8 +10,8 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link tal:reroot="href" rel="stylesheet" type="text/css" href="/css/upthings.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script tal:reroot="src" src="/javascript/tooltips.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
body {
|
||||
background: white url(/images/upthings.jpeg) fixed top left no-repeat;
|
||||
color: black;
|
||||
font-family: sans-serif;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<title metal:define-slot="title">[title]</title>
|
||||
<link tal:reroot="href" rel="stylesheet" href="/css/vecam.css" />
|
||||
<link tal:reroot="href" rel="home" href="/" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
<script type="text/javascript">
|
||||
function goRubric(form) {
|
||||
|
@ -18,7 +19,6 @@ function goRubric(form) {
|
|||
return false;
|
||||
}
|
||||
</script>
|
||||
<script tal:reroot="src" src="/javascript/balloonHelp.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body id="glasnost-vecam">
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
html, body {
|
||||
background: #10743d;
|
||||
color: black;
|
||||
padding-bottom: 15px;
|
||||
font-family: verdana, sans-serif;
|
||||
font-size: 12px;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -9,6 +9,8 @@
|
|||
<title metal:define-slot="title">Website title</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link rel="stylesheet" title="Default" href="/css/watercolor.css" />
|
||||
<meta metal:define-slot="contextualHeaders" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="header" tal:content="str(virtualHost)">website title</h1>
|
||||
|
@ -37,7 +39,7 @@
|
|||
<span metal:use-macro="buttons.tal/login">login</span>
|
||||
<span metal:use-macro="buttons.tal/logout" />
|
||||
<span metal:use-macro="buttons.tal/preferences" />
|
||||
<a href="http://glasnost.entrouvert.org">Glasnost</a>
|
||||
<a href="/about">Glasnost</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
@import url("/css/balloonHelp.css");
|
||||
@import url("/css/calendar.css");
|
||||
|
||||
html, body {
|
||||
|
@ -117,10 +118,6 @@ div#footer a.button {
|
|||
margin: 0 0.5em;
|
||||
}
|
||||
|
||||
.tooltip, .balloon-help {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div#content ul {
|
||||
list-style: circle;
|
||||
}
|
||||
|
@ -153,6 +150,7 @@ div.row ul {
|
|||
|
||||
div.buttons-bar {
|
||||
margin-top: 1em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div.buttons-bar .button {
|
||||
|
@ -233,3 +231,9 @@ div.diff-error {
|
|||
font-size: 80%;
|
||||
}
|
||||
|
||||
.preview {
|
||||
border: 1px solid #44618f;
|
||||
padding: 0.5em;
|
||||
margin: 0.5em 0 0 2em;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<metal:block define-macro="pre"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
</metal:block>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
|
@ -9,6 +9,7 @@
|
|||
<title metal:define-slot="title">Website title</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />
|
||||
<link rel="stylesheet" title="Default" href="/css/wretched.css" />
|
||||
<script metal:use-macro="forms.tal/formScript"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
# -*- coding: iso-8859-15 -*-
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
glasnostPythonDir = '/usr/local/lib/glasnost-tests'
|
||||
sys.path.insert(0, glasnostPythonDir)
|
||||
|
||||
from GlasnostTestCase import MinimalTestCase
|
||||
|
||||
from glasnost.web.AppointmentsWeb import weekNumberToDate, dateToWeekNumber
|
||||
|
||||
class WeekNumberKnownValuesTestCase(MinimalTestCase):
|
||||
knownValues = ( ( (1995, 1), (1995, 1, 2) ),
|
||||
( (1996, 1), (1996, 1, 1) ),
|
||||
( (1997, 1), (1996, 12, 30) ),
|
||||
( (1998, 1), (1997, 12, 29) ),
|
||||
( (1999, 1), (1999, 1, 4) ),
|
||||
( (2000, 1), (2000, 1, 3) ),
|
||||
( (2001, 1), (2001, 1, 1) ),
|
||||
( (2002, 1), (2001, 12, 31) ),
|
||||
( (2003, 1), (2002, 12, 30) ),
|
||||
( (2003, 2), (2003, 1, 6) ),
|
||||
( (2003, 25), (2003, 6, 16) ),
|
||||
( (2003, 52), (2003, 12, 22) ),
|
||||
( (2004, 1), (2003, 12, 29) ),
|
||||
( (1979, 24), (1979, 6, 11) ),
|
||||
)
|
||||
knownFromDateValues = ( ( (2003, 3, 16), (2003, 11) ),
|
||||
( (2003, 3, 17), (2003, 12) ),
|
||||
( (2003, 3, 18), (2003, 12) ),
|
||||
( (2003, 3, 19), (2003, 12) ),
|
||||
( (2003, 3, 20), (2003, 12) ),
|
||||
( (2003, 3, 21), (2003, 12) ),
|
||||
( (2003, 3, 22), (2003, 12) ),
|
||||
( (2003, 3, 23), (2003, 12) ),
|
||||
( (2003, 3, 24), (2003, 13) ),
|
||||
( (1999, 12, 31), (1999, 52) ),
|
||||
( (2000, 1, 1), (1999, 52) ),
|
||||
( (2000, 1, 2), (1999, 52) ),
|
||||
( (2000, 1, 3), (2000, 1) ),
|
||||
)
|
||||
|
||||
def test01_ToDateKnownValues(self):
|
||||
"""Convert week numbers to dates"""
|
||||
for ywTuple, ymdTuple in self.knownValues:
|
||||
date = weekNumberToDate(ywTuple[0], ywTuple[1])
|
||||
self.assertEqual(date[:3], ymdTuple)
|
||||
|
||||
def test02_FromDateKnownValues(self):
|
||||
"""Convert dates to week numbers"""
|
||||
for ywTuple, ymdTuple in self.knownValues:
|
||||
week = dateToWeekNumber(ymdTuple[0], ymdTuple[1], ymdTuple[2])
|
||||
self.assertEqual(week, ywTuple)
|
||||
|
||||
def testFromDateMoreKnownValues(self):
|
||||
"""Convert more dates to week numbers"""
|
||||
for ymdTuple, ywTuple in self.knownFromDateValues:
|
||||
week = dateToWeekNumber(ymdTuple[0], ymdTuple[1], ymdTuple[2])
|
||||
self.assertEqual(week, ywTuple)
|
||||
|
||||
|
||||
suite1 = unittest.makeSuite(WeekNumberKnownValuesTestCase, 'test')
|
||||
|
||||
allTests = unittest.TestSuite((suite1,))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.TextTestRunner(verbosity=2).run(allTests)
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
# -*- coding: iso-8859-15 -*-
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
glasnostPythonDir = '/usr/local/lib/glasnost-tests'
|
||||
sys.path.insert(0, glasnostPythonDir)
|
||||
|
||||
from GlasnostTestCase import MinimalTestCase, OneUserTestCase
|
||||
|
||||
import glasnost.common.context as context
|
||||
import glasnost.common.faults as faults
|
||||
import glasnost.common.system as system
|
||||
import glasnost.common.tools_new as commonTools
|
||||
|
||||
from glasnost.proxy.tools import getProxyForServerRole
|
||||
|
||||
|
||||
articlesProxy = getProxyForServerRole('articles')
|
||||
|
||||
class AddingTestCase(OneUserTestCase):
|
||||
def test01_noneObject(self):
|
||||
'''Add a None article'''
|
||||
try:
|
||||
articlesProxy.addObject(None)
|
||||
self.fail('Server accepted None')
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def test02_nonArticleObject(self):
|
||||
"""Add a non article object"""
|
||||
|
||||
badObject = 'This is it!'
|
||||
try:
|
||||
articlesProxy.addObject(badObject)
|
||||
self.fail('Server accepted a random string')
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def test03_viciousObject(self):
|
||||
"""Add a vicious article"""
|
||||
|
||||
class ViciousObject:
|
||||
def exportToXmlRpc(self):
|
||||
return {
|
||||
'__thingCategory__' : 'object',
|
||||
'__thingName__' : 'articles.Article',
|
||||
}
|
||||
|
||||
viciousObject = ViciousObject()
|
||||
|
||||
try:
|
||||
articlesProxy.addObject(viciousObject)
|
||||
self.fail('Server accepted the vicious object')
|
||||
except faults.MissingSlotValue:
|
||||
pass
|
||||
|
||||
|
||||
suite1 = unittest.makeSuite(AddingTestCase, 'test')
|
||||
|
||||
allTests = unittest.TestSuite((suite1, ))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.TextTestRunner(verbosity=2).run(allTests)
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
# -*- coding: iso-8859-15 -*-
|
||||
|
||||
|
||||
# Glasnost
|
||||
# By: Odile Bénassy <obenassy@entrouvert.com>
|
||||
# Romain Chantereau <rchantereau@entrouvert.com>
|
||||
# Nicolas Clapiès <nclapies@easter-eggs.org>
|
||||
# Pierre-Antoine Dejace <padejace@entrouvert.be>
|
||||
# Thierry Dulieu <tdulieu@easter-eggs.com>
|
||||
# Florent Monnier <monnier@codelutin.com>
|
||||
# Cédric Musso <cmusso@easter-eggs.org>
|
||||
# Frédéric Péters <fpeters@entrouvert.be>
|
||||
# Benjamin Poussin <poussin@codelutin.com>
|
||||
# Emmanuel Raviart <eraviart@entrouvert.com>
|
||||
# Sébastien Régnier <regnier@codelutin.com>
|
||||
# Emmanuel Saracco <esaracco@easter-eggs.com>
|
||||
#
|
||||
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
|
||||
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
|
||||
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
|
||||
# Emmanuel Saracco & Théridion
|
||||
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
|
||||
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
|
||||
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
|
||||
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
|
||||
# Régnier, Emmanuel Saracco, Théridion & Vecam
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
"""Glasnost AuthenticationProxy Unit Tests."""
|
||||
|
||||
|
||||
__version__ = '$Revision$'[11:-2]
|
||||
|
||||
|
||||
import base64
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
glasnostPythonDir = '/usr/local/lib/glasnost-tests'
|
||||
sys.path.insert(0, glasnostPythonDir)
|
||||
|
||||
import glasnost.common.context as context
|
||||
import glasnost.common.faults as faults
|
||||
import glasnost.common.tools_new as commonTools
|
||||
|
||||
from glasnost.proxy.tools import getProxyForServerRole
|
||||
|
||||
import getemailpassword
|
||||
import TestCase
|
||||
|
||||
|
||||
authenticationProxy = getProxyForServerRole('authentication')
|
||||
peopleProxy = getProxyForServerRole('people')
|
||||
|
||||
|
||||
class TestCase01_getUserToken(TestCase.PeopleTestCase):
|
||||
"""Test the AuthenticationProxy.getUserToken method."""
|
||||
pass
|
||||
|
||||
suite_testAuthentication = unittest.defaultTestLoader.loadTestsFromModule(
|
||||
sys.modules[__name__])
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
# -*- coding: iso-8859-15 -*-
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
glasnostPythonDir = '/usr/local/lib/glasnost-tests'
|
||||
sys.path.insert(0, glasnostPythonDir)
|
||||
|
||||
from GlasnostTestCase import MinimalTestCase
|
||||
|
||||
import glasnost.common.faults as faults
|
||||
|
||||
import glasnost.proxy.CardsProxy as CardsProxy
|
||||
import glasnost.proxy.kinds as kinds
|
||||
import glasnost.proxy.properties as properties
|
||||
from glasnost.proxy.tools import getProxyForServerRole
|
||||
|
||||
|
||||
cardsProxy = getProxyForServerRole('cards')
|
||||
|
||||
class CardsTestCase(MinimalTestCase):
|
||||
cardsCount = None
|
||||
|
||||
def setUp(self):
|
||||
MinimalTestCase.setUp(self)
|
||||
self.cardsCount = cardsProxy.getObjectsCount()
|
||||
|
||||
def tearDown(self):
|
||||
try:
|
||||
if self.cardsCount is not None:
|
||||
self.failUnlessEqual(cardsProxy.getObjectsCount(),
|
||||
self.cardsCount)
|
||||
finally:
|
||||
MinimalTestCase.tearDown(self)
|
||||
|
||||
|
||||
class BasicCardsTestCase(CardsTestCase):
|
||||
def test01_cardCreationAndDeletion(self):
|
||||
"""Test card creation and deletion"""
|
||||
|
||||
card = CardsProxy.Card()
|
||||
cardId = cardsProxy.addObject(card)
|
||||
card = cardsProxy.getObject(cardId)
|
||||
cardsProxy.deleteObject(cardId)
|
||||
|
||||
def test02_cardWithOneProperty(self):
|
||||
"""Test card with one property"""
|
||||
|
||||
card = CardsProxy.Card()
|
||||
card.properties = []
|
||||
|
||||
property = properties.Property()
|
||||
property.name = 'firstName'
|
||||
kind = kinds.String()
|
||||
kind.isTranslatable = 0
|
||||
property.kind = kind
|
||||
card.properties.append(property)
|
||||
|
||||
cardId = cardsProxy.addObject(card)
|
||||
card = cardsProxy.getObject(cardId)
|
||||
propertyNames = card.getPropertyNames()
|
||||
self.failUnlessEqual(propertyNames, ['firstName'])
|
||||
self.failUnlessEqual(
|
||||
card.getSlot('firstName').getKind().getThingName(), 'String')
|
||||
self.failIf(card.getSlot('firstName').getKind().isTranslatable)
|
||||
cardsProxy.deleteObject(cardId)
|
||||
|
||||
def test03_newCardWithOnePropertyAndValue(self):
|
||||
"""Test creating a card with one property and its value"""
|
||||
|
||||
card = CardsProxy.Card()
|
||||
card.properties = []
|
||||
|
||||
property = properties.Property()
|
||||
property.name = 'greetings'
|
||||
kind = kinds.String()
|
||||
property.kind = kind
|
||||
card.properties.append(property)
|
||||
card.getSlot('greetings').setValue('Hello World')
|
||||
self.failUnlessEqual(card.getSlot('greetings').getValue(),
|
||||
'Hello World')
|
||||
|
||||
cardId = cardsProxy.addObject(card)
|
||||
card = cardsProxy.getObject(cardId)
|
||||
propertyNames = card.getPropertyNames()
|
||||
self.failUnlessEqual(propertyNames, ['greetings'])
|
||||
self.failUnlessEqual(
|
||||
card.getSlot('greetings').getKind().getThingName(), 'String')
|
||||
self.failUnlessEqual(card.getSlot('greetings').getValue(),
|
||||
'Hello World')
|
||||
cardsProxy.deleteObject(cardId)
|
||||
|
||||
def test04_settingPropertyValue(self):
|
||||
"""Test setting a property value"""
|
||||
|
||||
card = CardsProxy.Card()
|
||||
card.properties = []
|
||||
|
||||
property = properties.Property()
|
||||
property.name = 'greetings'
|
||||
kind = kinds.String()
|
||||
property.kind = kind
|
||||
card.properties.append(property)
|
||||
|
||||
cardId = cardsProxy.addObject(card)
|
||||
card = cardsProxy.getObject(cardId)
|
||||
propertyNames = card.getPropertyNames()
|
||||
self.failUnlessEqual(propertyNames, ['greetings'])
|
||||
self.failUnlessEqual(
|
||||
card.getSlot('greetings').getKind().getThingName(), 'String')
|
||||
self.failUnlessEqual(card.getSlot('greetings').getValue(), None)
|
||||
|
||||
card.getSlot('greetings').setValue('Hello World')
|
||||
self.failUnlessEqual(card.getSlot('greetings').getValue(),
|
||||
'Hello World')
|
||||
|
||||
cardsProxy.modifyObject(card)
|
||||
card = cardsProxy.getObject(cardId)
|
||||
propertyNames = card.getPropertyNames()
|
||||
self.failUnlessEqual(propertyNames, ['greetings'])
|
||||
self.failUnlessEqual(
|
||||
card.getSlot('greetings').getKind().getThingName(), 'String')
|
||||
self.failUnlessEqual(card.getSlot('greetings').getValue(),
|
||||
'Hello World')
|
||||
|
||||
cardsProxy.deleteObject(cardId)
|
||||
|
||||
def test06_settingPropertyValueRemotely(self):
|
||||
"""Test setting a property value using remote function"""
|
||||
|
||||
card = CardsProxy.Card()
|
||||
card.properties = []
|
||||
|
||||
property = properties.Property()
|
||||
property.name = 'greetings'
|
||||
kind = kinds.String()
|
||||
property.kind = kind
|
||||
card.properties.append(property)
|
||||
|
||||
cardId = cardsProxy.addObject(card)
|
||||
|
||||
valueHolder = cardsProxy.getObjectSlotValueHolder(
|
||||
cardId, 'self.greetings')
|
||||
self.failUnlessEqual(valueHolder.value, None)
|
||||
valueHolder.value = 'Hello World!'
|
||||
cardsProxy.setObjectSlotValueHolder(
|
||||
cardId, 'self.greetings', valueHolder)
|
||||
valueHolder = cardsProxy.getObjectSlotValueHolder(
|
||||
cardId, 'self.greetings')
|
||||
self.failUnlessEqual(valueHolder.value, 'Hello World!')
|
||||
|
||||
cardsProxy.deleteObject(cardId)
|
||||
|
||||
|
||||
class ComplexCardsTestCase(CardsTestCase):
|
||||
cardId = None
|
||||
|
||||
def checkCard(self, card):
|
||||
propertyNames = card.getPropertyNames()
|
||||
self.failUnlessEqual(
|
||||
propertyNames,
|
||||
['greetings', 'firstName', 'lastName', 'login', 'email'])
|
||||
self.failUnlessEqual(
|
||||
card.getSlot('greetings').getKind().getThingName(), 'String')
|
||||
self.failUnless(card.getSlot('greetings').getKind().hideLabel)
|
||||
self.failUnlessEqual(
|
||||
card.getSlot('greetings').getKind().stateInEditMode,
|
||||
'read-only')
|
||||
self.failUnlessEqual(card.getSlot('greetings').getValue(),
|
||||
'Hello World')
|
||||
self.failUnlessEqual(
|
||||
card.getSlot('firstName').getKind().getThingName(), 'String')
|
||||
self.failIf(card.getSlot('firstName').getKind().isTranslatable)
|
||||
self.failUnlessEqual(card.getSlot('lastName').getKind().getThingName(),
|
||||
'String')
|
||||
self.failIf(card.getSlot('lastName').getKind().isTranslatable)
|
||||
self.failUnlessEqual(card.getSlot('login').getKind().getThingName(),
|
||||
'String')
|
||||
self.failIf(card.getSlot('login').getKind().isTranslatable)
|
||||
self.failUnlessEqual(card.getSlot('email').getKind().getThingName(),
|
||||
'Email')
|
||||
|
||||
def setUp(self):
|
||||
CardsTestCase.setUp(self)
|
||||
|
||||
card = CardsProxy.Card()
|
||||
card.properties = []
|
||||
|
||||
property = properties.Property()
|
||||
property.name = 'greetings'
|
||||
kind = kinds.String()
|
||||
kind.hideLabel = 1
|
||||
kind.stateInEditMode = 'read-only'
|
||||
property.kind = kind
|
||||
card.properties.append(property)
|
||||
card.getSlot('greetings').setValue('Hello World')
|
||||
|
||||
property = properties.Property()
|
||||
property.name = 'firstName'
|
||||
kind = kinds.String()
|
||||
kind.isTranslatable = 0
|
||||
property.kind = kind
|
||||
card.properties.append(property)
|
||||
|
||||
property = properties.Property()
|
||||
property.name = 'lastName'
|
||||
kind = kinds.String()
|
||||
kind.isTranslatable = 0
|
||||
property.kind = kind
|
||||
card.properties.append(property)
|
||||
|
||||
property = properties.Property()
|
||||
property.name = 'login'
|
||||
kind = kinds.String()
|
||||
kind.isTranslatable = 0
|
||||
property.kind = kind
|
||||
card.properties.append(property)
|
||||
|
||||
property = properties.Property()
|
||||
property.name = 'email'
|
||||
kind = kinds.Email()
|
||||
property.kind = kind
|
||||
card.properties.append(property)
|
||||
|
||||
self.cardId = cardsProxy.addObject(card)
|
||||
|
||||
def tearDown(self):
|
||||
if self.cardsCount is not None:
|
||||
cardsProxy.deleteObject(self.cardId)
|
||||
CardsTestCase.tearDown(self)
|
||||
|
||||
def test01_card(self):
|
||||
"""Test card with several properties"""
|
||||
|
||||
card = cardsProxy.getObject(self.cardId)
|
||||
self.checkCard(card)
|
||||
|
||||
def test02_cardImplementation(self):
|
||||
"""Test implementation of card with several properties"""
|
||||
|
||||
card = CardsProxy.Card()
|
||||
card.prototypeIds = [self.cardId]
|
||||
|
||||
cardId = cardsProxy.addObject(card)
|
||||
card = cardsProxy.getObject(cardId)
|
||||
self.checkCard(card)
|
||||
cardsProxy.deleteObject(cardId)
|
||||
|
||||
def test03_cardDepth2Implementation(self):
|
||||
"""Test depth 2 implementation of card with several properties"""
|
||||
|
||||
cardImplementationIds = []
|
||||
prototypeId = self.cardId
|
||||
for i in range(2):
|
||||
cardI = CardsProxy.Card()
|
||||
cardI.prototypeIds = [prototypeId]
|
||||
cardIId = cardsProxy.addObject(cardI)
|
||||
cardImplementationIds.append(cardIId)
|
||||
prototypeId = cardIId
|
||||
|
||||
cardId = cardImplementationIds[-1]
|
||||
card = cardsProxy.getObject(cardId)
|
||||
self.checkCard(card)
|
||||
cardImplementationIds.reverse()
|
||||
for cardImplemetationId in cardImplementationIds:
|
||||
cardsProxy.deleteObject(cardImplemetationId)
|
||||
|
||||
## def test04_cardDepth10ImplementationPerformance(self):
|
||||
## """Test depth 10 implementation performance of card with
|
||||
## several properties"""
|
||||
|
||||
## import time
|
||||
## startTime = time.time()
|
||||
|
||||
## self.test03_cardDepth10Implementation()
|
||||
|
||||
## duration = time.time() - startTime
|
||||
## self.failIf(
|
||||
## duration < 2.5,
|
||||
## 'Card prototyping is faster than before (= %s s)' % duration)
|
||||
## self.failIf(
|
||||
## duration > 4.0,
|
||||
## 'Card prototyping is slower than before (= %s s)' % duration)
|
||||
|
||||
suite1 = unittest.makeSuite(BasicCardsTestCase, 'test')
|
||||
suite2 = unittest.makeSuite(ComplexCardsTestCase, 'test')
|
||||
|
||||
allTests = unittest.TestSuite((suite1, suite2))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.TextTestRunner(verbosity=2).run(allTests)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue