diff --git a/dev-plone4.cfg b/dev-plone4.cfg index a72be2a..9d8fb5e 100644 --- a/dev-plone4.cfg +++ b/dev-plone4.cfg @@ -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 diff --git a/docs/Makefile b/docs/Makefile index 1703755..fa0cca6 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -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 diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle deleted file mode 100644 index 0cce652..0000000 Binary files a/docs/build/doctrees/environment.pickle and /dev/null differ diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree deleted file mode 100644 index bee0b81..0000000 Binary files a/docs/build/doctrees/index.doctree and /dev/null differ diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv deleted file mode 100644 index ff9ff6d..0000000 --- a/docs/build/html/objects.inv +++ /dev/null @@ -1,3 +0,0 @@ -# Sphinx inventory version 1 -# Project: plone.app.discussion -# Version: 1.0b4 diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js deleted file mode 100644 index cd14546..0000000 --- a/docs/build/html/searchindex.js +++ /dev/null @@ -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"]}) \ No newline at end of file diff --git a/docs/doctrees/architecture.doctree b/docs/doctrees/architecture.doctree new file mode 100644 index 0000000..baeffde Binary files /dev/null and b/docs/doctrees/architecture.doctree differ diff --git a/docs/doctrees/design.doctree b/docs/doctrees/design.doctree new file mode 100644 index 0000000..5826cf7 Binary files /dev/null and b/docs/doctrees/design.doctree differ diff --git a/docs/doctrees/environment.pickle b/docs/doctrees/environment.pickle new file mode 100644 index 0000000..cd1b752 Binary files /dev/null and b/docs/doctrees/environment.pickle differ diff --git a/docs/doctrees/index.doctree b/docs/doctrees/index.doctree new file mode 100644 index 0000000..25c3f75 Binary files /dev/null and b/docs/doctrees/index.doctree differ diff --git a/docs/build/html/.buildinfo b/docs/html/.buildinfo similarity index 100% rename from docs/build/html/.buildinfo rename to docs/html/.buildinfo diff --git a/docs/html/_sources/architecture.txt b/docs/html/_sources/architecture.txt new file mode 100644 index 0000000..1e2de51 --- /dev/null +++ b/docs/html/_sources/architecture.txt @@ -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. diff --git a/docs/html/_sources/design.txt b/docs/html/_sources/design.txt new file mode 100644 index 0000000..20079a9 --- /dev/null +++ b/docs/html/_sources/design.txt @@ -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 = [ ] + [ ] SimpleItem = [ ] ISimpleItem + [ ] Item [ ] + [?] Base = [ ] + [ ] Resource = [ ] + [ ] CopySource = [ ] ICopySource + [ ] Tabs = [ ] + [x] Traversable = [ ] ITraversable + [ ] Element = [ ] + [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. diff --git a/docs/build/html/_sources/index.txt b/docs/html/_sources/index.txt similarity index 60% rename from docs/build/html/_sources/index.txt rename to docs/html/_sources/index.txt index 4b02841..0e152d2 100644 --- a/docs/build/html/_sources/index.txt +++ b/docs/html/_sources/index.txt @@ -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 ================== diff --git a/docs/build/html/_static/basic.css b/docs/html/_static/basic.css similarity index 100% rename from docs/build/html/_static/basic.css rename to docs/html/_static/basic.css diff --git a/docs/build/html/_static/default.css b/docs/html/_static/default.css similarity index 95% rename from docs/build/html/_static/default.css rename to docs/html/_static/default.css index 3725744..42ed6ec 100644 --- a/docs/build/html/_static/default.css +++ b/docs/html/_static/default.css @@ -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; diff --git a/docs/build/html/_static/doctools.js b/docs/html/_static/doctools.js similarity index 100% rename from docs/build/html/_static/doctools.js rename to docs/html/_static/doctools.js diff --git a/docs/build/html/_static/file.png b/docs/html/_static/file.png similarity index 100% rename from docs/build/html/_static/file.png rename to docs/html/_static/file.png diff --git a/docs/build/html/_static/jquery.js b/docs/html/_static/jquery.js similarity index 100% rename from docs/build/html/_static/jquery.js rename to docs/html/_static/jquery.js diff --git a/docs/build/html/_static/minus.png b/docs/html/_static/minus.png similarity index 100% rename from docs/build/html/_static/minus.png rename to docs/html/_static/minus.png diff --git a/docs/build/html/_static/plus.png b/docs/html/_static/plus.png similarity index 100% rename from docs/build/html/_static/plus.png rename to docs/html/_static/plus.png diff --git a/docs/build/html/_static/pygments.css b/docs/html/_static/pygments.css similarity index 100% rename from docs/build/html/_static/pygments.css rename to docs/html/_static/pygments.css diff --git a/docs/build/html/_static/searchtools.js b/docs/html/_static/searchtools.js similarity index 100% rename from docs/build/html/_static/searchtools.js rename to docs/html/_static/searchtools.js diff --git a/docs/html/architecture.html b/docs/html/architecture.html new file mode 100644 index 0000000..7809648 --- /dev/null +++ b/docs/html/architecture.html @@ -0,0 +1,159 @@ + + + + + + + Architectural Principles — plone.app.discussion v1.0b4 documentation + + + + + + + + + + + + +
+
+
+
+ +
+

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.
+
+
+
+ + +
+
+
+
+
+

Previous topic

+

Welcome to plone.app.discussion’s documentation!

+

Next topic

+

Design Notes

+

This Page

+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/html/design.html b/docs/html/design.html new file mode 100644 index 0000000..2379a13 --- /dev/null +++ b/docs/html/design.html @@ -0,0 +1,303 @@ + + + + + + + Design Notes — plone.app.discussion v1.0b4 documentation + + + + + + + + + + + +
+
+
+
+ +
+

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.

+
+
+ + +
+
+
+
+
+

Table Of Contents

+ + +

Previous topic

+

Architectural Principles

+

This Page

+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/html/genindex.html b/docs/html/genindex.html similarity index 69% rename from docs/build/html/genindex.html rename to docs/html/genindex.html index 4a60dcd..8431d57 100644 --- a/docs/build/html/genindex.html +++ b/docs/html/genindex.html @@ -28,6 +28,9 @@
  • index
  • +
  • + modules |
  • plone.app.discussion v1.0b4 documentation »
  • @@ -40,11 +43,32 @@

    Index

    - + C | E | P
    +

    C

    +
    +
    + +
    Conversation (class in plone.app.discussion.conversation)
    +
    + +

    E

    +
    +
    + +
    enabled() (plone.app.discussion.conversation.Conversation method)
    +
    + +

    P

    +
    +
    + +
    plone.app.discussion (module)
    +
    + @@ -78,12 +102,15 @@
  • index
  • +
  • + modules |
  • plone.app.discussion v1.0b4 documentation »
  • \ No newline at end of file diff --git a/docs/html/index.html b/docs/html/index.html new file mode 100644 index 0000000..66e4b6b --- /dev/null +++ b/docs/html/index.html @@ -0,0 +1,278 @@ + + + + + + + Welcome to plone.app.discussion’s documentation! — plone.app.discussion v1.0b4 documentation + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    Welcome to plone.app.discussion’s documentation!

    +

    Contents:

    + +
    +

    API

    +
    +
    +class plone.app.discussion.conversation.Conversation(id='++conversation++default')
    +

    A conversation is a container for all comments on a content object.

    +

    It manages internal data structures for comment threading and efficient +comment lookup.

    +
    +
    +enabled()
    +
    hi world
    + +
    + +
    +
    +
    +

    Changelog

    +
    +

    1.0b4 (unreleased)

    +
      +
    • Fix #662654: As an administrator, I can configure a Collection to show recent comments. +Comment.Type() now correctly returns the FTI title (‘Comment’) +[chaoflow]
    • +
    • German translation updated. +[juh]
    • +
    • Fix #2419342: Fix untranslated published/deleted status messages. +[timo]
    • +
    • Remove fixed width of the actions column of the moderation view. The +translated button titles can differ in size from the English titles. +[timo]
    • +
    • Fix #2494228: Remove comments as well when a content object is deleted. +[timo]
    • +
    • Fix unicode error when non-ASCII characters are typed into the name field of a +comment by anonymous users. +[regebro]
    • +
    • New feature: As a moderator, I am notified when new comments require my +attention. +[timo]
    • +
    • Make p.a.d. work with the recent version of plone.z3cform (0.5.10) +[timo]
    • +
    • Make p.a.d. styles less generic. This fixes #10253. +[timo]
    • +
    • Added greek translation. +[ggozad]
    • +
    +
    +
    +

    1.0b3 (2010-01-28)

    +
      +
    • Added an i18n directory for messages in the plone domain and updated scripts +to rebuild and sync it. +[hannosch]
    • +
    • 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]
    • +
    • Play by the Plone 3.3+ rules and use the INavigationRoot as a base for the +moderation view. +[hannosch]
    • +
    • Added a commentTitle CSS class to the comment titles. +[hannosch]
    • +
    • Update message ids to match their real text. +[hannosch]
    • +
    • Set CSS classes for the comment form in the updateActions method. +[timo]
    • +
    • Respect the allow_comments field on an object and avoid calculations if no +comments should be shown. +[hannosch]
    • +
    • Automatically load the ZCML files of the captcha widgets if they are +installed. +[hannosch]
    • +
    • Fixed i18n domain in GenericSetup profiles to be plone. Other values +aren’t supported for GS profiles. +[hannosch]
    • +
    • Provide our own copy of the default one state workflow. Not all Plone sites +have this workflow installed. +[hannosch]
    • +
    • Register the event subscribers for the correct interfaces in Plone 3. +[hannosch]
    • +
    • Factored out subscriber declarations into its own ZCML file. +[hannosch]
    • +
    • Bugfix for #2281226: Moderation View: Comments disappear when hitting the +‘Apply’ button without choosing a bulk action. +[timo]
    • +
    • Allow to show the full text of a comment in the moderation view. +[timo]
    • +
    • German translation added. +[timo]
    • +
    • Italian translation added. +[keul]
    • +
    +
    +
    +

    1.0b2 (2010-01-22)

    +
      +
    • Bugfix for #2010181: The name of a commenter who commented while not logged in +should not appear as a link.
    • +
    • Bugfix for #2010078: Comments that await moderation are visually distinguished +from published comments.
    • +
    • Bugfix for #2010085: Use object_provides instead of portal_type to query the +catalog for comment.
    • +
    • Bugfix for #2010071: p.a.d. works with plone.z3cform 0.5.7 and +plone.app.z3cform 0.4.9 now.
    • +
    • Bugfix for #1513398: Show “anonymous” when name field is empty in comment +form.
    • +
    • Migration view: Dry run option added, abort transaction when something goes +wrong during migration, be more verbose about errors.
    • +
    +
    +
    +

    1.0b1 (2009-12-08)

    +
      +
    • Fix redirect after a adding a comment
    • +
    • Replace yes/no widgets with check boxes in the discussion control panel
    • +
    • Make comments viewlet show up in Plone 4
    • +
    • Apply Plone 4 styles to comment form
    • +
    • Simplify moderation view by removing the filters
    • +
    +
    +
    +

    1.0a2 (2009-10-18)

    +
      +
    • Plone 4 / Zope 2.12 support
    • +
    • Comment migration script added
    • +
    • Pluggable plone.z3cform comment forms
    • +
    • Captcha and ReCaptcha support added
    • +
    +
    +
    +

    1.0a1 (2009-06-07)

    +
      +
    • Basic commenting functionality and batch moderation.
    • +
    +
    +
    +
    +

    Indices and tables

    + +
    + + +
    +
    +
    +
    +
    +

    Table Of Contents

    + + +

    Next topic

    +

    Architectural Principles

    +

    This Page

    + + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/build/html/index.html b/docs/html/modindex.html similarity index 61% rename from docs/build/html/index.html rename to docs/html/modindex.html index d8d82ec..2e43beb 100644 --- a/docs/build/html/index.html +++ b/docs/html/modindex.html @@ -5,7 +5,7 @@ - Welcome to plone.app.discussion’s documentation! — plone.app.discussion v1.0b4 documentation + Global Module Index — plone.app.discussion v1.0b4 documentation - + + + + @@ -37,20 +43,23 @@
    -
    -

    Welcome to plone.app.discussion’s documentation!

    -

    Contents:

    -
      -
    -
    -
    -

    Indices and tables

    - -
    + +

    Global Module Index

    + P +
    + + + + + + + +
     
    P
    + plone +
        + plone.app.discussion +
    @@ -58,19 +67,6 @@
    -

    Table Of Contents

    - - -

    This Page

    - \ No newline at end of file diff --git a/docs/html/objects.inv b/docs/html/objects.inv new file mode 100644 index 0000000..7c831cd --- /dev/null +++ b/docs/html/objects.inv @@ -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 diff --git a/docs/build/html/search.html b/docs/html/search.html similarity index 91% rename from docs/build/html/search.html rename to docs/html/search.html index 7562e5d..7660679 100644 --- a/docs/build/html/search.html +++ b/docs/html/search.html @@ -29,6 +29,9 @@
  • index
  • +
  • + modules |
  • plone.app.discussion v1.0b4 documentation »
  • @@ -77,13 +80,16 @@
  • index
  • +
  • + modules |
  • plone.app.discussion v1.0b4 documentation »
  • diff --git a/docs/html/searchindex.js b/docs/html/searchindex.js new file mode 100644 index 0000000..1aa49a4 --- /dev/null +++ b/docs/html/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({desctypes:{"0":"class","1":"method"},terms:{represent:1,all:[0,1],chain:1,queri:0,global:[1,2],pluggabl:0,modul:0,children:1,profil:0,readabl:2,send:2,string:1,util:1,fall:1,portalcont:1,administr:0,level:1,cmf:2,itravers:1,list:1,iter:2,factori:[0,1],item:[1,2],quick:2,outlin:2,natur:2,sync:0,design:[0,1,2],further:1,btree:2,even:[1,2],index:[0,1,2],appear:0,repli:[1,2],abl:1,"while":0,access:2,delet:[0,1],version:0,"new":0,method:0,metadata:[1,2],widget:0,full:[0,1,2],gener:[0,1],updateact:0,address:1,modifi:[1,2],implicit:1,valu:[0,1,2],dry:0,search:[0,2],convers:[0,1],dublin:2,action:0,implement:[1,2],via:1,appli:0,app:[0,1,2],api:[0,1],icontentish:1,instal:0,plone:[0,1,2],"__parent__":1,from:[0,1],would:1,regist:0,handler:1,call:[1,2],taken:1,type:[0,1,2],more:[0,2],henc:1,relat:1,site:0,visual:0,actual:1,iobjectaddedev:1,must:1,retriev:[0,1,2],viewlet:[0,1],work:[0,1],annot:1,remain:1,can:[0,1,2],fetch:1,control:[0,1],complic:1,want:1,process:2,share:0,indic:0,captcha:0,abort:0,tab:1,commenttitl:0,alwai:[1,2],mai:[1,2],quot:1,iobjectcreatedev:1,how:0,reject:[1,2],instead:0,css:0,updat:0,resourc:1,await:0,befor:1,catalog:[0,2],attent:0,date:[1,2],data:[0,1],light:2,explicit:[1,2],element:1,inform:1,allow:[0,1,2],anoth:1,order:[1,2],over:1,approv:2,brain:2,style:0,ifactori:1,fix:0,bypass:1,persist:1,easier:2,them:2,good:1,"return":[0,1,2],thei:[0,2],handl:[1,2],auto:[1,2],untransl:0,initi:1,now:0,discuss:[0,1,2],name:0,changelog:0,revers:2,separ:1,zcml:0,each:1,unicod:0,button:0,mean:2,domain:0,weight:2,replac:[0,1],brittl:1,our:0,happen:2,imutabledublincor:1,event:[0,1,2],out:0,shown:[0,1],goe:0,publish:[0,1],content:[0,1,2],adapt:1,fti:[0,1],extensibleform:1,correct:0,after:0,workflow:[0,1,2],migrat:0,manipul:[1,2],standard:[1,2],standalon:1,base:[0,1,2],copysourc:1,thread:[0,1,2],could:1,wrong:0,keep:1,filter:[0,2],perhap:1,place:1,principl:[0,2],assign:1,size:0,notifi:0,render:2,number:1,acquisit:1,construct:2,regebro:0,differ:0,script:0,top:1,messag:0,white:1,conveni:2,"final":1,friend:1,option:0,namespac:1,copi:0,consult:1,ipropertymanag:1,undosupport:1,provid:[0,2],remov:[0,2],tree:1,structur:0,charact:0,ggozad:0,store:[0,1,2],posit:1,browser:1,ani:[1,2],simpleitem:1,have:[0,1,2],tabl:0,need:[1,2],optimis:2,greek:0,note:[0,1],also:1,ideal:[1,2],z3c:[1,2],simplifi:0,though:2,usernam:1,object:[0,1,2],most:[1,2],plai:0,propertymanag:1,icom:1,"class":[0,1,2],renam:[],request:1,declar:[0,1],neg:1,link:0,usual:[1,2],review:1,show:[0,1],german:0,text:[0,1],verbos:0,permiss:[0,1,2],redirect:0,current:1,just:1,transact:0,configur:0,solut:1,should:[0,1,2],dict:[1,2],factor:0,z3cform:[0,1],local:1,hit:0,variou:1,get:1,express:1,requir:[0,1],reveal:1,enabl:[0,1],"0b2":0,across:0,"default":0,hannosch:0,contain:[0,1,2],where:1,view:[0,1],manger:1,forego:2,set:[0,1,2],chaoflow:0,creator:1,subject:2,statu:0,wire:1,kei:2,correctli:0,someth:0,state:[0,1,2],email:1,rolemanag:1,parent:1,javascript:1,extens:2,distinguish:0,addit:[1,2],protect:[1,2],plugin:2,howev:1,linguaplon:0,etc:1,instanc:1,context:1,load:[0,1],respect:0,"0a1":0,"0a2":0,rebuild:0,empti:0,mark:1,basic:[0,1],box:0,fire:[1,2],bulk:0,i18n:0,those:1,properti:1,batch:0,calcul:0,error:0,anonym:[0,1,2],iundosupport:1,increment:1,helper:1,canon:0,non:[0,1],lightweight:2,discussionitem:1,ascii:0,disappear:0,subscrib:0,welcom:0,perform:1,make:[0,1,2],html:2,zope:[0,2],document:[0,1,2],iown:1,ipermissionmappingsupport:1,effect:1,retriv:2,portal:1,user:[0,1],ownership:1,icopysourc:1,recent:[0,2],travers:[0,1],moder:[0,1,2],choos:0,thu:1,well:[0,1],inherit:1,without:0,thi:[0,1,2],english:0,unchang:1,comment:[0,1,2],portal_typ:[0,2],less:0,obtain:1,speed:2,mix:1,other:[0,2],iobjectremovedev:1,lookup:[0,1,2],save:2,transit:[1,2],match:0,real:0,transpar:1,recaptcha:0,world:0,like:[1,2],manual:2,integ:1,collect:0,page:0,italian:0,visibl:1,some:1,back:1,inavigationroot:0,intern:0,genericsetup:0,guarante:1,keul:0,avoid:0,irolemanag:1,per:1,track:1,iobjectmodifiedev:1,notabl:1,core:2,who:0,run:0,allow_com:0,post:1,cmfcatalogawar:1,panel:[0,1],plug:1,about:0,obj:1,column:0,absolute_url:1,iconvers:1,lifecycleev:2,act:[1,2],contextualis:1,own:[0,1],effici:0,automat:[0,1,2],storag:[0,1],manag:[0,1,2],log:0,spam:[1,2],aren:0,support:[0,1,2],custom:[1,2],width:0,interfac:[0,1,2],includ:1,"function":0,creation:2,form:[0,1,2],juh:0,idublincor:1,idynamictyp:1,translat:0,inlin:1,"true":[1,2],faster:2,"0b4":0,"0b1":0,"0b3":0,possibl:[1,2],whether:1,bugfix:0,displai:1,record:2,below:1,allow_discuss:1,similar:1,isimpleitem:1,featur:0,creat:1,certain:2,dure:0,object_provid:0,unreleas:0,exist:[1,2],file:0,check:0,probabl:1,titl:0,when:[0,1,2],field:[0,1],valid:2,role:1,architectur:[0,2],registri:[1,2],icatalogabledublincor:1,algorithm:2,defaultdublincoreimpl:1,directori:0,rule:0,dynamictyp:1,conversationcanonicaladapterfactori:0,time:1,timo:0},titles:["Welcome to plone.app.discussion’s documentation!","Design Notes","Architectural Principles"],modules:{"plone.app.discussion":0},descrefs:{"plone.app.discussion.conversation":{Conversation:[0,0]},"plone.app.discussion.conversation.Conversation":{enabled:[0,1]}},filenames:["index","design","architecture"]}) \ No newline at end of file diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..b3fda13 --- /dev/null +++ b/docs/make.bat @@ -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 ^` where ^ 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 diff --git a/docs/source/architecture.txt b/docs/source/architecture.txt new file mode 100644 index 0000000..1e2de51 --- /dev/null +++ b/docs/source/architecture.txt @@ -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. diff --git a/docs/source/design.txt b/docs/source/design.txt new file mode 100644 index 0000000..20079a9 --- /dev/null +++ b/docs/source/design.txt @@ -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 = [ ] + [ ] SimpleItem = [ ] ISimpleItem + [ ] Item [ ] + [?] Base = [ ] + [ ] Resource = [ ] + [ ] CopySource = [ ] ICopySource + [ ] Tabs = [ ] + [x] Traversable = [ ] ITraversable + [ ] Element = [ ] + [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. diff --git a/docs/source/index.txt b/docs/source/index.txt index 4b02841..0e152d2 100644 --- a/docs/source/index.txt +++ b/docs/source/index.txt @@ -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 ==================