Skip to content

Enhancement : improve UX for scrum report editing #558

Open
kaungmyatshwe1397 wants to merge 6 commits intofossasia:mainfrom
kaungmyatshwe1397:fix/update-scrumReport-UX
Open

Enhancement : improve UX for scrum report editing #558
kaungmyatshwe1397 wants to merge 6 commits intofossasia:mainfrom
kaungmyatshwe1397:fix/update-scrumReport-UX

Conversation

@kaungmyatshwe1397
Copy link
Copy Markdown
Contributor

@kaungmyatshwe1397 kaungmyatshwe1397 commented Apr 16, 2026

📌 Fixes

Fixes #557


📝 Summary of Changes

  • Restructured generated scrum reports into separate sections with locked headings and editable bodies
  • Updated the popup report container to work correctly with structured scrum report content
  • Added structured export handling so Copy and Insert in Email generate clean HTML instead of popup-specific markup
  • Preserved compatibility with legacy scrum report HTML through a fallback export path
  • Sanitized exported section content by stripping edit-related attributes and normalizing heading/body content
  • Fixed the heading-removal order during export so duplicated nested heading blocks are removed correctly before copy/email output is built

📸 Screenshots / Demo (if UI-related)

Editable report body with fixed headings

Screen.Recording.2026-04-16.101338.mp4

Testing the update report to check sanitizing when report insert into email

Screen.Recording.2026-04-16.101622.mp4

✅ Checklist

  • I’ve tested my changes locally
  • I’ve added tests (if applicable)
  • I’ve updated documentation (if applicable)
  • My code follows the project’s code style guidelines

👀 Reviewer Notes

This PR is intended as a focused UX enhancement for scrum report editing rather than a broad refactor.

Summary by Sourcery

Improve the scrum report editing UX by structuring generated reports into locked-heading sections while ensuring clean HTML export for email and copy actions.

New Features:

  • Structure generated scrum reports into distinct sections with fixed headings and editable bodies in the popup.

Bug Fixes:

  • Ensure copied and emailed scrum reports export clean, sanitized HTML instead of popup-specific markup and attributes.
  • Preserve compatibility with previously stored legacy scrum report HTML while still supporting the new structured format.
  • Avoid stale unstructured reports by regenerating when cached content is not in the new structured format.

Enhancements:

  • Toggle scrum report editability automatically based on whether structured sections are present, keeping headings non-editable.
  • Normalize section body content on export by stripping edit-related attributes and removing duplicated nested headings.
  • Reuse username and cache-based logic for restoring last scrum reports while integrating the new structured report handling.

Copilot AI review requested due to automatic review settings April 16, 2026 03:34
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Apr 16, 2026

Reviewer's Guide

Implements structured scrum report sections with locked headings and editable bodies in the popup, adds robust HTML export/sanitization for copy/email actions (with legacy fallback), and wires popup lifecycle and storage logic to correctly toggle editability and regenerate reports when needed.

Sequence diagram for scrum report export (copy and insert in email)

sequenceDiagram
  actor popupUser
  participant Popup
  participant buildExportableScrumHtml
  participant normalizeLegacyReportHtml
  participant EmailClientAdapter
  participant Clipboard

  popupUser->>Popup: Click insertInEmail
  Popup->>buildExportableScrumHtml: buildExportableScrumHtml(scrumReport)
  buildExportableScrumHtml->>buildExportableScrumHtml: Find [data-scrum-report]
  alt Structured_scrum_report
    buildExportableScrumHtml->>buildExportableScrumHtml: Collect [data-scrum-section]
    buildExportableScrumHtml->>buildExportableScrumHtml: For_each_section
    buildExportableScrumHtml->>buildExportableScrumHtml: normalizeSectionBodyHtml(bodyEl)
    buildExportableScrumHtml->>buildExportableScrumHtml: escapeHtmlForExport(headingText)
    buildExportableScrumHtml-->>Popup: Joined_clean_HTML
  else Legacy_html
    buildExportableScrumHtml->>normalizeLegacyReportHtml: normalizeLegacyReportHtml(innerHTML)
    normalizeLegacyReportHtml->>normalizeLegacyReportHtml: stripEditAttributes(wrapper)
    normalizeLegacyReportHtml-->>buildExportableScrumHtml: Normalized_HTML
    buildExportableScrumHtml-->>Popup: Normalized_HTML
  end
  Popup->>EmailClientAdapter: injectContent(body, exportHtml, contentChangeEventType)

  popupUser->>Popup: Click copyReport
  Popup->>buildExportableScrumHtml: buildExportableScrumHtml(scrumReport)
  buildExportableScrumHtml-->>Popup: Exportable_HTML
  Popup->>Clipboard: Copy_via_temporary_hidden_div
Loading

File-Level Changes

Change Details Files
Introduce structured scrum report sections with locked headings and editable bodies and wire popup editability to this structure.
  • Generate scrum report popup HTML as a structured container with data-scrum-report, data-scrum-section, data-scrum-heading, and data-scrum-body attributes instead of a single flat HTML blob.
  • Split heading text generation into a dedicated helper so both popup and email outputs use the same heading strings.
  • Make the scrumReport container non-editable by default and programmatically toggle its contenteditable flag based on whether structured sections are present, including reacting to DOM mutations.
src/scripts/scrumHelper.js
src/scripts/popup.js
src/popup.html
Add clean export pipeline for structured scrum reports for Copy/Insert in Email, with sanitization and legacy HTML fallback.
  • Detect whether cached/loaded HTML is a structured scrum report before reusing it in the popup; for legacy HTML, trigger a fresh generation instead of reusing.
  • Implement helpers to strip edit-time attributes, normalize legacy and section body HTML, and escape heading text for safe export.
  • Build export HTML from structured sections by joining bold headings with their corresponding body HTML, and use this output for both email insertion and copy operations.
  • Ensure that when no structured sections are found, export falls back to sanitized legacy HTML so older cached reports still work.
src/scripts/popup.js
src/scripts/scrumHelper.js
Refine popup behavior, caching, and minor formatting for better UX and readability.
  • Re-enable scrum report generation/caching with platform- and username-aware keys while keeping compatibility with previous storage structure.
  • Ensure scrumReport edit mode is synchronized whenever cached HTML is restored or platform changes clear the report.
  • Tidy several long lines and event listeners for consistency and readability without changing behavior (e.g., token listeners, repo filtering notices).
src/scripts/popup.js

Assessment against linked issues

Issue Objective Addressed Explanation
#557 Generate the scrum report in a structured format with separate, locked heading sections and editable body sections, and ensure the popup detects structured content and syncs the container edit mode accordingly.
#557 Convert structured popup scrum report content into clean export HTML for copy/email actions, including sanitizing edit-specific attributes and nested heading blocks, while preserving compatibility by falling back to legacy report HTML when structured data is not available.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 6 security issues, 1 other issue, and left some high level feedback:

Security issues:

  • User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities (link)
  • User controlled data in a wrapper.innerHTML is an anti-pattern that can lead to XSS vulnerabilities (link)
  • User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities (link)
  • User controlled data in a tempDiv.innerHTML is an anti-pattern that can lead to XSS vulnerabilities (link)
  • User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities (link)
  • User controlled data in a scrumReport.innerHTML is an anti-pattern that can lead to XSS vulnerabilities (link)

General comments:

  • The structured scrum report HTML is currently built with large template strings in writeScrumBody; consider constructing the DOM nodes programmatically (or at least centralizing the section/attribute names) to reduce the risk of markup/escaping bugs and keep the structure easier to evolve.
  • isStructuredScrumReportHtml relies on a raw html.includes('data-scrum-report="true"') check against cached HTML, which is brittle to formatting/attribute ordering; parsing into a temporary element and reusing the same selector logic as syncScrumReportEditMode would make the detection more robust.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The structured scrum report HTML is currently built with large template strings in `writeScrumBody`; consider constructing the DOM nodes programmatically (or at least centralizing the section/attribute names) to reduce the risk of markup/escaping bugs and keep the structure easier to evolve.
- `isStructuredScrumReportHtml` relies on a raw `html.includes('data-scrum-report="true"')` check against cached HTML, which is brittle to formatting/attribute ordering; parsing into a temporary element and reusing the same selector logic as `syncScrumReportEditMode` would make the detection more robust.

## Individual Comments

### Comment 1
<location path="src/scripts/scrumHelper.js" line_range="1189" />
<code_context>
+		const blockerText = buildBlockerTextHtml();
+		const { heading1, heading2, heading3 } = buildScrumSectionHeadings();
+
+		// sturcture sections with locked headings and editable bodies
+		const popupContent = `<div data-scrum-report="true">
+<div data-scrum-section="1">
+<div data-scrum-heading="1" contenteditable="false"><b>${heading1}</b></div>
</code_context>
<issue_to_address>
**nitpick (typo):** Fix typo in the comment describing structured sections.

The comment currently says `sturcture sections`—please correct to `structure sections` for clarity.

```suggestion
		// structure sections with locked headings and editable bodies
```
</issue_to_address>

### Comment 2
<location path="src/scripts/popup.js" line_range="472" />
<code_context>
		wrapper.innerHTML = html;
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-document-method):** User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 3
<location path="src/scripts/popup.js" line_range="472" />
<code_context>
		wrapper.innerHTML = html;
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-innerhtml):** User controlled data in a `wrapper.innerHTML` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 4
<location path="src/scripts/popup.js" line_range="855" />
<code_context>
			tempDiv.innerHTML = buildExportableScrumHtml(scrumReport);
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-document-method):** User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 5
<location path="src/scripts/popup.js" line_range="855" />
<code_context>
			tempDiv.innerHTML = buildExportableScrumHtml(scrumReport);
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-innerhtml):** User controlled data in a `tempDiv.innerHTML` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 6
<location path="src/scripts/scrumHelper.js" line_range="1216" />
<code_context>
				scrumReport.innerHTML = popupContent;
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-document-method):** User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 7
<location path="src/scripts/scrumHelper.js" line_range="1216" />
<code_context>
				scrumReport.innerHTML = popupContent;
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-innerhtml):** User controlled data in a `scrumReport.innerHTML` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/scripts/scrumHelper.js Outdated
const blockerText = buildBlockerTextHtml();
const { heading1, heading2, heading3 } = buildScrumSectionHeadings();

// sturcture sections with locked headings and editable bodies
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nitpick (typo): Fix typo in the comment describing structured sections.

The comment currently says sturcture sections—please correct to structure sections for clarity.

Suggested change
// sturcture sections with locked headings and editable bodies
// structure sections with locked headings and editable bodies

Comment thread src/scripts/popup.js
if (!html || typeof html !== 'string') return '';

const wrapper = document.createElement('div');
wrapper.innerHTML = html;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

security (javascript.browser.security.insecure-document-method): User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

Comment thread src/scripts/popup.js
if (!html || typeof html !== 'string') return '';

const wrapper = document.createElement('div');
wrapper.innerHTML = html;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

security (javascript.browser.security.insecure-innerhtml): User controlled data in a wrapper.innerHTML is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

Comment thread src/scripts/popup.js
const scrumReport = document.getElementById('scrumReport');
const tempDiv = document.createElement('div');
tempDiv.innerHTML = scrumReport.innerHTML;
tempDiv.innerHTML = buildExportableScrumHtml(scrumReport);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

security (javascript.browser.security.insecure-document-method): User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

Comment thread src/scripts/popup.js
const scrumReport = document.getElementById('scrumReport');
const tempDiv = document.createElement('div');
tempDiv.innerHTML = scrumReport.innerHTML;
tempDiv.innerHTML = buildExportableScrumHtml(scrumReport);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

security (javascript.browser.security.insecure-innerhtml): User controlled data in a tempDiv.innerHTML is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

if (scrumReport) {
log('Found popup div, updating content');
scrumReport.innerHTML = content;
scrumReport.innerHTML = popupContent;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

security (javascript.browser.security.insecure-document-method): User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

if (scrumReport) {
log('Found popup div, updating content');
scrumReport.innerHTML = content;
scrumReport.innerHTML = popupContent;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

security (javascript.browser.security.insecure-innerhtml): User controlled data in a scrumReport.innerHTML is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

Copy link
Copy Markdown
Contributor

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 enhances the scrum report editing UX in the extension popup by introducing a structured report layout (locked headings + editable bodies) and ensuring copy/email exports generate clean HTML rather than popup-specific markup.

Changes:

  • Generate scrum reports as structured sections in the popup (non-editable headings, editable bodies).
  • Update popup behavior to detect structured reports, toggle editability appropriately, and export sanitized/clean HTML for Copy / Insert in Email.
  • Add fallback export handling for legacy (non-structured) scrum report HTML.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
src/scripts/scrumHelper.js Generates structured popup HTML with locked headings and separate editable bodies; keeps email output as clean non-structured HTML.
src/scripts/popup.js Detects structured scrum report markup, syncs popup edit mode, and builds export-ready HTML (Copy / Insert in Email) with legacy fallback.
src/popup.html Sets the scrum report container default to non-editable to support structured content.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/scripts/popup.js
Comment on lines 632 to +636
if (reportEmpty && lastScrumReportHtml && matches) {
if (!isStructuredScrumReportHtml(lastScrumReportHtml)) {
setGenerateButtonLoading(generateBtn, true);
window.generateScrumReport();
return;
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

bootstrapScrumReportOnPopupLoad forces a full regeneration when cached lastScrumReportHtml is legacy (non-structured), even though the PR description mentions preserving compatibility via a fallback export path. This behavior can discard a user's previously edited cached report within the TTL window. Consider rendering the legacy cached HTML as-is (and rely on buildExportableScrumHtml() for clean copy/email), or explicitly migrating legacy HTML to the structured format instead of regenerating unconditionally.

Copilot uses AI. Check for mistakes.
Comment thread src/scripts/scrumHelper.js Outdated
const blockerText = buildBlockerTextHtml();
const { heading1, heading2, heading3 } = buildScrumSectionHeadings();

// sturcture sections with locked headings and editable bodies
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

Typo in the comment: "sturcture" should be "structure".

Suggested change
// sturcture sections with locked headings and editable bodies
// structure sections with locked headings and editable bodies

Copilot uses AI. Check for mistakes.
Comment thread src/scripts/popup.js Outdated
return clone.innerHTML || '';
}

// Change clean html from structure scrumReport before sending email
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

Wording/grammar in this comment is unclear ("Change clean html from structure scrumReport..."). Consider rephrasing to something like "Build clean HTML from structured scrum report content before exporting" to avoid confusion for future maintainers.

Suggested change
// Change clean html from structure scrumReport before sending email
// Build clean HTML from structured scrum report content before sending email.

Copilot uses AI. Check for mistakes.
Comment thread src/scripts/scrumHelper.js Outdated
Comment on lines 1165 to 1166
const weekOrDay = yesterdayContribution ? 'yesterday' : 'the period';
const weekOrDay2 = 'today';
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

In buildScrumSectionHeadings, weekOrDay is only used in the yesterdayContribution branch; when yesterdayContribution is false it becomes an unused variable. Consider moving the declaration inside the if block or removing it to keep the function minimal.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core extension frontend javascript Pull requests that update javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Enhancement]: improve scrum report editing with lock headings and clean export

2 participants