Skip to content

Add contributor and access_level flags to work item note

Deepika Guliani requested to merge note-permission-backend into master

What does this MR do and why?

To show relevant badges with work item notes , whether the author of the note is a contributor and the what role the note author has in the project , we need some fields in the GraphlQL response.

This information is already present in issuables -> Issues/MR's

Contributor badge in issuables Role badge in issuables
Screenshot_2023-06-09_at_11.05.28_AM Screenshot_2023-06-09_at_11.05.34_AM

This MR aims at adding those fields in WorkItemNote

Closes task - Add Backend for contributor and access level of... (#413617 - closed)

Parent Issue - Work item discussions: Show author role/human a... (#412786 - closed)

The name of the exposed 2 new fields to WorkItemNote

  1. authorIsContributor - Boolean field to know if the author of the note is a contributor
  2. maxAccessLevelOfAuthor - String field to know the role of the note author in the project Can be Owner/Developer/Maintainer

Screenshots or screen recordings

Graphql Query
  • Visit http://gdk.test:3000/-/graphql-explorer and test the following query:
query workItemNotesByIid($fullPath: ID!, $iid: String, $after: String, $pageSize: Int) {
  workspace: project(fullPath: $fullPath) {
    id
    workItems(iid: $iid) {
      nodes {
        id
        iid
        widgets {
          ... on WorkItemWidgetNotes {
            type
            discussions(first: $pageSize, after: $after, filter: ALL_NOTES) {
              pageInfo {
                ...PageInfo
                __typename
              }
              nodes {
                id
                notes {
                  nodes {
                    ...WorkItemNote
                    __typename
                  }
                  __typename
                }
                __typename
              }
              __typename
            }
            __typename
          }
          __typename
        }
        __typename
      }
      __typename
    }
    __typename
  }
}

fragment PageInfo on PageInfo {
  hasNextPage
  hasPreviousPage
  startCursor
  endCursor
  __typename
}

fragment WorkItemNote on Note {
  id
  body
  bodyHtml
  system
  internal
  systemNoteIconName
  createdAt
  lastEditedAt
  url
  lastEditedBy {
    ...User
    webPath
    __typename
  }
  discussion {
    id
    __typename
  }
  author {
    ...User
    __typename
  }
  userPermissions {
    adminNote
    awardEmoji
    readNote
    createNote
    resolveNote
    repositionNote
    __typename
  }
  maxAccessLevelOfAuthor
  authorIsContributor
  systemNoteMetadata {
    id
    descriptionVersion {
      id
      description
      diff
      diffPath
      deletePath
      canDelete
      deleted
      __typename
    }
    __typename
  }
  __typename
}

fragment User on User {
  id
  avatarUrl
  name
  username
  webUrl
  __typename
}

You need to pass the following variables

{
  "fullPath": "gitlab-org/gitlab-shell",
  "iid": "38", // iid of any work item with notes
  "pageSize": 30
}
Graphql Response
{
  "data": {
    "workspace": {
      "id": "gid://gitlab/Project/3",
      "workItems": {
        "nodes": [
          {
            "id": "gid://gitlab/WorkItem/612",
            "iid": "38",
            "widgets": [
              {
                "__typename": "WorkItemWidgetAssignees"
              },
              {
                "__typename": "WorkItemWidgetLabels"
              },
              {
                "__typename": "WorkItemWidgetDescription"
              },
              {
                "__typename": "WorkItemWidgetHierarchy"
              },
              {
                "__typename": "WorkItemWidgetStartAndDueDate"
              },
              {
                "__typename": "WorkItemWidgetMilestone"
              },
              {
                "type": "NOTES",
                "discussions": {
                  "pageInfo": {
                    "hasNextPage": false,
                    "hasPreviousPage": false,
                    "startCursor": null,
                    "endCursor": null,
                    "__typename": "PageInfo"
                  },
                  "nodes": [
                    {
                      "id": "gid://gitlab/Discussion/ecaf3f0f65a4b44768b3ef4b811f591f1e1582e0",
                      "notes": {
                        "nodes": [
                          {
                            "id": "gid://gitlab/Note/327",
                            "body": "added #37 as parent issue",
                            "bodyHtml": "<p data-sourcepos=\"1:1-1:25\" dir=\"auto\">added <a href=\"/gitlab-org/gitlab-shell/-/issues/37\" data-reference-type=\"issue\" data-original=\"#37\" data-link=\"false\" data-link-reference=\"false\" data-project=\"3\" data-issue=\"456\" data-project-path=\"gitlab-org/gitlab-shell\" data-iid=\"37\" data-issue-type=\"issue\" data-container=\"body\" data-placement=\"top\" title=\"Dismiss Cipher with no integrity\" class=\"gfm gfm-issue\">#37</a> as parent issue</p>",
                            "system": true,
                            "internal": false,
                            "systemNoteIconName": "link",
                            "createdAt": "2023-05-29T08:41:54Z",
                            "lastEditedAt": "2023-05-29T08:41:54Z",
                            "url": "http://127.0.0.1:3000/gitlab-org/gitlab-shell/-/work_items/38#note_327",
                            "lastEditedBy": null,
                            "discussion": {
                              "id": "gid://gitlab/Discussion/ecaf3f0f65a4b44768b3ef4b811f591f1e1582e0",
                              "__typename": "Discussion"
                            },
                            "author": {
                              "id": "gid://gitlab/User/1",
                              "avatarUrl": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
                              "name": "Administrator",
                              "username": "root",
                              "webUrl": "http://127.0.0.1:3000/root",
                              "__typename": "UserCore"
                            },
                            "userPermissions": {
                              "adminNote": false,
                              "awardEmoji": true,
                              "readNote": true,
                              "createNote": true,
                              "resolveNote": true,
                              "repositionNote": false,
                              "__typename": "NotePermissions"
                            },
                            "maxAccessLevelOfAuthor": "Owner",
                            "authorIsContributor": false,
                            "systemNoteMetadata": {
                              "id": "gid://gitlab/SystemNoteMetadata/151",
                              "descriptionVersion": null,
                              "__typename": "SystemNoteMetadata"
                            },
                            "__typename": "Note"
                          }
                        ],
                        "__typename": "NoteConnection"
                      },
                      "__typename": "Discussion"
                    },
                    {
                      "id": "gid://gitlab/Discussion/f711c1f642be17f8748b71af1e838cf2791300b3",
                      "notes": {
                        "nodes": [
                          {
                            "id": "gid://gitlab/Note/328",
                            "body": "comment",
                            "bodyHtml": "<p data-sourcepos=\"1:1-1:7\" dir=\"auto\">comment</p>",
                            "system": false,
                            "internal": false,
                            "systemNoteIconName": null,
                            "createdAt": "2023-05-29T08:42:03Z",
                            "lastEditedAt": "2023-05-29T08:42:03Z",
                            "url": "http://127.0.0.1:3000/gitlab-org/gitlab-shell/-/work_items/38#note_328",
                            "lastEditedBy": null,
                            "discussion": {
                              "id": "gid://gitlab/Discussion/f711c1f642be17f8748b71af1e838cf2791300b3",
                              "__typename": "Discussion"
                            },
                            "author": {
                              "id": "gid://gitlab/User/1",
                              "avatarUrl": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
                              "name": "Administrator",
                              "username": "root",
                              "webUrl": "http://127.0.0.1:3000/root",
                              "__typename": "UserCore"
                            },
                            "userPermissions": {
                              "adminNote": true,
                              "awardEmoji": true,
                              "readNote": true,
                              "createNote": true,
                              "resolveNote": true,
                              "repositionNote": true,
                              "__typename": "NotePermissions"
                            },
                            "maxAccessLevelOfAuthor": "Owner",
                            "authorIsContributor": false,
                            "systemNoteMetadata": null,
                            "__typename": "Note"
                          }
                        ],
                        "__typename": "NoteConnection"
                      },
                      "__typename": "Discussion"
                    }
                  ],
                  "__typename": "DiscussionConnection"
                },
                "__typename": "WorkItemWidgetNotes"
              },
              {
                "__typename": "WorkItemWidgetIteration"
              },
              {
                "__typename": "WorkItemWidgetWeight"
              },
              {
                "__typename": "WorkItemWidgetNotifications"
              },
              {
                "__typename": "WorkItemWidgetCurrentUserTodos"
              },
              {
                "__typename": "WorkItemWidgetAwardEmoji"
              }
            ],
            "__typename": "WorkItem"
          }
        ],
        "__typename": "WorkItemConnection"
      },
      "__typename": "Project"
    }
  }
}

How to set up and validate locally

Numbered steps to set up and validate the change are strongly suggested.

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Deepika Guliani

Merge request reports

Loading