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