debate-map / app

Monorepo for the client, server, etc. of the Debate Map website.
https://debatemap.app
MIT License
73 stars 16 forks source link

Add comments panel for nodes (basic implementation for now; will rework later) #256

Closed Venryx closed 2 months ago

Venryx commented 10 months ago

General area of the codebase where the node user-interface components are defined: https://github.com/debate-map/app/tree/main/Packages/client/Source/UI/%40Shared/Maps/Node

User-interface

This comments feature would be added as a new panel (named "Comments"), shown in the list that appears when the user hovers over a "node". (the buttons letting you open the different panels are rendered in the NodeUI_LeftBox.tsx file; the comments panel itself would be in a new file created in the Panels subfolder)

For now, the commenting functionality is fine to be quite basic. We'll iterate on the design once basic functionality is in place (likely will involve discussions between me (Venryx) and Jamie, since Jamie is the one who requested this comments panel/feature).

Basic functionality

Similar to the commenting feature of Facebook or Reddit, where signed-in users can provide a "root level" comment, or reply to an existing comment (which will then create a new thread / indent level in the UI). [no need for "likes" on comments at this point] These comments should be rendered as Markdown (ie. using the VReactMarkdown_Remarkable component, OR the VReactMarkdown component if the former has issues).

Adding comments

Each comment should be represented by two entries being added to the database -- one to the nodes table, and one to the nodeRevisions table. This is accomplished by calling the addChildNode endpoint in the graphql api of the app-server rust package.

You can play around with the graphql api by starting your local instance of the backend (using npm start backend.tiltUp_local), then going to localhost:5100/app-server/gql-playground. In that window, you should be able to explore the graphql api (using the "Docs" panel at the right of the page), and try out sending calls to it. You can also reference the file in the frontend that constructs these graphql requests, as seen here.

In this case, adding a comment should involve a graphql request that looks something like this:

mutation {
  addChildNode(input: {
    parentID: "PUT_ID_OF_NODE_BEING_COMMENTED_ON_HERE",
    node: {
      accessPolicy: "PUT_ID_OF_ACCESS_POLICY",
      type: "category"
    },
    revision: {
      phrasing: {
        text_base: "My new comment!",
        terms: []
      },
      attachments: []
    },
    link: {
      group: "freeform",
      orderKey: "a0"
    }
  }) {
    nodeID
    revisionID
    linkID
  }
}

The request above should "work as presented" for adding a regular child node, after:

Naturally of course, in this case we don't actually want a regular node, but rather a new type of "comment" node, which does not display in the regular map but rather gets displayed in the "Comments" panel. So start with the query above (in the graphql playground page linked above) just to get familiarity with the graphql api; but then when actually implementing the comments feature, you'll need to: (beyond the changes already mentioned)

Deleting comments

Should involve a call to the deleteNode endpoint, with the comment node's id supplied as the nodeID field. Basic implementation should be straightforward. Although worth noting that currently debate-map doesn't let you delete nodes until all "children and descendants" of the node are deleted or moved elsewhere. This is not ideal for a commenting system, but we can ignore this limitation for the moment.

Updating comments

We'll get into the details for this later on; for now simply adding and deleting comments is sufficient.

Displaying comments

Of course, this is only on the "comment adding" side. For displaying the comments, you'll need to get the list of comments on the node itself, display those, then in each of those comment component-instances, you'll need to get their set of subcomments, display those -- and so on recursively. For this, you'll want to use the GetNodeChildren() function in the frontend, and then filter the result from that to only the nodes of type "comment". So basically, in a new CommentUI component's render function you'd have a line like:

const subcomments = GetNodeChildren(comment.id).filter(a=>a.type == NodeType.comment);

Preventing comments from showing up elsewhere

While the above should be all that's needed for basic commenting functionality, an unwanted side-effect of "adding a new node-type" is that it means those comments will, by default, end up showing in some other places as well, where they shouldn't show up. The one that comes to mind at the moment is the "Search" panel at the top-right of the screen. Long-term we'll want to actually change the search endpoint in the backend to exclude nodes of type "comment". But for now, we can use a simpler patch where we just change the UI layer to not show search-results if the matching node that was found has type: comment.