Skip to content

Conversation

EstoesMoises
Copy link

Hello everyone! I'm super happy to be writing this PR as it's one of my first open-source contributions :) Plus, this is a feature that I really want to have as part of DecapCMS.

Meet the Notes Pane!


Summary

  • Introduced a Notes Pane in the Editor (only for the Editorial Workflow), allowing users to add, edit, resolve, and delete notes linked to entries.
  • Notes are managed per entry and support author info, timestamps, and resolution status.
  • Notes are synchronized with backend storage and displayed in the dedicated UI pane (the Notes Pane).
  • Added localization (English only) for all note-related actions and notifications.

Currently, the Notes feature has only been fully implemented on the GitHub backend and the Test Backend. I've also written some code for the Proxy Backend, but the feature will not work with local_backend as it requires the Editorial Workflow.

In essence, the goal of this feature works as a layer of abstraction for PR issue comments. With this we take more advantage of the information that is recorded in each PR issue. This aligns well with the philosophy behind the Editorial Workflow, particularly the (awesome) work Decap has done around PR and branch handling.

I made this change after following the discussion on [Issue 52](#52), and personally Decap is a tool that I really want to use for some Documentation projects, the only thing I felt was missing was a "comments" feature, which is collaboration aspect that other popular platforms like Google Docs provide. But well, Decap is cooler ¯_(ツ)_/¯ so it should have one as well.


Test Plan / Demonstration

Notes Pane UI within the Editor:

Screenshot 2025-07-28 214457

GitHub Comments:

Screenshot 2025-07-28 214711

Resolving Notes adds an HTML comment to the GitHub PR Issue Comment:

Screenshot 2025-07-28 214723 Screenshot 2025-07-28 214732

This passes all current tests, and I've modified some test files to account for the Notes actions. There’s still a pending change to add backend/implementation-specific testing.


Current state / room for improvement

There is definitely room for improvement in this MVP. A few features that come to mind, and that are definitely on my roadmap (and I’d be more than happy to collaborate with others to make them happen) are:

  • Polling new comments every few seconds/minutes
  • As discussed in [Issue 52](Add a "notes pane" to the edit screen #52), this pane could be extended to show recent user activity, for example, when an entry has been reviewed, published, or unpublished.
  • Implementation across all backends (currently only GitHub is supported as a production backend)
  • Better unit testing

One of the main reasons I wanted to publish this in its current state is to get some early feedback before diving into more work. I’m really looking forward to hearing the maintainers’ thoughts and collaborating to make the Notes Pane feature as solid as possible.


Checklist

Please add an x inside each checkbox:


A picture of a cute animal (not mandatory but encouraged)

My dog, Luna :)

image

@EstoesMoises
Copy link
Author

In case this also helps navigate changes. Here's a summary provided by CoderabbitAI on the files changed:

Cohort / File(s) Change Summary
GitHub Backend Notes API
packages/decap-cms-backend-github/src/API.ts, packages/decap-cms-backend-github/src/implementation.tsx, packages/decap-cms-backend-github/src/types/githubPullRequests.ts
Adds methods to manage notes as PR comments, parse/format note content, handle note CRUD, and fetch PR metadata. Exposes note management in the backend implementation and defines the GitHubIssueComment type.
Proxy and Test Backend Notes
packages/decap-cms-backend-proxy/src/implementation.ts, packages/decap-cms-backend-test/src/implementation.ts
Implements note CRUD and PR metadata methods in proxy and test backends, with in-memory or delegated storage, including error handling and mock data for tests.
Core Backend and Types
packages/decap-cms-core/src/backend.ts, packages/decap-cms-lib-util/src/implementation.ts, packages/decap-cms-lib-util/src/index.ts
Extends backend interface and lib-util types to support notes and PR metadata methods, including the Note type and related signatures.
Redux Actions and Reducers
packages/decap-cms-core/src/actions/entries.ts, packages/decap-cms-core/src/reducers/entryDraft.js, packages/decap-cms-core/src/types/redux.ts, packages/decap-cms-core/src/reducers/__tests__/entryDraft.spec.js
Adds note-related action types, action creators, and thunks for note lifecycle events. Updates reducer and types to manage notes in draft state, with corresponding test updates.
Editor UI Integration
packages/decap-cms-core/src/components/Editor/Editor.js, packages/decap-cms-core/src/components/Editor/EditorInterface.js
Integrates notes into the editor UI, including state management, loading, and persistence, with new handlers and props for note actions and conditional rendering of the notes pane.
Editor Notes Pane Components
packages/decap-cms-core/src/components/Editor/EditorNotesPane/AddNoteForm.js, packages/decap-cms-core/src/components/Editor/EditorNotesPane/EditorNotesPane.js, packages/decap-cms-core/src/components/Editor/EditorNotesPane/NoteItem.js, packages/decap-cms-core/src/components/Editor/EditorNotesPane/NotesList.js
Introduces new React components for displaying, adding, editing, resolving, and deleting notes in a dedicated notes pane, with styled UI and user interaction logic.
Localization
packages/decap-cms-locales/src/en/index.js
Adds English localization strings for all notes-related UI, actions, and notifications.
Core Actions Test
packages/decap-cms-core/src/actions/__tests__/editorialWorkflow.spec.js
Updates editorial workflow test to cover note loading and related action dispatches.

@martinjagodic martinjagodic requested a review from Copilot July 31, 2025 08:35
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a collaborative Notes Pane feature for the Editor screen, enabling users to add, edit, resolve, and delete notes linked to entries in the Editorial Workflow. The notes are backed by GitHub PR comments and synchronized with backend storage.

  • Added comprehensive Notes system with CRUD operations, resolution tracking, and UI components
  • Implemented backend support for GitHub and Test backends with PR comments integration
  • Added localization support for all note-related messages and actions

Reviewed Changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/decap-cms-locales/src/en/index.js Added English localization strings for Notes Pane UI and notifications
packages/decap-cms-lib-util/src/implementation.ts Added Note interface and optional note-related methods to Implementation
packages/decap-cms-core/src/types/redux.ts Added Note types and action payload definitions for Redux state
packages/decap-cms-core/src/reducers/entryDraft.js Updated reducer to handle notes state and actions
packages/decap-cms-core/src/components/Editor/EditorNotesPane/*.js Created Notes Pane UI components for displaying and managing notes
packages/decap-cms-core/src/components/Editor/EditorInterface.js Integrated Notes Pane into editor interface with toggle functionality
packages/decap-cms-core/src/components/Editor/Editor.js Added notes loading and change handling logic
packages/decap-cms-core/src/backend.ts Added backend wrapper methods for note operations
packages/decap-cms-core/src/actions/entries.ts Implemented Redux actions for notes CRUD operations
packages/decap-cms-backend-/src/implementation. Added notes implementation for GitHub, Test, and Proxy backends

state = {
showEventBlocker: false,
previewVisible: localStorage.getItem(PREVIEW_VISIBLE) !== 'false',
notesVisible: localStorage.getItem(NOTES_VISIBLE) === 'false',
Copy link
Preview

Copilot AI Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for initializing notesVisible is inverted. It should be === 'true' to show notes when the localStorage value is 'true', not when it's 'false'.

Suggested change
notesVisible: localStorage.getItem(NOTES_VISIBLE) === 'false',
notesVisible: localStorage.getItem(NOTES_VISIBLE) === 'true',

Copilot uses AI. Check for mistakes.

<AvatarImage
src={note.get('avatarUrl')}
alt={`${note.get('author')} avatar`}
onError={e => {
Copy link
Preview

Copilot AI Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onError handler assumes the next sibling exists but doesn't verify it. This could cause runtime errors if the DOM structure changes. Consider adding a null check: e.target.nextSibling?.style && (e.target.nextSibling.style.display = 'flex')

Copilot uses AI. Check for mistakes.

author: currentUser.login || currentUser.name,
avatarUrl: currentUser.avatar_url,
entrySlug: slug,
timestamp: noteData.timestamp || new Date().toISOString(),
Copy link
Preview

Copilot AI Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The noteData.timestamp is being used as a fallback, but the Note interface shows timestamp as a required field. Either the interface should mark it as optional or this fallback should be removed to ensure consistency.

Copilot uses AI. Check for mistakes.

private formatNoteForPR(note: Note): string {
const status = note.resolved ? API.NOTE_STATUS_RESOLVED : API.NOTE_STATUS_OPEN;

return `<!-- DecapCMS Note - Status: ${status} -->
Copy link
Preview

Copilot AI Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The template literal has trailing spaces after the HTML comment. This could cause inconsistent formatting. Consider removing trailing whitespace or using a more structured approach.

Suggested change
return `<!-- DecapCMS Note - Status: ${status} -->
return `<!-- DecapCMS Note - Status: ${status} -->

Copilot uses AI. Check for mistakes.

const loadedEntry = await tryLoadEntry(getState(), collection, slug);
dispatch(entryLoaded(collection, loadedEntry));
dispatch(createDraftFromEntry(loadedEntry));
await dispatch(loadNotes(collection, slug));
Copy link
Preview

Copilot AI Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loadNotes call is made without checking if the backend supports notes or if workflow is enabled. This could cause unnecessary API calls or errors for backends that don't implement notes.

Copilot uses AI. Check for mistakes.

Comment on lines 108 to 114
handleBlur = () => {
// Delay to allow button click to register
setTimeout(() => {
if (!this.state.content.trim()) {
this.setState({ isFocused: false });
}
}, 150);
Copy link
Preview

Copilot AI Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using setTimeout with magic number 150ms to handle blur/click timing is fragile and could cause race conditions. Consider using a more robust approach like checking if the click target is the submit button or using onMouseDown instead of onClick.

Suggested change
handleBlur = () => {
// Delay to allow button click to register
setTimeout(() => {
if (!this.state.content.trim()) {
this.setState({ isFocused: false });
}
}, 150);
handleBlur = e => {
const { relatedTarget } = e;
if (relatedTarget && relatedTarget.type === 'submit') {
return; // Do not update state if blur is caused by clicking the submit button
}
if (!this.state.content.trim()) {
this.setState({ isFocused: false });
}

Copilot uses AI. Check for mistakes.

@EstoesMoises
Copy link
Author

EstoesMoises commented Aug 1, 2025

Hey @martinjagodic, I'm planning to tackle some of the action items from Copilot and to review this and ensure it is production-ready for the Github Backend

Leaving the base for others to add compatibility with the other backends if they are interested.

The action items I'm thinking of before moving this from Draft PR to Ready are:

  • Tackling copilot recommendations
  • Add the new tests for my code
  • Add a way to GET the notes when other users add them, probably using GitHub Webhooks if possible, and if not, a button to manually reload the notes.

I believe that with that done, I would consider it ready to be implemented in Main after your review.

Let me know your thoughts on this and if you'd like to add anything else, or if you have any feedback.

Thanks very much!

@martinjagodic
Copy link
Member

@EstoesMoises sounds good! How do you debug this while developing, as it doesn't work with the local server?

@EstoesMoises
Copy link
Author

EstoesMoises commented Aug 1, 2025

@EstoesMoises sounds good! How do you debug this while developing, as it doesn't work with the local server?

@martinjagodic I've been swapping backends by changing the config.yml from the dev-test folder. Since I'm focusing on Github compatibility, I'm using the configuration for Github locally - https://github.com/decaporg/decap-cms/blob/main/dev-test/config.yml

For debugging, I created and connected my GitHub account and I use a GitHub repository I made for this purpose.

Please let me know if there is a different approach that you suggest.

Side note: So far, I've tested the Test Backend and GitHub Backend. When I started implementing this feature, I also considered creating functionality for the local backend by creating a .json for notes, but I reverted those changes to make this feature only available on Editorial Workflow.

@martinjagodic
Copy link
Member

I had a really quick check and these are my first impressions:

  • Notes should be opt-in. I suggest editor.notes: true/false (false is default)
  • Should work with i18n. The toggle button should be different, because now it's the same icon that toggles side-by-side locale editing.
  • All entries should have notes, not only unpublished ones.

@EstoesMoises
Copy link
Author

I had a really quick check and these are my first impressions:

  • Notes should be opt-in. I suggest editor.notes: true/false (false is default)
  • Should work with i18n. The toggle button should be different, because now it's the same icon that toggles side-by-side locale editing.
  • All entries should have notes, not only unpublished ones.

Perfect! - Thanks for the feedback Martin. I will work on this

@EstoesMoises
Copy link
Author

Just wanted to leave a quick note - due to some unexpected life events, it might take me up to two weeks to get back with an update. I’ll still be working on the changes as soon as I can and I'm looking forward and aiming to get this feature completed 👍

@EstoesMoises
Copy link
Author

Hello everyone, due to unexpected circumstances, it has been a while since my last update, but I'm still here and will get this updated very soon 👍 I'm just sending this message to confirm that this is not abandoned, and I'm very excited about getting this feature ready :P

@EstoesMoises EstoesMoises marked this pull request as ready for review September 25, 2025 20:34
@EstoesMoises EstoesMoises requested a review from a team as a code owner September 25, 2025 20:34
@EstoesMoises
Copy link
Author

EstoesMoises commented Sep 25, 2025

Hey @martinjagodic this PR is ready for your review.

  • I made notes optional as suggested. Via config editor.notes
  • I've added the required tests for the Github implementation.
  • Changed from using PR Comments to create Github issues (and issues comments), this way I could enable Notes to both Published and Unpublished entries.
  • Github issues are closed when entries are published and are reopened if that same entry is unpublished.

Let me know your thoughts on this ! Looking forward to your feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants