Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Feature Request) Collaboration Features (comments on findings; tracked changes) #425

Open
includesec-nick opened this issue Apr 30, 2024 · 7 comments

Comments

@includesec-nick
Copy link

Our internal QA workflow involves a combination of inline editing and comments by our Technical Writers, which are then reviewed by consultants. It would be awesome if Ghostwriter supported comment threads and tracked changes/version history on individual findings so that consultants and reviewers can easily iterate on findings throughout the QA process.

If you have any thoughts on how this could be implemented please let me know--we might be able to help!

@includesec-nick includesec-nick changed the title Collaboration Features (comments on findings; tracked changes) (Feature Request) Collaboration Features (comments on findings; tracked changes) Apr 30, 2024
@domwhewell-sage
Copy link

+1 for this feature.
We're finding ourselves generating docx's QA'ing those then making changes in ghostwriter which can get complex. It would really help if there was a system for in-line comments!

@domwhewell-sage
Copy link

Hmm looks like the editor in use currently "tinymce" has a comments plugin tinycomments this looks to be very nifty as it adds a <span> containing an ID that can map to a record in the database containing the comment. However it looks to be a premium plugin

@domwhewell-sage
Copy link

Looking around abit more and I found LANCE a plugin to add inline comments to the editor. It works similar to the other one wrapping the selected text in an <annotation> tag and storing the comments in a dictionary in the annotations-data attribute. It seemed promising as I was able to add the plugin into my configuration but the editor was striping the <annotation> tag upon save.
There is also FLITE to track changes in your editor field.

The implimentation seems abit difficult to me as there is not much documentation out there and what does exist is rather vague
@chrismaddalena I dont know if you could help at all? A way these features could be implemented using these plugins or another way?

@includesec-nick
Copy link
Author

Hmm looks like the editor in use currently "tinymce" has a comments plugin tinycomments this looks to be very nifty as it adds a <span> containing an ID that can map to a record in the database containing the comment. However it looks to be a premium plugin

Hey @domwhewell-sage , thanks for looking into this! We reached out to TinyMCE and unfortunately tinycomments cannot be used in open source projects.

@chrismaddalena
Copy link
Collaborator

Tracking changes, keeping history, enabling comments, and collaborative editing are all things I have tracked on my wishlist. The implementation is tricky. TinyMCE supports these features, but they're all paid plugins and require TinyMCE Cloud.

Some Ghostwriter servers need to be run without an active internet connection, so a cloud service isn't an option. A service like TinyMCE cloud is also something that a lot of data handling policies wouldn't allow for some of the data stored in a Ghostwriter instance. That means it needs to be local to the server and scratch built. Maybe not entirely from scratch, but there aren't many good open-source options to use as a foundation.

@domwhewell-sage
Copy link

domwhewell-sage commented Jun 27, 2024

I have quickly mocked up a comments system based from what I saw in the LANCE comment system and tinymce
image
image

<p>This is the description of the <span class="comment" comment-data="%5B%7B%22author%22%3A%22646f6d2e77686577656c6c%22%2C%22comment%22%3A%22Is%20this%20not%20too%20short%3F%22%7D%2C%7B%22author%22%3A%2261646d696e%22%2C%22comment%22%3A%22No%22%7D%5D">vulnerability</span></p>

It needs alot more thought and cleaning up. But I think this should provide a good base

editor.ui.registry.addMenuItem('comment', {
    icon: 'comment',
    text: 'Comment',
    onAction: function () {
        const hex2ascii = (hexString) => {
            let decodedStr = '';
            for (let i = 0; i < hexString.length; i += 2) {
                const byte = parseInt(hexString.substr(i, 2), 16);
                decodedStr += String.fromCharCode(byte);
            }
            return decodedStr
        }

        const selection = editor.selection.getContent();
        const commentNode = editor.selection.getNode();
        let commentsThread = '';
        if (commentNode.nodeName === 'SPAN' && commentNode.hasAttribute('comment-data')) {
            commentDataDecoded = decodeURIComponent(commentNode.getAttribute('comment-data'));
            commentData = JSON.parse(commentDataDecoded);
            commentData.forEach(item => {
                const author = hex2ascii(item.author);
                const comment = item.comment;
                const float = author === hex2ascii(username) ? 'right' : 'left';
                commentsThread += `<div id="commentThread" style="float: ${float}; clear: both;">
                    <h1>${author}</h1>
                    <p>${comment}</p>
                </div>`;
            });
        }

        if (selection) {
            const commentBox = editor.windowManager.open({
                title: 'Add Comment',
                body: {
                    type: 'panel',
                    items: [
                        { type: 'htmlpanel', name: 'existingComments', html: commentsThread},
                        { type: 'textarea', name: 'comment', label: 'Comment' },
                    ]
                },
                buttons: [
                    { type: 'cancel', text: 'Cancel' },
                    { type: 'submit', text: 'Save' }
                ],
                onSubmit: (api) => {
                    const comment = api.getData().comment;
                    let commentThread = [];
                    const commentNode = editor.selection.getNode();
                    if (commentNode.nodeName === 'SPAN' && commentNode.hasAttribute('comment-data')) {
                        commentDataDecoded = decodeURIComponent(commentNode.getAttribute('comment-data'));
                        commentData = JSON.parse(commentDataDecoded);
                        commentData.forEach(item => {
                            const author = item.author;
                            const comment = item.comment;
                            commentThread.push({ author: author, comment: comment });
                        });
                    }
                    commentThread.push({ author: username, comment: comment });
                    editor.execCommand('mceInsertContent', false, `<span class="comment" comment-data="${encodeURIComponent(JSON.stringify(commentThread))}">${selection}</span>`);
                    api.close();
                }
            });
        }
    }
});

editor.on('click', function (e) {
    const node = editor.selection.getNode();
    if (node.nodeName === 'SPAN' && node.hasAttribute('comment-data')) {
        editor.selection.select(node.firstChild);
        editor.ui.registry.getAll().menuItems.comment.onAction();
    }
});

@chrismaddalena
Copy link
Collaborator

That looks great @domwhewell-sage. If we did something like this, we'll also need to update the reporting engine so it knows to ignore span elements with that class or comment-data attribute.

FLITE looks great for an editor solution. We'd probably want to do tracked changes on the server side to allow for sharing the tracking, showing diffs, and making it easy to revert to a specific version, but we could start with something like FLITE.

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

No branches or pull requests

3 participants