Continued work on new Appy GUI.

This commit is contained in:
Gaetan Delannay 2011-09-18 15:00:05 +02:00
parent 377a322faa
commit 7ff56a6520
38 changed files with 1179 additions and 1289 deletions

View file

@ -674,7 +674,7 @@ class Type:
if 'cell' not in layouts:
layouts['cell'] = Table(other=layouts['view'], derivedType='cell')
# Put the required CSS classes in the layouts
layouts['cell'].addCssClasses('no-style-table')
layouts['cell'].addCssClasses('noStyle')
if self.master:
# This type has a master (so is a slave): we add css classes
# allowing to show/hide, in Javascript, its widget according to
@ -1462,13 +1462,10 @@ class Date(Type):
label)
def getCss(self, layoutType):
if (layoutType == 'edit') and self.calendar:
return ('jscalendar/calendar-system.css',)
if (layoutType == 'edit') and self.calendar: return ('calendar.css',)
def getJs(self, layoutType):
if (layoutType == 'edit') and self.calendar:
return ('jscalendar/calendar_stripped.js',
'jscalendar/calendar-en.js')
if (layoutType == 'edit') and self.calendar: return ('calendar.js',)
def getSelectableYears(self):
'''Gets the list of years one may select for this field.'''
@ -1727,7 +1724,8 @@ class Ref(Type):
historized, sync, mapping, label)
self.validable = self.link
def getDefaultLayouts(self): return {'view': Table('l-f'), 'edit': 'lrv-f'}
def getDefaultLayouts(self):
return {'view': Table('l-f', width='100%'), 'edit': 'lrv-f'}
def isShowable(self, obj, layoutType):
res = Type.isShowable(self, obj, layoutType)
@ -2639,11 +2637,6 @@ class Config:
# People having one of these roles will be able to create instances
# of classes defined in your application.
self.defaultCreators = ['Manager', 'Owner']
# If True, the following flag will produce a minimalist Plone, where
# some actions, portlets or other stuff less relevant for building
# web applications, are removed or hidden. Using this produces
# effects on your whole Plone site!
self.minimalistPlone = False
# If you want to replace the Plone front page with a page coming from
# your application, use the following parameter. Setting
# frontPage = True will replace the Plone front page with a page
@ -2651,9 +2644,6 @@ class Config:
self.frontPage = False
# You can choose the Plone or Appy main template
self.frontPageTemplate = 'plone' # or "appy"
# If you don't need the portlet that appy.gen has generated for your
# application, set the following parameter to False.
self.showPortlet = True
# Number of translations for every page on a Translation object
self.translationsPerPage = 30
# Language that will be used as a basis for translating to other

View file

@ -14,9 +14,6 @@
# w - The widgets of the current page/class
# n - The navigation panel (inter-objects navigation)
# b - The range of buttons (intra-object navigation, save, edit, delete...)
# m - The global status message sometimes shown. If you specify this in a
# layout, ensure that you have hidden the global_statusmessage zone as
# proposed by Plone. Else, the message will appear twice.
# Layout elements for a field --------------------------------------------------
# l - "label" The field label
@ -48,7 +45,6 @@ macroDict = {
# Page-related elements
's': ('page', 'header'), 'w': ('page', 'widgets'),
'n': ('navigate', 'objectNavigate'), 'b': ('page', 'buttons'),
'm': ('page', 'message'),
# Field-related elements
'l': ('show', 'label'), 'd': ('show', 'description'),
'h': ('show', 'help'), 'v': ('show', 'validation'),
@ -220,6 +216,6 @@ class Table(LayoutElement):
# ------------------------------------------------------------------------------
defaultPageLayouts = {
'view': Table('m;-s|-n!-w|-b|'), 'edit': Table('m;-w|-b|')}
'view': Table('s|-n!-w|-b|'), 'edit': Table('w|-b|')}
defaultFieldLayouts = {'edit': 'lrv;f!'}
# ------------------------------------------------------------------------------

View file

@ -45,7 +45,6 @@ class Generator(AbstractGenerator):
# i18n labels to generate
self.labels = [] # i18n labels
self.toolInstanceName = 'portal_%s' % self.applicationName.lower()
self.portletName = '%s_portlet' % self.applicationName.lower()
self.skinsFolder = 'skins/%s' % self.applicationName
# The following dict, pre-filled in the abstract generator, contains a
# series of replacements that need to be applied to file templates to
@ -168,15 +167,9 @@ class Generator(AbstractGenerator):
destFolder='profiles/default')
self.copyFile('ProfileInit.py', self.repls, destFolder='profiles',
destName='__init__.py')
self.copyFile('Portlet.pt', self.repls,
destName='%s.pt' % self.portletName, destFolder=self.skinsFolder)
self.copyFile('tool.gif', {})
self.copyFile('Styles.css.dtml',self.repls, destFolder=self.skinsFolder,
destName = '%s.css.dtml' % self.applicationName)
self.copyFile('IEFixes.css.dtml',self.repls,destFolder=self.skinsFolder)
if self.config.minimalistPlone:
self.copyFile('colophon.pt', self.repls,destFolder=self.skinsFolder)
self.copyFile('footer.pt', self.repls, destFolder=self.skinsFolder)
# Create version.txt
f = open(os.path.join(self.outputFolder, 'version.txt'), 'w')
f.write(self.version)
@ -393,10 +386,8 @@ class Generator(AbstractGenerator):
grantableRoles = self.getAllUsedRoles(local=False, grantable=True)
repls['grRoles'] = ','.join(['"%s"' % r.name for r in grantableRoles])
# Generate configuration options
repls['showPortlet'] = self.config.showPortlet
repls['languages'] = ','.join('"%s"' % l for l in self.config.languages)
repls['languageSelector'] = self.config.languageSelector
repls['minimalistPlone'] = self.config.minimalistPlone
repls['appFrontPage'] = bool(self.config.frontPage)
repls['sourceLanguage'] = self.config.sourceLanguage
self.copyFile('config.py', repls)
@ -595,9 +586,7 @@ class Generator(AbstractGenerator):
"(getattr(OrderedBaseFolder,'__implements__',()),)",
'register': "registerType(%s, '%s')" % (self.tool.name,
self.applicationName),
'static': "left_slots = ['here/portlet_prefs/macros/portlet']\n " \
"right_slots = []\n " \
"def __init__(self, id=None):\n " \
'static': "def __init__(self, id=None):\n " \
" OrderedBaseFolder.__init__(self, '%s')\n " \
" self.setTitle('%s')\n" % (self.toolInstanceName,
self.applicationName)})

View file

@ -27,7 +27,6 @@ class PloneInstaller:
self.config = cfg = config
# Unwrap some useful variables from config
self.productName = cfg.PROJECTNAME
self.minimalistPlone = cfg.minimalistPlone
self.appClasses = cfg.appClasses
self.appClassNames = cfg.appClassNames
self.allClassNames = cfg.allClassNames
@ -35,7 +34,6 @@ class PloneInstaller:
self.applicationRoles = cfg.applicationRoles # Roles defined in the app
self.defaultAddRoles = cfg.defaultAddRoles
self.appFrontPage = cfg.appFrontPage
self.showPortlet = cfg.showPortlet
self.languages = cfg.languages
self.languageSelector = cfg.languageSelector
self.attributes = cfg.attributes
@ -78,19 +76,6 @@ class PloneInstaller:
logger.info('Created index "%s" of type "%s"...' % \
(indexName, indexType))
actionsToHide = {
'portal_actions': ('sitemap', 'accessibility', 'change_state','sendto'),
'portal_membership': ('mystuff', 'preferences'),
'portal_undo': ('undo',)
}
def customizePlone(self):
'''Hides some UI elements that appear by default in Plone.'''
for portalName, toHide in self.actionsToHide.iteritems():
portal = getattr(self.ploneSite, portalName)
portalActions = portal.listActions()
for action in portalActions:
if action.id in toHide: action.visible = False
appyFolderType = 'AppyFolder'
def registerAppyFolderType(self):
'''We need a specific content type for the folder that will hold all
@ -265,30 +250,6 @@ class PloneInstaller:
# If an instance with the same name already exists, this error will
# be unelegantly raised by Zope.
pass
except:
e = sys.exc_info()
if e[0] != 'Bad Request': raise
# Hide the tool from the search form
portalProperties = self.ploneSite.portal_properties
if portalProperties is not None:
siteProperties = getattr(portalProperties, 'site_properties', None)
if siteProperties is not None and \
siteProperties.hasProperty('types_not_searched'):
current = list(siteProperties.getProperty('types_not_searched'))
if self.toolName not in current:
current.append(self.toolName)
siteProperties.manage_changeProperties(
**{'types_not_searched' : current})
# Hide the tool in the navigation
if portalProperties is not None:
nvProps = getattr(portalProperties, 'navtree_properties', None)
if nvProps is not None and nvProps.hasProperty('idsNotToList'):
current = list(nvProps.getProperty('idsNotToList'))
if self.toolInstanceName not in current:
current.append(self.toolInstanceName)
nvProps.manage_changeProperties(**{'idsNotToList': current})
self.tool = getattr(self.ploneSite, self.toolInstanceName)
self.tool.refreshSecurity()
@ -297,25 +258,9 @@ class PloneInstaller:
self.tool.createOrUpdate(False, None)
else:
self.tool.createOrUpdate(True, None)
self.updatePodTemplates()
# Uncatalog tool
self.tool.unindexObject()
# Register tool as configlet
portalControlPanel = self.ploneSite.portal_controlpanel
portalControlPanel.unregisterConfiglet(self.toolName)
portalControlPanel.registerConfiglet(
self.toolName, self.productName,
'string:${portal_url}/%s' % self.toolInstanceName, 'python:True',
'Manage portal', # Access permission
'Products', # Section to which the configlet should be added:
# (Plone, Products (default) or Member)
1, # Visibility
'%sID' % self.toolName, 'site_icon.gif', # Icon in control_panel
self.productName, None)
def installTranslations(self):
'''Creates or updates the translation objects within the tool.'''
translations = [t.o.id for t in self.appyTool.translations]
@ -386,32 +331,6 @@ class PloneInstaller:
defaults.update(cssInfo)
portalCss.registerStylesheet(**defaults)
def managePortlets(self):
'''Shows or hides the application-specific portlet and configures other
Plone portlets if relevant.'''
portletName= 'here/%s_portlet/macros/portlet' % self.productName.lower()
site = self.ploneSite
leftPortlets = site.getProperty('left_slots')
if not leftPortlets: leftPortlets = []
else: leftPortlets = list(leftPortlets)
if self.showPortlet and (portletName not in leftPortlets):
leftPortlets.insert(0, portletName)
if not self.showPortlet and (portletName in leftPortlets):
leftPortlets.remove(portletName)
# Remove some basic Plone portlets that make less sense when building
# web applications.
portletsToRemove = ["here/portlet_navigation/macros/portlet",
"here/portlet_recent/macros/portlet",
"here/portlet_related/macros/portlet"]
if not self.minimalistPlone: portletsToRemove = []
for p in portletsToRemove:
if p in leftPortlets:
leftPortlets.remove(p)
site.manage_changeProperties(left_slots=tuple(leftPortlets))
if self.minimalistPlone:
site.manage_changeProperties(right_slots=())
def manageIndexes(self):
'''For every indexed field, this method installs and updates the
corresponding index if it does not exist yet.'''
@ -442,21 +361,11 @@ class PloneInstaller:
def finalizeInstallation(self):
'''Performs some final installation steps.'''
site = self.ploneSite
# Do not generate an action (tab) for each root folder
if self.minimalistPlone:
site.portal_properties.site_properties.manage_changeProperties(
disable_folder_sections=True)
# Do not allow an anonymous user to register himself as new user
site.manage_permission('Add portal member', ('Manager',), acquire=0)
# Call custom installer if any
if hasattr(self.appyTool, 'install'):
self.tool.executeAppyAction('install', reindex=False)
# Patch the "logout" action with a custom Appy one that updates the
# list of currently logged users.
for action in site.portal_membership._actions:
if action.id == 'logout':
action.setActionExpression(
'string:${portal_url}/%s/logout' % self.toolInstanceName)
# Replace Plone front-page with an application-specific page if needed
if self.appFrontPage:
frontPageName = self.productName + 'FrontPage'
@ -465,14 +374,12 @@ class PloneInstaller:
def info(self, msg): return self.appyTool.log(msg)
def install(self):
if self.minimalistPlone: self.customizePlone()
self.installRootFolder()
self.installTypes()
self.installTool()
self.installTranslations()
self.installRolesAndGroups()
self.installStyleSheet()
self.managePortlets()
self.manageIndexes()
self.manageLanguages()
self.finalizeInstallation()

View file

@ -27,6 +27,10 @@ class ToolMixin(BaseMixin):
res = '%s%s' % (elems[1], elems[4])
return res
def getApp(self):
'''Returns the root application object.'''
return self.portal_url.getPortalObject()
def getSiteUrl(self):
'''Returns the absolute URL of this site.'''
return self.portal_url.getPortalObject().absolute_url()
@ -342,6 +346,11 @@ class ToolMixin(BaseMixin):
def getPublishedObject(self):
'''Gets the currently published object, if its meta_class is among
application classes.'''
req = self.REQUEST
# If we are querying object, there is no published object (the truth is:
# the tool is the currently published object but we don't want to
# consider it this way).
if not req['ACTUAL_URL'].endswith('/skyn/view'): return
obj = self.REQUEST['PUBLISHED']
parent = obj.getParentNode()
if parent.id == 'skyn': obj = parent.getParentNode()
@ -538,8 +547,8 @@ class ToolMixin(BaseMixin):
if refInfo: criteria['_ref'] = refInfo
rq.SESSION['searchCriteria'] = criteria
# Go to the screen that displays search results
backUrl = '%s/query?type_name=%s&&search=_advanced' % \
(os.path.dirname(rq['URL']),rq['type_name'])
backUrl = '%s/skyn/query?type_name=%s&&search=_advanced' % \
(self.absolute_url(), rq['type_name'])
return self.goto(backUrl)
def getJavascriptMessages(self):
@ -605,7 +614,7 @@ class ToolMixin(BaseMixin):
'''This method creates the URL that allows to perform a (non-Ajax)
request for getting queried objects from a search named p_searchName
on p_contentType.'''
baseUrl = self.getAppFolder().absolute_url() + '/skyn'
baseUrl = self.absolute_url() + '/skyn'
baseParams = 'type_name=%s' % contentType
rq = self.REQUEST
if rq.get('ref'): baseParams += '&ref=%s' % rq.get('ref')

View file

@ -4,23 +4,26 @@
It can also have a parameter "action", that refers to a method that will be triggered on
contextObj before returning the result of the macro to the browser.
</tal:comment>
<tal:ajax define="page request/page;
macro request/macro;
contextObj context/getParentNode;
action request/action|nothing;
response request/RESPONSE;
member context/portal_membership/getAuthenticatedMember;
portal context/portal_url/getPortalObject;
portal_url python: context.portal_url();
template python: contextObj.getPageTemplate(portal.skyn, page);
dummy python: response.setHeader('Content-Type','text/html;;charset=utf-8');
dummy2 python: response.setHeader('Expires', 'Mon, 11 Dec 1975 12:05:05 GMT');
dummy3 python: response.setHeader('CacheControl', 'no-cache')">
<tal:ajax define="contextObj context/getParentNode;
tool contextObj/getTool;
req python: request;
resp req/RESPONSE;
page req/page;
macro req/macro;
action req/action|nothing;
user contextObj/portal_membership/getAuthenticatedMember;
app tool/getApp;
appUrl app/absolute_url;
template python: contextObj.getPageTemplate(app.skyn, page);
x python: resp.setHeader('Content-Type','text/html;;charset=utf-8');
x python: resp.setHeader('Expires', 'Mon, 11 Dec 1975 12:05:05 GMT');
x python: resp.setHeader('Content-Language', req.get('language', 'en'));
x python: resp.setHeader('CacheControl', 'no-cache')">
<tal:comment replace="nothing">Keys "Expires" and "CacheControl" are used for preventing IE to cache
this page. Indeed, this page is retrieved through an asynchronous XMLHttpRequest by the browser, and
IE caches this by default.</tal:comment>
<tal:executeAction condition="action">
<tal:do define="dummy python: contextObj.getMethod('on'+action)()" omit-tag=""/>
<tal:do define="x python: contextObj.getMethod('on'+action)()" omit-tag=""/>
</tal:executeAction>
<metal:callMacro use-macro="python: template.macros.get(macro)"/>
</tal:ajax>

View file

@ -1,37 +1,64 @@
body {
font: 75% Lucida,Helvetica,Arial,sans-serif;
background-color: #EAEAEA;
}
a {text-decoration: none; color: #747171;}
a:visited {color: #840107;}
body { font: 70% Lucida,Helvetica,Arial,sans-serif; background-color: #EAEAEA; }
h1 { font-size: 11pt; margin:0;}
h2 { font-size: 10pt; margin:0; font-style: italic; font-weight: normal;}
h3 { font-size: 9pt; margin:0; font-weight: bold;}
a { text-decoration: none; color: #503737;}
a:visited { color: #503737;}
table { font-size: 100%; border-spacing: 0px; border-collapse:collapse;}
input {border: 1px solid #a79e9e;}
form {margin: 0; padding: 0;}
p {margin: 0;}
h1 {font-size: 11pt; margin:0;}
h2 {font-size: 10pt; margin:0; font-style: italic; font-weight: normal;}
h3 {font-size: 9pt; margin:0; font-weight: bold;}
.main {
width: 900px;
background-color: white;
border-style: solid;
border-width: 1px;
border-color: grey;
box-shadow: 3px 3px 3px #A9A9A9;
}
form { margin: 0; padding: 0;}
p { margin: 0;}
acronym {cursor: help;}
input { border: 1px solid #a79e9e;
font-family: Lucida,Helvetica,Arial,sans-serif; }
input[type=image] { border-width: 0px; background: none; }
textarea { width: 99%; font: 100% Lucida,Helvetica,Arial,sans-serif;
border: 1px solid #a79e9e;}
label { font-weight: 600; font-style: italic; line-height: 1.4em;}
.main { width: 900px; background-color: white; box-shadow: 3px 3px 3px #A9A9A9;
border-style: solid; border-width: 1px; border-color: grey; }
.top { height: 75px; margin-left: 3em; vertical-align: top;}
.lang { margin-right: 3px; }
.userStrip {
background-color: #a2a2a2;
border-top: 3px solid #525252;
border-bottom: 2px solid #9b0000;
height: 30px;
}
.userStrip { background-color: #a2a2a2; height: 30px;
border-top: 3px solid #525252; border-bottom: 2px solid #9b0000; }
.login { margin-top: 2px; margin-bottom: 2px; color: white;}
.buttons { margin-left: 4px; }
.content {margin: 7px 0 9px 4px;}
.message {color: #9b0000; font-style: italic; position: absolute; top: -50px; right: 5px}
.message { color: #9b0000; font-style: italic;
position: absolute; top: -15px; right: 5px}
.discreet { font-size: 90%; }
.portlet { width: 150px; padding: 3px 7px 0px 7px;
border-right: 1px solid #9b0000;}
.portletCurrent { font-weight: bold; }
.portletSep { border-top: 1px solid grey; margin-top: 5px; padding-top: 5px}
.portletPage { font-style: italic; }
.phase { border-style: dashed; border-width: thin; padding: 0 0.6em 0 1em; }
.content { padding: 3px 3px 7px 15px;}
.grey { display: none; position: absolute; left: 0px; top: 0px;
width:100%; height:100%; background:grey; opacity:0.5;
-moz-opacity:0.5; -khtml-opacity:0.5; filter:alpha(Opacity=50);}
.popup { display: none; position: absolute; top: 30%; left: 35%;
width: 350px; z-index : 100; background: white; padding: 8px;
border: 1px solid grey; }
.list { border: 1px solid grey; margin-bottom: 3px;}
.list td, .list th { border: 1px solid grey;
padding-left: 3px; padding-right: 3px;}
.list th { background-color: #cbcbcb; font-style: italic; font-weight: normal;}
.noStyle { border: 0 !important; padding: 0 !important; margin: 0 !important; }
.noStyle td { border:0 !important; padding:0 !important; margin:0 !important; }
.translationLabel { background-color: #EAEAEA; border-bottom: 1px dashed grey;
margin-top: 0.5em; margin-bottom: 0.5em; }
.section1 { font-size: 120%; margin: 0.45em 0em 0.1em 0;
padding: 0.3em 0em 0.2em 0.1em; background-color: #eef3f5;
border-top: 1px solid #8CACBB;border-bottom: 1px solid #8CACBB; }
.section2 { font-size: 110%; font-style: italic; margin: 0.45em 0em 0.1em 0;
border-bottom: 2px solid grey; }
.section3 { font-size: 100%; font-style: italic; margin: 0.45em 0em 0.1em 0;
background-color: #efeae8; text-align: center; color: grey; }
.odd { background-color: white; }
.even { background-color: #ededed; }
.summary {margin-bottom: 5px;}
.objectTitle { font-size: 11pt; border-bottom: 3px solid grey;
font-weight: bold;}
.by { background-color: #ededed; font-style: italic; padding-top: 3px;}
.workflow { background-color: #ededed; text-align: center;}
.objectNavigate { margin-top: 3px;}

View file

@ -1,3 +1,4 @@
// Functions related to user authentication
function cookiesAreEnabled() {
// Test whether cookies are enabled by attempting to set a cookie and then
// change its value
@ -30,3 +31,376 @@ function setLoginVars() {
if (password.value.length==0) emptyPassword.value = '1';
else emptyPassword.value = '0';
}
// AJAX machinery
var isIe = (navigator.appName == "Microsoft Internet Explorer");
// AJAX machinery
var xhrObjects = new Array(); // An array of XMLHttpRequest objects
function XhrObject() { // Wraps a XmlHttpRequest object
this.freed = 1; // Is this xhr object already dealing with a request or not?
this.xhr = false;
if (window.XMLHttpRequest) this.xhr = new XMLHttpRequest();
else this.xhr = new ActiveXObject("Microsoft.XMLHTTP");
this.hook = ''; /* The ID of the HTML element in the page that will be
replaced by result of executing the Ajax request. */
this.onGet = ''; /* The name of a Javascript function to call once we
receive the result. */
this.info = {}; /* An associative array for putting anything else. */
}
function getAjaxChunk(pos) {
// This function is the callback called by the AJAX machinery (see function
// askAjaxChunk below) when an Ajax response is available.
// First, find back the correct XMLHttpRequest object
if ( (typeof(xhrObjects[pos]) != 'undefined') &&
(xhrObjects[pos].freed == 0)) {
var hook = xhrObjects[pos].hook;
if (xhrObjects[pos].xhr.readyState == 1) {
// The request has been initialized: display the waiting radar
var hookElem = document.getElementById(hook);
if (hookElem) hookElem.innerHTML = "<div align=\"center\"><img src=\"skyn/waiting.gif\"/><\/div>";
}
if (xhrObjects[pos].xhr.readyState == 4) {
// We have received the HTML chunk
var hookElem = document.getElementById(hook);
if (hookElem && (xhrObjects[pos].xhr.status == 200)) {
hookElem.innerHTML = xhrObjects[pos].xhr.responseText;
// Call a custom Javascript function if required
if (xhrObjects[pos].onGet) {
xhrObjects[pos].onGet(xhrObjects[pos], hookElem);
}
// Eval inner scripts if any.
var innerScripts = document.getElementsByName("appyHook");
for (var i=0; i<innerScripts.length; i++) {
eval(innerScripts[i].innerHTML);
}
xhrObjects[pos].freed = 1;
}
}
}
}
function askAjaxChunk(hook,mode,url,page,macro,params,beforeSend,onGet) {
/* This function will ask to get a chunk of HTML on the server through a
XMLHttpRequest. p_mode can be 'GET' or 'POST'. p_url is the URL of a
given server object. On this URL we will call the page "ajax.pt" that
will call a specific p_macro in a given p_page with some additional
p_params (must be an associative array) if required.
p_hook is the ID of the HTML element that will be filled with the HTML
result from the server.
p_beforeSend is a Javascript function to call before sending the request.
This function will get 2 args: the XMLHttpRequest object and the
p_params. This method can return, in a string, additional parameters to
send, ie: "&param1=blabla&param2=blabla".
p_onGet is a Javascript function to call when we will receive the answer.
This function will get 2 args, too: the XMLHttpRequest object and the
HTML node element into which the result has been inserted.
*/
// First, get a non-busy XMLHttpRequest object.
var pos = -1;
for (var i=0; i < xhrObjects.length; i++) {
if (xhrObjects[i].freed == 1) { pos = i; break; }
}
if (pos == -1) {
pos = xhrObjects.length;
xhrObjects[pos] = new XhrObject();
}
xhrObjects[pos].hook = hook;
xhrObjects[pos].onGet = onGet;
if (xhrObjects[pos].xhr) {
var rq = xhrObjects[pos];
rq.freed = 0;
// Construct parameters
var paramsFull = 'page=' + page + '&macro=' + macro;
if (params) {
for (var paramName in params)
paramsFull = paramsFull + '&' + paramName + '=' + params[paramName];
}
// Call beforeSend if required
if (beforeSend) {
var res = beforeSend(rq, params);
if (res) paramsFull = paramsFull + res;
}
// Construct the URL to call
var urlFull = url + '/skyn/ajax';
if (mode == 'GET') {
urlFull = urlFull + '?' + paramsFull;
}
// Perform the asynchronous HTTP GET or POST
rq.xhr.open(mode, urlFull, true);
if (mode == 'POST') {
// Set the correct HTTP headers
rq.xhr.setRequestHeader(
"Content-Type", "application/x-www-form-urlencoded");
rq.xhr.setRequestHeader("Content-length", paramsFull.length);
rq.xhr.setRequestHeader("Connection", "close");
rq.xhr.onreadystatechange = function(){ getAjaxChunk(pos); }
rq.xhr.send(paramsFull);
}
else if (mode == 'GET') {
rq.xhr.onreadystatechange = function() { getAjaxChunk(pos); }
if (window.XMLHttpRequest) { rq.xhr.send(null); }
else if (window.ActiveXObject) { rq.xhr.send(); }
}
}
}
/* The functions below wrap askAjaxChunk for getting specific content through
an Ajax request. */
function askQueryResult(hookId, objectUrl, contentType, searchName,
startNumber, sortKey, sortOrder, filterKey) {
// Sends an Ajax request for getting the result of a query.
var params = {'type_name': contentType, 'search': searchName,
'startNumber': startNumber};
if (sortKey) params['sortKey'] = sortKey;
if (sortOrder) params['sortOrder'] = sortOrder;
if (filterKey) {
var filterWidget = document.getElementById(hookId + '_' + filterKey);
if (filterWidget && filterWidget.value) {
params['filterKey'] = filterKey;
params['filterValue'] = filterWidget.value;
}
}
askAjaxChunk(hookId,'GET',objectUrl, 'result', 'queryResult', params);
}
function askObjectHistory(hookId, objectUrl, maxPerPage, startNumber) {
// Sends an Ajax request for getting the history of an object
var params = {'maxPerPage': maxPerPage, 'startNumber': startNumber};
askAjaxChunk(hookId, 'GET', objectUrl, 'page', 'objectHistory', params);
}
function askRefField(hookId, objectUrl, fieldName, innerRef, startNumber,
action, actionParams){
// Sends an Ajax request for getting the content of a reference field.
var startKey = hookId + '_startNumber';
var params = {'fieldName': fieldName, 'innerRef': innerRef, };
params[startKey] = startNumber;
if (action) params['action'] = action;
if (actionParams) {
for (key in actionParams) { params[key] = actionParams[key]; };
}
askAjaxChunk(hookId, 'GET', objectUrl, 'widgets/ref', 'viewContent',params);
}
function askComputedField(hookId, objectUrl, fieldName) {
// Sends an Ajax request for getting the content of a computed field
var params = {'fieldName': fieldName};
askAjaxChunk(hookId, 'GET', objectUrl, 'widgets/computed', 'viewContent', params);
}
// Function used by checkbox widgets for having radio-button-like behaviour
function toggleCheckbox(visibleCheckbox, hiddenBoolean) {
vis = document.getElementById(visibleCheckbox);
hidden = document.getElementById(hiddenBoolean);
if (vis.checked) hidden.value = 'True';
else hidden.value = 'False';
}
// Functions used for master/slave relationships between widgets
function getMasterValue(widget) {
// Returns an array of selected options in a select widget
res = new Array();
if (widget.type == 'checkbox') {
var mv = widget.checked + '';
mv = mv.charAt(0).toUpperCase() + mv.substr(1);
res.push(mv);
}
else { // SELECT widget
for (var i=0; i < widget.options.length; i++) {
if (widget.options[i].selected) res.push(widget.options[i].value);
}
}
return res;
}
function updateSlaves(masterValues, appyTypeId) {
// Given the value(s) selected in a master field, this function updates the
// state of all corresponding slaves.
var slaves = cssQuery('table.slave_' + appyTypeId);
for (var i=0; i< slaves.length; i++){
slaves[i].style.display = "none";
}
for (var i=0; i < masterValues.length; i++) {
var activeSlaves = cssQuery('table.slaveValue_' + appyTypeId + '_' + masterValues[i]);
for (var j=0; j < activeSlaves.length; j++){
activeSlaves[j].style.display = "";
}
}
}
// Function used for triggering a workflow transition
function triggerTransition(transitionId, msg) {
var theForm = document.getElementById('triggerTransitionForm');
theForm.workflow_action.value = transitionId;
if (!msg) {
theForm.submit();
}
else { // Ask the user to confirm.
askConfirm('form', 'triggerTransitionForm', msg);
}
}
function onDeleteObject(objectUid) {
f = document.getElementById('deleteForm');
f.objectUid.value = objectUid;
askConfirm('form', 'deleteForm', delete_confirm);
}
function toggleCookie(cookieId) {
// What is the state of this boolean (expanded/collapsed) cookie?
var state = readCookie(cookieId);
if ((state != 'collapsed') && (state != 'expanded')) {
// No cookie yet, create it.
createCookie(cookieId, 'collapsed');
state = 'collapsed';
}
var hook = document.getElementById(cookieId); // The hook is the part of
// the HTML document that needs to be shown or hidden.
var displayValue = 'none';
var newState = 'collapsed';
var imgSrc = 'skyn/expand.gif';
if (state == 'collapsed') {
// Show the HTML zone
displayValue = 'block';
imgSrc = 'skyn/collapse.gif';
newState = 'expanded';
}
// Update the corresponding HTML element
hook.style.display = displayValue;
var img = document.getElementById(cookieId + '_img');
img.src = imgSrc;
// Inverse the cookie value
createCookie(cookieId, newState);
}
// Function that allows to generate a document from a pod template.
function generatePodDocument(contextUid, fieldName, podFormat, queryData) {
var theForm = document.getElementsByName("podTemplateForm")[0];
theForm.objectUid.value = contextUid;
theForm.fieldName.value = fieldName;
theForm.podFormat.value = podFormat;
theForm.askAction.value = "False";
theForm.queryData.value = queryData;
var askActionWidget = document.getElementById(contextUid + '_' + fieldName);
if (askActionWidget && askActionWidget.checked) {
theForm.askAction.value = "True";
}
theForm.submit();
}
// Functions for opening and closing a popup
function openPopup(popupId, msg) {
// Put the message into the popup
var confirmElem = document.getElementById('appyConfirmText');
confirmElem.innerHTML = msg;
// Open the popup
var popup = document.getElementById(popupId);
// Put it at the right place on the screen
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || 0;
popup.style.top = (scrollTop + 150) + 'px';
popup.style.display = "block";
// Show the greyed zone
var greyed = document.getElementById('grey');
greyed.style.top = scrollTop + 'px';
greyed.style.display = "block";
}
function closePopup(popupId) {
// Close the popup
var popup = document.getElementById(popupId);
popup.style.display = "none";
// Hide the greyed zone
var greyed = document.getElementById('grey');
greyed.style.display = "none";
}
// Function triggered when an action needs to be confirmed by the user
function askConfirm(actionType, action, msg) {
/* Store the actionType (send a form, call an URL or call a script) and the
related action, and shows the confirm popup. If the user confirms, we
will perform the action. */
var confirmForm = document.getElementById('confirmActionForm');
confirmForm.actionType.value = actionType;
confirmForm.action.value = action;
openPopup("confirmActionPopup", msg);
}
// Function triggered when an action confirmed by the user must be performed
function doConfirm() {
// The user confirmed: perform the required action.
closePopup('confirmActionPopup');
var confirmForm = document.getElementById('confirmActionForm');
var actionType = confirmForm.actionType.value;
var action = confirmForm.action.value;
if (actionType == 'form') {
// We must submit the form whose id is in "action"
document.getElementById(action).submit();
}
else if (actionType == 'url') {
// We must go to the URL defined in "action"
window.location = action;
}
else if (actionType == 'script') {
// We must execute Javascript code in "action"
eval(action);
}
}
// Function that finally posts the edit form after the user has confirmed that
// she really wants to post it.
function postConfirmedEditForm() {
var theForm = document.getElementById('appyEditForm');
theForm.confirmed.value = "True";
theForm.submit();
}
// Function that shows or hides a tab. p_action is 'show' or 'hide'.
function manageTab(tabId, action) {
// Manage the tab content (show it or hide it)
var content = document.getElementById('tabcontent_' + tabId);
if (action == 'show') { content.style.display = 'table-row'; }
else { content.style.display = 'none'; }
// Manage the tab itself (show as selected or unselected)
var left = document.getElementById('tab_' + tabId + '_left');
var tab = document.getElementById('tab_' + tabId);
var right = document.getElementById('tab_' + tabId + '_right');
if (action == 'show') {
left.src = "skyn/tabLeft.png";
tab.style.backgroundImage = "url(skyn/tabBg.png)";
right.src = "skyn/tabRight.png";
}
if (action == 'hide') {
left.src = "skyn/tabLeftu.png";
tab.style.backgroundImage = "url(skyn/tabBgu.png)";
right.src = "skyn/tabRightu.png";
}
}
// Function used for displaying/hiding content of a tab
function showTab(tabId) {
// 1st, show the tab to show
manageTab(tabId, 'show');
// Compute the number of tabs.
var idParts = tabId.split('_');
var prefix = idParts[0] + '_';
// Store the currently selected tab in a cookie.
createCookie('tab_' + idParts[0], tabId);
var nbOfTabs = idParts[2]*1;
// Then, hide the other tabs.
for (var i=0; i<nbOfTabs; i++) {
var idTab = prefix + (i+1) + '_' + nbOfTabs;
if (idTab != tabId) {
manageTab(idTab, 'hide');
}
}
}
// Function that initializes the state of a tab
function initTab(cookieId, defaultValue) {
var toSelect = readCookie(cookieId);
if (!toSelect) { showTab(defaultValue) }
else { showTab(toSelect); }
}

252
gen/plone25/skin/calendar.css Executable file
View file

@ -0,0 +1,252 @@
/* The main calendar widget. DIV containing a table. */
.calendar {
position: relative;
display: none;
border: 1px solid;
border-color: #fff #000 #000 #fff;
font-size: 11px;
cursor: default;
background: Window;
color: WindowText;
font-family: tahoma,verdana,sans-serif;
}
.calendar table {
border: 1px solid;
border-color: #fff #000 #000 #fff;
font-size: 11px;
cursor: default;
background: Window;
color: WindowText;
font-family: tahoma,verdana,sans-serif;
}
/* Header part -- contains navigation buttons and day names. */
.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */
text-align: center;
padding: 1px;
border: 1px solid;
border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
background: ButtonFace;
}
.calendar .nav {
background: ButtonFace url(menuarrow.gif) no-repeat 100% 100%;
}
.calendar thead .title { /* This holds the current "month, year" */
font-weight: bold;
padding: 1px;
border: 1px solid #000;
background: ActiveCaption;
color: CaptionText;
text-align: center;
}
.calendar thead .headrow { /* Row <TR> containing navigation buttons */
}
.calendar thead .daynames { /* Row <TR> containing the day names */
}
.calendar thead .name { /* Cells <TD> containing the day names */
border-bottom: 1px solid ButtonShadow;
padding: 2px;
text-align: center;
background: ButtonFace;
color: ButtonText;
}
.calendar thead .weekend { /* How a weekend day name shows in header */
color: #f00;
}
.calendar thead .hilite { /* How do the buttons in header appear when hover */
border: 2px solid;
padding: 0px;
border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
}
.calendar thead .active { /* Active (pressed) buttons in header */
border-width: 1px;
padding: 2px 0px 0px 2px;
border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
}
/* The body part -- contains all the days in month. */
.calendar tbody .day { /* Cells <TD> containing month days dates */
width: 2em;
text-align: right;
padding: 2px 4px 2px 2px;
}
.calendar tbody .day.othermonth {
font-size: 80%;
color: #aaa;
}
.calendar tbody .day.othermonth.oweekend {
color: #faa;
}
.calendar table .wn {
padding: 2px 3px 2px 2px;
border-right: 1px solid ButtonShadow;
background: ButtonFace;
color: ButtonText;
}
.calendar tbody .rowhilite td {
background: Highlight;
color: HighlightText;
}
.calendar tbody td.hilite { /* Hovered cells <TD> */
padding: 1px 3px 1px 1px;
border-top: 1px solid #fff;
border-right: 1px solid #000;
border-bottom: 1px solid #000;
border-left: 1px solid #fff;
}
.calendar tbody td.active { /* Active (pressed) cells <TD> */
padding: 2px 2px 0px 2px;
border: 1px solid;
border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
}
.calendar tbody td.selected { /* Cell showing selected date */
font-weight: bold;
border: 1px solid;
border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
padding: 2px 2px 0px 2px;
background: ButtonFace;
color: ButtonText;
}
.calendar tbody td.weekend { /* Cells showing weekend days */
color: #f00;
}
.calendar tbody td.today { /* Cell showing today date */
font-weight: bold;
color: #00f;
}
.calendar tbody td.disabled { color: GrayText; }
.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */
visibility: hidden;
}
.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */
display: none;
}
/* The footer part -- status bar and "Close" button */
.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */
}
.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */
background: ButtonFace;
padding: 1px;
border: 1px solid;
border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
color: ButtonText;
text-align: center;
}
.calendar tfoot .hilite { /* Hover style for buttons in footer */
border-top: 1px solid #fff;
border-right: 1px solid #000;
border-bottom: 1px solid #000;
border-left: 1px solid #fff;
padding: 1px;
background: #e4e0d8;
}
.calendar tfoot .active { /* Active (pressed) style for buttons in footer */
padding: 2px 0px 0px 2px;
border-top: 1px solid #000;
border-right: 1px solid #fff;
border-bottom: 1px solid #fff;
border-left: 1px solid #000;
}
/* Combo boxes (menus that display months/years for direct selection) */
.calendar .combo {
position: absolute;
display: none;
width: 4em;
top: 0px;
left: 0px;
cursor: default;
border: 1px solid;
border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
background: Menu;
color: MenuText;
font-size: 90%;
padding: 1px;
z-index: 100;
}
.calendar .combo .label,
.calendar .combo .label-IEfix {
text-align: center;
display: block;
padding: 1px;
}
.calendar .combo .label-IEfix {
width: 4em;
}
.calendar .combo .active {
padding: 0px;
border: 1px solid #000;
}
.calendar .combo .hilite {
background: Highlight;
color: HighlightText;
}
.calendar td.time {
border-top: 1px solid ButtonShadow;
padding: 1px 0px;
text-align: center;
background-color: ButtonFace;
}
.calendar td.time .hour,
.calendar td.time .minute,
.calendar td.time .ampm {
padding: 0px 3px 0px 4px;
border: 1px solid #889;
font-weight: bold;
background-color: Menu;
}
.calendar td.time .ampm {
text-align: center;
}
.calendar td.time .colon {
padding: 0px 2px 0px 3px;
font-weight: bold;
}
.calendar td.time span.hilite {
border-color: #000;
background-color: Highlight;
color: HighlightText;
}
.calendar td.time span.active {
border-color: #f00;
background-color: #000;
color: #0f0;
}

BIN
gen/plone25/skin/calendar.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 B

140
gen/plone25/skin/calendar.js Executable file

File diff suppressed because one or more lines are too long

View file

@ -4,11 +4,8 @@
<tal:call tal:define="macroName options/macroName;
page python: options['page'];
contextObj python: options['contextObj'];
tool python: contextObj.getTool();
tool contextObj/getTool;
layoutType python:'view';
putils python: contextObj.plone_utils;
portal python: contextObj.portal_url.getPortalObject();
portal_url python: contextObj.portal_url();
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType='view');
phase phaseInfo/name;">
<metal:callMacro use-macro="python: page.macros[macroName]"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 476 B

After

Width:  |  Height:  |  Size: 475 B

View file

@ -1,65 +1,37 @@
<tal:edit metal:define-macro="master"
define="contextObj python:context.getParentNode();
errors request/errors | python:{};
layoutType python:'edit';
layout python: contextObj.getPageLayout(layoutType);
tool contextObj/getTool;
appFolder tool/getAppFolder;
appName appFolder/getId;
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType=layoutType);
phase phaseInfo/name;
page request/page|python:'main';
cssJs python: contextObj.getCssAndJs(contextObj.getAppyTypes(layoutType, page), layoutType);
confirmMsg request/confirmMsg | nothing;">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
metal:use-macro="here/main_template/macros/master">
<tal:comment replace="nothing">Disable the Standard Plone green tab</tal:comment>
<div metal:fill-slot="top_slot">
<metal:block metal:use-macro="here/global_defines/macros/defines" />
<div tal:define="dummy python:request.set('disable_border', 1)" />
</div>
<tal:main define="tool context/getTool">
<html metal:use-macro="context/skyn/template/macros/main">
<metal:fill fill-slot="content"
tal:define="contextObj python:context.getParentNode();
errors request/errors | python:{};
layoutType python:'edit';
layout python: contextObj.getPageLayout(layoutType);
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType=layoutType);
phase phaseInfo/name;
page request/page|python:'main';
cssJs python: contextObj.getCssAndJs(contextObj.getAppyTypes(layoutType, page), layoutType);
confirmMsg request/confirmMsg | nothing;">
<tal:comment replace="nothing">Include type-specific CSS and JS.</tal:comment>
<metal:js fill-slot="javascript_head_slot">
<tal:js condition="cssJs/js" repeat="jsFile cssJs/js">
<script type="text/javascript" charset="iso-8859-1"
tal:condition="python:exists('portal/%s' % jsFile)"
tal:attributes="src string:$portal_url/$jsFile">
</script>
</tal:js>
</metal:js>
<metal:css fill-slot="css_slot">
<tal:css condition="cssJs/css" repeat="cssFile cssJs/css">
<style type="text/css" media="all"
tal:condition="python:exists('portal/%s' % cssFile)"
tal:content="structure string:<!-- @import url($portal_url/$cssFile); -->">
</style>
</tal:css>
</metal:css>
<link tal:repeat="cssFile cssJs/css" rel="stylesheet" type="text/css"
tal:attributes="href string:$appUrl/skyn/$cssFile"/>
<script tal:repeat="jsFile cssJs/js" type="text/javascript"
tal:attributes="src string:$appUrl/skyn/$jsFile"></script>
<body>
<metal:fill fill-slot="main">
<metal:prologue use-macro="here/skyn/page/macros/prologue"/>
<form id="appyEditForm" name="appyEditForm" method="post" enctype="multipart/form-data"
tal:attributes="action python: contextObj.absolute_url()+'/skyn/do';
class python: test(confirmMsg, 'atBaseEditForm', 'enableUnloadProtection atBaseEditForm')">
<input type="hidden" name="action" value="Update"/>
<input type="hidden" name="page" tal:attributes="value page"/>
<input type="hidden" name="nav" tal:attributes="value request/nav|nothing"/>
<input type="hidden" name="is_new" tal:attributes="value contextObj/isTemporary"/>
<input type="hidden" name="confirmed" value="False"/>
<metal:show use-macro="here/skyn/page/macros/show"/>
</form>
<script tal:condition="confirmMsg"
tal:content="python: 'askConfirm(\'script\', \'postConfirmedEditForm()\', \'%s\')' % confirmMsg">
</script>
<metal:footer use-macro="here/skyn/page/macros/footer"/>
</metal:fill>
</body>
<metal:prologue use-macro="here/skyn/page/macros/prologue"/>
<form id="appyEditForm" name="appyEditForm" method="post" enctype="multipart/form-data"
tal:attributes="action python: contextObj.absolute_url()+'/skyn/do';
class python: test(confirmMsg, 'atBaseEditForm', 'enableUnloadProtection atBaseEditForm')">
<input type="hidden" name="action" value="Update"/>
<input type="hidden" name="page" tal:attributes="value page"/>
<input type="hidden" name="nav" tal:attributes="value request/nav|nothing"/>
<input type="hidden" name="is_new" tal:attributes="value contextObj/isTemporary"/>
<input type="hidden" name="confirmed" value="False"/>
<metal:show use-macro="here/skyn/page/macros/show"/>
</form>
<script tal:condition="confirmMsg"
tal:content="python: 'askConfirm(\'script\', \'postConfirmedEditForm()\', \'%s\')' % confirmMsg">
</script>
<metal:footer use-macro="here/skyn/page/macros/footer"/>
</metal:fill>
</html>
</tal:edit>
</tal:main>

View file

@ -83,14 +83,14 @@
<tr>
<th tal:repeat="columnHeader python: importElems[0]">
<img tal:condition="python: repeat['columnHeader'].number() == 1"
tal:attributes="src string:$portal_url/skyn/eye.png;
tal:attributes="src string:$appUrl/skyn/eye.png;
title python: tool.translate('import_show_hide')"
style="cursor:pointer" onClick="toggleViewableElements()" align="left" />
<span tal:replace="columnHeader"/>
</th>
<th tal:content="python: tool.translate('ref_actions')"></th>
<th width="20px"><img
tal:attributes="src string: $portal_url/skyn/select_elems.png;
tal:attributes="src string: $appUrl/skyn/select_elems.png;
title python: tool.translate('select_delesect')"
onClick="toggleCheckboxes()" style="cursor:pointer"/>
</tr>

View file

@ -2,46 +2,46 @@
<tal:comment replace="nothing">
Buttons for navigating among a list of elements (next, back, first, last, etc).
</tal:comment>
<table cellpadding="0" cellspacing="0" class="appyNav"
<table class="listNavigate"
tal:define="mustSortAndFilter python: ajaxHookId == 'queryResult';
sortKey sortKey|python:'';
sortOrder sortOrder|python:'';
filterKey filterKey|python:'';
sortAndFilter python: test(mustSortAndFilter, ',\'%s\',\'%s\',\'%s\'' % (sortKey, sortOrder, filterKey), '')">
<tr>
<tr valign="middle">
<tal:comment replace="nothing">Go to the first page</tal:comment>
<td><img style="cursor:pointer" tal:condition="python: (startNumber != 0) and (startNumber != batchSize)"
tal:attributes="src string: $portal_url/skyn/arrowLeftDouble.png;
<td tal:condition="python: (startNumber != 0) and (startNumber != batchSize)"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/skyn/arrowLeftDouble.png;
title python: tool.translate('goto_first');
onClick python: navBaseCall.replace('**v**', '0'+sortAndFilter)"/></td>
<tal:comment replace="nothing">Go to the previous page</tal:comment>
<td><img style="cursor:pointer" tal:condition="python: startNumber != 0"
tal:define="sNumber python: startNumber - batchSize"
tal:attributes="src string: $portal_url/skyn/arrowLeftSimple.png;
title python: tool.translate('goto_previous');
onClick python: navBaseCall.replace('**v**', str(sNumber)+sortAndFilter)"/></td>
<td tal:define="sNumber python: startNumber - batchSize"
tal:condition="python: startNumber != 0"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/skyn/arrowLeftSimple.png;
title python: tool.translate('goto_previous');
onClick python: navBaseCall.replace('**v**', str(sNumber)+sortAndFilter)"/></td>
<tal:comment replace="nothing">Explain which elements are currently shown</tal:comment>
<td class="discreet" valign="middle">&nbsp;
<td class="discreet">&nbsp;
<span tal:replace="python: startNumber+1"/>
<img tal:attributes="src string: $portal_url/skyn/to.png"/>
<img tal:attributes="src string: $appUrl/skyn/to.png"/>
<span tal:replace="python: startNumber+len(objs)"/>&nbsp;<b>//</b>
<span tal:replace="python: totalNumber"/>&nbsp;&nbsp;
</td>
<tal:comment replace="nothing">Go to the next page</tal:comment>
<td><img style="cursor:pointer" tal:condition="python: sNumber &lt; totalNumber"
tal:define="sNumber python: startNumber + batchSize"
tal:attributes="src string: $portal_url/skyn/arrowRightSimple.png;
title python: tool.translate('goto_next');
onClick python: navBaseCall.replace('**v**', str(sNumber)+sortAndFilter)"/></td>
<td tal:define="sNumber python: startNumber + batchSize"
tal:condition="python: sNumber &lt; totalNumber"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/skyn/arrowRightSimple.png;
title python: tool.translate('goto_next');
onClick python: navBaseCall.replace('**v**', str(sNumber)+sortAndFilter)"/></td>
<tal:comment replace="nothing">Go to the last page</tal:comment>
<td><img style="cursor:pointer" tal:condition="python: (startNumber != sNumber) and (startNumber != sNumber-batchSize)"
tal:define="lastPageIsIncomplete python: totalNumber % batchSize;
<td tal:define="lastPageIsIncomplete python: totalNumber % batchSize;
nbOfCompletePages python: totalNumber/batchSize;
nbOfCountedPages python: test(lastPageIsIncomplete, nbOfCompletePages, nbOfCompletePages-1);
sNumber python: (nbOfCountedPages*batchSize)"
tal:attributes="src string: $portal_url/skyn/arrowRightDouble.png;
title python: tool.translate('goto_last');
onClick python: navBaseCall.replace('**v**', str(sNumber)+sortAndFilter)"/></td>
tal:condition="python: (startNumber != sNumber) and (startNumber != sNumber-batchSize)"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/skyn/arrowRightDouble.png;
title python: tool.translate('goto_last');
onClick python: navBaseCall.replace('**v**', str(sNumber)+sortAndFilter)"/></td>
</tr>
</table>
</div>
@ -51,7 +51,7 @@
Buttons for going to next/previous elements if this one is among bunch of referenced or searched objects.
currentNumber starts with 1.
</tal:comment>
<table cellpadding="0" cellspacing="0"
<table class="objectNavigate"
tal:define="navInfo tool/getNavigationInfo;
currentNumber navInfo/currentNumber;
totalNumber navInfo/totalNumber;
@ -61,32 +61,32 @@
lastUrl navInfo/lastUrl;
sourceUrl navInfo/sourceUrl;
backText navInfo/backText">
<tr>
<tr valign="middle">
<tal:comment replace="nothing">Go to the source URL (search or referred object)</tal:comment>
<td><a tal:condition="sourceUrl" tal:attributes="href sourceUrl"><img style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/gotoSource.png;
title python: backText + ' : ' + tool.translate('goto_source')"/></a></td>
<td tal:condition="sourceUrl"><a tal:attributes="href sourceUrl"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/skyn/gotoSource.png;
title python: backText + ' : ' + tool.translate('goto_source')"/></a></td>
<tal:comment replace="nothing">Go to the first page</tal:comment>
<td><a tal:condition="firstUrl" tal:attributes="href firstUrl"><img style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/arrowLeftDouble.png;
title python: tool.translate('goto_first')"/></a></td>
<td tal:condition="firstUrl"><a tal:attributes="href firstUrl"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/skyn/arrowLeftDouble.png;
title python: tool.translate('goto_first')"/></a></td>
<tal:comment replace="nothing">Go to the previous page</tal:comment>
<td><a tal:condition="previousUrl" tal:attributes="href previousUrl"><img style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/arrowLeftSimple.png;
title python: tool.translate('goto_previous')"/></a></td>
<td tal:condition="previousUrl"><a tal:attributes="href previousUrl"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/skyn/arrowLeftSimple.png;
title python: tool.translate('goto_previous')"/></a></td>
<tal:comment replace="nothing">Explain which element is currently shown</tal:comment>
<td class="discreet" valign="middle">&nbsp;
<td class="discreet">&nbsp;
<span tal:replace="python: currentNumber"/>&nbsp;<b>//</b>
<span tal:replace="python: totalNumber"/>&nbsp;&nbsp;
</td>
<tal:comment replace="nothing">Go to the next page</tal:comment>
<td><a tal:condition="python: nextUrl" tal:attributes="href nextUrl"><img style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/arrowRightSimple.png;
title python: tool.translate('goto_next')"/></a></td>
<td tal:condition="python: nextUrl"><a tal:attributes="href nextUrl"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/skyn/arrowRightSimple.png;
title python: tool.translate('goto_next')"/></a></td>
<tal:comment replace="nothing">Go to the last page</tal:comment>
<td><a tal:condition="lastUrl" tal:attributes="href lastUrl"><img style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/arrowRightDouble.png;
title python: tool.translate('goto_last')"/></a></td>
<td tal:condition="lastUrl"><a tal:attributes="href lastUrl"><img style="cursor:pointer"
tal:attributes="src string: $appUrl/skyn/arrowRightDouble.png;
title python: tool.translate('goto_last')"/></a></td>
</tr>
</table>
</div>
@ -97,11 +97,11 @@
</tal:comment>
<metal:sortAndFilter define-macro="sortAndFilter" tal:define="fieldName widget/name">
<tal:sort condition="sortable">
<img tal:attributes="src string: $portal_url/skyn/sortDown.gif;
<img tal:attributes="src string: $appUrl/skyn/sortDown.gif;
onClick python: navBaseCall.replace('**v**', '0,\'%s\',\'asc\',\'%s\'' % (fieldName, filterKey))"
tal:condition="python: (sortKey != fieldName) or (sortOrder == 'desc')"
style="cursor:pointer"/>
<img tal:attributes="src string: $portal_url/skyn/sortUp.gif;
<img tal:attributes="src string: $appUrl/skyn/sortUp.gif;
onClick python: navBaseCall.replace('**v**', '0,\'%s\',\'desc\',\'%s\'' % (fieldName, filterKey))"
tal:condition="python: (sortKey != fieldName) or (sortOrder == 'asc')"
style="cursor:pointer"/>
@ -110,7 +110,7 @@
<input type="text" size="7"
tal:attributes="id python: '%s_%s' % (ajaxHookId, fieldName);
value python: test(filterKey == fieldName, filterValue, '')"/>
<img tal:attributes="src string: $portal_url/skyn/funnel.png;
<img tal:attributes="src string: $appUrl/skyn/funnel.png;
onClick python: navBaseCall.replace('**v**', '0,\'%s\',\'%s\',\'%s\'' % (sortKey, sortOrder, fieldName))"
style="cursor:pointer"/>
</tal:filter>

View file

@ -2,374 +2,9 @@
This macro contains global page-related Javascripts.
</tal:comment>
<div metal:define-macro="prologue">
<tal:comment replace="nothing">Global elements used in every page.</tal:comment>
<tal:comment replace="nothing">Javascript messages</tal:comment>
<script language="javascript" tal:content="tool/getJavascriptMessages"></script>
<tal:comment replace="nothing">"Static" javascripts</tal:comment>
<script language="javascript">
<!--
var isIe = (navigator.appName == "Microsoft Internet Explorer");
// AJAX machinery
var xhrObjects = new Array(); // An array of XMLHttpRequest objects
function XhrObject() { // Wraps a XmlHttpRequest object
this.freed = 1; // Is this xhr object already dealing with a request or not?
this.xhr = false;
if (window.XMLHttpRequest) this.xhr = new XMLHttpRequest();
else this.xhr = new ActiveXObject("Microsoft.XMLHTTP");
this.hook = ''; /* The ID of the HTML element in the page that will be
replaced by result of executing the Ajax request. */
this.onGet = ''; /* The name of a Javascript function to call once we
receive the result. */
this.info = {}; /* An associative array for putting anything else. */
}
function getAjaxChunk(pos) {
// This function is the callback called by the AJAX machinery (see function
// askAjaxChunk below) when an Ajax response is available.
// First, find back the correct XMLHttpRequest object
if ( (typeof(xhrObjects[pos]) != 'undefined') &&
(xhrObjects[pos].freed == 0)) {
var hook = xhrObjects[pos].hook;
if (xhrObjects[pos].xhr.readyState == 1) {
// The request has been initialized: display the waiting radar
var hookElem = document.getElementById(hook);
if (hookElem) hookElem.innerHTML = "<div align=\"center\"><img src=\"skyn/waiting.gif\"/><\/div>";
}
if (xhrObjects[pos].xhr.readyState == 4) {
// We have received the HTML chunk
var hookElem = document.getElementById(hook);
if (hookElem && (xhrObjects[pos].xhr.status == 200)) {
hookElem.innerHTML = xhrObjects[pos].xhr.responseText;
// Call a custom Javascript function if required
if (xhrObjects[pos].onGet) {
xhrObjects[pos].onGet(xhrObjects[pos], hookElem);
}
// Eval inner scripts if any.
var innerScripts = document.getElementsByName("appyHook");
for (var i=0; i<innerScripts.length; i++) {
eval(innerScripts[i].innerHTML);
}
xhrObjects[pos].freed = 1;
}
}
}
}
function askAjaxChunk(hook,mode,url,page,macro,params,beforeSend,onGet) {
/* This function will ask to get a chunk of HTML on the server through a
XMLHttpRequest. p_mode can be 'GET' or 'POST'. p_url is the URL of a
given server object. On this URL we will call the page "ajax.pt" that
will call a specific p_macro in a given p_page with some additional
p_params (must be an associative array) if required.
p_hook is the ID of the HTML element that will be filled with the HTML
result from the server.
p_beforeSend is a Javascript function to call before sending the request.
This function will get 2 args: the XMLHttpRequest object and the
p_params. This method can return, in a string, additional parameters to
send, ie: "&param1=blabla&param2=blabla".
p_onGet is a Javascript function to call when we will receive the answer.
This function will get 2 args, too: the XMLHttpRequest object and the
HTML node element into which the result has been inserted.
*/
// First, get a non-busy XMLHttpRequest object.
var pos = -1;
for (var i=0; i < xhrObjects.length; i++) {
if (xhrObjects[i].freed == 1) { pos = i; break; }
}
if (pos == -1) {
pos = xhrObjects.length;
xhrObjects[pos] = new XhrObject();
}
xhrObjects[pos].hook = hook;
xhrObjects[pos].onGet = onGet;
if (xhrObjects[pos].xhr) {
var rq = xhrObjects[pos];
rq.freed = 0;
// Construct parameters
var paramsFull = 'page=' + page + '&macro=' + macro;
if (params) {
for (var paramName in params)
paramsFull = paramsFull + '&' + paramName + '=' + params[paramName];
}
// Call beforeSend if required
if (beforeSend) {
var res = beforeSend(rq, params);
if (res) paramsFull = paramsFull + res;
}
// Construct the URL to call
var urlFull = url + '/skyn/ajax';
if (mode == 'GET') {
urlFull = urlFull + '?' + paramsFull;
}
// Perform the asynchronous HTTP GET or POST
rq.xhr.open(mode, urlFull, true);
if (mode == 'POST') {
// Set the correct HTTP headers
rq.xhr.setRequestHeader(
"Content-Type", "application/x-www-form-urlencoded");
rq.xhr.setRequestHeader("Content-length", paramsFull.length);
rq.xhr.setRequestHeader("Connection", "close");
rq.xhr.onreadystatechange = function(){ getAjaxChunk(pos); }
rq.xhr.send(paramsFull);
}
else if (mode == 'GET') {
rq.xhr.onreadystatechange = function() { getAjaxChunk(pos); }
if (window.XMLHttpRequest) { rq.xhr.send(null); }
else if (window.ActiveXObject) { rq.xhr.send(); }
}
}
}
/* The functions below wrap askAjaxChunk for getting specific content through
an Ajax request. */
function askQueryResult(hookId, objectUrl, contentType, searchName,
startNumber, sortKey, sortOrder, filterKey) {
// Sends an Ajax request for getting the result of a query.
var params = {'type_name': contentType, 'search': searchName,
'startNumber': startNumber};
if (sortKey) params['sortKey'] = sortKey;
if (sortOrder) params['sortOrder'] = sortOrder;
if (filterKey) {
var filterWidget = document.getElementById(hookId + '_' + filterKey);
if (filterWidget && filterWidget.value) {
params['filterKey'] = filterKey;
params['filterValue'] = filterWidget.value;
}
}
askAjaxChunk(hookId,'GET',objectUrl, 'result', 'queryResult', params);
}
function askObjectHistory(hookId, objectUrl, maxPerPage, startNumber) {
// Sends an Ajax request for getting the history of an object
var params = {'maxPerPage': maxPerPage, 'startNumber': startNumber};
askAjaxChunk(hookId, 'GET', objectUrl, 'page', 'objectHistory', params);
}
function askRefField(hookId, objectUrl, fieldName, innerRef, startNumber,
action, actionParams){
// Sends an Ajax request for getting the content of a reference field.
var startKey = hookId + '_startNumber';
var params = {'fieldName': fieldName, 'innerRef': innerRef, };
params[startKey] = startNumber;
if (action) params['action'] = action;
if (actionParams) {
for (key in actionParams) { params[key] = actionParams[key]; };
}
askAjaxChunk(hookId, 'GET', objectUrl, 'widgets/ref', 'viewContent',params);
}
function askComputedField(hookId, objectUrl, fieldName) {
// Sends an Ajax request for getting the content of a computed field
var params = {'fieldName': fieldName};
askAjaxChunk(hookId, 'GET', objectUrl, 'widgets/computed', 'viewContent',
params);
}
// Function used by checkbox widgets for having radio-button-like behaviour
function toggleCheckbox(visibleCheckbox, hiddenBoolean) {
vis = document.getElementById(visibleCheckbox);
hidden = document.getElementById(hiddenBoolean);
if (vis.checked) hidden.value = 'True';
else hidden.value = 'False';
}
// Functions used for master/slave relationships between widgets
function getMasterValue(widget) {
// Returns an array of selected options in a select widget
res = new Array();
if (widget.type == 'checkbox') {
var mv = widget.checked + '';
mv = mv.charAt(0).toUpperCase() + mv.substr(1);
res.push(mv);
}
else { // SELECT widget
for (var i=0; i < widget.options.length; i++) {
if (widget.options[i].selected) res.push(widget.options[i].value);
}
}
return res;
}
function updateSlaves(masterValues, appyTypeId) {
// Given the value(s) selected in a master field, this function updates the
// state of all corresponding slaves.
var slaves = cssQuery('table.slave_' + appyTypeId);
for (var i=0; i< slaves.length; i++){
slaves[i].style.display = "none";
}
for (var i=0; i < masterValues.length; i++) {
var activeSlaves = cssQuery('table.slaveValue_' + appyTypeId + '_' + masterValues[i]);
for (var j=0; j < activeSlaves.length; j++){
activeSlaves[j].style.display = "";
}
}
}
// Function used for triggering a workflow transition
function triggerTransition(transitionId, msg) {
var theForm = document.getElementById('triggerTransitionForm');
theForm.workflow_action.value = transitionId;
if (!msg) {
theForm.submit();
}
else { // Ask the user to confirm.
askConfirm('form', 'triggerTransitionForm', msg);
}
}
function onDeleteObject(objectUid) {
f = document.getElementById('deleteForm');
f.objectUid.value = objectUid;
askConfirm('form', 'deleteForm', delete_confirm);
}
function toggleCookie(cookieId) {
// What is the state of this boolean (expanded/collapsed) cookie?
var state = readCookie(cookieId);
if ((state != 'collapsed') && (state != 'expanded')) {
// No cookie yet, create it.
createCookie(cookieId, 'collapsed');
state = 'collapsed';
}
var hook = document.getElementById(cookieId); // The hook is the part of
// the HTML document that needs to be shown or hidden.
var displayValue = 'none';
var newState = 'collapsed';
var imgSrc = 'skyn/expand.gif';
if (state == 'collapsed') {
// Show the HTML zone
displayValue = 'block';
imgSrc = 'skyn/collapse.gif';
newState = 'expanded';
}
// Update the corresponding HTML element
hook.style.display = displayValue;
var img = document.getElementById(cookieId + '_img');
img.src = imgSrc;
// Inverse the cookie value
createCookie(cookieId, newState);
}
// Function that allows to generate a document from a pod template.
function generatePodDocument(contextUid, fieldName, podFormat, queryData) {
var theForm = document.getElementsByName("podTemplateForm")[0];
theForm.objectUid.value = contextUid;
theForm.fieldName.value = fieldName;
theForm.podFormat.value = podFormat;
theForm.askAction.value = "False";
theForm.queryData.value = queryData;
var askActionWidget = document.getElementById(contextUid + '_' + fieldName);
if (askActionWidget && askActionWidget.checked) {
theForm.askAction.value = "True";
}
theForm.submit();
}
// Functions for opening and closing a popup
function openPopup(popupId, msg) {
// Put the message into the popup
var confirmElem = document.getElementById('appyConfirmText');
confirmElem.innerHTML = msg;
// Open the popup
var popup = document.getElementById(popupId);
// Put it at the right place on the screen
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || 0;
popup.style.top = (scrollTop + 150) + 'px';
popup.style.display = "block";
// Show the greyed zone
var greyed = document.getElementById('appyGrey');
greyed.style.top = scrollTop + 'px';
greyed.style.display = "block";
}
function closePopup(popupId) {
// Close the popup
var popup = document.getElementById(popupId);
popup.style.display = "none";
// Hide the greyed zone
var greyed = document.getElementById('appyGrey');
greyed.style.display = "none";
}
// Function triggered when an action needs to be confirmed by the user
function askConfirm(actionType, action, msg) {
/* Store the actionType (send a form, call an URL or call a script) and the
related action, and shows the confirm popup. If the user confirms, we
will perform the action. */
var confirmForm = document.getElementById('confirmActionForm');
confirmForm.actionType.value = actionType;
confirmForm.action.value = action;
openPopup("confirmActionPopup", msg);
}
// Function triggered when an action confirmed by the user must be performed
function doConfirm() {
// The user confirmed: perform the required action.
closePopup('confirmActionPopup');
var confirmForm = document.getElementById('confirmActionForm');
var actionType = confirmForm.actionType.value;
var action = confirmForm.action.value;
if (actionType == 'form') {
// We must submit the form whose id is in "action"
document.getElementById(action).submit();
}
else if (actionType == 'url') {
// We must go to the URL defined in "action"
window.location = action;
}
else if (actionType == 'script') {
// We must execute Javascript code in "action"
eval(action);
}
}
// Function that finally posts the edit form after the user has confirmed that
// she really wants to post it.
function postConfirmedEditForm() {
var theForm = document.getElementById('appyEditForm');
theForm.confirmed.value = "True";
theForm.submit();
}
// Function that shows or hides a tab. p_action is 'show' or 'hide'.
function manageTab(tabId, action) {
// Manage the tab content (show it or hide it)
var content = document.getElementById('tabcontent_' + tabId);
if (action == 'show') { content.style.display = 'table-row'; }
else { content.style.display = 'none'; }
// Manage the tab itself (show as selected or unselected)
var left = document.getElementById('tab_' + tabId + '_left');
var tab = document.getElementById('tab_' + tabId);
var right = document.getElementById('tab_' + tabId + '_right');
if (action == 'show') {
left.src = "skyn/tabLeft.png";
tab.style.backgroundImage = "url(skyn/tabBg.png)";
right.src = "skyn/tabRight.png";
}
if (action == 'hide') {
left.src = "skyn/tabLeftu.png";
tab.style.backgroundImage = "url(skyn/tabBgu.png)";
right.src = "skyn/tabRightu.png";
}
}
// Function used for displaying/hiding content of a tab
function showTab(tabId) {
// 1st, show the tab to show
manageTab(tabId, 'show');
// Compute the number of tabs.
var idParts = tabId.split('_');
var prefix = idParts[0] + '_';
// Store the currently selected tab in a cookie.
createCookie('tab_' + idParts[0], tabId);
var nbOfTabs = idParts[2]*1;
// Then, hide the other tabs.
for (var i=0; i<nbOfTabs; i++) {
var idTab = prefix + (i+1) + '_' + nbOfTabs;
if (idTab != tabId) {
manageTab(idTab, 'hide');
}
}
}
// Function that initializes the state of a tab
function initTab(cookieId, defaultValue) {
var toSelect = readCookie(cookieId);
if (!toSelect) { showTab(defaultValue) }
else { showTab(toSelect); }
}
-->
</script>
<tal:comment replace="nothing">Global form for deleting an object</tal:comment>
<form id="deleteForm" method="post" action="skyn/do">
<input type="hidden" name="action" value="Delete"/>
@ -405,14 +40,14 @@
layoutType We must know if we must render the widgets in a "view",
"edit" or "cell" layout
</tal:comment>
<table metal:define-macro="widgets" cellpadding="0" cellspacing="0"
<table metal:define-macro="widgets"
tal:attributes="width layout/width">
<tr tal:repeat="widget python: contextObj.getGroupedAppyTypes(layoutType, page)">
<td tal:condition="python: widget['type'] == 'group'">
<metal:call use-macro="portal/skyn/widgets/show/macros/group"/>
<metal:call use-macro="app/skyn/widgets/show/macros/group"/>
</td>
<td tal:condition="python: widget['type'] != 'group'">
<metal:call use-macro="portal/skyn/widgets/show/macros/field"/>
<metal:call use-macro="app/skyn/widgets/show/macros/field"/>
</td>
</tr>
</table>
@ -501,7 +136,7 @@
tal:content="python: tool.translate(contextObj.getWorkflowLabel(stateInfo['name']))">
</td>
<td tal:condition="python: stateInfo['name'] != states[-1]['name']">
<img tal:attributes="src string: $portal_url/skyn/nextState.png"/>
<img tal:attributes="src string: $appUrl/skyn/nextState.png"/>
</td>
</tal:state>
</tr>
@ -558,15 +193,13 @@
tal:condition="not: contextObj/isTemporary">
<tal:comment replace="nothing">Information that is common to all tabs (object title, state, etc)</tal:comment>
<table width="100%" tal:condition="showCommonInfo" class="appyCommonInfo">
<tr valign="bottom" align="left">
<tal:comment replace="nothing">Title and state</tal:comment>
<td width="80%">
<b class="appyTitle" tal:content="contextObj/title_or_id"></b>
</td>
<table width="100%" tal:condition="showCommonInfo" class="summary">
<tr>
<tal:comment replace="nothing">Title</tal:comment>
<td colspan="2" class="objectTitle" tal:content="contextObj/title_or_id"></td>
</tr>
<tr align="left">
<td class="documentByLine" colspan="2">
<tr class="underTitle">
<td class="by" colspan="2">
<tal:comment replace="nothing">Creator and last modification date</tal:comment>
<tal:comment replace="nothing">Plus/minus icon for accessing history</tal:comment>
<tal:accessHistory condition="hasHistory">
@ -579,34 +212,32 @@
<tal:comment replace="nothing">Show document creator</tal:comment>
<tal:creator condition="creator"
define="author python:contextObj.portal_membership.getMemberInfo(creator)">
<span class="documentAuthor" i18n:domain="plone" i18n:translate="label_by_author">
by <a tal:attributes="href string:${portal_url}/author/${creator}"
tal:content="python:author and author['fullname'] or creator"
tal:omit-tag="not:author" i18n:name="author"/>
<span i18n:domain="plone" i18n:translate="label_by_author">
by <span tal:content="python:author and author['fullname'] or creator"
tal:omit-tag="not:author" i18n:name="author"/>
&mdash;
</span>
</tal:creator>
<tal:comment replace="nothing">Show last modification date</tal:comment>
<span i18n:translate="box_last_modified" i18n:domain="plone"></span>
<span tal:replace="python:contextObj.restrictedTraverse('@@plone').toLocalizedTime(contextObj.ModificationDate(),long_format=1)"></span>
</td>
</tr>
<tal:comment replace="nothing">Object history</tal:comment>
<tr tal:condition="hasHistory" align="left">
<tr tal:condition="hasHistory">
<td colspan="2">
<span id="appyHistory"
tal:attributes="style python:test(historyExpanded, 'display:block', 'display:none')">
<div tal:define="ajaxHookId python: contextObj.UID() + '_history';"
tal:attributes="id ajaxHookId">
<script language="javascript" tal:content="python: 'askObjectHistory(\'%s\',\'%s\',%d,0)' % (ajaxHookId, contextObj.absolute_url(),historyMaxPerPage)">
<script tal:content="python: 'askObjectHistory(\'%s\',\'%s\',%d,0)' % (ajaxHookId, contextObj.absolute_url(),historyMaxPerPage)">
</script>
</div>
</span>
</td>
</tr>
<tal:comment replace="nothing">Workflow-related information and actions</tal:comment>
<tr tal:condition="python: showWorkflow and contextObj.getWorkflowLabel()" align="left">
<td colspan="2" class="appyWorkflow">
<tr tal:condition="python: showWorkflow and contextObj.getWorkflowLabel()">
<td colspan="2" class="workflow">
<table width="100%">
<tr>
<td><metal:states use-macro="here/skyn/page/macros/states"/></td>
@ -622,7 +253,7 @@
The page footer.
</tal:comment>
<metal:footer define-macro="footer">
<tal:dummy define="messages putils/showPortalMessages"/>
<tal:dummy define="messages app/plone_utils/showPortalMessages"/>
<script language="javascript">
<!--
// When the current page is loaded, we must set the correct state for all slave fields.
@ -674,12 +305,12 @@
<tal:button condition="isEdit">
<input type="image" class="imageInput" style="cursor:pointer" name="buttonPrevious"
title="label_previous" i18n:attributes="title" i18n:domain="plone"
tal:attributes="src string:$portal_url/skyn/previous.png"/>
tal:attributes="src string:$appUrl/skyn/previous.png"/>
<input type="hidden" name="previousPage" tal:attributes="value previousPage"/>
</tal:button>
<tal:link condition="not: isEdit">
<a tal:attributes="href python: contextObj.getUrl(page=previousPage)">
<img tal:attributes="src string:$portal_url/skyn/previous.png"
<img tal:attributes="src string:$appUrl/skyn/previous.png"
title="label_previous" i18n:attributes="title" i18n:domain="plone"/>
</a>
</tal:link>
@ -688,38 +319,38 @@
<tal:save condition="python: isEdit and pageInfo['showSave']">
<input type="image" class="imageInput" style="cursor:pointer" name="buttonOk"
title="label_save" i18n:attributes="title" i18n:domain="plone"
tal:attributes="src string:$portal_url/skyn/save.png"/>
tal:attributes="src string:$appUrl/skyn/save.png"/>
</tal:save>
<tal:cancel condition="python: isEdit and pageInfo['showCancel']">
<input type="image" class="imageInput" style="cursor:pointer" name="buttonCancel"
title="label_cancel" i18n:attributes="title" i18n:domain="plone"
tal:attributes="src string:$portal_url/skyn/cancel.png"/>
tal:attributes="src string:$appUrl/skyn/cancel.png"/>
</tal:cancel>
<tal:edit condition="python: not isEdit and pageInfo['showOnEdit']">
<img title="Edit" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
tal:attributes="onClick python: 'href: window.location=\'%s\'' % contextObj.getUrl(mode='edit', page=page);
src string: $portal_url/skyn/editBig.png"
tal:condition="python: member.has_permission('Modify portal content', contextObj)"/>
src string: $appUrl/skyn/editBig.png"
tal:condition="python: contextObj.allows('Modify portal content')"/>
</tal:edit>
<tal:refresh condition="contextObj/isDebug">
<img title="Refresh" style="cursor:pointer"
tal:attributes="onClick python: 'href: window.location=\'%s\'' % contextObj.getUrl(mode=layoutType, page=page, refresh='yes');
src string: $portal_url/skyn/refresh.png"/>
src string: $appUrl/skyn/refresh.png"/>
</tal:refresh>
<tal:next condition="python: nextPage and pageInfo['showNext']">
<tal:button condition="isEdit">
<input type="image" class="imageInput" style="cursor:pointer" name="buttonNext"
title="label_next" i18n:attributes="title" i18n:domain="plone"
tal:attributes="src string:$portal_url/skyn/next.png"/>
tal:attributes="src string:$appUrl/skyn/next.png"/>
<input type="hidden" name="nextPage" tal:attributes="value nextPage"/>
</tal:button>
<tal:link condition="not: isEdit">
<a tal:attributes="href python: contextObj.getUrl(page=nextPage)">
<img tal:attributes="src string:$portal_url/skyn/next.png"
<img tal:attributes="src string:$appUrl/skyn/next.png"
title="label_next" i18n:attributes="title" i18n:domain="plone"/>
</a>
</tal:link>
@ -731,17 +362,12 @@
</tal:comment>
<metal:message define-macro="message">
<tal:comment replace="nothing">Single message from portal_status_message request key</tal:comment>
<div tal:define="msg request/portal_status_message | nothing"
tal:condition="msg" class="portalMessage" tal:content="structure msg"></div>
<div tal:define="msg req/portal_status_message | nothing"
tal:condition="msg" class="message" tal:content="structure msg"></div>
<tal:comment replace="nothing">Messages added via plone_utils</tal:comment>
<tal:messages define="messages putils/showPortalMessages" condition="messages">
<tal:msgs define="type_css_map python: {'info':'portalMessage', 'warn':'portalWarningMessage',
'stop':'portalStopMessage'};"
repeat="msg messages">
<div tal:define="mtype msg/type | nothing;"
tal:attributes="class python:mtype and type_css_map[mtype] or 'info';"
tal:content="structure msg/message | nothing"></div>
</tal:msgs>
<tal:messages define="messages python: ''.join([m.message for m in app.plone_utils.showPortalMessages()])"
condition="messages">
<div class="message" tal:content="structure messages"></div>
</tal:messages>
</metal:message>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 246 B

View file

@ -1,76 +1,57 @@
<tal:comment replace="nothing">
This macro displays the content of the application portlet.
</tal:comment>
<metal:portletContent define-macro="portletContent"
tal:define="queryUrl python: '%s/skyn/query' % appFolder.absolute_url();
currentSearch request/search|nothing;
currentType request/type_name|nothing;
contextObj python: tool.getPublishedObject()">
<tal:comment replace="nothing">Portlet title, with link to tool.</tal:comment>
<dt class="portletHeader">
<tal:comment replace="nothing">For the Manager, clicking on the portlet
title allows to see all root objects in the database.</tal:comment>
<table cellpadding="0" cellspacing="0" width="100%">
<tr>
<td tal:define="titleIsClickable python: member.has_role('Manager') and rootClasses">
<a tal:condition="titleIsClickable"
tal:attributes="href python:'%s?type_name=%s' % (queryUrl, ','.join(rootClasses))"
tal:content="structure python: tool.translate(appName)"></a>
<span tal:condition="not: titleIsClickable"
tal:replace="structure python: tool.translate(appName)"/>
</td>
<td align="right">
<img style="cursor:pointer"
tal:condition="python: member.has_role('Manager')"
tal:attributes="onClick python: 'href: window.location=\'%s\'' % tool.getUrl(page='main', nav='');
title python: tool.translate('%sTool' % appName);
src string:$portal_url/skyn/appyConfig.gif"/>
</td>
</dt>
<metal:portlet define-macro="portlet"
tal:define="queryUrl python: '%s/skyn/query' % tool.absolute_url();
toolUrl tool/absolute_url;
currentSearch req/search|nothing;
currentType req/type_name|nothing;
contextObj tool/getPublishedObject;
rootClasses tool/getRootClasses">
<tal:publishedObject condition="python: contextObj and contextObj.mayNavigate()">
<dt class="portletAppyItem portletCurrent"><b tal:content="contextObj/Title"></b></dt>
<dt class="portletAppyItem"><metal:phases use-macro="here/skyn/portlet/macros/phases"/></dt>
<b tal:content="contextObj/Title"></b>
<span><metal:phases use-macro="here/skyn/portlet/macros/phases"/></span>
</tal:publishedObject>
<tal:comment replace="nothing">Create a section for every root class.</tal:comment>
<tal:comment replace="nothing">One section for every searchable root class.</tal:comment>
<tal:section repeat="rootClass python: [rc for rc in rootClasses if tool.userMaySearch(rc)]">
<tal:comment replace="nothing">Section title, with action icons</tal:comment>
<dt tal:attributes="class python:test((repeat['rootClass'].number()==1) and not contextObj, 'portletAppyItem', 'portletAppyItem portletSep')">
<table width="100%" cellspacing="0" cellpadding="0" class="no-style-table">
<tr>
<td>
<a tal:attributes="href python: '%s?type_name=%s' % (queryUrl, rootClass);
class python:test(not currentSearch and (currentType==rootClass), 'portletCurrent', '')"
tal:content="structure python: tool.translate(rootClass + '_plural')"></a>
</td>
<td align="right"
tal:define="addPermission python: '%s: Add %s' % (appName, rootClass);
userMayAdd python: member.has_permission(addPermission, appFolder);
createMeans python: tool.getCreateMeans(rootClass)">
<tal:comment replace="nothing">Create a new object from a web form</tal:comment>
<img style="cursor:pointer"
tal:condition="python: ('form' in createMeans) and userMayAdd"
tal:attributes="onClick python: 'href: window.location=\'%s/skyn/do?action=Create&type_name=%s\'' % (appFolder.absolute_url(), rootClass);
src string: $portal_url/skyn/plus.png;
title python: tool.translate('query_create')"/>
<tal:comment replace="nothing">Create (a) new object(s) by importing data</tal:comment>
<img style="cursor:pointer"
tal:condition="python: ('import' in createMeans) and userMayAdd"
tal:attributes="onClick python: 'href: window.location=\'%s/skyn/import?type_name=%s\'' % (appFolder.absolute_url(), rootClass);
src string: $portal_url/skyn/import.png;
title python: tool.translate('query_import')"/>
<tal:comment replace="nothing">Search objects of this type</tal:comment>
<img style="cursor:pointer"
tal:define="showSearch python: tool.getAttr('enableAdvancedSearchFor%s' % rootClass)"
tal:condition="showSearch"
tal:attributes="onClick python: 'href: window.location=\'%s/skyn/search?type_name=%s\'' % (appFolder.absolute_url(), rootClass);
src string: $portal_url/skyn/search.gif;
title python: tool.translate('search_objects')"/>
</td>
</tr>
</table>
</dt>
<table width="100%"
tal:define="afUrl appFolder/absolute_url"
tal:attributes="class python:test((repeat['rootClass'].number()==1) and not contextObj, '', 'portletSep')">
<tr>
<td>
<a tal:attributes="href python: '%s?type_name=%s' % (queryUrl, rootClass);
class python:test(not currentSearch and (currentType==rootClass), 'portletCurrent', '')"
tal:content="structure python: _(rootClass + '_plural')"></a>
</td>
<td align="right"
tal:define="addPermission python: '%s: Add %s' % (appName, rootClass);
userMayAdd python: user.has_permission(addPermission, appFolder);
createMeans python: tool.getCreateMeans(rootClass)">
<tal:comment replace="nothing">Create a new object from a web form</tal:comment>
<img style="cursor:pointer"
tal:condition="python: ('form' in createMeans) and userMayAdd"
tal:attributes="onClick python: 'href: window.location=\'%s/skyn/do?action=Create&type_name=%s\'' % (afUrl, rootClass);
src string: $appUrl/skyn/plus.png;
title python: _('query_create')"/>
<tal:comment replace="nothing">Create (a) new object(s) by importing data</tal:comment>
<img style="cursor:pointer"
tal:condition="python: ('import' in createMeans) and userMayAdd"
tal:attributes="onClick python: 'href: window.location=\'%s/skyn/import?type_name=%s\'' % (toolUrl, rootClass);
src string: $appUrl/skyn/import.png;
title python: _('query_import')"/>
<tal:comment replace="nothing">Search objects of this type</tal:comment>
<img style="cursor:pointer"
tal:define="showSearch python: tool.getAttr('enableAdvancedSearchFor%s' % rootClass)"
tal:condition="showSearch"
tal:attributes="onClick python: 'href: window.location=\'%s/skyn/search?type_name=%s\'' % (toolUrl, rootClass);
src string: $appUrl/skyn/search.gif;
title python: _('search_objects')"/>
</td>
</tr>
</table>
<tal:comment replace="nothing">Searches for this content type.</tal:comment>
<tal:searchOrGroup repeat="searchOrGroup python: tool.getSearches(rootClass)">
<tal:group condition="searchOrGroup/isGroup">
@ -106,28 +87,7 @@
</dt>
</tal:searchOrGroup>
</tal:section>
<tal:comment replace="nothing">
Greyed transparent zone that is deployed on the
whole screen when a popup is displayed.
</tal:comment>
<div id="appyGrey" class="appyGrey"></div>
<tal:comment replace="nothing">Popup for confirming an action</tal:comment>
<div id="confirmActionPopup" class="appyPopup">
<form id="confirmActionForm" method="post">
<div align="center">
<p id="appyConfirmText"></p>
<input type="hidden" name="actionType"/>
<input type="hidden" name="action"/>
<input type="button" onClick="doConfirm()"
tal:attributes="value python:tool.translate('yes')"/>
<input type="button" value="No" onClick="closePopup('confirmActionPopup')"
tal:attributes="value python:tool.translate('no')"/>
</div>
</form>
</div>
</metal:portletContent>
</metal:portlet>
<tal:comment replace="nothing">
This macro displays, within the portlet, the navigation tree for the
@ -135,48 +95,48 @@
</tal:comment>
<metal:phases define-macro="phases">
<table tal:define="phases contextObj/getAppyPhases|nothing;
page python: request.get('page', 'main')"
page python: req.get('page', 'main')"
tal:condition="python: phases and not ((len(phases)==1) and len(phases[0]['pages'])==1)"
cellspacing="1" cellpadding="2" width="100%">
width="100%">
<tal:phase repeat="phase phases">
<tal:comment replace="nothing">The box containing phase-related information</tal:comment>
<tr>
<td tal:define="label python:'%s_phase_%s' % (contextObj.meta_type, phase['name']);
displayLink python: (phase['phaseStatus'] != 'Future') and ('/portal_factory' not in contextObj.absolute_url()) and (len(phase['pages']) == 1)"
tal:attributes="class python: (len(phases) &gt; 1) and ('appyPhase step%s' % phase['phaseStatus']) or 'appyPhase'">
tal:attributes="class python: (len(phases) &gt; 1) and 'phase' or ''">
<div class="portletGroup" tal:condition="python: len(phases) &gt; 1">
<tal:comment replace="nothing">A single page in the phase</tal:comment>
<table tal:condition="displayLink" cellpadding="0" cellspacing="0" width="100%">
<table tal:condition="displayLink" width="100%">
<tr tal:define="pageName python: phase['pages'][0]">
<td><a tal:attributes="href python: contextObj.getUrl(page=pageName)"
tal:content="structure python: tool.translate(label)"></a>
tal:content="structure python: _(label)"></a>
</td>
<td align="right">
<img title="Edit" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
tal:attributes="onClick python: 'href: window.location=\'%s\'' % contextObj.getUrl(mode='edit', page=pageName);
src string: $portal_url/skyn/edit.gif"
tal:condition="python: member.has_permission('Modify portal content', contextObj) and phase['pagesInfo'][pageName]['showOnEdit']"/>
src string: $appUrl/skyn/edit.gif"
tal:condition="python: contextObj.allows('Modify portal content') and phase['pagesInfo'][pageName]['showOnEdit']"/>
</td>
</tr>
</table>
<tal:comment replace="nothing">Several pages in the phase</tal:comment>
<span tal:condition="not: displayLink" tal:replace="structure python: tool.translate(label)"/>
<span tal:condition="not: displayLink" tal:replace="structure python: _(label)"/>
</div>
<div class="portletMenu">
<table cellpadding="0" cellspacing="0" width="100%"
tal:condition="python: len(phase['pages']) &gt; 1">
<tr tal:repeat="aPage phase/pages" valign="top">
<td tal:attributes="class python: test(aPage == page, 'portletCurrent portletPageItem', 'portletPageItem')">
<td tal:attributes="class python: test(aPage == page, 'portletCurrent portletPage', 'portletPage')">
<a tal:attributes="href python: contextObj.getUrl(page=aPage)"
tal:content="structure python: tool.translate('%s_page_%s' % (contextObj.meta_type, aPage))">
tal:content="structure python: _('%s_page_%s' % (contextObj.meta_type, aPage))">
</a>
</td>
<td align="right">
<img title="Edit" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
tal:attributes="onClick python: 'href: window.location=\'%s\'' % contextObj.getUrl(mode='edit', page=aPage);
src string: $portal_url/skyn/edit.gif"
tal:condition="python: member.has_permission('Modify portal content', contextObj) and phase['pagesInfo'][aPage]['showOnEdit']"/>
src string: $appUrl/skyn/edit.gif"
tal:condition="python: user.has_permission('Modify portal content', contextObj) and phase['pagesInfo'][aPage]['showOnEdit']"/>
</td>
</tr>
</table>
@ -185,7 +145,7 @@
</tr>
<tal:comment replace="nothing">The down arrow pointing to the next phase (if any)</tal:comment>
<tr tal:condition="python: phase['name'] != phases[-1]['name']">
<td>&nbsp;&nbsp;<img tal:attributes="src string: $portal_url/skyn/nextPhase.png"/></td>
<td>&nbsp;&nbsp;<img tal:attributes="src string: $appUrl/skyn/nextPhase.png"/></td>
</tr>
</tal:phase>
</table>

View file

@ -1,22 +1,8 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
metal:use-macro="here/main_template/macros/master">
<tal:comment replace="nothing">This page presents results of queries</tal:comment>
<body>
<tal:comment replace="nothing">Disable standard Plone green tabs</tal:comment>
<div metal:fill-slot="top_slot">
<metal:block metal:use-macro="here/global_defines/macros/defines" />
<div tal:define="dummy python:request.set('disable_border', 1)" />
</div>
<tal:comment replace="nothing">We suppose we are in the app folder here.</tal:comment>
<div metal:fill-slot="main"
tal:define="appFolder context/getParentNode;
appName appFolder/id;
tool python: portal.get('portal_%s' % appName.lower());
contentType request/type_name;
searchName request/search|python:''">
<tal:main define="tool context/getParentNode">
<html metal:use-macro="context/skyn/template/macros/main">
<metal:fill fill-slot="content"
tal:define="contentType request/type_name;
searchName request/search|python:''">
<div metal:use-macro="here/skyn/page/macros/prologue"/>
<tal:comment replace="nothing">Query result</tal:comment>
@ -26,6 +12,6 @@
tal:define="ajaxUrl python: tool.getQueryUrl(contentType, searchName)"
tal:content="python: 'askQueryResult(\'queryResult\', \'%s\',\'%s\',\'%s\',0)' % (tool.absolute_url(), contentType, searchName)">
</script>
</div>
</body>
</metal:fill>
</html>
</tal:main>

View file

@ -1,6 +1,5 @@
<metal:queryResults define-macro="queryResult"
tal:define="tool python: contextObj;
contentType request/type_name;
tal:define="contentType request/type_name;
refInfo tool/getRefInfo;
refField python: refInfo[1];
refInfo python: refInfo[0];
@ -21,7 +20,7 @@
batchSize queryResult/batchSize;
ajaxHookId python:'queryResult';
navBaseCall python: 'askQueryResult(\'%s\',\'%s\',\'%s\',\'%s\',**v**)' % (ajaxHookId, tool.absolute_url(), contentType, searchName);
newSearchUrl python: '%s/skyn/search?type_name=%s&ref=%s' % (tool.getAppFolder().absolute_url(), contentType, refInfo);">
newSearchUrl python: '%s/skyn/search?type_name=%s&ref=%s' % (tool.absolute_url(), contentType, refInfo);">
<tal:result condition="objs">
@ -36,7 +35,7 @@
</legend>
<tal:comment replace="nothing">Display here POD templates if required.</tal:comment>
<table align="right" cellpadding="0" cellspacing="0"
<table align="right"
tal:define="widgets python: tool.getResultPodFields(contentType);
layoutType python:'view'"
tal:condition="python: objs and widgets">
@ -46,7 +45,7 @@
</td></tr>
</table>
<table cellpadding="0" cellspacing="0" width="100%">
<table width="100%">
<tr>
<tal:descr condition="searchName">
<td tal:define="descr python: tool.translate('%s_descr' % labelId)"
@ -63,7 +62,7 @@
<table tal:define="fieldNames python: tool.getResultColumnsNames(contentType, refField);
widgets python: objs[0].getAppyTypesFromNames(fieldNames);"
class="listing nosort" width="100%" cellpadding="0" cellspacing="0">
class="list" width="100%">
<tal:comment replace="nothing">Headers, with filters and sort arrows</tal:comment>
<tr>
<tal:header repeat="widget widgets">
@ -118,21 +117,21 @@
<tal:comment replace="nothing">Column "Actions"</tal:comment>
<td align="right">
<table class="no-style-table" cellpadding="0" cellspacing="0">
<table class="noStyle">
<tr>
<tal:comment replace="nothing">Edit the element</tal:comment>
<td class="noPadding">
<td>
<a tal:define="navInfo python:'search.%s.%s.%d.%d' % (contentType, searchName, repeat['obj'].number()+startNumber, totalNumber);"
tal:attributes="href python: obj.getUrl(mode='edit', page='main', nav=navInfo)"
tal:condition="python: member.has_permission('Modify portal content', obj)">
tal:condition="python: obj.allows('Modify portal content')">
<img title="Edit" i18n:domain="plone" i18n:attributes="title"
tal:attributes="src string: $portal_url/skyn/edit.gif"/>
tal:attributes="src string: $appUrl/skyn/edit.gif"/>
</a></td>
<tal:comment replace="nothing">Delete the element</tal:comment>
<td class="noPadding">
<img tal:condition="python: member.has_permission('Delete objects', obj) and obj.mayDelete()"
<td>
<img tal:condition="python: obj.allows('Delete objects') and obj.mayDelete()"
title="Delete" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/delete.png;
tal:attributes="src string: $appUrl/skyn/delete.png;
onClick python:'onDeleteObject(\'%s\')' % obj.UID()"/>
</td>
</tr>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 189 B

View file

@ -1,43 +1,16 @@
<tal:search metal:define-macro="master"
define="appFolder context/getParentNode;
contentType request/type_name;
refInfo request/ref|nothing;
tool python: here.portal_url.getPortalObject().get('portal_%s' % appFolder.id.lower());
searchInfo python: tool.getSearchInfo(contentType, refInfo);
cssJs python: tool.getCssAndJs(searchInfo['fields'], 'edit')">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
metal:use-macro="here/main_template/macros/master">
<tal:comment replace="nothing">Disable standard Plone green tabs</tal:comment>
<div metal:fill-slot="top_slot">
<metal:block metal:use-macro="here/global_defines/macros/defines" />
<div tal:define="dummy python:request.set('disable_border', 1)" />
</div>
<tal:main define="tool context/getParentNode">
<html metal:use-macro="context/skyn/template/macros/main">
<metal:fill fill-slot="content"
tal:define="contentType request/type_name;
refInfo request/ref|nothing;
searchInfo python: tool.getSearchInfo(contentType, refInfo);
cssJs python: tool.getCssAndJs(searchInfo['fields'], 'edit')">
<tal:comment replace="nothing">Include type-specific CSS and JS.</tal:comment>
<metal:js fill-slot="javascript_head_slot">
<tal:js condition="cssJs/js" repeat="jsFile cssJs/js">
<script type="text/javascript" charset="iso-8859-1"
tal:condition="python:exists('portal/%s' % jsFile)"
tal:attributes="src string:$portal_url/$jsFile">
</script>
</tal:js>
</metal:js>
<metal:css fill-slot="css_slot">
<tal:css condition="cssJs/css" repeat="cssFile cssJs/css">
<style type="text/css" media="all"
tal:condition="python:exists('portal/%s' % cssFile)"
tal:content="structure string:<!-- @import url($portal_url/$cssFile); -->">
</style>
</tal:css>
</metal:css>
<body>
<metal:fill fill-slot="main">
<link tal:repeat="cssFile cssJs/css" rel="stylesheet" type="text/css"
tal:attributes="href string:$appUrl/skyn/$cssFile"/>
<script tal:repeat="jsFile cssJs/js" type="text/javascript"
tal:attributes="src string:$appUrl/skyn/$jsFile"></script>
<tal:comment replace="nothing">Search title</tal:comment>
<h1><span tal:replace="python: tool.translate('%s_plural' % contentType)"/> —
@ -49,7 +22,7 @@
<input type="hidden" name="type_name" tal:attributes="value contentType"/>
<input tal:condition="refInfo" type="hidden" name="ref" tal:attributes="value refInfo"/>
<table class="no-style-table" cellpadding="0" cellspacing="0" width="100%">
<table width="100%">
<tr tal:repeat="searchRow python: tool.tabularize(searchInfo['fieldDicts'], searchInfo['nbOfColumns'])"
valign="top">
<td tal:repeat="widget searchRow" tal:attributes="width python:'%d%%' % (100/searchInfo['nbOfColumns'])">
@ -69,7 +42,6 @@
<input type="submit" tal:attributes="value python:tool.translate('search_button')"/>
</p>
</form>
</metal:fill>
</body>
</metal:fill>
</html>
</tal:search>
</tal:main>

View file

@ -1,14 +1,16 @@
<html metal:define-macro="main"
tal:define="user context/portal_membership/getAuthenticatedMember;
isAnon python: user.getUserName() == 'Anonymous User';
app python: tool.getParentNode();
app tool/getApp;
appUrl app/absolute_url;
appFolder tool/getAppFolder;
appName appFolder/getId;
_ python: tool.translate;
req python: request;
resp req/RESPONSE;
x python: resp.setHeader('Content-Type', 'text/html;;charset=utf-8');
x python: resp.setHeader('Expires', 'Thu, 11 Dec 1975 12:05:00 GMT+2');
x python: resp.setHeader('Content-Language', request.get('language', 'en'))">
x python: resp.setHeader('Content-Language', req.get('language', 'en'))">
<head>
<title tal:content="tool/getAppName"></title>
@ -17,14 +19,14 @@
</head>
<body>
<table class="main" align="center">
<table class="main" align="center" cellpadding="0">
<tal:comment replace="nothing">Top banner</tal:comment>
<tr class="top" metal:define-slot="top">
<td>
<table width="100%">
<tr valign="top">
<tal:comment replace="nothing">Logo</tal:comment>
<td><a tal:attributes="href appUrl"><img src="skyn/logo.jpg"/></a></td>
<td><a tal:attributes="href appUrl"><img tal:attributes="src string: $appUrl/skyn/logo.jpg"/></a></td>
<tal:comment replace="nothing">Language selector (links or listbox)</tal:comment>
<td align="right"
tal:define="appLangs app/portal_languages/listSupportedLanguages;
@ -55,6 +57,31 @@
</table>
</td>
</tr>
<tal:comment replace="nothing">The message strip</tal:comment>
<tr>
<td>
<div style="position: relative" align="right">
<metal:msg use-macro="app/skyn/page/macros/message"/>
</div>
<tal:comment replace="nothing">Grey background shown when popups are shown</tal:comment>
<div id="grey" class="grey"></div>
<tal:comment replace="nothing">Popup for confirming an action</tal:comment>
<div id="confirmActionPopup" class="popup">
<form id="confirmActionForm" method="post">
<div align="center">
<p id="appyConfirmText"></p>
<input type="hidden" name="actionType"/>
<input type="hidden" name="action"/>
<input type="button" onClick="doConfirm()"
tal:attributes="value python:_('yes')"/>
<input type="button" value="No" onClick="closePopup('confirmActionPopup')"
tal:attributes="value python:_('no')"/>
</div>
</form>
</div>
</td>
</tr>
<tal:comment replace="nothing">The user data strip</tal:comment>
<tr>
<td>
@ -88,12 +115,17 @@
<td>
<!-- Go home -->
<a tal:attributes="href appUrl; title python: _('home')">
<img src="skyn/home.gif"/>
<img tal:attributes="src string: $appUrl/skyn/home.gif"/>
</a>
<!-- Config -->
<img style="cursor:pointer" tal:condition="python: user.has_role('Manager')"
tal:attributes="onClick python: 'href: window.location=\'%s\'' % tool.getUrl(page='main', nav='');
title python: _('%sTool' % appName);
src string:$appUrl/skyn/appyConfig.gif"/>
<!-- Logout -->
<a tal:attributes="href python: tool.absolute_url() + '/performLogout';
title python: _('logout')">
<img src="skyn/logout.gif"/>
<img tal:attributes="src string: $appUrl/skyn/logout.gif"/>
</a>
</td>
</tr>
@ -103,20 +135,16 @@
</table>
</td>
</tr>
<tal:comment replace="nothing">The message strip</tal:comment>
<tr tal:define="msg request/portal_status_message | nothing">
<td>
<div style="position: relative" align="right">
<div tal:condition="msg" class="message" tal:content="structure msg"></div>
</div>
</td>
</tr>
<tr>
<td>
<table class="content" width="100%">
<tr>
<td><span metal:define-slot="content"></span>
<table width="99%">
<tr valign="top">
<tal:comment replace="nothing">Portlet</tal:comment>
<td tal:condition="python: tool.showPortlet(context)" class="portlet">
<metal:portlet use-macro="app/skyn/portlet/macros/portlet"/>
</td>
<tal:comment replace="nothing">Page content</tal:comment>
<td class="content"><span metal:define-slot="content"></span></td>
</tr>
</table>
</td>

View file

@ -1,34 +1,17 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
metal:use-macro="here/main_template/macros/master">
<head><title></title></head>
<tal:comment replace="nothing">Disable standard Plone green tabs</tal:comment>
<div metal:fill-slot="top_slot">
<metal:block metal:use-macro="here/global_defines/macros/defines" />
<div tal:define="dummy python:request.set('disable_border', 1)" />
</div>
<tal:comment replace="nothing">Fill main slot of Plone main_template</tal:comment>
<body>
<metal:fill fill-slot="main"
tal:define="contextObj python:context.getParentNode();
portal_type python:here.getPortalTypeName().lower().replace(' ', '_');
errors python:request.get('errors', {});
layoutType python:'view';
layout python: contextObj.getPageLayout(layoutType);
tool contextObj/getTool;
appFolder tool/getAppFolder;
appName appFolder/getId;
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType='view');
page request/page|python:'main';
phase phaseInfo/name;">
<metal:prologue use-macro="here/skyn/page/macros/prologue"/>
<metal:show use-macro="here/skyn/page/macros/show"/>
<metal:footer use-macro="here/skyn/page/macros/footer"/>
</metal:fill>
</body>
<tal:main define="tool context/getTool">
<html metal:use-macro="context/skyn/template/macros/main">
<metal:fill fill-slot="content"
tal:define="contextObj python:context.getParentNode();
portal_type python:here.getPortalTypeName().lower().replace(' ', '_');
errors python:req.get('errors', {});
layoutType python:'view';
layout python: contextObj.getPageLayout(layoutType);
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType='view');
page req/page|python:'main';
phase phaseInfo/name;">
<metal:prologue use-macro="here/skyn/page/macros/prologue"/>
<metal:show use-macro="here/skyn/page/macros/show"/>
<metal:footer use-macro="here/skyn/page/macros/footer"/>
</metal:fill>
</html>
</tal:main>

View file

@ -20,17 +20,17 @@
widget python: contextObj.getAppyType(name, asDict=True);
value python: contextObj.getFieldValue(name);
sync python:True">
<metal:call use-macro="portal/skyn/widgets/computed/macros/view"/>
<metal:call use-macro="app/skyn/widgets/computed/macros/view"/>
</metal:view>
<tal:comment replace="nothing">Edit macro for a Computed.</tal:comment>
<metal:edit define-macro="edit">
<metal:call use-macro="portal/skyn/widgets/computed/macros/view"/>
<metal:call use-macro="app/skyn/widgets/computed/macros/view"/>
</metal:edit>
<tal:comment replace="nothing">Cell macro for a Computed.</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="portal/skyn/widgets/computed/macros/view"/>
<metal:call use-macro="app/skyn/widgets/computed/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro for a Computed.</tal:comment>

View file

@ -44,7 +44,7 @@
</select>
<tal:comment replace="nothing">The icon for displaying the calendar (=date chooser)</tal:comment>
<a tal:condition="widget/calendar"
tal:attributes="onclick python: 'return showJsCalendar(\'%s_month\', \'%s\', \'%s_year\', \'%s_month\', \'%s_day\', null, null, %d, %d)' % (name, dummyName, name, name, name, years[0], years[-1])"><img tal:attributes="src string: $portal_url/popup_calendar.gif"/></a>
tal:attributes="onclick python: 'return showJsCalendar(\'%s_month\', \'%s\', \'%s_year\', \'%s_month\', \'%s_day\', null, null, %d, %d)' % (name, dummyName, name, name, name, years[0], years[-1])"><img tal:attributes="src string: $appUrl/calendar.gif"/></a>
<tal:hour condition="python: widget['format'] == 0">
<select tal:define="hours python:range(0,24);"
@ -111,7 +111,7 @@
<tal:comment replace="nothing">The icon for displaying the calendar (=date chooser)</tal:comment>
<a tal:condition="widget/calendar"
tal:attributes="onclick python: 'return showJsCalendar(\'%s\', \'%s\', \'%s\', \'%s\', \'%s\', null, null, %d, %d)' % (monthFromName, dummyFromName, yearFromName, monthFromName, dayFromName, years[0], years[-1])">
<img tal:attributes="src string: $portal_url/popup_calendar.gif"/></a>
<img tal:attributes="src string: $appUrl/calendar.gif"/></a>
</td>
</tr>
<tal:comment replace="nothing">To</tal:comment>
@ -142,7 +142,7 @@
</select>
<a tal:condition="widget/calendar"
tal:attributes="onclick python: 'return showJsCalendar(\'%s\', \'%s\', \'%s\', \'%s\', \'%s\', null, null, %d, %d)' % (monthToName, dummyToName, yearToName, monthToName, dayToName, years[0], years[-1])">
<img tal:attributes="src string: $portal_url/popup_calendar.gif"/></a>
<img tal:attributes="src string: $appUrl/calendar.gif"/></a>
</td>
</tr>
</table>

View file

@ -4,7 +4,7 @@
imageSrc string:${contextObj/absolute_url}/download?name=$name">
<tal:file condition="python: not empty and not widget['isImage']">
<img tal:define="icon value/getBestIcon"
tal:condition="icon" tal:attributes="src string: $portal_url/$icon"/>
tal:condition="icon" tal:attributes="src string: $appUrl/$icon"/>
<a tal:attributes="href imageSrc"
tal:content="value/filename">
</a>&nbsp;&nbsp;-

View file

@ -8,7 +8,7 @@
tal:content="python: tool.translate(doLabel)"></label>
</tal:askAction>
<img tal:repeat="podFormat python: tool.getPodInfo(contextObj, name)[1]"
tal:attributes="src string: $portal_url/skyn/${podFormat}.png;
tal:attributes="src string: $appUrl/skyn/${podFormat}.png;
onClick python: 'generatePodDocument(\'%s\',\'%s\',\'%s\',\'%s\')' % (contextObj.UID(), name, podFormat, tool.getQueryInfo());
title podFormat/capitalize"
style="cursor:pointer"/>

View file

@ -19,39 +19,39 @@
<metal:objectActions define-macro="objectActions">
<tal:comment replace="nothing">Displays icons for triggering actions on a given
referenced object (edit, delete, etc).</tal:comment>
<table class="no-style-table" cellpadding="0" cellspacing="0">
<table class="noStyle">
<tr>
<tal:comment replace="nothing">Arrows for moving objects up or down</tal:comment>
<td class="noPadding" tal:condition="python: not appyType['isBack'] and (len(objs)&gt;1) and member.has_permission('Modify portal content', contextObj)">
<td tal:condition="python: not appyType['isBack'] and (len(objs)&gt;1) and context.allows('Modify portal content')">
<tal:moveRef define="objectIndex python: contextObj.getAppyRefIndex(fieldName, obj);
ajaxBaseCall python: navBaseCall.replace('**v**', '\'%s\',\'ChangeRefOrder\', {\'refObjectUid\':\'%s\', \'move\':\'**v**\'}' % (startNumber, obj.UID()))">
<tal:comment replace="nothing">Move up</tal:comment>
<img tal:condition="python: objectIndex &gt; 0"
tal:attributes="src string: $portal_url/skyn/arrowUp.png;
tal:attributes="src string: $appUrl/skyn/arrowUp.png;
title python: tool.translate('move_up');
onClick python: ajaxBaseCall.replace('**v**', 'up')"
style="cursor:pointer"/>
<tal:comment replace="nothing">Move down</tal:comment>
<img tal:condition="python: objectIndex &lt; (totalNumber-1)"
tal:attributes="src string: $portal_url/skyn/arrowDown.png;
tal:attributes="src string: $appUrl/skyn/arrowDown.png;
title python: tool.translate('move_down');
onClick python: ajaxBaseCall.replace('**v**', 'down')"
style="cursor:pointer"/>
</tal:moveRef>
</td>
<tal:comment replace="nothing">Edit the element</tal:comment>
<td class="noPadding" tal:condition="python: member.has_permission('Modify portal content', obj) and not appyType['noForm']">
<td tal:condition="python: obj.allows('Modify portal content') and not appyType['noForm']">
<a tal:define="navInfo python:'ref.%s.%s:%s.%d.%d' % (contextObj.UID(), fieldName, appyType['pageName'], repeat['obj'].number()+startNumber, totalNumber);"
tal:attributes="href python: obj.getUrl(mode='edit', page='main', nav=navInfo)">
<img title="label_edit" i18n:domain="plone" i18n:attributes="title"
tal:attributes="src string: $portal_url/skyn/edit.gif"/>
tal:attributes="src string: $appUrl/skyn/edit.gif"/>
</a>
</td>
<tal:comment replace="nothing">Delete the element</tal:comment>
<td class="noPadding">
<img tal:condition="python: not appyType['isBack'] and member.has_permission('Delete objects', obj) and obj.mayDelete()"
<td>
<img tal:condition="python: not appyType['isBack'] and obj.allows('Delete objects') and obj.mayDelete()"
title="Delete" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
tal:attributes="src string: $portal_url/skyn/delete.png;
tal:attributes="src string: $appUrl/skyn/delete.png;
onClick python:'onDeleteObject(\'%s\')' % obj.UID()"/>
</td>
</tr>
@ -68,7 +68,7 @@
formCall python: test(appyType['addConfirm'], 'askConfirm(\'script\', &quot;%s&quot;, &quot;%s&quot;)' % (formCall, addConfirmMsg), formCall);
noFormCall python: navBaseCall.replace('**v**', '%d, \'CreateWithoutForm\'' % startNumber);
noFormCall python: test(appyType['addConfirm'], 'askConfirm(\'script\', &quot;%s&quot;, &quot;%s&quot;)' % (noFormCall, addConfirmMsg), noFormCall)"
tal:attributes="src string:$portal_url/skyn/plus.png;
tal:attributes="src string:$appUrl/skyn/plus.png;
title python: tool.translate('add_ref');
onClick python: test(appyType['noForm'], noFormCall, formCall)"/>
</metal:plusIcon>
@ -81,10 +81,10 @@
tal:define="ajaxBaseCall python: navBaseCall.replace('**v**', '\'%s\',\'SortReference\', {\'sortKey\':\'%s\', \'reverse\':\'**v**\'}' % (startNumber, widget['name']))"
tal:condition="python: canWrite and tool.isSortable(widget['name'], objs[0].meta_type, 'ref')">
<img style="cursor:pointer"
tal:attributes="src string:$portal_url/skyn/sortAsc.png;
tal:attributes="src string:$appUrl/skyn/sortAsc.png;
onClick python: ajaxBaseCall.replace('**v**', 'False')"/>
<img style="cursor:pointer"
tal:attributes="src string:$portal_url/skyn/sortDesc.png;
tal:attributes="src string:$appUrl/skyn/sortDesc.png;
onClick python: ajaxBaseCall.replace('**v**', 'True')"/>
</metal:sortIcons>
@ -115,16 +115,16 @@
folder python: contextObj.isPrincipiaFolderish and contextObj or contextObj.getParentNode();
linkedPortalType python: tool.getPortalType(appyType['klass']);
addPermission python: '%s: Add %s' % (tool.getAppName(), linkedPortalType);
canWrite python: not appyType['isBack'] and member.has_permission(appyType['writePermission'], contextObj);
canWrite python: not appyType['isBack'] and contextObj.allows(appyType['writePermission']);
multiplicity appyType/multiplicity;
maxReached python:(multiplicity[1] != None) and (len(objs) >= multiplicity[1]);
showPlusIcon python:not appyType['isBack'] and appyType['add'] and not maxReached and member.has_permission(addPermission, folder) and canWrite;
showPlusIcon python:not appyType['isBack'] and appyType['add'] and not maxReached and user.has_permission(addPermission, folder) and canWrite;
atMostOneRef python: (multiplicity[1] == 1) and (len(objs)&lt;=1);
label python: contextObj.translate('label', field=appyType);
addConfirmMsg python: appyType['addConfirm'] and tool.translate('%s_addConfirm' % appyType['labelId']) or '';
navBaseCall python: 'askRefField(\'%s\',\'%s\',\'%s\',\'%s\',**v**)' % (ajaxHookId, contextObj.absolute_url(), fieldName, innerRef)">
<tal:comment replace="nothing">This macro displays the Reference widget on a "consult" page.
<tal:comment replace="nothing">This macro displays the Reference widget on a "view" page.
The definition of "atMostOneRef" above may sound strange: we shouldn't check the actual number
of referenced objects. But for back references people often forget to specify multiplicities.
@ -133,20 +133,20 @@
<tal:atMostOneReference condition="atMostOneRef">
<tal:comment replace="nothing">Display a simplified widget if maximum number of
referenced objects is 1.</tal:comment>
<table class="no-style-table" cellpadding="0" cellspacing="0"><tr valign="top">
<table><tr valign="top">
<td><span class="appyLabel" tal:condition="python: not innerRef and not appyType['link']"
tal:content="structure label"></span></td>
<tal:comment replace="nothing">If there is no object...</tal:comment>
<tal:noObject condition="not:objs">
<td tal:content="python: tool.translate('no_ref')"></td>
<td><metal:plusIcon use-macro="portal/skyn/widgets/ref/macros/plusIcon"/></td>
<td><metal:plusIcon use-macro="app/skyn/widgets/ref/macros/plusIcon"/></td>
</tal:noObject>
<tal:comment replace="nothing">If there is an object...</tal:comment>
<tal:objectIsPresent condition="objs">
<tal:obj repeat="obj objs">
<td tal:define="includeShownInfo python:True"><metal:showObjectTitle use-macro="portal/skyn/widgets/ref/macros/objectTitle" /></td>
<td tal:define="includeShownInfo python:True"><metal:showObjectTitle use-macro="app/skyn/widgets/ref/macros/objectTitle" /></td>
</tal:obj>
</tal:objectIsPresent>
</tr></table>
@ -158,7 +158,7 @@
<legend tal:condition="python: not innerRef or showPlusIcon">
<span tal:condition="not: innerRef" tal:content="label"/>
(<span tal:replace="totalNumber"/>)
<metal:plusIcon use-macro="portal/skyn/widgets/ref/macros/plusIcon"/>
<metal:plusIcon use-macro="app/skyn/widgets/ref/macros/plusIcon"/>
<tal:comment replace="nothing">The search icon if field is queryable</tal:comment>
<a tal:condition="appyType/queryable"
tal:attributes="href python: '%s/skyn/search?type_name=%s&ref=%s:%s' % (tool.getAppFolder().absolute_url(), linkedPortalType, contextObj.meta_type, appyType['name'])">
@ -175,28 +175,27 @@
<tal:comment replace="nothing">No object is present</tal:comment>
<p tal:condition="not:objs" tal:content="python: tool.translate('no_ref')"></p>
<table width="100%" cellspacing="0" cellpadding="0" tal:condition="objs"
<table width="100%" tal:condition="python: objs"
tal:attributes="class python:test(innerRef, 'innerAppyTable', '')">
<tr valign="bottom"><td>
<tal:comment replace="nothing">Show forward or backward reference(s)</tal:comment>
<table tal:attributes="class python:test(innerRef, '', 'listing nosort');
width python:test(innerRef, '100%', appyType['layouts']['view']['width']);"
align="right" tal:condition="python: objs" cellpadding="0" cellspacing="0">
<table tal:attributes="class python:test(innerRef, '', 'list');
width python:test(innerRef, '100%', appyType['layouts']['view']['width']);">
<tal:widgets define="widgets python: objs[0].getAppyTypesFromNames(appyType['shownInfo'])">
<tr tal:condition="appyType/showHeaders">
<th tal:repeat="widget widgets">
<span tal:content="python: tool.translate(widget['labelId'])"></span>
<metal:sortIcons use-macro="portal/skyn/widgets/ref/macros/sortIcons" />
<metal:sortIcons use-macro="app/skyn/widgets/ref/macros/sortIcons" />
</th>
<th tal:content="python: tool.translate('ref_actions')"></th>
</tr>
<tal:row repeat="obj objs">
<tr valign="top" tal:define="odd repeat/obj/odd"
<tr valign="middle" tal:define="odd repeat/obj/odd"
tal:attributes="class python:test(odd, 'even', 'odd')">
<td tal:repeat="widget widgets">
<tal:title condition="python: widget['name'] == 'title'">
<metal:showObjectTitle use-macro="portal/skyn/widgets/ref/macros/objectTitle"/>
<metal:showObjectTitle use-macro="app/skyn/widgets/ref/macros/objectTitle"/>
</tal:title>
<tal:state condition="python: widget['name'] == 'state'"
content="python: tool.translate(obj.getWorkflowLabel())">
@ -205,13 +204,13 @@
<tal:field define="contextObj python:obj;
layoutType python: 'cell';
innerRef python:True">
<metal:field use-macro="portal/skyn/widgets/show/macros/field" />
<metal:field use-macro="app/skyn/widgets/show/macros/field" />
</tal:field>
</tal:other>
</td>
<tal:comment replace="nothing">Actions</tal:comment>
<td align="right">
<metal:showObjectActions use-macro="portal/skyn/widgets/ref/macros/objectActions" />
<metal:showObjectActions use-macro="app/skyn/widgets/ref/macros/objectActions" />
</td>
</tr>
</tal:row>
@ -254,7 +253,7 @@
<tal:comment replace="nothing">Cell macro for a Ref.</tal:comment>
<metal:cell define-macro="cell">
<metal:call use-macro="portal/skyn/widgets/ref/macros/view"/>
<metal:call use-macro="app/skyn/widgets/ref/macros/view"/>
</metal:cell>
<tal:comment replace="nothing">Search macro for a Ref.</tal:comment>

View file

@ -8,10 +8,10 @@
Options:
contextMacro The base folder containing the macros to call for
rendering the elements within the layout.
Defaults to portal.skyn
Defaults to app.skyn
</tal:comment>
<metal:show define-macro="layout"
tal:define="contextMacro contextMacro| python: portal.skyn">
tal:define="contextMacro contextMacro| python: app.skyn">
<table tal:attributes="cellpadding layout/cellpadding;
cellspacing layout/cellspacing;
width layout/width;
@ -28,7 +28,7 @@
<tr tal:repeat="row layout/rows" tal:attributes="valign row/valign">
<td tal:repeat="cell row/cells"
tal:attributes="align cell/align; colspan cell/colspan;
style python: test(repeat['cell'].end, '', 'padding-right: 0.4em')"><tal:content repeat="elem cell/content"><tal:field condition="python: elem == '?'"><metal:call use-macro="python: contextMacro.get(widget['type'].lower()).macros.get(layoutType)"/></tal:field><tal:other condition="python: elem != '?'"><metal:call use-macro="python: contextMacro.get(elem[0]).macros.get(elem[1])"/></tal:other><img tal:condition="not: repeat/elem/end" tal:attributes="src string: $portal_url/skyn/space.gif"/></tal:content>
style python: test(repeat['cell'].end, '', 'padding-right: 0.4em')"><tal:content repeat="elem cell/content"><tal:field condition="python: elem == '?'"><metal:call use-macro="python: contextMacro.get(widget['type'].lower()).macros.get(layoutType)"/></tal:field><tal:other condition="python: elem != '?'"><metal:call use-macro="python: contextMacro.get(elem[0]).macros.get(elem[1])"/></tal:other><img tal:condition="not: repeat/elem/end" tal:attributes="src string: $appUrl/skyn/space.gif"/></tal:content>
</td>
</tr>
</table>
@ -42,7 +42,7 @@
widget The widget to render
</tal:comment>
<metal:field define-macro="field"
tal:define="contextMacro python: portal.skyn.widgets;
tal:define="contextMacro python: app.skyn.widgets;
layout python: widget['layouts'][layoutType];
name widget/name;
sync python: widget['sync'][layoutType];
@ -70,15 +70,15 @@
<legend tal:condition="widget/hasLabel">
<i tal:content="structure python: contextObj.translate(widget['labelId'])"></i>
<tal:help condition="widget/hasHelp">
<metal:call use-macro="portal/skyn/widgets/show/macros/help"/>
<metal:call use-macro="app/skyn/widgets/show/macros/help"/>
</tal:help>
</legend>
<div tal:condition="widget/hasDescr" class="discreet"
tal:content="structure python: contextObj.translate(widget['descrId'])"></div>
<metal:content use-macro="portal/skyn/widgets/show/macros/groupContent"/>
<metal:content use-macro="app/skyn/widgets/show/macros/groupContent"/>
</fieldset>
<tal:asSection condition="python: widget['style'] not in ('fieldset', 'tabs')">
<metal:content use-macro="portal/skyn/widgets/show/macros/groupContent"/>
<metal:content use-macro="app/skyn/widgets/show/macros/groupContent"/>
</tal:asSection>
<tal:asTabs condition="python: widget['style'] == 'tabs'">
<table cellpadding="0" cellspacing="0"
@ -90,15 +90,15 @@
<tr valign="middle">
<tal:tab repeat="widgetRow widget/widgets">
<tal:id define="tabId python:'tab_%s_%d_%d' % (widget['name'], repeat['widgetRow'].number(), len(widget['widgets']))">
<td><img tal:attributes="src string: $portal_url/skyn/tabLeft.png;
<td><img tal:attributes="src string: $appUrl/skyn/tabLeft.png;
id python: '%s_left' % tabId"/><td>
<td tal:attributes="style python:'background-image: url(%s/skyn/tabBg.png)' % portal_url;
<td tal:attributes="style python:'background-image: url(%s/skyn/tabBg.png)' % appUrl;
id tabId">
<a style="cursor:pointer"
tal:content="python: tool.translate('%s_col%d' % (widget['labelId'], repeat['widgetRow'].number()))"
tal:attributes="onClick python: 'showTab(\'%s_%d_%d\')' % (widget['name'], repeat['widgetRow'].number(), len(widget['widgets']))"></a>
</td>
<td><img tal:attributes="src string: $portal_url/skyn/tabRight.png;
<td><img tal:attributes="src string: $appUrl/skyn/tabRight.png;
id python: '%s_right' % tabId"/><td>
</tal:id>
</tal:tab>
@ -111,10 +111,10 @@
style python: test(repeat['widgetRow'].number()==1, 'display:table-row', 'display:none')">
<td tal:define="widget python: widgetRow[0]">
<tal:group condition="python: widget['type'] == 'group'">
<metal:call use-macro="portal/skyn/widgets/show/macros/group"/>
<metal:call use-macro="app/skyn/widgets/show/macros/group"/>
</tal:group>
<tal:field condition="python: widget['type'] != 'group'">
<metal:call use-macro="portal/skyn/widgets/show/macros/field"/>
<metal:call use-macro="app/skyn/widgets/show/macros/field"/>
</tal:field>
</td>
</tr>
@ -141,7 +141,7 @@
class widget/style" align="left">
<span tal:replace="structure python: contextObj.translate(widget['labelId'])"/>
<tal:help condition="widget/hasHelp">
<metal:call use-macro="portal/skyn/widgets/show/macros/help"/>
<metal:call use-macro="app/skyn/widgets/show/macros/help"/>
</tal:help>
</td>
</tr>
@ -164,10 +164,10 @@
style python: test(repeat['widget'].number() != len(widgetRow), 'padding-right: %s'%cellgap, '')">
<tal:showWidget condition="widget">
<tal:group condition="python: widget['type'] == 'group'">
<metal:call use-macro="portal/skyn/widgets/show/macros/group"/>
<metal:call use-macro="app/skyn/widgets/show/macros/group"/>
</tal:group>
<tal:field condition="python: widget['type'] != 'group'">
<metal:call use-macro="portal/skyn/widgets/show/macros/field"/>
<metal:call use-macro="app/skyn/widgets/show/macros/field"/>
</tal:field>
</tal:showWidget>
</td>
@ -182,10 +182,10 @@
</tal:description>
<tal:comment replace="nothing">Displays a field help.</tal:comment>
<tal:help metal:define-macro="help"><acronym tal:attributes="title python: contextObj.translate('help', field=widget)"><img tal:attributes="src string: $portal_url/skyn/help.png"/></acronym></tal:help>
<tal:help metal:define-macro="help"><acronym tal:attributes="title python: contextObj.translate('help', field=widget)"><img tal:attributes="src string: $appUrl/skyn/help.png"/></acronym></tal:help>
<tal:comment replace="nothing">Displays validation-error-related info about a field.</tal:comment>
<tal:validation metal:define-macro="validation"><acronym tal:condition="inError" tal:attributes="title python: errors[name]"><img tal:attributes="src string: $portal_url/skyn/warning.png"/></acronym><img tal:condition="not: inError" tal:attributes="src string: $portal_url/skyn/warning_no.gif"/></tal:validation>
<tal:validation metal:define-macro="validation"><acronym tal:condition="inError" tal:attributes="title python: errors[name]"><img tal:attributes="src string: $appUrl/skyn/warning.png"/></acronym><img tal:condition="not: inError" tal:attributes="src string: $appUrl/skyn/warning_no.gif"/></tal:validation>
<tal:comment replace="nothing">Displays the fact that a field is required.</tal:comment>
<tal:required metal:define-macro="required"><img tal:attributes="src string: $portal_url/skyn/required.gif"/></tal:required>
<tal:required metal:define-macro="required"><img tal:attributes="src string: $appUrl/skyn/required.gif"/></tal:required>

View file

@ -74,7 +74,7 @@
content="python: ', '.join(value)">
</tal:multiple>
<tal:notMultiple condition="not: multipleValues">
<metal:call use-macro="portal/skyn/widgets/string/macros/view"/>
<metal:call use-macro="app/skyn/widgets/string/macros/view"/>
</tal:notMultiple>
</metal:cell>

View file

@ -1,82 +0,0 @@
/* Appy-specific IE-fixes */
.portletSearch { font-size: 85%; border-left: 1px solid #8cacbb; border-right: 1px solid #8cacbb; }
/* Stylesheet with Internet Explorer-specific workarounds. */
* html #portal-columns { width: 100%; }
* html*#portal-columns { width: auto; }
/* <dtml-with base_properties> */
#topIcons { right: 238px; }
#portal-globalnav { margin-top: -1px; }
#portal-globalnav th { height: 32px; }
.navTreeItem a, dd.portletItem .navTreeItem a { font-size: 105%; }
#portlet-navigation-tree { margin-top: 8px; }
.navigation-section-header { height: 28px; }
#portal-globalnav a { font-size: 110%; }
#portal-column-two .portletHeader { font-size:110%; padding-bottom:11px; }
#portlet-hp-news .portletHeader { margin-top: 1px; }
.section-ncp-home .portletHeader { font-size:110%; }
input { margin-bottom: 1px; }
table.listing td.top { position: relative; left: -1px; top: -1px; }
div#portal-columns div.portlet { text-align: left; }
div#portal-columns div#portal-column-one,
div#portal-columns div#portal-column-two { overflow: hidden; }
textarea { width: 97%; }
.visualOverflow { width: 88%; }
.visualGhosted { filter:alpha(opacity=20); }
#portal-logo {
height /**/: <dtml-var "_[logoName].height">px;
overflow: hidden;
}
#clear-space-before-wrapper-table { display: none };
/* Fix bottom margin on tabs in IE */
#portal-globalnav li.selected a { position: relative; }
#portal-colophon .colophonIcon { height: 0px !important; height /**/: 15px; }
.actionMenu .actionMenuHeader a { display: inline; }
.actionMenu .actionMenuContent { top: 1.4em; }
/* Calendar fixes */
.ploneCalendar { border-collapse:collapse; width:auto; height:1%; }
.ploneCalendar td { width:1%; }
.ploneCalendar .todaynoevent,
.ploneCalendar .todayevent { position: relative; }
.hiddenStructure { position: absolute; }
body { /* These work in IE only, changes the look of the scrollbar + textareas */
scrollbar-base-color: &dtml-globalBackgroundColor;;
scrollbar-highlight-color: &dtml-globalBackgroundColor;;
scrollbar-track-color: &dtml-evenRowBackgroundColor;;
scrollbar-darkshadow-color: &dtml-evenRowBackgroundColor;;
scrollbar-3dlight-color: &dtml-globalBorderColor;;
scrollbar-shadow-color: &dtml-globalBorderColor;;
scrollbar-arrow-color: &dtml-globalFontColor;;
}
#floatholder, #float { height: 1%; }
* html .link-external,
* html .link-external a,
* html .link-mailto a,
* html .link-mailto { height: 1%; }
* html .visualIEFloatFix,
* html h1,
* html h2,
* html h3,
* html h4,
* html h5,
* html h6,
* html dd,
* html .documentDescription,
* html .visualClear,
* html .portalMessage,
* html .portalWarningMessage,
* html .portalStopMessage,
* html .system-message,
* html #error-handling,
* html .documentContent { height: 0.1%; }
* html p { position: relative; }
* html h1.documentFirstHeading { height: auto; }
* html #objectMenu.actionMenu .actionMenuContent li { height: auto; }
#portal-searchbox { overflow: hidden; }
/* </dtml-with> */

View file

@ -1,17 +0,0 @@
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
i18n:domain="<!applicationName!>">
<body>
<div metal:define-macro="portlet"
tal:define="tool python: context.<!toolInstanceName!>;"
tal:condition="python: tool.showPortlet(context)">
<metal:block metal:use-macro="here/global_defines/macros/defines" />
<metal:prologue use-macro="here/skyn/page/macros/prologue"/>
<dl tal:define="rootClasses tool/getRootClasses;
appName string:<!applicationName!>;
appFolder tool/getAppFolder" class="portlet">
<metal:content use-macro="here/skyn/portlet/macros/portletContent"/>
</dl>
</div>
</body>
</html>

View file

@ -1,20 +1,11 @@
/* <dtml-var "enableHTTPCompression(request=REQUEST, debug=1, css=1)"> (this is for http compression) */
/* <dtml-with base_properties> (do not remove this :) */
/* <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either :) */
textarea { width: 99%; }
#portal-breadcrumbs { display: none; }
#importedElem { color: grey; font-style: italic; }
label { font-weight: bold; font-style: italic; line-height: 1.4em; font-size: 92%;}
.discreet { font-size: 94%; }
.appyList { line-height: 1.1em; margin: 0 0 0.5em 1.2em; padding: 0; }
.appyBullet { margin: 0; }
.appyPod { float:right; }
.appyNav { padding: 0.4em 0 0.4em 0; }
.appyFocus { color: #900101; }
.appyTitle { padding-top: 0.5em; font-size: 110%; }
.appyWorkflow { text-align: center; background-color: &dtml-globalBackgroundColor;;}
.appyPlusImg {
vertical-align: top;
@ -23,12 +14,6 @@ label { font-weight: bold; font-style: italic; line-height: 1.4em; font-
top: -0.55em;
}
.appyPhase {
border-style: dashed;
border-width: thin;
padding: 0 0.6em 0 1em;
}
.appyState {
font-size: 85%;
font-style: normal;
@ -61,54 +46,6 @@ label { font-weight: bold; font-style: italic; line-height: 1.4em; font-
font-size: 105%;
}
/* Following classes are used for displaying status of a phase or state. */
.stepDone {
background-color: #cde2a7;
background-image: url(&dtml-portal_url;/skyn/done.png);
background-repeat: no-repeat;
background-position: -1px 7px;
}
.stepDoneState {
background-color: #cde2a7;
background-image: url(&dtml-portal_url;/skyn/done.png);
background-repeat: no-repeat;
background-position: -1px 4px;
}
.stepCurrent {
background-color: #eef3f5;
background-image: url(&dtml-portal_url;/skyn/current.png);
background-repeat: no-repeat;
background-position: -1px 7px;
}
.stepCurrentState {
background-color: #eef3f5;
background-image: url(&dtml-portal_url;/skyn/current.png);
background-repeat: no-repeat;
background-position: -1px 4px;
}
.stepFuture {
background-color: #ffffff;
color: #C8C8C8;
border-style: dashed;
}
.stepUnselected {
background-color: #ffffff;
}
.appyCommonInfo {
border-color: #ffa500;
background-color: &dtml-evenRowBackgroundColor;;
border-style: solid;
border-width: 2px;
margin-bottom: 0.5em;
}
/* With fields layout in columns, standard error frame is too large */
.odd { background-color: white; }
/* Tooltip */
a.tooltip span {
display:none;
@ -126,18 +63,6 @@ a.tooltip:hover span {
}
/* Table styles */
.no-style-table {
border: 0 !important;
padding: 0 !important;
margin: 0 !important;
}
.no-style-table td {
border: 0 !important;
padding-left: 0 !important;
margin: 0 !important;
}
fieldset {
line-height: 1em;
border: 2px solid #8CACBB;
@ -145,41 +70,6 @@ fieldset {
padding: 0 0.7em 0.5em;
}
th {
font-style: italic;
font-weight: normal;
}
.section1 {
font-size: 120%;
margin: 0.45em 0em 0.1em 0;
padding: 0.3em 0em 0.2em 0.1em;
background-color: #eef3f5;
border-top: 1px solid #8CACBB;
border-bottom: 1px solid #8CACBB;
}
.section2 {
font-size: 110%;
font-style: italic;
margin: 0.45em 0em 0.1em 0;
border-bottom: 2px solid #8CACBB;
}
.section3 {
font-size: 100%;
font-style: italic;
margin: 0.45em 0em 0.1em 0;
background-color: #efeae8;
text-align: center;
color: grey;
}
.imageInput {
border-width: 0px;
background: none;
}
.noPadding {
padding-right: 0em !important;
padding-left: 0em !important;
@ -238,14 +128,6 @@ th {
text-transform: none;
padding: 1px 0.5em;
}
.portletAppyItem {
margin: 0;
padding: 1px 0.5em;
border-left: 1px solid #8cacbb;
border-right: 1px solid #8cacbb;
font-weight: normal;
text-transform: none;
}
.portletSearch {
padding: 0 0 0 0.6em;
font-style: normal;
@ -256,53 +138,10 @@ th {
font-weight: bold;
font-style: normal;
}
.portletSep { border-top: 1px dashed #8cacbb; }
.portletGroupItem { padding-left: 0.8em; font-style: italic; }
.portletPageItem { font-style: italic; }
.portletCurrent { font-weight: bold; }
.portletMenu { margin-bottom: 0.4em; }
div.appyGrey {
display: none;
position: absolute;
left: 0px;
top: 0px;
width:100%;
height:100%;
background:gray;
filter:alpha(Opacity=50);
opacity:0.5;
-moz-opacity:0.5;
-khtml-opacity:0.5
}
div.appyPopup {
display: none;
position: absolute;
top: 30%;
left: 35%;
width: 350px;
z-index : 100;
background: white;
padding: 8px;
border: 1px solid gray;
}
.translationLabel {
background-color: #EAEAEA;
border-bottom: 1px dashed grey;
margin-top: 1em;
margin-bottom: 0.5em;
}
/* Uncomment this if you want to hide breadcrumbs */
/*
#portal-breadcrumbs {
display: none;
}
*/
/* </dtml-with> */
/* image-right, but without border */
.image-right {
border:0px solid Black;
@ -311,47 +150,4 @@ div.appyPopup {
margin:0.5em;
}
/* DOCUMENTATION ON PRE-DEFINED PROPERTIES FROM PLONE */
/* You can insert colors and other variables from Plone's
base_properties by doing:
& dtml-variableName ; (without the spaces, excluded here to not make it render)
Example:
myLink {
color: & dtml-fontColor ; (again, without the spaces)
}
This means you can generate your own elements that use Plone's defaults,
and respect any customizations people have done. See base_properties for
the default values.
These are the available properties:
logoName - the file name of the portal logo.
fontFamily - the font family used for all text that is not headers
fontBaseSize - the base font size that everything is calculated from
fontColor - the main font color
backgroundColor - the background color
linkColor - the color used on normal links
linkActiveColor - color used on active links
linkVisitedColor - color used on visited links
borderWidth - the width of most borders in Plone
borderStyle - the style of the border lines, normally solid
borderStyleAnnotations - style of border lines on comments etc
globalBorderColor - the border color used on the main tabs, the portlets etc
globalBackgroundColor - background color for the selected tabs, portlet headings etc
globalFontColor - the color of the font in the tabs and in portlet headings
headingFontFamily - font family for h1/h2/h3/h4/h5/h6 headlines.
headingFontBaseSize - the base size used when calculating the different headline sizes
contentViewBorderColor - the content view tabs border color
contentViewBackgroundColor - the content view tabs background color
contentViewFontColor - the font color used in the content view tabs
textTransform - whether to lowercase text in portlets, tabs etc.
evenRowBackgroundColor - the background color of even rows in listings
oddRowBackgroundColor - the background color of even rows in listings
notifyBorderColor - border color of notification elements like the status message, the calendar focus
notifyBackgroundColor - background color of notification elements like the status message, the calendar focus
discreetColor:string=#999999
helpBackgroundColor:string=#ffffe1
*/

View file

@ -1,7 +0,0 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
i18n:domain="<!applicationName!>">
<body>
<div id="portal-colophon" metal:define-macro="colophon">
</div>
</body>
</html>

View file

@ -66,10 +66,8 @@ applicationGlobalRoles = [<!gRoles!>]
grantableRoles = [<!grRoles!>]
# Configuration options
showPortlet = <!showPortlet!>
languages = [<!languages!>]
languageSelector = <!languageSelector!>
minimalistPlone = <!minimalistPlone!>
appFrontPage = <!appFrontPage!>
sourceLanguage = '<!sourceLanguage!>'
# ------------------------------------------------------------------------------

View file

@ -1,7 +0,0 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
i18n:domain="<!applicationName!>">
<body>
<div id="portal-footer" metal:define-macro="portal_footer">
</div>
</body>
</html>