Skip to content

This PR adds customization and Template saving Features to extension. #103

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

Open
wants to merge 14 commits into
base: master
Choose a base branch
from

Conversation

Preeti9764
Copy link
Contributor

@Preeti9764 Preeti9764 commented Jun 2, 2025

Fixes

Fixes #88


📝 Summary of Changes

  • Added a new Settings tab for customization options
  • Added GitHub data filtering options
  • Added ability to save and load custom layout templates

✅ Checklist

  • I’ve tested my changes locally
  • My code follows the project’s code style guidelines

Summary by Sourcery

Add persistent customization controls and template management to the Scrum Helper extension, update the report generation logic to honor user settings, enhance the popup UI with a Settings tab, and configure a Release Drafter workflow for automated release notes generation.

New Features:

  • Add a Settings tab to toggle report sections (tasks, PRs, reviewed PRs, blockers) and GitHub filters (open only, exclude drafts)
  • Enable users to save, load, and delete custom layout templates persisted in extension storage

Enhancements:

  • Refactor content generation to respect section toggles and filters when assembling the scrum report
  • Introduce helper functions for loading, saving, and filtering settings and templates
  • Update popup UI and styling to support tabbed interface and settings management

CI:

  • Add GitHub Release Drafter workflow and configuration for automated changelog drafting

Preeti9764 and others added 8 commits May 25, 2025 15:29
Scrum subject and body message are now correctly added in Outlook (fossasia#81)
merge the readme changes
Signed-off-by: Vedansh Saini <[email protected]>
new changes added to the master before 1 june
Copy link
Contributor

sourcery-ai bot commented Jun 2, 2025

Reviewer's Guide

This PR introduces a persistent customization layer—allowing users to toggle report sections and apply GitHub filters—alongside the ability to save and load layout templates, restructures the popup UI to include a dedicated Settings tab, refactors content-generation routines to respect those settings, applies new styling for tabs and templates, and adds a Release Drafter workflow for automated release notes.

Sequence Diagram for Saving a Customization Template

sequenceDiagram
    actor User
    participant SettingsUI as "Settings UI (settings.js)"
    participant ScrumHelper as "scrumHelper.js"
    participant Storage as "chrome.storage.local"

    User->>SettingsUI: Modifies section toggles & filters
    User->>SettingsUI: Enters template name ("My Layout")
    User->>SettingsUI: Clicks "Save Current Layout"
    SettingsUI->>ScrumHelper: saveTemplate("My Layout", currentSettings)
    ScrumHelper->>Storage: get(["scrumTemplates"])
    Storage-->>ScrumHelper: { scrumTemplates: existingTemplates }
    ScrumHelper->>ScrumHelper: Add/Update "My Layout" in templates
    ScrumHelper->>Storage: set({ scrumTemplates: updatedTemplates })
    Storage-->>ScrumHelper: Promise resolves (save confirmation)
    ScrumHelper-->>SettingsUI: Promise resolves
    SettingsUI->>SettingsUI: refreshTemplateList()
    SettingsUI->>ScrumHelper: loadSettings() // Called by refreshTemplateList
    ScrumHelper->>Storage: get(["scrumSettings", "scrumTemplates"])
    Storage-->>ScrumHelper: { settings, templates: updatedTemplates }
    ScrumHelper-->>SettingsUI: { settings, templates }
    SettingsUI->>User: Display updated template list
Loading

Sequence Diagram for Report Generation with Custom Settings

sequenceDiagram
    actor User
    participant PopupUI as "Popup UI (popup.js)"
    participant ScrumHelper as "scrumHelper.js"
    participant Storage as "chrome.storage.local"
    participant GitHubAPI as "GitHub API"

    User->>PopupUI: Clicks "Generate Report"
    PopupUI->>ScrumHelper: allIncluded("popup")
    ScrumHelper->>ScrumHelper: loadSettings()
    ScrumHelper->>Storage: get(["scrumSettings", "scrumTemplates"])
    Storage-->>ScrumHelper: { settings, templates }
    ScrumHelper->>GitHubAPI: fetchGithubData() (details omitted)
    GitHubAPI-->>ScrumHelper: rawIssuesData, rawPrsReviewData
    ScrumHelper->>ScrumHelper: writeGithubIssuesPrs(rawIssuesData, settings)
    ScrumHelper->>ScrumHelper: filterGithubData(rawIssuesData, settings) // internal call
    ScrumHelper->>ScrumHelper: writeGithubPrsReviews(rawPrsReviewData, settings)
    ScrumHelper->>ScrumHelper: filterGithubData(rawPrsReviewData, settings) // internal call
    ScrumHelper->>ScrumHelper: writeScrumBody(settings)
    ScrumHelper-->>PopupUI: Formatted report content
    PopupUI->>User: Display report reflecting settings
Loading

Entity Relationship Diagram for Settings and Templates Storage

erDiagram
    CHROME_STORAGE_LOCAL {
        string key PK "Primary Key e.g., 'scrumSettings' or 'scrumTemplates'"
        json value "Stored data as JSON string"
    }

    ScrumSettingsObject {
        map sections "Key-value pairs for section visibility, e.g., {tasks: true, prs: false}"
        map filters "Key-value pairs for GitHub filters, e.g., {openOnly: true, excludeDrafts: false}"
    }

    TemplateObject {
        string name PK "User-defined template name"
        map sections "Snapshot of section visibility settings"
        map filters "Snapshot of GitHub filter settings"
    }

    CHROME_STORAGE_LOCAL ||--1 ScrumSettingsObject : "stores current settings (value for key 'scrumSettings')"
    CHROME_STORAGE_LOCAL ||--1 TemplateCollection : "stores all templates (value for key 'scrumTemplates')"

    TemplateCollection ||--o{ TemplateObject : "contains many (as a map of name:TemplateObject)"
Loading

Class Diagram for Settings and Template Management Logic

classDiagram
    class ScrumHelper {
      <<JavaScript: scrumHelper.js>>
      +DEFAULT_SETTINGS : Object
      +loadSettings() : Promise
      +saveSettings(settings) : Promise
      +saveTemplate(name, settings) : Promise
      +loadTemplate(name) : Promise
      +deleteTemplate(name) : Promise
      +filterGithubData(data, settings) : Object
      +allIncluded(outputTarget) : void
      +writeScrumBody() : void
      +writeGithubPrsReviews() : void
      +writeGithubIssuesPrs() : void
    }

    class SettingsController {
      <<JavaScript: settings.js>>
      +initializeUI() : void
      +refreshTemplateList() : void
      +handleSaveTemplate() : void
      +handleLoadTemplate(templateName) : void
      +handleDeleteTemplate(templateName) : void
      +handleSettingChange() : void
    }

    class ChromeStorageAPI {
      <<Browser API: chrome.storage.local>>
      +get(keys) : Promise
      +set(items) : Promise
    }

    ScrumHelper ..> ChromeStorageAPI : Uses
    SettingsController ..> ScrumHelper : Uses
    SettingsController ..> ChromeStorageAPI : Uses (via ScrumHelper.loadSettings)
Loading

File-Level Changes

Change Details Files
Persistent settings and template management
  • Define and load DEFAULT_SETTINGS via Chrome storage
  • Implement saveSettings, loadSettings, saveTemplate, loadTemplate, deleteTemplate
  • Add settings.js to bind UI toggles and template actions
src/scripts/scrumHelper.js
src/scripts/settings.js
Popup UI restructure with Settings tab
  • Introduce tabs in popup.html (CodeHeat & Settings)
  • Restructure HTML to separate CodeHeat content and Settings panel
  • Update main.js to initialize and persist selected tab
  • Include settings.js script in popup
src/popup.html
src/scripts/main.js
Dynamic content respects user settings and filters
  • Wrap writeScrumBody, writeGithubIssuesPrs, writeGithubPrsReviews in loadSettings promises
  • Invoke filterGithubData to apply openOnly/excludeDrafts filters
  • Conditionally include sections (tasks, PRs, reviewed, blockers) based on toggles
src/scripts/scrumHelper.js
Style updates for tabs and settings panel
  • Define tab and indicator styling, settings panel spacing, and template‐list appearance
  • Adjust form element and button styles for consistency
  • Add independent scrolling for settings content
src/index.css
Add automated release notes via Release Drafter
  • Add GitHub Actions workflow to draft releases on pushes to master
  • Provide release-drafter template for categorizing changes
.github/workflows/release-drafter.yml
.github/release-drafter.yml

Assessment against linked issues

Issue Objective Addressed Explanation

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
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 @Preeti9764 - I've reviewed your changes and found some issues that need to be addressed.

Blocking 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 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 reportElement.innerHTML is an anti-pattern that can lead to XSS vulnerabilities (link)
  • Concatenating raw item data directly into HTML risks XSS (link)

General comments:

  • Consider caching settings and templates upon initialization and passing them through your data-processing functions instead of repeatedly calling chrome.storage.local.get in each step to improve performance and readability.
  • The repeated promise wrappers around chrome.storage.local.get/set could be refactored into a single storage utility to reduce duplication and simplify future maintenance.
  • The CSS approach for toggling between the main and settings tabs relies on complex sibling selectors—switching to explicit class toggles on the container might be more robust and easier to maintain.
Here's what I looked at during the review
  • 🟡 General issues: 5 issues found
  • 🔴 Security: 4 blocking issues
  • 🟢 Testing: all looks good
  • 🟢 Documentation: all looks good

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.

window.generateScrumReport();

// Reset button state after a short delay
setTimeout(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (bug_risk): Avoid fixed timeout for resetting Generate button

Instead of using a hardcoded delay, reset the button state when generateScrumReport() completes—either by returning a promise or emitting an event and handling it accordingly.

Suggested implementation:

        // Generate report and reset button state when done
        Promise.resolve(window.generateScrumReport()).finally(() => {
            this.innerHTML = '<i class="fa fa-refresh"></i> Generate Report';
            this.disabled = false;

            // Ensure the window stops scrolling
            window.scrollTo(0, window.scrollY);
        });
  • Ensure that window.generateScrumReport() returns a Promise that resolves when the report generation is complete. If it does not, you will need to refactor that function accordingly.

loadSettings().then(({ settings }) => {
setTimeout(() => {
// Generate content based on enabled sections
var lastWeekUl = '<ul>';
Copy link
Contributor

Choose a reason for hiding this comment

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

🚨 suggestion (security): Concatenating raw item data directly into HTML risks XSS

Sanitize user-supplied values like item.title and project, or use DOM APIs to prevent XSS vulnerabilities from untrusted content.

Suggested implementation:

		loadSettings().then(({ settings }) => {
			setTimeout(() => {
				// Utility function to escape HTML special characters
				function escapeHtml(str) {
					return String(str)
						.replace(/&/g, '&amp;')
						.replace(/</g, '&lt;')
						.replace(/>/g, '&gt;')
						.replace(/"/g, '&quot;')
						.replace(/'/g, '&#39;');
				}
				// Generate content based on enabled sections

You must now use escapeHtml() whenever you insert user-supplied values (such as item.title, project, etc.) into HTML strings. For example:

lastWeekUl += '<li>' + escapeHtml(item.title) + ' (' + escapeHtml(project) + ')</li>';

Search for all such concatenations in this file and update them accordingly.

});

// Initialize template list
refreshTemplateList(templates);
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: refreshTemplateList is called with an unused argument

Consider removing the unused argument from the call or updating the function to use it for clarity.

Comment on lines +21 to +22
document.getElementById('filter-open-only').checked = settings.filters.openOnly;
document.getElementById('filter-exclude-drafts').checked = settings.filters.excludeDrafts;
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Initial filter toggles aren’t reflected in label styling

Apply the same class toggling for filter labels during initialization as is done in handleOpenLabelChange to ensure consistent UI state.

Suggested change
document.getElementById('filter-open-only').checked = settings.filters.openOnly;
document.getElementById('filter-exclude-drafts').checked = settings.filters.excludeDrafts;
document.getElementById('filter-open-only').checked = settings.filters.openOnly;
document.getElementById('filter-exclude-drafts').checked = settings.filters.excludeDrafts;
// Reflect initial filter state in label styling
['filter-open-only', 'filter-exclude-drafts'].forEach(filterId => {
const filter = document.getElementById(filterId);
const label = document.querySelector(`label[for="${filterId}"]`);
if (label) {
if (filter.checked) {
label.classList.add('active');
} else {
label.classList.remove('active');
}
}
});

var repository_url = item.repository_url;
var project = repository_url.substr(repository_url.lastIndexOf('/') + 1);
var title = item.title;
var number = item.number;
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Use const or let instead of var. (avoid-using-var)

Explanation`const` is preferred as it ensures you cannot reassign references (which can lead to buggy and confusing code). `let` may be used if you need to reassign references - it's preferred to `var` because it is block- rather than function-scoped.

From the Airbnb JavaScript Style Guide

var project = repository_url.substr(repository_url.lastIndexOf('/') + 1);
var title = item.title;
var number = item.number;
var html_url = item.html_url;
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Use const or let instead of var. (avoid-using-var)

Explanation`const` is preferred as it ensures you cannot reassign references (which can lead to buggy and confusing code). `let` may be used if you need to reassign references - it's preferred to `var` because it is block- rather than function-scoped.

From the Airbnb JavaScript Style Guide

Comment on lines 428 to 433
var obj = {
number: number,
html_url: html_url,
title: title,
state: item.state,
};
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Use const or let instead of var. (avoid-using-var)

Explanation`const` is preferred as it ensures you cannot reassign references (which can lead to buggy and confusing code). `let` may be used if you need to reassign references - it's preferred to `var` because it is block- rather than function-scoped.

From the Airbnb JavaScript Style Guide

prText1 += issue_opened_button;

for (var repo in githubPrsReviewDataProcessed) {
var repoLi = '<li><i>(' + repo + ')</i> - Reviewed ';
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Use const or let instead of var. (avoid-using-var)

Explanation`const` is preferred as it ensures you cannot reassign references (which can lead to buggy and confusing code). `let` may be used if you need to reassign references - it's preferred to `var` because it is block- rather than function-scoped.

From the Airbnb JavaScript Style Guide


if (githubPrsReviewDataProcessed[repo].length <= 1) {
for (var pr in githubPrsReviewDataProcessed[repo]) {
var pr_arr = githubPrsReviewDataProcessed[repo][pr];
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Use const or let instead of var. (avoid-using-var)

Explanation`const` is preferred as it ensures you cannot reassign references (which can lead to buggy and confusing code). `let` may be used if you need to reassign references - it's preferred to `var` because it is block- rather than function-scoped.

From the Airbnb JavaScript Style Guide

@Preeti9764
Copy link
Contributor Author

Preeti9764 commented Jun 2, 2025

@hpdang @mariobehling I've implemented customisation and Template saving Features in the Scrum Helper extension. Suggest changes which i can do in Ui and your feedback on this, whether these features looks goods. For now i have added the codeheat tab only. Open to changes and happy to iterate based on your suggestions.

@Preeti9764 Preeti9764 changed the title This PR adds customization features and Template saving Features to extension. This PR adds customization and Template saving Features to extension. Jun 2, 2025
Copy link
Contributor

@vedansh-5 vedansh-5 left a comment

Choose a reason for hiding this comment

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

The templates are a nice addition, I've left a few comments.
Also another thing that can be added in the templates is custom headings.
We can discuss this in the weekly meeting today.
Thanks!

@Preeti9764
Copy link
Contributor Author

hey, @vedansh-5 I have made changes for some of the issues you mentioned , the same name one is left..It would be great if you once check and give feedback.

Copy link
Contributor

@vedansh-5 vedansh-5 left a comment

Choose a reason for hiding this comment

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

The templates work as expected also the caching is in place, I observed a weird behavior with the checks, I believe they would be removed in the future.
image
Also please include the headers in template and drop caching since I already have a pr for the same.

@Preeti9764
Copy link
Contributor Author

Preeti9764 commented Jun 7, 2025

The templates work as expected also the caching is in place, I observed a weird behavior with the checks, I believe they would be removed in the future.

Yes, they are for testing purposes.

@Preeti9764
Copy link
Contributor Author

Also please include the headers in template and drop caching since I already have a pr for the same.

Please elloborate about headers you want me to add.

@Preeti9764
Copy link
Contributor Author

Preeti9764 commented Jun 7, 2025

@hpdang I request you try the new features and share your feedback whenever you get time

customisation.mp4

@hpdang
Copy link
Member

hpdang commented Jun 9, 2025

To do for this PRs:

CodeHeat tab:

  • Replace the word CodeHeat with Setting
  • Define default setup here (use the current setup we have under GSoC)

Setting tab

  • Replace the word Setting with Template
  • What is the flow if no template is selected

Change the top description to:
"Report your development progress by auto-fetching your Git activity for a selected period."

@Preeti9764
Copy link
Contributor Author

To do for this PRs:

CodeHeat tab:

  • Replace the word CodeHeat with Setting
  • Define default setup here (use the current setup we have under GSoC)

Setting tab

  • Replace the word Setting with Template
  • What is the flow if no template is selected

Change the top description to: "Report your development progress by auto-fetching your GitHub activity for a selected period."

okay thanks! will do these changes soon

@Preeti9764
Copy link
Contributor Author

Preeti9764 commented Jun 9, 2025

  • What is the flow if no template is selected

Initially, all checkboxes are selected, and the type of report includes PRs, issues, and reviews. After that, the user can filter it by going to the Template tab and also save the changes for future use, which will be saved in Templates.if no template is selected, the report will be generated according to the selected checkboxes.

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.

Feature Request: Customization ,Template Saving And Enhanced GitHub Integration for Scrum Generation
3 participants