- Réorg des web, edit, submit et tout. Plusieurs fois, et chaque fois un peu
plus loin. A priori, sans trop tester (mais c'est la première fois que j'allais aussi loin dans les cards), ça fonctionne. Il y a encore quelques questions mais on verra ça à Paris. (il y a eu un conflit au niveau des Cards, je ne vérifie pas si ça fonctionen toujours, je n'ai pas vraiment le temps...) (normalement, oui) - Ajout d'un LdapPeopleWeb pour aller chercher les personnes dans un annuaire LDAP. Ça va de pair avec l'authentification LDAP et ça marche. - Ajout d'un groupe "Logged Users" dont la possibilité a été découverte par hasard. (le groupe "General Public" m'acceptait quand je n'étais pas loggé et me refusait quand j'étais loggé via LDAP, avec un userId != people) - Ajout du support pour commentaires à un article, ça fonctionne mais c'est un peu caché pour le moment. - ...
This commit is contained in:
parent
99159e7dd7
commit
af3c12c90b
1
Makefile
1
Makefile
|
@ -358,6 +358,7 @@ po: glasnost-web/ \
|
|||
shared/proxy/ \
|
||||
shared/server/ \
|
||||
shared/web/ \
|
||||
system/ \
|
||||
talTranslations.py
|
||||
|
||||
cp po/glasnost-web/de.po po/glasnost-web/de.pox
|
||||
|
|
|
@ -80,9 +80,6 @@ UseHTTPS = false
|
|||
|
||||
The available options are:
|
||||
|
||||
BaseSectionLevel:
|
||||
Define the base tag for article subtitles (default: 2 -> <h2>)
|
||||
|
||||
CacheFiles:
|
||||
Define if Glasnost should cache page results in some circumstances (user
|
||||
not logged, no active session...) (default: false)
|
||||
|
@ -101,9 +98,12 @@ GettextDomains:
|
|||
Allows to add more gettext domains to look in for translations.
|
||||
|
||||
Profiling:
|
||||
Dumps profiling informations into /tmp/glasnost-web.prof
|
||||
Dumps profiling informations into /tmp/
|
||||
(default: false)
|
||||
|
||||
SectionLevel:
|
||||
Define the base tag for article subtitles (default: 2 -> <h2>)
|
||||
|
||||
ShowFullListInSelectIdForServerRoles:
|
||||
Define the server roles for which the whole list should appear in SelectId
|
||||
<select> widgets (instead of the last visited objects).
|
||||
|
|
|
@ -105,6 +105,10 @@ class Application(applications.Application):
|
|||
keywords = keywordsArguments.copy()
|
||||
if objectId is not None:
|
||||
keywords['id'] = objectId
|
||||
|
||||
if keywords.has_key('nextUri'):
|
||||
context.setVar('nextUri', keywords['nextUri'])
|
||||
del keywords['nextUri']
|
||||
|
||||
functionCode = function.func_code
|
||||
expectedArguments = functionCode.co_varnames[:functionCode.co_argcount]
|
||||
|
@ -242,6 +246,7 @@ class Application(applications.Application):
|
|||
preferences = None,
|
||||
readLanguages = None,
|
||||
req = req,
|
||||
sectionLevel = 1,
|
||||
serverRole = None,
|
||||
session = None,
|
||||
sessionToken = None,
|
||||
|
@ -560,7 +565,7 @@ class Application(applications.Application):
|
|||
for language in languages]
|
||||
try:
|
||||
possibleLanguages = translationsProxy.getPossibleLanguages()
|
||||
except faults.UnknownServerId:
|
||||
except (faults.UnknownServerId, faults.UnknownDispatcherInId):
|
||||
possibleLanguages = []
|
||||
if not virtualHost.language in possibleLanguages:
|
||||
possibleLanguages.append(virtualHost.language)
|
||||
|
@ -662,9 +667,9 @@ class Application(applications.Application):
|
|||
profiling = webTools.getConfig('Profiling', 'false') == 'true'
|
||||
handlerContext.setVar('profiling', profiling)
|
||||
|
||||
baseSectionLevel = int(
|
||||
webTools.getConfig('BaseSectionLevel', default = '2'))
|
||||
handlerContext.setVar('baseSectionLevel', baseSectionLevel)
|
||||
sectionLevel = int(
|
||||
webTools.getConfig('sectionLevel', default = 1))
|
||||
handlerContext.setVar('sectionLevel', sectionLevel)
|
||||
|
||||
cacheTime = int(webTools.getConfig('CacheTime', '15')) * 60
|
||||
handlerContext.setVar('cacheTime', cacheTime)
|
||||
|
|
|
@ -418,3 +418,11 @@ ul.multi>li>div{
|
|||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
span.comment-no {
|
||||
display: none;
|
||||
}
|
||||
|
||||
ul.article-meta {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,8 @@ import glasnost.common.xhtmlgenerator as X
|
|||
from glasnost.web.tools import *
|
||||
|
||||
|
||||
def index(nextUri = '', **keywords):
|
||||
def index(**keywords):
|
||||
nextUri = context.getVar('nextUri') or ''
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
session = context.getVar('session')
|
||||
|
@ -84,7 +85,8 @@ def index(nextUri = '', **keywords):
|
|||
return redirect(uri)
|
||||
|
||||
|
||||
def testCookie(nextUri = ''):
|
||||
def testCookie():
|
||||
nextUri = context.getVar('nextUri') or ''
|
||||
session = context.getVar('session')
|
||||
nextUri = cleanUpUri(nextUri, ['sessionToken'])
|
||||
canUseCookie = context.getVar('canUseCookie', default = 0)
|
||||
|
@ -93,3 +95,4 @@ def testCookie(nextUri = ''):
|
|||
nextUri,
|
||||
'sessionToken=' + context.getVar('sessionToken'))
|
||||
return redirect(nextUri)
|
||||
|
||||
|
|
|
@ -50,13 +50,16 @@ from glasnost.web.tools import *
|
|||
|
||||
|
||||
|
||||
def index(nextUri = '', access = '', again = '', error = '', **keywords):
|
||||
authWeb = getWebForServerRole('authentication-login-password')
|
||||
# TODO: getDefaultMethod
|
||||
return authWeb.login(nextUri, access, again, error, **keywords)
|
||||
def index(access = ''):
|
||||
authAdmin = getWebForServerRole('authentication').getAdmin()
|
||||
for authMethod in authAdmin.authenticationMethods or ['login-password']:
|
||||
authWeb = getWebForServerRole('authentication-%s' % authMethod)
|
||||
if authWeb:
|
||||
break
|
||||
return authWeb.login(access)
|
||||
|
||||
|
||||
def logout(nextUri = ''):
|
||||
def logout():
|
||||
authWeb = getWebForServerRole('authentication')
|
||||
return authWeb.logout(nextUri)
|
||||
return authWeb.logout()
|
||||
|
||||
|
|
|
@ -53,24 +53,25 @@ import glasnost.common.xhtmlgenerator as X
|
|||
from glasnost.web.tools import *
|
||||
|
||||
|
||||
def _switchLang(lang, nextUri):
|
||||
def _switchLang(lang):
|
||||
if not lang in languageKeys:
|
||||
return writePageLayout(
|
||||
X.p(_('The language you asked for is not available.')),
|
||||
'Language not available')
|
||||
nextUri = context.getVar('nextUri') or ''
|
||||
if not nextUri:
|
||||
nextUri = X.rootUrl()
|
||||
uri = X.roleUrl('define').add('lang', lang).add('nextUri', nextUri)
|
||||
return redirect(uri)
|
||||
|
||||
def english(nextUri = ''):
|
||||
return _switchLang('en', nextUri)
|
||||
def english():
|
||||
return _switchLang('en')
|
||||
|
||||
def french(nextUri = ''):
|
||||
return _switchLang('fr', nextUri)
|
||||
def french():
|
||||
return _switchLang('fr')
|
||||
|
||||
def spanish(nextUri = ''):
|
||||
return _switchLang('es', nextUri)
|
||||
def spanish():
|
||||
return _switchLang('es')
|
||||
|
||||
index = _switchLang
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ then
|
|||
fi
|
||||
|
||||
echo "Installing glasnost://system environment in root-system/"
|
||||
mkdir system/data
|
||||
test -d system/data || mkdir system/data
|
||||
rm -f config && make config config-system install \
|
||||
GLASNOST=glasnost-system PORT=8500 \
|
||||
PREFIX=`pwd`/root-system/usr/local \
|
||||
|
|
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
|
@ -977,5 +977,6 @@ class ArticlesServer(ArticlesCommonMixin, ObjectsServer):
|
|||
articlesServer = ArticlesServer()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
articlesServer.launch(applicationName, applicationRole)
|
||||
|
||||
|
|
|
@ -106,7 +106,9 @@ class AuthenticationLdapVirtualServer(AdministrableVirtualServer):
|
|||
#'uid=%s, ou=People, o=entrouvert, c=be' %
|
||||
except ldap.INVALID_CREDENTIALS:
|
||||
raise faults.WrongPassword('****')
|
||||
return 'glasnost://system/atoms/1'
|
||||
return '%s/ldappeople/%s' % (
|
||||
commonTools.extractDispatcherId(self.virtualServerId),
|
||||
authenticationObject.login)
|
||||
|
||||
def deleteAccount(self, authenticationObject):
|
||||
pass
|
||||
|
|
|
@ -123,7 +123,7 @@ class Card(ObjectServerMixin, CardCommon):
|
|||
for slotName in ['properties', 'prototypeIds']:
|
||||
slot = self.getSlot(slotName)
|
||||
kind = slot.getKind()
|
||||
if kind.isAutomaticalyModified:
|
||||
if kind.isAutomaticallyModified:
|
||||
kind.setAutomaticalValue(slot)
|
||||
continue
|
||||
if not kind.isImportable():
|
||||
|
|
|
@ -47,6 +47,7 @@ __version__ = '$Revision$'[11:-2]
|
|||
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
glasnostPythonDir = '/usr/local/lib/glasnost-devel' # changed on make install
|
||||
sys.path.insert(0, glasnostPythonDir)
|
||||
|
@ -74,62 +75,69 @@ register(AdminComments)
|
|||
|
||||
|
||||
class Comment(ObjectServerMixin, CommentCommon):
|
||||
pass
|
||||
def checkAddIsPossible(self):
|
||||
ObjectServerMixin.checkAddIsPossible(self)
|
||||
virtualServerId = context.getVar('applicationId')
|
||||
ultimateParentId = self.getServer().getParentId(self)
|
||||
parent = getObject(ultimateParentId)
|
||||
# if it booms out; adding was not possible, we get what we want
|
||||
# TODO: parent object should tell if it accepts comments
|
||||
|
||||
def modify(self, changes, givenSlotNames = None):
|
||||
return ObjectServerMixin.modify(self, changes,
|
||||
['language', 'title', 'body'])
|
||||
|
||||
def setAutomaticalSlots(self, parentSlot = None):
|
||||
ObjectServerMixin.setAutomaticalSlots(self, parentSlot = parentSlot)
|
||||
self.authorId = getProxyForServerRole('authentication').getUserId()
|
||||
self.creationTime = time.time()
|
||||
register(Comment)
|
||||
|
||||
|
||||
class CommentsServer(CommentsCommonMixin, ObjectsServer):
|
||||
useAdminWritersSet = 1
|
||||
|
||||
def canAddObject(self):
|
||||
# FIXME: should check if parent forum allows anonymous posts
|
||||
return 1
|
||||
|
||||
def getComments(self, replyToId):
|
||||
def canGetObject(self, objectId):
|
||||
result = ObjectsServer.canGetObject(self, objectId)
|
||||
if result == 0:
|
||||
return 0
|
||||
virtualServerId = context.getVar('applicationId')
|
||||
virtualServer = self.getVirtualServer(virtualServerId)
|
||||
objects = virtualServer.objects.values()
|
||||
ids = [o.id for o in objects if o.replyToId == replyToId]
|
||||
# Sort the comments by chronological order.
|
||||
ids.sort(lambda id1, id2:
|
||||
cmp(int(commonTools.extractLocalId(id1)),
|
||||
int(commonTools.extractLocalId(id2))))
|
||||
return [self.getObjectXmlRpc(commentId) for commentId in ids]
|
||||
object = virtualServer.loadObjectCore(objectId)
|
||||
parentId = self.getParentId(object)
|
||||
roleProxy = getProxyForServerRole(
|
||||
commonTools.extractRole(parentId))
|
||||
return roleProxy.canGetObject(parentId)
|
||||
|
||||
def getEveryCommentsUnder(self, replyToId):
|
||||
# FIXME: Need to sort the ids.
|
||||
virtualServerId = context.getVar('applicationId')
|
||||
virtualServer = self.getVirtualServer(virtualServerId)
|
||||
objects = virtualServer.objects.values()
|
||||
everyIds = [o.id for o in objects if o.replyToId == replyToId]
|
||||
doneIds = [replyToId]
|
||||
i = 0
|
||||
while i < len(everyIds):
|
||||
id = everyIds[i]
|
||||
i += 1
|
||||
if id in doneIds:
|
||||
continue
|
||||
doneIds.append(id)
|
||||
everyIds += [o.id for o in objects if o.replyToId == id]
|
||||
return [self.getObjectXmlRpc(commentId) for commentId in everyIds]
|
||||
def canGetObjects(self):
|
||||
return 0
|
||||
|
||||
def incNbReplies(self, commentId):
|
||||
def getObjectIdsWithParent(self, parentId):
|
||||
virtualServerId = context.getVar('applicationId')
|
||||
virtualServer = self.getVirtualServer(virtualServerId)
|
||||
objects = virtualServer.objects.values()
|
||||
for o in objects:
|
||||
if o.id==commentId:
|
||||
o.nbReplies = o.nbReplies + 1
|
||||
o.markAsDirty()
|
||||
tempResult = []
|
||||
for objectId, objectCore in virtualServer.objects.items():
|
||||
if self.getParentId(objectCore) == parentId:
|
||||
tempResult.append(objectId)
|
||||
result = []
|
||||
for objectId in tempResult:
|
||||
if self.canGetObject(objectId):
|
||||
result.append(objectId)
|
||||
return result
|
||||
|
||||
def getParentId(self, comment):
|
||||
currentComment = comment
|
||||
while 1:
|
||||
role = commonTools.extractRole(currentComment.parentId)
|
||||
if role != 'comments':
|
||||
return currentComment.parentId
|
||||
currentComment = self.getObjectCore(currentComment.parentId)
|
||||
|
||||
def registerPublicMethods(self):
|
||||
ObjectsServer.registerPublicMethods(self)
|
||||
self.registerPublicMethod('getComments')
|
||||
self.registerPublicMethod('incNbReplies')
|
||||
|
||||
self.registerPublicMethod('getObjectIdsWithParent')
|
||||
|
||||
commentsServer = CommentsServer()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
commentsServer.launch(applicationName, applicationRole)
|
||||
|
||||
|
|
|
@ -99,6 +99,11 @@ class GroupIntersection(GroupMixin, commonGroups.GroupIntersection):
|
|||
objects.register(GroupIntersection)
|
||||
|
||||
|
||||
class GroupRole(GroupMixin, commonGroups.GroupRole):
|
||||
pass
|
||||
objects.register(GroupRole)
|
||||
|
||||
|
||||
class GroupUnion(GroupMixin, commonGroups.GroupUnion):
|
||||
pass
|
||||
objects.register(GroupUnion)
|
||||
|
|
|
@ -84,6 +84,29 @@ class SessionsVirtualServer(VirtualServer):
|
|||
|
||||
class SessionsServer(Server):
|
||||
VirtualServer = SessionsVirtualServer
|
||||
temporaryData = None
|
||||
|
||||
def addTemporaryData(self, sessionToken, data):
|
||||
if not self.temporaryData:
|
||||
self.temporaryData = {}
|
||||
while 1:
|
||||
dataToken = str(self.randomGenerator.uniform(0.1, 1))
|
||||
if not self.temporaryData.has_key(dataToken):
|
||||
break
|
||||
self.temporaryData[sessionToken+dataToken] = data
|
||||
return dataToken
|
||||
|
||||
def getTemporaryData(self, sessionToken, dataToken):
|
||||
if not self.temporaryData or \
|
||||
not self.temporaryData.has_key(sessionToken+dataToken):
|
||||
return None
|
||||
return self.temporaryData[sessionToken+dataToken]
|
||||
|
||||
def delTemporaryData(self, sessionToken, dataToken):
|
||||
if not self.temporaryData or \
|
||||
not self.temporaryData.has_key(sessionToken+dataToken):
|
||||
return None
|
||||
del self.temporaryData[sessionToken+dataToken]
|
||||
|
||||
def convertVirtualServersIds(self, sourceDispatcherId,
|
||||
destinationDispatcherId):
|
||||
|
@ -100,6 +123,10 @@ class SessionsServer(Server):
|
|||
self.rememberOldSession(virtualServer,
|
||||
virtualServer.objects[sessionToken])
|
||||
del virtualServer.objects[sessionToken]
|
||||
if self.temporaryData:
|
||||
for k in self.temporaryData.keys():
|
||||
if k.startswith(sessionToken):
|
||||
del self.temporaryData[k]
|
||||
virtualServer.lock.release()
|
||||
virtualServer.markCoreAsDirty()
|
||||
#invalidateValue(no id!)
|
||||
|
@ -192,6 +219,9 @@ class SessionsServer(Server):
|
|||
self.registerPublicMethod('getObject')
|
||||
self.registerPublicMethod('newObject')
|
||||
self.registerPublicMethod('setObject')
|
||||
self.registerPublicMethod('addTemporaryData')
|
||||
self.registerPublicMethod('getTemporaryData')
|
||||
self.registerPublicMethod('delTemporaryData')
|
||||
|
||||
def rememberOldSession(self, virtualServer, session):
|
||||
if not session.has_key('userId'):
|
||||
|
|
|
@ -58,10 +58,18 @@ class ArticleCommon(ObjectCommon):
|
|||
authorsSet_kindName = 'AuthorsSet'
|
||||
|
||||
body = None
|
||||
body_kind_balloonHelp = N_('Enter the text of the document.')
|
||||
body_kind_isRequired = 1
|
||||
body_kind_useCustomStorage = 1
|
||||
body_kindName = 'String'
|
||||
class body_kindClass:
|
||||
_kindName = 'String'
|
||||
balloonHelp = N_('Enter the text of the document.')
|
||||
label = N_('Text')
|
||||
isRequired = 1
|
||||
useCustomStorage = 1
|
||||
widget_colSpan = 2
|
||||
widget_preview = 1
|
||||
widgetName = 'TextArea'
|
||||
|
||||
def getTextFormat(self, slot):
|
||||
return slot.getObject().format
|
||||
|
||||
creationTime = None
|
||||
creationTime_kindName = 'CreationTime'
|
||||
|
|
|
@ -49,18 +49,8 @@ from ObjectsCommon import AdminCommon, ObjectCommon, ObjectsCommonMixin
|
|||
|
||||
|
||||
class AdminCommentsCommon(AdminCommon):
|
||||
allowAnonymousComments = 0
|
||||
allowAnonymousComments_kind_isRequired = 1
|
||||
allowAnonymousComments_kindName = 'Boolean'
|
||||
|
||||
serverRole = 'comments'
|
||||
|
||||
def getOrderedLayoutSlotNames(self, parentSlot = None):
|
||||
slotNames = AdminCommon.getOrderedLayoutSlotNames(
|
||||
self, parentSlot = parentSlot)
|
||||
slotNames += ['allowAnonymousComments']
|
||||
return slotNames
|
||||
|
||||
|
||||
class CommentCommon(ObjectCommon):
|
||||
authorId = None
|
||||
|
@ -72,33 +62,23 @@ class CommentCommon(ObjectCommon):
|
|||
body_kind_balloonHelp = N_('Enter the text of your comment.')
|
||||
body_kind_isTranslatable = 0
|
||||
body_kind_isRequired = 1
|
||||
body_kind_textFormat = 'spip'
|
||||
body_kindName = 'String'
|
||||
|
||||
creationTime = None
|
||||
creationTime_kind_importExport = 'from-server-only'
|
||||
creationTime_kindName = 'CreationTime'
|
||||
|
||||
serverRole = 'comments'
|
||||
|
||||
replyToId = None
|
||||
replyToId_kind_importExport = 'from-server-only'
|
||||
replyToId_kindName = 'Id'
|
||||
|
||||
name = None
|
||||
name_kind_balloonHelp = N_('Enter your name (if you want).')
|
||||
name_kind_isRequired = 0
|
||||
name_kindName = 'String'
|
||||
parentId = None
|
||||
parentId_kindName = 'Id'
|
||||
|
||||
title = None
|
||||
title_kind_balloonHelp = N_('Enter the title of your comment.')
|
||||
title_kind_isRequired = 1
|
||||
title_kindName = 'String'
|
||||
|
||||
nbReplies = 0
|
||||
nbReplies_kind_importExport = 'from-server-only'
|
||||
nbReplies_kindName = 'Integer'
|
||||
nbReplies_kind_defaultValue = 0
|
||||
|
||||
|
||||
def canCache(self):
|
||||
return 1
|
||||
|
||||
|
@ -110,7 +90,7 @@ class CommentCommon(ObjectCommon):
|
|||
def getOrderedLayoutSlotNames(self, parentSlot = None):
|
||||
slotNames = ObjectCommon.getOrderedLayoutSlotNames(
|
||||
self, parentSlot = parentSlot)
|
||||
slotNames += ['title', 'body', 'name', 'sourceId', 'authorId']
|
||||
slotNames += ['title', 'authorId', 'body' ]
|
||||
return slotNames
|
||||
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ class AdminGroups(objects.AdminCommon):
|
|||
|
||||
|
||||
class GroupAbstract(objects.ObjectCommon):
|
||||
# FIME: Replace by kind ServerRoles.
|
||||
# FIXME: Replace by kind ServerRoles.
|
||||
acceptedRoles = None
|
||||
acceptedRoles_kindName = 'AcceptedRoles'
|
||||
|
||||
|
@ -127,7 +127,8 @@ class GroupAbstract(objects.ObjectCommon):
|
|||
if groupId == system.generalPublicId:
|
||||
if results.has_key(groupId):
|
||||
return results[groupId]
|
||||
if not serverRoles or 'people' in serverRoles:
|
||||
if not serverRoles or 'people' in serverRoles or \
|
||||
'ldappeople' in serverRoles:
|
||||
smallAndLarge = 'uncountable', 'uncountable'
|
||||
else:
|
||||
smallAndLarge = [], []
|
||||
|
@ -153,8 +154,9 @@ class GroupAbstract(objects.ObjectCommon):
|
|||
if groupId == system.generalPublicId:
|
||||
if results.has_key(groupId):
|
||||
return results[groupId]
|
||||
result = not objectId \
|
||||
or commonTools.extractRole(objectId) == 'people'
|
||||
result = not objectId or \
|
||||
commonTools.extractRole(objectId) in \
|
||||
('people', 'ldappeople')
|
||||
results[groupId] = result
|
||||
return result
|
||||
else:
|
||||
|
@ -164,8 +166,18 @@ class GroupAbstract(objects.ObjectCommon):
|
|||
|
||||
class GroupCountableAbstract(GroupAbstract):
|
||||
membersSet = None
|
||||
membersSet_kind_itemKind_valueName = 'Id'
|
||||
membersSet_kindName = 'Sequence'
|
||||
class membersSet_kindClass:
|
||||
_kindName = 'Sequence'
|
||||
class itemKind_valueClass:
|
||||
_kindName = 'Id'
|
||||
def getServerRoles(self, slot):
|
||||
acceptedRoles = slot.getObject().acceptedRoles
|
||||
if acceptedRoles is None:
|
||||
return []
|
||||
if acceptedRoles == ['__all__']:
|
||||
return None
|
||||
return acceptedRoles
|
||||
label = N_('Members')
|
||||
|
||||
def getOrderedLayoutSlotNames(self, parentSlot = None):
|
||||
import glasnost.proxy.GroupsProxy as proxyGroups
|
||||
|
@ -338,6 +350,25 @@ class GroupIntersection(GroupCountableAbstract):
|
|||
return result
|
||||
|
||||
|
||||
class GroupRole(GroupAbstract):
|
||||
def contains2(self, objectId, indirect, results):
|
||||
if self.acceptedRoles is None:
|
||||
return 1
|
||||
if not objectId:
|
||||
return 0
|
||||
role = commonTools.extractRole(objectId)
|
||||
return role in self.acceptedRoles
|
||||
|
||||
def getContainedIds2(self, serverRoles, results):
|
||||
# FIXME: not sure ?
|
||||
if not serverRoles or self.acceptedRoles is None:
|
||||
return 'uncountable', 'uncountable'
|
||||
for acceptedRole in self.acceptedRoles:
|
||||
if acceptedRole in serverRoles:
|
||||
return 'uncountable', 'uncountable'
|
||||
return [], []
|
||||
|
||||
|
||||
class GroupUnion(GroupCountableAbstract):
|
||||
membersSet_kind_balloonHelp = N_('Select the items of this group.')
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -146,10 +146,7 @@ class Aspect(things.BaseThing):
|
|||
def getValues(self, slot, fields):
|
||||
nameSlot = slot.getContainer().getSlot(
|
||||
'name', parentSlot = slot.parent)
|
||||
error, errorFields, name = nameSlot.getKind().submitField2(
|
||||
nameSlot, fields)
|
||||
if error:
|
||||
name = None
|
||||
name = nameSlot.getValue()
|
||||
if name:
|
||||
card = slot.getObject()
|
||||
if card.hasSlotName(name):
|
||||
|
|
|
@ -66,6 +66,7 @@ def parseGlasnostLink(link):
|
|||
|
||||
Note that those can contains replaceable items (with replaceSpecialTags).
|
||||
"""
|
||||
link = link.replace('\n', ' ')
|
||||
matchObject = re.match(
|
||||
r'(?P<role>alias|art(icle)?|atom|book|card|election|file|'\
|
||||
'grade|group|heading|im(g|age)?|person(ne)?|rubri(c|que)|'\
|
||||
|
@ -1781,7 +1782,7 @@ def makeHtmlFromReStructuredText(text, simple = 0, inline = 0, **keywords):
|
|||
self.translator_class = GlasnostHTMLTranslator
|
||||
sectionLevel = 2
|
||||
if keywords.has_key('sectionLevel'):
|
||||
sectionLevel = int(keywords['sectionLevel'])
|
||||
sectionLevel = int(keywords['sectionLevel']) - 1
|
||||
self.translator_class.baseSectionLevel = sectionLevel
|
||||
|
||||
class GlasnostHTMLTranslator(htmlTranslator):
|
||||
|
|
|
@ -47,6 +47,8 @@ __version__ = '$Revision$'[11:-2]
|
|||
|
||||
import things
|
||||
|
||||
import glasnost.common.tools_new as commonTools
|
||||
|
||||
|
||||
class Property(things.BaseThing):
|
||||
kind = None
|
||||
|
@ -65,6 +67,10 @@ class Property(things.BaseThing):
|
|||
name_kind_label = N_('Name')
|
||||
name_kindName = 'PythonIdentifier'
|
||||
|
||||
def getDefaultValue(self, slot):
|
||||
property = commonTools.newThing('other', 'Property')
|
||||
return property
|
||||
|
||||
def getOrderedLayoutSlotNames(self, parentSlot = None):
|
||||
slotNames = things.BaseThing.getOrderedLayoutSlotNames(
|
||||
self, parentSlot = parentSlot)
|
||||
|
|
|
@ -160,7 +160,7 @@ class BaseSlot:
|
|||
|
||||
def getFieldOption(self, fields, optionName, default = None):
|
||||
fieldOptionName = self.getFieldOptionName(optionName)
|
||||
if not fields.has_key(fieldOptionName):
|
||||
if not fields or not fields.has_key(fieldOptionName):
|
||||
return default
|
||||
return fields[fieldOptionName]
|
||||
|
||||
|
@ -497,7 +497,10 @@ class Item(BaseSlot): # Sequence Item.
|
|||
return str(self.index)
|
||||
|
||||
def getLocalValue(self, setIfNone = 0):
|
||||
return self.getContainer(setIfNone = setIfNone)[self.index]
|
||||
container = self.getContainer(setIfNone = setIfNone)
|
||||
if container is None:
|
||||
return None
|
||||
return container[self.index]
|
||||
|
||||
def getPath(self):
|
||||
return '%s[%s]' % (self.getContainerPath(), self.index)
|
||||
|
@ -688,7 +691,7 @@ class Property(Attribute): # Card Property.
|
|||
self.setValue(None)
|
||||
|
||||
def getKind(self):
|
||||
# This doesn't work, because the kind would always be a commom kind.
|
||||
# This doesn't work, because the kind would always be a common kind.
|
||||
# import properties
|
||||
# return properties.Property().newKind()
|
||||
property = commonTools.newThing('other', 'Property')
|
||||
|
|
|
@ -46,4 +46,5 @@ __version__ = '$Revision$'[11:-2]
|
|||
|
||||
|
||||
generalPublicId = 'glasnost://system/groups/1'
|
||||
loggedUsersGroupId = 'glasnost://system/groups/2'
|
||||
|
||||
|
|
|
@ -71,6 +71,11 @@ class GroupIntersection(objects.ObjectGtkMixin, proxyGroups.GroupIntersection):
|
|||
objects.register(GroupIntersection)
|
||||
|
||||
|
||||
class GroupRole(objects.ObjectGtkMixin, proxyGroups.GroupRole):
|
||||
pass
|
||||
objects.register(GroupRole)
|
||||
|
||||
|
||||
class GroupUnion(objects.ObjectGtkMixin, proxyGroups.GroupUnion):
|
||||
pass
|
||||
objects.register(GroupUnion)
|
||||
|
|
|
@ -48,7 +48,7 @@ __version__ = '$Revision$'[11:-2]
|
|||
from glasnost.common.CommentsCommon import *
|
||||
import glasnost.common.tools_new as commonTools
|
||||
|
||||
from DispatcherProxy import callServer, getApplicationToken
|
||||
from DispatcherProxy import MultiCall, callServer, getApplicationToken
|
||||
from ObjectsProxy import register, AdminMixin, ObjectProxyMixin, ObjectsProxy
|
||||
from tools import *
|
||||
|
||||
|
@ -64,36 +64,22 @@ register(Comment)
|
|||
|
||||
|
||||
class CommentsProxy(CommentsCommonMixin, ObjectsProxy):
|
||||
def getComments(self, replyToId, serverId = None):
|
||||
serverId = self.getServerId(serverId = serverId)
|
||||
def getObjectIdsWithParent(self, parentId, serverId = None):
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
results = callServer(
|
||||
serverId,
|
||||
'getComments',
|
||||
[serverId, getApplicationToken(), userToken, replyToId])
|
||||
ret = []
|
||||
for objectImport in results:
|
||||
object = commonTools.importThing(objectImport)
|
||||
ret.append(object)
|
||||
return ret
|
||||
serverId = self.getServerId(serverId = serverId)
|
||||
return callServer(
|
||||
serverId,
|
||||
'getObjectIdsWithParent',
|
||||
[serverId, getApplicationToken(), userToken, parentId])
|
||||
|
||||
def getObjectsWithParent(self, parentId, serverId = None):
|
||||
objectIds = self.getObjectIdsWithParent(parentId, serverId = serverId)
|
||||
multiCall = MultiCall()
|
||||
for objectId in objectIds:
|
||||
self.getObject(objectId, multiCall = multiCall)
|
||||
lazyObjects = multiCall.call()
|
||||
objects = {}
|
||||
for i in range(len(objectIds)):
|
||||
objects[objectIds[i]] = lazyObjects[i]()
|
||||
return objects
|
||||
|
||||
def getEveryCommentsUnder(self, replyToId, serverId = None):
|
||||
serverId = self.getServerId(serverId = serverId)
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
results = callServer(
|
||||
serverId,
|
||||
'getEveryCommentsUnder',
|
||||
[serverId, getApplicationToken(), userToken, replyToId])
|
||||
ret = []
|
||||
for objectImport in results:
|
||||
object = commonTools.importThing(objectImport)
|
||||
ret.append(object)
|
||||
return ret
|
||||
|
||||
def incNbReplies(self, commentId, serverId = None):
|
||||
serverId = self.getServerId(serverId = serverId)
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
results = callServer(
|
||||
serverId,
|
||||
'incNbReplies',
|
||||
[serverId, getApplicationToken(), userToken, commentId])
|
||||
|
|
|
@ -79,11 +79,17 @@ class GroupIntersection(GroupMixin, commonGroups.GroupIntersection):
|
|||
objects.register(GroupIntersection)
|
||||
|
||||
|
||||
class GroupRole(GroupMixin, commonGroups.GroupRole):
|
||||
pass
|
||||
objects.register(GroupRole)
|
||||
|
||||
|
||||
class GroupUnion(GroupMixin, commonGroups.GroupUnion):
|
||||
pass
|
||||
objects.register(GroupUnion)
|
||||
|
||||
|
||||
|
||||
class GroupsProxy(commonGroups.GroupsCommonMixin, objects.ObjectsProxy):
|
||||
def addObjectMember(self, objectId, memberId):
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
|
|
|
@ -1276,6 +1276,10 @@ class ObjectsProxy(ObjectsCommonMixin, AdministrableProxyMixin, Proxy):
|
|||
if not objectId:
|
||||
return ''
|
||||
label, language = self.getObjectLabelAndLanguage(objectId)
|
||||
if destinationLanguages[0] == context.getVar('readLanguages')[0] and \
|
||||
language == 'en' and hasattr(_.im_self, '_catalog') and \
|
||||
_.im_self._catalog.has_key(label):
|
||||
return _(label)
|
||||
translationsProxy = getProxyForServerRole('translations')
|
||||
if translationsProxy:
|
||||
labelTranslated = translationsProxy.getTranslation(
|
||||
|
@ -1569,7 +1573,7 @@ class ObjectsProxy(ObjectsCommonMixin, AdministrableProxyMixin, Proxy):
|
|||
userToken, objectExport, givenSlotNames])
|
||||
return None
|
||||
|
||||
def newObject(self, fields):
|
||||
def newObject(self, fields = None):
|
||||
"""Instanciate a new object.
|
||||
|
||||
The class of the new object instance is stored in the *objectClassName*
|
||||
|
|
|
@ -54,6 +54,36 @@ from ObjectsProxy import Proxy
|
|||
class SessionsProxy(Proxy):
|
||||
serverRole = 'sessions'
|
||||
|
||||
def addTemporaryData(self, data, serverId = None):
|
||||
userToken = context.getVar('userToken')
|
||||
sessionToken = context.getVar('sessionToken')
|
||||
serverId = self.getServerId(serverId = serverId)
|
||||
return callServer(
|
||||
serverId,
|
||||
'addTemporaryData',
|
||||
[serverId, getApplicationToken(), userToken,
|
||||
sessionToken, data])
|
||||
|
||||
def delTemporaryData(self, dataToken, serverId = None):
|
||||
userToken = context.getVar('userToken')
|
||||
sessionToken = context.getVar('sessionToken')
|
||||
serverId = self.getServerId(serverId = serverId)
|
||||
callServer(
|
||||
serverId,
|
||||
'delTemporaryData',
|
||||
[serverId, getApplicationToken(), userToken,
|
||||
sessionToken, dataToken])
|
||||
|
||||
def getTemporaryData(self, dataToken, serverId = None):
|
||||
userToken = context.getVar('userToken')
|
||||
sessionToken = context.getVar('sessionToken')
|
||||
serverId = self.getServerId(serverId = serverId)
|
||||
return callServer(
|
||||
serverId,
|
||||
'getTemporaryData',
|
||||
[serverId, getApplicationToken(), userToken,
|
||||
sessionToken, dataToken])
|
||||
|
||||
def deleteSession(self, objectToken, serverId = None):
|
||||
userToken = context.getVar('userToken')
|
||||
serverId = self.getServerId(serverId = serverId)
|
||||
|
|
|
@ -57,6 +57,8 @@ from ObjectsProxy import register, AdminWithoutWritersMixin, \
|
|||
AdministrableProxyMixin, ObjectProxyMixin, Proxy
|
||||
from tools import *
|
||||
|
||||
import kinds
|
||||
import widgets
|
||||
|
||||
class AdminTranslations(AdminWithoutWritersMixin, AdminTranslationsCommon):
|
||||
pass
|
||||
|
@ -89,7 +91,7 @@ class TranslationsProxy(TranslationsCommonMixin, AdministrableProxyMixin,
|
|||
'canModifyLocalization',
|
||||
[serverId, getApplicationToken(), userToken, localizationKey,
|
||||
sourceStringDigest])
|
||||
|
||||
|
||||
def getLanguagesForObjectId(self, objectId):
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
serverId = commonTools.makeApplicationId(objectId, self.serverRole)
|
||||
|
|
|
@ -92,10 +92,10 @@ class ObjectServerMixin(things.ThingMixin):
|
|||
The client that want to operate on the object is usualy a other server.
|
||||
"""
|
||||
|
||||
id_kind_isAutomaticalyModified = 1
|
||||
id_kind_isAutomaticallyModified = 1
|
||||
# The method id_kind_setAutomaticalValue() is defined below.
|
||||
|
||||
version_kind_isAutomaticalyModified = 1
|
||||
version_kind_isAutomaticallyModified = 1
|
||||
# The method version_kind_setAutomaticalValue() is defined below.
|
||||
|
||||
def __getinitargs__(self):
|
||||
|
@ -217,7 +217,7 @@ class ObjectServerMixin(things.ThingMixin):
|
|||
kind = slot.getKind()
|
||||
if not kind.isModifiable:
|
||||
continue
|
||||
if kind.isAutomaticalyModified:
|
||||
if kind.isAutomaticallyModified:
|
||||
continue
|
||||
if not kind.isImportable():
|
||||
continue
|
||||
|
@ -304,7 +304,7 @@ class ObjectServerMixin(things.ThingMixin):
|
|||
kind = slot.getKind()
|
||||
if not kind.isModifiable:
|
||||
continue
|
||||
if kind.isAutomaticalyModified:
|
||||
if kind.isAutomaticallyModified:
|
||||
kind.setAutomaticalValue(slot)
|
||||
continue
|
||||
if not kind.isImportable():
|
||||
|
@ -425,7 +425,7 @@ class ObjectServerMixin(things.ThingMixin):
|
|||
for slotName in self.getModifySlotNames():
|
||||
slot = self.getSlot(slotName)
|
||||
kind = slot.getKind()
|
||||
if kind.isAutomaticalyModified:
|
||||
if kind.isAutomaticallyModified:
|
||||
kind.setAutomaticalValue(slot, init = 1)
|
||||
|
||||
def version_kind_setAutomaticalValue(self, slot, init = 0):
|
||||
|
@ -1086,8 +1086,9 @@ class Server(things.BaseThing, applications.Application):
|
|||
% applicationName)
|
||||
sys.exit(1)
|
||||
|
||||
goDaemon()
|
||||
self.setLogFile()
|
||||
if not context.getVar('verbose'):
|
||||
goDaemon()
|
||||
self.setLogFile()
|
||||
self.init()
|
||||
self.load()
|
||||
self.startRpcServer()
|
||||
|
|
|
@ -61,9 +61,6 @@ register(AdminAppointments)
|
|||
|
||||
_Appointment = Appointment
|
||||
class Appointment(ObjectWebMixin, Appointment):
|
||||
addToId_kindName = None
|
||||
addToSlot_kindName = None
|
||||
|
||||
body_kind_widget_fieldLabel = N_('Text')
|
||||
body_kind_widget_cols = 40
|
||||
body_kind_widget_colSpan = 2
|
||||
|
@ -689,8 +686,8 @@ class AppointmentsWeb(ObjectsWebMixin, AppointmentsProxy):
|
|||
ul += X.li(yearLink)
|
||||
return X.array(ul, self.getViewAllButtonsBarLayout())
|
||||
|
||||
def submitAddObject(self, object, **keywords):
|
||||
result = ObjectsWebMixin.submitAddObject(self, object, **keywords)
|
||||
def submitAddObject(self, object):
|
||||
result = ObjectsWebMixin.submitAddObject(self, object)
|
||||
if result:
|
||||
return result
|
||||
groupsProxy = getProxyForServerRole('groups')
|
||||
|
@ -698,8 +695,8 @@ class AppointmentsWeb(ObjectsWebMixin, AppointmentsProxy):
|
|||
groupsProxy.addObjectMember(groupId, object.id)
|
||||
# what happens if it fails ?
|
||||
|
||||
def submitModifyObject(self, object, **keywords):
|
||||
result = ObjectsWebMixin.submitModifyObject(self, object, **keywords)
|
||||
def submitModifyObject(self, object):
|
||||
result = ObjectsWebMixin.submitModifyObject(self, object)
|
||||
if result:
|
||||
return result
|
||||
groupsProxy = getProxyForServerRole('groups')
|
||||
|
|
|
@ -54,7 +54,8 @@ import glasnost.common.slots as slots
|
|||
|
||||
from glasnost.proxy.ArticlesProxy import *
|
||||
|
||||
from ObjectsWeb import register, AdminMixin, ObjectWebMixin, ObjectsWebMixin
|
||||
from ObjectsWeb import register, AdminMixin, ObjectWebMixin, ObjectsWebMixin, \
|
||||
CommentableObjectMixin
|
||||
from tools import *
|
||||
|
||||
|
||||
|
@ -64,11 +65,6 @@ register(AdminArticles)
|
|||
|
||||
|
||||
class Article(ObjectWebMixin, Article):
|
||||
body_kind_widget_fieldLabel = N_('Text')
|
||||
body_kind_widget_colSpan = 2
|
||||
body_kind_widget_preview = 1
|
||||
body_kind_widgetName = 'TextArea'
|
||||
|
||||
editionTime_kind_stateInEditMode = 'hidden'
|
||||
editionTime_kind_widget_fieldLabel = N_('Edition Time')
|
||||
editionTime_kind_widgetName = 'InputText'
|
||||
|
@ -92,24 +88,6 @@ class Article(ObjectWebMixin, Article):
|
|||
title_kind_widget_size = 40
|
||||
title_kind_widgetName = 'InputText'
|
||||
|
||||
# this is all it takes to get a list of checkbox to select authors
|
||||
#
|
||||
#authorsSet_kind_widgetName = 'MultiCheck'
|
||||
#authorsSet_kind_itemKind_value_valuesGetterName = 'authorsSetValues'
|
||||
#
|
||||
#def authorsSetValues(self, slot, fields):
|
||||
# return getProxyForServerRole('people').getObjectIds()
|
||||
|
||||
def getEditLayout(self, fields, parentSlot = None):
|
||||
formatSlot = self.getSlot('format', parentSlot = parentSlot)
|
||||
formatValue = formatSlot.getField(fields, default = 'spip')
|
||||
slot = self.getSlot('body', parentSlot = parentSlot)
|
||||
self.body_kind = copy.copy(self.body_kind) # Deleted below.
|
||||
self.body_kind.textFormat = formatValue
|
||||
layout = ObjectWebMixin.getEditLayout(self, fields, parentSlot)
|
||||
del self.body_kind # Created above.
|
||||
return layout
|
||||
|
||||
def getFormattedBody(self, translate = 0):
|
||||
# TODO: don't duplicate from widgets.
|
||||
fieldValue = self.body
|
||||
|
@ -125,9 +103,7 @@ class Article(ObjectWebMixin, Article):
|
|||
if state not in ('translated', 'untranslatable'):
|
||||
fieldValue = self.body
|
||||
virtualHost = context.getVar('virtualHost')
|
||||
sectionLevel = 2
|
||||
if virtualHost:
|
||||
sectionLevel = context.getVar('baseSectionLevel')
|
||||
sectionLevel = context.getVar('sectionLevel')+1
|
||||
if self.format == 'docbook':
|
||||
formattedText = parsers.makeHtmlFromDocBook(fieldValue)
|
||||
elif self.format == 'html':
|
||||
|
@ -145,11 +121,11 @@ class Article(ObjectWebMixin, Article):
|
|||
|
||||
def getViewLayout(self, fields, parentSlot = None):
|
||||
layout = X.array()
|
||||
if fields.has_key('title'):
|
||||
if self.title:
|
||||
translationsProxy = getProxyForServerRole('translations')
|
||||
if translationsProxy:
|
||||
title = translationsProxy.getTranslation(
|
||||
fields['title'], self.getId(), 'self.title',
|
||||
self.title, self.getId(), 'self.title',
|
||||
self.getLanguage(), context.getVar('readLanguages'))
|
||||
else:
|
||||
title = self.title
|
||||
|
@ -157,34 +133,35 @@ class Article(ObjectWebMixin, Article):
|
|||
title = ''
|
||||
if parentSlot and parentSlot.getLabel() == 'Root':
|
||||
context.setVar('pageTitle', title)
|
||||
slot = self.getSlot('body', parentSlot = parentSlot)
|
||||
self.body_kind = copy.copy(self.body_kind) # Deleted below.
|
||||
self.body_kind.textFormat = self.format
|
||||
if self.format == 'docbook':
|
||||
#article = td # FIXME: this is obsolete
|
||||
pass
|
||||
else:
|
||||
titlePage = X.div(_class = 'titlepage')
|
||||
layout += titlePage
|
||||
if not (parentSlot and parentSlot.getLabel() == 'Root') and title:
|
||||
titlePage += X.h2(_class = 'title')(title)
|
||||
from glasnost.proxy.GroupsProxy import getSetContainedIds
|
||||
authorIds = getSetContainedIds(
|
||||
self.authorsSet,
|
||||
self.authorsSet_kind.itemKind.getServerRoles())
|
||||
for authorId in authorIds:
|
||||
titlePage += X.h3(_class = 'author')(
|
||||
X.objectHypertextLabel(authorId))
|
||||
slot = self.getSlot('editionTime', parentSlot = parentSlot)
|
||||
titlePage += X.p(_class = 'pubdate')(
|
||||
slot.getWidget().getHtmlValue(slot, fields))
|
||||
|
||||
sectionLevel = context.getVar('sectionLevel')
|
||||
titleTag = getattr(X, 'h%s' % (sectionLevel+1))
|
||||
if not (parentSlot and parentSlot.getLabel() == 'Root') and title:
|
||||
layout += titleTag(_class = 'title')(title)
|
||||
|
||||
from glasnost.proxy.GroupsProxy import getSetContainedIds
|
||||
authorIds = getSetContainedIds(
|
||||
self.authorsSet,
|
||||
self.authorsSet_kind.itemKind.getServerRoles(None))
|
||||
authorIds = [x for x in authorIds if \
|
||||
getWebForServerRole(commonTools.extractRole(x)).hasObject(x)]
|
||||
meta = X.ul(_class = 'article-meta')
|
||||
if authorIds:
|
||||
meta += X.li(_class = 'authors')(X.asIs(
|
||||
', '.join([X.objectHypertextLabel(x).getAsXml()
|
||||
for x in authorIds])))
|
||||
|
||||
slot = self.getSlot('editionTime', parentSlot = parentSlot)
|
||||
meta += X.li(_class = 'edition-time')(
|
||||
slot.getWidget().getHtmlValue(slot, fields))
|
||||
layout += meta
|
||||
|
||||
slot = self.getSlot('body', parentSlot = parentSlot)
|
||||
context.push(inForm = 0)
|
||||
try:
|
||||
layout += slot.getWidget().getHtmlValue(slot, fields)
|
||||
finally:
|
||||
context.pull()
|
||||
del self.body_kind # Created above.
|
||||
|
||||
layout += ObjectWebMixin.getViewLayout(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
|
@ -209,7 +186,8 @@ class Article(ObjectWebMixin, Article):
|
|||
register(Article)
|
||||
|
||||
|
||||
class ArticlesWeb(ObjectsWebMixin, ArticlesProxy):
|
||||
class ArticlesWeb(ObjectsWebMixin, CommentableObjectMixin, ArticlesProxy):
|
||||
|
||||
def all(self):
|
||||
return ObjectsWebMixin.viewAll(self, slotNames = ['editionTime'])
|
||||
all.isPublicForWeb = 1
|
||||
|
@ -226,10 +204,6 @@ class ArticlesWeb(ObjectsWebMixin, ArticlesProxy):
|
|||
article = self.getObject(id)
|
||||
version = self.getObjectDiff(id, editionTime)
|
||||
|
||||
keywords = {}
|
||||
article.makeFieldsFromInstance(keywords)
|
||||
article.repairFields(keywords)
|
||||
|
||||
label = article.getLabelTranslated(
|
||||
context.getVar('readLanguages'))
|
||||
|
||||
|
@ -323,8 +297,7 @@ class ArticlesWeb(ObjectsWebMixin, ArticlesProxy):
|
|||
layout += X.buttonStandalone(
|
||||
'history', X.idUrl(object.id, 'history'))
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
if userToken and fields.has_key('format') \
|
||||
and fields['format'] != 'text':
|
||||
if userToken and object.format and object.format != 'text':
|
||||
layout += X.buttonStandalone(
|
||||
'source', X.idUrl(object.id, 'source'))
|
||||
return layout
|
||||
|
@ -380,12 +353,16 @@ class ArticlesWeb(ObjectsWebMixin, ArticlesProxy):
|
|||
if not self.hasObject(id):
|
||||
return pageNotFound()
|
||||
article = self.getObject(id)
|
||||
body = getProxyForServerRole('translations').getTranslation(
|
||||
article.getBody(), article.getId(), 'self.body',
|
||||
article.getLanguage(), context.getVar('readLanguages'))
|
||||
|
||||
label = article.getLabelTranslated(
|
||||
context.getVar('readLanguages'))
|
||||
translationsProxy = getProxyForServerRole('translations')
|
||||
if translationsProxy:
|
||||
body = translationsProxy.getTranslation(
|
||||
article.getBody(), article.getId(), 'self.body',
|
||||
article.getLanguage(), context.getVar('readLanguages'))
|
||||
label = article.getLabelTranslated(
|
||||
context.getVar('readLanguages'))
|
||||
else:
|
||||
body = article.body
|
||||
label = article.getLabel()
|
||||
|
||||
layout = X.array()
|
||||
layout += X.pre(_class = 'spip')(body)
|
||||
|
@ -413,17 +390,12 @@ class ArticlesWeb(ObjectsWebMixin, ArticlesProxy):
|
|||
article.lastEditorId = version['editorId']
|
||||
article.editionTime = version['editionTime']
|
||||
|
||||
keywords = {}
|
||||
article.makeFieldsFromInstance(keywords)
|
||||
article.repairFields(keywords)
|
||||
|
||||
label = article.getLabelTranslated(
|
||||
context.getVar('readLanguages'))
|
||||
label = article.getLabelTranslated(context.getVar('readLanguages'))
|
||||
|
||||
layout = X.array()
|
||||
slot = slots.Root(article)
|
||||
widget = slot.getWidget()
|
||||
layout += widget.getModelPageBodyLayout(slot, keywords)
|
||||
layout += widget.getModelPageBodyLayout(slot, None)
|
||||
|
||||
return writePageLayout(layout, _('Version - %s') % label)
|
||||
version.isPublicForWeb = 1
|
||||
|
|
|
@ -64,21 +64,19 @@ register(Atom)
|
|||
|
||||
|
||||
class AtomsWeb(ObjectsWebMixin, AtomsProxy):
|
||||
def submitAddObject(self, object, **keywords):
|
||||
def submitAddObject(self, object):
|
||||
try:
|
||||
return ObjectsWebMixin.submitAddObject(self, object, **keywords)
|
||||
return ObjectsWebMixin.submitAddObject(self, object)
|
||||
except faults.DuplicateValue, f:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
context.setVar('error', 1)
|
||||
object.setError('self.name', f)
|
||||
return self.edit(object = object, **keywords)
|
||||
return self.editObject(object)
|
||||
|
||||
def submitModifyObject(self, object, **keywords):
|
||||
def submitModifyObject(self, object):
|
||||
try:
|
||||
return ObjectsWebMixin.submitModifyObject(self, object, **keywords)
|
||||
return ObjectsWebMixin.submitModifyObject(self, object)
|
||||
except faults.DuplicateValue, f:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
context.setVar('error', 1)
|
||||
object.setError('self.name', f)
|
||||
return self.edit(object = object, **keywords)
|
||||
return self.editObject(object)
|
||||
|
||||
|
|
|
@ -76,23 +76,21 @@ class AccountLdap(BaseObjectWebMixin, AccountLdap):
|
|||
register(AccountLdap)
|
||||
|
||||
class AuthenticationLdapWeb(AdministrableWebMixin, AuthenticationLdapProxy):
|
||||
def login(self, nextUri = '', access = '', again = '', error = '', **keywords):
|
||||
return failure(
|
||||
X.asIs('LDAP is not enabled in this release'), X.rootUrl())
|
||||
def getMenuCommands(self):
|
||||
return
|
||||
|
||||
def login(self, access = ''):
|
||||
authObject = self.newAuthenticationObject()
|
||||
return self.loginObject(authObject, access)
|
||||
login.isPublicForWeb = 1
|
||||
|
||||
def loginObject(authObject, access = ''):
|
||||
req = context.getVar('req')
|
||||
req.headers_out['Cache-Control'] = 'no-cache, must-revalidate'
|
||||
req.headers_out['Pragma'] = 'no-cache'
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
authObject = self.newAuthenticationObject()
|
||||
if keywords.has_key('object'):
|
||||
oldAuthObject = keywords['object']
|
||||
if isinstance(oldAuthObject, authObject.__class__):
|
||||
authObject = oldAuthObject
|
||||
|
||||
authObject.login = 1
|
||||
if not again:
|
||||
authObject.initFields(keywords)
|
||||
authObject.repairFields(keywords)
|
||||
|
||||
context.push(_level = 'index', layoutMode = 'edit',
|
||||
authMode = 'login')
|
||||
try:
|
||||
|
@ -100,8 +98,8 @@ class AuthenticationLdapWeb(AdministrableWebMixin, AuthenticationLdapProxy):
|
|||
if access == 'forbidden':
|
||||
layout += X.p(_(
|
||||
'To access this part of the site, you need to sign in.'))
|
||||
if error:
|
||||
layout += authObject.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += authObject.getErrorLayout()
|
||||
|
||||
submitUrl = X.roleUrl(self.serverRole, 'loginSubmit')
|
||||
if context.getVar('virtualHost').useHTTPS:
|
||||
|
@ -116,9 +114,9 @@ class AuthenticationLdapWeb(AdministrableWebMixin, AuthenticationLdapProxy):
|
|||
|
||||
form += authObject.getEditLayout(keywords)
|
||||
|
||||
if nextUri:
|
||||
if context.getVar('nextUri'):
|
||||
form += X.div(X.input(name = 'nextUri', type = 'hidden',
|
||||
value = nextUri))
|
||||
value = context.getVar('nextUri')))
|
||||
form += X.div(_class = 'buttons-bar')(
|
||||
X.span(_class = 'action-buttons-bar')(
|
||||
X.buttonInForm('login', 'loginButton')),
|
||||
|
@ -126,38 +124,26 @@ class AuthenticationLdapWeb(AdministrableWebMixin, AuthenticationLdapProxy):
|
|||
return writePageLayout(layout, _('Login'))
|
||||
finally:
|
||||
context.pull(_level = 'index')
|
||||
login.isPublicForWeb = 1
|
||||
|
||||
def loginSubmit(self, nextUri = '', **keywords):
|
||||
def loginSubmit(self, **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
error = 0
|
||||
|
||||
authObject = self.newAuthenticationObject()
|
||||
if error:
|
||||
keywords['again'] = 1
|
||||
keywords['error'] = 1
|
||||
else:
|
||||
authObject.submitFields(keywords)
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
uri = X.roleUrl(self.serverRole, 'login')
|
||||
uri.add('nextUri', nextUri)
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
authObject.submitFields(keywords)
|
||||
if context.getVar('again'):
|
||||
return self.loginObject(authObject)
|
||||
authWeb = getWebForServerRole('authentication')
|
||||
try:
|
||||
return authWeb.loginSubmitted(
|
||||
'ldap', authObject, nextUri)
|
||||
return authWeb.loginSubmitted('ldap', authObject)
|
||||
except faults.WrongLogin, f:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
context.setVar('error', 1)
|
||||
authObject.setError('self.login', f)
|
||||
return self.login(object = authObject, **keywords)
|
||||
return self.loginObject(authObject)
|
||||
except faults.WrongPassword:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
context.setVar('error', 1)
|
||||
authObject.setError('self.password', f)
|
||||
return self.login(object = authObject, **keywords)
|
||||
return self.loginObject(authObject)
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
|
|
|
@ -110,8 +110,10 @@ class AuthenticationLibertyAllianceWeb(
|
|||
return writePageLayout(
|
||||
X.p('Error in Liberty Alliance authentication'), 'error')
|
||||
idpAnswer.isPublicForWeb = 1
|
||||
|
||||
def login(self, nextUri = '', access = ''):
|
||||
|
||||
def login(self, access = ''):
|
||||
idpUrl = 'http://localhost:8989/processAuthnRequest.html'
|
||||
# TODO: get this from admin
|
||||
from lvparano.Provider.ServiceProvider import ServiceProvider
|
||||
sp = ServiceProvider('localhost', 8089, 8090,
|
||||
SOAPEndpoint = 'http://localhost/soapEndPoint.html')
|
||||
|
|
|
@ -157,25 +157,24 @@ class ChangingUserPassword(BaseObjectWebMixin, ObjectCommon):
|
|||
|
||||
class AuthenticationLoginPasswordWeb(AdministrableWebMixin,
|
||||
AuthenticationLoginPasswordProxy):
|
||||
def changePassword(self, again = '', error = '', **keywords):
|
||||
def changePassword(self):
|
||||
if not self.getAdmin().userCanChoosePassword:
|
||||
return accessForbidden()
|
||||
|
||||
passwordChange = ChangingPassword()
|
||||
if not again:
|
||||
passwordChange.initFields(keywords)
|
||||
passwordChange.repairFields(keywords)
|
||||
return self.changePasswordObject(passwordChange)
|
||||
changePassword.isPublicForWeb = 1
|
||||
|
||||
def changePasswordObject(self, object):
|
||||
context.push(_level = 'index', layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
if error:
|
||||
layout += passwordChange.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += object.getErrorLayout()
|
||||
form = X.form(
|
||||
action = X.actionUrl('changePasswordSubmit'),
|
||||
enctype= 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
form += passwordChange.getEditLayout(keywords)
|
||||
form += object.getEditLayout(fields = None)
|
||||
form += X.div(_class = 'buttons-bar')(
|
||||
X.span(_class = 'action-buttons-bar')(
|
||||
X.buttonInForm('ok', 'okButton')),
|
||||
|
@ -183,43 +182,33 @@ class AuthenticationLoginPasswordWeb(AdministrableWebMixin,
|
|||
return writePageLayout(layout, _('Changing Password'))
|
||||
finally:
|
||||
context.pull(_level = 'index')
|
||||
changePassword.isPublicForWeb = 1
|
||||
|
||||
|
||||
def changePasswordSubmit(self, **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
if not context.getVar('userToken'):
|
||||
return accessForbidden()
|
||||
admin = self.getAdmin()
|
||||
if not admin.userCanChoosePassword:
|
||||
return accessForbidden(dontAskForLogin = 1)
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
error = 0
|
||||
passwordChange = ChangingPassword()
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
else:
|
||||
passwordChange.submitFields(keywords)
|
||||
passwordChange.submitFields(keywords)
|
||||
|
||||
if not error:
|
||||
if not context.getVar('error'):
|
||||
authProxy = getProxyForServerRole('authentication')
|
||||
authObject = authProxy.getAuthObject()
|
||||
if authObject.password != passwordChange.currentPassword:
|
||||
slot = passwordChange.getSlot('currentPassword')
|
||||
slot.setFieldOption(keywords, 'error', 'wrongValue')
|
||||
error = 1
|
||||
passwordChange.setError(slot.getPath(), faults.BadValue)
|
||||
context.setVar('error', 1)
|
||||
if passwordChange.newPassword != passwordChange.new2Password:
|
||||
error = 1
|
||||
if error:
|
||||
keywords['newPassword'] = ''
|
||||
keywords['new2Password'] = ''
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
context.setVar('error', 1)
|
||||
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
uri = X.actionUrl('changePassword')
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
if context.getVar('error'):
|
||||
passwordChange.newPassword = ''
|
||||
passwordChange.new2Password = ''
|
||||
return self.changePasswordObject(passwordChange)
|
||||
|
||||
authObject.password = passwordChange.newPassword
|
||||
self.modifyAccount(context.getVar('userId'), authObject)
|
||||
|
@ -230,29 +219,28 @@ class AuthenticationLoginPasswordWeb(AdministrableWebMixin,
|
|||
changePasswordSubmit.isPublicForWeb = 1
|
||||
|
||||
|
||||
def changeUserPassword(self, account, again = '', error = '', **keywords):
|
||||
def changeUserPassword(self, account):
|
||||
if not self.getAdmin().userCanChoosePassword:
|
||||
return accessForbidden(dontAskForLogin = 1)
|
||||
if not self.isAdmin():
|
||||
return accessForbidden()
|
||||
if not keywords:
|
||||
keywords = {}
|
||||
keywords['login'] = account
|
||||
passwordChange = ChangingUserPassword()
|
||||
if not again:
|
||||
passwordChange.initFields(keywords)
|
||||
passwordChange.repairFields(keywords)
|
||||
|
||||
passwordChange = ChangingUserPassword()
|
||||
passwordChange.login = account
|
||||
return self.changeUserPasswordObject(passwordChange)
|
||||
changeUserPassword.isPublicForWeb = 1
|
||||
|
||||
def changeUserPasswordObject(self, object):
|
||||
context.push(_level = 'index', layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
if error:
|
||||
layout += passwordChange.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += object.getErrorLayout()
|
||||
form = X.form(
|
||||
action = X.actionUrl('changeUserPasswordSubmit'),
|
||||
enctype= 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
form += passwordChange.getEditLayout(keywords)
|
||||
form += object.getEditLayout(fields = None)
|
||||
form += X.div(_class = 'buttons-bar')(
|
||||
X.span(_class = 'action-buttons-bar')(
|
||||
X.buttonInForm('ok', 'okButton')),
|
||||
|
@ -260,29 +248,22 @@ class AuthenticationLoginPasswordWeb(AdministrableWebMixin,
|
|||
return writePageLayout(layout, _('Changing User Password'))
|
||||
finally:
|
||||
context.pull(_level = 'index')
|
||||
changeUserPassword.isPublicForWeb = 1
|
||||
|
||||
|
||||
def changeUserPasswordSubmit(self, **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
|
||||
if not self.getAdmin().userCanChoosePassword:
|
||||
return accessForbidden(dontAskForLogin = 1)
|
||||
if not self.isAdmin():
|
||||
return accessForbidden()
|
||||
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
error = 0
|
||||
passwordChange = ChangingUserPassword()
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
else:
|
||||
passwordChange.submitFields(keywords)
|
||||
passwordChange.submitFields(keywords)
|
||||
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
uri = X.actionUrl('changeUserPassword')
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
if context.getVar('again'):
|
||||
return self.changeUserPasswordObject(passwordChange)
|
||||
|
||||
authObject = self.newAuthenticationObject()
|
||||
authObject.login = passwordChange.login
|
||||
|
@ -407,29 +388,25 @@ class AuthenticationLoginPasswordWeb(AdministrableWebMixin,
|
|||
return layout
|
||||
|
||||
|
||||
def login(self, nextUri = '', access = '', again = '', error = '', **keywords):
|
||||
def login(self, access = ''):
|
||||
authObject = AccountLoginPassword()
|
||||
return self.loginObject(authObject, access)
|
||||
login.isPublicForWeb = 1
|
||||
|
||||
def loginObject(self, object, access = ''):
|
||||
req = context.getVar('req')
|
||||
req.headers_out['Cache-Control'] = 'no-cache, must-revalidate'
|
||||
req.headers_out['Pragma'] = 'no-cache'
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
authObject = AccountLoginPassword()
|
||||
if keywords.has_key('object'):
|
||||
oldAuthObject = keywords['object']
|
||||
if isinstance(oldAuthObject, authObject.__class__):
|
||||
authObject = oldAuthObject
|
||||
authObject.skipPassword = 0
|
||||
if not again:
|
||||
authObject.initFields(keywords)
|
||||
authObject.repairFields(keywords)
|
||||
|
||||
object.skipPassword = 0
|
||||
context.push(_level = 'index', layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
if access == 'forbidden':
|
||||
layout += X.p(_(
|
||||
'To access this part of the site, you need to sign in.'))
|
||||
if error:
|
||||
layout += authObject.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += object.getErrorLayout()
|
||||
|
||||
submitUrl = X.roleUrl(self.serverRole, 'loginSubmit')
|
||||
if context.getVar('virtualHost').useHTTPS:
|
||||
|
@ -442,11 +419,11 @@ class AuthenticationLoginPasswordWeb(AdministrableWebMixin,
|
|||
method = 'post')
|
||||
layout += form
|
||||
|
||||
form += authObject.getEditLayout(keywords)
|
||||
form += object.getEditLayout(fields = None)
|
||||
|
||||
if nextUri:
|
||||
if context.getVar('nextUri'):
|
||||
form += X.div(X.input(name = 'nextUri', type = 'hidden',
|
||||
value = nextUri))
|
||||
value = context.getVar('nextUri')))
|
||||
buttonsBar = X.div(_class = 'buttons-bar')
|
||||
form += buttonsBar
|
||||
buttonsBar += X.buttonInForm('login', 'loginButton')
|
||||
|
@ -458,21 +435,17 @@ class AuthenticationLoginPasswordWeb(AdministrableWebMixin,
|
|||
context.pull(_level = 'index')
|
||||
login.isPublicForWeb = 1
|
||||
|
||||
def loginSubmit(self, nextUri = '', **keywords):
|
||||
def loginSubmit(self, **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
error = 0
|
||||
sendPasswordByEmail = isButtonSelected('sendButton', keywords)
|
||||
|
||||
authObject = self.newAuthenticationObject()
|
||||
if error:
|
||||
keywords['again'] = 1
|
||||
keywords['error'] = 1
|
||||
else:
|
||||
authObject.submitFields(keywords)
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
uri = X.roleUrl(self.serverRole, 'login')
|
||||
return self.login(object = authObject, **keywords)
|
||||
authObject.submitFields(keywords)
|
||||
|
||||
if context.getVar('again'):
|
||||
return self.loginObject(authObject)
|
||||
|
||||
if sendPasswordByEmail:
|
||||
try:
|
||||
self.emailPassword(authObject)
|
||||
|
@ -483,17 +456,15 @@ class AuthenticationLoginPasswordWeb(AdministrableWebMixin,
|
|||
authWeb = getWebForServerRole('authentication')
|
||||
try:
|
||||
return authWeb.loginSubmitted(
|
||||
'login-password', authObject, nextUri)
|
||||
'login-password', authObject)
|
||||
except faults.WrongLogin, f:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
context.getVar('error', 1)
|
||||
authObject.setError('self.login', f)
|
||||
return self.login(object = authObject, **keywords)
|
||||
return self.loginObject(authObject)
|
||||
except faults.WrongPassword, f:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
context.getVar('error', 1)
|
||||
authObject.setError('self.password', f)
|
||||
return self.login(object = authObject, **keywords)
|
||||
return self.loginObject(authObject)
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
|
@ -501,46 +472,32 @@ class AuthenticationLoginPasswordWeb(AdministrableWebMixin,
|
|||
loginSubmit.isPublicForWeb = 1
|
||||
|
||||
|
||||
def newAccount(self, again = '', error = '', **keywords):
|
||||
def newAccount(self):
|
||||
usercardWeb = getProxyForServerRole('people')
|
||||
if not usercardWeb.canAddObject():
|
||||
return accessForbidden()
|
||||
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
userCardObject = usercardWeb.newObject(None)
|
||||
if keywords.has_key('userCardObject') and \
|
||||
isinstance(keywords['userCardObject'],
|
||||
userCardObject.__class__):
|
||||
userCardObject = keywords['userCardObject']
|
||||
del keywords['userCardObject']
|
||||
userCardSlot = slots.Root(userCardObject, name = 'userCard')
|
||||
if not again:
|
||||
userCardObject.initFields(keywords, parentSlot = userCardSlot)
|
||||
userCardObject.repairFields(keywords, parentSlot = userCardSlot)
|
||||
|
||||
authObject = self.newAuthenticationObject()
|
||||
if keywords.has_key('authObject') and \
|
||||
isinstance(keywords['authObject'], authObject.__class__):
|
||||
authObject = keywords['authObject']
|
||||
del keywords['authObject']
|
||||
if not again:
|
||||
authObject.initFields(keywords)
|
||||
authObject.repairFields(keywords)
|
||||
|
||||
return self.newAccountObject(userCardObject, authObject)
|
||||
|
||||
def newAccountObject(self, userCardObject, authObject):
|
||||
userCardSlot = slots.Root(userCardObject, name = 'userCard')
|
||||
|
||||
context.push(_level = 'index', layoutMode = 'edit')
|
||||
|
||||
try:
|
||||
layout = X.array()
|
||||
if error:
|
||||
layout += userCardObject.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += userCardObject.getErrorLayout()
|
||||
form = X.form(action = X.actionUrl('newAccountSubmit'),
|
||||
method = 'post')
|
||||
layout += form
|
||||
|
||||
form += userCardObject.getEditLayout(
|
||||
keywords, parentSlot = userCardSlot)
|
||||
form += authObject.getEditLayout(keywords)
|
||||
fields = None, parentSlot = userCardSlot)
|
||||
form += authObject.getEditLayout(fields = None)
|
||||
|
||||
form += X.div(_class = 'buttons-bar')(
|
||||
X.span(_class = 'action-buttons-bar')(
|
||||
|
@ -552,25 +509,24 @@ class AuthenticationLoginPasswordWeb(AdministrableWebMixin,
|
|||
newAccount.isPublicForWeb = 1
|
||||
|
||||
def newAccountSubmit(self, **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
|
||||
usercardWeb = getProxyForServerRole('people')
|
||||
if not usercardWeb.canAddObject():
|
||||
return accessForbidden()
|
||||
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
|
||||
userCardObject = usercardWeb.newObject(None)
|
||||
userCardObject = usercardWeb.newObject(fields = None)
|
||||
userCardSlot = slots.Root(userCardObject, name = 'userCard')
|
||||
userCardObject.submitFields(keywords, parentSlot = userCardSlot)
|
||||
|
||||
authObject = self.newAuthenticationObject()
|
||||
authObject.submitFields(keywords)
|
||||
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
return self.newAccount(
|
||||
if context.getVar('again'):
|
||||
return self.newAccountObject(
|
||||
userCardObject = userCardObject,
|
||||
authObject = authObject,
|
||||
**keywords)
|
||||
authObject = authObject)
|
||||
|
||||
userId = usercardWeb.addObject(userCardObject)
|
||||
try:
|
||||
|
|
|
@ -61,11 +61,11 @@ import widgets
|
|||
|
||||
class AuthAdminWidget(widgets.Select):
|
||||
def getHtmlViewValue(self, slot, fields, **keywords):
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
value = slot.getValue()
|
||||
layout = X.array(
|
||||
widgets.Select.getHtmlViewValue(self, slot, fields, **keywords),
|
||||
X.buttonStandalone('settings',
|
||||
X.roleUrl('authentication-'+fieldValue, 'admin')) )
|
||||
X.roleUrl('authentication-'+value, 'admin')) )
|
||||
return layout
|
||||
register(AuthAdminWidget)
|
||||
|
||||
|
@ -103,7 +103,7 @@ class AuthenticationWeb(AdministrableWebMixin, AuthenticationProxy):
|
|||
layout += X.buttonStandalone('settings', X.actionUrl('admin'))
|
||||
return layout
|
||||
|
||||
def loginSubmitted(self, authMethod, authObject, nextUri = ''):
|
||||
def loginSubmitted(self, authMethod, authObject):
|
||||
userToken = self.getUserToken(authMethod, authObject)
|
||||
session = context.getVar('session')
|
||||
sessionToken = context.getVar('sessionToken')
|
||||
|
@ -126,6 +126,7 @@ class AuthenticationWeb(AdministrableWebMixin, AuthenticationProxy):
|
|||
context.setVar('userId', userId)
|
||||
session['userToken'] = userToken
|
||||
session['isDirty'] = 1
|
||||
nextUri = context.getVar('nextUri') or ''
|
||||
if not nextUri:
|
||||
hostNameAndPort = commonTools.makeHttpHostNameAndPort(
|
||||
context.getVar('httpHostName'),
|
||||
|
@ -152,7 +153,7 @@ class AuthenticationWeb(AdministrableWebMixin, AuthenticationProxy):
|
|||
context.setVar('canUseCookie', 1)
|
||||
return redirect(uri)
|
||||
|
||||
def logout(self, nextUri = ''):
|
||||
def logout(self):
|
||||
authenticationProxy = getProxyForServerRole('authentication')
|
||||
authenticationProxy.delUserToken()
|
||||
session = context.getVar('session')
|
||||
|
@ -175,6 +176,7 @@ class AuthenticationWeb(AdministrableWebMixin, AuthenticationProxy):
|
|||
# # use
|
||||
# # the cookie when loging out.
|
||||
# context.setVar('canUseCookie', 0)
|
||||
nextUri = context.getVar('nextUri') or ''
|
||||
if not nextUri:
|
||||
nextUri = '/'
|
||||
else:
|
||||
|
|
|
@ -119,9 +119,6 @@ class AbstractCard(BaseObjectWebMixin, Card):
|
|||
return prototype.viewModeUsersSet
|
||||
return [system.generalPublicId]
|
||||
|
||||
def initFields(self, fields, parentSlot = None):
|
||||
self.makeFieldsFromInstance(fields, parentSlot = parentSlot)
|
||||
|
||||
|
||||
class Card(AbstractCard):
|
||||
pass
|
||||
|
@ -240,8 +237,8 @@ class CardForUse(AbstractCard):
|
|||
|
||||
def getC3PrototypeLinearization(self):
|
||||
if self._c3PrototypeLinearization is None:
|
||||
self._c3PrototypeLinearization \
|
||||
= AbstractCard.getC3PrototypeLinearization(self)
|
||||
self._c3PrototypeLinearization = \
|
||||
AbstractCard.getC3PrototypeLinearization(self)
|
||||
return self._c3PrototypeLinearization
|
||||
|
||||
def getSlotToModifyNames(self, parentSlot = None):
|
||||
|
@ -276,12 +273,6 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
contentWidget = contentKind.getModelWidget(
|
||||
contentSlot, forceEmbedding = 1)
|
||||
|
||||
keywords = {}
|
||||
|
||||
contentKind.makeFieldFromValue(
|
||||
contentSlot, keywords, content, forceEmbedding = 1)
|
||||
contentKind.repairField(contentSlot, keywords, forceEmbedding = 1)
|
||||
|
||||
layout = X.array()
|
||||
|
||||
if contentSlot.parent is not None:
|
||||
|
@ -306,7 +297,7 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
publicPath.append(itemTitle)
|
||||
layout += X.div(_class = 'public-path')(publicPath)
|
||||
|
||||
layout += contentWidget.getModelPageBodyLayout(contentSlot, keywords)
|
||||
layout += contentWidget.getModelPageBodyLayout(contentSlot, None)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')
|
||||
layout += buttonsBar
|
||||
|
@ -330,78 +321,7 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
edit.isPublicForWeb = 0 # Important, so that self.parseHttpPathAction is
|
||||
# called.
|
||||
|
||||
## def edit(self, id = '', again = '', error = '', **keywords):
|
||||
## if not id:
|
||||
## uri = X.actionUrl('editDefinition')
|
||||
## uri.add('id', id)
|
||||
## uri.addKeywords(keywords)
|
||||
## return redirect(uri)
|
||||
|
||||
## if keywords is None:
|
||||
## keywords = {}
|
||||
## keywords['id'] = id
|
||||
## if not self.hasObject(id):
|
||||
## return pageNotFound()
|
||||
## if not self.canModifyObject(id):
|
||||
## return accessForbidden()
|
||||
## object = self.getObject(id)
|
||||
## object.__class__ = CardForUse # Important.
|
||||
## rememberObject(id)
|
||||
## object.execute('onEdit')
|
||||
|
||||
## if not again:
|
||||
## object.makeFieldsFromInstance(keywords)
|
||||
## object.repairFields(keywords)
|
||||
|
||||
## headerTitle = _('Editing %s - %s') % (
|
||||
## _(self.objectNameCapitalized), object.getLabel())
|
||||
|
||||
## if keywords.has_key('headerTitle'):
|
||||
## headerTitle = keywords['headerTitle']
|
||||
|
||||
## context.push(_level = 'edit',
|
||||
## isCreateEditMode = not id,
|
||||
## layoutMode = 'edit')
|
||||
## try:
|
||||
## layout = X.array()
|
||||
## leadIn = self.getEditLeadIn(object, keywords)
|
||||
## if leadIn:
|
||||
## layout += X.enclose(leadIn, _class = 'lead-in')
|
||||
## layout += object.getErrorLayout(error, keywords)
|
||||
## form = X.form(action = X.actionUrl('submit'),
|
||||
## enctype = 'multipart/form-data', method = 'post')
|
||||
## layout += form
|
||||
## if keywords.has_key('cloned') and keywords['cloned']:
|
||||
## form += X.input(name = 'cloned', type = 'hidden', value = '1')
|
||||
|
||||
## if keywords.has_key('nextUri') and keywords['nextUri']:
|
||||
## form += X.input(name = 'nextUri', type = 'hidden',
|
||||
## value = keywords['nextUri'])
|
||||
|
||||
## slot = slots.Root(object)
|
||||
## widget = slot.getWidget()
|
||||
## form += widget.getModelPageBodyLayout(slot, keywords)
|
||||
|
||||
## buttonsBar = X.div(_class = 'buttons-bar')
|
||||
## form += buttonsBar
|
||||
## actionButtonsBar = X.span(_class = 'action-buttons-bar')
|
||||
## buttonsBar += actionButtonsBar
|
||||
## if self.canDeleteObject(id):
|
||||
## actionButtonsBar += X.buttonStandalone(
|
||||
## 'delete', X.idUrl(id, 'confirmDelete'))
|
||||
## actionButtonsBar += X.buttonInForm('modify', 'modifyButton')
|
||||
|
||||
## return writePageLayout(layout, headerTitle)
|
||||
## finally:
|
||||
## context.pull(_level = 'edit')
|
||||
## edit.isPublicForWeb = 1
|
||||
|
||||
def editDefinition(self, id, contentPath = '', again = '', error = '',
|
||||
**keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['id'] = id
|
||||
keywords['contentPath'] = contentPath
|
||||
def editDefinition(self, id, contentPath = ''):
|
||||
if id and not self.hasObject(id):
|
||||
return pageNotFound()
|
||||
|
||||
|
@ -413,8 +333,14 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
else:
|
||||
if not self.canAddObject():
|
||||
return accessForbidden()
|
||||
object = self.newObject(keywords)
|
||||
object = self.newObject(None)
|
||||
|
||||
object.__class__ = CardForDefinition # Important.
|
||||
|
||||
return self.editDefinitionObject(object, id, contentPath)
|
||||
editDefinition.isPublicForWeb = 1
|
||||
|
||||
def editDefinitionObject(self, object, id = '', contentPath = ''):
|
||||
try:
|
||||
contentSlot = object.getSlotByPath(contentPath)
|
||||
except: # FIXME.
|
||||
|
@ -428,13 +354,6 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
contentWidget = contentKind.getModelWidget(
|
||||
contentSlot, forceEmbedding = 1)
|
||||
|
||||
if not id and not again:
|
||||
contentKind.initField(contentSlot, keywords, forceEmbedding = 1)
|
||||
if id and not again:
|
||||
contentKind.makeFieldFromValue(
|
||||
contentSlot, keywords, content, forceEmbedding = 1)
|
||||
contentKind.repairField(contentSlot, keywords, forceEmbedding = 1)
|
||||
|
||||
if not id:
|
||||
headerTitle = _(self.newObjectNameCapitalized)
|
||||
else:
|
||||
|
@ -467,8 +386,8 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
publicPath.append(itemTitle)
|
||||
layout += X.div(_class = 'public-path')(publicPath)
|
||||
|
||||
if error:
|
||||
layout += object.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += object.getErrorLayout()
|
||||
form = X.form(action = X.actionUrl('submitDefinition'),
|
||||
enctype= 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
|
@ -477,7 +396,7 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
form += X.input(name = 'contentPath', type = 'hidden',
|
||||
value = contentPath)
|
||||
|
||||
form += contentWidget.getModelPageBodyLayout(contentSlot, keywords)
|
||||
form += contentWidget.getModelPageBodyLayout(contentSlot, None)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')
|
||||
form += buttonsBar
|
||||
|
@ -491,7 +410,6 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
return writePageLayout(layout, headerTitle)
|
||||
finally:
|
||||
context.pull(_level = 'editDefinition')
|
||||
editDefinition.isPublicForWeb = 1
|
||||
|
||||
def getViewAllActionButtonsBarLayout(self):
|
||||
layout = X.array()
|
||||
|
@ -521,52 +439,6 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
'implement', X.idUrl(object.id, 'new'))
|
||||
return layout
|
||||
|
||||
## def implement(self, id, again = '', error = '', **keywords):
|
||||
## prototypeId = id
|
||||
## id = ''
|
||||
## if keywords is None:
|
||||
## keywords = {}
|
||||
## keywords['id'] = ''
|
||||
## if not self.hasObject(prototypeId):
|
||||
## return pageNotFound()
|
||||
## if not self.canAddObject():
|
||||
## return accessForbidden()
|
||||
|
||||
## object = self.newObject(keywords)
|
||||
## object.__class__ = CardForImplement # Important.
|
||||
## object.prototypeIds = [prototypeId]
|
||||
## object.execute('onCreate')
|
||||
|
||||
## if not again:
|
||||
## object.makeFieldsFromInstance(keywords)
|
||||
## object.repairFields(keywords)
|
||||
|
||||
## headerTitle = _('New %s') % _(self.objectNameCapitalized)
|
||||
|
||||
## context.push(_level = 'implement',
|
||||
## isCreateEditMode = 1,
|
||||
## layoutMode = 'edit')
|
||||
## try:
|
||||
## layout = X.array()
|
||||
## layout += object.getErrorLayout(error, keywords)
|
||||
## form = X.form(
|
||||
## action = X.actionUrl('submitImplementation'),
|
||||
## enctype = 'multipart/form-data', method = 'post')
|
||||
## layout += form
|
||||
## form += X.input(
|
||||
## name = 'prototypeId', type = 'hidden', value = prototypeId)
|
||||
|
||||
## slot = slots.Root(object)
|
||||
## widget = slot.getWidget()
|
||||
## form += widget.getModelPageBodyLayout(slot, keywords)
|
||||
|
||||
## form += X.div(_class = 'buttons-bar')(
|
||||
## X.span(_class = 'action-buttons-bar')(
|
||||
## X.buttonInForm('create', 'createButton')))
|
||||
## return writePageLayout(layout, headerTitle)
|
||||
## finally:
|
||||
## context.pull(_level = 'implement')
|
||||
## implement.isPublicForWeb = 1
|
||||
|
||||
def implementations(self, id, slotNames = None):
|
||||
if type(slotNames) is not types.ListType:
|
||||
|
@ -602,12 +474,6 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
implementations.isPublicForWeb = 1
|
||||
|
||||
def index(self, id, modeName = '', *arguments, **keywords):
|
||||
again = keywords.has_key('again') and keywords['again']
|
||||
if keywords.has_key('error'):
|
||||
error = keywords['error']
|
||||
else:
|
||||
error = ''
|
||||
|
||||
localId = commonTools.extractLocalId(id)
|
||||
if localId.startswith('draft/'):
|
||||
draftKey = localId
|
||||
|
@ -622,6 +488,7 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
return accessForbidden()
|
||||
object = self.getObject(id)
|
||||
object.__class__ = CardForUse # Important.
|
||||
|
||||
if not modeName:
|
||||
modeName = object.getDefaultModeName()
|
||||
elif not object.hasMode(modeName):
|
||||
|
@ -636,11 +503,10 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
mode.getModelUsersSet(object)):
|
||||
return accessForbidden()
|
||||
|
||||
create = 0
|
||||
command = None
|
||||
if arguments:
|
||||
action = arguments[0]
|
||||
if action == 'new':
|
||||
create = 1
|
||||
prototypeId = id
|
||||
id = ''
|
||||
if not self.canAddObject():
|
||||
|
@ -648,25 +514,38 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
object = self.newObject(keywords)
|
||||
object.__class__ = CardForUse # Important.
|
||||
object.prototypeIds = [prototypeId]
|
||||
command = actions.Command()
|
||||
command.action = 'create'
|
||||
|
||||
keywords['id'] = id
|
||||
if id:
|
||||
rememberObject(id)
|
||||
|
||||
return self.indexObject(object, mode, command)
|
||||
index.isPublicForWeb = 1
|
||||
|
||||
def indexObject(self, object, mode, command):
|
||||
modeName = mode.getName()
|
||||
if modeName == 'edit':
|
||||
layoutMode = 'edit'
|
||||
elif modeName == 'view':
|
||||
layoutMode = 'view'
|
||||
else:
|
||||
layoutMode = 'use'
|
||||
|
||||
create = 0
|
||||
if command and (command.action == 'create' or
|
||||
command.action == 'submit' and not object.id):
|
||||
create = 1
|
||||
prototypeId = object.prototypeIds[0]
|
||||
|
||||
context.push(_level = 'index', layoutMode = layoutMode)
|
||||
try:
|
||||
headerTitle, pageBodyLayout, buttonsBarLayout, inForm \
|
||||
= mode.getModelLayoutInfos(object, keywords, again, create)
|
||||
headerTitle, pageBodyLayout, buttonsBarLayout, inForm = \
|
||||
mode.getModelLayoutInfos(object, None, create)
|
||||
layout = X.array()
|
||||
if inForm:
|
||||
if error:
|
||||
layout += object.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += object.getErrorLayout()
|
||||
form = X.form(action = X.actionUrl('submit'),
|
||||
enctype = 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
|
@ -676,13 +555,6 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
if create:
|
||||
form += X.input(name = 'prototypeId', type = 'hidden',
|
||||
value = prototypeId)
|
||||
# FIXME: Should we keep the handling of cloned and nextUri?
|
||||
if keywords.has_key('cloned') and keywords['cloned']:
|
||||
form += X.input(name = 'cloned', type = 'hidden',
|
||||
value = '1')
|
||||
if keywords.has_key('nextUri') and keywords['nextUri']:
|
||||
form += X.input(name = 'nextUri', type = 'hidden',
|
||||
value = keywords['nextUri'])
|
||||
form += pageBodyLayout
|
||||
if buttonsBarLayout:
|
||||
form += buttonsBarLayout
|
||||
|
@ -698,7 +570,6 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
return layout
|
||||
finally:
|
||||
context.pull(_level = 'index')
|
||||
index.isPublicForWeb = 1
|
||||
|
||||
def parseHttpPathAction(self, remaining):
|
||||
context.push()
|
||||
|
@ -769,11 +640,10 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
def submit(self, id = '', modeName = '', prototypeId = '', **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['id'] = id
|
||||
keywords['id'] = id # FIXME: not sure it is still useful
|
||||
if isButtonSelected('applyButton', keywords):
|
||||
keywords['again'] = '1'
|
||||
keywords['hideErrors'] = '1'
|
||||
error = 0
|
||||
context.setVar('again', 1)
|
||||
context.setVar('hideErrors', 1)
|
||||
|
||||
removeDraft = 0
|
||||
if id:
|
||||
|
@ -802,24 +672,26 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
mode.getModelUsersSet(object)):
|
||||
return accessForbidden()
|
||||
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
else:
|
||||
command = actions.Command()
|
||||
command.action = 'submit'
|
||||
command.nextObjectId = id
|
||||
context.push(_level = 'submit',
|
||||
command = command)
|
||||
try:
|
||||
mode.submitModelFields(object, keywords)
|
||||
finally:
|
||||
command = context.getVar('command')
|
||||
context.pull(_level = 'submit')
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
uri = X.idUrl(id, modeName)
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
command = actions.Command()
|
||||
command.action = 'submit'
|
||||
command.nextObjectId = id
|
||||
context.push(_level = 'submit',
|
||||
command = command)
|
||||
try:
|
||||
mode.submitModelFields(object, keywords)
|
||||
finally:
|
||||
# I don't like this; why is the submit in its own context ?
|
||||
again = context.getVar('again')
|
||||
error = context.getVar('error')
|
||||
command = context.getVar('command')
|
||||
context.pull(_level = 'submit')
|
||||
if again:
|
||||
context.setVar('again', 1)
|
||||
if error:
|
||||
context.setVar('error', 1)
|
||||
|
||||
if context.getVar('again'):
|
||||
return self.indexObject(object, mode, command)
|
||||
mode.executeModel(object, 'onSubmit', command)
|
||||
action = command.action
|
||||
if action == 'create' or action == 'submit' and not id:
|
||||
|
@ -837,12 +709,10 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
try:
|
||||
self.modifyPartialObject(object, slotToModifyNames)
|
||||
except faults.WrongVersion:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
keywords['versionError'] = '1'
|
||||
uri = X.idUrl(id, modeName)
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
object.setError('version', 1)
|
||||
return self.indexObject(object, mode, command)
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
|
@ -904,9 +774,8 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
keywords['id'] = id
|
||||
keywords['contentPath'] = contentPath
|
||||
if isButtonSelected('applyButton', keywords):
|
||||
keywords['again'] = '1'
|
||||
keywords['hideErrors'] = '1'
|
||||
error = 0
|
||||
context.setVar('again', 1)
|
||||
context.setVar('hideErrors', 1)
|
||||
|
||||
if id:
|
||||
object = self.getObject(id)
|
||||
|
@ -923,17 +792,13 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
contentSlot = slots.Root(object)
|
||||
content = contentSlot.getValue()
|
||||
contentKind = contentSlot.getKind()
|
||||
contentWidget = contentSlot.getWidget()
|
||||
|
||||
contentWidget.submitEmbedded(contentSlot, keywords)
|
||||
|
||||
if context.getVar('again'):
|
||||
return self.editDefinitionObject(object, contentPath)
|
||||
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
else:
|
||||
contentKind.submitField(contentSlot, keywords, forceEmbedding = 1)
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
uri = X.idUrl(id, 'editDefinition/%s' % contentPath)
|
||||
del keywords['contentPath']
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
if not id:
|
||||
try:
|
||||
id = self.addObject(object)
|
||||
|
@ -945,13 +810,10 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
try:
|
||||
self.modifyPartialObject(object, object.getSlotToModifyNames())
|
||||
except faults.WrongVersion:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
keywords['versionError'] = '1'
|
||||
uri = X.idUrl(id, 'editDefinition/%s' % contentPath)
|
||||
del keywords['contentPath']
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
object.setError('version', 1)
|
||||
return self.editDefinitionObject(object, contentPath)
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
|
@ -959,37 +821,6 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
return redirect(X.idUrl(id, 'definition/%s' % contentPath))
|
||||
submitDefinition.isPublicForWeb = 1
|
||||
|
||||
## def submitImplementation(self, prototypeId, **keywords):
|
||||
## if keywords is None:
|
||||
## keywords = {}
|
||||
## keywords['id'] = ''
|
||||
|
||||
## if isButtonSelected('applyButton', keywords):
|
||||
## keywords['again'] = '1'
|
||||
## keywords['hideErrors'] = '1'
|
||||
## error = 0
|
||||
|
||||
## object = self.newObject(keywords)
|
||||
## object.__class__ = CardForImplement # Important.
|
||||
## object.prototypeIds = [prototypeId]
|
||||
## if error:
|
||||
## keywords['again'] = '1'
|
||||
## keywords['error'] = '1'
|
||||
## else:
|
||||
## object.submitFields(keywords)
|
||||
## if keywords.has_key('again') and keywords['again']:
|
||||
## uri = X.idUrl(prototypeId, 'implement')
|
||||
## uri.addKeywords(keywords)
|
||||
## return redirect(uri)
|
||||
## try:
|
||||
## id = self.addObject(object)
|
||||
## except faults.Fault:
|
||||
## if context.getVar('debug'):
|
||||
## raise
|
||||
## return accessForbidden()
|
||||
## return redirect(X.idUrl(id))
|
||||
## submitImplementation.isPublicForWeb = 1
|
||||
|
||||
def use(self, *arguments, **keywords):
|
||||
pass
|
||||
use.isPublicForWeb = 0 # Important, so that self.parseHttpPathAction is
|
||||
|
@ -1000,44 +831,3 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
|
|||
view.isPublicForWeb = 0 # Important, so that self.parseHttpPathAction is
|
||||
# called.
|
||||
|
||||
## def view(self, id):
|
||||
## if not self.hasObject(id):
|
||||
## return pageNotFound()
|
||||
## if not self.canGetObject(id):
|
||||
## return accessForbidden()
|
||||
## object = self.getObject(id)
|
||||
## object.__class__ = CardForUse # Important.
|
||||
## rememberObject(id)
|
||||
## object.execute('onView')
|
||||
|
||||
## keywords = {}
|
||||
|
||||
## object.makeFieldsFromInstance(keywords)
|
||||
## object.repairFields(keywords)
|
||||
|
||||
## label = object.getLabelTranslated(context.getVar('readLanguages'))
|
||||
|
||||
## layout = X.array()
|
||||
## leadIn = self.getViewLeadIn(object, keywords)
|
||||
## if leadIn:
|
||||
## layout += X.enclose(leadIn, _class = 'lead-in')
|
||||
## slot = slots.Root(object)
|
||||
## widget = slot.getWidget()
|
||||
## layout += object.getViewLayout(fields, parentSlot = None)
|
||||
## layout += widget.getModelPageBodyLayout(slot, keywords)
|
||||
## pageTitle = context.getVar('pageTitle', default = None)
|
||||
## layout += self.getViewAboveButtonsBarLayout(object, keywords)
|
||||
## if context.getVar('userId'):
|
||||
## layout += self.getViewButtonsBarLayout(object, keywords)
|
||||
## layout += self.getViewBelowButtonsBarLayout(object, keywords)
|
||||
|
||||
## context.push(
|
||||
## currentObject = WebAPI.GlasnostObject(object = object),
|
||||
## )
|
||||
## if not pageTitle:
|
||||
## pageTitle = '%s - %s' % (_(self.objectNameCapitalized), label)
|
||||
## layout = writePageLayout(layout, pageTitle)
|
||||
## context.pull()
|
||||
## return layout
|
||||
## view.isPublicForWeb = 1
|
||||
|
||||
|
|
|
@ -54,17 +54,11 @@ from tools import *
|
|||
|
||||
|
||||
class AdminComments(AdminMixin, AdminComments):
|
||||
allowAnonymousComments_kind_widget_fieldLabel = N_(
|
||||
'Allow Anonymous Comments')
|
||||
allowAnonymousComments_kind_widgetName = 'InputCheckBox'
|
||||
pass
|
||||
register(AdminComments)
|
||||
|
||||
|
||||
class Comment(ObjectWebMixin, Comment):
|
||||
authorId_kind_stateInEditMode = 'hidden'
|
||||
authorId_kind_widget_fieldLabel = N_('Author')
|
||||
authorId_kind_widgetName = 'SelectId'
|
||||
|
||||
body_kind_widget_fieldLabel = N_('Text')
|
||||
body_kind_widget_cols = 75
|
||||
body_kind_widget_colSpan = 2
|
||||
|
@ -72,124 +66,76 @@ class Comment(ObjectWebMixin, Comment):
|
|||
body_kind_widget_rows = 20
|
||||
body_kind_widgetName = 'TextArea'
|
||||
|
||||
creationTime_kind_stateInEditMode = 'hidden'
|
||||
|
||||
language_kind_stateInEditMode = 'hidden'
|
||||
|
||||
name_kind_widget_fieldLabel = N_('Name')
|
||||
name_kind_widget_size = 40
|
||||
name_kind_widgetName = 'InputText'
|
||||
|
||||
nbReplies_kind_stateInEditMode = 'hidden'
|
||||
|
||||
title_kind_widget_fieldLabel = N_('Title')
|
||||
title_kind_widget_size = 40
|
||||
title_kind_widgetName = 'InputText'
|
||||
|
||||
replyToId_kind_stateInEditMode = 'hidden'
|
||||
replyToId_kind_widget_fieldLabel = N_('Commented Item')
|
||||
replyToId_kind_widgetName = 'SelectId'
|
||||
|
||||
def getEditLayoutHiddenSlotNames(self, fields, parentSlot = None):
|
||||
hiddenSlotNames = ObjectWebMixin.getEditLayoutHiddenSlotNames(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
hiddenSlotNames = hiddenSlotNames[:]
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
if userToken:
|
||||
hiddenSlotNames += ['name']
|
||||
return hiddenSlotNames
|
||||
def getEditLayoutSlotNames(self, fields, parentSlot = None):
|
||||
slotNames = ObjectWebMixin.getEditLayoutSlotNames(self, fields,
|
||||
parentSlot = parentSlot) [:]
|
||||
if 'authorId' in slotNames:
|
||||
slotNames.remove('authorId')
|
||||
if 'parentId' in slotNames:
|
||||
slotNames.remove('parentId')
|
||||
if 'creationTime' in slotNames:
|
||||
slotNames.remove('creationTime')
|
||||
return slotNames
|
||||
|
||||
def getViewLayoutSlotNames(self, fields, parentSlot = None):
|
||||
return ['title', 'body']
|
||||
|
||||
def getViewLayout(self, fields, parentSlot = None):
|
||||
sectionLevel = context.getVar('sectionLevel')
|
||||
context.push(sectionLevel = sectionLevel+1)
|
||||
|
||||
def render(self):
|
||||
layout = X.array()
|
||||
layout += X.h4(self.getLabel())
|
||||
commentInfos = X.div(_class = 'comment-infos')
|
||||
layout += commentInfos
|
||||
if self.authorId:
|
||||
commentInfos += X.span(_class = 'comment-author')( \
|
||||
X.objectHypertextLabel(self.authorId))
|
||||
elif self.name:
|
||||
commentInfos += X.span(_class = 'comment-author')(self.name)
|
||||
else:
|
||||
commentInfos += X.span(_class = 'comment-author')(_('Anonymous'))
|
||||
if self.creationTime:
|
||||
value = time.strftime('%Y-%m-%d %H:%M:%S',
|
||||
time.localtime(self.creationTime))
|
||||
commentInfos += X.span(_class = 'comment-time')(value)
|
||||
|
||||
layout += X.asIs(replaceSpecialTags(
|
||||
parsers.makeHtmlFromSpip(self.body)))
|
||||
return layout
|
||||
titleSlot = self.getSlot('title')
|
||||
titleHtml = titleSlot.getWidget().getHtmlValue(titleSlot, fields)
|
||||
titleTag = getattr(X, 'h%s' % (sectionLevel+1))
|
||||
if len(titleHtml.children) == 2:
|
||||
# remove translation bar
|
||||
del titleHtml.children[1]
|
||||
layout += titleTag(titleHtml)
|
||||
|
||||
authorIdSlot = self.getSlot('authorId')
|
||||
if authorIdSlot.getValue():
|
||||
layout += X.span(_class = 'authorId')(
|
||||
authorIdSlot.getWidget().getHtmlValue(authorIdSlot, fields))
|
||||
else:
|
||||
layout += X.span(_class = 'authorId')(_('Anonymous'))
|
||||
creationTimeSlot = self.getSlot('creationTime')
|
||||
layout += X.span(_class = 'creationTime')(
|
||||
creationTimeSlot.getWidget().getHtmlValue(creationTimeSlot, fields))
|
||||
bodySlot = self.getSlot('body')
|
||||
layout += X.div(bodySlot.getWidget().getHtmlValue(bodySlot, fields))
|
||||
context.pull()
|
||||
|
||||
return layout
|
||||
register(Comment)
|
||||
|
||||
|
||||
class CommentsWeb(ObjectsWebMixin, CommentsProxy):
|
||||
def edit(self, id = '', again = '', error = '', **keywords):
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
if not userToken:
|
||||
return pageNotFound()
|
||||
return ObjectsWebMixin.edit(self, id, again, error, **keywords)
|
||||
edit.isPublicForWeb = 1
|
||||
def clone(self): pass
|
||||
def confirmDelete(self): pass
|
||||
def delete(self): pass
|
||||
def download(self): pass
|
||||
def edit(self): pass
|
||||
def id(self): pass
|
||||
def image(self): pass
|
||||
def imageEdit(self): pass
|
||||
def rss(self): pass
|
||||
def search(self): pass
|
||||
def submit(self): pass
|
||||
def thumbnail(self): pass
|
||||
def use(self): pass
|
||||
def view(self): pass
|
||||
|
||||
def postXml(self, id):
|
||||
if not context.getVar('xmlPost'):
|
||||
return pageNotFound()
|
||||
|
||||
xmlPost = context.getVar('xmlPost')
|
||||
item = xmlPost.firstChild
|
||||
dict = convertNodesToDict(item.childNodes)
|
||||
title = author = description = link = source = ''
|
||||
|
||||
if dict.has_key('title'):
|
||||
title = dict['title']
|
||||
if dict.has_key('author'):
|
||||
author = dict['author']
|
||||
if dict.has_key('description'):
|
||||
description = dict['description']
|
||||
if dict.has_key('link'):
|
||||
link = dict['link']
|
||||
if dict.has_key('source'):
|
||||
source = dict['source']
|
||||
|
||||
comment = commonTools.newThing('object', 'comments.Comment')
|
||||
comment.body = description
|
||||
comment.replyToId = id
|
||||
comment.name = author
|
||||
comment.title = title
|
||||
if context.getVar('virtualHost'):
|
||||
comment.language = context.getVar('virtualHost').language
|
||||
else:
|
||||
comment.language = 'en'
|
||||
try:
|
||||
commentId = self.addObject(comment)
|
||||
except faults.Fault:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
return accessForbidden()
|
||||
return writePageLayout(X.array(), 'Comment API')
|
||||
postXml.isPublicForWeb = 1
|
||||
|
||||
def submit(self, id = '', **keywords):
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
if not userToken:
|
||||
return pageNotFound()
|
||||
return ObjectsWebMixin.submit(self, id, **keywords)
|
||||
submit.isPublicForWeb = 1
|
||||
|
||||
def view(self, id):
|
||||
if not self.hasObject(id):
|
||||
return pageNotFound()
|
||||
if not self.canGetObject(id):
|
||||
return accessForbidden()
|
||||
object = self.getObject(id)
|
||||
layout = object.render()
|
||||
return writePageLayout(layout, '%s' % _(self.objectNameCapitalized))
|
||||
view.isPublicForWeb = 1
|
||||
|
||||
def viewAll(self):
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
if not userToken:
|
||||
return pageNotFound()
|
||||
return ObjectsWebMixin.viewAll(self)
|
||||
layout = X.array()
|
||||
userToken = context.getVar('userToken')
|
||||
if self.canModifyAdmin() and userToken:
|
||||
layout += X.div(_class = 'buttons-bar')(
|
||||
X.buttonStandalone('settings', X.actionUrl('admin')))
|
||||
return writePageLayout(layout, _(self.objectsNameCapitalized))
|
||||
viewAll.isPublicForWeb = 1
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ class ElectionMixin(ObjectWebMixin):
|
|||
|
||||
method = None
|
||||
method_kind_defaultValue = 'condorcet'
|
||||
method_kind_hasToMakeFieldFromValue = 0
|
||||
#method_kind_hasToMakeFieldFromValue = 0
|
||||
method_kind_isRequired = 1
|
||||
method_kind_values = [
|
||||
'average',
|
||||
|
@ -185,12 +185,11 @@ class ElectionMixin(ObjectWebMixin):
|
|||
readOnlySlotNames = ObjectWebMixin.getEditLayoutReadOnlySlotNames(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
readOnlySlotNames = readOnlySlotNames[:]
|
||||
state = fields['state']
|
||||
if not fields.has_key('id') or not fields['id']:
|
||||
if not self.id:
|
||||
slotName = 'state'
|
||||
if not slotName in readOnlySlotNames:
|
||||
readOnlySlotNames.append(slotName)
|
||||
if state in ['closed', 'running']:
|
||||
if self.state in ['closed', 'running']:
|
||||
for slotName in [
|
||||
'ballotKind', 'candidatesSet', 'method', 'subject', 'title',
|
||||
'voteKind', 'votersSet', 'weightingsGradeId']:
|
||||
|
@ -371,14 +370,6 @@ class ElectionMixin(ObjectWebMixin):
|
|||
tr += vote.getMarksRowLayout(candidateIds)
|
||||
return layout
|
||||
|
||||
def makeFieldsFromInstance(self, fields, parentSlot = None):
|
||||
if self.__class__ == ElectionAverage:
|
||||
fields['method'] = 'average'
|
||||
else:
|
||||
fields['method'] = 'condorcet'
|
||||
ObjectWebMixin.makeFieldsFromInstance(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
|
||||
def newVote(self):
|
||||
vote = commonTools.newThing('object', 'votes.%s' % self.voteKind)
|
||||
if self.ballotKind != 'voter-choice':
|
||||
|
@ -604,7 +595,6 @@ class ElectionCondorcet(ElectionMixin, ElectionCondorcet):
|
|||
table += X.colgroup()
|
||||
table += X.colgroup(span = 3)
|
||||
table += X.thead(X.tr(
|
||||
# FIXME: I don't know which scope to apply to this <th>
|
||||
X.th()(_('Candidates')),
|
||||
X.th(scope = 'col')(_('Wins')),
|
||||
X.th(scope = 'col')(_('Losses')),
|
||||
|
@ -669,15 +659,10 @@ class ElectionsWeb(ObjectsWebMixin, ElectionsProxy):
|
|||
if not self.canCloneObject(id):
|
||||
return accessForbidden()
|
||||
object = self.getObject(id)
|
||||
object.id = None
|
||||
object.version = 0
|
||||
object.state = 'draft' # The difference is here.
|
||||
keywords = {}
|
||||
object.makeFieldsFromInstance(keywords)
|
||||
del keywords['id']
|
||||
keywords['again'] = 1
|
||||
keywords['cloned'] = 1
|
||||
uri = X.actionUrl('edit')
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
return self.editObject(object)
|
||||
clone.isPublicForWeb = 1
|
||||
|
||||
def confirmPesterAbstentionnists(self, id):
|
||||
|
@ -699,6 +684,15 @@ class ElectionsWeb(ObjectsWebMixin, ElectionsProxy):
|
|||
canCache = 0)
|
||||
confirmPesterAbstentionnists.isPublicForWeb = 1
|
||||
|
||||
def getObject_handleResult(self, lazyObject):
|
||||
object = ElectionsProxy.getObject_handleResult(self,
|
||||
lazyObject)
|
||||
if self.__class__ is ElectionAverage:
|
||||
object.getSlot('method').setValue('average')
|
||||
else:
|
||||
object.getSlot('method').setValue('condorcet')
|
||||
return object
|
||||
|
||||
def getViewBelowButtonsBarLayout(self, object, fields):
|
||||
layout = X.div(_class = 'election-results')
|
||||
layout += ObjectsWebMixin.getViewBelowButtonsBarLayout(
|
||||
|
@ -776,8 +770,9 @@ class ElectionsWeb(ObjectsWebMixin, ElectionsProxy):
|
|||
return OK
|
||||
graphPie.isPublicForWeb = 1
|
||||
|
||||
def newObject(self, fields):
|
||||
if fields.has_key('method') and fields['method'] == 'average':
|
||||
def newObject(self, fields = None):
|
||||
if fields and fields.has_key('method') and \
|
||||
fields['method'] == 'average':
|
||||
object = ElectionAverage()
|
||||
else:
|
||||
object = ElectionCondorcet()
|
||||
|
@ -800,18 +795,13 @@ class ElectionsWeb(ObjectsWebMixin, ElectionsProxy):
|
|||
X.idUrl(id))
|
||||
pesterAbstentionnists.isPublicForWeb = 1
|
||||
|
||||
def submitAddObject(self, object, **keywords):
|
||||
def submitAddObject(self, object):
|
||||
try:
|
||||
return ObjectsWebMixin.submitAddObject(self, object, **keywords)
|
||||
return ObjectsWebMixin.submitAddObject(self, object)
|
||||
except faults.WinnersGroupNotEmpty, f:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
context.setVar('error', 1)
|
||||
object.setError('self.winnersGroupId', f)
|
||||
return self.editObject(object, **keywords)
|
||||
keywords['winnersGroupId_error'] = _('Group not empty!')
|
||||
uri = X.idUrl(object.id, 'edit')
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
return self.editObject(object)
|
||||
|
||||
def view(self, id):
|
||||
if not self.hasObject(id):
|
||||
|
|
|
@ -75,254 +75,5 @@ register(Forum)
|
|||
|
||||
|
||||
class ForumsWeb(ObjectsWebMixin, ForumsProxy):
|
||||
def addComment(self, id, replyToId = '', again = '', error = '',
|
||||
**keywords):
|
||||
if not self.hasObject(id):
|
||||
return pageNotFound()
|
||||
forum = self.getObject(id)
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['id'] = id
|
||||
if replyToId:
|
||||
keywords['replyToId'] = replyToId
|
||||
else:
|
||||
keywords['replyToId'] = id
|
||||
keywords['language'] = forum.language
|
||||
userId = context.getVar('userId', '')
|
||||
if userId:
|
||||
keywords['authorId'] = userId
|
||||
if not self.hasObject(id):
|
||||
return pageNotFound()
|
||||
commentsWeb = getWebForServerRole('comments')
|
||||
|
||||
comment = commonTools.newThing('object', 'comments.Comment')
|
||||
if not again:
|
||||
comment.initFields(keywords)
|
||||
comment.repairFields(keywords)
|
||||
|
||||
context.push(_level = 'addComment',
|
||||
isCreateEditMode = 1,
|
||||
layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
if error:
|
||||
layout += comment.getErrorLayout(keywords)
|
||||
form = X.form(
|
||||
action = X.actionUrl('submitComment'),
|
||||
enctype= 'multipart/form-data',
|
||||
method = 'post', replyToId = replyToId)
|
||||
layout += form
|
||||
|
||||
slot = slots.Root(comment)
|
||||
widget = slot.getWidget()
|
||||
form += widget.getModelPageBodyLayout(slot, keywords)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')
|
||||
form += buttonsBar
|
||||
actionButtonsBar = X.span(_class = 'action-buttons-bar')
|
||||
buttonsBar += actionButtonsBar
|
||||
actionButtonsBar += X.buttonInForm('create', 'createButton')
|
||||
|
||||
return writePageLayout(layout, _('New Comment'))
|
||||
finally:
|
||||
context.pull(_level = 'addComment')
|
||||
addComment.isPublicForWeb = 1
|
||||
|
||||
def submitComment(self, id, **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['id'] = id
|
||||
|
||||
forum = self.getObject(id)
|
||||
|
||||
if isButtonSelected('applyButton', keywords):
|
||||
keywords['again'] = '1'
|
||||
keywords['hideErrors'] = '1'
|
||||
error = 0
|
||||
commentsWeb = getWebForServerRole('comments')
|
||||
|
||||
|
||||
if keywords.has_key('replyToId') and keywords['replyToId']:
|
||||
commentsWeb.incNbReplies(keywords['replyToId'])
|
||||
|
||||
comment = commonTools.newThing('object', 'comments.Comment')
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
else:
|
||||
del keywords['id'] # Not the comment id.
|
||||
comment.submitFields(keywords)
|
||||
comment.language = forum.language
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
uri = X.idUrl(id, 'addComment')
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
try:
|
||||
commentId = commentsWeb.addObject(comment)
|
||||
except faults.Fault:
|
||||
raise
|
||||
return accessForbidden()
|
||||
return redirect(X.idUrl(id))
|
||||
submitComment.isPublicForWeb = 1
|
||||
|
||||
def renderReplies(self, forumId, commentId):
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
|
||||
layout = X.array()
|
||||
# add quick path :
|
||||
layout += X.a(href = X.actionUrl())('Index Forums')
|
||||
layout += ' -> '
|
||||
# ... and build the forum link :
|
||||
object = getObject(forumId)
|
||||
layout += X.a(href = X.idUrl(forumId))(object.title)
|
||||
|
||||
# render original comment :
|
||||
commentsWeb = getWebForServerRole('comments')
|
||||
comment = commentsWeb.getObject(commentId)
|
||||
layout += comment.render()
|
||||
|
||||
# comment add button :
|
||||
if userToken:
|
||||
layout += X.buttonStandalone('post-reply',
|
||||
X.idUrl(forumId, 'addComment').add('replyToId', commentId))
|
||||
|
||||
# render replies :
|
||||
layout += X.h4(_('replies: %d') % comment.nbReplies)
|
||||
comments = commentsWeb.getComments(replyToId = commentId)
|
||||
for comment in comments:
|
||||
layout += X.hr()
|
||||
layout += comment.render()
|
||||
|
||||
return writePageLayout(layout, _('Replies List'))
|
||||
renderReplies.isPublicForWeb = 1
|
||||
|
||||
|
||||
def getViewActionButtonsBarLayout(self, object, fields):
|
||||
layout = ObjectsWebMixin.getViewActionButtonsBarLayout(
|
||||
self, object, fields)
|
||||
|
||||
layout += X.array()
|
||||
layout += X.br()
|
||||
layout += X.br()
|
||||
# add post button (new subject ) :
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
if object.isActive:
|
||||
if userToken:
|
||||
layout += X.buttonStandalone(
|
||||
'post-comment', X.idUrl(object.id, 'addComment'))
|
||||
# add quick path :
|
||||
layout += X.a(href = X.actionUrl())('Index Forums')
|
||||
|
||||
return layout
|
||||
|
||||
def getViewNavigationButtonsBarLayout(self, object, fields):
|
||||
pass
|
||||
|
||||
def getViewOtherActionButtonsBarLayout(self, object, fields):
|
||||
pass
|
||||
|
||||
|
||||
def view(self, id):
|
||||
# render the subjects/comments of the forum :
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
|
||||
if not self.hasObject(id):
|
||||
return pageNotFound()
|
||||
if not self.canGetObject(id):
|
||||
return accessForbidden()
|
||||
|
||||
object = Forum()
|
||||
slotNames = [x for x in object.getSlotNames()]
|
||||
object = self.getPartialObject(id, slotNames)
|
||||
rememberObject(id)
|
||||
|
||||
keywords = {}
|
||||
object.makeFieldsFromInstance(keywords)
|
||||
object.repairFields(keywords)
|
||||
|
||||
layout = X.array()
|
||||
|
||||
# button bar :
|
||||
layout += self.getViewActionButtonsBarLayout(object, keywords)
|
||||
|
||||
# index link :
|
||||
if not userToken:
|
||||
layout += X.div(_class = 'indexForum')
|
||||
layout += X.a(href = X.actionUrl())('Index Forums')
|
||||
|
||||
commentsWeb = getWebForServerRole('comments')
|
||||
comments = commentsWeb.getComments(replyToId = id)
|
||||
if comments:
|
||||
# FIXME: probably not xhtml strict (there are other
|
||||
# cases in this file, pay attention)
|
||||
table = X.table(width="100%", cellspacing="2", cellpadding="2",
|
||||
border="0", align="center")
|
||||
tr = X.tr()
|
||||
tr += X.th()(_('Subject'))
|
||||
tr += X.th()(_('Replies'))
|
||||
tr += X.th()(_('Author'))
|
||||
table += tr
|
||||
for comment in comments:
|
||||
tr = X.tr()
|
||||
tr += X.td(width = "65%", align = "left")(X.a(
|
||||
href = X.idUrl(id, 'renderReplies').add(
|
||||
'forumId', id).add('commentId', comment.id))(
|
||||
comment.title))
|
||||
tr += X.td(align = "center")(comment.nbReplies)
|
||||
if comment.authorId:
|
||||
tr += X.td(align = "center")(
|
||||
X.objectHypertextLabel(comment.authorId))
|
||||
elif comment.name:
|
||||
tr += X.td(align = "center")(comment.name)
|
||||
else:
|
||||
tr += X.td(align = "center")(comment.body)
|
||||
table += tr
|
||||
layout += table
|
||||
|
||||
return writePageLayout(layout, '%s' % object.title)
|
||||
view.isPublicForWeb = 1
|
||||
|
||||
def getIndexForumLayout(self):
|
||||
forumsWeb = getWebForServerRole('forums')
|
||||
forums = forumsWeb.getForums()
|
||||
|
||||
layout = X.array()
|
||||
if len(forums)>0:
|
||||
table = X.table(width="100%", cellspacing="2",
|
||||
cellpadding="2", border="0", align="center")
|
||||
tr = X.tr()
|
||||
tr += X.th()(_('Forum'))
|
||||
tr += X.th()(_('Active'))
|
||||
tr += X.th()(_('Subjects'))
|
||||
table += tr
|
||||
for p in forums:
|
||||
commentsWeb = getWebForServerRole('comments')
|
||||
comments = commentsWeb.getComments(replyToId = p.id)
|
||||
nb_subjects = len(comments)
|
||||
tr = X.tr()
|
||||
tr += X.td(align="left")(X.a(href = X.idUrl(p.id))(p.title))
|
||||
if p.isActive:
|
||||
isActive = _('Yes')
|
||||
else:
|
||||
isActive = _('No')
|
||||
tr += X.td(align="center")(isActive)
|
||||
tr += X.td(align="center")(nb_subjects)
|
||||
table += tr
|
||||
|
||||
layout += table
|
||||
|
||||
layout += X.br()
|
||||
layout += ObjectsWebMixin.getViewAllActionButtonsBarLayout(self)
|
||||
|
||||
return layout
|
||||
|
||||
def viewAll(self):
|
||||
context.push(_level = 'viewAll',
|
||||
defaultDispatcherId = context.getVar('dispatcherId'))
|
||||
try:
|
||||
layout = self.getIndexForumLayout()
|
||||
finally:
|
||||
context.pull(_level = 'viewAll')
|
||||
return writePageLayout(layout, _('Forums List'))
|
||||
viewAll.isPublicForWeb = 1
|
||||
pass
|
||||
|
||||
|
|
|
@ -93,10 +93,10 @@ class MarksWidget(widgets.BaseWidget):
|
|||
else:
|
||||
td = X.td(_class = 'field-value')
|
||||
tr += td
|
||||
errorCode = slot.getFieldOption(
|
||||
fields, objectId + '_error')
|
||||
if errorCode and not fields.has_key('hideErrors'):
|
||||
td += X.asIs(makeErrorMessage(errorCode))
|
||||
error = slot.getObject().getError(slot.getPath())
|
||||
if error and not context.getVar('hideErrors'):
|
||||
td += X.span(_class = 'error-message')(
|
||||
_(error.uiFaultString))
|
||||
td += X.input(maxlength = 6, name = fieldName, size = 6,
|
||||
type = 'text', value = mark)
|
||||
td += X.nbsp
|
||||
|
@ -146,7 +146,7 @@ class Grade(ObjectWebMixin, Grade):
|
|||
value = []
|
||||
for i in range(count):
|
||||
itemSlot = kind.getItemSlot(slot, i)
|
||||
itemValue = itemSlot.getField(fields, default = '')
|
||||
itemValue = itemSlot.getValue() or ''
|
||||
if itemValue:
|
||||
value.append(itemValue)
|
||||
if value == []:
|
||||
|
|
|
@ -63,7 +63,7 @@ objects.register(AdminGroups)
|
|||
|
||||
|
||||
class GroupMixin(objects.ObjectWebMixin):
|
||||
# FIME: Replace by kind ServerRoles.
|
||||
# FIXME: Replace by kind ServerRoles.
|
||||
acceptedRoles_kind_itemKind_value_widget_allLabel = N_('Every Type')
|
||||
acceptedRoles_kind_itemKind_value_widget_noneLabel = N_('No Type')
|
||||
acceptedRoles_kind_widget_apply = 1
|
||||
|
@ -71,8 +71,6 @@ class GroupMixin(objects.ObjectWebMixin):
|
|||
|
||||
className = None
|
||||
className_kind_defaultValue = 'GroupUnion'
|
||||
className_kind_hasToMakeFieldFromValue = 0
|
||||
className_kind_hasToSubmitField = 0
|
||||
className_kind_importExport = 'private'
|
||||
className_kind_isRequired = 1
|
||||
className_kind_values = [
|
||||
|
@ -106,26 +104,6 @@ class GroupMixin(objects.ObjectWebMixin):
|
|||
slotNames.remove(slotName)
|
||||
return slotNames
|
||||
|
||||
def initFields(self, fields, parentSlot = None):
|
||||
fields['className'] = self.__class__.__name__
|
||||
objects.ObjectWebMixin.initFields(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
|
||||
def makeFieldsFromInstance(self, fields, parentSlot = None):
|
||||
fields['className'] = self.__class__.__name__
|
||||
objects.ObjectWebMixin.makeFieldsFromInstance(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
|
||||
def repairFields(self, fields, parentSlot = None):
|
||||
if fields.has_key('className'):
|
||||
self.__class__ = commonTools.getThingClass(
|
||||
'object', 'groups.%s' % fields['className'])
|
||||
else:
|
||||
self.__class__ = commonTools.getThingClass(
|
||||
'object', 'groups.GroupUnion')
|
||||
objects.ObjectWebMixin.repairFields(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
|
||||
|
||||
class GroupCountableMixin(GroupMixin):
|
||||
itemIds = None
|
||||
|
@ -137,30 +115,6 @@ class GroupCountableMixin(GroupMixin):
|
|||
itemIds_kind_widgetName = 'Multi'
|
||||
itemIds_kindName = 'Sequence'
|
||||
|
||||
membersSet_kind_itemKind_value_widgetName = 'SelectId'
|
||||
membersSet_kind_widget_fieldLabel = N_('Members')
|
||||
membersSet_kind_widgetName = 'Multi'
|
||||
|
||||
def getEditLayout(self, fields, parentSlot = None):
|
||||
acceptedRolesSlot = self.getSlot(
|
||||
'acceptedRoles', parentSlot = parentSlot)
|
||||
# Duplicates fields, so that the "missing value" error fields generated
|
||||
# by the following submitField are not displayed.
|
||||
tmpFields = fields.copy()
|
||||
acceptedRolesSlot.getKind().submitField(acceptedRolesSlot, tmpFields)
|
||||
acceptedRoles = self.acceptedRoles
|
||||
if acceptedRoles:
|
||||
self.membersSet_kind = copy.copy(self.membersSet_kind)
|
||||
self.membersSet_kind.itemKind = copy.copy(
|
||||
self.membersSet_kind.itemKind)
|
||||
self.membersSet_kind.itemKind.serverRoles = acceptedRoles
|
||||
layout = GroupMixin.getEditLayout(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
if acceptedRoles:
|
||||
del(self.membersSet_kind.itemKind)
|
||||
del(self.membersSet_kind)
|
||||
return layout
|
||||
|
||||
def getEditLayoutSlotNames(self, fields, parentSlot = None):
|
||||
slotNames = GroupMixin.getEditLayoutSlotNames(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
|
@ -181,23 +135,6 @@ class GroupCountableMixin(GroupMixin):
|
|||
slotNames.remove(slotName)
|
||||
return slotNames
|
||||
|
||||
def makeFieldsFromInstance(self, fields, parentSlot = None):
|
||||
self.itemIds_kind = None
|
||||
GroupMixin.makeFieldsFromInstance(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
del self.itemIds_kind
|
||||
try:
|
||||
self.itemIds = self.getContainedIds()
|
||||
except faults.IllegalRecursiveGroup:
|
||||
self.itemIds_kind = commonTools.newThing(
|
||||
'kind', 'String', isTranslatable = 0)
|
||||
self.itemIds = _('Illegal recursive group')
|
||||
else:
|
||||
self.itemIds = sortIds(self.itemIds)
|
||||
slot = self.getSlot('itemIds', parentSlot = parentSlot)
|
||||
kind = self.itemIds_kind
|
||||
kind.makeFieldFromValue(slot, fields, self.itemIds)
|
||||
|
||||
|
||||
class GroupAll(GroupMixin, proxyGroups.GroupAll):
|
||||
pass
|
||||
|
@ -214,20 +151,44 @@ class GroupIntersection(GroupCountableMixin, proxyGroups.GroupIntersection):
|
|||
objects.register(GroupIntersection)
|
||||
|
||||
|
||||
class GroupRole(GroupMixin, proxyGroups.GroupRole):
|
||||
pass
|
||||
objects.register(GroupRole)
|
||||
|
||||
|
||||
class GroupUnion(GroupCountableMixin, proxyGroups.GroupUnion):
|
||||
pass
|
||||
objects.register(GroupUnion)
|
||||
|
||||
|
||||
class GroupsWeb(objects.ObjectsWebMixin, proxyGroups.GroupsProxy):
|
||||
def newObject(self, fields):
|
||||
if fields.has_key('className'):
|
||||
object = commonTools.newThing(
|
||||
'object', 'groups.%s' % fields['className'])
|
||||
else:
|
||||
object = commonTools.newThing('object', 'groups.GroupUnion')
|
||||
def getObject_handleResult(self, lazyObject):
|
||||
object = proxyGroups.GroupsProxy.getObject_handleResult(self,
|
||||
lazyObject)
|
||||
object.className = object.__class__.__name__
|
||||
if hasattr(object, 'itemIds'): # group is countable
|
||||
try:
|
||||
object.itemIds = object.getContainedIds()
|
||||
object.itemIds = sortIds(object.itemIds)
|
||||
except faults.IllegalRecursiveGroup:
|
||||
object.itemIds_kind = commonTools.newThing(
|
||||
'kind', 'String', isTranslatable = 0)
|
||||
object.itemIds = _('Illegal recursive group')
|
||||
return object
|
||||
|
||||
def newObject(self, fields = None):
|
||||
group = GroupUnion() # fake group to get className
|
||||
if not fields:
|
||||
group.className = 'GroupUnion'
|
||||
return group
|
||||
classNameSlot = group.getSlot('className')
|
||||
className = classNameSlot.getWidget().submit(classNameSlot, fields)
|
||||
if not className:
|
||||
className = 'GroupUnion'
|
||||
group = commonTools.newThing('object', 'groups.%s' % className)
|
||||
group.className = className
|
||||
return group
|
||||
|
||||
def view(self, id):
|
||||
webTools.addContextualHeader('noindex')
|
||||
return objects.ObjectsWebMixin.view(self, id)
|
||||
|
|
|
@ -84,10 +84,7 @@ class BaseObjectWebMixin(things.ThingMixin):
|
|||
version_kind_widgetName = 'InputText'
|
||||
|
||||
def getEmbeddedViewLayout(self):
|
||||
fields = {}
|
||||
self.makeFieldsFromInstance(fields)
|
||||
self.repairFields(fields)
|
||||
return self.getCompactViewLayout(fields, parentSlot = None)
|
||||
return self.getCompactViewLayout(None, parentSlot = None)
|
||||
|
||||
def getLabelTranslated(self, destinationLanguages = None, multiCall = None):
|
||||
translationsProxy = getProxyForServerRole('translations')
|
||||
|
@ -145,39 +142,8 @@ class AdminMixin(AdminWithoutWritersMixin):
|
|||
|
||||
|
||||
class ObjectWebMixin(BaseObjectWebMixin):
|
||||
addToId = None
|
||||
addToId_kind_stateInEditMode = 'read-only'
|
||||
addToId_kind_widget_fieldLabel = N_('Added to')
|
||||
addToId_kind_widgetName = 'SelectId'
|
||||
addToId_kindName = 'Id'
|
||||
|
||||
addToSlot = None
|
||||
addToSlot_kind_stateInEditMode = 'hidden'
|
||||
addToSlot_kind_stateInViewMode = 'hidden'
|
||||
addToSlot_kind_widget_fieldLabel = N_('Added to slot')
|
||||
addToSlot_kindName = 'String'
|
||||
|
||||
def getViewLayoutSlotNames(self, fields, parentSlot = None):
|
||||
slotNames = BaseObjectWebMixin.getViewLayoutSlotNames(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
if 'addToId' in slotNames:
|
||||
slotNames.remove('addToId')
|
||||
if 'addToSlot' in slotNames:
|
||||
slotNames.remove('addToSlot')
|
||||
return slotNames
|
||||
|
||||
def getEditLayoutSlotNames(self, fields, parentSlot = None):
|
||||
slotNames = BaseObjectWebMixin.getEditLayoutSlotNames(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
if 'addToId' in slotNames:
|
||||
slotNames.remove('addToId')
|
||||
if 'addToSlot' in slotNames:
|
||||
slotNames.remove('addToSlot')
|
||||
if fields.has_key('addToId') and fields['addToId'] and \
|
||||
not (fields.has_key('id') and fields['id']):
|
||||
slotNames.insert(0, 'addToId')
|
||||
slotNames.insert(0, 'addToSlot')
|
||||
return slotNames
|
||||
# this class had methods to add an object to another
|
||||
pass
|
||||
|
||||
|
||||
class WebMixin(things.ThingMixin):
|
||||
|
@ -193,12 +159,8 @@ class AdministrableWebMixin(WebMixin):
|
|||
return accessForbidden()
|
||||
admin = self.getAdmin()
|
||||
|
||||
keywords = {}
|
||||
admin.makeFieldsFromInstance(keywords)
|
||||
admin.repairFields(keywords)
|
||||
|
||||
layout = X.array()
|
||||
layout += admin.getViewLayout(keywords)
|
||||
layout += admin.getViewLayout(fields = None)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')
|
||||
layout += buttonsBar
|
||||
|
@ -217,34 +179,27 @@ class AdministrableWebMixin(WebMixin):
|
|||
layout,_('%s Settings') % _(self.objectsNameCapitalized))
|
||||
admin.isPublicForWeb = 1
|
||||
|
||||
def adminEdit(self, again = '', error = '', **keywords):
|
||||
def adminEdit(self):
|
||||
if not self.isAdmin():
|
||||
return accessForbidden()
|
||||
admin = self.getAdmin()
|
||||
return self.adminObjectEdit(admin)
|
||||
adminEdit.isPublicForWeb = 1
|
||||
|
||||
def adminObjectEdit(self, admin):
|
||||
|
||||
context.push(_level = 'adminEdit',
|
||||
defaultDispatcherId = context.getVar('dispatcherId'),
|
||||
layoutMode = 'edit')
|
||||
try:
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
if not self.isAdmin():
|
||||
return accessForbidden()
|
||||
admin = self.getAdmin()
|
||||
|
||||
if keywords.has_key('adminObject') and \
|
||||
isinstance(keywords['adminObject'], admin.__class__):
|
||||
admin = keywords['adminObject']
|
||||
del keywords['adminObject']
|
||||
|
||||
if not again:
|
||||
admin.makeFieldsFromInstance(keywords)
|
||||
admin.repairFields(keywords)
|
||||
|
||||
layout = X.array()
|
||||
if error:
|
||||
layout += admin.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += admin.getErrorLayout()
|
||||
form = X.form(
|
||||
action = X.actionUrl('adminSubmit'),
|
||||
enctype= 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
form += admin.getEditLayout(keywords)
|
||||
form += admin.getEditLayout(fields = None)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')
|
||||
form += buttonsBar
|
||||
|
@ -255,7 +210,6 @@ class AdministrableWebMixin(WebMixin):
|
|||
context.pull(_level = 'adminEdit')
|
||||
return writePageLayout(layout, _('Editing %s Settings') \
|
||||
% _(self.objectsNameCapitalized))
|
||||
adminEdit.isPublicForWeb = 1
|
||||
|
||||
def adminSubmit(self, **keywords):
|
||||
uri = None
|
||||
|
@ -266,25 +220,21 @@ class AdministrableWebMixin(WebMixin):
|
|||
keywords = {}
|
||||
if not self.isAdmin():
|
||||
return accessForbidden()
|
||||
admin = self.getAdmin()
|
||||
|
||||
if isButtonSelected('applyButton', keywords):
|
||||
keywords['again'] = '1'
|
||||
keywords['hideErrors'] = '1'
|
||||
context.setVar('again', 1)
|
||||
context.setVar('hideErrors', 1)
|
||||
admin = self.newAdmin(keywords)
|
||||
admin.submitFields(keywords)
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
return self.adminEdit(adminObject = admin, **keywords)
|
||||
if context.getVar('again'):
|
||||
return self.adminObjectEdit(admin)
|
||||
try:
|
||||
self.modifyAdmin(admin)
|
||||
except faults.WrongVersion:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
keywords['versionError'] = '1'
|
||||
uri = X.actionUrl('adminEdit')
|
||||
uri.addKeywords(keywords)
|
||||
return # The redirect(uri) will be returned by the finally
|
||||
# instruction.
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
admin.setError('version', 1)
|
||||
return self.adminObjectEdit(admin)
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
|
@ -309,14 +259,9 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
if not self.canCloneObject(id):
|
||||
return accessForbidden()
|
||||
object = self.getObject(id)
|
||||
keywords = {}
|
||||
object.makeFieldsFromInstance(keywords)
|
||||
del keywords['id']
|
||||
keywords['again'] = 1
|
||||
keywords['cloned'] = 1
|
||||
uri = X.actionUrl('edit')
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
object.id = None
|
||||
object.version = 0
|
||||
return self.editObject(object)
|
||||
clone.isPublicForWeb = 1
|
||||
|
||||
def confirmDelete(self, id):
|
||||
|
@ -392,10 +337,7 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
return OK
|
||||
download.isPublicForWeb = 1
|
||||
|
||||
def edit(self, id = '', **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['id'] = id
|
||||
def edit(self, id = ''):
|
||||
if id and not self.hasObject(id):
|
||||
return pageNotFound()
|
||||
|
||||
|
@ -407,50 +349,45 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
else:
|
||||
if not self.canAddObject():
|
||||
return accessForbidden()
|
||||
object = self.newObject(keywords)
|
||||
object = self.newObject(None)
|
||||
|
||||
return self.editObject(object, **keywords)
|
||||
if not object.id:
|
||||
object.fillWithDefaultValues()
|
||||
|
||||
return self.editObject(object)
|
||||
edit.isPublicForWeb = 1
|
||||
|
||||
def editObject(self, object, again = 0, error = 0, **keywords):
|
||||
if object.id and not again:
|
||||
object.makeFieldsFromInstance(keywords)
|
||||
if not object.id and not again:
|
||||
object.initFields(keywords)
|
||||
object.repairFields(keywords)
|
||||
|
||||
def editObject(self, object):
|
||||
if not object.id:
|
||||
headerTitle = _(self.newObjectNameCapitalized)
|
||||
else:
|
||||
headerTitle = _('Editing %s - %s') % (
|
||||
_(self.objectNameCapitalized), object.getLabel())
|
||||
|
||||
if keywords.has_key('headerTitle'):
|
||||
headerTitle = keywords['headerTitle']
|
||||
if context.getVar('headerTitle'):
|
||||
headerTitle = context.getVar('headerTitle')
|
||||
|
||||
context.push(_level = 'edit',
|
||||
isCreateEditMode = not object.id,
|
||||
layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
leadIn = self.getEditLeadIn(object, keywords)
|
||||
leadIn = self.getEditLeadIn(object)
|
||||
if leadIn:
|
||||
layout += X.enclose(leadIn, _class = 'lead-in')
|
||||
if error:
|
||||
layout += object.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += object.getErrorLayout()
|
||||
form = X.form(action = X.actionUrl('submit'),
|
||||
enctype = 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
if keywords.has_key('cloned') and keywords['cloned']:
|
||||
form += X.input(name = 'cloned', type = 'hidden', value = '1')
|
||||
|
||||
if keywords.has_key('nextUri') and keywords['nextUri']:
|
||||
if context.getVar('nextUri'):
|
||||
form += X.input(name = 'nextUri', type = 'hidden',
|
||||
value = keywords['nextUri'])
|
||||
value = context.getVar('nextUri'))
|
||||
|
||||
slot = slots.Root(object)
|
||||
widget = slot.getWidget()
|
||||
form += widget.getModelPageBodyLayout(slot, keywords)
|
||||
form += widget.getModelPageBodyLayout(slot, fields = None)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')
|
||||
form += buttonsBar
|
||||
|
@ -471,7 +408,7 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
finally:
|
||||
context.pull(_level = 'edit')
|
||||
|
||||
def getEditLeadIn(self, object, fields):
|
||||
def getEditLeadIn(self, object):
|
||||
return None
|
||||
|
||||
def getObjectsLayout(self, partialObjects, objectIds,
|
||||
|
@ -526,11 +463,6 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
if kind.hasToMakeFieldFromValue:
|
||||
kind.makeFieldFromValue(
|
||||
slot, fields, slot.getValue())
|
||||
for slotName in slotNames:
|
||||
slot = partialObject.getSlot(slotName)
|
||||
kind = slot.getKind()
|
||||
if kind.hasToRepairField:
|
||||
kind.repairField(slot, fields)
|
||||
tr = X.tr(_class = ((even and 'even') or 'odd'))
|
||||
even = not even
|
||||
tbody += tr
|
||||
|
@ -549,7 +481,6 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
ul += X.li()(
|
||||
X.a(href = X.idUrl(partialObject.id))(label))
|
||||
|
||||
#layout += X.br()
|
||||
return layout
|
||||
|
||||
def getObjectsSectionLayout(self, partialObjects, intertitle,
|
||||
|
@ -592,18 +523,6 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
else:
|
||||
label = partialObject.getLabel()
|
||||
fields = {}
|
||||
if slotNames:
|
||||
for slotName in slotNames:
|
||||
slot = partialObject.getSlot(slotName)
|
||||
kind = slot.getKind()
|
||||
if kind.hasToMakeFieldFromValue:
|
||||
kind.makeFieldFromValue(
|
||||
slot, fields, slot.getValue())
|
||||
for slotName in slotNames:
|
||||
slot = partialObject.getSlot(slotName)
|
||||
kind = slot.getKind()
|
||||
if kind.hasToRepairField:
|
||||
kind.repairField(slot, fields)
|
||||
tr = X.tr(_class = ((even and 'even') or 'odd'))
|
||||
even = not even
|
||||
tbody += tr
|
||||
|
@ -715,7 +634,7 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
return None
|
||||
return layout
|
||||
|
||||
def getViewLeadIn(self, object, fields):
|
||||
def getViewLeadIn(self, object):
|
||||
return None
|
||||
|
||||
def getViewNavigationButtonsBarLayout(self, object, fields):
|
||||
|
@ -742,10 +661,7 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
image = download
|
||||
image.isPublicForWeb = 1
|
||||
|
||||
def imageEdit(self, id = '', path = '', **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['id'] = id
|
||||
def imageEdit(self, id = '', path = ''):
|
||||
if id:
|
||||
localId = commonTools.extractLocalId(id)
|
||||
if localId == '__admin__':
|
||||
|
@ -762,21 +678,20 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
else:
|
||||
if not self.canAddObject():
|
||||
return accessForbidden()
|
||||
object = self.newObject(keywords)
|
||||
object = self.newObject()
|
||||
|
||||
uploadSlot = object.getSlotByPath(path)
|
||||
upload = uploadSlot.getValue()
|
||||
data = upload.getSlot('data', parentSlot = uploadSlot).getField(
|
||||
keywords)
|
||||
data = upload.getSlot('data', parentSlot = uploadSlot).getValue()
|
||||
req = context.getVar('req')
|
||||
dataFileName = upload.getSlot(
|
||||
'dataFileName', parentSlot = uploadSlot).getField(keywords)
|
||||
'dataFileName', parentSlot = uploadSlot).getValue()
|
||||
if dataFileName:
|
||||
req.headers_out['Content-disposition'] = \
|
||||
'attachment; filename="%s"' % dataFileName
|
||||
req.headers_out['Content-length'] = str(len(data))
|
||||
req.content_type = upload.getSlot(
|
||||
'dataType', parentSlot = uploadSlot).getField(keywords)
|
||||
'dataType', parentSlot = uploadSlot).getValue()
|
||||
setHttpCookie()
|
||||
req.send_http_header()
|
||||
if req.method == 'HEAD':
|
||||
|
@ -840,8 +755,7 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
terms = terms.split(' ')
|
||||
object = self.newObject(keywords)
|
||||
allSlotNames = object.getSlotNames()
|
||||
for slotName in ['addToId', 'addToSlot', 'serverRole',
|
||||
'thingName', 'thingCategory']:
|
||||
for slotName in ['serverRole', 'thingName', 'thingCategory']:
|
||||
if slotName in allSlotNames:
|
||||
allSlotNames.remove(slotName)
|
||||
for slotName in allSlotNames:
|
||||
|
@ -877,38 +791,34 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
|
||||
keywords['id'] = id
|
||||
if isButtonSelected('applyButton', keywords):
|
||||
keywords['again'] = '1'
|
||||
keywords['hideErrors'] = '1'
|
||||
context.setVar('again', 1)
|
||||
context.setVar('hideErrors', 1)
|
||||
|
||||
error = 0
|
||||
object = self.newObject(keywords)
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
else:
|
||||
object.submitFields(keywords)
|
||||
object.submitFields(keywords)
|
||||
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
return self.editObject(object = object, **keywords)
|
||||
if context.getVar('again'):
|
||||
return self.editObject(object = object)
|
||||
|
||||
if not id:
|
||||
result = self.submitAddObject(object, **keywords)
|
||||
else:
|
||||
result = self.submitModifyObject(object, **keywords)
|
||||
try:
|
||||
if not id:
|
||||
result = self.submitAddObject(object)
|
||||
else:
|
||||
result = self.submitModifyObject(object)
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
return accessForbidden() # TODO: return failure ?
|
||||
|
||||
if result:
|
||||
return result
|
||||
|
||||
if not id and keywords.has_key('addToId') and keywords['addToId']:
|
||||
keywords['id'] = object.id
|
||||
self.submitAddObjectToOther(**keywords)
|
||||
|
||||
if keywords.has_key('nextUri') and keywords['nextUri']:
|
||||
return redirect(keywords['nextUri'])
|
||||
if context.getVar('nextUri'):
|
||||
return redirect(context.getVar('nextUri'))
|
||||
return redirect(X.idUrl(object.id))
|
||||
submit.isPublicForWeb = 1
|
||||
|
||||
def submitAddObject(self, object, **keywords):
|
||||
def submitAddObject(self, object):
|
||||
try:
|
||||
object.id = self.addObject(object)
|
||||
except faults.UserAccessDenied:
|
||||
|
@ -916,47 +826,14 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
raise
|
||||
return accessForbidden()
|
||||
|
||||
def submitAddObjectToOther(self, **keywords):
|
||||
# FIXME: proper error handling
|
||||
addToId = keywords['addToId']
|
||||
proxy = getProxy(addToId)
|
||||
objectWeAddTo = proxy.getObject(addToId)
|
||||
if keywords.has_key('addToSlot') and keywords['addToSlot']:
|
||||
slotName = keywords['addToSlot']
|
||||
slot = objectWeAddTo.getSlot(slotName)
|
||||
else:
|
||||
# if not slotname specified, we take the first sequence
|
||||
for slotName in objectWeAddTo.getOrderedLayoutSlotNames():
|
||||
slot = objectWeAddTo.getSlot(slotName)
|
||||
kind = slot.getKind()
|
||||
if kind.getThingName() != 'Sequence':
|
||||
continue
|
||||
if kind.itemKind.getThingName() != 'Id':
|
||||
continue
|
||||
break
|
||||
else:
|
||||
raise 'Unable to find a slot to add to'
|
||||
kindName = slot.getKind().getThingName()
|
||||
cV = slot.getValue()
|
||||
if kindName == 'Sequence':
|
||||
if not cV:
|
||||
cV = []
|
||||
cV.append(keywords['id'])
|
||||
else:
|
||||
cV = keywords['id']
|
||||
setattr(objectWeAddTo, slotName, cV)
|
||||
proxy.modifyObject(objectWeAddTo)
|
||||
|
||||
def submitModifyObject(self, object, **keywords):
|
||||
def submitModifyObject(self, object):
|
||||
try:
|
||||
self.modifyPartialObject(object, object.getSlotToModifyNames())
|
||||
except faults.WrongVersion:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
keywords['versionError'] = '1'
|
||||
uri = X.idUrl(object.id, 'edit')
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
object.setError('version', 1)
|
||||
return self.editObject(object)
|
||||
except faults.UserAccessDenied:
|
||||
return accessForbidden()
|
||||
|
||||
|
@ -1032,24 +909,19 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
object = self.getObject(id)
|
||||
rememberObject(id)
|
||||
|
||||
keywords = {}
|
||||
|
||||
object.makeFieldsFromInstance(keywords)
|
||||
object.repairFields(keywords)
|
||||
|
||||
label = object.getLabelTranslated(context.getVar('readLanguages'))
|
||||
|
||||
layout = X.array()
|
||||
leadIn = self.getViewLeadIn(object, keywords)
|
||||
leadIn = self.getViewLeadIn(object)
|
||||
if leadIn:
|
||||
layout += X.enclose(leadIn, _class = 'lead-in')
|
||||
slot = slots.Root(object)
|
||||
widget = slot.getWidget()
|
||||
layout += widget.getModelPageBodyLayout(slot, keywords)
|
||||
layout += widget.getModelPageBodyLayout(slot, None)
|
||||
pageTitle = context.getVar('pageTitle', default = None)
|
||||
layout += self.getViewAboveButtonsBarLayout(object, keywords)
|
||||
layout += self.getViewButtonsBarLayout(object, keywords)
|
||||
layout += self.getViewBelowButtonsBarLayout(object, keywords)
|
||||
layout += self.getViewAboveButtonsBarLayout(object, None)
|
||||
layout += self.getViewButtonsBarLayout(object, None)
|
||||
layout += self.getViewBelowButtonsBarLayout(object, None)
|
||||
|
||||
context.push(
|
||||
currentObject = WebAPI.GlasnostObject(object = object),
|
||||
|
@ -1151,3 +1023,109 @@ class ObjectsWebMixin(AdministrableWebMixin):
|
|||
raise apache.SERVER_RETURN, HTTP_INTERNAL_SERVER_ERROR
|
||||
return OK
|
||||
|
||||
class CommentableObjectMixin(things.ThingMixin):
|
||||
def addComment(self, id):
|
||||
if not self.hasObject(id):
|
||||
return pageNotFound()
|
||||
webRole = getWebForServerRole('comments')
|
||||
if not webRole:
|
||||
return pageNotFound()
|
||||
object = webRole.newObject(None)
|
||||
object.fillWithDefaultValues()
|
||||
return self.addCommentObject(id, object)
|
||||
addComment.isPublicForWeb = 1
|
||||
|
||||
def addCommentObject(self, id, object):
|
||||
webRole = getWebForServerRole('comments')
|
||||
context.push(_level = 'edit', layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
leadIn = webRole.getEditLeadIn(object)
|
||||
if leadIn:
|
||||
layout += X.enclose(leadIn, _class = 'lead-in')
|
||||
if context.getVar('error'):
|
||||
layout += object.getErrorLayout()
|
||||
form = X.form(action = X.idUrl(id, 'addCommentSubmit'),
|
||||
enctype = 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
slot = slots.Root(object)
|
||||
widget = slot.getWidget()
|
||||
form += widget.getModelPageBodyLayout(slot, None)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')(
|
||||
X.buttonInForm('add', 'addButton'))
|
||||
form += buttonsBar
|
||||
|
||||
return writePageLayout(layout, _(webRole.newObjectNameCapitalized))
|
||||
finally:
|
||||
context.pull(_level = 'edit')
|
||||
|
||||
def addCommentSubmit(self, id, **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
webRole = getWebForServerRole('comments')
|
||||
object = webRole.newObject(keywords)
|
||||
object.submitFields(keywords)
|
||||
object.parentId = id
|
||||
if context.getVar('again'):
|
||||
return self.addCommentObject(id, object)
|
||||
|
||||
try:
|
||||
webRole.submitAddObject(object)
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
return accessForbidden()
|
||||
return redirect(X.idUrl(id, 'withComments'))
|
||||
addCommentSubmit.isPublicForWeb = 1
|
||||
|
||||
def commentsLayout(self, id):
|
||||
commentsWeb = getWebForServerRole('comments')
|
||||
comments = commentsWeb.getObjectsWithParent(id).values()
|
||||
comments.sort(lambda x,y: cmp(x.creationTime, y.creationTime))
|
||||
layout = X.array()
|
||||
if len(comments) == 0:
|
||||
layout += X.p(_('No comment.'))
|
||||
for i, comment in zip(range(len(comments)), comments):
|
||||
layout += X.div(_class = 'comment', id = 'comment-%d' % (i+i))(
|
||||
X.span(_class = 'comment-no')(str(i+1)),
|
||||
comment.getViewLayout(self, None))
|
||||
# TODO: check if we can add comments to the object
|
||||
layout += X.div(_class = 'buttons-bar')(
|
||||
X.buttonStandalone('add', X.idUrl(id, 'addComment')))
|
||||
return layout
|
||||
|
||||
def comments(self, id):
|
||||
layout = self.commentsLayout(id)
|
||||
return writePageLayout(layout, _('Comments'))
|
||||
comments.isPublicForWeb = 1
|
||||
|
||||
def withComments(self, id):
|
||||
object = self.getObject(id)
|
||||
rememberObject(id)
|
||||
|
||||
label = object.getLabelTranslated(context.getVar('readLanguages'))
|
||||
|
||||
layout = X.array()
|
||||
slot = slots.Root(object)
|
||||
widget = slot.getWidget()
|
||||
layout += widget.getModelPageBodyLayout(slot, {})
|
||||
layout += self.getViewButtonsBarLayout(object, None)
|
||||
pageTitle = context.getVar('pageTitle', default = None)
|
||||
|
||||
layout += X.h2(id = 'comments')(_('Comments'))
|
||||
context.push(sectionLevel = context.getVar('sectionLevel') + 1)
|
||||
layout += self.commentsLayout(id)
|
||||
context.pull()
|
||||
|
||||
context.push(
|
||||
currentObject = WebAPI.GlasnostObject(object = object),
|
||||
)
|
||||
if not pageTitle:
|
||||
pageTitle = '%s - %s' % (_(self.objectNameCapitalized), label)
|
||||
layout = writePageLayout(layout, pageTitle)
|
||||
context.pull()
|
||||
return layout
|
||||
withComments.isPublicForWeb = 1
|
||||
|
||||
|
||||
|
|
|
@ -70,21 +70,19 @@ register(PageName)
|
|||
|
||||
class PageNamesWeb(ObjectsWebMixin, PageNamesProxy):
|
||||
|
||||
def submitAddObject(self, object, **keywords):
|
||||
def submitAddObject(self, object):
|
||||
try:
|
||||
return ObjectsWebMixin.submitAddObject(self, object, **keywords)
|
||||
return ObjectsWebMixin.submitAddObject(self, object)
|
||||
except faults.DuplicateValue:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
context.setVar('error', 1)
|
||||
object.setError('self.name', f)
|
||||
return self.edit(object = object, **keywords)
|
||||
return self.editObject(object)
|
||||
|
||||
def submitModifyObject(self, object, **keywords):
|
||||
def submitModifyObject(self, object):
|
||||
try:
|
||||
return ObjectsWebMixin.submitModifyObject(self, object, **keywords)
|
||||
return ObjectsWebMixin.submitModifyObject(self, object)
|
||||
except faults.DuplicateValue:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
context.setVar('error', 1)
|
||||
object.setError('self.name', f)
|
||||
return self.edit(object = object, **keywords)
|
||||
return self.editObject(object)
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ class Person(ObjectWebMixin, Person):
|
|||
email_kind_widgetName = 'Email' #'InputText'
|
||||
|
||||
fingerprint_kind_widget_fieldLabel = N_('GnuPG Fingerprint')
|
||||
fingerprint_kind_widget_size = 40
|
||||
fingerprint_kind_widget_size = 60
|
||||
fingerprint_kind_widgetName = 'InputText'
|
||||
|
||||
firstName_kind_widget_fieldLabel = N_('First Name')
|
||||
|
@ -96,6 +96,8 @@ class Person(ObjectWebMixin, Person):
|
|||
voteTokens_kind_stateInViewMode = 'hidden'
|
||||
|
||||
def getEditLayout(self, fields, parentSlot = None):
|
||||
if context.getVar('userId') != self.id:
|
||||
return ObjectWebMixin.getEditLayout(self, fields, parentSlot)
|
||||
dict = { 'firstName': _('Enter your first name.'),
|
||||
'lastName': _('Enter your last name.'),
|
||||
'nickname': _('Enter your nickname (optional).'),
|
||||
|
@ -104,7 +106,7 @@ class Person(ObjectWebMixin, Person):
|
|||
'(mandatory to receive encrypted emails).'),
|
||||
}
|
||||
for k, v in dict.items():
|
||||
kind = copy.copy(getattr(self, '%s_kind' % k))
|
||||
kind = copy.copy(self.getSlot(k).getKind())
|
||||
kind.balloonHelp = v
|
||||
setattr(self, '%s_kind' % k, kind)
|
||||
layout = ObjectWebMixin.getEditLayout(self, fields, parentSlot)
|
||||
|
@ -150,16 +152,6 @@ register(Person)
|
|||
|
||||
class PeopleWeb(ObjectsWebMixin, PeopleProxy):
|
||||
|
||||
def edit(self, id = '', **keywords):
|
||||
userToken = context.getVar('userToken')
|
||||
if not userToken:
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['headerTitle'] = _('New Account')
|
||||
|
||||
return ObjectsWebMixin.edit(self, id, **keywords)
|
||||
edit.isPublicForWeb = 1
|
||||
|
||||
def getSortedIds(self, objects):
|
||||
labels = {}
|
||||
for object in objects.values():
|
||||
|
@ -187,9 +179,10 @@ class PeopleWeb(ObjectsWebMixin, PeopleProxy):
|
|||
for election in elections:
|
||||
if not person.id in election.getVoterIds():
|
||||
continue
|
||||
tr = X.tr(X.td(X.a(href = X.idUrl(election.id))(
|
||||
election.getLabelTranslated(
|
||||
context.getVar('readLanguages')))))
|
||||
tr = X.tr(X.th(scope = 'row')(
|
||||
X.a(href = X.idUrl(election.id))(
|
||||
election.getLabelTranslated(
|
||||
context.getVar('readLanguages')))))
|
||||
table += tr
|
||||
if not votes.has_key(election.id):
|
||||
tr += X.td(_('Abstention'))
|
||||
|
@ -228,80 +221,46 @@ class PeopleWeb(ObjectsWebMixin, PeopleProxy):
|
|||
_("""The votes for the closed elections"""))
|
||||
return layout
|
||||
|
||||
def submit(self, id = '', **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['id'] = id
|
||||
if isButtonSelected('applyButton', keywords):
|
||||
keywords['again'] = '1'
|
||||
keywords['hideErrors'] = '1'
|
||||
def submitAddObject(self, object):
|
||||
error = 0
|
||||
object = self.newObject(keywords)
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
else:
|
||||
object.submitFields(keywords)
|
||||
try:
|
||||
return ObjectsWebMixin.submitAddObject(self, object)
|
||||
except faults.DuplicateFullName, f:
|
||||
error = 1
|
||||
object.setError('self.lastName', f)
|
||||
except faults.DuplicateEmail, f:
|
||||
error = 1
|
||||
object.setError('self.email', f)
|
||||
except faults.DuplicateFingerprint:
|
||||
error = 1
|
||||
object.setError('self.fingerprint', f)
|
||||
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
return self.edit(object = object, **keywords)
|
||||
if not id:
|
||||
try:
|
||||
id = self.addObject(object)
|
||||
except faults.DuplicateFullName, f:
|
||||
error = 1
|
||||
object.getSlot('lastName').error = f
|
||||
except faults.DuplicateEmail, f:
|
||||
error = 1
|
||||
object.getSlot('email').error = f
|
||||
except faults.DuplicateFingerprint:
|
||||
error = 1
|
||||
object.getSlot('fingerprint').error = f
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
return accessForbidden()
|
||||
else:
|
||||
error = 0
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
uri = X.idUrl(id, 'edit')
|
||||
return self.edit(object = object, **keywords)
|
||||
### if object.email:
|
||||
### return success(
|
||||
### _("""\
|
||||
### The account has successfully been created.
|
||||
### An email containing the password has been sent to %s.\
|
||||
### """) % object.email, X.idUrl(id))
|
||||
else:
|
||||
try:
|
||||
self.modifyPartialObject(object, object.getSlotToModifyNames())
|
||||
except faults.WrongVersion:
|
||||
error = 1
|
||||
keywords['versionError'] = '1'
|
||||
except faults.DuplicateFullName, f:
|
||||
error = 1
|
||||
object.getSlot('lastName').error = f
|
||||
except faults.DuplicateEmail, f:
|
||||
error = 1
|
||||
object.getSlot('email').error = f
|
||||
except faults.DuplicateFingerprint, f:
|
||||
error = 1
|
||||
object.getSlot('fingerprint').error = f
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
return accessForbidden()
|
||||
else:
|
||||
error = 0
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
uri = X.idUrl(id, 'edit')
|
||||
return self.edit(object = object, **keywords)
|
||||
return redirect(X.idUrl(id))
|
||||
submit.isPublicForWeb = 1
|
||||
if error:
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
return self.editObject(object)
|
||||
|
||||
def submitModifyObject(self, object):
|
||||
error = 0
|
||||
try:
|
||||
self.modifyPartialObject(object, object.getSlotToModifyNames())
|
||||
except faults.WrongVersion:
|
||||
error = 1
|
||||
object.setError('version', 1)
|
||||
except faults.DuplicateFullName, f:
|
||||
error = 1
|
||||
object.setError('self.lastName', f)
|
||||
except faults.DuplicateEmail, f:
|
||||
error = 1
|
||||
object.setError('self.email', f)
|
||||
except faults.DuplicateFingerprint, f:
|
||||
error = 1
|
||||
object.setError('self.fingerprint', f)
|
||||
|
||||
if error:
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
return self.editObject(object)
|
||||
|
||||
def view(self, id):
|
||||
webTools.addContextualHeader('noindex')
|
||||
|
|
|
@ -96,32 +96,31 @@ register(Preference)
|
|||
|
||||
|
||||
class PreferencesWeb(WebMixin, PreferencesProxy):
|
||||
def edit(self, again = '', error = '', **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
def edit(self):
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
if not userToken:
|
||||
return accessForbidden()
|
||||
|
||||
preference = self.getPreference()
|
||||
if not again:
|
||||
preference.makeFieldsFromInstance(keywords)
|
||||
preference.repairFields(keywords)
|
||||
|
||||
return self.editObject(preference)
|
||||
edit.isPublicForWeb = 1
|
||||
|
||||
def editObject(self, preference):
|
||||
headerTitle = _('Editing Preferences')
|
||||
|
||||
context.push(_level = 'edit', layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
if error:
|
||||
layout += preference.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += preference.getErrorLayout()
|
||||
form = X.form(action = X.actionUrl('submit'),
|
||||
enctype= 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
|
||||
slot = slots.Root(preference)
|
||||
widget = slot.getWidget()
|
||||
form += widget.getModelPageBodyLayout(slot, keywords)
|
||||
form += widget.getModelPageBodyLayout(slot, None)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')
|
||||
form += buttonsBar
|
||||
|
@ -132,34 +131,24 @@ class PreferencesWeb(WebMixin, PreferencesProxy):
|
|||
return writePageLayout(layout, headerTitle)
|
||||
finally:
|
||||
context.pull(_level = 'edit')
|
||||
edit.isPublicForWeb = 1
|
||||
|
||||
def submit(self, **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
if isButtonSelected('applyButton', keywords):
|
||||
keywords['again'] = '1'
|
||||
keywords['hideErrors'] = '1'
|
||||
error = 0
|
||||
context.setVar('again', 1)
|
||||
context.setVar('hideErrors', 1)
|
||||
preference = Preference()
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
else:
|
||||
preference.submitFields(keywords)
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
uri = X.actionUrl('edit')
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
preference.submitFields(keywords)
|
||||
if context.getVar('again'):
|
||||
return self.editObject(preference)
|
||||
try:
|
||||
self.setPreference(preference)
|
||||
except faults.WrongVersion:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
keywords['versionError'] = '1'
|
||||
uri = X.actionUrl('edit')
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
preference.setError('version', 1)
|
||||
return self.editObject(preference)
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
|
@ -174,14 +163,10 @@ class PreferencesWeb(WebMixin, PreferencesProxy):
|
|||
|
||||
preference = self.getPreference()
|
||||
|
||||
keywords = {}
|
||||
preference.makeFieldsFromInstance(keywords)
|
||||
preference.repairFields(keywords)
|
||||
|
||||
layout = X.array()
|
||||
slot = slots.Root(preference)
|
||||
widget = slot.getWidget()
|
||||
layout += widget.getModelPageBodyLayout(slot, keywords)
|
||||
layout += widget.getModelPageBodyLayout(slot)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')
|
||||
layout += buttonsBar
|
||||
|
|
|
@ -78,11 +78,10 @@ class Rubric(ObjectWebMixin, Rubric):
|
|||
|
||||
def getViewLayout(self, fields, parentSlot = None):
|
||||
layout = X.array()
|
||||
contentId = fields['contentId']
|
||||
if contentId:
|
||||
web = getWeb(contentId)
|
||||
if web.canGetObject(contentId):
|
||||
object = web.getObject(contentId)
|
||||
if self.contentId:
|
||||
web = getWeb(self.contentId)
|
||||
if web.canGetObject(self.contentId):
|
||||
object = web.getObject(self.contentId)
|
||||
if object.getLabel() == self.getLabel() and \
|
||||
parentSlot and parentSlot.getLabel() == 'Root':
|
||||
context.setVar('pageTitle',
|
||||
|
@ -92,9 +91,9 @@ class Rubric(ObjectWebMixin, Rubric):
|
|||
|
||||
layout += object.getEmbeddedViewLayout()
|
||||
|
||||
if web.canModifyObject(contentId):
|
||||
if web.canModifyObject(self.contentId):
|
||||
layout += X.buttonStandalone(
|
||||
'edit', X.idUrl(contentId, 'edit'))
|
||||
'edit', X.idUrl(self.contentId, 'edit'))
|
||||
|
||||
layout += X.div(_class = 'clear')(X.hr())
|
||||
|
||||
|
@ -141,12 +140,80 @@ class RubricsWeb(ObjectsWebMixin, RubricsProxy):
|
|||
if not hasattr(webRole, 'canAddObject') or \
|
||||
not webRole.canAddObject():
|
||||
continue
|
||||
select += X.option(value = role.urlNew.add(
|
||||
'addToId', object.id).add(
|
||||
'nextUri', X.idUrl(object.id).getAsAbsoluteUrl()).add(
|
||||
'addToSlot', 'membersSet'))(
|
||||
select += X.option(
|
||||
value = X.idUrl(object.id,
|
||||
'addContent/%s' % role.web.serverRole))(
|
||||
_(webRole.objectNameCapitalized))
|
||||
if select.children:
|
||||
layout += form
|
||||
return layout
|
||||
|
||||
def addContent(self, id, serverRole):
|
||||
if not self.hasObject(id):
|
||||
return pageNotFound()
|
||||
rubric = self.getObject(id)
|
||||
webRole = getWebForServerRole(serverRole)
|
||||
if webRole is None:
|
||||
return pageNotFound()
|
||||
object = webRole.newObject(None)
|
||||
object.fillWithDefaultValues()
|
||||
if object.hasSlotName('writersSet'):
|
||||
object.writersSet = rubric.writersSet
|
||||
if object.hasSlotName('readersSet'):
|
||||
object.readersSet = rubric.readersSet
|
||||
return self.addContentObject(id, serverRole, object)
|
||||
addContent.isPublicForWeb = 1
|
||||
|
||||
def addContentObject(self, id, serverRole, object):
|
||||
webRole = getWebForServerRole(serverRole)
|
||||
context.push(_level = 'edit', layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
leadIn = webRole.getEditLeadIn(object)
|
||||
if leadIn:
|
||||
layout += X.enclose(leadIn, _class = 'lead-in')
|
||||
if context.getVar('error'):
|
||||
layout += object.getErrorLayout()
|
||||
form = X.form(action = X.idUrl(id, 'addContentSubmit/%s' % serverRole),
|
||||
enctype = 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
slot = slots.Root(object)
|
||||
widget = slot.getWidget()
|
||||
form += widget.getModelPageBodyLayout(slot, None)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')(
|
||||
X.buttonInForm('create', 'createButton'))
|
||||
form += buttonsBar
|
||||
|
||||
return writePageLayout(layout,
|
||||
_('Add %s To Rubric') % webRole.objectNameCapitalized)
|
||||
finally:
|
||||
context.pull(_level = 'edit')
|
||||
|
||||
def addContentSubmit(self, id, serverRole, **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
|
||||
webRole = getWebForServerRole(serverRole)
|
||||
object = webRole.newObject(keywords)
|
||||
object.submitFields(keywords)
|
||||
if context.getVar('again'):
|
||||
return self.addContentObject(id, serverRole, object)
|
||||
|
||||
try:
|
||||
webRole.submitAddObject(object)
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
return accessForbidden()
|
||||
|
||||
rubric = self.getObject(id)
|
||||
if not rubric.membersSet:
|
||||
rubric.membersSet = []
|
||||
rubric.membersSet.append(object.id)
|
||||
self.modifyObject(rubric)
|
||||
|
||||
return redirect(X.idUrl(id))
|
||||
addContentSubmit.isPublicForWeb = 1
|
||||
|
||||
|
||||
|
|
|
@ -68,11 +68,11 @@ class SimilarStringWidget(widgets.TextArea):
|
|||
|
||||
def getHtmlValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
similarString = slot.getField(fields, default = '')
|
||||
similarString = slot.getValue() or ''
|
||||
assert self.isInForm()
|
||||
assert self.isReadOnly(slot)
|
||||
sourceStringSlot = slot.getContainer().getSlot('sourceString')
|
||||
sourceString = sourceStringSlot.getField(fields, default = '')
|
||||
sourceString = sourceStringSlot.getValue() or ''
|
||||
|
||||
layout = X.array(
|
||||
self.getModelHiddenLayout(slot, fields),
|
||||
|
@ -99,63 +99,63 @@ class SimilarStringWidget(widgets.TextArea):
|
|||
return layout
|
||||
widgets.register(SimilarStringWidget)
|
||||
|
||||
|
||||
class TranslationToAddWidget(widgets.BaseWidget):
|
||||
thingName = 'TranslationToAdd'
|
||||
|
||||
def getHtmlValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
if not self.isInForm():
|
||||
return
|
||||
fromFieldName = slot.getFieldOptionName('from')
|
||||
toFieldName = slot.getFieldOptionName('to')
|
||||
fromFieldValue = slot.getFieldOption(fields, 'from', default = '')
|
||||
toFieldValue = slot.getFieldOption(fields, 'to', default = '')
|
||||
assert self.isInForm()
|
||||
assert not self.isReadOnly(slot)
|
||||
values = translation.languageKeys
|
||||
labels = translation.languageLabels
|
||||
layout = X.array()
|
||||
layout += self.getModelErrorLayout(slot, fields)
|
||||
layout += self.getModelHelpLayout(slot, fields)
|
||||
fromSelect = X.select(name = fromFieldName)
|
||||
if not fromFieldValue in values:
|
||||
fromSelect += X.option(
|
||||
selected = 'selected', value = '')(_('None'))
|
||||
for value in values:
|
||||
optionAttributes = {}
|
||||
if value == fromFieldValue:
|
||||
optionAttributes['selected'] = 'selected'
|
||||
fromSelect += X.option(value = value, **optionAttributes)(
|
||||
_(labels[value]))
|
||||
toSelect = X.select(name = toFieldName)
|
||||
if not toFieldValue in values:
|
||||
toSelect += X.option(
|
||||
selected = 'selected', value = '')(_('None'))
|
||||
for value in values:
|
||||
optionAttributes = {}
|
||||
if value == toFieldValue:
|
||||
optionAttributes['selected'] = 'selected'
|
||||
toSelect += X.option(value = value, **optionAttributes)(
|
||||
_(labels[value]))
|
||||
layout += _('From ')
|
||||
layout += fromSelect
|
||||
layout += _(' to ')
|
||||
layout += toSelect
|
||||
layout += ' '
|
||||
layout += X.array( _('From '), fromSelect, _(' to '), toSelect, ' ')
|
||||
layout += X.buttonInForm('add', slot.getFieldOptionName('addButton'))
|
||||
return layout
|
||||
|
||||
def submit(self, slot, fields):
|
||||
addButtonName = slot.getFieldOptionName('addButton')
|
||||
if not isButtonSelected(addButtonName, fields):
|
||||
return None
|
||||
|
||||
fromLanguage = slot.getFieldOption(fields, 'from') or ''
|
||||
toLanguage = slot.getFieldOption(fields, 'to') or ''
|
||||
if len(fromLanguage) != 2 or len(toLanguage) != 2:
|
||||
return None
|
||||
|
||||
object = slot.getObject()
|
||||
object.translationLanguages.append('%s%s' % (fromLanguage, toLanguage))
|
||||
slotKey = 'translatorsSet_%s_%s' % (fromLanguage, toLanguage)
|
||||
setattr(object, slotKey, None)
|
||||
kind = commonTools.newThing('kind', 'UsersSet')
|
||||
kind.widget = TranslatorsSetWidget()
|
||||
kind.buildKinds()
|
||||
setattr(object, slotKey + '_kind', kind)
|
||||
|
||||
context.setVar('again', 1)
|
||||
context.setVar('hideErrors', 1)
|
||||
return None
|
||||
widgets.register(TranslationToAddWidget)
|
||||
|
||||
|
||||
class TranslatorsSetWidget(widgets.Multi):
|
||||
thingName = 'TranslatorsSet'
|
||||
|
||||
def getHtmlFieldLabel(self, slot):
|
||||
fieldName = slot.getFieldName()
|
||||
assert fieldName.endswith('TranslatorsSet')
|
||||
languages = fieldName[:-len('TranslatorsSet')][-4:]
|
||||
fromLanguage = languages[:2]
|
||||
toLanguage = languages[2:4]
|
||||
fromLanguage = fieldName[-5:-3]
|
||||
toLanguage = fieldName[-2:]
|
||||
fieldLabelLocalized = _('%(from)s to %(to)s Translators') % {
|
||||
'from': _(translation.languageLabels[fromLanguage]),
|
||||
'to': _(translation.languageLabels[toLanguage]),
|
||||
|
@ -167,184 +167,31 @@ widgets.register(TranslatorsSetWidget)
|
|||
|
||||
|
||||
class AdminTranslations(AdminWithoutWritersMixin, AdminTranslations):
|
||||
translationLanguages = None
|
||||
|
||||
translationToAdd = None
|
||||
translationToAdd_kindName = 'TranslationToAdd'
|
||||
translationToAdd_kind_widget_fieldLabel = N_('Translation')
|
||||
translationToAdd_kind_widgetName = 'TranslationToAdd'
|
||||
|
||||
translatorsSets_kind_importExport = 'private'
|
||||
translatorsSets_kind_stateInEditMode = 'hidden'
|
||||
translatorsSets_kind_stateInViewMode = 'hidden'
|
||||
translatorsSets_kind_isRequired = 0
|
||||
translatorsSets_widgetName = 'TranslatorsSetsWidget'
|
||||
|
||||
def addTranslatorsSetsFields(self, localizationKeys):
|
||||
for localizationKey in localizationKeys:
|
||||
attributeName = localizationKey + 'TranslatorsSet'
|
||||
if not hasattr(self, attributeName):
|
||||
setattr(self, attributeName, None)
|
||||
setattr(self, attributeName + '_kind', kinds.Sequence(
|
||||
itemKind = kinds.Id(
|
||||
serverRoles = ['groups', 'people'],
|
||||
widget = widgets.SelectId()),
|
||||
widget = TranslatorsSetWidget()))
|
||||
|
||||
def delTranslatorsSetsFields(self, localizationKeys):
|
||||
for localizationKey in localizationKeys:
|
||||
attributeName = localizationKey + 'TranslatorsSet'
|
||||
delattr(self, attributeName + '_kind')
|
||||
|
||||
def exportToXmlRpc(self, requiredSlotNames = None, parentSlot = None):
|
||||
# It would have been better not having been forced to write this
|
||||
# here... Something like a better field_exporter support...
|
||||
result = AdminWithoutWritersCommon.exportToXmlRpc(
|
||||
self, requiredSlotNames = requiredSlotNames,
|
||||
parentSlot = parentSlot)
|
||||
translatorsSets = {}
|
||||
for translatorsLabel, translatorsSet in self.__dict__.items():
|
||||
if not translatorsLabel.endswith('TranslatorsSet'):
|
||||
continue
|
||||
if translatorsSet is None:
|
||||
continue
|
||||
localizationKey = translatorsLabel[:-len('TranslatorsSet')][-4:]
|
||||
translatorsSets[localizationKey] = translatorsSet
|
||||
if translatorsSets:
|
||||
result['translatorsSets'] = translatorsSets
|
||||
else:
|
||||
if not result.has_key('__noneSlotNames__'):
|
||||
result['__noneSlotNames__'] = []
|
||||
result['__noneSlotNames__'].append('translatorsSets')
|
||||
return result
|
||||
|
||||
def getEditLayout(self, fields, parentSlot = None):
|
||||
localizationKeys = []
|
||||
for translatorsLabel in fields.keys():
|
||||
if not translatorsLabel.endswith('TranslatorsSet_count'):
|
||||
continue
|
||||
localizationKey = translatorsLabel[:-len('TranslatorsSet_count')][
|
||||
-4:]
|
||||
localizationKeys.append(localizationKey)
|
||||
self.addTranslatorsSetsFields(localizationKeys)
|
||||
|
||||
context.push(fields = fields)
|
||||
layout = AdminWithoutWritersMixin.getEditLayout(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
context.pull()
|
||||
|
||||
self.delTranslatorsSetsFields(localizationKeys)
|
||||
return layout
|
||||
|
||||
def getOrderedLayoutSlotNames(self, parentSlot = None):
|
||||
slotNames = AdminWithoutWritersCommon.getOrderedLayoutSlotNames(
|
||||
self, parentSlot = parentSlot)
|
||||
slotNames = slotNames[:]
|
||||
fields = context.getVar('fields')
|
||||
for translatorsLabel in fields.keys():
|
||||
if not translatorsLabel.endswith('TranslatorsSet_count'):
|
||||
continue
|
||||
localizationKey = translatorsLabel[:-len('TranslatorsSet_count')][
|
||||
-4:]
|
||||
slotNames.append(localizationKey + 'TranslatorsSet')
|
||||
slotNames += ['translationToAdd']
|
||||
def getLayoutSlotNames(self, fields, parentSlot = None):
|
||||
slotNames = AdminWithoutWritersMixin.getLayoutSlotNames(self, fields, parentSlot)
|
||||
slotNames.remove('translatorsSets')
|
||||
slotNames.remove('translationToAdd')
|
||||
return slotNames
|
||||
|
||||
def getViewLayout(self, fields, parentSlot = None):
|
||||
localizationKeys = []
|
||||
for translatorsLabel in fields.keys():
|
||||
if not translatorsLabel.endswith('TranslatorsSet_count'):
|
||||
continue
|
||||
localizationKey = translatorsLabel[:-len('TranslatorsSet_count')][
|
||||
-4:]
|
||||
localizationKeys.append(localizationKey)
|
||||
self.addTranslatorsSetsFields(localizationKeys)
|
||||
|
||||
context.push(fields = fields)
|
||||
layout = AdminWithoutWritersMixin.getViewLayout(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
context.pull()
|
||||
|
||||
self.delTranslatorsSetsFields(localizationKeys)
|
||||
return layout
|
||||
|
||||
def getViewLayoutSlotNames(self, fields, parentSlot = None):
|
||||
slotNames = AdminWithoutWritersMixin.getViewLayoutSlotNames(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
slotNames = slotNames[:]
|
||||
if 'translationToAdd' in slotNames:
|
||||
slotNames.remove('translationToAdd')
|
||||
def getEditLayoutSlotNames(self, fields, parentSlot = None):
|
||||
slotNames = AdminWithoutWritersMixin.getViewLayoutSlotNames(self,
|
||||
fields, parentSlot)
|
||||
slotNames.append('translationToAdd')
|
||||
return slotNames
|
||||
|
||||
def importFromXmlRpc(self, dataImport, parentSlot = None):
|
||||
if dataImport.has_key('__noneSlotNames__'):
|
||||
noneSlotNames = dataImport['__noneSlotNames__']
|
||||
else:
|
||||
noneSlotNames = []
|
||||
for slotName in self.getSlotNames(parentSlot = parentSlot):
|
||||
if slotName in [
|
||||
'__noneSlotNames__', '__thingCategory__', '__thingName__']:
|
||||
continue
|
||||
# A slotName must always be a valid Python Indentifier, so no
|
||||
# encoding is needed to for the dataImport keys.
|
||||
if dataImport.has_key(slotName):
|
||||
exportedValue = dataImport[slotName]
|
||||
elif slotName in noneSlotNames:
|
||||
exportedValue = None
|
||||
else:
|
||||
continue
|
||||
if slotName == 'translatorsSets':
|
||||
if exportedValue is None:
|
||||
continue
|
||||
for localizationKey, translatorsSet in exportedValue.items():
|
||||
slotName = localizationKey + 'TranslatorsSet'
|
||||
setattr(self, slotName, translatorsSet)
|
||||
continue
|
||||
slot = self.getSlot(slotName)
|
||||
kind = slot.getKind()
|
||||
if not kind.isImportable():
|
||||
continue
|
||||
slot.setValue(kind.importValueFromXmlRpc(slot, exportedValue))
|
||||
|
||||
def makeFieldsFromInstance(self, fields, parentSlot = None):
|
||||
localizationKeys = []
|
||||
for translatorsLabel in self.__dict__.keys():
|
||||
if not translatorsLabel.endswith('TranslatorsSet'):
|
||||
continue
|
||||
localizationKey = translatorsLabel[:-len('TranslatorsSet')][-4:]
|
||||
localizationKeys.append(localizationKey)
|
||||
self.addTranslatorsSetsFields(localizationKeys)
|
||||
AdminWithoutWritersMixin.makeFieldsFromInstance(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
self.delTranslatorsSetsFields(localizationKeys)
|
||||
|
||||
def repairFields(self, fields, parentSlot = None):
|
||||
localizationKeys = []
|
||||
for translatorsLabel in fields.keys():
|
||||
if not translatorsLabel.endswith('TranslatorsSet_count'):
|
||||
continue
|
||||
localizationKey = translatorsLabel[:-len('TranslatorsSet_count')][
|
||||
-4:]
|
||||
localizationKeys.append(localizationKey)
|
||||
self.addTranslatorsSetsFields(localizationKeys)
|
||||
AdminWithoutWritersMixin.repairFields(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
self.delTranslatorsSetsFields(localizationKeys)
|
||||
|
||||
def submitFields(self, fields, parentSlot = None):
|
||||
localizationKeys = []
|
||||
for translatorsLabel in fields.keys():
|
||||
if not translatorsLabel.endswith('TranslatorsSet_count'):
|
||||
continue
|
||||
localizationKey = translatorsLabel[:-len('TranslatorsSet_count')][
|
||||
-4:]
|
||||
localizationKeys.append(localizationKey)
|
||||
self.addTranslatorsSetsFields(localizationKeys)
|
||||
AdminWithoutWritersMixin.submitFields(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
self.delTranslatorsSetsFields(localizationKeys)
|
||||
register(AdminTranslations)
|
||||
|
||||
|
||||
class Localization(ObjectWebMixin, Localization):
|
||||
destinationLanguage_kind_defaultValue = 'VoteRanking'
|
||||
destinationLanguage_kind_defaultValue = 'VoteRanking' # FIXME: wtf???
|
||||
destinationLanguage_kind_stateInEditMode = 'hidden'
|
||||
destinationLanguage_kind_stateInViewMode = 'hidden'
|
||||
destinationLanguage_kind_widget_fieldLabel = N_('Translation Language')
|
||||
|
@ -408,9 +255,8 @@ class Localization(ObjectWebMixin, Localization):
|
|||
layout = X.array()
|
||||
nbLines = len([
|
||||
x
|
||||
for x in self.getSlot(
|
||||
'sourceString', parentSlot = parentSlot).getField(
|
||||
fields, default = '')
|
||||
for x in (self.getSlot(
|
||||
'sourceString', parentSlot = parentSlot).getValue() or '')
|
||||
if x == '\n'])
|
||||
if nbLines > 18:
|
||||
nbLinesDestination = 20
|
||||
|
@ -430,8 +276,7 @@ class Localization(ObjectWebMixin, Localization):
|
|||
hiddenSlotNames = ObjectWebMixin.getEditLayoutHiddenSlotNames(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
hiddenSlotNames = hiddenSlotNames[:]
|
||||
if self.getSlot('isTranslatable', parentSlot = parentSlot).getField(
|
||||
fields):
|
||||
if self.getSlot('isTranslatable', parentSlot = parentSlot).getValue():
|
||||
isTranslatable = 1
|
||||
else:
|
||||
isTranslatable = 0
|
||||
|
@ -445,14 +290,13 @@ class Localization(ObjectWebMixin, Localization):
|
|||
slotNames = ObjectWebMixin.getEditLayoutSlotNames(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
slotNames = slotNames[:]
|
||||
if self.getSlot('isTranslatable', parentSlot = parentSlot).getField(
|
||||
fields):
|
||||
if self.getSlot('isTranslatable', parentSlot = parentSlot).getValue():
|
||||
isTranslatable = 1
|
||||
else:
|
||||
isTranslatable = 0
|
||||
slotName = 'similarString'
|
||||
slot = self.getSlot(slotName, parentSlot = parentSlot)
|
||||
if not isTranslatable or not slot.getField(fields):
|
||||
if not isTranslatable or not slot.getValue():
|
||||
if slotName in slotNames:
|
||||
slotNames.remove(slotName)
|
||||
return slotNames
|
||||
|
@ -467,33 +311,16 @@ class Localization(ObjectWebMixin, Localization):
|
|||
return slotNames
|
||||
|
||||
def submitFields(self, fields, parentSlot = None):
|
||||
slot = self.getSlot('isTranslatable', parentSlot = parentSlot)
|
||||
if slot.getField(fields):
|
||||
isTranslatable = 1
|
||||
else:
|
||||
isTranslatable = 0
|
||||
if fields.has_key('destinationString') and fields['destinationString']:
|
||||
fields['again'] = '1'
|
||||
fields['error'] = '1'
|
||||
errorFields = {}
|
||||
slot.setFieldOption(errorFields, 'error',
|
||||
_('Destination string set while translation '\
|
||||
'was marked as not necessary'))
|
||||
fields.update(errorFields)
|
||||
isTranslatable = 1
|
||||
fields['isTranslatable'] = '1'
|
||||
|
||||
for slotName in ('similarString', 'destinationString', 'isFuzzy'):
|
||||
# Duplicate each kind.
|
||||
slot = self.getSlot(slotName, parentSlot = parentSlot)
|
||||
kindName = slotName + '_kind'
|
||||
setattr(self, kindName, copy.copy(getattr(self, kindName)))
|
||||
getattr(self, kindName).hasToSubmitField = isTranslatable
|
||||
ObjectWebMixin.submitFields(self, fields, parentSlot = parentSlot)
|
||||
for slotName in ('similarString', 'destinationString', 'isFuzzy'):
|
||||
# Remove kind duplicate.
|
||||
kindName = slotName + '_kind'
|
||||
delattr(self, kindName)
|
||||
if not self.isTranslatable and self.destinationString:
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
slot = self.getSlot('isTranslatable')
|
||||
# TODO: fault with correct description
|
||||
_('Destination string set while translation '\
|
||||
'was marked as not necessary')
|
||||
self.setError(slot.getPath(), faults.BadValue())
|
||||
self.isTranslatable = 1
|
||||
register(Localization)
|
||||
|
||||
|
||||
|
@ -519,26 +346,17 @@ class TranslationsWeb(ObjectsWebMixin, TranslationsProxy):
|
|||
return redirect(X.actionUrl('viewAll/%s' % localizationKey))
|
||||
delete.isPublicForWeb = 1
|
||||
|
||||
def edit(self, localizationKey, sourceStringDigest, again = '',
|
||||
error = '', **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['localizationKey'] = localizationKey
|
||||
keywords['sourceStringDigest'] = sourceStringDigest
|
||||
def edit(self, localizationKey, sourceStringDigest):
|
||||
if not self.hasSourceString(localizationKey, sourceStringDigest):
|
||||
return pageNotFound()
|
||||
if not self.canModifyLocalization(localizationKey, sourceStringDigest):
|
||||
return accessForbidden()
|
||||
localization = self.getLocalization(localizationKey,
|
||||
sourceStringDigest)
|
||||
if keywords.has_key('localization'):
|
||||
if isinstance(keywords['localization'], localization.__class__):
|
||||
localization = keywords['localization']
|
||||
|
||||
if not again:
|
||||
localization.makeFieldsFromInstance(keywords)
|
||||
localization.repairFields(keywords)
|
||||
return self.editObject(localization, localizationKey, sourceStringDigest)
|
||||
edit.isPublicForWeb = 1
|
||||
|
||||
def editObject(self, localization, localizationKey, sourceStringDigest):
|
||||
headerTitle = _('Editing Translation')
|
||||
headerTitle += ' (%s -> %s)' % (
|
||||
_(translation.languageLabels[localization.sourceLanguage]),
|
||||
|
@ -548,21 +366,19 @@ class TranslationsWeb(ObjectsWebMixin, TranslationsProxy):
|
|||
context.push(_level = 'edit', layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
if error:
|
||||
layout += localization.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += localization.getErrorLayout()
|
||||
form = X.form(action = X.actionUrl('submit'),
|
||||
enctype= 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
if keywords.has_key('cloned') and keywords['cloned']:
|
||||
form += X.input(name = 'cloned', type = 'hidden', value = '1')
|
||||
|
||||
if keywords.has_key('nextUri') and keywords['nextUri']:
|
||||
if context.getVar('nextUri'):
|
||||
form += X.input(name = 'nextUri', type = 'hidden',
|
||||
value = keywords['nextUri'])
|
||||
value = context.getVar('nextUri'))
|
||||
|
||||
slot = slots.Root(localization)
|
||||
widget = slot.getWidget()
|
||||
form += widget.getModelPageBodyLayout(slot, keywords)
|
||||
form += widget.getModelPageBodyLayout(slot, None)
|
||||
form += X.input(name = 'localizationKey', type = 'hidden',
|
||||
value = localizationKey)
|
||||
|
||||
|
@ -577,12 +393,55 @@ class TranslationsWeb(ObjectsWebMixin, TranslationsProxy):
|
|||
return writePageLayout(layout, headerTitle)
|
||||
finally:
|
||||
context.pull(_level = 'edit')
|
||||
edit.isPublicForWeb = 1
|
||||
|
||||
def getAdmin(self, serverId = None):
|
||||
admin = TranslationsProxy.getAdmin(self, serverId = serverId)
|
||||
admin.translationLanguages = []
|
||||
if admin.translatorsSets:
|
||||
for languages, translators in admin.translatorsSets.items():
|
||||
admin.translationLanguages.append(languages)
|
||||
fromLanguage = languages[:2]
|
||||
toLanguage = languages[2:4]
|
||||
slotKey = 'translatorsSet_%s_%s' % (fromLanguage, toLanguage)
|
||||
setattr(admin, slotKey, translators)
|
||||
kind = commonTools.newThing('kind', 'UsersSet')
|
||||
kind.widget = TranslatorsSetWidget()
|
||||
kind.buildKinds()
|
||||
setattr(admin, slotKey + '_kind', kind)
|
||||
return admin
|
||||
|
||||
def modifyAdmin(self, admin, serverId = None):
|
||||
admin.translatorsSets = {}
|
||||
for languages in admin.translationLanguages or []:
|
||||
fromLanguage = languages[:2]
|
||||
toLanguage = languages[2:4]
|
||||
slotKey = 'translatorsSet_%s_%s' % (fromLanguage, toLanguage)
|
||||
admin.translatorsSets[languages] = admin.getSlot(slotKey).getValue()
|
||||
if not admin.translatorsSets[languages]:
|
||||
del admin.translatorsSets[languages]
|
||||
return TranslationsProxy.modifyAdmin(self, admin, serverId = serverId)
|
||||
|
||||
def newAdmin(self, keywords):
|
||||
ks = [x[15:20] for x in keywords.keys() if
|
||||
x.startswith('translatorsSet_') and len(x) == 22]
|
||||
admin = AdminTranslations()
|
||||
admin.translationLanguages = []
|
||||
for k in ks:
|
||||
fromLanguage = k[:2]
|
||||
toLanguage = k[3:5]
|
||||
admin.translationLanguages.append('%s%s' % (fromLanguage, toLanguage))
|
||||
slotKey = 'translatorsSet_%s_%s' % (fromLanguage, toLanguage)
|
||||
setattr(admin, slotKey, None)
|
||||
kind = commonTools.newThing('kind', 'UsersSet')
|
||||
kind.widget = TranslatorsSetWidget()
|
||||
kind.buildKinds()
|
||||
setattr(admin, slotKey + '_kind', kind)
|
||||
return admin
|
||||
|
||||
def getObjectsSectionLayout(self, key, digestsAndLabels, intertitle):
|
||||
layout = None
|
||||
if len(digestsAndLabels) > 0:
|
||||
layout = X.array( X.h3()(intertitle) )
|
||||
layout = X.array( X.h2()(intertitle) )
|
||||
ul = X.ul()
|
||||
layout += ul
|
||||
for digest, label, wordsCount in digestsAndLabels:
|
||||
|
@ -599,8 +458,6 @@ class TranslationsWeb(ObjectsWebMixin, TranslationsProxy):
|
|||
def submit(self, localizationKey, sourceStringDigest, **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['localizationKey'] = localizationKey
|
||||
keywords['sourceStringDigest'] = sourceStringDigest
|
||||
if isButtonSelected('deleteButton', keywords):
|
||||
return confirmDelete(
|
||||
X.actionUrl('delete').add(
|
||||
|
@ -608,32 +465,27 @@ class TranslationsWeb(ObjectsWebMixin, TranslationsProxy):
|
|||
'sourceStringDigest', sourceStringDigest),
|
||||
objectName = self.objectName)
|
||||
if isButtonSelected('applyButton', keywords):
|
||||
keywords['again'] = '1'
|
||||
keywords['hideErrors'] = '1'
|
||||
error = 0
|
||||
context.setVar('again', 1)
|
||||
context.setVar('hideErrors', 1)
|
||||
localization = Localization()
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
else:
|
||||
localization.submitFields(keywords)
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
return self.edit(localization = localization, **keywords)
|
||||
localization.submitFields(keywords)
|
||||
localization.sourceStringDigest = sourceStringDigest
|
||||
if context.getVar('again'):
|
||||
return self.editObject(localization, localizationKey,
|
||||
sourceStringDigest)
|
||||
try:
|
||||
self.modifyLocalization(localization)
|
||||
except faults.WrongVersion:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
keywords['versionError'] = '1'
|
||||
uri = X.actionUrl('edit')
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
context.setVar('error', 1)
|
||||
localization.setError('version', 1)
|
||||
return self.editObject(localization, localizationKey,
|
||||
sourceStringDigest)
|
||||
except:
|
||||
if context.getVar('debug'):
|
||||
raise
|
||||
return accessForbidden()
|
||||
if keywords.has_key('nextUri') and keywords['nextUri']:
|
||||
return redirect(keywords['nextUri'])
|
||||
if context.getVar('nextUri'):
|
||||
return redirect(context.getVar('nextUri'))
|
||||
return redirect(X.actionUrl('viewAll/%s' % localizationKey))
|
||||
submit.isPublicForWeb = 1
|
||||
|
||||
|
|
|
@ -136,7 +136,8 @@ class UploadFile(ObjectWebMixin, UploadFile):
|
|||
slotNames = ObjectWebMixin.getViewLayoutSlotNames(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
slotNames = slotNames[:]
|
||||
if not isTypeOfMimeType(fields['dataType'], 'image'):
|
||||
dataType = self.getSlot('dataType').getValue()
|
||||
if not isTypeOfMimeType(dataType, 'image'):
|
||||
if 'height' in slotNames:
|
||||
slotNames.remove('height')
|
||||
if 'width' in slotNames:
|
||||
|
@ -162,16 +163,13 @@ class UploadFile(ObjectWebMixin, UploadFile):
|
|||
if self.dataFileName:
|
||||
del self.data_kind
|
||||
return layout
|
||||
|
||||
def makeFieldsFromInstance(self, fields, parentSlot = None):
|
||||
for slotName in ('height', 'width'):
|
||||
self.getSlot(slotName, parentSlot = parentSlot).getKind(
|
||||
).hasToMakeFieldFromValue = self.isType('image')
|
||||
ObjectWebMixin.makeFieldsFromInstance(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
for slotName in ('height', 'width'):
|
||||
del self.getSlot(slotName, parentSlot = parentSlot).getKind(
|
||||
).hasToMakeFieldFromValue
|
||||
|
||||
def submitFields(self, fields, parentSlot = None):
|
||||
ObjectWebMixin.submitFields(self, fields, parentSlot = parentSlot)
|
||||
upload = context.getVar('UploadFilesXXX')
|
||||
if upload:
|
||||
self.dataFileName = upload.dataFileName
|
||||
self.dataType = upload.dataType
|
||||
register(UploadFile)
|
||||
|
||||
|
||||
|
@ -180,74 +178,9 @@ class UploadFilesWeb(ObjectsWebMixin, UploadFilesProxy):
|
|||
return ObjectsWebMixin.viewAll(self)
|
||||
all.isPublicForWeb = 1
|
||||
|
||||
|
||||
def editObject(self, object, again = 0, error = 0, **keywords):
|
||||
if object.id and not again:
|
||||
object.makeFieldsFromInstance(keywords)
|
||||
if not object.id and not again:
|
||||
object.initFields(keywords)
|
||||
object.repairFields(keywords)
|
||||
if again:
|
||||
if keywords.has_key('data') and keywords['data']:
|
||||
data = keywords['data']
|
||||
if keywords.has_key('dataType') and \
|
||||
isTypeOfMimeType(keywords['dataType'], 'image'):
|
||||
uploadFileFile = cStringIO.StringIO(data)
|
||||
uploadFileObject = PILImage.open(uploadFileFile)
|
||||
width, height = uploadFileObject.size
|
||||
keywords['width'] = str(width)
|
||||
keywords['height'] = str(height)
|
||||
keywords['size'] = str(len(data))
|
||||
if keywords.has_key('data') and keywords['data']:
|
||||
uri = X.idUrl(id, 'imageEdit')
|
||||
uri.add('again', again)
|
||||
uri.add('error', error)
|
||||
uri.addKeywords(keywords)
|
||||
else:
|
||||
uri = None
|
||||
keywords['dataUri'] = uri
|
||||
|
||||
if not object.id:
|
||||
headerTitle = _('New %s') % _(self.objectNameCapitalized)
|
||||
else:
|
||||
headerTitle = _('Editing %s - %s') % (
|
||||
_(self.objectNameCapitalized), object.getLabel())
|
||||
|
||||
context.push(_level = 'edit',
|
||||
isCreateEditMode = not object.id,
|
||||
layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
if error:
|
||||
layout += object.getErrorLayout(keywords)
|
||||
form = X.form(action = X.actionUrl('submit'),
|
||||
enctype= 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
if keywords.has_key('cloned') and keywords['cloned']:
|
||||
form += X.input(name = 'cloned', type = 'hidden', value = '1')
|
||||
|
||||
slot = slots.Root(object)
|
||||
widget = slot.getWidget()
|
||||
form += widget.getModelPageBodyLayout(slot, keywords)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')
|
||||
form += buttonsBar
|
||||
actionButtonsBar = X.span(_class = 'action-buttons-bar')
|
||||
buttonsBar += actionButtonsBar
|
||||
if not object.id:
|
||||
actionButtonsBar += X.buttonInForm('create', 'createButton')
|
||||
else:
|
||||
# The button Delete is also added here, so that the user can
|
||||
# delete the object he is editing without having to make it
|
||||
# valid, clic modify and then delete it.
|
||||
if self.canDeleteObject(object.id):
|
||||
actionButtonsBar += X.buttonStandalone(
|
||||
'delete', X.idUrl(object.id, 'confirmDelete'))
|
||||
actionButtonsBar += X.buttonInForm('modify', 'modifyButton')
|
||||
|
||||
return writePageLayout(layout, headerTitle)
|
||||
finally:
|
||||
context.pull(_level = 'edit')
|
||||
#uploadFileFile = cStringIO.StringIO(data)
|
||||
#uploadFileObject = PILImage.open(uploadFileFile)
|
||||
#width, height = uploadFileObject.size
|
||||
|
||||
def image(self, id, fileName = None):
|
||||
if not self.hasObject(id):
|
||||
|
@ -267,7 +200,7 @@ class UploadFilesWeb(ObjectsWebMixin, UploadFilesProxy):
|
|||
if object.dataFileName:
|
||||
req.headers_out['Content-Disposition'] = \
|
||||
'inline; filename="%s"' % object.dataFileName
|
||||
req.headers_out['Content-Length'] = str(object.size)
|
||||
req.headers_out['Content-Length'] = str(object.size or 0)
|
||||
if object.dataType:
|
||||
req.content_type = object.dataType
|
||||
setHttpCookie()
|
||||
|
@ -276,7 +209,7 @@ class UploadFilesWeb(ObjectsWebMixin, UploadFilesProxy):
|
|||
return OK
|
||||
if req.caching:
|
||||
req.openCachePage()
|
||||
req.write(object.data)
|
||||
req.write(object.data or '')
|
||||
if req.caching:
|
||||
req.closeCachePage()
|
||||
return OK
|
||||
|
@ -302,35 +235,17 @@ class UploadFilesWeb(ObjectsWebMixin, UploadFilesProxy):
|
|||
return HTTP_NO_CONTENT
|
||||
file.isPublicForWeb = ('PUT',)
|
||||
|
||||
def imageEdit(self, id = '', again = '', error = '', **keywords):
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['id'] = id
|
||||
if id and not self.hasObject(id):
|
||||
return pageNotFound()
|
||||
if id:
|
||||
if not self.canModifyObject(id):
|
||||
return accessForbidden()
|
||||
object = self.getObject(id)
|
||||
rememberObject(id)
|
||||
else:
|
||||
if not self.canAddObject():
|
||||
return accessForbidden()
|
||||
object = self.newObject(keywords)
|
||||
|
||||
if id and not again:
|
||||
object.makeFieldsFromInstance(keywords)
|
||||
if not id and not again:
|
||||
object.initFields(keywords)
|
||||
object.repairFields(keywords)
|
||||
|
||||
def imageEdit(self, dataToken, path = ''):
|
||||
sessionsProxy = getProxyForServerRole('sessions')
|
||||
data = sessionsProxy.getTemporaryData(dataToken)
|
||||
|
||||
req = context.getVar('req')
|
||||
req.content_type = keywords['dataType']
|
||||
req.content_type = data['type']
|
||||
setHttpCookie()
|
||||
req.send_http_header()
|
||||
if req.method == 'HEAD':
|
||||
return OK
|
||||
req.write(keywords['data'])
|
||||
req.write(data['data'])
|
||||
return OK
|
||||
imageEdit.isPublicForWeb = 1
|
||||
|
||||
|
@ -375,30 +290,23 @@ class UploadFilesWeb(ObjectsWebMixin, UploadFilesProxy):
|
|||
object.data = 'fake data'
|
||||
rememberObject(id)
|
||||
|
||||
keywords = {}
|
||||
object.makeFieldsFromInstance(keywords)
|
||||
object.repairFields(keywords)
|
||||
|
||||
if isTypeOfMimeType(object.dataType, 'image'):
|
||||
fullUri = X.idUrl(id, 'image')
|
||||
else:
|
||||
fullUri = X.idUrl(id, 'download')
|
||||
keywords['dataFullUri'] = fullUri
|
||||
uri = X.idUrl(id, 'thumbnail')
|
||||
uri.add('width', 256)
|
||||
uri.add('height', 256)
|
||||
keywords['dataUri'] = uri
|
||||
|
||||
label = object.getLabelTranslated(
|
||||
context.getVar('readLanguages'))
|
||||
label = object.getLabelTranslated(context.getVar('readLanguages'))
|
||||
|
||||
layout = X.array()
|
||||
slot = slots.Root(object)
|
||||
widget = slot.getWidget()
|
||||
layout += widget.getModelPageBodyLayout(slot, keywords)
|
||||
layout += self.getViewAboveButtonsBarLayout(object, keywords)
|
||||
layout += self.getViewButtonsBarLayout(object, keywords)
|
||||
layout += self.getViewBelowButtonsBarLayout(object, keywords)
|
||||
layout += widget.getModelPageBodyLayout(slot, None)
|
||||
layout += self.getViewAboveButtonsBarLayout(object, None)
|
||||
layout += self.getViewButtonsBarLayout(object, None)
|
||||
layout += self.getViewBelowButtonsBarLayout(object, None)
|
||||
return writePageLayout(
|
||||
layout, '%s - %s' % (_(self.objectNameCapitalized), label))
|
||||
view.isPublicForWeb = 1
|
||||
|
|
|
@ -67,6 +67,7 @@ class VirtualHost(ObjectWebMixin, VirtualHost):
|
|||
useBalloonHelp = 1
|
||||
|
||||
def initTemplateList(self):
|
||||
# TODO: rewrite this in kind values getter
|
||||
templatesDirectoryPath = context.getVar(
|
||||
'templatesDirectoryPath')
|
||||
dirs = os.listdir(templatesDirectoryPath)
|
||||
|
|
|
@ -73,17 +73,53 @@ class MarksWidget(widgets.BaseWidget):
|
|||
idsGetter = getattr(container, idsGetterName)
|
||||
objectIds = idsGetter(fields)
|
||||
layout = X.array()
|
||||
marks = slot.getValue()
|
||||
if objectIds:
|
||||
for objectId in objectIds:
|
||||
fieldName = slot.getFieldOptionName(objectId)
|
||||
mark = slot.getFieldOption(fields, objectId, default = '')
|
||||
mark = ''
|
||||
if marks and marks.has_key(objectId):
|
||||
mark = str(marks[objectId])
|
||||
layout += X.input(name = fieldName, type = 'hidden',
|
||||
value = mark),
|
||||
return layout
|
||||
|
||||
def submit(self, slot, fields):
|
||||
container = slot.getContainer()
|
||||
idsGetterName = slot.getKind().idsGetterName
|
||||
idsGetter = getattr(container, idsGetterName)
|
||||
objectIds = idsGetter(fields) or []
|
||||
isBlank = isButtonSelected(
|
||||
slot.getFieldOptionName('blankButton'), fields)
|
||||
result = {}
|
||||
if isBlank:
|
||||
# why not returning an empty dictionary ?
|
||||
for objectId in objectIds:
|
||||
result[objectId] = 0
|
||||
return result
|
||||
|
||||
for objectId in objectIds:
|
||||
fieldName = slot.getFieldOptionName(objectId)
|
||||
mark = self.submitOneMark(slot, objectId, fields)
|
||||
result[objectId] = mark
|
||||
return result
|
||||
|
||||
def submitOneMark(self, slot, objectId, fields):
|
||||
mark = slot.getFieldOption(fields, objectId)
|
||||
try:
|
||||
return int(mark)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
class VoteApprovalMarksWidget(MarksWidget):
|
||||
def submitOneMark(self, slot, objectId, fields):
|
||||
mark = slot.getFieldOption(fields, objectId)
|
||||
if not mark:
|
||||
mark = '0'
|
||||
return int(mark)
|
||||
|
||||
def getHtmlFieldValue(self, slot, fields, **keywords):
|
||||
marks = slot.getValue()
|
||||
container = slot.getContainer()
|
||||
idsGetterName = slot.getKind().idsGetterName
|
||||
idsGetter = getattr(container, idsGetterName)
|
||||
|
@ -104,11 +140,15 @@ class VoteApprovalMarksWidget(MarksWidget):
|
|||
if objectIds:
|
||||
for objectId in objectIds:
|
||||
fieldName = slot.getFieldOptionName(objectId)
|
||||
mark = slot.getFieldOption(fields, objectId, default = '')
|
||||
mark = 0
|
||||
if marks and marks.has_key(objectId) and marks[objectId]:
|
||||
mark = marks[objectId]
|
||||
|
||||
if mark:
|
||||
markSymbol = 'x'
|
||||
else:
|
||||
markSymbol = X.nbsp
|
||||
|
||||
tr = X.tr()
|
||||
table += tr
|
||||
if not self.isInForm() or self.isReadOnly(slot):
|
||||
|
@ -116,10 +156,10 @@ class VoteApprovalMarksWidget(MarksWidget):
|
|||
else:
|
||||
td = X.td()
|
||||
tr += td
|
||||
errorCode = slot.getFieldOption(
|
||||
fields, objectId + '_error')
|
||||
if errorCode and not fields.has_key('hideErrors'):
|
||||
td += X.asIs(makeErrorMessage(errorCode))
|
||||
error = slot.getObject().getError(slot.getPath())
|
||||
if error and not context.getVar('hideErrors'):
|
||||
td += X.span(_class = 'error-message')(
|
||||
_(error.uiFaultString))
|
||||
inputAttributes = {}
|
||||
if mark:
|
||||
inputAttributes['checked'] = 'checked'
|
||||
|
@ -132,6 +172,7 @@ widgets.register(VoteApprovalMarksWidget)
|
|||
|
||||
class VoteDistributionMarksWidget(MarksWidget):
|
||||
def getHtmlFieldValue(self, slot, fields, **keywords):
|
||||
marks = slot.getValue()
|
||||
container = slot.getContainer()
|
||||
idsGetterName = slot.getKind().idsGetterName
|
||||
idsGetter = getattr(container, idsGetterName)
|
||||
|
@ -152,7 +193,9 @@ class VoteDistributionMarksWidget(MarksWidget):
|
|||
if objectIds:
|
||||
for objectId in objectIds:
|
||||
fieldName = slot.getFieldOptionName(objectId)
|
||||
mark = slot.getFieldOption(fields, objectId, default = '')
|
||||
mark = ''
|
||||
if marks and marks.has_key(objectId) and marks[objectId]:
|
||||
mark = '%.2f' % (marks[objectId]*100)
|
||||
tr = X.tr()
|
||||
table += tr
|
||||
tr += X.td(X.objectHypertextLabel(objectId), X.asIs(_(':')))
|
||||
|
@ -161,20 +204,35 @@ class VoteDistributionMarksWidget(MarksWidget):
|
|||
else:
|
||||
td = X.td()
|
||||
tr += td
|
||||
errorCode = slot.getFieldOption(
|
||||
fields, objectId + '_error')
|
||||
if errorCode and not fields.has_key('hideErrors'):
|
||||
td += X.asIs(makeErrorMessage(errorCode))
|
||||
error = slot.getObject().getError(slot.getPath())
|
||||
if error and not context.getVar('hideErrors'):
|
||||
td += X.span(_class = 'error-message')(
|
||||
_(error.uiFaultString))
|
||||
td += X.input(maxlength = 6, name = fieldName, size = 6,
|
||||
type = 'text', value = mark)
|
||||
td += X.nbsp
|
||||
td += '%'
|
||||
return X.div(_class = 'cell')(layout)
|
||||
|
||||
def submitOneMark(self, slot, objectId, fields):
|
||||
mark = slot.getFieldOption(fields, objectId) or ''
|
||||
if mark and mark.strip():
|
||||
try:
|
||||
mark = float(mark) / 100.
|
||||
except ValueError:
|
||||
raise faults.BadValue()
|
||||
mark = 0
|
||||
else:
|
||||
mark = 0
|
||||
|
||||
return mark
|
||||
|
||||
widgets.register(VoteDistributionMarksWidget)
|
||||
|
||||
|
||||
class VoteRankingMarksWidget(MarksWidget):
|
||||
def getHtmlFieldValue(self, slot, fields, **keywords):
|
||||
marks = slot.getValue()
|
||||
container = slot.getContainer()
|
||||
idsGetterName = slot.getKind().idsGetterName
|
||||
idsGetter = getattr(container, idsGetterName)
|
||||
|
@ -195,7 +253,12 @@ class VoteRankingMarksWidget(MarksWidget):
|
|||
if objectIds:
|
||||
for objectId in objectIds:
|
||||
fieldName = slot.getFieldOptionName(objectId)
|
||||
mark = slot.getFieldOption(fields, objectId, default = '')
|
||||
|
||||
mark = ''
|
||||
if marks and marks.has_key(objectId) and marks[objectId]:
|
||||
mark = marks[objectId]
|
||||
mark = str(mark)
|
||||
|
||||
tr = X.tr()
|
||||
table += tr
|
||||
if not self.isInForm() or self.isReadOnly(slot):
|
||||
|
@ -203,10 +266,10 @@ class VoteRankingMarksWidget(MarksWidget):
|
|||
else:
|
||||
td = X.td()
|
||||
tr += td
|
||||
errorCode = slot.getFieldOption(
|
||||
fields, objectId + '_error')
|
||||
if errorCode and not fields.has_key('hideErrors'):
|
||||
td += X.asIs(makeErrorMessage(errorCode))
|
||||
error = slot.getObject().getError(slot.getPath())
|
||||
if error and not context.getVar('hideErrors'):
|
||||
td += X.span(_class = 'error-message')(
|
||||
_(error.uiFaultString))
|
||||
maxLength = len(str(len(objectIds)))
|
||||
td += X.input(
|
||||
maxlength = maxLength, name = fieldName,
|
||||
|
@ -219,6 +282,7 @@ widgets.register(VoteRankingMarksWidget)
|
|||
|
||||
class VoteRatingMarksWidget(MarksWidget):
|
||||
def getHtmlFieldValue(self, slot, fields, **keywords):
|
||||
marks = slot.getValue()
|
||||
container = slot.getContainer()
|
||||
idsGetterName = slot.getKind().idsGetterName
|
||||
idsGetter = getattr(container, idsGetterName)
|
||||
|
@ -239,7 +303,9 @@ class VoteRatingMarksWidget(MarksWidget):
|
|||
if objectIds:
|
||||
for objectId in objectIds:
|
||||
fieldName = slot.getFieldOptionName(objectId)
|
||||
mark = slot.getFieldOption(fields, objectId, default = '')
|
||||
mark = ''
|
||||
if marks and marks.has_key(objectId) and marks[objectId]:
|
||||
mark = marks[objectId]
|
||||
tr = X.tr()
|
||||
table += tr
|
||||
tr += X.td()(X.objectHypertextLabel(objectId), X.asIs(_(':')))
|
||||
|
@ -248,10 +314,10 @@ class VoteRatingMarksWidget(MarksWidget):
|
|||
else:
|
||||
td = X.td()
|
||||
tr += td
|
||||
errorCode = slot.getFieldOption(
|
||||
fields, objectId + '_error')
|
||||
if errorCode and not fields.has_key('hideErrors'):
|
||||
td += X.asIs(makeErrorMessage(errorCode))
|
||||
error = slot.getObject().getError(slot.getPath())
|
||||
if error and not context.getVar('hideErrors'):
|
||||
td += X.span(_class = 'error-message')(
|
||||
_(error.uiFaultString))
|
||||
td += X.input(maxlength = 6, name = fieldName, size = 6,
|
||||
type = 'text', value = mark)
|
||||
return X.div(_class = 'cell')(layout)
|
||||
|
@ -272,8 +338,8 @@ class VoteMixin(ObjectWebMixin):
|
|||
comment_kind_widget_rows = 4
|
||||
comment_kind_widgetName = 'TextArea'
|
||||
|
||||
electionId_kind_hasToInitField = 0
|
||||
electionId_kind_hasToMakeFieldFromValue = 0
|
||||
#electionId_kind_hasToInitField = 0
|
||||
#electionId_kind_hasToMakeFieldFromValue = 0
|
||||
electionId_kind_hasToRepairField = 0
|
||||
electionId_kind_hasToSubmitField = 0
|
||||
electionId_kind_stateInEditMode = 'hidden'
|
||||
|
@ -288,12 +354,17 @@ class VoteMixin(ObjectWebMixin):
|
|||
electionToken_kind_widget_fieldLabel = N_('Election Token')
|
||||
electionToken_kind_widgetName = 'Token'
|
||||
|
||||
subject = None
|
||||
subject_kind_isTranslatable = 0
|
||||
subject_kind_stateInEditMode = 'read-only'
|
||||
subject_kindName = 'String'
|
||||
|
||||
token_kind_stateInEditMode = 'read-only'
|
||||
token_kind_widget_fieldLabel = N_('Vote Token')
|
||||
token_kind_widgetName = 'Token'
|
||||
|
||||
voterId_kind_hasToInitField = 0
|
||||
voterId_kind_hasToMakeFieldFromValue = 0
|
||||
#voterId_kind_hasToInitField = 0
|
||||
#voterId_kind_hasToMakeFieldFromValue = 0
|
||||
voterId_kind_hasToRepairField = 0
|
||||
voterId_kind_hasToSubmitField = 0
|
||||
voterId_kind_stateInEditMode = 'read-only'
|
||||
|
@ -307,15 +378,19 @@ class VoteMixin(ObjectWebMixin):
|
|||
voterToken_kind_widgetName = 'Token'
|
||||
|
||||
def getElectionCandidateIds(self, fields):
|
||||
return fields['election'].candidateIds
|
||||
return getObject(self.electionId).candidateIds
|
||||
|
||||
def getEditLayout(self, fields, parentSlot = None):
|
||||
election = fields['election']
|
||||
election = getObject(self.electionId)
|
||||
slot = election.getSlot('subject')
|
||||
subject, destinationLanguage, state = \
|
||||
getProxyForServerRole('translations').getTranslationInfos(
|
||||
election.subject, election.getId(), slot.getPath(),
|
||||
election.getLanguage(), context.getVar('readLanguages'))
|
||||
translationsProxy = getProxyForServerRole('translations')
|
||||
if translationsProxy:
|
||||
subject, destinationLanguage, state = \
|
||||
translationsProxy.getTranslationInfos(
|
||||
election.subject, election.getId(), slot.getPath(),
|
||||
election.getLanguage(), context.getVar('readLanguages'))
|
||||
else:
|
||||
subject = election.subject
|
||||
self.subject = subject
|
||||
self.subject_kind = copy.copy(election.subject_kind)
|
||||
self.subject_kind.stateInEditMode = 'read-only'
|
||||
|
@ -339,22 +414,26 @@ class VoteMixin(ObjectWebMixin):
|
|||
self, fields, parentSlot = parentSlot)
|
||||
hiddenSlotNames = hiddenSlotNames[:]
|
||||
slot = self.getSlot('voterId')
|
||||
if slot.getField(fields):
|
||||
if slot.getValue():
|
||||
hiddenSlotNames.append('voterToken')
|
||||
else:
|
||||
hiddenSlotNames.append('voterId')
|
||||
election = fields['election']
|
||||
election = getObject(self.electionId)
|
||||
if election.ballotKind != 'voterChoice':
|
||||
hiddenSlotNames.append('ballotKind')
|
||||
return hiddenSlotNames
|
||||
|
||||
def getViewLayout(self, fields, parentSlot = None):
|
||||
election = fields['election']
|
||||
election = getObject(self.electionId)
|
||||
slot = election.getSlot('subject')
|
||||
subject, destinationLanguage, state = \
|
||||
getProxyForServerRole('translations').getTranslationInfos(
|
||||
election.subject, election.getId(), slot.getPath(),
|
||||
election.getLanguage(), context.getVar('readLanguages'))
|
||||
translationsProxy = getProxyForServerRole('translations')
|
||||
if translationsProxy:
|
||||
subject, destinationLanguage, state = \
|
||||
translationsProxy.getTranslationInfos(
|
||||
election.subject, election.getId(), slot.getPath(),
|
||||
election.getLanguage(), context.getVar('readLanguages'))
|
||||
else:
|
||||
subject = election.subject
|
||||
self.subject = subject
|
||||
self.subject_kind = copy.copy(election.subject_kind)
|
||||
self.subject_kind.isTranslatable = 0
|
||||
|
@ -377,40 +456,15 @@ class VoteMixin(ObjectWebMixin):
|
|||
self, fields, parentSlot = parentSlot)
|
||||
hiddenSlotNames = hiddenSlotNames[:]
|
||||
slot = self.getSlot('voterId')
|
||||
if slot.getField(fields):
|
||||
if slot.getValue():
|
||||
hiddenSlotNames.append('voterToken')
|
||||
else:
|
||||
hiddenSlotNames.append('voterId')
|
||||
election = fields['election']
|
||||
election = getObject(self.electionId)
|
||||
if election.ballotKind != 'voterChoice':
|
||||
hiddenSlotNames.append('ballotKind')
|
||||
return hiddenSlotNames
|
||||
|
||||
def makeFieldsFromInstance(self, fields, parentSlot = None):
|
||||
if self.isBlank(self.getElectionCandidateIds(fields)):
|
||||
# Duplicate the marks kind.
|
||||
slot = self.getSlot('marks', parentSlot = parentSlot)
|
||||
self.marks_kind = copy.copy(self.marks_kind)
|
||||
self.marks_kind.hasToMakeFieldFromValue = 0
|
||||
ObjectWebMixin.makeFieldsFromInstance(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
slot.getKind().makeFieldFromValue(slot, fields, {})
|
||||
# Delete the duplicated marks kind.
|
||||
del self.marks_kind
|
||||
else:
|
||||
ObjectWebMixin.makeFieldsFromInstance(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
|
||||
def submitFields(self, fields, parentSlot = None):
|
||||
election = fields['election']
|
||||
# Duplicate the ballotKind kind.
|
||||
slot = self.getSlot('ballotKind', parentSlot = parentSlot)
|
||||
self.ballotKind_kind = copy.copy(self.ballotKind_kind)
|
||||
self.ballotKind_kind.hasToSubmitField = \
|
||||
election.ballotKind == 'voterChoice'
|
||||
ObjectWebMixin.submitFields(self, fields, parentSlot = parentSlot)
|
||||
# Delete the duplicated ballotKind kind.
|
||||
del self.ballotKind_kind
|
||||
|
||||
class AbstractVote(VoteMixin, AbstractVote):
|
||||
pass
|
||||
|
@ -637,15 +691,10 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
|
|||
def canAddObject(self, serverId = None):
|
||||
return 0
|
||||
|
||||
def edit(self, id = '', electionId = '', again = '', error = '',
|
||||
**keywords):
|
||||
def edit(self, id = '', electionId = ''):
|
||||
ballotsWeb = getWebForServerRole('ballots')
|
||||
electionsWeb = getWebForServerRole('elections')
|
||||
peopleWeb = getWebForServerRole('people')
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['id'] = id
|
||||
keywords['electionId'] = electionId
|
||||
userId = context.getVar('userId', default = '')
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
if not userToken:
|
||||
|
@ -682,28 +731,25 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
|
|||
vote = ballotsWeb.getVoteFromToken(voteToken)
|
||||
except faults.UnknownVoteToken:
|
||||
vote = election.newVote()
|
||||
vote.fillWithDefaultValues()
|
||||
else:
|
||||
id = vote.id
|
||||
rememberObject(id)
|
||||
else:
|
||||
vote = election.newVote()
|
||||
|
||||
keywords['election'] = election
|
||||
if id and not again:
|
||||
vote.makeFieldsFromInstance(keywords)
|
||||
if not id and not again:
|
||||
vote.initFields(keywords)
|
||||
vote.repairFields(keywords)
|
||||
return self.editObject(vote, electionId)
|
||||
edit.isPublicForWeb = 1
|
||||
|
||||
slot = vote.getSlot('electionId')
|
||||
slot.getKind().makeFieldFromValue(slot, keywords, electionId)
|
||||
slot = election.getSlot('subject')
|
||||
slot.getKind().makeFieldFromValue(
|
||||
slot, keywords, election.subject)
|
||||
slot = vote.getSlot('voterId')
|
||||
slot.getKind().makeFieldFromValue(slot, keywords, userId)
|
||||
def editObject(self, vote, electionId = ''):
|
||||
electionsWeb = getWebForServerRole('elections')
|
||||
election = electionsWeb.getObject(electionId)
|
||||
userId = context.getVar('userId', default = '')
|
||||
vote.getSlot('electionId').setValue(electionId)
|
||||
vote.getSlot('voterId').setValue(userId)
|
||||
vote.getSlot('subject').setValue(election.subject)
|
||||
|
||||
if not id:
|
||||
if not vote.id:
|
||||
headerTitle = _('New %s') % _(self.objectNameCapitalized)
|
||||
else:
|
||||
headerTitle = _('Editing %s - %s') % (
|
||||
|
@ -712,16 +758,15 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
|
|||
context.push(_level = 'edit', layoutMode = 'edit')
|
||||
try:
|
||||
layout = X.array()
|
||||
if error:
|
||||
layout += vote.getErrorLayout(keywords)
|
||||
if context.getVar('error'):
|
||||
layout += vote.getErrorLayout()
|
||||
form = X.form(action = X.actionUrl('submit'),
|
||||
enctype= 'multipart/form-data', method = 'post')
|
||||
layout += form
|
||||
|
||||
slot = slots.Root(vote)
|
||||
widget = slot.getWidget()
|
||||
form += widget.getModelPageBodyLayout(slot, keywords)
|
||||
del keywords['election']
|
||||
form += widget.getModelPageBodyLayout(slot, None)
|
||||
|
||||
buttonsBar = X.div(_class = 'buttons-bar')
|
||||
form += buttonsBar
|
||||
|
@ -736,7 +781,6 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
|
|||
return writePageLayout(layout, headerTitle)
|
||||
finally:
|
||||
context.pull(_level = 'edit')
|
||||
edit.isPublicForWeb = 1
|
||||
|
||||
def submit(self, id = '', electionId = '', **keywords):
|
||||
ballotsWeb = getWebForServerRole('ballots')
|
||||
|
@ -744,10 +788,8 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
|
|||
if keywords is None:
|
||||
keywords = {}
|
||||
keywords['id'] = id
|
||||
keywords['electionId'] = electionId
|
||||
userId = context.getVar('userId', default = '')
|
||||
userToken = context.getVar('userToken', default = '')
|
||||
error = 0
|
||||
if not userToken:
|
||||
return accessForbidden()
|
||||
if not electionId \
|
||||
|
@ -756,8 +798,8 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
|
|||
if not electionsWeb.canVote(electionId):
|
||||
return accessForbidden()
|
||||
if isButtonSelected('applyButton', keywords):
|
||||
keywords['again'] = '1'
|
||||
keywords['hideErrors'] = '1'
|
||||
context.setVar('again', 1)
|
||||
context.setVar('hideErrors', 1)
|
||||
elif isButtonSelected('abstainButton', keywords):
|
||||
try:
|
||||
ballotsWeb.abstainForVote(electionId)
|
||||
|
@ -769,22 +811,18 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
|
|||
'electionId', electionId).add('voterId', userId))
|
||||
election = electionsWeb.getObject(electionId)
|
||||
vote = election.newVote()
|
||||
if error:
|
||||
keywords['again'] = '1'
|
||||
keywords['error'] = '1'
|
||||
else:
|
||||
keywords['election'] = election
|
||||
vote.submitFields(keywords)
|
||||
del keywords['election']
|
||||
if keywords.has_key('again') and keywords['again']:
|
||||
uri = X.idUrl(id, 'edit')
|
||||
uri.add('electionId', electionId)
|
||||
uri.addKeywords(keywords)
|
||||
return redirect(uri)
|
||||
#try:
|
||||
id = ballotsWeb.vote(electionId, vote)
|
||||
#except faults.Fault:
|
||||
# return accessForbidden()
|
||||
vote.getSlot('electionId').setValue(electionId)
|
||||
keywords['election'] = election
|
||||
vote.submitFields(keywords)
|
||||
del keywords['election']
|
||||
if context.getVar('again'):
|
||||
return self.editObject(vote, electionId)
|
||||
try:
|
||||
id = ballotsWeb.vote(electionId, vote)
|
||||
except faults.WrongVersion:
|
||||
context.setVar('error', 1)
|
||||
vote.setError('version', 1)
|
||||
return self.editObject(vote, electionId)
|
||||
return redirect(X.idUrl(id))
|
||||
submit.isPublicForWeb = 1
|
||||
|
||||
|
@ -840,18 +878,12 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
|
|||
else:
|
||||
vote = election.newVote()
|
||||
|
||||
vote.getSlot('electionId').setValue(electionId)
|
||||
vote.getSlot('voterId').setValue(userId)
|
||||
vote.getSlot('subject').setValue(election.subject)
|
||||
|
||||
keywords = {}
|
||||
keywords['election'] = election
|
||||
vote.makeFieldsFromInstance(keywords)
|
||||
vote.repairFields(keywords)
|
||||
|
||||
slot = vote.getSlot('electionId')
|
||||
slot.getKind().makeFieldFromValue(slot, keywords, electionId)
|
||||
slot = election.getSlot('subject')
|
||||
slot.getKind().makeFieldFromValue(
|
||||
slot, keywords, election.subject)
|
||||
slot = vote.getSlot('voterId')
|
||||
slot.getKind().makeFieldFromValue(slot, keywords, voterId)
|
||||
|
||||
label = election.getLabelTranslated(
|
||||
context.getVar('readLanguages'))
|
||||
|
@ -859,7 +891,7 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
|
|||
layout = X.array()
|
||||
slot = slots.Root(vote)
|
||||
widget = slot.getWidget()
|
||||
layout += widget.getModelPageBodyLayout(slot, keywords)
|
||||
layout += widget.getModelPageBodyLayout(slot, None)
|
||||
del keywords['election']
|
||||
layout += X.br()
|
||||
if voterId and voterId == userId and electionsWeb.canVote(electionId):
|
||||
|
|
|
@ -510,7 +510,7 @@ def template(filename, xtal=0, **keywords):
|
|||
|
||||
program, macros = t.getCode()
|
||||
|
||||
from TAL.TALInterpreter import TALInterpreter
|
||||
from GlasnostTALInterpreter import GlasnostTALInterpreter
|
||||
from GlasnostTALEngine import GlasnostTALEngine
|
||||
engine = GlasnostTALEngine(macros)
|
||||
#context.setVar('talEngine', engine)
|
||||
|
@ -518,7 +518,7 @@ def template(filename, xtal=0, **keywords):
|
|||
for k, v in keywords.items():
|
||||
engine.locals[k] = v
|
||||
stream = tools.StringIO()
|
||||
interp = TALInterpreter(program, macros, engine, stream=stream, wrap=80)
|
||||
interp = GlasnostTALInterpreter(program, macros, engine, stream=stream, wrap=80)
|
||||
interp()
|
||||
return stream.getvalue()
|
||||
|
||||
|
|
1436
shared/web/kinds.py
1436
shared/web/kinds.py
File diff suppressed because it is too large
Load Diff
|
@ -48,6 +48,7 @@ __version__ = '$Revision$'[11:-2]
|
|||
import copy
|
||||
|
||||
import glasnost.common.context as context
|
||||
import glasnost.common.faults as faults
|
||||
import glasnost.common.tools_new as commonTools
|
||||
import glasnost.common.xhtmlgenerator as X
|
||||
|
||||
|
@ -63,51 +64,6 @@ class Aspect(things.ThingMixin, proxyModes.Aspect):
|
|||
kind = None # Not a slot
|
||||
slot = None # Not a slot.
|
||||
|
||||
class widget_kindClass(proxyModes.Aspect.widget_kindClass):
|
||||
def repairField(self, slot, fields, forceEmbedding = 0, **keywords):
|
||||
if forceEmbedding or self.isModelEmbedded(slot):
|
||||
return self.getRealKindClass().repairField(
|
||||
self, slot, fields, forceEmbedding = forceEmbedding,
|
||||
**keywords)
|
||||
values = self.getValues(slot, fields)
|
||||
if values and not slot.getField(fields) in values:
|
||||
fieldValue = values[0]
|
||||
slot.setField(fields, fieldValue)
|
||||
|
||||
def submitField2(self, slot, fields, forceEmbedding = 0, **keywords):
|
||||
if forceEmbedding or self.isModelEmbedded(slot):
|
||||
return self.getRealKindClass().submitField2(
|
||||
self, slot, fields, forceEmbedding = forceEmbedding,
|
||||
**keywords)
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
error = 0
|
||||
errorFields = {}
|
||||
value = None
|
||||
values = self.getValues(slot, fields)
|
||||
if not fieldValue:
|
||||
if self.isRequired:
|
||||
error = 1
|
||||
slot.setFieldOption(errorFields, 'error', 'missingValue')
|
||||
else:
|
||||
value = None
|
||||
else:
|
||||
try:
|
||||
oldValue = slot.getValue()
|
||||
except:
|
||||
oldValue = None
|
||||
if not fieldValue in values and (
|
||||
oldValue is None
|
||||
or oldValue.getThingName() != fieldValue):
|
||||
error = 2
|
||||
slot.setFieldOption(errorFields, 'error', 'wrongValue')
|
||||
else:
|
||||
value = commonTools.newThing(
|
||||
self.valueThingCategory, fieldValue)
|
||||
if oldValue is not None \
|
||||
and oldValue.getThingName() == value.getThingName():
|
||||
value = oldValue
|
||||
return (error, errorFields, value)
|
||||
|
||||
def isModelHidden(self):
|
||||
return self.state == 'hidden' \
|
||||
or self.state == 'read-only/hidden-if-empty' \
|
||||
|
@ -131,11 +87,6 @@ class ModeMixin(things.ThingMixin):
|
|||
context.getVar('readLanguages'))
|
||||
return headerTitle
|
||||
|
||||
def makeModelFields(self, object, fields, again, parentSlot = None):
|
||||
if not again:
|
||||
object.makeFieldsFromInstance(fields, parentSlot = parentSlot)
|
||||
object.repairFields(fields, parentSlot = parentSlot)
|
||||
|
||||
|
||||
class ModeAbstract(ModeMixin, proxyModes.ModeAbstract):
|
||||
pass
|
||||
|
@ -150,8 +101,7 @@ class Custom(ModeMixin, proxyModes.Custom):
|
|||
kind = slot.getKind()
|
||||
kind.executeModel(slot, when, command = command)
|
||||
|
||||
def getModelLayoutInfos(self, object, fields, again, create,
|
||||
parentSlot = None):
|
||||
def getModelLayoutInfos(self, object, fields, create, parentSlot = None):
|
||||
inForm = 0
|
||||
if self.aspects:
|
||||
aspects = []
|
||||
|
@ -172,7 +122,6 @@ class Custom(ModeMixin, proxyModes.Custom):
|
|||
for aspect in aspects:
|
||||
aspect.kind.executeModel(aspect.slot, 'onDisplay')
|
||||
|
||||
self.makeModelFields(object, fields, again, parentSlot = parentSlot)
|
||||
headerTitle = self.getModelHeaderTitle(
|
||||
object, fields, parentSlot = parentSlot)
|
||||
|
||||
|
@ -246,15 +195,32 @@ class Custom(ModeMixin, proxyModes.Custom):
|
|||
return self.usersSet
|
||||
|
||||
def submitModelFields(self, object, fields, parentSlot = None):
|
||||
object.delErrors()
|
||||
|
||||
for slotName in object.getRequiredFieldSlotNames(
|
||||
fields, parentSlot = parentSlot):
|
||||
if slotName in ['thingCategory', 'thingName']:
|
||||
continue
|
||||
slot = object.getSlot(slotName, parentSlot = parentSlot)
|
||||
kind = slot.getKind()
|
||||
widget = slot.getWidget()
|
||||
if (kind.isRequiredInEditMode or kind.isExportable()) \
|
||||
and kind.hasToSubmitField:
|
||||
kind.submitField(slot, fields)
|
||||
try:
|
||||
value = widget.submit(slot, fields)
|
||||
if value is not None and \
|
||||
type(value) != kind.pythonStorageType:
|
||||
value = kind.convertValueFromOtherType(value)
|
||||
if kind.isEmptyModelValue(slot, value):
|
||||
value = None
|
||||
kind.checkModelValue(slot, value)
|
||||
except faults.BaseFault, f:
|
||||
self.setError(slot.getPath(), f)
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
|
||||
if not slot.hasValue() or value != slot.getValue():
|
||||
slot.setValue(value)
|
||||
|
||||
if self.aspects:
|
||||
for aspect in self.aspects:
|
||||
|
@ -262,7 +228,21 @@ class Custom(ModeMixin, proxyModes.Custom):
|
|||
continue
|
||||
slot = object.getSlot(aspect.name, parentSlot = parentSlot)
|
||||
kind = slot.getKind()
|
||||
kind.submitField(slot, fields)
|
||||
widget = slot.getWidget()
|
||||
|
||||
try:
|
||||
value = widget.submit(slot, fields)
|
||||
if value is not None and \
|
||||
type(value) != kind.pythonStorageType:
|
||||
value = kind.convertValueFromOtherType(value)
|
||||
if kind.isEmptyModelValue(slot, value):
|
||||
value = None
|
||||
kind.checkModelValue(slot, value)
|
||||
except faults.BaseFault, f:
|
||||
self.setError(slot.getPath(), f)
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
slot.setValue(value)
|
||||
register(Custom)
|
||||
|
||||
|
||||
|
@ -278,9 +258,7 @@ class Edit(ModeMixin, proxyModes.Edit):
|
|||
_(web.objectNameCapitalized), label)
|
||||
return headerTitle
|
||||
|
||||
def getModelLayoutInfos(self, object, fields, again, create,
|
||||
parentSlot = None):
|
||||
self.makeModelFields(object, fields, again, parentSlot = parentSlot)
|
||||
def getModelLayoutInfos(self, object, fields, create, parentSlot = None):
|
||||
headerTitle = self.getModelHeaderTitle(
|
||||
object, fields, parentSlot = parentSlot)
|
||||
|
||||
|
@ -324,9 +302,7 @@ class View(ModeMixin, proxyModes.View):
|
|||
headerTitle = '%s - %s' % (_(web.objectNameCapitalized), label)
|
||||
return headerTitle
|
||||
|
||||
def getModelLayoutInfos(self, object, fields, again, create,
|
||||
parentSlot = None):
|
||||
self.makeModelFields(object, fields, again, parentSlot = parentSlot)
|
||||
def getModelLayoutInfos(self, object, fields, create, parentSlot = None):
|
||||
headerTitle = self.getModelHeaderTitle(
|
||||
object, fields, parentSlot = parentSlot)
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ import glasnost.common.xhtmlgenerator as X
|
|||
|
||||
import glasnost.proxy.things as proxyThings
|
||||
|
||||
from tools import getWebForServerRole
|
||||
from tools import getWebForServerRole, isButtonSelected
|
||||
|
||||
|
||||
class ThingClasses(commonThings.ThingClasses):
|
||||
|
@ -74,6 +74,12 @@ def register(thingClass):
|
|||
class ThingMixin:
|
||||
errors = None
|
||||
|
||||
def fillWithDefaultValues(self, parentSlot = None):
|
||||
for slotName in self.getSlotNames(parentSlot = parentSlot):
|
||||
slot = self.getSlot(slotName, parentSlot = parentSlot)
|
||||
kind = slot.getKind()
|
||||
kind.setToDefaultValue(slot)
|
||||
|
||||
def getCompactEditLayout(self, fields, parentSlot = None):
|
||||
if parentSlot is None:
|
||||
level = 'getCompactEditLayout'
|
||||
|
@ -156,7 +162,7 @@ class ThingMixin:
|
|||
|
||||
def getEditLayoutSlotNames(self, fields, parentSlot = None):
|
||||
slotNames = self.getLayoutSlotNames(fields, parentSlot = parentSlot)
|
||||
if not fields.has_key('id') or not fields['id']:
|
||||
if hasattr(self, 'id') and not self.id:
|
||||
slotNamesToRemove = ['creationTime', 'lastEditorId',
|
||||
'modificationTime']
|
||||
for slotName in slotNamesToRemove:
|
||||
|
@ -164,18 +170,20 @@ class ThingMixin:
|
|||
slotNames.remove(slotName)
|
||||
return slotNames
|
||||
|
||||
def getErrorLayout(self, keywords):
|
||||
if keywords.has_key('hideErrors'):
|
||||
def getErrorLayout(self):
|
||||
if context.getVar('hideErrors'):
|
||||
return None
|
||||
|
||||
div = X.div(_class = 'error-message')
|
||||
div += X.h1(_('Error!'))
|
||||
if keywords.has_key('versionError') and keywords['versionError']:
|
||||
if self.getError('version'):
|
||||
div += X.p()(
|
||||
_("""\
|
||||
The informations have been changed while you were editing them.
|
||||
Please backup your changes and redo the edition.\
|
||||
"""))
|
||||
div += X.buttonStandalone(
|
||||
_('Look at new version'), X.idUrl(self.id))
|
||||
return div
|
||||
|
||||
def getFieldSlotNames(self, fields, parentSlot = None):
|
||||
|
@ -231,7 +239,7 @@ Please backup your changes and redo the edition.\
|
|||
return slotNames
|
||||
|
||||
def getOrderedFieldSlotNames(self, fields, parentSlot = None):
|
||||
return []
|
||||
return self.getOrderedLayoutSlotNames(parentSlot)
|
||||
|
||||
def getViewLayout(self, fields, parentSlot = None):
|
||||
context.push(_level = 'getViewLayout',
|
||||
|
@ -272,42 +280,18 @@ Please backup your changes and redo the edition.\
|
|||
def getViewLayoutSlotNames(self, fields, parentSlot = None):
|
||||
return self.getLayoutSlotNames(fields, parentSlot = parentSlot)
|
||||
|
||||
def initFields(self, fields, parentSlot = None):
|
||||
for slotName in self.getFieldSlotNames(
|
||||
fields, parentSlot = parentSlot):
|
||||
slot = self.getSlot(slotName, parentSlot = parentSlot)
|
||||
kind = slot.getKind()
|
||||
if kind.hasToInitField:
|
||||
kind.initField(slot, fields)
|
||||
|
||||
def makeFieldsFromInstance(self, fields, parentSlot = None):
|
||||
for slotName in self.getFieldSlotNames(
|
||||
fields, parentSlot = parentSlot):
|
||||
slot = self.getSlot(slotName, parentSlot = parentSlot)
|
||||
kind = slot.getKind()
|
||||
if kind.hasToMakeFieldFromValue:
|
||||
if slotName == 'thingName':
|
||||
value = self.getThingName()
|
||||
else:
|
||||
value = slot.getValue()
|
||||
kind.makeFieldFromValue(slot, fields, value)
|
||||
|
||||
def newWidget(self, parentSlot = None):
|
||||
return commonTools.newThing('widget', 'Thing')
|
||||
|
||||
def repairFields(self, fields, parentSlot = None):
|
||||
for slotName in self.getFieldSlotNames(
|
||||
fields, parentSlot = parentSlot):
|
||||
slot = self.getSlot(slotName, parentSlot = parentSlot)
|
||||
kind = slot.getKind()
|
||||
if kind.hasToRepairField:
|
||||
kind.repairField(slot, fields)
|
||||
|
||||
def getError(self, slotName):
|
||||
if not self.errors or not self.errors.has_key(slotName):
|
||||
return None
|
||||
return self.errors[slotName]
|
||||
|
||||
def hasErrors(self):
|
||||
# not not so we get a boolean
|
||||
return not not self.errors
|
||||
|
||||
def setError(self, slotPath, error):
|
||||
if not self.errors:
|
||||
self.errors = {}
|
||||
|
@ -317,15 +301,21 @@ Please backup your changes and redo the edition.\
|
|||
self.errors = {}
|
||||
|
||||
def submitFields(self, fields, parentSlot = None):
|
||||
self.delErrors()
|
||||
#self.delErrors()
|
||||
|
||||
if isButtonSelected('applyButton', fields):
|
||||
context.setVar('again', 1)
|
||||
context.setVar('hideErrors', 1)
|
||||
|
||||
# Change the class of the thing if needed.
|
||||
for slotName in ['thingCategory', 'thingName']:
|
||||
slot = self.getSlot(slotName, parentSlot = parentSlot)
|
||||
widget = slot.getWidget()
|
||||
kind = slot.getKind()
|
||||
if (kind.isRequiredInEditMode or kind.isExportable()) \
|
||||
and kind.hasToSubmitField:
|
||||
kind.submitField(slot, fields)
|
||||
value = widget.submit(slot, fields)
|
||||
slot.setValue(value)
|
||||
thingCategory = self.thingCategory
|
||||
if self.__dict__.has_key('thingCategory'):
|
||||
del self.thingCategory
|
||||
|
@ -336,8 +326,13 @@ Please backup your changes and redo the edition.\
|
|||
del self.thingName
|
||||
if thingCategory != self.thingCategory \
|
||||
or thingName != self.getThingName():
|
||||
self.__class__ = commonTools.getThingClass(
|
||||
try:
|
||||
self.__class__ = commonTools.getThingClass(
|
||||
thingCategory, thingName)
|
||||
except:
|
||||
pass
|
||||
# FIXME: I don't know what I'm doing
|
||||
# (was necessary to get properties (in cards) working
|
||||
|
||||
for slotName in self.getFieldSlotNames(
|
||||
fields, parentSlot = parentSlot):
|
||||
|
@ -349,22 +344,23 @@ Please backup your changes and redo the edition.\
|
|||
if (kind.isRequiredInEditMode or kind.isExportable()) \
|
||||
and kind.hasToSubmitField:
|
||||
try:
|
||||
valueKind, value = widget.submit(slot, fields)
|
||||
if valueKind is not None:
|
||||
value = kind.convertValueFromOtherKind(
|
||||
value, valueKind)
|
||||
value = widget.submit(slot, fields)
|
||||
if value is not None and \
|
||||
type(value) != kind.pythonStorageType:
|
||||
value = kind.convertValueFromOtherType(value)
|
||||
if kind.isEmptyModelValue(slot, value):
|
||||
value = None
|
||||
kind.checkModelValue(slot, value)
|
||||
except faults.BaseFault, f:
|
||||
self.setError(slot.getPath(), f)
|
||||
fields['again'] = '1'
|
||||
fields['error'] = '1'
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
continue
|
||||
#except NotImplementedError:
|
||||
# kind.submitField(slot, fields)
|
||||
|
||||
if not slot.hasValue() or value != slot.getValue():
|
||||
slot.setValue(value)
|
||||
|
||||
|
||||
|
||||
class BaseThing(ThingMixin, proxyThings.BaseThing):
|
||||
pass
|
||||
|
||||
|
|
|
@ -326,6 +326,9 @@ def isTypeOfMimeType(mimeType, type):
|
|||
|
||||
|
||||
def makeErrorMessage(error):
|
||||
# this function is no longer used;
|
||||
# it is kept since it has some strings that I want to keep in gettext
|
||||
# for future use.
|
||||
if error == 'can\'tChangeValue':
|
||||
message = N_('Can\'t change value!')
|
||||
elif error == 'duplicateValue':
|
||||
|
@ -647,10 +650,9 @@ def getTemplateVars():
|
|||
|
||||
shortNewsLabel = _('Short News')
|
||||
|
||||
session = context.getVar('session')
|
||||
if session and session.has_key('userId'):
|
||||
if userId:
|
||||
try:
|
||||
userName = getObject(session['userId']).getLabel()
|
||||
userName = getObject(userId).getLabel()
|
||||
except (faults.MissingItem, faults.UserAccessDenied):
|
||||
userName = _('Unknown')
|
||||
else:
|
||||
|
@ -722,7 +724,8 @@ def writePageLayout(layout, title, canCache = 1):
|
|||
program, macros = t.getCode()
|
||||
# this takes roughly 0.01 seconds, not worth caching
|
||||
|
||||
from TAL.TALInterpreter import TALInterpreter
|
||||
from GlasnostTALInterpreter import GlasnostTALInterpreter
|
||||
from TAL.HTMLParser import HTMLParseError
|
||||
from GlasnostTALEngine import GlasnostTALEngine, TALError
|
||||
engine = GlasnostTALEngine(macros)
|
||||
context.setVar('talEngine', engine)
|
||||
|
@ -732,7 +735,7 @@ def writePageLayout(layout, title, canCache = 1):
|
|||
for k, v in dict.items():
|
||||
engine.locals[k] = v
|
||||
|
||||
interp = TALInterpreter(program, macros, engine, stream=req, wrap=80)
|
||||
interp = GlasnostTALInterpreter(program, macros, engine, stream=req, wrap=80)
|
||||
try:
|
||||
interp()
|
||||
except TALError:
|
||||
|
@ -976,7 +979,7 @@ def processTALFile(fileName, file = None, xtal = None, **keywords):
|
|||
t.parseString(file)
|
||||
program, macros = t.getCode()
|
||||
|
||||
from TAL.TALInterpreter import TALInterpreter
|
||||
from GlasnostTALInterpreter import GlasnostTALInterpreter
|
||||
from GlasnostTALEngine import GlasnostTALEngine, TALError
|
||||
engine = GlasnostTALEngine(macros)
|
||||
context.setVar('talEngine', engine)
|
||||
|
@ -988,7 +991,7 @@ def processTALFile(fileName, file = None, xtal = None, **keywords):
|
|||
for k, v in dict.items():
|
||||
engine.locals[k] = v
|
||||
|
||||
interp = TALInterpreter(program, macros, engine, stream=req, wrap=80)
|
||||
interp = GlasnostTALInterpreter(program, macros, engine, stream=req, wrap=80)
|
||||
try:
|
||||
interp()
|
||||
except TALError:
|
||||
|
|
|
@ -58,6 +58,24 @@ import glasnost.common.tools_new as commonTools
|
|||
import glasnost.common.xhtmlgenerator as X
|
||||
|
||||
|
||||
def addContextualHeader(htmlLine):
|
||||
knownLines = {
|
||||
'tooltips.js':
|
||||
'<script src="%s" type="text/javascript"></script>' % \
|
||||
X.fileUrl('/javascript/tooltips.js'),
|
||||
'calendar.css':
|
||||
'<link href="%s" rel="stylesheet" type="text/css" />' % \
|
||||
X.fileUrl('/css/calendar.css'),
|
||||
'noindex':
|
||||
'<meta name="robots" content="noindex" />',
|
||||
}
|
||||
if htmlLine in knownLines.keys():
|
||||
htmlLine = knownLines[htmlLine]
|
||||
contextualHeaders = context.getVar('htmlHeaders')
|
||||
if not htmlLine in contextualHeaders:
|
||||
contextualHeaders.append(htmlLine)
|
||||
|
||||
|
||||
def debugInfos():
|
||||
req = context.getVar('req')
|
||||
req.content_type = 'text/html'
|
||||
|
@ -138,20 +156,3 @@ 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'),
|
||||
'calendar.css':
|
||||
'<link href="%s" rel="stylesheet" type="text/css" />' % \
|
||||
X.fileUrl('/css/calendar.css'),
|
||||
'noindex':
|
||||
'<meta name="robots" content="noindex" />',
|
||||
}
|
||||
if htmlLine in knownLines.keys():
|
||||
htmlLine = knownLines[htmlLine]
|
||||
contextualHeaders = context.getVar('htmlHeaders')
|
||||
if not htmlLine in contextualHeaders:
|
||||
contextualHeaders.append(htmlLine)
|
||||
|
||||
|
|
|
@ -64,7 +64,10 @@ def getFieldTranslated(object, field, keywords):
|
|||
|
||||
def getFieldValueAndTranslationBar(slot, noBar = 0):
|
||||
value = slot.getValue()
|
||||
value = slot.getKind().convertValueToOtherKind(value, kinds.String())
|
||||
|
||||
if type(value) is not types.StringType:
|
||||
value = slot.getKind().convertValueToOtherType(value, types.StringType)
|
||||
|
||||
if not value:
|
||||
return value, None
|
||||
|
||||
|
|
|
@ -105,12 +105,12 @@ class Upload(things.ThingMixin, proxyUploads.Upload):
|
|||
|
||||
def getEditLayout(self, fields, parentSlot = None):
|
||||
dataSlot = self.getSlot('data', parentSlot = parentSlot)
|
||||
data = dataSlot.getField(fields)
|
||||
data = dataSlot.getValue()
|
||||
sizeSlot = self.getSlot('size', parentSlot = parentSlot)
|
||||
if data and not sizeSlot.getField(fields):
|
||||
if data and not sizeSlot.getValue():
|
||||
sizeSlot.setField(fields, str(len(data)))
|
||||
dataTypeSlot = self.getSlot('dataType', parentSlot = parentSlot)
|
||||
if isTypeOfMimeType(dataTypeSlot.getField(fields, default = ''),
|
||||
if isTypeOfMimeType(dataTypeSlot.getValue() or '',
|
||||
'image') and PILImage:
|
||||
imageFile = cStringIO.StringIO(data)
|
||||
try:
|
||||
|
@ -141,8 +141,8 @@ class Upload(things.ThingMixin, proxyUploads.Upload):
|
|||
slotNames = things.ThingMixin.getViewLayoutSlotNames(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
slotNames = slotNames[:]
|
||||
if not fields.has_key('dataType') \
|
||||
or not isTypeOfMimeType(fields['dataType'], 'image'):
|
||||
if not self.dataType or \
|
||||
not isTypeOfMimeType(self.dataType, 'image'):
|
||||
if 'height' in slotNames:
|
||||
slotNames.remove('height')
|
||||
if 'width' in slotNames:
|
||||
|
@ -154,14 +154,4 @@ class Upload(things.ThingMixin, proxyUploads.Upload):
|
|||
if slotName in slotNames:
|
||||
slotNames.remove(slotName)
|
||||
return slotNames
|
||||
|
||||
def makeFieldsFromInstance(self, fields, parentSlot = None):
|
||||
for slotName in ('height', 'width'):
|
||||
self.getSlot(slotName, parentSlot = parentSlot).getKind(
|
||||
).hasToMakeFieldFromValue = self.isType('image')
|
||||
things.ThingMixin.makeFieldsFromInstance(
|
||||
self, fields, parentSlot = parentSlot)
|
||||
for slotName in ('height', 'width'):
|
||||
del self.getSlot(slotName, parentSlot = parentSlot).getKind(
|
||||
).hasToMakeFieldFromValue
|
||||
things.register(Upload)
|
||||
|
|
|
@ -49,8 +49,9 @@ __version__ = '$Revision$'[11:-2]
|
|||
|
||||
|
||||
import locale
|
||||
import time
|
||||
import re
|
||||
import time
|
||||
import types
|
||||
import urllib
|
||||
|
||||
import glasnost.common.context as context
|
||||
|
@ -100,9 +101,8 @@ class WidgetMixin(things.ThingMixin):
|
|||
label.setAttribute('class', ' '.join(
|
||||
[label.getAttribute('class'), 'fullwidth']))
|
||||
|
||||
if slot.getObject().getError(slot.getPath() or
|
||||
slot.getFieldOption(fields, 'error')) and \
|
||||
not fields.has_key('hideErrors'):
|
||||
if slot.getObject().getError(slot.getPath()) and \
|
||||
not context.getVar('hideErrors'):
|
||||
layout.setAttribute('class', ' '.join(
|
||||
[layout.getAttribute('class'), 'error']))
|
||||
layout += cell
|
||||
|
@ -171,8 +171,8 @@ class WidgetMixin(things.ThingMixin):
|
|||
return self.getHtmlFormValue(slot, fields, **keywords)
|
||||
|
||||
def getHtmlViewValue(self, slot, fields, **keywords):
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
format = slot.getKind().textFormat
|
||||
fieldValue = slot.getValue() or ''
|
||||
format = slot.getKind().getTextFormat(slot)
|
||||
if format == 'html':
|
||||
formattedText = parsers.makeHtmlFromHtml(fieldValue, inline = 1)
|
||||
elif format == 'text':
|
||||
|
@ -196,7 +196,7 @@ class WidgetMixin(things.ThingMixin):
|
|||
|
||||
def getHtmlFormValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
fieldValue = slot.getValue() or ''
|
||||
layout = X.array()
|
||||
layout += self.getModelErrorLayout(slot, fields)
|
||||
layout += self.getModelHelpLayout(slot, fields)
|
||||
|
@ -206,24 +206,18 @@ class WidgetMixin(things.ThingMixin):
|
|||
return layout
|
||||
|
||||
def getModelErrorLayout(self, slot, fields):
|
||||
if fields.has_key('hideErrors'):
|
||||
if context.getVar('hideErrors'):
|
||||
return None
|
||||
|
||||
try:
|
||||
error = slot.getObject().getError(slot.getPath())
|
||||
except:
|
||||
raise repr(slot)
|
||||
except (TypeError, IndexError):
|
||||
error = None
|
||||
if error:
|
||||
return X.span(_class = 'error-message')(
|
||||
_(error.uiFaultString))
|
||||
|
||||
errorCode = slot.getFieldOption(fields, 'error')
|
||||
if errorCode:
|
||||
return X.asIs(makeErrorMessage(errorCode))
|
||||
return None
|
||||
|
||||
def getModelFieldLayout(self, slot, fields, **keywords):
|
||||
assert fields is not None
|
||||
kind = slot.getKind()
|
||||
tagName = kind.getModelFieldTag(slot)
|
||||
if tagName == 'div-with-label':
|
||||
|
@ -255,12 +249,13 @@ class WidgetMixin(things.ThingMixin):
|
|||
|
||||
def getModelHiddenLayout(self, slot, fields):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = ''
|
||||
try:
|
||||
fieldValue = slot.getValue()
|
||||
except TypeError:
|
||||
pass
|
||||
return X.input(name = fieldName, type = 'hidden', value = fieldValue)
|
||||
value = slot.getValue()
|
||||
if value is None:
|
||||
value = ''
|
||||
if type(value) is not types.StringType:
|
||||
value = slot.getKind().convertValueToOtherType(
|
||||
value, types.StringType)
|
||||
return X.input(name = fieldName, type = 'hidden', value = value)
|
||||
|
||||
def getModelPageBodyLayout(self, slot, fields):
|
||||
layoutMode = context.getVar('layoutMode')
|
||||
|
@ -272,12 +267,14 @@ class WidgetMixin(things.ThingMixin):
|
|||
layout = self.getHtmlFormValue(slot, fields)
|
||||
return layout
|
||||
|
||||
def submitEmbedded(self, slot, fields):
|
||||
kind = slot.getKind()
|
||||
parentSlot, value = kind.getCreatedModelSlotAndValue(slot)
|
||||
value.submitFields(fields, parentSlot = parentSlot)
|
||||
return value
|
||||
|
||||
def submit(self, slot, fields):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = str(slot.getField(fields, default = ''))
|
||||
if not fieldValue:
|
||||
return None, None
|
||||
return kinds.String(), fieldValue
|
||||
return slot.getField(fields) or None
|
||||
|
||||
|
||||
class InputTextMixin(WidgetMixin):
|
||||
|
@ -287,7 +284,7 @@ class InputTextMixin(WidgetMixin):
|
|||
if not fieldValue:
|
||||
fieldValue = ''
|
||||
|
||||
format = slot.getKind().textFormat
|
||||
format = slot.getKind().getTextFormat(slot)
|
||||
if format == 'html':
|
||||
formattedText = parsers.makeHtmlFromHtml(fieldValue, inline = 1)
|
||||
elif format == 'text':
|
||||
|
@ -313,7 +310,12 @@ class InputTextMixin(WidgetMixin):
|
|||
def getHtmlReadOnlyValue(self, slot, fields, **keywords):
|
||||
fieldValue = slot.getValue()
|
||||
|
||||
format = slot.getKind().textFormat
|
||||
if type(fieldValue) is not types.StringType:
|
||||
fieldValue = slot.getKind().convertValueToOtherType(fieldValue,
|
||||
types.StringType)
|
||||
|
||||
|
||||
format = slot.getKind().getTextFormat(slot)
|
||||
if format == 'html':
|
||||
formattedText = parsers.makeHtmlFromHtml(fieldValue, inline = 1)
|
||||
elif format == 'text':
|
||||
|
@ -335,7 +337,11 @@ class InputTextMixin(WidgetMixin):
|
|||
|
||||
def getHtmlFormValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = str(slot.getField(fields, default = ''))
|
||||
fieldValue = slot.getValue()
|
||||
|
||||
if type(fieldValue) is not types.StringType:
|
||||
fieldValue = slot.getKind().convertValueToOtherType(fieldValue,
|
||||
types.StringType)
|
||||
|
||||
layout = X.array()
|
||||
layout += self.getModelErrorLayout(slot, fields)
|
||||
|
@ -361,12 +367,11 @@ class InputTextMixin(WidgetMixin):
|
|||
return layout
|
||||
|
||||
def submit(self, slot, fields):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = str(slot.getField(fields, default = ''))
|
||||
if not fieldValue:
|
||||
return None, None
|
||||
fieldValue = fieldValue.replace('\r\n', '\n')
|
||||
fieldValue = fieldValue.replace(
|
||||
value = WidgetMixin.submit(self, slot, fields)
|
||||
if value is None:
|
||||
return None
|
||||
value = value.replace('\r\n', '\n')
|
||||
value = value.replace(
|
||||
'\x91', "'").replace('\x92', "'").replace(
|
||||
'\x93', "'").replace('\x94', "'").replace(
|
||||
'\x81', "'").replace('\x82', "'").replace(
|
||||
|
@ -374,7 +379,7 @@ class InputTextMixin(WidgetMixin):
|
|||
'–', '--').replace('“', '"').replace(
|
||||
'´', "'").replace('”', '"').replace(
|
||||
'‘', "'")
|
||||
return kinds.String(), fieldValue
|
||||
return value
|
||||
|
||||
|
||||
class ThingMixin(WidgetMixin):
|
||||
|
@ -407,6 +412,28 @@ class ThingMixin(WidgetMixin):
|
|||
layout = value.getViewLayout(fields, parentSlot = parentSlot)
|
||||
return layout
|
||||
|
||||
def submit(self, slot, fields):
|
||||
# TODO: clarify things in my head
|
||||
kind = slot.getKind()
|
||||
parentSlot, value = kind.getCreatedModelSlotAndValue(slot)
|
||||
value.submitFields(fields, parentSlot)
|
||||
return value # ?
|
||||
|
||||
value = WidgetMixin.submit(self, slot, fields)
|
||||
if not value:
|
||||
return None
|
||||
try:
|
||||
oldValue = slot.getValue()
|
||||
except:
|
||||
oldValue = None
|
||||
kind = slot.getKind()
|
||||
value = commonTools.newThing(
|
||||
kind.valueThingCategory, value)
|
||||
if oldValue is not None and \
|
||||
oldValue.getThingName() == value.getThingName():
|
||||
value = oldValue
|
||||
return value
|
||||
|
||||
|
||||
class TimeMixin(InputTextMixin):
|
||||
pass
|
||||
|
@ -436,7 +463,6 @@ class Amount(WidgetMixin, proxyWidgets.Amount):
|
|||
X.nbsp,
|
||||
X.asIs(_(sideFieldLabel)),
|
||||
)
|
||||
|
||||
|
||||
def getHtmlFormValue(self, slot, fields, **keywords):
|
||||
mainFieldName = slot.getFieldOptionName('main')
|
||||
|
@ -492,6 +518,14 @@ class Amount(WidgetMixin, proxyWidgets.Amount):
|
|||
X.input(name = sideFieldName, type = 'hidden',
|
||||
value = sideFieldValue),
|
||||
)
|
||||
|
||||
def submit(self, slot, fields):
|
||||
value = int(slot.getFieldOption(fields, 'main',
|
||||
default = '0')) * 100 + \
|
||||
int(slot.getFieldOption(fields, 'cents', default = '0'))
|
||||
if slot.getFieldOption(fields, 'side', default = '') == 'debit':
|
||||
value = -value
|
||||
return value
|
||||
register(Amount)
|
||||
|
||||
|
||||
|
@ -607,7 +641,7 @@ class Date(TimeMixin, proxyWidgets.Date):
|
|||
|
||||
def submit(self, slot, fields):
|
||||
try:
|
||||
return kinds.Time(), time.mktime( [
|
||||
return time.mktime( [
|
||||
int(slot.getFieldOption(fields, 'year', default = '')),
|
||||
int(slot.getFieldOption(fields, 'month', default = '')),
|
||||
int(slot.getFieldOption(fields, 'day', default = '')) ] +
|
||||
|
@ -693,6 +727,21 @@ class Duration(WidgetMixin, proxyWidgets.Duration):
|
|||
X.input(name = dayFieldName, type = 'hidden',
|
||||
value = dayFieldValue),
|
||||
)
|
||||
|
||||
def submit(self, slot, fields):
|
||||
factors = {
|
||||
'second' : 1,
|
||||
'minute' : 60,
|
||||
'hour' : 60*60,
|
||||
'day' : 24*60*60
|
||||
}
|
||||
try:
|
||||
return reduce(lambda x,y:x+y,
|
||||
[int(slot.getFieldOption(
|
||||
fields, z, default = '0')) * factors[z]
|
||||
for z in factors.keys()] )
|
||||
except: # should be tighter
|
||||
raise faults.BadValue()
|
||||
register(Duration)
|
||||
|
||||
|
||||
|
@ -733,28 +782,19 @@ class Email(WidgetMixin, proxyWidgets.Email):
|
|||
layout += ' '
|
||||
layout += X.buttonInForm('apply', 'applyButton')
|
||||
return layout
|
||||
|
||||
def getModelHiddenLayout(self, slot, fields):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = slot.getValue() or ''
|
||||
|
||||
return X.array(
|
||||
X.input(name = fieldName, type = 'hidden',
|
||||
value = fieldValue),
|
||||
)
|
||||
register(Email)
|
||||
|
||||
|
||||
class InputCheckBox(WidgetMixin, proxyWidgets.InputCheckBox):
|
||||
def getHtmlViewValue(self, slot, fields, **keywords):
|
||||
kind = slot.getKind()
|
||||
value = kind.getModelValueFromFields(slot, fields)
|
||||
value = slot.getValue()
|
||||
return self.makeModelTitleFromValue(slot, fields, value)
|
||||
|
||||
def getHtmlFormValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
kind = slot.getKind()
|
||||
value = kind.getModelValueFromFields(slot, fields)
|
||||
value = slot.getValue() or 0
|
||||
|
||||
layout = X.array()
|
||||
layout += self.getModelErrorLayout(slot, fields)
|
||||
|
@ -790,6 +830,12 @@ class InputCheckBox(WidgetMixin, proxyWidgets.InputCheckBox):
|
|||
if labels and labels.has_key(valueAsString):
|
||||
return _(labels[valueAsString])
|
||||
return None
|
||||
|
||||
def submit(self, slot, fields):
|
||||
value = WidgetMixin.submit(self, slot, fields)
|
||||
if value is None:
|
||||
value = 0
|
||||
return int(value)
|
||||
register(InputCheckBox)
|
||||
|
||||
|
||||
|
@ -896,6 +942,10 @@ class Link(WidgetMixin, proxyWidgets.Link):
|
|||
X.input(name = urlFieldName, type = 'hidden',
|
||||
value = urlFieldValue),
|
||||
)
|
||||
|
||||
def submit(self, slot, fields):
|
||||
return (slot.getFieldOption(fields, 'name', default = ''),
|
||||
slot.getFieldOption(fields, 'url', default = '') )
|
||||
register(Link)
|
||||
|
||||
|
||||
|
@ -906,7 +956,6 @@ class Mapping(WidgetMixin, proxyWidgets.Mapping):
|
|||
count = kind.getItemsCount(slot, fields)
|
||||
layout = X.array()
|
||||
fieldset = X.div(_class = 'fieldset')
|
||||
# not X.fieldset because it's buggy on several proprietary browsers
|
||||
layout += fieldset
|
||||
if self.isInForm():
|
||||
layout += X.input(name = countName, type = 'hidden', value = count)
|
||||
|
@ -956,6 +1005,55 @@ class Mapping(WidgetMixin, proxyWidgets.Mapping):
|
|||
slot.getPath(), str(valueSlot.getKind().__dict__)))
|
||||
layout += valueWidget.getModelHiddenLayout(valueSlot, fields)
|
||||
return layout
|
||||
|
||||
def submit(self, slot, fields):
|
||||
count = slot.getKind().fieldsCountMin
|
||||
try:
|
||||
count = max(count,
|
||||
int(slot.getFieldOption(fields, 'count', default = '0')))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
value = {}
|
||||
for i in range(count):
|
||||
keySlot = slot.getKind().getItemKeySlot(slot, i)
|
||||
try:
|
||||
keyKind = keySlot.getKind()
|
||||
keyValue = keySlot.getWidget().submit(keySlot, fields)
|
||||
if keyValue is None:
|
||||
continue
|
||||
if type(keyValue) != keyKind.pythonStorageType:
|
||||
keyValue = keyKind.convertValueFromOtherType(keyValue)
|
||||
if keyKind.isEmptyModelValue(keySlot, keyValue):
|
||||
continue
|
||||
keyKind.checkModelValue(keySlot, keyValue)
|
||||
except faults.BaseFault, f:
|
||||
slot.getObject().setError(keySlot.getPath(), f)
|
||||
|
||||
itemSlot = slot.getKind().getItemKeyValueSlot(keySlot)
|
||||
try:
|
||||
itemKind = itemSlot.getKind()
|
||||
itemValue = itemSlot.getWidget().submit(itemSlot, fields)
|
||||
if itemValue is None and kind.deleteNullValues:
|
||||
continue
|
||||
if type(itemValue) != itemKind.pythonStorageType:
|
||||
itemValue = itemKind.convertValueFromOtherType(itemValue)
|
||||
if itemKind.isEmptyModelValue(itemSlot, itemValue) and \
|
||||
kind.deleteNullValues:
|
||||
continue
|
||||
except faults.BaseFault, f:
|
||||
slot.getObject().setError(itemSlot.getPath(), f)
|
||||
|
||||
value[keyValue] = itemValue
|
||||
|
||||
addButtonName = slot.getFieldOptionName('addButton')
|
||||
if isButtonSelected(addButtonName, fields):
|
||||
# TODO: fill with default value
|
||||
count = count + 1
|
||||
slot.setFieldOption(fields, 'count', str(count))
|
||||
context.setVar('again', 1)
|
||||
context.setVar('hideErrors', 1)
|
||||
return value
|
||||
register(Mapping)
|
||||
|
||||
|
||||
|
@ -963,7 +1061,7 @@ class Multi(WidgetMixin, proxyWidgets.Multi):
|
|||
def getHtmlViewValue(self, slot, fields, **keywords):
|
||||
kind = slot.getKind()
|
||||
layout = X.ul(_class = 'multi')
|
||||
value = slot.getValue()
|
||||
value = slot.getValue() or []
|
||||
for i, v in zip(range(len(value)), value):
|
||||
itemSlot = kind.getItemSlot(slot, i)
|
||||
itemWidget = itemSlot.getWidget()
|
||||
|
@ -978,6 +1076,8 @@ class Multi(WidgetMixin, proxyWidgets.Multi):
|
|||
kind = slot.getKind()
|
||||
countName = slot.getFieldOptionName('count')
|
||||
count = kind.getItemsCount(slot, fields)
|
||||
if slot.getValue():
|
||||
count = max(count, len(slot.getValue()) )
|
||||
layout = X.array()
|
||||
layout += self.getModelErrorLayout(slot, fields)
|
||||
|
||||
|
@ -1007,7 +1107,12 @@ class Multi(WidgetMixin, proxyWidgets.Multi):
|
|||
layout += X.buttonInForm('apply', 'applyButton')
|
||||
return layout
|
||||
|
||||
def getModelHiddenLayout(self, slot, fields):
|
||||
def getHtmlReadOnlyValue(self, slot, fields, **keywords):
|
||||
return X.array(
|
||||
self.getModelHiddenLayout(slot, fields, children = 0),
|
||||
self.getHtmlViewValue(slot, fields, **keywords) )
|
||||
|
||||
def getModelHiddenLayout(self, slot, fields, children = 1):
|
||||
countName = slot.getFieldOptionName('count')
|
||||
count = slot.getKind().fieldsCountMin
|
||||
try:
|
||||
|
@ -1018,17 +1123,19 @@ class Multi(WidgetMixin, proxyWidgets.Multi):
|
|||
layout = X.array()
|
||||
if count:
|
||||
layout += X.input(name = countName, type = 'hidden', value = count)
|
||||
for i in range(count):
|
||||
itemSlot = slot.getKind().getItemSlot(slot, i)
|
||||
itemWidget = itemSlot.getWidget()
|
||||
if itemWidget is None:
|
||||
raise Exception('Missing item widget for %s in %s' % (
|
||||
slot.getPath(), str(itemSlot.getKind().__dict__)))
|
||||
layout += itemWidget.getModelHiddenLayout(itemSlot, fields)
|
||||
if children:
|
||||
for i in range(count):
|
||||
itemSlot = slot.getKind().getItemSlot(slot, i)
|
||||
itemWidget = itemSlot.getWidget()
|
||||
if itemWidget is None:
|
||||
raise Exception('Missing item widget for %s in %s' % (
|
||||
slot.getPath(), str(itemSlot.getKind().__dict__)))
|
||||
layout += itemWidget.getModelHiddenLayout(itemSlot, fields)
|
||||
return layout
|
||||
|
||||
def submit(self, slot, fields):
|
||||
count = 1 # FIXME: was self.fieldsCountMin
|
||||
kind = slot.getKind()
|
||||
count = kind.fieldsCountMin
|
||||
try:
|
||||
count = max(count,
|
||||
int(slot.getFieldOption(fields, 'count', default = '0')))
|
||||
|
@ -1036,40 +1143,39 @@ class Multi(WidgetMixin, proxyWidgets.Multi):
|
|||
pass
|
||||
|
||||
value = []
|
||||
kind = slot.getKind()
|
||||
for i in range(count):
|
||||
itemSlot = kind.getItemSlot(slot, i)
|
||||
itemWidget = itemSlot.getWidget()
|
||||
itemKind = itemSlot.getKind()
|
||||
try:
|
||||
valueKind, itemValue = itemWidget.submit(itemSlot, fields)
|
||||
if valueKind is not None:
|
||||
itemValue = itemKind.convertValueFromOtherKind(
|
||||
itemValue, valueKind)
|
||||
else:
|
||||
# nothing selected; nothing added
|
||||
itemValue = itemWidget.submit(itemSlot, fields)
|
||||
if itemValue is None:
|
||||
# what if emptyValue != None ?
|
||||
continue
|
||||
if type(itemValue) != itemKind.pythonStorageType:
|
||||
itemValue = itemKind.convertValueFromOtherType(itemValue)
|
||||
if itemKind.isEmptyModelValue(itemSlot, itemValue):
|
||||
continue
|
||||
itemKind.checkModelValue(itemSlot, itemValue)
|
||||
except faults.BaseFault, f:
|
||||
itemSlot.getObject().setError(slot.getPath(), f)
|
||||
fields['again'] = '1'
|
||||
fields['error'] = '1'
|
||||
context.setVar('again', 1)
|
||||
context.setVar('error', 1)
|
||||
continue
|
||||
value.append(itemValue)
|
||||
|
||||
addButtonName = slot.getFieldOptionName('addButton')
|
||||
if isButtonSelected(addButtonName, fields):
|
||||
count = count + 1
|
||||
slot.setFieldOption(fields, 'count', str(count))
|
||||
fields['again'] = '1'
|
||||
fields['hideErrors'] = '1'
|
||||
|
||||
return kinds.Sequence(), value
|
||||
itemSlot = kind.getItemSlot(slot, count)
|
||||
itemKind = itemSlot.getKind()
|
||||
value.append(itemKind.getDefaultValue(itemSlot))
|
||||
context.setVar('again', 1)
|
||||
context.setVar('hideErrors', 1)
|
||||
return value
|
||||
register(Multi)
|
||||
|
||||
|
||||
class MultiCheck(WidgetMixin, proxyWidgets.MultiCheck):
|
||||
|
||||
def getHtmlViewValue(self, slot, fields, **keywords):
|
||||
kind = slot.getKind()
|
||||
layout = X.ul()
|
||||
|
@ -1103,22 +1209,22 @@ class MultiCheck(WidgetMixin, proxyWidgets.MultiCheck):
|
|||
values = kind.itemKind.getValues(slot, fields)
|
||||
for i in range(len(values)):
|
||||
fieldName = slot.getFieldOptionName(values[i])
|
||||
fieldValue = slot.getFieldOption(fields, values[i])
|
||||
if fieldValue == 'on':
|
||||
itemValue = slot.getFieldOption(fields, values[i])
|
||||
if itemValue == 'on':
|
||||
value.append(values[i])
|
||||
return kinds.Sequence(), value
|
||||
return value
|
||||
register(MultiCheck)
|
||||
|
||||
|
||||
class Path(WidgetMixin, proxyWidgets.Path):
|
||||
def getHtmlViewValue(self, slot, fields, **keywords):
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
fieldValue = slot.getValue() or ''
|
||||
return X.a(href = X.idUrl(object.id).add('path', fieldValue))(
|
||||
fieldValue)
|
||||
|
||||
def getHtmlFormValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
fieldValue = slot.getValue() or ''
|
||||
|
||||
layout = X.array()
|
||||
layout += self.getModelErrorLayout(slot, fields)
|
||||
|
@ -1155,7 +1261,7 @@ register(PushButton)
|
|||
class Select(WidgetMixin, proxyWidgets.Select):
|
||||
def getHtmlViewValue(self, slot, fields, **keywords):
|
||||
kind = slot.getKind()
|
||||
value = kind.getModelValueFromFields(slot, fields)
|
||||
value = slot.getValue() or ''
|
||||
valueAsString = kind.getModelValueAsString(value)
|
||||
labels = self.getLabels(slot, fields)
|
||||
if labels.has_key(valueAsString):
|
||||
|
@ -1168,8 +1274,18 @@ class Select(WidgetMixin, proxyWidgets.Select):
|
|||
def getHtmlFormValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
kind = slot.getKind()
|
||||
value = kind.getModelValueFromFields(slot, fields)
|
||||
valueAsString = kind.getModelValueAsString(value)
|
||||
try:
|
||||
value = slot.getValue() or ''
|
||||
except IndexError:
|
||||
value = None
|
||||
|
||||
if type(value) is types.StringType:
|
||||
valueAsString = value
|
||||
else:
|
||||
try:
|
||||
valueAsString = kind.convertValueToOtherType(value, types.StringType)
|
||||
except: # happens with class_ instance
|
||||
valueAsString = ''
|
||||
|
||||
if hasattr(kind, 'sortLabels') and kind.sortLabels:
|
||||
values = kind.getSortedValues(slot, fields)
|
||||
|
@ -1187,7 +1303,7 @@ class Select(WidgetMixin, proxyWidgets.Select):
|
|||
selectAttributes['name'] = fieldName
|
||||
select = X.select(**selectAttributes)
|
||||
itemsCount = len(values)
|
||||
if not value in values:
|
||||
if not valueAsString in [x or '' for x in values]:
|
||||
if labels.has_key(valueAsString):
|
||||
noneLabel = _(labels[valueAsString])
|
||||
else:
|
||||
|
@ -1219,7 +1335,7 @@ class Select(WidgetMixin, proxyWidgets.Select):
|
|||
for itemValue in groupValues:
|
||||
optionAttributes = {}
|
||||
itemValueAsString = kind.getModelValueAsString(itemValue)
|
||||
if itemValue == value:
|
||||
if itemValue == valueAsString:
|
||||
optionAttributes['selected'] = 'selected'
|
||||
if labels.has_key(itemValueAsString):
|
||||
label = _(labels[itemValueAsString])
|
||||
|
@ -1289,8 +1405,8 @@ class SelectId(WidgetMixin, proxyWidgets.SelectId):
|
|||
layout += self.getModelErrorLayout(slot, fields)
|
||||
layout += self.getModelHelpLayout(slot, fields)
|
||||
kind = slot.getKind()
|
||||
serverRoles = kind.getServerRoles()
|
||||
if not serverRoles:
|
||||
serverRoles = kind.getServerRoles(slot)
|
||||
if serverRoles is None:
|
||||
serverRoles = context.getVar('knownRoles')
|
||||
serverRoles = serverRoles[:]
|
||||
serverRoles.sort()
|
||||
|
@ -1353,10 +1469,8 @@ class TextArea(WidgetMixin, proxyWidgets.TextArea):
|
|||
**textareaAttributes)(fieldValue)
|
||||
else:
|
||||
virtualHost = context.getVar('virtualHost')
|
||||
sectionLevel = 2
|
||||
if virtualHost:
|
||||
sectionLevel = int(webTools.getConfig('BaseSectionLevel', '2'))
|
||||
format = slot.getKind().textFormat
|
||||
sectionLevel = context.getVar('sectionLevel') + 1
|
||||
format = slot.getKind().getTextFormat(slot)
|
||||
inline = context.getVar('inline', default = 0)
|
||||
if format == 'docbook':
|
||||
formattedText = parsers.makeHtmlFromDocBook(
|
||||
|
@ -1387,7 +1501,7 @@ class TextArea(WidgetMixin, proxyWidgets.TextArea):
|
|||
return layout
|
||||
|
||||
def getHtmlReadOnlyValue(self, slot, fields, **keywords):
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
fieldValue = slot.getValue() or ''
|
||||
layout = X.array(self.getModelHiddenLayout(slot, fields))
|
||||
if self.viewInTextArea:
|
||||
textareaAttributes = self.getTextAreaAttributes()
|
||||
|
@ -1395,11 +1509,8 @@ class TextArea(WidgetMixin, proxyWidgets.TextArea):
|
|||
**textareaAttributes)(fieldValue)
|
||||
return layout
|
||||
else:
|
||||
virtualHost = context.getVar('virtualHost')
|
||||
sectionLevel = 2
|
||||
if virtualHost:
|
||||
sectionLevel = int(webTools.getConfig('BaseSectionLevel', '2'))
|
||||
format = slot.getKind().textFormat
|
||||
sectionLevel = context.getVar('sectionLevel') + 1
|
||||
format = slot.getKind().getTextFormat(slot)
|
||||
inline = context.getVar('inline', default = 0)
|
||||
if format == 'docbook':
|
||||
formattedText = parsers.makeHtmlFromDocBook(
|
||||
|
@ -1441,7 +1552,7 @@ class TextArea(WidgetMixin, proxyWidgets.TextArea):
|
|||
|
||||
def getHtmlFormValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
fieldValue = slot.getValue() or ''
|
||||
|
||||
textareaAttributes = self.getTextAreaAttributes()
|
||||
|
||||
|
@ -1460,11 +1571,14 @@ class TextArea(WidgetMixin, proxyWidgets.TextArea):
|
|||
buttonsBar += X.buttonInForm('apply', 'applyButton')
|
||||
|
||||
if self.preview and fieldValue:
|
||||
format = slot.getKind().textFormat
|
||||
format = slot.getKind().getTextFormat(slot)
|
||||
if format == 'docbook':
|
||||
formattedText = parsers.makeHtmlFromDocBook(fieldValue)
|
||||
elif format == 'html':
|
||||
formattedText = parsers.makeHtmlFromHtml(fieldValue)
|
||||
if not slot.getObject().getError(slot.getPath()):
|
||||
formattedText = parsers.makeHtmlFromHtml(fieldValue)
|
||||
else:
|
||||
formattedText = '<strong>error in HTML</strong>'
|
||||
elif format == 'text':
|
||||
formattedText = parsers.makeHtmlFromPreformattedText(
|
||||
fieldValue)
|
||||
|
@ -1479,8 +1593,10 @@ class TextArea(WidgetMixin, proxyWidgets.TextArea):
|
|||
formattedText = replaceSpecialTags(formattedText)
|
||||
preferences = context.getVar('preferences')
|
||||
if (not preferences or preferences.spellcheckEntries) and \
|
||||
fields.has_key('language'):
|
||||
formattedText = spellcheck(formattedText, fields['language'])
|
||||
slot.getObject().hasSlotName('language'):
|
||||
languageSlot = slot.getObject().getSlot('language')
|
||||
formattedText = spellcheck(formattedText,
|
||||
languageSlot.getValue())
|
||||
if formattedText:
|
||||
layout += X.div(_class = 'preview')(X.asIs(formattedText))
|
||||
|
||||
|
@ -1527,7 +1643,7 @@ class UploadFile(WidgetMixin, proxyWidgets.UploadFile):
|
|||
typeSlot = slot.getContainer().getSlot(
|
||||
slot.name + 'Type', parentSlot = slot.parent)
|
||||
|
||||
if isTypeOfMimeType(typeSlot.getField(fields, default = ''), 'image'):
|
||||
if isTypeOfMimeType(typeSlot.getValue() or '', 'image'):
|
||||
uri = X.idUrl(object.id, 'thumbnail')
|
||||
if slot.parent is not None:
|
||||
uri.add('path', slot.parent.getPath())
|
||||
|
@ -1547,62 +1663,95 @@ class UploadFile(WidgetMixin, proxyWidgets.UploadFile):
|
|||
return ''
|
||||
|
||||
def getHtmlReadOnlyValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
|
||||
session = context.getVar('session')
|
||||
if session is not None:
|
||||
session['field_' + fieldName] = base64.encodestring(fieldValue)
|
||||
session['isDirty'] = 1
|
||||
return X.array(
|
||||
self.getModelHiddenLayout(slot, fields),
|
||||
self.getRepresentation(slot, fields, **keywords) )
|
||||
|
||||
def getModelHiddenLayout(self, slot, fields):
|
||||
value = slot.getValue()
|
||||
typeSlot = slot.getContainer().getSlot(
|
||||
slot.name + 'Type', parentSlot = slot.parent)
|
||||
fileName = self.fileName or ''
|
||||
|
||||
data = {
|
||||
'data': value,
|
||||
'type': typeSlot.getValue() or '',
|
||||
'fileName': fileName
|
||||
}
|
||||
|
||||
if context.getVar('session') is None:
|
||||
# TODO: create session
|
||||
pass
|
||||
sessionsProxy = getProxyForServerRole('sessions')
|
||||
self.dataToken = sessionsProxy.addTemporaryData(data)
|
||||
return X.input(name = slot.getFieldOptionName('dataToken'),
|
||||
type = 'hidden', value = self.dataToken)
|
||||
|
||||
def getHtmlFormValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
fieldValue = slot.getValue() or ''
|
||||
|
||||
layout = X.array()
|
||||
layout += self.getModelErrorLayout(slot, fields)
|
||||
layout += self.getModelHelpLayout(slot, fields)
|
||||
session = context.getVar('session')
|
||||
if session is not None:
|
||||
session['field_' + fieldName] = base64.encodestring(fieldValue)
|
||||
session['isDirty'] = 1
|
||||
layout += X.input(name = '%s|session' % fieldName,
|
||||
type = 'hidden', value = 1)
|
||||
layout += self.getModelHiddenLayout(slot, fields)
|
||||
representation = self.getRepresentation(slot, fields, **keywords)
|
||||
if representation:
|
||||
layout += representation
|
||||
layout += X.br()
|
||||
layout += X.input(name = '%s_field' % fieldName, type = 'file')
|
||||
layout += X.input(name = fieldName, type = 'file')
|
||||
return layout
|
||||
|
||||
def getRepresentation(self, slot, fields, **keywords):
|
||||
typeSlot = slot.getContainer().getSlot(
|
||||
slot.name + 'Type', parentSlot = slot.parent)
|
||||
|
||||
if not isTypeOfMimeType(
|
||||
typeSlot.getField(fields, default = ''), 'image'):
|
||||
if not isTypeOfMimeType(typeSlot.getValue() or '', 'image'):
|
||||
return ''
|
||||
|
||||
typeSlot = slot.getContainer().getSlot(
|
||||
slot.name + 'Type', parentSlot = slot.parent)
|
||||
object = slot.getObject()
|
||||
|
||||
fieldName = slot.getFieldName()
|
||||
uri = X.idUrl(object.id, 'imageEdit')
|
||||
if slot.parent is not None:
|
||||
uri.add('path', slot.parent.getPath())
|
||||
uri.add('%s|session' % fieldName, 1)
|
||||
uri.addKeywords(keywords)
|
||||
uri.add('dataToken', self.dataToken)
|
||||
return X.img(src = uri)
|
||||
|
||||
def submit(self, slot, fields):
|
||||
value = slot.getField(fields)
|
||||
upload = commonTools.newThing('other', 'Upload')
|
||||
dataToken = slot.getFieldOption(fields, 'dataToken')
|
||||
sessionsProxy = getProxyForServerRole('sessions')
|
||||
if value.value:
|
||||
upload.data = value.value
|
||||
upload.dataFileName = value.filename
|
||||
upload.dataType = value.type
|
||||
else:
|
||||
data = sessionsProxy.getTemporaryData(dataToken)
|
||||
if not data:
|
||||
return None
|
||||
upload.data = data['data']
|
||||
upload.dataFileName = data['fileName']
|
||||
upload.dataType = data['type']
|
||||
|
||||
# UploadFiles use Upload widget but not Upload kind
|
||||
# (and it wants information about type and filename)
|
||||
#
|
||||
# This line (+ more in UploadFilesWeb.py (submitFields))
|
||||
# is there while waiting for UploadFiles conversion
|
||||
# to Upload kind.
|
||||
context.setVar('UploadFilesXXX', upload)
|
||||
|
||||
sessionsProxy.delTemporaryData(dataToken)
|
||||
return upload
|
||||
register(UploadFile)
|
||||
|
||||
|
||||
class Url(WidgetMixin, proxyWidgets.Url):
|
||||
def getHtmlViewValue(self, slot, fields, **keywords):
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
fieldValue = slot.getValue() or ''
|
||||
if fieldValue:
|
||||
if fieldValue.startswith('http://'):
|
||||
href = fieldValue
|
||||
|
@ -1614,7 +1763,7 @@ class Url(WidgetMixin, proxyWidgets.Url):
|
|||
|
||||
def getHtmlFormValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = str(slot.getField(fields, default = ''))
|
||||
fieldValue = slot.getValue() or ''
|
||||
|
||||
layout = X.array()
|
||||
layout += self.getModelErrorLayout(slot, fields)
|
||||
|
@ -1638,15 +1787,6 @@ class Url(WidgetMixin, proxyWidgets.Url):
|
|||
layout += ' '
|
||||
layout += X.buttonInForm('apply', 'applyButton')
|
||||
return layout
|
||||
|
||||
def getModelHiddenLayout(self, slot, fields):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
|
||||
return X.array(
|
||||
X.input(name = fieldName, type = 'hidden',
|
||||
value = fieldValue),
|
||||
)
|
||||
register(Url)
|
||||
|
||||
|
||||
|
@ -1656,7 +1796,7 @@ class XSelect(Select, proxyWidgets.XSelect):
|
|||
|
||||
def getHtmlValue(self, slot, fields, **keywords):
|
||||
fieldName = slot.getFieldName()
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
fieldValue = slot.getValue()
|
||||
if fieldValue is None:
|
||||
fieldValue = ''
|
||||
else:
|
||||
|
@ -1788,11 +1928,7 @@ class XSelect(Select, proxyWidgets.XSelect):
|
|||
def getModelHiddenLayout(self, slot, fields):
|
||||
fieldName = slot.getFieldName()
|
||||
otherFieldName = slot.getFieldOptionName('other')
|
||||
fieldValue = slot.getField(fields, default = '')
|
||||
otherFieldValue = slot.getFieldOption(fields, 'other', default = '')
|
||||
if otherFieldValue:
|
||||
return X.input(name = otherFieldName, type = 'hidden',
|
||||
value = otherFieldValue)
|
||||
fieldValue = slot.getValue() or ''
|
||||
return X.input(name = fieldName, type = 'hidden', value = fieldValue)
|
||||
|
||||
def makeModelTitleFromValue(self, slot, fields, value):
|
||||
|
@ -1812,5 +1948,11 @@ class XSelect(Select, proxyWidgets.XSelect):
|
|||
if labels and labels.has_key(valueAsString):
|
||||
return _(labels[valueAsString])
|
||||
return valueAsString
|
||||
|
||||
def submit(self, slot, fields):
|
||||
otherFieldValue = slot.getFieldOption(fields, 'other', default = '')
|
||||
if otherFieldValue:
|
||||
return otherFieldValue
|
||||
return WidgetMixin.submit(self, slot, fields)
|
||||
register(XSelect)
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ class BuildCase01_generalPublicGroup(unittest.TestCase):
|
|||
"""Build the general public group."""
|
||||
|
||||
group = groups.GroupAll()
|
||||
group.acceptedRoles = ['people']
|
||||
group.acceptedRoles = ['people', 'ldappeople']
|
||||
group.language = 'en'
|
||||
group.name = N_('General Public')
|
||||
## group.itemIds = [system.generalPublicId]
|
||||
|
@ -78,6 +78,18 @@ class BuildCase01_generalPublicGroup(unittest.TestCase):
|
|||
commonTools.extractLocalId(groupId),
|
||||
commonTools.extractLocalId(system.generalPublicId))
|
||||
|
||||
def build02_loggedUserGroup(self):
|
||||
"""Build the logged users group."""
|
||||
|
||||
group = groups.GroupRole()
|
||||
group.acceptedRoles = [ 'people', 'ldappeople' ]
|
||||
group.language = 'en'
|
||||
group.name = N_('Logged Users')
|
||||
groupId = groupsProxy.addObject(group)
|
||||
self.failUnlessEqual(
|
||||
commonTools.extractLocalId(groupId),
|
||||
commonTools.extractLocalId(system.loggedUsersGroupId))
|
||||
|
||||
|
||||
buildLoader = unittest.TestLoader()
|
||||
buildLoader.testMethodPrefix = 'build'
|
||||
|
|
|
@ -89,11 +89,11 @@ h2.title {
|
|||
font-size: 120%;
|
||||
}
|
||||
|
||||
h3.author {
|
||||
li.authors {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
p.pubdate {
|
||||
li.edition-time {
|
||||
font-size: 60%;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,11 +119,11 @@ h2.title {
|
|||
font-size: 120%;
|
||||
}
|
||||
|
||||
h3.author {
|
||||
li.authors {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
p.pubdate {
|
||||
li.edition-time {
|
||||
font-size: 60%;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,8 +68,8 @@ p {
|
|||
text-align: justify;
|
||||
}
|
||||
|
||||
h3.author { display: none; }
|
||||
p.pubdate { display: none; }
|
||||
li.authors { display: none; }
|
||||
li.edition-time{ display: none; }
|
||||
|
||||
h2.title {
|
||||
color: #F18B1D;
|
||||
|
|
|
@ -80,7 +80,7 @@ h2.title {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
h3.author {
|
||||
li.authors {
|
||||
font-size: xx-small;
|
||||
}
|
||||
|
||||
|
|
|
@ -229,10 +229,6 @@ body>#menu {width:234px;}
|
|||
display: inline;
|
||||
}
|
||||
|
||||
.author {
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
#clock {
|
||||
background-image: url("../img/ikon_clock.png");
|
||||
background-repeat: no-repeat;
|
||||
|
|
|
@ -224,10 +224,6 @@ body>#menu {width:190px;}
|
|||
display: inline;
|
||||
}
|
||||
|
||||
.author {
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
#clock {
|
||||
background-image: url("../img/ikon_clock.png");
|
||||
background-repeat: no-repeat;
|
||||
|
|
|
@ -211,10 +211,6 @@ body>#header {height:14px;}
|
|||
display: inline;
|
||||
}
|
||||
|
||||
.author {
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
#clock {
|
||||
background-image: url("../img/ikon_clock.png");
|
||||
background-repeat: no-repeat;
|
||||
|
|
|
@ -37,14 +37,6 @@ p img {
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
hr {
|
||||
clear: both;
|
||||
height: 1px;
|
||||
color: #316700;
|
||||
}
|
||||
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: black;
|
||||
clear: left;
|
||||
|
@ -622,7 +614,7 @@ div.error-message {
|
|||
.odd {
|
||||
}
|
||||
|
||||
div#main-content h3.author {
|
||||
div#main-content li.authors {
|
||||
margin: 0;
|
||||
padding-top: 5px;
|
||||
font-size: 80%;
|
||||
|
@ -630,7 +622,7 @@ div#main-content h3.author {
|
|||
margin-left: 1em;
|
||||
}
|
||||
|
||||
div#main-content p.pubdate {
|
||||
div#main-content li.edition-time {
|
||||
font-size: 70%;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
|
|
@ -90,11 +90,11 @@ h2.title {
|
|||
font-size: 120%;
|
||||
}
|
||||
|
||||
h3.author {
|
||||
li.authors {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
p.pubdate {
|
||||
li.edition-time {
|
||||
font-size: 60%;
|
||||
}
|
||||
|
||||
|
|
|
@ -129,11 +129,11 @@ h2.title {
|
|||
font-size: 120%;
|
||||
}
|
||||
|
||||
h3.author {
|
||||
li.authors {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
p.pubdate {
|
||||
li.edition-time {
|
||||
font-size: 60%;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,10 @@ h1, h2, h3, h4 {
|
|||
font-weight: normal;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
clear: both;
|
||||
}
|
||||
|
@ -231,3 +235,24 @@ table.calendar-month-full th, table.calendar-week-full th {
|
|||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
hr {
|
||||
clear: both;
|
||||
height: 1px;
|
||||
color: #444;
|
||||
background-color: #444;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
span.comment-no {
|
||||
display: block;
|
||||
float: left;
|
||||
font-size: 200%;
|
||||
padding-right: 0.5em;
|
||||
font-style: italic;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
div.comment h2, div.comment h3 {
|
||||
clear: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
<div metal:fill-slot="main">
|
||||
|
||||
<div class="spacer"> </div>
|
||||
<div id="contact-infos" tal:content="structure GlasnostObject('/articles/3').getFormattedBody()"
|
||||
|
||||
<div tal:replace="structure GlasnostObject('/articles/3').getFormattedBody()"
|
||||
tal:on-error="nothing">
|
||||
Présentation de Glasnost
|
||||
</div>
|
||||
|
|
|
@ -34,12 +34,6 @@ p img {
|
|||
}
|
||||
|
||||
|
||||
hr {
|
||||
clear: both;
|
||||
height: 1px;
|
||||
color: #8cacbb;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: black;
|
||||
clear: left;
|
||||
|
@ -585,17 +579,19 @@ div.error-message {
|
|||
.odd {
|
||||
}
|
||||
|
||||
div#main-content h3.author {
|
||||
margin: 0;
|
||||
padding-top: 5px;
|
||||
font-size: 80%;
|
||||
border-bottom: 0;
|
||||
margin-left: 1em;
|
||||
ul.article-meta {
|
||||
margin-top: -1em;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div#main-content p.pubdate {
|
||||
ul.article-meta li.authors {
|
||||
margin: 0;
|
||||
font-size: 80%;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
ul.article-meta li.edition-time {
|
||||
font-size: 70%;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
div#main-content h2 {
|
||||
|
|
|
@ -57,7 +57,6 @@ h1#header {
|
|||
|
||||
div#content {
|
||||
margin: 4em 14em 0px 50px;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
div#content h1 {
|
||||
|
@ -72,6 +71,7 @@ div#content h2 {
|
|||
/*margin-left: -30px;*/
|
||||
margin-left: 0.5em;
|
||||
margin-right: 10%;
|
||||
margin-bottom: 0;
|
||||
color: #33517f;
|
||||
border-bottom: 1px solid #33517f;
|
||||
font-weight: normal;
|
||||
|
@ -82,18 +82,27 @@ div#content h2:first-letter {
|
|||
/*color: #90abdb;*/
|
||||
}
|
||||
|
||||
div.titlepage {
|
||||
div#content p {
|
||||
margin: 0.5em 0;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
ul.article-meta {
|
||||
border: 1px solid #33517f;
|
||||
border-top: none;
|
||||
float: right;
|
||||
background: #7297ce url('/images/border-top.png') top left repeat-x;
|
||||
margin: -5px 1em 1em 1em;
|
||||
font-size: 80%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.titlepage .author, div.titlepage p {
|
||||
margin: 0 1em;
|
||||
font-size: 100%;
|
||||
ul.article-meta li {
|
||||
text-align: center;
|
||||
max-width: 13em;
|
||||
margin: 0 0.5em;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
a:link {
|
||||
|
@ -149,7 +158,9 @@ div.row ul {
|
|||
|
||||
div.buttons-bar {
|
||||
margin-top: 1em;
|
||||
width: 130%;
|
||||
clear: both;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.buttons-bar .button {
|
||||
|
@ -236,3 +247,15 @@ div.diff-error {
|
|||
margin: 0.5em 0 0 2em;
|
||||
}
|
||||
|
||||
pre {
|
||||
border: 1px solid #44618f;
|
||||
background: #a0bbfb;
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
|
||||
div.comment span.comment-no {
|
||||
float: left;
|
||||
font-size: 200%;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
|
|
Reference in New Issue