Skip to content

fix: improve responsive behavior of AssetMapper and EntryMapper table…#1118

Merged
vikrantraut-cstk merged 5 commits into
devfrom
bugfix/delta
Jul 21, 2026
Merged

fix: improve responsive behavior of AssetMapper and EntryMapper table…#1118
vikrantraut-cstk merged 5 commits into
devfrom
bugfix/delta

Conversation

@yashin4112

Copy link
Copy Markdown
Contributor

🔗 Jira Ticket

CMG-1044


📋 PR Type

  • ✨ Feature
  • 🐛 Bug Fix
  • 🔥 Hotfix
  • ♻️ Refactor
  • 🧹 Chore / Dependency Update
  • 📝 Documentation

📝 Description

What changed?

  • Made the Entry Mapper and Asset Mapper tables (Map Entry step) fully responsive so the pagination bar and Save footer stay visible and reachable at any browser zoom level.
  • Reworked the height chain into a bounded flex layout: .entry-asset-mapper is now pinned to the real step-content area (calc(100vh - 246px), derived from the stepper's own .stepContent height minus its fixed header padding), so the subtree is self-bounding instead of growing to content height.
  • The table body height is now measured off the bounded outer box (minus the toggle, search row, pagination bar and Save footer) and fed into InfiniteScrollTable's tableHeight prop via a ResizeObserver, so react-window's virtual viewport matches the visible area and its native scroll works. Anchored on the outer box (never on .Table/.Table__body) to avoid a measurement feedback loop.
  • Replaced the fixed calc(100vh - Npx) / hardcoded tableHeight={400} sizing with flex + measured height; the table body scrolls internally while pagination + Save stay pinned below.
  • Added the entry-asset-mapper class to the Entry/Asset toggle wrapper (it had none, so its flex layout rules never applied) and removed dead .asset-mapper-container .Table fixed-height rules.

Why?

On zoom (110%+), the fixed-pixel/100vh-based table height didn't shrink with the effective viewport, so the pagination bar slid below the Save footer and the Save button became unreachable — the UI locked with no way to scroll to it. This makes the layout distribute height correctly and keep the controls in view at 100%, 110% and beyond.


🧩 Affected Areas

  • api — Node.js backend
  • ui — React frontend
  • upload-api — Upload API server
  • docker / docker-compose
  • CI / GitHub Actions workflows
  • Environment variables / config
  • Other:

🧪 How to Test

  1. Open a delta-iteration project and go to the Map Entry step (Entries / Assets tabs).
  2. Select a content type with enough entries to paginate.
  3. Set browser zoom to 100%, then 110% and higher.

Expected result: At every zoom level the table body scrolls internally, and the pagination bar and Save button stay visible and reachable at the bottom (no overflow, no locked UI). Repeat on the Assets tab.


📸 Screenshots / Recordings

Before After

🔗 Related PRs / Dependencies


✅ Author Checklist

  • Branch follows naming convention: feature/, bugfix/, or hotfix/ + 5–30 lowercase chars
  • Jira ticket linked above
  • Self-reviewed the diff — no debug logs, commented-out code, or TODOs left in
  • .env / example.env updated if new environment variables were added — N/A (no env changes)
  • No sensitive credentials or secrets committed
  • Existing tests pass locally (npm test)
  • New tests written (or not applicable — explain why) — N/A, CSS/layout-only change with no unit-testable logic
  • README.md / docs updated if behaviour changed — N/A
  • Talisman pre-push scan passes (no secrets flagged)

👀 Reviewer Notes

The table body height is driven by a measured JS value (tableHeight prop), not CSS, because InfiniteScrollTable/react-window sizes its virtual scroll viewport from that number. The measurement deliberately anchors on the bounded outer box (.entry-asset-mapper) and never reads .Table/.Table__body — reading those creates a runaway feedback loop (we saw tableHeight blow up to ~9966px during development). Please sanity-check the calc(100vh - 246px) reserve if the surrounding stepper chrome changes.


Migration v2 · Docs · Issues

…s to ensure pagination and footer remain visible on zoom
@yashin4112
yashin4112 requested a review from a team as a code owner July 21, 2026 07:23
@github-actions

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 1 0 10 ✅ Passed
🟠 High Severity 7 384 25 ✅ Passed
🟡 Medium Severity 0 1 500 ✅ Passed
🔵 Low Severity 1 0 1000 ✅ Passed

⏱️ SLA Breach Summary

⚠️ Warning: The following vulnerabilities have exceeded their SLA thresholds (days since publication).

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 1 0 15 / 30 days ❌ Failed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

🔴 Critical Severity - SLA Breached Issues (with fixes)

Showing 1 issue(s) that have exceeded the 15-day SLA threshold:

  1. Resources Downloaded over Insecure Protocol
    • ID: SNYK-JS-ESBUILD-17750822
    • Package: esbuild@0.27.3
    • Published: 19 days ago (SLA: 15 days)
    • CVSS Score: 9.2

ℹ️ Vulnerabilities Without Available Fixes (Informational Only)

The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:

  • Critical without fixes: 0
  • High without fixes: 384
  • Medium without fixes: 1
  • Low without fixes: 0

❌ BUILD FAILED - Security checks failed

Please review and fix the security vulnerabilities before merging.

@github-actions

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 0 10 ✅ Passed
🟠 High Severity 7 384 25 ✅ Passed
🟡 Medium Severity 1 2 500 ✅ Passed
🔵 Low Severity 0 0 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

ℹ️ Vulnerabilities Without Available Fixes (Informational Only)

The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:

  • Critical without fixes: 0
  • High without fixes: 384
  • Medium without fixes: 2
  • Low without fixes: 0

✅ BUILD PASSED - All security checks passed

Copilot AI left a comment

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 0 10 ✅ Passed
🟠 High Severity 7 384 25 ✅ Passed
🟡 Medium Severity 7 8 500 ✅ Passed
🔵 Low Severity 0 0 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

ℹ️ Vulnerabilities Without Available Fixes (Informational Only)

The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:

  • Critical without fixes: 0
  • High without fixes: 384
  • Medium without fixes: 8
  • Low without fixes: 0

✅ BUILD PASSED - All security checks passed

@umesh-more-cstk umesh-more-cstk left a comment

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.

Review — CMG-1044 responsive AssetMapper/EntryMapper tables

Solid, well-documented fix for a genuinely awkward layout problem — the extensive comments explaining the feedback-loop avoidance and the calc(100vh - 246px) reserve are appreciated and made this reviewable. The bounded-flex + measured-tableHeight approach is sound, and observing the fixed-size outer box (not .Table/.Table__body) correctly avoids the runaway loop. Only one mapper mounts at a time (ternary in entryAssetMapper.tsx), so the global document.querySelector reads don't cross-match between the two.

Verdict: Comment — no blockers. Two things I'd like addressed before merge (both inline): extract the duplicated measurement effect into a shared hook, and confirm the entry-table column-width change doesn't trade the vertical overflow for a horizontal one at the same 110%+ zoom this targets.

Please address before merge

  1. Duplicated measurement effect (entryMapper.tsxassetMapper.tsx) — inline.
  2. equalWidthColumns flip + fixed column widths — verify no horizontal overflow — inline.

Non-blocking nits

  • box?.clientHeight ?? … doesn't catch 0; avail > 80 leaves a stale height at extreme zoom (inline).
  • Magic numbers 246/520/64/65/56 are duplicated across both files and the SCSS. The initial state uses innerHeight - 520 but the box fallback uses innerHeight - 246 — worth a shared named constant, and the two seeds reconciled.
  • The window.addEventListener('resize', measure) is largely redundant with the ResizeObserver on a 100vh-based box (both fire on zoom). Harmless, just noise.
  • index.scss: the removed .Table rule leaves a double blank line, and the file has no trailing newline (lint should catch both).

Comment thread ui/src/components/ContentMapper/entryMapper.tsx Outdated
Comment thread ui/src/components/ContentMapper/entryMapper.tsx
Comment thread ui/src/components/ContentMapper/entryMapper.tsx Outdated
Comment thread ui/src/components/ContentMapper/entryMapper.tsx Outdated
@github-actions

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 0 10 ✅ Passed
🟠 High Severity 7 384 25 ✅ Passed
🟡 Medium Severity 10 11 500 ✅ Passed
🔵 Low Severity 0 0 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

ℹ️ Vulnerabilities Without Available Fixes (Informational Only)

The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:

  • Critical without fixes: 0
  • High without fixes: 384
  • Medium without fixes: 11
  • Low without fixes: 0

✅ BUILD PASSED - All security checks passed

@umesh-more-cstk umesh-more-cstk left a comment

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.

Review: fix: improve responsive behavior of AssetMapper and EntryMapper tables (CMG-1044)

Verdict: COMMENT (non-gating). This is a well-engineered layout fix. I traced the full flex chain at the head commit and it holds together: .entry-asset-mapper (bounded to calc(100vh - 246px), overflow:hidden) → .step-container (flex:1) → .table-container (flex:1 1 auto, align-items/content:stretch) → .content-types-fields-wrapper (flex col) → .entry-table-wrapper (flex:1 1 auto) → .entry-mapper-table.Table + .mapper-footer. The measured-height approach (feed react-window's tableHeight off the bounded outer box, never off .Table/.Table__body) is the right way to avoid the feedback loop, and the effect cleanup (ResizeObserver disconnect + resize listener removal) is correct.

I could not find a blocking issue. One thing I checked and disproved: I suspected the reserve in useMeasuredTableHeight omits the .locale-select-inline row and would clip the footer on multi-locale projects — but that row is position:absolute (overlaid on .TablePanel, which reserves space via min-height:64px; padding-right:272px), so it does not consume flex height. No bug there.

Non-blocking (inline):

  • nituseMeasuredTableHeight.ts:44: initial tableHeight guess is unclamped and inconsistent with the hook's own box model.
  • questionentryMapper.tsx:656: entry columns switched from equal-width to fixed non-shrinking widths (a horizontal-layout change bundled with the vertical fix) — please confirm no horizontal overflow at the min supported width.

Out-of-diff heads-ups (not blocking):

  • Tests / ResizeObserver: new ResizeObserver(...) is called unconditionally, but ui/tests/setup.ts does not polyfill it. The only ContentMapper tests today are *.utils.test.ts (pure functions) — no test mounts EntryMapper/AssetMapper — so CI is unaffected now. If a component render test is ever added it will throw ReferenceError: ResizeObserver is not defined under jsdom; worth a stub in tests/setup.ts preemptively.
  • Description vs diff: the PR text says it "Added the entry-asset-mapper class to the Entry/Asset toggle wrapper (it had none)". In the code, .entry-asset-mapper is already on the outer wrapper in entryAssetMapper.tsx (.mapper-view-toggle is the toggle), and that file is not part of this diff — the description likely reflects an earlier commit on the branch. No code impact.

Verified good: dev-only console.warn on missing selectors instead of silently falling back to magic constants (directly addresses this repo's "DOM reads by hard-coded class names that silently fall back to magic numbers" concern); DOM reads scoped to wrapperRef rather than global document; the empty-state height rule (.Table:has(.EmptyState), 4-class specificity) still wins over the new .entry-mapper-table .Table { height:auto }, so the empty state is preserved; and the entry/asset .Table__body rules don't cross-contaminate. Scope is clean — UI-only, matches the stated Affected Area, no lockfile/dependency churn.

Comment thread ui/src/components/ContentMapper/useMeasuredTableHeight.ts Outdated
Comment thread ui/src/components/ContentMapper/entryMapper.tsx
…ss and update initial table height calculation
@github-actions

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 0 10 ✅ Passed
🟠 High Severity 7 384 25 ✅ Passed
🟡 Medium Severity 10 11 500 ✅ Passed
🔵 Low Severity 0 0 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

ℹ️ Vulnerabilities Without Available Fixes (Informational Only)

The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:

  • Critical without fixes: 0
  • High without fixes: 384
  • Medium without fixes: 11
  • Low without fixes: 0

✅ BUILD PASSED - All security checks passed

@vikrantraut-cstk
vikrantraut-cstk merged commit 0c0ae67 into dev Jul 21, 2026
9 checks passed
@vikrantraut-cstk
vikrantraut-cstk deleted the bugfix/delta branch July 21, 2026 13:31
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.

4 participants