use collective.recipe.sphinxbuilder;
svn path=/plone.app.discussion/trunk/; revision=35274
This commit is contained in:
parent
8150617081
commit
6135fcf6d4
@ -7,6 +7,7 @@ parts =
|
||||
test
|
||||
coverage-test
|
||||
coverage-report
|
||||
sphinxbuilder
|
||||
|
||||
dump-picked-versions-file = versions.cfg
|
||||
overwrite-picked-versions-file = True
|
||||
@ -28,6 +29,7 @@ find-links =
|
||||
|
||||
# Add additional eggs here
|
||||
eggs =
|
||||
Sphinx
|
||||
plone.app.discussion
|
||||
plone.formwidget.captcha
|
||||
plone.formwidget.recaptcha
|
||||
@ -45,6 +47,7 @@ auto-checkout =
|
||||
|
||||
[versions]
|
||||
zope.schema = 3.6.0
|
||||
Sphinx = 0.6.4
|
||||
|
||||
[instance]
|
||||
# For more information on this step and configuration options see:
|
||||
@ -96,6 +99,10 @@ eggs = z3c.coverage
|
||||
scripts = coverage=coverage-report
|
||||
arguments = ('coverage', 'report')
|
||||
|
||||
[sphinxbuilder]
|
||||
recipe = collective.recipe.sphinxbuilder
|
||||
interpreter = ${buildout:directory}/bin/zopepy
|
||||
|
||||
[sources]
|
||||
plone.formwidget.captcha = svn https://svn.plone.org/svn/plone/plone.formwidget.captcha/trunk
|
||||
plone.formwidget.recaptcha = svn https://svn.plone.org/svn/plone/plone.formwidget.recaptcha/trunk
|
||||
|
@ -3,14 +3,14 @@
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SPHINXBUILD = /home/timo/workspace/pad/plone.app.discussion/bin/zopepy /home/timo/workspace/pad/plone.app.discussion/bin/sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = build
|
||||
BUILDDIR = /home/timo/workspace/pad/plone.app.discussion/docs
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) /home/timo/workspace/pad/plone.app.discussion/docs/source
|
||||
|
||||
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
|
||||
|
||||
@ -61,9 +61,9 @@ qthelp:
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ploneappdiscussion.qhcp"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sphinxbuilder.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ploneappdiscussion.qhc"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sphinxbuilder.qhc"
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
|
BIN
docs/build/doctrees/environment.pickle
vendored
BIN
docs/build/doctrees/environment.pickle
vendored
Binary file not shown.
BIN
docs/build/doctrees/index.doctree
vendored
BIN
docs/build/doctrees/index.doctree
vendored
Binary file not shown.
3
docs/build/html/objects.inv
vendored
3
docs/build/html/objects.inv
vendored
@ -1,3 +0,0 @@
|
||||
# Sphinx inventory version 1
|
||||
# Project: plone.app.discussion
|
||||
# Version: 1.0b4
|
1
docs/build/html/searchindex.js
vendored
1
docs/build/html/searchindex.js
vendored
@ -1 +0,0 @@
|
||||
Search.setIndex({desctypes:{},terms:{index:0,search:0,welcom:0,app:0,indic:0,discuss:0,content:0,tabl:0,modul:0,document:0,plone:0,page:0},titles:["Welcome to plone.app.discussion’s documentation!"],modules:{},descrefs:{},filenames:["index"]})
|
BIN
docs/doctrees/architecture.doctree
Normal file
BIN
docs/doctrees/architecture.doctree
Normal file
Binary file not shown.
BIN
docs/doctrees/design.doctree
Normal file
BIN
docs/doctrees/design.doctree
Normal file
Binary file not shown.
BIN
docs/doctrees/environment.pickle
Normal file
BIN
docs/doctrees/environment.pickle
Normal file
Binary file not shown.
BIN
docs/doctrees/index.doctree
Normal file
BIN
docs/doctrees/index.doctree
Normal file
Binary file not shown.
59
docs/html/_sources/architecture.txt
Normal file
59
docs/html/_sources/architecture.txt
Normal file
@ -0,0 +1,59 @@
|
||||
========================
|
||||
Architectural Principles
|
||||
========================
|
||||
|
||||
This document outlines architectural principles used in the design of
|
||||
plone.app.discussion.
|
||||
|
||||
**Discussion items have a portal_type**
|
||||
This makes it easier to search for them and manage them using existing
|
||||
CMF and Plone UI constructs.
|
||||
|
||||
**Discussion items are cataloged**
|
||||
It is be possible to search for discussion items like any other type of
|
||||
content.
|
||||
|
||||
**Discussion items are subject to workflow and permission**
|
||||
Moderation, anonymous commenting, and auto approve/reject should be
|
||||
handled using workflow states, automatic and manual transitions, and
|
||||
permissions.
|
||||
|
||||
**Discussion items are light weight objects**
|
||||
Discussion item objects are as light weight as possible.
|
||||
Ideally, a discussion item should be as lightweight as a catalog brain.
|
||||
This may mean that we forego convenience base classes and re-implement
|
||||
certain interfaces. Comments should not provide the full set of dublin
|
||||
core metadata, though custom indexers can be used to provide values for
|
||||
standard catalog indexes.
|
||||
|
||||
**Optimise for retrival speed**
|
||||
HTML filtering and other processing should happen on save, not on render,
|
||||
to make rendering quick.
|
||||
|
||||
**Settings are stored using plone.registry**
|
||||
Any global setting should be stored in plone.registry records
|
||||
|
||||
**Forms are constructed using extensible z3c.form forms**
|
||||
This allows plugins (such as spam protection algorithms) to provide
|
||||
additional validation
|
||||
|
||||
**Discussion items are stored in a BTree container**
|
||||
This allows faster lookup and manipulation
|
||||
|
||||
**Discussion items are accessed using a dict-like interface**
|
||||
This makes iteration and manipulation more natural. Even if comments are
|
||||
not stored threaded, the dict interface should act as if they are, i.e.
|
||||
calling items() on a comment should return the replies to that comment
|
||||
(in order).
|
||||
|
||||
**Discussion items are retrieved in reverse creation date order**
|
||||
Discussion items do not need to support explicit ordering. They should
|
||||
always be retrieved in reverse creation date order (most recent for).
|
||||
They can be stored with keys so that this is always true.
|
||||
|
||||
**Discussion items do not need readable ids**
|
||||
Ids can be based on the creation date.
|
||||
|
||||
**Discussion items send events**
|
||||
The usual zope.lifecycleevent and zope.container events are fired when
|
||||
discussion items are added, removed, or modified.
|
169
docs/html/_sources/design.txt
Normal file
169
docs/html/_sources/design.txt
Normal file
@ -0,0 +1,169 @@
|
||||
============
|
||||
Design Notes
|
||||
============
|
||||
|
||||
This document contains design notes for plone.app.discussion.
|
||||
|
||||
Storage and traversal
|
||||
---------------------
|
||||
|
||||
For each content item, there is a Conversation object stored in annotations.
|
||||
This can be traversed to via the ++conversation++ namespace, but also fetched
|
||||
via an adapter lookup to IConversation.
|
||||
|
||||
The conversation stores all comments related to a content object. Each
|
||||
comment has an integer id (also representable as a string, to act as an OFS
|
||||
id and allow traversal). Hence, traversing to obj/++conversation++/123 retrieves
|
||||
the comment with id 123.
|
||||
|
||||
Comments ids are assigned in order, so a comment with id N was posted before
|
||||
a comment with id N + 1. However, it is not guaranteed that ids will be
|
||||
incremental. Ids must be positive integers - 0 or negative numbers are not
|
||||
allowed.
|
||||
|
||||
Threading information is stored in the conversation: we keep track of the
|
||||
set of children and the parent if any comment. Top-level comments have a
|
||||
parent id of 0. This information is managed by the conversation class when
|
||||
comments are manipulated using a dict-like API.
|
||||
|
||||
Note that the __parent__/acquisition parent of an IComment is the
|
||||
IConversation, and the __parent__/acquisition parent of an IConversation is
|
||||
the content object.
|
||||
|
||||
Events
|
||||
------
|
||||
|
||||
Manipulating the IConversation object should fire the usual IObjectAddedEvent
|
||||
and IObjectRemovedEvent events. The UI may further fire IObjectCreatedEvent
|
||||
and IObjectModifiedEvent for comments.
|
||||
|
||||
Factories
|
||||
---------
|
||||
|
||||
Comments should always be created via the 'Discussion Item' IFactory utility.
|
||||
Conversations should always be obtained via the IConversation adapter (even
|
||||
the ++conversation++ namespace should use this). This makes it possible to
|
||||
replace conversations and comments transparently.
|
||||
|
||||
The Comment class
|
||||
-----------------
|
||||
|
||||
The inheritance tree for DiscussionItem is shown below. Classes we want to
|
||||
mix in and interface we want to implement in the Comment class are marked
|
||||
with [x].
|
||||
|
||||
[ ] DiscussionItem
|
||||
[ ] Document
|
||||
[ ] PortalContent = [ ] IContentish
|
||||
[ ] DynamicType = [ ] IDynamicType
|
||||
[ ] CMFCatalogAware = [ ] <no interface>
|
||||
[ ] SimpleItem = [ ] ISimpleItem
|
||||
[ ] Item [ ]
|
||||
[?] Base = [ ] <no interface>
|
||||
[ ] Resource = [ ] <no interface>
|
||||
[ ] CopySource = [ ] ICopySource
|
||||
[ ] Tabs = [ ] <no interface>
|
||||
[x] Traversable = [ ] ITraversable
|
||||
[ ] Element = [ ] <no interface>
|
||||
[x] Owned = [ ] IOwned
|
||||
[ ] UndoSupport = [ ] IUndoSupport
|
||||
[ ] Persistent [ ]
|
||||
[ ] Implicit [ ]
|
||||
[x] RoleManager = [ ] IRoleManager
|
||||
[ ] RoleManager = [ ] IPermissionMappingSupport
|
||||
[ ] DefaultDublinCoreImpl = [ ] IDublinCore
|
||||
[ ] ICatalogableDublinCore
|
||||
[ ] IMutableDublinCore
|
||||
[ ] PropertyManager = [ ] IPropertyManager
|
||||
|
||||
Thus, we want:
|
||||
|
||||
* Traversable, to get absolute_url() and friends
|
||||
- this requires a good acquisition chain at all times
|
||||
* Acquisition.Explicit, to support acquisition
|
||||
- we do not want implicit acquisition
|
||||
* Owned, to be able to track ownership
|
||||
* RoleManager, to support permissions and local roles
|
||||
|
||||
We also want to use a number of custom indexers for most of the standard
|
||||
metadata such as creator, effective date etc.
|
||||
|
||||
Finally, we'll need event handlers to perform the actual indexing.
|
||||
|
||||
Discussion settings
|
||||
-------------------
|
||||
|
||||
Discussion can be enabled per-type and per-instance, via values in the FTI
|
||||
(allow_discussion) and on the object. These will remain unchanged. The
|
||||
IConversation object's 'enabled' property should consult these.
|
||||
|
||||
Global settings should be managed using plone.registry. A control panel
|
||||
can be generated from this as well, using the helper class in
|
||||
plone.app.registry.
|
||||
|
||||
Note that some settings, notably those to do with permissions and workflow,
|
||||
will need to be wired up as custom form fields with custom data mangers
|
||||
or similar.
|
||||
|
||||
Workflow and permissions
|
||||
------------------------
|
||||
|
||||
Where possible, we should use existing permissions:
|
||||
|
||||
* View
|
||||
* Reply to Item
|
||||
* Modify Portal Content
|
||||
* Request Review
|
||||
|
||||
In addition, we'll need a 'Moderator' role and a moderation permission,
|
||||
|
||||
* Moderate comment
|
||||
* Bypass moderation
|
||||
|
||||
To control whether Anonymous can post comments, we manage the 'Reply to Item'
|
||||
permission. To control whether moderation is required for various roles, we
|
||||
could manage the 'Bypass moderation' permission.
|
||||
|
||||
These could work in a workflow like this:
|
||||
|
||||
* --> [posted] -- {publish} --> [published]--> *
|
||||
| ^
|
||||
| |
|
||||
+----- {auto-publish} -----+
|
||||
| |
|
||||
+----- {auto-moderate} ----+
|
||||
|
||||
The 'posted' state is the initial state. 'published' is the state where the
|
||||
comment is visible to non-reviewers.
|
||||
|
||||
The 'publish' transition would be protected by the 'Moderate comment'
|
||||
permission. We could have states and transition for 'rejected', etc, but it
|
||||
is probably just as good to delete comments that are rejected.
|
||||
|
||||
The 'auto-publish' transition would be an automatic transition protected by
|
||||
the 'Bypass moderation' permission.
|
||||
|
||||
The 'auto-moderate' transition would be another automatic transition protected
|
||||
by an expression (e.g. calling a view) that returns True if the user is on
|
||||
an auto-moderation 'white-list', e.g. by email address or username.
|
||||
|
||||
Forms and UI
|
||||
------------
|
||||
|
||||
The basic commenting display/reply form should be placed in a viewlet.
|
||||
|
||||
Ideally, the reply form should be inline, perhaps revealed with JavaScript
|
||||
if enabled. This allows full contextualisation of replies. The current
|
||||
solution, with a separate form that shows some context, is brittle and
|
||||
over-complicated.
|
||||
|
||||
If we support quoting of comments in replies, we can load the text to quote
|
||||
using JavaScript as well.
|
||||
|
||||
As a fall-back for non-JavaScript enabled browsers, it is probably OK not to
|
||||
support quoting and/or viewing of context, e.g. the user is taken to a standalone
|
||||
'comment reply' form.
|
||||
|
||||
All actual forms should be handled using z3c.form and plone.z3cform's
|
||||
ExtensibleForm support. This makes it possible to plug in additional fields
|
||||
declaratively, e.g. to include spam protection.
|
@ -6,11 +6,29 @@
|
||||
Welcome to plone.app.discussion's documentation!
|
||||
================================================
|
||||
|
||||
.. module:`plone.app.discussion`
|
||||
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
architecture.txt
|
||||
design.txt
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. automodule:: plone.app.discussion
|
||||
|
||||
.. autoclass:: plone.app.discussion.conversation.Conversation
|
||||
|
||||
.. automethod:: plone.app.discussion.conversation.Conversation.enabled
|
||||
|
||||
.. include:: ../../CHANGES.txt
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
@ -166,18 +166,6 @@ div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.admonition p {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.admonition pre {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.admonition ul, div.admonition ol {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
Before Width: | Height: | Size: 392 B After Width: | Height: | Size: 392 B |
Before Width: | Height: | Size: 199 B After Width: | Height: | Size: 199 B |
Before Width: | Height: | Size: 199 B After Width: | Height: | Size: 199 B |
159
docs/html/architecture.html
Normal file
159
docs/html/architecture.html
Normal file
@ -0,0 +1,159 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Architectural Principles — plone.app.discussion v1.0b4 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '#',
|
||||
VERSION: '1.0b4',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="plone.app.discussion v1.0b4 documentation" href="index.html" />
|
||||
<link rel="next" title="Design Notes" href="design.html" />
|
||||
<link rel="prev" title="Welcome to plone.app.discussion’s documentation!" href="index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="modindex.html" title="Global Module Index"
|
||||
accesskey="M">modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="design.html" title="Design Notes"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="index.html" title="Welcome to plone.app.discussion’s documentation!"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="architectural-principles">
|
||||
<h1>Architectural Principles<a class="headerlink" href="#architectural-principles" title="Permalink to this headline">¶</a></h1>
|
||||
<p>This document outlines architectural principles used in the design of
|
||||
plone.app.discussion.</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><strong>Discussion items have a portal_type</strong></dt>
|
||||
<dd>This makes it easier to search for them and manage them using existing
|
||||
CMF and Plone UI constructs.</dd>
|
||||
<dt><strong>Discussion items are cataloged</strong></dt>
|
||||
<dd>It is be possible to search for discussion items like any other type of
|
||||
content.</dd>
|
||||
<dt><strong>Discussion items are subject to workflow and permission</strong></dt>
|
||||
<dd>Moderation, anonymous commenting, and auto approve/reject should be
|
||||
handled using workflow states, automatic and manual transitions, and
|
||||
permissions.</dd>
|
||||
<dt><strong>Discussion items are light weight objects</strong></dt>
|
||||
<dd>Discussion item objects are as light weight as possible.
|
||||
Ideally, a discussion item should be as lightweight as a catalog brain.
|
||||
This may mean that we forego convenience base classes and re-implement
|
||||
certain interfaces. Comments should not provide the full set of dublin
|
||||
core metadata, though custom indexers can be used to provide values for
|
||||
standard catalog indexes.</dd>
|
||||
<dt><strong>Optimise for retrival speed</strong></dt>
|
||||
<dd>HTML filtering and other processing should happen on save, not on render,
|
||||
to make rendering quick.</dd>
|
||||
<dt><strong>Settings are stored using plone.registry</strong></dt>
|
||||
<dd>Any global setting should be stored in plone.registry records</dd>
|
||||
<dt><strong>Forms are constructed using extensible z3c.form forms</strong></dt>
|
||||
<dd>This allows plugins (such as spam protection algorithms) to provide
|
||||
additional validation</dd>
|
||||
<dt><strong>Discussion items are stored in a BTree container</strong></dt>
|
||||
<dd>This allows faster lookup and manipulation</dd>
|
||||
<dt><strong>Discussion items are accessed using a dict-like interface</strong></dt>
|
||||
<dd>This makes iteration and manipulation more natural. Even if comments are
|
||||
not stored threaded, the dict interface should act as if they are, i.e.
|
||||
calling items() on a comment should return the replies to that comment
|
||||
(in order).</dd>
|
||||
<dt><strong>Discussion items are retrieved in reverse creation date order</strong></dt>
|
||||
<dd>Discussion items do not need to support explicit ordering. They should
|
||||
always be retrieved in reverse creation date order (most recent for).
|
||||
They can be stored with keys so that this is always true.</dd>
|
||||
<dt><strong>Discussion items do not need readable ids</strong></dt>
|
||||
<dd>Ids can be based on the creation date.</dd>
|
||||
<dt><strong>Discussion items send events</strong></dt>
|
||||
<dd>The usual zope.lifecycleevent and zope.container events are fired when
|
||||
discussion items are added, removed, or modified.</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="index.html"
|
||||
title="previous chapter">Welcome to plone.app.discussion’s documentation!</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="design.html"
|
||||
title="next chapter">Design Notes</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/architecture.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="modindex.html" title="Global Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="design.html" title="Design Notes"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="index.html" title="Welcome to plone.app.discussion’s documentation!"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2010, Timo Stollenwerk.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
303
docs/html/design.html
Normal file
303
docs/html/design.html
Normal file
@ -0,0 +1,303 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Design Notes — plone.app.discussion v1.0b4 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '#',
|
||||
VERSION: '1.0b4',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="plone.app.discussion v1.0b4 documentation" href="index.html" />
|
||||
<link rel="prev" title="Architectural Principles" href="architecture.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="modindex.html" title="Global Module Index"
|
||||
accesskey="M">modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="architecture.html" title="Architectural Principles"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="design-notes">
|
||||
<h1>Design Notes<a class="headerlink" href="#design-notes" title="Permalink to this headline">¶</a></h1>
|
||||
<p>This document contains design notes for plone.app.discussion.</p>
|
||||
<div class="section" id="storage-and-traversal">
|
||||
<h2>Storage and traversal<a class="headerlink" href="#storage-and-traversal" title="Permalink to this headline">¶</a></h2>
|
||||
<p>For each content item, there is a Conversation object stored in annotations.
|
||||
This can be traversed to via the ++conversation++ namespace, but also fetched
|
||||
via an adapter lookup to IConversation.</p>
|
||||
<p>The conversation stores all comments related to a content object. Each
|
||||
comment has an integer id (also representable as a string, to act as an OFS
|
||||
id and allow traversal). Hence, traversing to obj/++conversation++/123 retrieves
|
||||
the comment with id 123.</p>
|
||||
<p>Comments ids are assigned in order, so a comment with id N was posted before
|
||||
a comment with id N + 1. However, it is not guaranteed that ids will be
|
||||
incremental. Ids must be positive integers - 0 or negative numbers are not
|
||||
allowed.</p>
|
||||
<p>Threading information is stored in the conversation: we keep track of the
|
||||
set of children and the parent if any comment. Top-level comments have a
|
||||
parent id of 0. This information is managed by the conversation class when
|
||||
comments are manipulated using a dict-like API.</p>
|
||||
<p>Note that the __parent__/acquisition parent of an IComment is the
|
||||
IConversation, and the __parent__/acquisition parent of an IConversation is
|
||||
the content object.</p>
|
||||
</div>
|
||||
<div class="section" id="events">
|
||||
<h2>Events<a class="headerlink" href="#events" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Manipulating the IConversation object should fire the usual IObjectAddedEvent
|
||||
and IObjectRemovedEvent events. The UI may further fire IObjectCreatedEvent
|
||||
and IObjectModifiedEvent for comments.</p>
|
||||
</div>
|
||||
<div class="section" id="factories">
|
||||
<h2>Factories<a class="headerlink" href="#factories" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Comments should always be created via the ‘Discussion Item’ IFactory utility.
|
||||
Conversations should always be obtained via the IConversation adapter (even
|
||||
the ++conversation++ namespace should use this). This makes it possible to
|
||||
replace conversations and comments transparently.</p>
|
||||
</div>
|
||||
<div class="section" id="the-comment-class">
|
||||
<h2>The Comment class<a class="headerlink" href="#the-comment-class" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The inheritance tree for DiscussionItem is shown below. Classes we want to
|
||||
mix in and interface we want to implement in the Comment class are marked
|
||||
with [x].</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt>[ ] DiscussionItem</dt>
|
||||
<dd><dl class="first last docutils">
|
||||
<dt>[ ] Document</dt>
|
||||
<dd><dl class="first last docutils">
|
||||
<dt>[ ] PortalContent = [ ] IContentish</dt>
|
||||
<dd><p class="first">[ ] DynamicType = [ ] IDynamicType
|
||||
[ ] CMFCatalogAware = [ ] <no interface>
|
||||
[ ] SimpleItem = [ ] ISimpleItem</p>
|
||||
<blockquote class="last">
|
||||
<dl class="docutils">
|
||||
<dt>[ ] Item [ ]</dt>
|
||||
<dd>[?] Base = [ ] <no interface>
|
||||
[ ] Resource = [ ] <no interface>
|
||||
[ ] CopySource = [ ] ICopySource
|
||||
[ ] Tabs = [ ] <no interface>
|
||||
[x] Traversable = [ ] ITraversable
|
||||
[ ] Element = [ ] <no interface>
|
||||
[x] Owned = [ ] IOwned
|
||||
[ ] UndoSupport = [ ] IUndoSupport</dd>
|
||||
</dl>
|
||||
<p>[ ] Persistent [ ]
|
||||
[ ] Implicit [ ]
|
||||
[x] RoleManager = [ ] IRoleManager</p>
|
||||
<blockquote>
|
||||
[ ] RoleManager = [ ] IPermissionMappingSupport</blockquote>
|
||||
</blockquote>
|
||||
</dd>
|
||||
<dt>[ ] DefaultDublinCoreImpl = [ ] IDublinCore</dt>
|
||||
<dd><blockquote class="first">
|
||||
[ ] ICatalogableDublinCore
|
||||
[ ] IMutableDublinCore</blockquote>
|
||||
<p class="last">[ ] PropertyManager = [ ] IPropertyManager</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>Thus, we want:</p>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><dl class="first docutils">
|
||||
<dt>Traversable, to get absolute_url() and friends</dt>
|
||||
<dd><ul class="first last simple">
|
||||
<li>this requires a good acquisition chain at all times</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li><dl class="first docutils">
|
||||
<dt>Acquisition.Explicit, to support acquisition</dt>
|
||||
<dd><ul class="first last simple">
|
||||
<li>we do not want implicit acquisition</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li><p class="first">Owned, to be able to track ownership</p>
|
||||
</li>
|
||||
<li><p class="first">RoleManager, to support permissions and local roles</p>
|
||||
</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>We also want to use a number of custom indexers for most of the standard
|
||||
metadata such as creator, effective date etc.</p>
|
||||
<p>Finally, we’ll need event handlers to perform the actual indexing.</p>
|
||||
</div>
|
||||
<div class="section" id="discussion-settings">
|
||||
<h2>Discussion settings<a class="headerlink" href="#discussion-settings" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Discussion can be enabled per-type and per-instance, via values in the FTI
|
||||
(allow_discussion) and on the object. These will remain unchanged. The
|
||||
IConversation object’s ‘enabled’ property should consult these.</p>
|
||||
<p>Global settings should be managed using plone.registry. A control panel
|
||||
can be generated from this as well, using the helper class in
|
||||
plone.app.registry.</p>
|
||||
<p>Note that some settings, notably those to do with permissions and workflow,
|
||||
will need to be wired up as custom form fields with custom data mangers
|
||||
or similar.</p>
|
||||
</div>
|
||||
<div class="section" id="workflow-and-permissions">
|
||||
<h2>Workflow and permissions<a class="headerlink" href="#workflow-and-permissions" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Where possible, we should use existing permissions:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>View</li>
|
||||
<li>Reply to Item</li>
|
||||
<li>Modify Portal Content</li>
|
||||
<li>Request Review</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>In addition, we’ll need a ‘Moderator’ role and a moderation permission,</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>Moderate comment</li>
|
||||
<li>Bypass moderation</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>To control whether Anonymous can post comments, we manage the ‘Reply to Item’
|
||||
permission. To control whether moderation is required for various roles, we
|
||||
could manage the ‘Bypass moderation’ permission.</p>
|
||||
<p>These could work in a workflow like this:</p>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><dl class="first docutils">
|
||||
<dt>–> [posted] – {publish} –> [published]–> *</dt>
|
||||
<dd><div class="first line-block">
|
||||
<div class="line">^</div>
|
||||
<div class="line"><a href="#id1"><span class="problematic" id="id2">|</span></a></div>
|
||||
</div>
|
||||
<p class="last">+—– {auto-publish} —–+
|
||||
| |
|
||||
+—– {auto-moderate} —-+</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>The ‘posted’ state is the initial state. ‘published’ is the state where the
|
||||
comment is visible to non-reviewers.</p>
|
||||
<p>The ‘publish’ transition would be protected by the ‘Moderate comment’
|
||||
permission. We could have states and transition for ‘rejected’, etc, but it
|
||||
is probably just as good to delete comments that are rejected.</p>
|
||||
<p>The ‘auto-publish’ transition would be an automatic transition protected by
|
||||
the ‘Bypass moderation’ permission.</p>
|
||||
<p>The ‘auto-moderate’ transition would be another automatic transition protected
|
||||
by an expression (e.g. calling a view) that returns True if the user is on
|
||||
an auto-moderation ‘white-list’, e.g. by email address or username.</p>
|
||||
</div>
|
||||
<div class="section" id="forms-and-ui">
|
||||
<h2>Forms and UI<a class="headerlink" href="#forms-and-ui" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The basic commenting display/reply form should be placed in a viewlet.</p>
|
||||
<p>Ideally, the reply form should be inline, perhaps revealed with JavaScript
|
||||
if enabled. This allows full contextualisation of replies. The current
|
||||
solution, with a separate form that shows some context, is brittle and
|
||||
over-complicated.</p>
|
||||
<p>If we support quoting of comments in replies, we can load the text to quote
|
||||
using JavaScript as well.</p>
|
||||
<p>As a fall-back for non-JavaScript enabled browsers, it is probably OK not to
|
||||
support quoting and/or viewing of context, e.g. the user is taken to a standalone
|
||||
‘comment reply’ form.</p>
|
||||
<p>All actual forms should be handled using z3c.form and plone.z3cform’s
|
||||
ExtensibleForm support. This makes it possible to plug in additional fields
|
||||
declaratively, e.g. to include spam protection.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="#">Design Notes</a><ul>
|
||||
<li><a class="reference external" href="#storage-and-traversal">Storage and traversal</a></li>
|
||||
<li><a class="reference external" href="#events">Events</a></li>
|
||||
<li><a class="reference external" href="#factories">Factories</a></li>
|
||||
<li><a class="reference external" href="#the-comment-class">The Comment class</a></li>
|
||||
<li><a class="reference external" href="#discussion-settings">Discussion settings</a></li>
|
||||
<li><a class="reference external" href="#workflow-and-permissions">Workflow and permissions</a></li>
|
||||
<li><a class="reference external" href="#forms-and-ui">Forms and UI</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="architecture.html"
|
||||
title="previous chapter">Architectural Principles</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/design.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="modindex.html" title="Global Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="architecture.html" title="Architectural Principles"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2010, Timo Stollenwerk.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -28,6 +28,9 @@
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="#" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="modindex.html" title="Global Module Index"
|
||||
accesskey="M">modules</a> |</li>
|
||||
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -40,11 +43,32 @@
|
||||
|
||||
<h1 id="index">Index</h1>
|
||||
|
||||
|
||||
<a href="#C"><strong>C</strong></a> | <a href="#E"><strong>E</strong></a> | <a href="#P"><strong>P</strong></a>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
<h2 id="C">C</h2>
|
||||
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
|
||||
<dl>
|
||||
|
||||
<dt><a href="index.html#plone.app.discussion.conversation.Conversation">Conversation (class in plone.app.discussion.conversation)</a></dt></dl></td><td width="33%" valign="top"><dl>
|
||||
</dl></td></tr></table>
|
||||
|
||||
<h2 id="E">E</h2>
|
||||
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
|
||||
<dl>
|
||||
|
||||
<dt><a href="index.html#plone.app.discussion.conversation.Conversation.enabled">enabled() (plone.app.discussion.conversation.Conversation method)</a></dt></dl></td><td width="33%" valign="top"><dl>
|
||||
</dl></td></tr></table>
|
||||
|
||||
<h2 id="P">P</h2>
|
||||
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
|
||||
<dl>
|
||||
|
||||
<dt><a href="index.html#module-plone.app.discussion">plone.app.discussion (module)</a></dt></dl></td><td width="33%" valign="top"><dl>
|
||||
</dl></td></tr></table>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
@ -78,12 +102,15 @@
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="#" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="modindex.html" title="Global Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2010, Timo Stollenwerk.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.5.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
278
docs/html/index.html
Normal file
278
docs/html/index.html
Normal file
@ -0,0 +1,278 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Welcome to plone.app.discussion’s documentation! — plone.app.discussion v1.0b4 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '#',
|
||||
VERSION: '1.0b4',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="plone.app.discussion v1.0b4 documentation" href="#" />
|
||||
<link rel="next" title="Architectural Principles" href="architecture.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="modindex.html" title="Global Module Index"
|
||||
accesskey="M">modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="architecture.html" title="Architectural Principles"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li><a href="#">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="welcome-to-plone-app-discussion-s-documentation">
|
||||
<h1>Welcome to plone.app.discussion’s documentation!<a class="headerlink" href="#welcome-to-plone-app-discussion-s-documentation" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Contents:</p>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference external" href="architecture.html">Architectural Principles</a></li>
|
||||
<li class="toctree-l1"><a class="reference external" href="design.html">Design Notes</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="design.html#storage-and-traversal">Storage and traversal</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="design.html#events">Events</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="design.html#factories">Factories</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="design.html#the-comment-class">The Comment class</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="design.html#discussion-settings">Discussion settings</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="design.html#workflow-and-permissions">Workflow and permissions</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="design.html#forms-and-ui">Forms and UI</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="section" id="module-plone.app.discussion">
|
||||
<h2>API<a class="headerlink" href="#module-plone.app.discussion" title="Permalink to this headline">¶</a></h2>
|
||||
<dl class="class">
|
||||
<dt id="plone.app.discussion.conversation.Conversation">
|
||||
<em class="property">class </em><tt class="descclassname">plone.app.discussion.conversation.</tt><tt class="descname">Conversation</tt><big>(</big><em>id='++conversation++default'</em><big>)</big><a class="headerlink" href="#plone.app.discussion.conversation.Conversation" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>A conversation is a container for all comments on a content object.</p>
|
||||
<p>It manages internal data structures for comment threading and efficient
|
||||
comment lookup.</p>
|
||||
<dl class="method">
|
||||
<dt id="plone.app.discussion.conversation.Conversation.enabled">
|
||||
<tt class="descname">enabled</tt><big>(</big><big>)</big><a class="headerlink" href="#plone.app.discussion.conversation.Conversation.enabled" title="Permalink to this definition">¶</a></dt>
|
||||
<dd>hi world</dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="changelog">
|
||||
<h1>Changelog<a class="headerlink" href="#changelog" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="b4-unreleased">
|
||||
<h2>1.0b4 (unreleased)<a class="headerlink" href="#b4-unreleased" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Fix #662654: As an administrator, I can configure a Collection to show recent comments.
|
||||
Comment.Type() now correctly returns the FTI title (‘Comment’)
|
||||
[chaoflow]</li>
|
||||
<li>German translation updated.
|
||||
[juh]</li>
|
||||
<li>Fix #2419342: Fix untranslated published/deleted status messages.
|
||||
[timo]</li>
|
||||
<li>Remove fixed width of the actions column of the moderation view. The
|
||||
translated button titles can differ in size from the English titles.
|
||||
[timo]</li>
|
||||
<li>Fix #2494228: Remove comments as well when a content object is deleted.
|
||||
[timo]</li>
|
||||
<li>Fix unicode error when non-ASCII characters are typed into the name field of a
|
||||
comment by anonymous users.
|
||||
[regebro]</li>
|
||||
<li>New feature: As a moderator, I am notified when new comments require my
|
||||
attention.
|
||||
[timo]</li>
|
||||
<li>Make p.a.d. work with the recent version of plone.z3cform (0.5.10)
|
||||
[timo]</li>
|
||||
<li>Make p.a.d. styles less generic. This fixes #10253.
|
||||
[timo]</li>
|
||||
<li>Added greek translation.
|
||||
[ggozad]</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="b3-2010-01-28">
|
||||
<h2>1.0b3 (2010-01-28)<a class="headerlink" href="#b3-2010-01-28" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Added an i18n directory for messages in the plone domain and updated scripts
|
||||
to rebuild and sync it.
|
||||
[hannosch]</li>
|
||||
<li>Added an optional conversationCanonicalAdapterFactory showing how to share
|
||||
comments across all translations with LinguaPlone, by storing and retrieving
|
||||
the conversation from the canonical object.
|
||||
[hannosch]</li>
|
||||
<li>Play by the Plone 3.3+ rules and use the INavigationRoot as a base for the
|
||||
moderation view.
|
||||
[hannosch]</li>
|
||||
<li>Added a commentTitle CSS class to the comment titles.
|
||||
[hannosch]</li>
|
||||
<li>Update message ids to match their real text.
|
||||
[hannosch]</li>
|
||||
<li>Set CSS classes for the comment form in the updateActions method.
|
||||
[timo]</li>
|
||||
<li>Respect the allow_comments field on an object and avoid calculations if no
|
||||
comments should be shown.
|
||||
[hannosch]</li>
|
||||
<li>Automatically load the ZCML files of the captcha widgets if they are
|
||||
installed.
|
||||
[hannosch]</li>
|
||||
<li>Fixed i18n domain in GenericSetup profiles to be <tt class="docutils literal"><span class="pre">plone</span></tt>. Other values
|
||||
aren’t supported for GS profiles.
|
||||
[hannosch]</li>
|
||||
<li>Provide our own copy of the default one state workflow. Not all Plone sites
|
||||
have this workflow installed.
|
||||
[hannosch]</li>
|
||||
<li>Register the event subscribers for the correct interfaces in Plone 3.
|
||||
[hannosch]</li>
|
||||
<li>Factored out subscriber declarations into its own ZCML file.
|
||||
[hannosch]</li>
|
||||
<li>Bugfix for #2281226: Moderation View: Comments disappear when hitting the
|
||||
‘Apply’ button without choosing a bulk action.
|
||||
[timo]</li>
|
||||
<li>Allow to show the full text of a comment in the moderation view.
|
||||
[timo]</li>
|
||||
<li>German translation added.
|
||||
[timo]</li>
|
||||
<li>Italian translation added.
|
||||
[keul]</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="b2-2010-01-22">
|
||||
<h2>1.0b2 (2010-01-22)<a class="headerlink" href="#b2-2010-01-22" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Bugfix for #2010181: The name of a commenter who commented while not logged in
|
||||
should not appear as a link.</li>
|
||||
<li>Bugfix for #2010078: Comments that await moderation are visually distinguished
|
||||
from published comments.</li>
|
||||
<li>Bugfix for #2010085: Use object_provides instead of portal_type to query the
|
||||
catalog for comment.</li>
|
||||
<li>Bugfix for #2010071: p.a.d. works with plone.z3cform 0.5.7 and
|
||||
plone.app.z3cform 0.4.9 now.</li>
|
||||
<li>Bugfix for #1513398: Show “anonymous” when name field is empty in comment
|
||||
form.</li>
|
||||
<li>Migration view: Dry run option added, abort transaction when something goes
|
||||
wrong during migration, be more verbose about errors.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="b1-2009-12-08">
|
||||
<h2>1.0b1 (2009-12-08)<a class="headerlink" href="#b1-2009-12-08" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Fix redirect after a adding a comment</li>
|
||||
<li>Replace yes/no widgets with check boxes in the discussion control panel</li>
|
||||
<li>Make comments viewlet show up in Plone 4</li>
|
||||
<li>Apply Plone 4 styles to comment form</li>
|
||||
<li>Simplify moderation view by removing the filters</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="a2-2009-10-18">
|
||||
<h2>1.0a2 (2009-10-18)<a class="headerlink" href="#a2-2009-10-18" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Plone 4 / Zope 2.12 support</li>
|
||||
<li>Comment migration script added</li>
|
||||
<li>Pluggable plone.z3cform comment forms</li>
|
||||
<li>Captcha and ReCaptcha support added</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="a1-2009-06-07">
|
||||
<h2>1.0a1 (2009-06-07)<a class="headerlink" href="#a1-2009-06-07" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Basic commenting functionality and batch moderation.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="indices-and-tables">
|
||||
<h1>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline">¶</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="reference external" href="genindex.html"><em>Index</em></a></li>
|
||||
<li><a class="reference external" href="modindex.html"><em>Module Index</em></a></li>
|
||||
<li><a class="reference external" href="search.html"><em>Search Page</em></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="#">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="#">Welcome to plone.app.discussion’s documentation!</a><ul>
|
||||
<li><a class="reference external" href="#module-plone.app.discussion">API</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#changelog">Changelog</a><ul>
|
||||
<li><a class="reference external" href="#b4-unreleased">1.0b4 (unreleased)</a></li>
|
||||
<li><a class="reference external" href="#b3-2010-01-28">1.0b3 (2010-01-28)</a></li>
|
||||
<li><a class="reference external" href="#b2-2010-01-22">1.0b2 (2010-01-22)</a></li>
|
||||
<li><a class="reference external" href="#b1-2009-12-08">1.0b1 (2009-12-08)</a></li>
|
||||
<li><a class="reference external" href="#a2-2009-10-18">1.0a2 (2009-10-18)</a></li>
|
||||
<li><a class="reference external" href="#a1-2009-06-07">1.0a1 (2009-06-07)</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#indices-and-tables">Indices and tables</a></li>
|
||||
</ul>
|
||||
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="architecture.html"
|
||||
title="next chapter">Architectural Principles</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/index.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="modindex.html" title="Global Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="architecture.html" title="Architectural Principles"
|
||||
>next</a> |</li>
|
||||
<li><a href="#">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2010, Timo Stollenwerk.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -5,7 +5,7 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Welcome to plone.app.discussion’s documentation! — plone.app.discussion v1.0b4 documentation</title>
|
||||
<title>Global Module Index — plone.app.discussion v1.0b4 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
@ -19,7 +19,10 @@
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="plone.app.discussion v1.0b4 documentation" href="#" />
|
||||
<link rel="top" title="plone.app.discussion v1.0b4 documentation" href="index.html" />
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
@ -28,7 +31,10 @@
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li><a href="#">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
<li class="right" >
|
||||
<a href="#" title="Global Module Index"
|
||||
accesskey="M">modules</a> |</li>
|
||||
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -37,20 +43,23 @@
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="welcome-to-plone-app-discussion-s-documentation">
|
||||
<h1>Welcome to plone.app.discussion’s documentation!<a class="headerlink" href="#welcome-to-plone-app-discussion-s-documentation" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Contents:</p>
|
||||
<ul class="simple">
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="indices-and-tables">
|
||||
<h1>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline">¶</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="reference external" href="genindex.html"><em>Index</em></a></li>
|
||||
<li><a class="reference external" href="modindex.html"><em>Module Index</em></a></li>
|
||||
<li><a class="reference external" href="search.html"><em>Search Page</em></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h1 id="global-module-index">Global Module Index</h1>
|
||||
<a href="#cap-P"><strong>P</strong></a>
|
||||
<hr/>
|
||||
|
||||
<table width="100%" class="indextable" cellspacing="0" cellpadding="2"><tr class="pcap"><td></td><td> </td><td></td></tr>
|
||||
<tr class="cap"><td></td><td><a name="cap-P"><strong>P</strong></a></td><td></td></tr><tr>
|
||||
<td><img src="_static/minus.png" id="toggle-1"
|
||||
class="toggler" style="display: none" alt="-" /></td>
|
||||
<td>
|
||||
<tt class="xref">plone</tt></td><td>
|
||||
<em></em></td></tr><tr class="cg-1">
|
||||
<td></td>
|
||||
<td>
|
||||
<a href="index.html#module-plone.app.discussion"><tt class="xref">plone.app.discussion</tt></a></td><td>
|
||||
<em></em></td></tr>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
@ -58,19 +67,6 @@
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="#">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="#">Welcome to plone.app.discussion’s documentation!</a><ul>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#indices-and-tables">Indices and tables</a></li>
|
||||
</ul>
|
||||
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/index.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
@ -94,12 +90,15 @@
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li><a href="#">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
<li class="right" >
|
||||
<a href="#" title="Global Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2010, Timo Stollenwerk.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.5.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
6
docs/html/objects.inv
Normal file
6
docs/html/objects.inv
Normal file
@ -0,0 +1,6 @@
|
||||
# Sphinx inventory version 1
|
||||
# Project: plone.app.discussion
|
||||
# Version: 1.0b4
|
||||
plone.app.discussion mod index.html
|
||||
plone.app.discussion.conversation.Conversation class index.html
|
||||
plone.app.discussion.conversation.Conversation.enabled method index.html
|
@ -29,6 +29,9 @@
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="modindex.html" title="Global Module Index"
|
||||
accesskey="M">modules</a> |</li>
|
||||
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -77,13 +80,16 @@
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="modindex.html" title="Global Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
© Copyright 2010, Timo Stollenwerk.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.5.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
|
||||
</div>
|
||||
<script type="text/javascript" src="searchindex.js"></script>
|
||||
|
1
docs/html/searchindex.js
Normal file
1
docs/html/searchindex.js
Normal file
File diff suppressed because one or more lines are too long
113
docs/make.bat
Normal file
113
docs/make.bat
Normal file
@ -0,0 +1,113 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
set SPHINXBUILD=sphinx-build
|
||||
set BUILDDIR=/home/timo/workspace/pad/plone.app.discussion/docs
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% /home/timo/workspace/pad/plone.app.discussion/docs/source
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\sphinxbuilder.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\sphinxbuilder.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
59
docs/source/architecture.txt
Normal file
59
docs/source/architecture.txt
Normal file
@ -0,0 +1,59 @@
|
||||
========================
|
||||
Architectural Principles
|
||||
========================
|
||||
|
||||
This document outlines architectural principles used in the design of
|
||||
plone.app.discussion.
|
||||
|
||||
**Discussion items have a portal_type**
|
||||
This makes it easier to search for them and manage them using existing
|
||||
CMF and Plone UI constructs.
|
||||
|
||||
**Discussion items are cataloged**
|
||||
It is be possible to search for discussion items like any other type of
|
||||
content.
|
||||
|
||||
**Discussion items are subject to workflow and permission**
|
||||
Moderation, anonymous commenting, and auto approve/reject should be
|
||||
handled using workflow states, automatic and manual transitions, and
|
||||
permissions.
|
||||
|
||||
**Discussion items are light weight objects**
|
||||
Discussion item objects are as light weight as possible.
|
||||
Ideally, a discussion item should be as lightweight as a catalog brain.
|
||||
This may mean that we forego convenience base classes and re-implement
|
||||
certain interfaces. Comments should not provide the full set of dublin
|
||||
core metadata, though custom indexers can be used to provide values for
|
||||
standard catalog indexes.
|
||||
|
||||
**Optimise for retrival speed**
|
||||
HTML filtering and other processing should happen on save, not on render,
|
||||
to make rendering quick.
|
||||
|
||||
**Settings are stored using plone.registry**
|
||||
Any global setting should be stored in plone.registry records
|
||||
|
||||
**Forms are constructed using extensible z3c.form forms**
|
||||
This allows plugins (such as spam protection algorithms) to provide
|
||||
additional validation
|
||||
|
||||
**Discussion items are stored in a BTree container**
|
||||
This allows faster lookup and manipulation
|
||||
|
||||
**Discussion items are accessed using a dict-like interface**
|
||||
This makes iteration and manipulation more natural. Even if comments are
|
||||
not stored threaded, the dict interface should act as if they are, i.e.
|
||||
calling items() on a comment should return the replies to that comment
|
||||
(in order).
|
||||
|
||||
**Discussion items are retrieved in reverse creation date order**
|
||||
Discussion items do not need to support explicit ordering. They should
|
||||
always be retrieved in reverse creation date order (most recent for).
|
||||
They can be stored with keys so that this is always true.
|
||||
|
||||
**Discussion items do not need readable ids**
|
||||
Ids can be based on the creation date.
|
||||
|
||||
**Discussion items send events**
|
||||
The usual zope.lifecycleevent and zope.container events are fired when
|
||||
discussion items are added, removed, or modified.
|
169
docs/source/design.txt
Normal file
169
docs/source/design.txt
Normal file
@ -0,0 +1,169 @@
|
||||
============
|
||||
Design Notes
|
||||
============
|
||||
|
||||
This document contains design notes for plone.app.discussion.
|
||||
|
||||
Storage and traversal
|
||||
---------------------
|
||||
|
||||
For each content item, there is a Conversation object stored in annotations.
|
||||
This can be traversed to via the ++conversation++ namespace, but also fetched
|
||||
via an adapter lookup to IConversation.
|
||||
|
||||
The conversation stores all comments related to a content object. Each
|
||||
comment has an integer id (also representable as a string, to act as an OFS
|
||||
id and allow traversal). Hence, traversing to obj/++conversation++/123 retrieves
|
||||
the comment with id 123.
|
||||
|
||||
Comments ids are assigned in order, so a comment with id N was posted before
|
||||
a comment with id N + 1. However, it is not guaranteed that ids will be
|
||||
incremental. Ids must be positive integers - 0 or negative numbers are not
|
||||
allowed.
|
||||
|
||||
Threading information is stored in the conversation: we keep track of the
|
||||
set of children and the parent if any comment. Top-level comments have a
|
||||
parent id of 0. This information is managed by the conversation class when
|
||||
comments are manipulated using a dict-like API.
|
||||
|
||||
Note that the __parent__/acquisition parent of an IComment is the
|
||||
IConversation, and the __parent__/acquisition parent of an IConversation is
|
||||
the content object.
|
||||
|
||||
Events
|
||||
------
|
||||
|
||||
Manipulating the IConversation object should fire the usual IObjectAddedEvent
|
||||
and IObjectRemovedEvent events. The UI may further fire IObjectCreatedEvent
|
||||
and IObjectModifiedEvent for comments.
|
||||
|
||||
Factories
|
||||
---------
|
||||
|
||||
Comments should always be created via the 'Discussion Item' IFactory utility.
|
||||
Conversations should always be obtained via the IConversation adapter (even
|
||||
the ++conversation++ namespace should use this). This makes it possible to
|
||||
replace conversations and comments transparently.
|
||||
|
||||
The Comment class
|
||||
-----------------
|
||||
|
||||
The inheritance tree for DiscussionItem is shown below. Classes we want to
|
||||
mix in and interface we want to implement in the Comment class are marked
|
||||
with [x].
|
||||
|
||||
[ ] DiscussionItem
|
||||
[ ] Document
|
||||
[ ] PortalContent = [ ] IContentish
|
||||
[ ] DynamicType = [ ] IDynamicType
|
||||
[ ] CMFCatalogAware = [ ] <no interface>
|
||||
[ ] SimpleItem = [ ] ISimpleItem
|
||||
[ ] Item [ ]
|
||||
[?] Base = [ ] <no interface>
|
||||
[ ] Resource = [ ] <no interface>
|
||||
[ ] CopySource = [ ] ICopySource
|
||||
[ ] Tabs = [ ] <no interface>
|
||||
[x] Traversable = [ ] ITraversable
|
||||
[ ] Element = [ ] <no interface>
|
||||
[x] Owned = [ ] IOwned
|
||||
[ ] UndoSupport = [ ] IUndoSupport
|
||||
[ ] Persistent [ ]
|
||||
[ ] Implicit [ ]
|
||||
[x] RoleManager = [ ] IRoleManager
|
||||
[ ] RoleManager = [ ] IPermissionMappingSupport
|
||||
[ ] DefaultDublinCoreImpl = [ ] IDublinCore
|
||||
[ ] ICatalogableDublinCore
|
||||
[ ] IMutableDublinCore
|
||||
[ ] PropertyManager = [ ] IPropertyManager
|
||||
|
||||
Thus, we want:
|
||||
|
||||
* Traversable, to get absolute_url() and friends
|
||||
- this requires a good acquisition chain at all times
|
||||
* Acquisition.Explicit, to support acquisition
|
||||
- we do not want implicit acquisition
|
||||
* Owned, to be able to track ownership
|
||||
* RoleManager, to support permissions and local roles
|
||||
|
||||
We also want to use a number of custom indexers for most of the standard
|
||||
metadata such as creator, effective date etc.
|
||||
|
||||
Finally, we'll need event handlers to perform the actual indexing.
|
||||
|
||||
Discussion settings
|
||||
-------------------
|
||||
|
||||
Discussion can be enabled per-type and per-instance, via values in the FTI
|
||||
(allow_discussion) and on the object. These will remain unchanged. The
|
||||
IConversation object's 'enabled' property should consult these.
|
||||
|
||||
Global settings should be managed using plone.registry. A control panel
|
||||
can be generated from this as well, using the helper class in
|
||||
plone.app.registry.
|
||||
|
||||
Note that some settings, notably those to do with permissions and workflow,
|
||||
will need to be wired up as custom form fields with custom data mangers
|
||||
or similar.
|
||||
|
||||
Workflow and permissions
|
||||
------------------------
|
||||
|
||||
Where possible, we should use existing permissions:
|
||||
|
||||
* View
|
||||
* Reply to Item
|
||||
* Modify Portal Content
|
||||
* Request Review
|
||||
|
||||
In addition, we'll need a 'Moderator' role and a moderation permission,
|
||||
|
||||
* Moderate comment
|
||||
* Bypass moderation
|
||||
|
||||
To control whether Anonymous can post comments, we manage the 'Reply to Item'
|
||||
permission. To control whether moderation is required for various roles, we
|
||||
could manage the 'Bypass moderation' permission.
|
||||
|
||||
These could work in a workflow like this:
|
||||
|
||||
* --> [posted] -- {publish} --> [published]--> *
|
||||
| ^
|
||||
| |
|
||||
+----- {auto-publish} -----+
|
||||
| |
|
||||
+----- {auto-moderate} ----+
|
||||
|
||||
The 'posted' state is the initial state. 'published' is the state where the
|
||||
comment is visible to non-reviewers.
|
||||
|
||||
The 'publish' transition would be protected by the 'Moderate comment'
|
||||
permission. We could have states and transition for 'rejected', etc, but it
|
||||
is probably just as good to delete comments that are rejected.
|
||||
|
||||
The 'auto-publish' transition would be an automatic transition protected by
|
||||
the 'Bypass moderation' permission.
|
||||
|
||||
The 'auto-moderate' transition would be another automatic transition protected
|
||||
by an expression (e.g. calling a view) that returns True if the user is on
|
||||
an auto-moderation 'white-list', e.g. by email address or username.
|
||||
|
||||
Forms and UI
|
||||
------------
|
||||
|
||||
The basic commenting display/reply form should be placed in a viewlet.
|
||||
|
||||
Ideally, the reply form should be inline, perhaps revealed with JavaScript
|
||||
if enabled. This allows full contextualisation of replies. The current
|
||||
solution, with a separate form that shows some context, is brittle and
|
||||
over-complicated.
|
||||
|
||||
If we support quoting of comments in replies, we can load the text to quote
|
||||
using JavaScript as well.
|
||||
|
||||
As a fall-back for non-JavaScript enabled browsers, it is probably OK not to
|
||||
support quoting and/or viewing of context, e.g. the user is taken to a standalone
|
||||
'comment reply' form.
|
||||
|
||||
All actual forms should be handled using z3c.form and plone.z3cform's
|
||||
ExtensibleForm support. This makes it possible to plug in additional fields
|
||||
declaratively, e.g. to include spam protection.
|
@ -6,11 +6,29 @@
|
||||
Welcome to plone.app.discussion's documentation!
|
||||
================================================
|
||||
|
||||
.. module:`plone.app.discussion`
|
||||
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
architecture.txt
|
||||
design.txt
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. automodule:: plone.app.discussion
|
||||
|
||||
.. autoclass:: plone.app.discussion.conversation.Conversation
|
||||
|
||||
.. automethod:: plone.app.discussion.conversation.Conversation.enabled
|
||||
|
||||
.. include:: ../../CHANGES.txt
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user