Loading workspace insights... Statistics interval
7 days30 daysLatest CI Pipeline Executions
6f9b2253 fix[smartling]: ENG-12342 fix 'Clear translation metadata' button not working (#4544)
## Problem
The **Clear translation metadata** content action in the Smartling
plugin was silently broken. Clicking the button and confirming the
dialog appeared to succeed (snackbar showed \"Translation metadata
cleared.\"), but the translation fields (`translationStatus`,
`translationJobId`, etc.) were never actually removed from the content.
## Root Cause
`content.meta` is a **MobX observable Map**. The button's `onClick`
handler cloned it using `fastClone`:
```ts
const updatedMeta = fastClone(content.meta);
// fastClone = (obj) => JSON.parse(JSON.stringify(obj))
```
`JSON.stringify` on a MobX observable Map serialises it as `{}` (an
empty plain object) ā Map entries are not picked up by the default JSON
serialiser. As a result:
- `updatedMeta` was always `{}`
- The subsequent `delete updatedMeta.translationStatus` (etc.) calls
were no-ops on a field that didn't exist
- `updateLatestDraft` was called with `meta: {}`, either leaving the
translation fields untouched (if the API merges) or wiping *all*
metadata (if the API replaces)
## Fix
Replace `fastClone(content.meta)` with `{ ...content.meta?.toJS() }`.
`.toJS()` is the correct MobX API for converting an observable Map to a
plain JS object. The spread then creates a regular mutable copy, and the
`delete` operations work as intended.
```ts
// Before
const updatedMeta = fastClone(content.meta);
// After
const updatedMeta = { ...content.meta?.toJS() };
```
This is exactly the same pattern already used in the backend's
`cleanupOrphanedTranslationMetadata` helper
([`smartling.ts:465`](../blob/main/plugins/smartling/src/smartling.ts#L465)),
confirming it's the correct approach.
## Test Plan
- [ ] Open a content entry that has stale translation metadata (e.g.
`translationStatus` = `completed` or `translationJobId` set, not in
`pending`/`local`)
- [ ] Open the content actions menu ā confirm **Clear translation
metadata** is visible
- [ ] Click it and confirm the dialog
- [ ] Verify the snackbar shows \"Translation metadata cleared.\"
- [ ] Reload the content entry and confirm all 7 translation fields
(`translationStatus`, `translationJobId`, `translationBy`,
`translationRevision`, `translationRevisionLatest`, `translationBatch`,
`translationRequested`) are gone from the meta
- [ ] Confirm the **Clear translation metadata** button no longer
appears for that entry
š¤ Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Scoped UI fix for one content action and a patch version bump; no auth
or broad meta-write path changes beyond correcting this handler.
>
> **Overview**
> Fixes the **Clear translation metadata** content action so it actually
removes Smartling fields instead of showing success while leaving
metadata unchanged.
>
> The handler no longer clones `content.meta` with `fastClone` /
`JSON.stringify`, which produced `{}` for MobX observable Maps. It now
builds a plain object via `content.meta.toJS()` (with a fallback),
deletes the seven translation keys, and persists with
`updateLatestDraft`. The confirm dialog call matches the updated API
shape.
>
> Plugin version is bumped to **0.1.2** in `package.json` and the
lockfile.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
035fad6056df312bf5ec4df7663dcfb53422c307. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Sanyam Kamat <1625114+sanyamkamat@users.noreply.github.com> 57a307ee fix[smartling]: ENG-12342 fix 'Clear translation metadata' button not working (#4544)
## Problem
The **Clear translation metadata** content action in the Smartling
plugin was silently broken. Clicking the button and confirming the
dialog appeared to succeed (snackbar showed \"Translation metadata
cleared.\"), but the translation fields (`translationStatus`,
`translationJobId`, etc.) were never actually removed from the content.
## Root Cause
`content.meta` is a **MobX observable Map**. The button's `onClick`
handler cloned it using `fastClone`:
```ts
const updatedMeta = fastClone(content.meta);
// fastClone = (obj) => JSON.parse(JSON.stringify(obj))
```
`JSON.stringify` on a MobX observable Map serialises it as `{}` (an
empty plain object) ā Map entries are not picked up by the default JSON
serialiser. As a result:
- `updatedMeta` was always `{}`
- The subsequent `delete updatedMeta.translationStatus` (etc.) calls
were no-ops on a field that didn't exist
- `updateLatestDraft` was called with `meta: {}`, either leaving the
translation fields untouched (if the API merges) or wiping *all*
metadata (if the API replaces)
## Fix
Replace `fastClone(content.meta)` with `{ ...content.meta?.toJS() }`.
`.toJS()` is the correct MobX API for converting an observable Map to a
plain JS object. The spread then creates a regular mutable copy, and the
`delete` operations work as intended.
```ts
// Before
const updatedMeta = fastClone(content.meta);
// After
const updatedMeta = { ...content.meta?.toJS() };
```
This is exactly the same pattern already used in the backend's
`cleanupOrphanedTranslationMetadata` helper
([`smartling.ts:465`](../blob/main/plugins/smartling/src/smartling.ts#L465)),
confirming it's the correct approach.
## Test Plan
- [ ] Open a content entry that has stale translation metadata (e.g.
`translationStatus` = `completed` or `translationJobId` set, not in
`pending`/`local`)
- [ ] Open the content actions menu ā confirm **Clear translation
metadata** is visible
- [ ] Click it and confirm the dialog
- [ ] Verify the snackbar shows \"Translation metadata cleared.\"
- [ ] Reload the content entry and confirm all 7 translation fields
(`translationStatus`, `translationJobId`, `translationBy`,
`translationRevision`, `translationRevisionLatest`, `translationBatch`,
`translationRequested`) are gone from the meta
- [ ] Confirm the **Clear translation metadata** button no longer
appears for that entry
š¤ Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Scoped UI fix for one content action and a patch version bump; no auth
or broad meta-write path changes beyond correcting this handler.
>
> **Overview**
> Fixes the **Clear translation metadata** content action so it actually
removes Smartling fields instead of showing success while leaving
metadata unchanged.
>
> The handler no longer clones `content.meta` with `fastClone` /
`JSON.stringify`, which produced `{}` for MobX observable Maps. It now
builds a plain object via `content.meta.toJS()` (with a fallback),
deletes the seven translation keys, and persists with
`updateLatestDraft`. The confirm dialog call matches the updated API
shape.
>
> Plugin version is bumped to **0.1.2** in `package.json` and the
lockfile.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
035fad6056df312bf5ec4df7663dcfb53422c307. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Sanyam Kamat <1625114+sanyamkamat@users.noreply.github.com> 6f9b2253 fix[smartling]: ENG-12342 fix 'Clear translation metadata' button not working (#4544)
## Problem
The **Clear translation metadata** content action in the Smartling
plugin was silently broken. Clicking the button and confirming the
dialog appeared to succeed (snackbar showed \"Translation metadata
cleared.\"), but the translation fields (`translationStatus`,
`translationJobId`, etc.) were never actually removed from the content.
## Root Cause
`content.meta` is a **MobX observable Map**. The button's `onClick`
handler cloned it using `fastClone`:
```ts
const updatedMeta = fastClone(content.meta);
// fastClone = (obj) => JSON.parse(JSON.stringify(obj))
```
`JSON.stringify` on a MobX observable Map serialises it as `{}` (an
empty plain object) ā Map entries are not picked up by the default JSON
serialiser. As a result:
- `updatedMeta` was always `{}`
- The subsequent `delete updatedMeta.translationStatus` (etc.) calls
were no-ops on a field that didn't exist
- `updateLatestDraft` was called with `meta: {}`, either leaving the
translation fields untouched (if the API merges) or wiping *all*
metadata (if the API replaces)
## Fix
Replace `fastClone(content.meta)` with `{ ...content.meta?.toJS() }`.
`.toJS()` is the correct MobX API for converting an observable Map to a
plain JS object. The spread then creates a regular mutable copy, and the
`delete` operations work as intended.
```ts
// Before
const updatedMeta = fastClone(content.meta);
// After
const updatedMeta = { ...content.meta?.toJS() };
```
This is exactly the same pattern already used in the backend's
`cleanupOrphanedTranslationMetadata` helper
([`smartling.ts:465`](../blob/main/plugins/smartling/src/smartling.ts#L465)),
confirming it's the correct approach.
## Test Plan
- [ ] Open a content entry that has stale translation metadata (e.g.
`translationStatus` = `completed` or `translationJobId` set, not in
`pending`/`local`)
- [ ] Open the content actions menu ā confirm **Clear translation
metadata** is visible
- [ ] Click it and confirm the dialog
- [ ] Verify the snackbar shows \"Translation metadata cleared.\"
- [ ] Reload the content entry and confirm all 7 translation fields
(`translationStatus`, `translationJobId`, `translationBy`,
`translationRevision`, `translationRevisionLatest`, `translationBatch`,
`translationRequested`) are gone from the meta
- [ ] Confirm the **Clear translation metadata** button no longer
appears for that entry
š¤ Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Scoped UI fix for one content action and a patch version bump; no auth
or broad meta-write path changes beyond correcting this handler.
>
> **Overview**
> Fixes the **Clear translation metadata** content action so it actually
removes Smartling fields instead of showing success while leaving
metadata unchanged.
>
> The handler no longer clones `content.meta` with `fastClone` /
`JSON.stringify`, which produced `{}` for MobX observable Maps. It now
builds a plain object via `content.meta.toJS()` (with a fallback),
deletes the seven translation keys, and persists with
`updateLatestDraft`. The confirm dialog call matches the updated API
shape.
>
> Plugin version is bumped to **0.1.2** in `package.json` and the
lockfile.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
035fad6056df312bf5ec4df7663dcfb53422c307. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Sanyam Kamat <1625114+sanyamkamat@users.noreply.github.com> d905293c fix[smartling]: ENG-12342 fix 'Clear translation metadata' button not working (#4544)
## Problem
The **Clear translation metadata** content action in the Smartling
plugin was silently broken. Clicking the button and confirming the
dialog appeared to succeed (snackbar showed \"Translation metadata
cleared.\"), but the translation fields (`translationStatus`,
`translationJobId`, etc.) were never actually removed from the content.
## Root Cause
`content.meta` is a **MobX observable Map**. The button's `onClick`
handler cloned it using `fastClone`:
```ts
const updatedMeta = fastClone(content.meta);
// fastClone = (obj) => JSON.parse(JSON.stringify(obj))
```
`JSON.stringify` on a MobX observable Map serialises it as `{}` (an
empty plain object) ā Map entries are not picked up by the default JSON
serialiser. As a result:
- `updatedMeta` was always `{}`
- The subsequent `delete updatedMeta.translationStatus` (etc.) calls
were no-ops on a field that didn't exist
- `updateLatestDraft` was called with `meta: {}`, either leaving the
translation fields untouched (if the API merges) or wiping *all*
metadata (if the API replaces)
## Fix
Replace `fastClone(content.meta)` with `{ ...content.meta?.toJS() }`.
`.toJS()` is the correct MobX API for converting an observable Map to a
plain JS object. The spread then creates a regular mutable copy, and the
`delete` operations work as intended.
```ts
// Before
const updatedMeta = fastClone(content.meta);
// After
const updatedMeta = { ...content.meta?.toJS() };
```
This is exactly the same pattern already used in the backend's
`cleanupOrphanedTranslationMetadata` helper
([`smartling.ts:465`](../blob/main/plugins/smartling/src/smartling.ts#L465)),
confirming it's the correct approach.
## Test Plan
- [ ] Open a content entry that has stale translation metadata (e.g.
`translationStatus` = `completed` or `translationJobId` set, not in
`pending`/`local`)
- [ ] Open the content actions menu ā confirm **Clear translation
metadata** is visible
- [ ] Click it and confirm the dialog
- [ ] Verify the snackbar shows \"Translation metadata cleared.\"
- [ ] Reload the content entry and confirm all 7 translation fields
(`translationStatus`, `translationJobId`, `translationBy`,
`translationRevision`, `translationRevisionLatest`, `translationBatch`,
`translationRequested`) are gone from the meta
- [ ] Confirm the **Clear translation metadata** button no longer
appears for that entry
š¤ Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Scoped UI fix for one content action and a patch version bump; no auth
or broad meta-write path changes beyond correcting this handler.
>
> **Overview**
> Fixes the **Clear translation metadata** content action so it actually
removes Smartling fields instead of showing success while leaving
metadata unchanged.
>
> The handler no longer clones `content.meta` with `fastClone` /
`JSON.stringify`, which produced `{}` for MobX observable Maps. It now
builds a plain object via `content.meta.toJS()` (with a fallback),
deletes the seven translation keys, and persists with
`updateLatestDraft`. The confirm dialog call matches the updated API
shape.
>
> Plugin version is bumped to **0.1.2** in `package.json` and the
lockfile.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
035fad6056df312bf5ec4df7663dcfb53422c307. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Sanyam Kamat <1625114+sanyamkamat@users.noreply.github.com> 6f9b2253 fix[smartling]: ENG-12342 fix 'Clear translation metadata' button not working (#4544)
## Problem
The **Clear translation metadata** content action in the Smartling
plugin was silently broken. Clicking the button and confirming the
dialog appeared to succeed (snackbar showed \"Translation metadata
cleared.\"), but the translation fields (`translationStatus`,
`translationJobId`, etc.) were never actually removed from the content.
## Root Cause
`content.meta` is a **MobX observable Map**. The button's `onClick`
handler cloned it using `fastClone`:
```ts
const updatedMeta = fastClone(content.meta);
// fastClone = (obj) => JSON.parse(JSON.stringify(obj))
```
`JSON.stringify` on a MobX observable Map serialises it as `{}` (an
empty plain object) ā Map entries are not picked up by the default JSON
serialiser. As a result:
- `updatedMeta` was always `{}`
- The subsequent `delete updatedMeta.translationStatus` (etc.) calls
were no-ops on a field that didn't exist
- `updateLatestDraft` was called with `meta: {}`, either leaving the
translation fields untouched (if the API merges) or wiping *all*
metadata (if the API replaces)
## Fix
Replace `fastClone(content.meta)` with `{ ...content.meta?.toJS() }`.
`.toJS()` is the correct MobX API for converting an observable Map to a
plain JS object. The spread then creates a regular mutable copy, and the
`delete` operations work as intended.
```ts
// Before
const updatedMeta = fastClone(content.meta);
// After
const updatedMeta = { ...content.meta?.toJS() };
```
This is exactly the same pattern already used in the backend's
`cleanupOrphanedTranslationMetadata` helper
([`smartling.ts:465`](../blob/main/plugins/smartling/src/smartling.ts#L465)),
confirming it's the correct approach.
## Test Plan
- [ ] Open a content entry that has stale translation metadata (e.g.
`translationStatus` = `completed` or `translationJobId` set, not in
`pending`/`local`)
- [ ] Open the content actions menu ā confirm **Clear translation
metadata** is visible
- [ ] Click it and confirm the dialog
- [ ] Verify the snackbar shows \"Translation metadata cleared.\"
- [ ] Reload the content entry and confirm all 7 translation fields
(`translationStatus`, `translationJobId`, `translationBy`,
`translationRevision`, `translationRevisionLatest`, `translationBatch`,
`translationRequested`) are gone from the meta
- [ ] Confirm the **Clear translation metadata** button no longer
appears for that entry
š¤ Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Scoped UI fix for one content action and a patch version bump; no auth
or broad meta-write path changes beyond correcting this handler.
>
> **Overview**
> Fixes the **Clear translation metadata** content action so it actually
removes Smartling fields instead of showing success while leaving
metadata unchanged.
>
> The handler no longer clones `content.meta` with `fastClone` /
`JSON.stringify`, which produced `{}` for MobX observable Maps. It now
builds a plain object via `content.meta.toJS()` (with a fallback),
deletes the seven translation keys, and persists with
`updateLatestDraft`. The confirm dialog call matches the updated API
shape.
>
> Plugin version is bumped to **0.1.2** in `package.json` and the
lockfile.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
035fad6056df312bf5ec4df7663dcfb53422c307. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Sanyam Kamat <1625114+sanyamkamat@users.noreply.github.com>