merge branch master
This commit is contained in:
commit
1800fe7c9e
11 changed files with 87 additions and 28 deletions
|
@ -737,7 +737,9 @@ on data provided in this form:
|
|||
|
||||
>>> component.provideAdapter(NameChooser)
|
||||
>>> request = TestRequest(form={'title': u'Test Note',
|
||||
... 'form.type': u'.loops/concepts/note'})
|
||||
... 'form.type': u'.loops/concepts/note',
|
||||
... 'contentType': u'text/restructured',
|
||||
... 'linkUrl': u'http://'})
|
||||
>>> view = NodeView(m112, request)
|
||||
>>> cont = CreateObject(view, request)
|
||||
>>> cont.update()
|
||||
|
@ -802,7 +804,7 @@ The new technique uses the ``fields`` and ``data`` attributes...
|
|||
linkText textline False None
|
||||
|
||||
>>> view.data
|
||||
{'linkUrl': u'http://', 'contentType': 'text/restructured', 'data': u'',
|
||||
{'linkUrl': u'http://', 'contentType': u'text/restructured', 'data': u'',
|
||||
'linkText': u'', 'title': u'Test Note'}
|
||||
|
||||
The object is changed via a FormController adapter created for
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
|
||||
# Copyright (c) 2015 Helmut Merz helmutm@cy55.de
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,8 +18,6 @@
|
|||
|
||||
"""
|
||||
Adapters and others classes for analyzing resources.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from itertools import tee
|
||||
|
@ -41,6 +39,7 @@ from loops.resource import Resource
|
|||
from loops.setup import addAndConfigureObject
|
||||
from loops.type import TypeInterfaceSourceList
|
||||
|
||||
logger = getLogger('Classifier')
|
||||
|
||||
TypeInterfaceSourceList.typeInterfaces += (IClassifier,)
|
||||
|
||||
|
@ -102,6 +101,7 @@ class Classifier(AdapterBase):
|
|||
if resource not in resources:
|
||||
concept.assignResource(resource, predicate)
|
||||
message = u'Assigning: %s %s %s'
|
||||
self.log(message % (resource.title, predicate.title, concept.title), 5)
|
||||
else:
|
||||
message = u'Already assigned: %s %s %s'
|
||||
self.log(message % (resource.title, predicate.title, concept.title), 4)
|
||||
|
@ -109,8 +109,7 @@ class Classifier(AdapterBase):
|
|||
def log(self, message, level=5):
|
||||
if level >= self.logLevel:
|
||||
#print 'Classifier %s:' % getName(self.context), message
|
||||
getLogger('Classifier').info(
|
||||
u'%s: %s' % (getName(self.context), message))
|
||||
logger.info(u'%s: %s' % (getName(self.context), message))
|
||||
|
||||
|
||||
class Extractor(object):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
|
||||
# Copyright (c) 2015 Helmut Merz helmutm@cy55.de
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,17 +18,20 @@
|
|||
|
||||
"""
|
||||
View class(es) for resource classifiers.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from logging import getLogger
|
||||
import transaction
|
||||
from zope import interface, component
|
||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
from zope.traversing.api import getName
|
||||
|
||||
from loops.browser.concept import ConceptView
|
||||
from loops.common import adapted
|
||||
|
||||
logger = getLogger('ClassifierView')
|
||||
|
||||
|
||||
class ClassifierView(ConceptView):
|
||||
|
||||
|
@ -42,12 +45,18 @@ class ClassifierView(ConceptView):
|
|||
if 'update' in self.request.form:
|
||||
cta = adapted(self.context)
|
||||
if cta is not None:
|
||||
for r in collectResources(self.context):
|
||||
for idx, r in enumerate(collectResources(self.context)):
|
||||
if idx % 1000 == 0:
|
||||
logger.info('Committing, resource # %s' % idx)
|
||||
transaction.commit()
|
||||
cta.process(r)
|
||||
logger.info('Finished processing')
|
||||
transaction.commit()
|
||||
return True
|
||||
|
||||
|
||||
def collectResources(concept, checkedConcepts=None, result=None):
|
||||
logger.info('Start collecting resources for %s' % getName(concept))
|
||||
if result is None:
|
||||
result = []
|
||||
if checkedConcepts is None:
|
||||
|
@ -59,4 +68,5 @@ def collectResources(concept, checkedConcepts=None, result=None):
|
|||
if c not in checkedConcepts:
|
||||
checkedConcepts.append(c)
|
||||
collectResources(c, checkedConcepts, result)
|
||||
logger.info('Collected %s resources' % len(result))
|
||||
return result
|
||||
|
|
Binary file not shown.
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
|
||||
"Project-Id-Version: 0.13.1\n"
|
||||
"POT-Creation-Date: 2007-05-22 12:00 CET\n"
|
||||
"PO-Revision-Date: 2015-06-06 12:00 CET\n"
|
||||
"PO-Revision-Date: 2015-09-22 12:00 CET\n"
|
||||
"Last-Translator: Helmut Merz <helmutm@cy55.de>\n"
|
||||
"Language-Team: loops developers <helmutm@cy55.de>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -597,9 +597,6 @@ msgstr "Informationen über dieses Objekt"
|
|||
msgid "Information about this object."
|
||||
msgstr "Informationen über dieses Objekt."
|
||||
|
||||
msgid "Send a link to this object by email."
|
||||
msgstr "Einen Link zu diesem Objekt per E-Mail versenden."
|
||||
|
||||
msgid "Edit with external editor."
|
||||
msgstr "Mit 'External Editor' bearbeiten."
|
||||
|
||||
|
@ -1416,3 +1413,27 @@ msgstr "Zeitraum"
|
|||
|
||||
msgid "Technology"
|
||||
msgstr "Technik"
|
||||
|
||||
# send mail
|
||||
|
||||
msgid "Send a link to this object by email."
|
||||
msgstr "Einen Link zu diesem Objekt per E-Mail versenden."
|
||||
|
||||
msgid "Send Link by Email"
|
||||
msgstr "Link per E-Mail versenden"
|
||||
|
||||
msgid "Mail Subject"
|
||||
msgstr "Betreff"
|
||||
|
||||
msgid "Mail Body"
|
||||
msgstr "Text"
|
||||
|
||||
msgid "Recipients"
|
||||
msgstr "Empfänger"
|
||||
|
||||
msgid "Additional Recipients"
|
||||
msgstr "Weitere Empfänger"
|
||||
|
||||
msgid "Send email"
|
||||
msgstr "E-Mail senden"
|
||||
|
||||
|
|
|
@ -175,6 +175,10 @@ class SendEmailForm(NodeView):
|
|||
|
||||
@Lazy
|
||||
def subject(self):
|
||||
optionKey = 'organize.sendmail_subject'
|
||||
option = self.globalOptions(optionKey) or self.typeOptions(optionKey)
|
||||
if option:
|
||||
return option[0]
|
||||
menu = self.context.getMenu()
|
||||
zdc = IZopeDublinCore(menu)
|
||||
zdc.languageInfo = self.languageInfo
|
||||
|
@ -185,6 +189,8 @@ class SendEmailForm(NodeView):
|
|||
|
||||
class SendEmail(FormController):
|
||||
|
||||
bccToSender = False
|
||||
|
||||
def checkPermissions(self):
|
||||
return (not self.isAnonymous and
|
||||
super(SendEmail, self).checkPermissions())
|
||||
|
@ -201,7 +207,10 @@ class SendEmail(FormController):
|
|||
msg = MIMEText(message.encode('utf-8'), 'plain', 'utf-8')
|
||||
msg['Subject'] = subject.encode('utf-8')
|
||||
msg['From'] = sender
|
||||
msg['To'] = ', '.join(r.strip() for r in recipients if r.strip())
|
||||
recipients = [r.strip() for r in recipients if r.strip()]
|
||||
msg['To'] = ', '.join(recipients)
|
||||
if self.bccToSender:
|
||||
recipients.append(sender)
|
||||
mailhost = component.getUtility(IMailDelivery, 'Mail')
|
||||
mailhost.send(sender, recipients, msg.as_string())
|
||||
return True
|
||||
|
|
|
@ -125,14 +125,15 @@
|
|||
<span tal:content="view/target/title"></span></div>
|
||||
<metal:content define-macro="mail_content">
|
||||
<div>
|
||||
<label i18n:translate="" for="subject">Subject</label>
|
||||
<label i18n:translate="" for="subject">Mail Subject</label>
|
||||
<div>
|
||||
<input name="subject" id="subject" style="width: 60em"
|
||||
dojoType="dijit.form.ValidationTextBox" required
|
||||
tal:attributes="value view/subject" /></div>
|
||||
</div>
|
||||
<div>
|
||||
<label i18n:translate="" for="mailbody">Mail Body</label>
|
||||
<label i18n:translate=""
|
||||
for="mailbody">Mail Body</label>
|
||||
<div>
|
||||
<textarea name="mailbody" cols="80" rows="4" id="mailbody"
|
||||
dojoType="dijit.form.SimpleTextarea" style="width: 60em"
|
||||
|
@ -155,7 +156,8 @@
|
|||
<span i18n:translate="">Toggle all</span></div>
|
||||
</div>
|
||||
<div>
|
||||
<label i18n:translate="" for="addrecipients">Additional recipients</label>
|
||||
<label i18n:translate=""
|
||||
for="addrecipients">Additional Recipients</label>
|
||||
<div>
|
||||
<textarea name="addrecipients" cols="80" rows="4" id="addrecipients"
|
||||
dojoType="dijit.form.SimpleTextarea"
|
||||
|
|
|
@ -177,11 +177,15 @@ Recent changes
|
|||
|
||||
>>> data[0].timeStamp
|
||||
u'... ...:...'
|
||||
|
||||
>>> data[0].objectData
|
||||
{'version': '', 'canAccess': True, 'title': 'Change Doc 001', 'url': '',
|
||||
'object': <loops.resource.Resource object at ...>, 'type': u'Text'}
|
||||
{'version': '', 'description': u'', 'title': 'Change Doc 001', 'url': '',
|
||||
'object': <loops.resource.Resource object at ...>, 'type': u'Text',
|
||||
'canAccess': True}
|
||||
|
||||
>>> data[0].user
|
||||
{'url': '', 'object': <loops.concept.Concept ...>, 'title': u'john'}
|
||||
|
||||
>>> data[0].action
|
||||
'modify'
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2014 Helmut Merz helmutm@cy55.de
|
||||
# Copyright (c) 2015 Helmut Merz helmutm@cy55.de
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -265,20 +265,23 @@ class TrackDetails(BaseView):
|
|||
def objectData(self):
|
||||
obj = self.object
|
||||
if obj is None:
|
||||
return dict(object=None, title='-', type='-', url='',
|
||||
return dict(object=None, title='-', description='',
|
||||
type='-', url='',
|
||||
version=None, canAccess=False)
|
||||
node = self.view.nodeView
|
||||
url = node is not None and node.getUrlForTarget(obj) or ''
|
||||
view = self.view.getViewForObject(obj)
|
||||
if view is None:
|
||||
title = obj.title
|
||||
desc = obj.description
|
||||
else:
|
||||
title = view.listingTitle
|
||||
desc = view.description
|
||||
versionable = IVersionable(self.object, None)
|
||||
version = ((versionable is not None and
|
||||
not (versionable.notVersioned) and
|
||||
versionable.versionId) or '')
|
||||
return dict(object=obj, title=title,
|
||||
return dict(object=obj, title=title, description=desc,
|
||||
type=self.longTypeTitle, url=url, version=version,
|
||||
canAccess=canAccessObject(obj))
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<tr tal:define="wiType row/workItemType"
|
||||
tal:attributes="class wiType/indicator|nothing">
|
||||
<td class="nowrap center"
|
||||
tal:define="today python: row.isToday and ' today' or ''"
|
||||
tal:define="today python:row.isToday and ' today' or ''"
|
||||
tal:attributes="title row/weekDay;
|
||||
class string:nowrap center$today"
|
||||
i18n:attributes="title"
|
||||
|
@ -35,9 +35,10 @@
|
|||
<td class="nowrap center" tal:content="row/start">17:30</td>
|
||||
<td class="nowrap center" tal:content="row/end">20:00</td>
|
||||
<td class="nowrap center" tal:content="row/duration">2:30</td>
|
||||
<td tal:condition="python: 'Task' in work.columns">
|
||||
<td tal:condition="python:'Task' in work.columns">
|
||||
<a tal:define="data row/objectData"
|
||||
tal:attributes="href data/url"
|
||||
tal:attributes="href data/url;
|
||||
title data/description"
|
||||
tal:content="data/title">Task</a></td>
|
||||
<td tal:condition="python: 'User' in work.columns">
|
||||
<a tal:attributes="href row/user/url"
|
||||
|
|
8
table.py
8
table.py
|
@ -88,6 +88,13 @@ class DataTable(AdapterBase):
|
|||
if data is None:
|
||||
data = OOBTree()
|
||||
self.context._data = data
|
||||
reclen = len(self.columns) - 1
|
||||
for k, v in data.items():
|
||||
v = v[:reclen]
|
||||
missing = reclen - len(v)
|
||||
if missing > 0:
|
||||
v += (missing * [u''])
|
||||
data[k] = v
|
||||
return data
|
||||
def setData(self, data):
|
||||
self.context._data = OOBTree(data)
|
||||
|
@ -102,6 +109,7 @@ class DataTable(AdapterBase):
|
|||
item[c] = k
|
||||
else:
|
||||
item[c] = v[idx-1]
|
||||
#item[c] = len(v) > idx and v[idx-1] or u''
|
||||
result.append(item)
|
||||
return result
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue