Add Dynamic View for unified cross-type mapping visualization#288
Merged
Conversation
added 10 commits
April 29, 2026 16:12
Introduce a new "Dynamic View" in the Mapping page that displays the full reference document alongside all directly mapped work items of every type in a unified two-column layout, providing a cross-type overview of specification coverage. API - New dynamic-view endpoint: - Add `ApiDynamicViewMapping` resource at `/mapping/api/dynamic-view` - Returns the full specification text plus all direct work items (SW Requirements, Test Specifications, Test Cases, Justifications, Documents) grouped and deduplicated by work item ID - Each work item group carries a list of snippet mappings with section, offset, coverage, match flag, and relation_id - SW Requirement snippets include children (nested SRs, TSs, TCs) when the snippet matches the specification - Document snippets include nested Documents when matching - Add comprehensive unit tests in `test_api_dynamic_view_mapping.py` covering auth, error handling, response structure, deduplication, and children Frontend - Dynamic View table component: - Add `MappingDynamicViewTable` component with two-column layout: reference document on the left, grouped work items on the right - Left column highlights covered sections in blue with a left border; uncovered sections appear in lighter color - Clicking a work item card selects it and narrows the reference document to show only the relevant mapped snippets - Add "Show full document" button to deselect and restore the full view - Show snippet count badge on each work item card - Support nested traceability: indirect Test Specifications, Test Cases, SW Requirements, and Documents rendered indented under their parent - Each card includes kebab menu, comments button, status label, version, and completion label Frontend - Snippets management modal: - Add `MappingSnippetsModal` component for viewing, adding, and removing snippet mappings for a work item from the Dynamic View - "Manage Snippets" button available on each work item card for logged-in users with write permissions - Allows selecting text from the reference document to create new snippet mappings Frontend - View selector and default view updates: - Add "Dynamic View" option to `MappingViewSelect` dropdown - Add `_DV` constant for `'dynamic-view'` - Add "Justifications Only" and "Dynamic View" radio buttons to the API form default view settings - Update `Mapping.tsx` to fetch from the dynamic-view endpoint when selected and pass data to the new table component - Update `MappingPageSection` to conditionally render `MappingDynamicViewTable` vs `MappingListingTable` based on selected view Frontend - Fix kebab menu click propagation in Dynamic View: - Add `e.stopPropagation()` to `onToggleClick` and `onSelect` in all 5 kebab menu components (SwRequirement, TestSpecification, TestCase, Justification, Document) to prevent the click from bubbling up to the parent Card and triggering the snippet selection behavior Frontend - CSS color refinements: - Update `.code-block-bg-green` to `#dbeafe` (blue tint matching Dynamic View) - Update `.code-block-bg-gold` to `#fef3c7` - Update `.code-block-bg-gray` to `#e5e7eb` Cypress E2E tests: - Add `mapping_dynamic_view.cy.js` with tests for switching to the Dynamic View, verifying mapped work items display, card selection/deselection, and multiple work item types rendering Documentation: - Add `mapping_views.rst` describing all mapping views in detail - Add reference to the new doc in `key_concepts.rst` and `index.rst` Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
…yout
Replace the single-table layout in MappingDynamicViewTable with a split-panel
flex layout where the Reference Document and Work Items sections scroll
independently, and the page can scroll to dismiss the header controls while
keeping the section titles always visible.
Mapping.tsx:
- Disable sticky PageGroup behavior when Dynamic View is selected, allowing
the page header (breadcrumb, view selector, indirect switches) to scroll
away and give more vertical space to the content panels.
MappingDynamicViewTable.tsx:
Layout replacement (table → flex panels):
- Remove PatternFly Table/Thead/Tbody/Tr/Td/Th imports and PageSection wrapper
- Replace the single-row two-column table with a flex container (height: 100vh)
where each side is an independently scrollable div (overflow-y: auto)
- Add sticky column headers ("REFERENCE DOCUMENT" / "WORK ITEMS") inside each
panel that remain pinned at the top while the panel content scrolls
Scroll capping (prevent section titles from disappearing):
- Compute the maximum allowed scrollTop of the main content container so that
the panels' top edge never scrolls above the viewport
- Intercept wheel events (passive: false) to prevent further scroll when at the
maximum, and clamp scrollTop in the scroll handler as a fallback
- Lazy-compute maxScroll via requestAnimationFrame to ensure layout is stable
Work item selection scroll reset:
- When a work item is clicked (selected), scroll both panels (left and right)
back to the top and reset the page scroll to 0, ensuring the section titles
and selected item are immediately visible
- Add specPanelRef for the left (reference document) panel to enable this
Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
…ondition
Fix race condition in MappingSectionMenuKebab causing empty modalSection
The kebab dropdown menu computed snippetSection and snippetOffset inside a
useEffect that fires asynchronously after paint. When Cypress (or a fast user)
clicked a dropdown item before the effect propagated, the modal opened with an
empty modalSection, causing the form validation to silently reject the
submission and no work item to be created.
- Moved getSection()/getOffset() computation from useEffect into the
onToggleClick handler so React batches the state updates into a single
re-render, ensuring dropdown items always have the correct snippetSection
from their first appearance
- Kept the useEffect only for the close case (resetting snippetOffset to -1)
Fix dynamic view Cypress tests for data conflicts and timing
Tests 3, 5, and 6 all reused sr_data.first to create a sw-requirement.
Since delete_work_item only removes the mapping (not the entity), subsequent
tests hit a 409 CONFLICT when trying to create the same sw-requirement again.
- Test 5 ("card selection highlights snippets") now uses sr_data.second
- Test 6 ("multiple work item types") now uses sr_data.third, including
its title assertion
- Added cy.wait(const_data.long_wait) after every cy.delete_work_item() call
to ensure backend cleanup completes before the next test runs
- Added scrollIntoView() and { force: true } on the "Show full document"
button click, which was covered by the sticky navigation bar
Increase .find('.pf-v5-c-card') timeout in Cypress custom commands
The .find() calls in custom commands inherited Cypress's default 4s timeout
instead of the 15s timeout set on the parent cy.get(). After several
create/delete cycles the backend becomes slower, causing legitimate cards to
take longer to appear.
- Propagated { timeout: 15000 } to all .find('.pf-v5-c-card') calls in
check_work_item, delete_work_item, assign_work_item,
assign_existing_work_item, and edit_work_item
- Added tableOptions constant to delete_work_item, assign_work_item,
assign_existing_work_item, and edit_work_item (was only in check_work_item)
- Removed leftover console.log debug statements from delete_work_item and
edit_work_item
Prettier formatting pass
- Minor trailing comma and line-break formatting fixes applied by Prettier to
cypress.config.ts, test_failing_tmt_test_case.cy.js,
test_passing_tmt_test_case.cy.js, user_files.cy.js, commands.js, and
TestRunConfigForm.tsx
New test file: mapping_nested_documents.cy.js
- Added e2e test for nested document mapping: creates a top-level document,
edits it, maps a nested document under it, edits the nested document, then
cleans up both in reverse order
Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
…lected text Add the ability for users to select a snippet of the reference document in the Dynamic View left panel and right-click to see which work items are mapped to that specific text region. This enables quick navigation from any part of the specification to its associated work items. The matching is offset-aware, meaning it uses the character position of the selected text within the specification string rather than a simple string match. This correctly handles repeated substrings (e.g. "if" in a C file) by only showing work items whose snippet offsets actually overlap with the selected range. - Add `specContentPreRef` ref and `contextMenu` state to track the custom right-click menu position and matching work items - Add `handleSpecContextMenu` handler that computes the exact character offset range of the user's text selection within the specification using the DOM Range API, then finds all work item groups with snippets overlapping that range - Each `<pre>` element in `renderSpecificationContent()` now carries a `data-spec-base-offset` attribute (0 for full document view, or `firstStart` when showing a focused subset for a selected work item) so the offset calculation is correct in all rendering modes - Render a fixed-position context menu overlay showing matched work items grouped by type (SW Requirement, Test Specification, Test Case, Justification, Document) with their icon, id, and truncated title - Clicking a context menu item selects the corresponding work item card, highlighting its snippets in the specification panel - Context menu auto-dismisses on click outside, Escape key, or panel scroll to avoid stale menus - Work item deduplication ensures each group appears at most once even if multiple snippets from the same work item overlap the selection - Prettier formatting applied to TestRunConfigForm.tsx (cosmetic only) Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
Sort the work items displayed in the right-click context menu of the reference document panel so they appear in a predictable, easy-to-scan order rather than the arbitrary order they happen to be found during the snippet overlap search. - Sort matching work items first by type (grouping all SW Requirements, Test Cases, etc. together) and then alphabetically by label within each type category - Uses localeCompare for consistent locale-aware string ordering Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
The local Prettier version (3.2.5) was formatting JSX differently from the CI version (3.8.3), causing the pipeline prettier check to fail. Upgrading the local version ensures consistent formatting across local development and CI. - Upgrade prettier from 3.2.5 to ^3.8.3 in app/package.json - Re-run prettier on TestRunConfigForm.tsx to fix two formatting discrepancies where 3.2.5 collapsed multi-line JSX map callbacks into single lines, while 3.8.3 keeps them expanded across multiple lines (FormSelectOption inside sshKeys and testingFarmComposes maps) Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
Signed-off-by: Luigi Pellecchia <lpellecc@redhat.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.
Introduce a new "Dynamic View" in the Mapping page that displays the full reference document alongside all directly mapped work items of every type in a unified two-column layout, providing a cross-type overview of specification coverage.
API - New dynamic-view endpoint:
ApiDynamicViewMappingresource at/mapping/api/dynamic-viewtest_api_dynamic_view_mapping.pycovering auth, error handling, response structure, deduplication, and childrenFrontend - Dynamic View table component:
MappingDynamicViewTablecomponent with two-column layout: reference document on the left, grouped work items on the rightFrontend - Snippets management modal:
MappingSnippetsModalcomponent for viewing, adding, and removing snippet mappings for a work item from the Dynamic ViewFrontend - View selector and default view updates:
MappingViewSelectdropdown_DVconstant for'dynamic-view'Mapping.tsxto fetch from the dynamic-view endpoint when selected and pass data to the new table componentMappingPageSectionto conditionally renderMappingDynamicViewTablevsMappingListingTablebased on selected viewFrontend - Fix kebab menu click propagation in Dynamic View:
e.stopPropagation()toonToggleClickandonSelectin all 5 kebab menu components (SwRequirement, TestSpecification, TestCase, Justification, Document) to prevent the click from bubbling up to the parent Card and triggering the snippet selection behaviorFrontend - CSS color refinements:
.code-block-bg-greento#dbeafe(blue tint matching Dynamic View).code-block-bg-goldto#fef3c7.code-block-bg-grayto#e5e7ebCypress E2E tests:
mapping_dynamic_view.cy.jswith tests for switching to the Dynamic View, verifying mapped work items display, card selection/deselection, and multiple work item types renderingDocumentation:
mapping_views.rstdescribing all mapping views in detailkey_concepts.rstandindex.rstRefers to #286