Skip to content

Comments

Records can have a conversation on their detail page: comments with one level of replies, Markdown, @mentions and requests for a reply that end up as tasks in the inbox.

final class OrderResource extends Resource
{
protected bool $comments = true;
// Optional: how comments behave.
public function comments(Comments $comments): Comments
{
return $comments->editWindow(15);
}
}

The comments appear below the components of the detail page, after the workflow, the ownership and your own detailComponents().

Permission Allows
<slug>.view reading the comments of records the user may see
<slug>.comment writing, answering, editing and removing own comments
<slug>.moderate removing comments of others

Both new permissions appear in the role editor when $comments is on. Every action is checked on the server against the record (permission and policies).

Method Default Effect
replies(bool) on replies to a comment, one level deep
mentions(bool) on @mentions of users, who are notified
replyRequests(bool) on Reply requested: the mentioned users get a task instead of a notification
notifyParticipants(bool) on who commented or was mentioned gets new comments of the record as notification
editWindow(?int $minutes) null null: authors edit any time, earlier versions stay visible; a number: editable for that many minutes, then fixed
  • Markdown like the MarkdownEditor: bold, lists, links. Raw HTML is escaped, unsafe links are removed.
  • Mentions: typing @ offers active members of the tenant who hold <slug>.view – arrows choose, Enter takes, Escape closes. A name typed by hand (@lena.schmidt) counts as well. The server finds the mentions in the text itself, among the users it would offer; you cannot mention yourself.
  • Reply requested: with the box ticked, each mentioned user gets a task in the inbox with the beginning of the comment and a link to it. The task is done when the user answers in the thread, or with Done without reply.
  • Ctrl/Cmd + Enter sends.
  • Editing keeps the text before each change as a version, shown below the comment (1 earlier version). With editWindow() only within the window; the server checks the time.
  • Removing replaces the comment with a note who removed it when. The text is kept in the audit log, the versions are deleted. Open reply requests of a removed thread are closed.
  • Every change of a comment is in the audit log, like changes of records.
Who When Message
mentioned users mentioned without reply request Lena mentioned you on “Order 42”
mentioned users with reply request the new task
participants a new comment, unless muted Lena commented on “Order 42”

Notifications link to the comment. They name the record, not the text. Mute on the comments of a record stops the notifications of that record for the user.

CommentCountColumn::make('comments')->label('Comments'),

The number of comments (removed ones are not counted), one query per page, with a speech bubble icon – useful in cards and on the board.

Comments are stored in anvil_comments with the table of the model and the internal id of the record (like files and tasks), versions in anvil_comment_versions, mentions in anvil_comment_mentions and muted records in anvil_comment_mutes. Deleting a record deletes its comments; soft deleted records keep them for a restore. service('comments') reads and writes comments from own code; it does not check permissions.

  • Mentions consider the permission <slug>.view, not policies of single records: a mentioned user may be refused by a policy when opening the link. Notifications therefore never contain the text of the comment.
  • Attachments of single comments are not supported; use the attachments of the record.
  • Reactions such as thumbs up are not part of comments.