Configurable issue types model (#14)#17
Open
stilliard wants to merge 4 commits into
Open
Conversation
Abstract the hardcoded issue "type" into a real data model where each type
maps to a GitHub native issue type, a set of default labels, and a body
template.
- Add Types module (popup/modules/types.js) with seeded defaults
(Bug/Enhancement/Other), backed by chrome.storage.local. Each type is
{ id, name, githubType, labels[], bodyTemplate }. Exposes getAll (seeds
on first use), saveAll, and find.
- Render the type radios from the model instead of hardcoded HTML.
- Build the new-issue URL from the selected type: emit &type= (native issue
type, ignored where unsupported), &labels= (supports multiple), and the
body template — replacing the inline if (type=='bug') chain.
- Adopt the updated feature template order: Story -> Requirements -> Tasks
-> Acceptance criteria.
- Gate IssueForm.init behind a readiness barrier so it never restores/binds
the async-rendered radios before they exist.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR implements a configurable “Issue Types” data model (GitHub native issue type + default labels + body template) and refactors the popup UI/submit flow to use it instead of hardcoded radios and template logic.
Changes:
- Added
popup/modules/types.jsto seed, persist, and query issue types fromchrome.storage.local. - Updated the report-issue screen to render type radios dynamically into
#type_optionsinstead of hardcoded HTML. - Refactored the submit handler to build
&type=, multi-label&labels=, and&body=from the selected type model.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| popup/modules/types.js | Introduces the Types model with defaults, storage helpers, and lookup. |
| popup/app.js | Renders type selector from storage and builds the GitHub new-issue URL from the selected type. |
| popup/app.html | Replaces hardcoded type radios with a render target and loads the new Types module. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+32
to
+40
| var radios = types.map(function (type, i) { | ||
| // TODO(#15): escape type.name/type.id once users can define their own types | ||
| var inputId = 'type_' + type.id; | ||
| return '<input type="radio" name="type" class="hidden-checkbox" ' | ||
| + 'value="' + type.id + '" id="' + inputId + '"' + (i === 0 ? ' checked' : '') + '>' | ||
| + '<label tabindex="0" role="button" class="hidden-checkbox-label" for="' + inputId + '">' | ||
| + type.name + '</label>'; | ||
| }); | ||
| $screen.find('#type_options').html(radios.join('')); |
Comment on lines
160
to
167
| added_url = $screen.find('#added_url').prop('checked'), | ||
| added_screenshot = $screen.find('#added_screenshot').prop('checked'), | ||
| added_debug = $screen.find('#added_debug').prop('checked'), | ||
| type_field = $screen.find('#type_field input[name="type"]:checked').val(), | ||
| type_id = $screen.find('#type_field input[name="type"]:checked').val(), | ||
| selectedType = Types.find(issueTypes, type_id), | ||
| body = '', | ||
| url = 'https://github.com/' + repo + '/issues/new?title=' + encodeURIComponent(title); | ||
|
|
Comment on lines
+91
to
+102
| function getAll(callback) { | ||
| chrome.storage.local.get(['types'], function (result) { | ||
| if (result.types) { | ||
| callback(JSON.parse(result.types)); | ||
| return; | ||
| } | ||
| // first use: seed storage with the defaults | ||
| saveAll(DEFAULTS, function () { | ||
| callback(DEFAULTS); | ||
| }); | ||
| }); | ||
| } |
…pacing Review follow-ups on #14: - Rename the popup "Issue type:" label to "Type:" - Restore the inter-button gap on the type radios (lost when moving from static markup to generated radios) - Render radios via DOM APIs + .text() and normalise the element id, so a hand-edited chrome.storage value can't inject markup or break the DOM - Fall back to the first (default) type when none is checked, avoiding an untyped issue on an early submit (regression vs the old static radios) - Parse stored types defensively, reseeding defaults on corrupt/invalid data Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The defaults are the single source of truth in code, so every user on the defaults gets template/type improvements with no migration. Removes the seed-on-read write, the defensive parse, the unused saveAll helper, and — getAll now being synchronous — the readiness barrier in app.js (the type radios render before IssueForm.init, so no race to guard). Persistence for user-customised types is deferred to #15. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #14.
Abstracts the hardcoded issue "type" into a real data model. Each type maps to a GitHub native issue type, a set of default labels, and a body template.
What changed
Typesmodule (popup/modules/types.js) with seeded defaults (Bug / Enhancement / Other), backed bychrome.storage.local. Shape:{ id, name, githubType, labels[], bodyTemplate }. ExposesgetAll(seeds on first use),saveAll,find.app.html→ a#type_optionsrender target).&type=(native issue type, gracefully ignored where unsupported),&labels=(supports multiple), and the body template — replacing the inlineif (type=='bug')chain. Pure-redirect UX preserved.IssueForm.initnever restores/binds the async-rendered radios before they exist.Status
npm run build);types.jspassesnode --check.npm run build, reload the unpacked extension atchrome://extensions&type=Feature&labels=enhancement+ body templateFollow-ups (separate issues)
TODO(#15)left inapp.jsto HTML-escape user-supplied type names once they're editable🤖 Generated with Claude Code