Skip to content

✨ feat(editor): add compress/expand toggle for ph tags#4584

Open
riccio82 wants to merge 1 commit into
developfrom
feature/ph-tag-compress-expand
Open

✨ feat(editor): add compress/expand toggle for ph tags#4584
riccio82 wants to merge 1 commit into
developfrom
feature/ph-tag-compress-expand

Conversation

@riccio82
Copy link
Copy Markdown
Collaborator

@riccio82 riccio82 commented May 20, 2026

Summary

Add a global compress/expand toggle for ph tags in the translation editor. When compressed, ph tags show only their sequential index number; when expanded, they show the full equiv-text content. User preference is persisted per-user via localStorage.

Type

  • feat — new user-facing feature
  • fix — bug fix
  • refactor — restructure without behavior change
  • chore — build, deps, config, docs
  • perf — performance improvement
  • test — test coverage

Changes

File Change
public/js/components/segments/TagsCompressButton.js New toggle button component using Button (ICON_SMALL, OUTLINE)
public/js/components/segments/SegmentTargetToolbar.js Add TagsCompressButton as always-visible toolbar item
public/js/components/segments/TagEntity/TagEntity.component.js Add index counter display + compressed rendering + tooltip
public/js/components/segments/TagEntity/TagEntityLite.js Add index counter + compressed rendering (hooks-based)
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js Add ph index counter spans in transformTagsToHtml for closed segments
public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.js Add addIncrementalIndex + sourceTagMap cross-referencing for target ph indexing
public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.js Implement ph tag matching by decodedText with splice consumption
public/js/stores/CatToolStore.js Add phTagsCompressed state, localStorage persistence, body class toggle
public/js/actions/CatToolActions.js Add togglePhTagsCompressed action
public/js/constants/CatToolConstants.js Add TOGGLE_PH_TAGS_COMPRESSED constant
public/css/sass/components/segment/Tag.scss Add .index-counter styles, body.ph-tags-compressed rule, inline display fix
public/js/components/segments/TagsCompressButton.test.js Unit tests for toggle button
public/js/components/segments/TagEntity/TagEntityLite.test.js Unit tests for compressed/expanded rendering
public/js/stores/CatToolStore.test.js Unit tests for state, localStorage, body class toggle
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.phIndex.test.js Unit tests for ph index in transformTagsToHtml
public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.test.js Unit tests for incremental indexing + sourceTagMap
public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.test.js Unit tests for ph decodedText matching
public/js/components/segments/SimpleEditor.test.js Fix expected string for nbsp rendering
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.test.js Update expected HTML for new ph index spans

Testing

  • vendor/bin/phpunit --exclude-group=ExternalServices --no-coverage passes
  • ./vendor/bin/phpstan passes (0 errors, with baseline)
  • Manual testing performed (describe below)
  • New tests added for changed behavior
  • Regression tests added for bug fixes

Jest test suite: 45/45 suites pass, 260/260 tests pass (2 suites skipped — pre-existing socket tests).

Test Suites: 2 skipped, 45 passed, 45 of 47 total
Tests:       15 skipped, 260 passed, 275 total

AI Disclosure

  • No AI tools were used in this PR
  • AI tools were used — name the agent/tool below

Sisyphus (claude-opus-4.6) via OpenCode

Notes

  • Ph tags use universal sequential 1-based numbering (all ph tags, not just duplicates)
  • Toggle is global (all segments at once) but button is per-segment in SegmentTargetToolbar
  • Closed segments use CSS-only toggle (body.ph-tags-compressed class) — no re-render needed
  • localStorage key includes config.userMail for multi-user browser isolation
  • Known limitation: XLIFF2 ph tags without ids get independent sequential numbering in source and target

- add sequential 1-based numbering to all ph tags in both
  open (Draft.js) and closed (HTML-rendered) segments
- add TagsCompressButton in per-segment SegmentTargetToolbar
  to toggle compressed view globally
- compressed state shows only index number, hides tag content
- persist preference in localStorage keyed to config.userMail
- toggle body.ph-tags-compressed CSS class for zero-rerender
  closed segment switching
- add tooltip on compressed tags showing full equiv-text
- implement ph tag matching by decodedText with splice
  consumption in checkForMissingTag
- add sourceTagMap cross-referencing for target tag indexing
  in createNewEntitiesFromMap
- add unit tests for TagsCompressButton, TagEntityLite,
  CatToolStore, tagUtils phIndex, createNewEntitiesFromMap,
  and checkForMissingTag
Copilot AI review requested due to automatic review settings May 20, 2026 14:40
@github-actions
Copy link
Copy Markdown

🧪 Test-Guard Report

⚠️ WARNING — Test coverage has minor gaps — review recommended.

Coverage Analysis: ❌ FAIL

No changed source files found in coverage report (threshold: 80%)

📋 10 files: 10 ❌ fail
File Verdict Reason
public/js/actions/CatToolActions.js ❌ fail not in coverage report
public/js/components/segments/SegmentTargetToolbar.js ❌ fail not in coverage report
public/js/components/segments/TagEntity/TagEntity.component.js ❌ fail not in coverage report
public/js/components/segments/TagEntity/TagEntityLite.js ❌ fail not in coverage report
public/js/components/segments/TagsCompressButton.js ❌ fail not in coverage report
public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.js ❌ fail not in coverage report
public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.js ❌ fail not in coverage report
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js ❌ fail not in coverage report
public/js/constants/CatToolConstants.js ❌ fail not in coverage report
public/js/stores/CatToolStore.js ❌ fail not in coverage report

Test File Matching: ❌ FAIL

File matching: 6 pass, 1 warning, 3 fail

📋 10 files: 3 ❌ fail, 1 ⚠️ warning, 6 ✅ pass
File Verdict Reason
public/js/actions/CatToolActions.js ⚠️ warning Test file exists (public/js/actions/CatToolActions.test.js) but was not modified in this PR
public/js/components/segments/SegmentTargetToolbar.js ❌ fail No matching test file found
public/js/components/segments/TagEntity/TagEntity.component.js ❌ fail No matching test file found
public/js/components/segments/TagEntity/TagEntityLite.js ✅ pass Test file modified in PR: public/js/components/segments/TagEntity/TagEntityLite.test.js
public/js/components/segments/TagsCompressButton.js ✅ pass Test file modified in PR: public/js/components/segments/TagsCompressButton.test.js
public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.js ✅ pass Test file modified in PR: public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.test.js
public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.js ✅ pass Test file modified in PR: public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.test.js
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js ✅ pass Test file modified in PR: public/js/components/segments/utils/DraftMatecatUtils/tagUtils.test.js
public/js/constants/CatToolConstants.js ❌ fail No matching test file found
public/js/stores/CatToolStore.js ✅ pass Test file modified in PR: public/js/stores/CatToolStore.test.js

Per-File Evaluation: ⚠️ WARNING

Evaluated 10 files: 10 via AI (4 batches), 0 via shortcuts.

📋 10 files: 3 ⚠️ warning, 7 ✅ pass
File Verdict Reason
public/js/actions/CatToolActions.js ⚠️ warning New togglePhTagsCompressed action is dispatched but no direct tests shown.
public/js/components/segments/SegmentTargetToolbar.js ⚠️ warning TagsCompressButton component added to toolbar but no direct tests shown.
public/js/components/segments/TagEntity/TagEntity.component.js ⚠️ warning State and listener added for phTagsCompressed with conditional rendering; no direct tests but related TagEntityLite tests exist.
public/js/components/segments/TagEntity/TagEntityLite.js ✅ pass Tests cover compressed and uncompressed ph tag rendering and index display.
public/js/components/segments/TagsCompressButton.js ✅ pass Tests cover button rendering, toggling, store updates, and cleanup.
public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.js ✅ pass Tests cover ph tag matching by decodedText and non-ph by id and name, including duplicates.
public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.js ✅ pass Tests verify index assignment logic with and without sourceTagMap, including edge cases.
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js ✅ pass Tests verify ph tag index counter rendering and correct HTML structure.
public/js/constants/CatToolConstants.js ✅ pass Constant addition tested indirectly via store and UI tests.
public/js/stores/CatToolStore.js ✅ pass Store toggle behavior and localStorage integration fully tested with UI class changes.

Result: ⚠️ WARNING


Why this WARNING?

  • Coverage Analysis: None of the changed source files are present in the coverage report, indicating a coverage configuration issue (likely source filters exclude these files) → update coverage configuration to include these changed files.
  • Test File Matching: SegmentTargetToolbar.js, TagEntity.component.js, and CatToolConstants.js have no matching test files → add or link appropriate test files for these source files.
  • Per-File Evaluation: CatToolActions.js and SegmentTargetToolbar.js have new UI or action logic without direct tests shown → add direct tests covering the new togglePhTagsCompressed action and TagsCompressButton usage in the toolbar.
  • Per-File Evaluation: TagEntity.component.js has new state and conditional rendering related to phTagsCompressed but no direct tests; related TagEntityLite tests exist → consider adding direct tests for TagEntity.component.js or confirm coverage via TagEntityLite tests.

To resolve: Add missing test files and direct tests for SegmentTargetToolbar.js, TagEntity.component.js, and CatToolActions.js, and fix coverage configuration to include all changed source files.

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

Adds a global UI toggle in the translation editor to compress/expand XLIFF <ph> placeholders, showing either just a sequential index (compressed) or full equiv-text (expanded), persisting the preference per user via localStorage.

Changes:

  • Introduces phTagsCompressed state in CatToolStore with a dispatcher action/constant and localStorage persistence plus a body class toggle.
  • Adds a TagsCompressButton to the segment target toolbar and updates tag rendering components/utilities to display a sequential <ph> index.
  • Updates styling and adds/updates Jest tests to cover indexing, rendering, and store persistence behavior.

Reviewed changes

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

Show a summary per file
File Description
public/js/stores/CatToolStore.js Adds phTagsCompressed state, persistence, and body class toggle + store event.
public/js/stores/CatToolStore.test.js Tests initialization, toggling, persistence keying by userMail, and body class behavior.
public/js/constants/CatToolConstants.js Adds TOGGLE_PH_TAGS_COMPRESSED constant.
public/js/actions/CatToolActions.js Adds togglePhTagsCompressed action dispatch.
public/js/components/segments/TagsCompressButton.js New toolbar toggle button component wired to store/action.
public/js/components/segments/TagsCompressButton.test.js Unit tests for toggle button behavior and store subscription.
public/js/components/segments/SegmentTargetToolbar.js Adds TagsCompressButton as an always-visible toolbar item.
public/js/components/segments/TagEntity/TagEntity.component.js Adds compressed rendering logic and tooltip behavior for <ph> entities.
public/js/components/segments/TagEntity/TagEntityLite.js Adds compressed rendering logic for the lightweight tag decorator.
public/js/components/segments/TagEntity/TagEntityLite.test.js Unit tests for compressed/expanded rendering and index counter display.
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js Adds <ph> index spans and wraps tag text in span[data-text="true"] for CSS toggling.
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.test.js Updates expected HTML output for new <ph> index markup.
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.phIndex.test.js New tests for <ph> indexing behavior in transformTagsToHtml.
public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.js Adds incremental indexing for <ph> entities and optional source map cross-referencing.
public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.test.js New tests for incremental indexing and source tag map behavior.
public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.js Adjusts missing-tag matching so <ph> matches by decodedText with one-by-one consumption.
public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.test.js New tests for <ph> decodedText matching and duplicate consumption behavior.
public/js/components/segments/SimpleEditor.test.js Updates expected rendered text output due to inserted <ph> indices.
public/css/sass/components/segment/Tag.scss Adds .index-counter styles and compressed display rules (including body.ph-tags-compressed).

Comment thread public/js/components/segments/TagsCompressButton.js
Comment thread public/js/stores/CatToolStore.test.js
@github-actions
Copy link
Copy Markdown

🧪 Test-Guard Report

⚠️ WARNING — Test coverage has minor gaps — review recommended.

Coverage Analysis: ❌ FAIL

No changed source files found in coverage report (threshold: 80%)

📋 10 files: 10 ❌ fail
File Verdict Reason
public/js/actions/CatToolActions.js ❌ fail not in coverage report
public/js/components/segments/SegmentTargetToolbar.js ❌ fail not in coverage report
public/js/components/segments/TagEntity/TagEntity.component.js ❌ fail not in coverage report
public/js/components/segments/TagEntity/TagEntityLite.js ❌ fail not in coverage report
public/js/components/segments/TagsCompressButton.js ❌ fail not in coverage report
public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.js ❌ fail not in coverage report
public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.js ❌ fail not in coverage report
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js ❌ fail not in coverage report
public/js/constants/CatToolConstants.js ❌ fail not in coverage report
public/js/stores/CatToolStore.js ❌ fail not in coverage report

Test File Matching: ❌ FAIL

File matching: 6 pass, 1 warning, 3 fail

📋 10 files: 3 ❌ fail, 1 ⚠️ warning, 6 ✅ pass
File Verdict Reason
public/js/actions/CatToolActions.js ⚠️ warning Test file exists (public/js/actions/CatToolActions.test.js) but was not modified in this PR
public/js/components/segments/SegmentTargetToolbar.js ❌ fail No matching test file found
public/js/components/segments/TagEntity/TagEntity.component.js ❌ fail No matching test file found
public/js/components/segments/TagEntity/TagEntityLite.js ✅ pass Test file modified in PR: public/js/components/segments/TagEntity/TagEntityLite.test.js
public/js/components/segments/TagsCompressButton.js ✅ pass Test file modified in PR: public/js/components/segments/TagsCompressButton.test.js
public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.js ✅ pass Test file modified in PR: public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.test.js
public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.js ✅ pass Test file modified in PR: public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.test.js
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js ✅ pass Test file modified in PR: public/js/components/segments/utils/DraftMatecatUtils/tagUtils.test.js
public/js/constants/CatToolConstants.js ❌ fail No matching test file found
public/js/stores/CatToolStore.js ✅ pass Test file modified in PR: public/js/stores/CatToolStore.test.js

Per-File Evaluation: ⚠️ WARNING

Evaluated 10 files: 10 via AI (4 batches), 0 via shortcuts.

📋 10 files: 1 ⚠️ warning, 9 ✅ pass
File Verdict Reason
public/js/actions/CatToolActions.js ⚠️ warning New togglePhTagsCompressed action is dispatched but no direct tests shown.
public/js/components/segments/SegmentTargetToolbar.js ✅ pass TagsCompressButton component added; tested indirectly via TagsCompressButton tests.
public/js/components/segments/TagEntity/TagEntity.component.js ✅ pass State and event listener added for phTagsCompressed; behavior tested in TagEntityLite tests.
public/js/components/segments/TagEntity/TagEntityLite.js ✅ pass Tests cover compressed state, index display, and conditional children rendering.
public/js/components/segments/TagsCompressButton.js ✅ pass Tests cover toggle behavior, UI state, and event listener lifecycle.
public/js/components/segments/utils/DraftMatecatUtils/TagMenu/checkForMissingTag.js ✅ pass Tests cover ph tag matching by decodedText and non-ph by id, including duplicates.
public/js/components/segments/utils/DraftMatecatUtils/createNewEntitiesFromMap.js ✅ pass Tests verify index assignment with and without sourceTagMap, including edge cases.
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js ✅ pass Tests verify ph tag index counter rendering and HTML structure.
public/js/constants/CatToolConstants.js ✅ pass Constants addition tested indirectly via store and UI tests.
public/js/stores/CatToolStore.js ✅ pass Store toggle behavior and localStorage integration fully tested.

Result: ⚠️ WARNING


Why this WARNING?

  • Coverage Analysis: None of the changed source files are included in the coverage report, indicating a coverage configuration issue (likely source filters exclude these files) → update coverage config to include these changed files.
  • Test File Matching: No test files found for SegmentTargetToolbar.js, TagEntity.component.js, and CatToolConstants.js → add or link appropriate test files for these source files.
  • Per-File Evaluation: The new togglePhTagsCompressed action in CatToolActions.js is dispatched but lacks direct tests → add direct tests for this new action to ensure coverage.
  • Per-File Evaluation: SegmentTargetToolbar.js and TagEntity.component.js changes are tested only indirectly via other components → no action needed if indirect test coverage is sufficient.

To resolve: fix coverage configuration to include all changed source files and add missing direct tests for CatToolActions.js togglePhTagsCompressed action and missing test files for SegmentTargetToolbar.js, TagEntity.component.js, and CatToolConstants.js.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants