.. doctest docs/specs/comments.rst .. _book.specs.comments: ===================================== ``comments`` : The comments framework ===================================== .. currentmodule:: lino.modlib.comments The :mod:`lino.modlib.comments` plugin adds a framework for handling comments. .. contents:: :local: .. include:: /../docs/shared/include/tested.rst >>> from lino import startup >>> startup('lino_book.projects.noi1e.settings.demo') >>> from lino.api.doctest import * Overview ======== .. glossary:: comment A written text that one user wants to share with others. A comment is always "about" something, called the :term:`discussion topic`. A comment has no "recipient". When you submit a comment, Lino notifies all users who registered their interest in the :term:`discussion topic`. A comment can be a *reply* to another comment. All comments replying directly or indirectly to a given comment are called a *discussion thread*. Comments are stored in the :class:`Comment` database model. discussion topic A database object that is the "topic" of a series of comments. commentable database model The application developer decides which database models can serve as topics for commenting by having these database models inherit from the :class:`Commentable` mixin. commenting group A group of users who discuss with each other using comments. Comments ======== .. class:: Comment Django model to represent a :term:`comment`. .. attribute:: user The author of the comment. .. attribute:: owner The *topic* this comment is about. This field is a Generic Foreign Key, i.e. users can basically comment on any database object. It is however the :term:`application developer` who decides where comments can be created and how they are being displayed. The :attr:`owner` of a comment is always an instance of a subclass of :class:`Commentable`. .. attribute:: body The full body text of your comment. .. attribute:: short_preview The first paragraph of your :attr:`body`. .. attribute:: emotion The emotion of this comment. .. attribute:: published When this comment has been published. A timestamp. .. class:: Comments .. attribute:: show_published Whether to show only (un)published comments, independently of the publication date. .. attribute:: start_date .. attribute:: end_date The date range to filter. .. attribute:: observed_event Which event (created, modified or published) to consider when applying the date range given by :attr:`start_date` and :attr:`end_date`. .. method:: as_li(cls, self, ar) Return this comment for usage in a list item as a string with HTML tags. .. class:: AllComments .. class:: MyComments .. class:: MyPendingComments .. class:: RecentComments Shows the comments for a given database object. .. attribute:: slave_summary .. method:: get_table_summary(cls, obj, ar) The :meth:`summary view ` for this table. .. class:: CommentsByX .. class:: CommentsByType .. class:: CommentsByRFC Shows the comments for a given database object. .. attribute:: slave_summary .. method:: get_table_summary(cls, obj, ar) The :meth:`summary view ` for this table. .. class:: ObservedTime .. class:: CommentEvents The choicelist with selections for :attr:`Comments.observed_event`. .. class:: PublishComment Publish this comment. .. class:: PublishAllComments Publish all comments. Emotions ======== .. class:: Emotions The list of available values for the :attr:`Comment.emotion` field. >>> rt.show("comments.Emotions") ========== ========== ========== ============= value name text Button text ---------- ---------- ---------- ------------- ok ok Okay agree agree Agree ✅ disagree disagree Disagree ❎ ========== ========== ========== ============= Comment types ============= .. class:: CommentType The :class:`CommentType` model is not being used in production, one day we will probably remove it. .. class:: CommentTypes The table with all existing comment types. This usually is accessible via the `Configure` menu. Commentable =========== .. class:: Commentable Mixin for models whose instances can be :term:`discussion topic` of comments. .. method:: get_rfc_description(self, ar) Return a HTML formatted string with the description of this Commentable as it should be displayed by the slave summary of CommentsByOwner. It must be a string and not an etree element. That's because it usually includes the content of RichTextField. If the API required an element, it would require us to parse this content just in order to generate HTML from it. .. method:: on_commented(self, comment, ar, cw) This is automatically called when a comment has been created or modified. .. method:: get_comment_group(self) Return either `None` or a database object that represents the :term:`commenting group` where this comment is being done. If not None, the object must have a field :attr:`ref` which will be shown in the summary of :class:`RecentComments`. .. method:: get_comments_filter(cls, user): Return the filter to be added when a given user requests comments about commentables of this type. Return `None` to not add any filter. Otherwise the return value should be a :class:`django.db.models.Q` object. Default behaviour is that public comments are visible even to anonymous while private comments are visible only to their author and to :class:`PrivateCommentsReader`. You can override this class method to define your own privacy settings. Usage example in :class:`lino_xl.lib.groups.Group` and :class:`lino_xl.lib.tickets.Ticket`. If you override this method, you probably want to define a :class:`django.contrib.contenttypes.fields.GenericRelation` on your Commentable in order to write filter conditions based on the owner of the comment. Utilities ========= .. function:: comments_by_owner The preview of a comment ======================== Usage examples: >>> from lino.modlib.memo.mixins import truncate_comment >>> print(truncate_comment('

Styled comment pasted from word!

')) ... #doctest: +NORMALIZE_WHITESPACE Styled comment pasted from word! >>> print(truncate_comment('

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

', 30)) Lorem ipsum dolor sit amet, co... >>> print(truncate_comment('

Lorem ipsum dolor sit amet

consectetur adipiscing elit.

', 30)) Lorem ipsum dolor sit amet (...) >>> print(truncate_comment('

A short paragraph

  • first
  • second

')) A short paragraph (...) >>> html = u'

Ich habe Hirn, ich will hier raus! – Wie im Netz der Flachsinn regiert.

\\n\\n
    \\n
  • Gefällt mirIch habe Hirn, ich will hier raus! – Wie im Netz der Flachsinn regiert\\n

     

    \\n806
  • \\n
  • Kommentar\\n

     

    \\n42
  • \\n
  • TeilenIch habe Hirn, ich will hier raus! – Wie im Netz der Flachsinn regiert teilen\\n

     

    \\n131
  • \\n
\\n

Gunter Dueck FolgenGunter Dueck Philosopher, Writer, Keynote Speaker

\\n

Das Smartphone vibriert, klingelt oder surrt. Zing! Das ist der Messenger. Eine Melodie von eBay zeigt an, dass eine Auktion in den nächsten Minuten endet. Freunde schicken Fotos, News versprechen uns "Drei Minuten, nach denen du bestimmt lange weinen musst" oder "Wenn du dieses Bild siehst, wird sich dein Leben auf der Stelle für immer verändern".

\\n

Politiker betreiben statt ihrer eigentlichen Arbeit nun simples Selbstmarketing und fordern uns auf, mal schnell unser Verhalten zu ändern – am besten natürlich "langfristig" und "nachhaltig". Manager fordern harsch immer mehr Extrameilen von uns ein, die alle ihre (!) Probleme beseitigen, und es gibt für jede Schieflage in unserem Leben Rat von allerlei Coaches und Therapeuten, es gibt Heilslehren und Globuli.

' >>> print(truncate_comment(html)) Ich habe Hirn, ich will hier raus! – Wie im Netz der Flachsinn regiert. (...) >>> print(truncate_comment('Some plain text.')) Some plain text. >>> print(truncate_comment('Two paragraphs of plain text.\n\n\nHere is the second paragraph.')) Two paragraphs of plain text. (...)