Skip to content

fix: activity tracking description#8268

Merged
sriramveeraghanta merged 8 commits intopreviewfrom
fix-activity-tracking-description
Dec 8, 2025
Merged

fix: activity tracking description#8268
sriramveeraghanta merged 8 commits intopreviewfrom
fix-activity-tracking-description

Conversation

@iam-vipin
Copy link
Member

@iam-vipin iam-vipin commented Dec 8, 2025

Description

This pull request introduces a mechanism to distinguish between regular and migration-only updates to issue descriptions, ensuring that activity logs are not generated for migration-only changes.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Screenshots and Media (if applicable)

Test Scenarios

References

Summary by CodeRabbit

  • New Features

    • Migration-aware description updates: edits can be flagged so they skip activity entries and version tasks.
    • Editor/inputs propagate a migration flag (and expose it to change/save handlers) so autosaves and manual saves can opt out of activity logging.
  • Bug Fixes

    • Reduced unwanted activity/version noise during bulk or automated description imports.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings December 8, 2025 16:04
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 8, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Editor transactions mark unique-id-only edits, the editor hook surfaces this as isMigrationUpdate, UI components propagate it through DescriptionInput submit, frontend sends skip_activity on migration description updates, and backend handlers conditionally suppress activity and description-version tasks when skip_activity and a description change are present.

Changes

Cohort / File(s) Summary
Backend activity suppression
apps/api/plane/app/views/intake/base.py, apps/api/plane/app/views/issue/base.py
Extract skip_activity from request data and detect is_description_update when description_html is present; if skip_activity && is_description_update, skip enqueuing activity and description-version tasks, otherwise preserve existing enqueue behavior.
Editor transaction metadata
packages/editor/src/core/extensions/unique-id/utils.ts
Add transaction meta uniqueIdOnlyChange = true for transactions that only update unique IDs.
Editor hook & types
packages/editor/src/core/hooks/use-editor.ts, packages/editor/src/core/types/editor.ts
Read uniqueIdOnlyChange meta in onUpdate and pass { isMigrationUpdate } as an optional third argument to onChange; update public onChange signature accordingly.
Description input component
apps/web/core/components/editor/rich-text/description-input/root.tsx
Add isMigrationUpdate to form data and state, change onSubmit signature to accept (value, isMigrationUpdate?), propagate isMigrationUpdate through debounced save, reset, and unmount save paths.
Description submit usages
apps/web/core/components/inbox/content/issue-root.tsx, apps/web/core/components/issues/issue-detail/main-content.tsx, apps/web/core/components/issues/peek-overview/issue-detail.tsx
Update DescriptionInput usage to accept isMigrationUpdate and include skip_activity: "true" in PATCH payload when isMigrationUpdate is truthy.
Misc manifest / deps
manifest_file, requirements.txt, pyproject.toml, package.json
Manifest and dependency files updated (paths listed in diff).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Editor as RichTextEditor
    participant Hook as use-editor
    participant Component as DescriptionInput
    participant API as Frontend API Client
    participant Backend as Intake/Issue Handler

    User->>Editor: Edit description (unique-id-only change)
    Editor->>Editor: tr.setMeta("uniqueIdOnlyChange", true)
    Editor->>Hook: onUpdate(editor, transaction)
    Hook->>Hook: read transaction.getMeta("uniqueIdOnlyChange")
    Hook->>Component: onChange(json, html, {isMigrationUpdate: true})
    Component->>Component: setValue("isMigrationUpdate", true)
    Component->>Component: Debounced save or submit
    Component->>API: PATCH /issue (description_html, skip_activity: "true")
    API->>Backend: Deliver payload
    Backend->>Backend: skip_activity = request.data.get("skip_activity")
    Backend->>Backend: is_description_update = presence of description_html
    alt skip_activity AND is_description_update
        Backend->>Backend: Do not enqueue activity or description-version tasks
    else
        Backend->>Backend: Enqueue normal activity and version tasks
    end
    Backend->>API: Return updated resource
    API->>Component: Success response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Areas needing focused review:
    • Backend gating in intake/base.py and issue/base.py to ensure tasks are correctly skipped only for migration-description updates.
    • Backwards compatibility of updated onChange signature in use-editor and packages/editor types where consumers may still expect two args.
    • Form plumbing and debounced/unmount save paths in description-input/root.tsx to ensure isMigrationUpdate is consistently preserved and propagated.
    • All DescriptionInput call sites to confirm skip_activity is sent only when intended.

Poem

🐰
I hop through edits, soft and sly,
A secret flag beneath my eye,
When migration hums, I hold the noise,
Quiet patches, gentle joys,
Carrots saved for calmer sky. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive Title is vague and does not clearly convey the specific change; 'activity tracking description' lacks specificity about the mechanism being introduced. Clarify the title to better reflect the core change, such as: 'fix: skip activity logging for migration-only description updates' or 'fix: distinguish migration updates from regular description edits'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed PR description covers the primary objective and type of change, but lacks test scenarios and references that would provide better context for reviewers.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-activity-tracking-description

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 968ce2b and 8099159.

📒 Files selected for processing (2)
  • apps/api/plane/app/views/intake/base.py (2 hunks)
  • apps/api/plane/app/views/issue/base.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/api/plane/app/views/issue/base.py
  • apps/api/plane/app/views/intake/base.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build and lint web apps
  • GitHub Check: Analyze (javascript)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
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

This pull request aims to prevent activity logs from being generated for migration-only updates to issue descriptions (specifically when unique IDs are added to editor content). The implementation tracks migration updates through the editor's transaction metadata and passes this information to the backend to conditionally skip activity logging.

Critical Issues Found: The PR contains several critical bugs that prevent it from working as intended:

  1. Parameter name mismatch between frontend (no_activity) and backend (skip_activity)
  2. Invalid TypeScript syntax in the editor type definition
  3. Logic errors in both backend views using OR instead of AND, which will cause incorrect behavior

Key Changes

  • Added isMigrationUpdate flag propagation from editor to API calls
  • Modified backend views to conditionally skip activity logging based on skip_activity flag
  • Updated editor onChange signature to include migration update metadata

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/editor/src/core/types/editor.ts Added optional third parameter to onChange callback for migration metadata (has syntax error)
packages/editor/src/core/hooks/use-editor.ts Detects migration updates via transaction metadata and passes to onChange
packages/editor/src/core/extensions/unique-id/utils.ts Sets metadata flag to identify unique-id-only changes
apps/web/core/components/editor/rich-text/description-input/root.tsx Captures and forwards isMigrationUpdate flag through form handling
apps/web/core/components/issues/peek-overview/issue-detail.tsx Passes migration flag to API with incorrect parameter name
apps/web/core/components/issues/issue-detail/main-content.tsx Passes migration flag to API with incorrect parameter name
apps/web/core/components/inbox/content/issue-root.tsx Passes migration flag to API with incorrect parameter name
apps/api/plane/app/views/issue/base.py Conditionally skips activity logging (has logic error)
apps/api/plane/app/views/intake/base.py Conditionally skips activity logging (has logic error)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (!issue.id || !issue.project_id) return;
await issueOperations.update(workspaceSlug, issue.project_id, issue.id, {
description_html: value,
...(isMigrationUpdate ? { no_activity: "true" } : {}),
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parameter name mismatch: the frontend sends no_activity but the backend expects skip_activity (see apps/api/plane/app/views/intake/base.py:325). This will cause the migration updates to still generate activity logs, defeating the purpose of this fix.

Change to:

...(isMigrationUpdate ? { skip_activity: true } : {}),
Suggested change
...(isMigrationUpdate ? { no_activity: "true" } : {}),
...(isMigrationUpdate ? { skip_activity: true } : {}),

Copilot uses AI. Check for mistakes.
user_id=request.user.id,
)

if not skip_activity or not is_description_update:
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic error: the condition if not skip_activity or not is_description_update: uses OR when it should use AND. This will cause activity logging to occur for ALL non-description updates, even when skip_activity=True. The intention is to skip activity ONLY when both conditions are true (skip_activity AND is_description_update).

Change to:

if not (skip_activity and is_description_update):
Suggested change
if not skip_activity or not is_description_update:
if not (skip_activity and is_description_update):

Copilot uses AI. Check for mistakes.
issue_id=str(pk),
user_id=request.user.id,
)
if not skip_activity or not is_description_update:
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic error: the condition if not skip_activity or not is_description_update: uses OR when it should use AND. This will cause activity logging to occur for ALL non-description updates, even when skip_activity=True. The intention is to skip activity ONLY when both conditions are true (skip_activity AND is_description_update).

Change to:

if not (skip_activity and is_description_update):
Suggested change
if not skip_activity or not is_description_update:
if not (skip_activity and is_description_update):

Copilot uses AI. Check for mistakes.
onAssetChange?: (assets: TEditorAsset[]) => void;
onEditorFocus?: () => void;
onChange?: (json: object, html: string) => void;
onChange?: (json: object, html: string, { isMigrationUpdate }?: { isMigrationUpdate?: boolean }) => void;
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid TypeScript syntax for optional parameter. The destructured parameter syntax is incorrect. The correct syntax for an optional third parameter should be:

onChange?: (json: object, html: string, options?: { isMigrationUpdate?: boolean }) => void;

The current syntax { isMigrationUpdate }?: { isMigrationUpdate?: boolean } is not valid TypeScript.

Suggested change
onChange?: (json: object, html: string, { isMigrationUpdate }?: { isMigrationUpdate?: boolean }) => void;
onChange?: (json: object, html: string, options?: { isMigrationUpdate?: boolean }) => void;

Copilot uses AI. Check for mistakes.
if (!issue.id || !issue.project_id) return;
await issueOperations.update(workspaceSlug, issue.project_id, issue.id, {
description_html: value,
...(isMigrationUpdate ? { no_activity: "true" } : {}),
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parameter name mismatch: the frontend sends no_activity but the backend expects skip_activity (see apps/api/plane/app/views/issue/base.py:615). This will cause the migration updates to still generate activity logs, defeating the purpose of this fix.

Change to:

...(isMigrationUpdate ? { skip_activity: true } : {}),
Suggested change
...(isMigrationUpdate ? { no_activity: "true" } : {}),
...(isMigrationUpdate ? { skip_activity: true } : {}),

Copilot uses AI. Check for mistakes.
if (!issue.id || !issue.project_id) return;
await issueOperations.update(workspaceSlug, issue.project_id, issue.id, {
description_html: value,
...(isMigrationUpdate ? { no_activity: "true" } : {}),
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parameter name mismatch: the frontend sends no_activity but the backend expects skip_activity (see apps/api/plane/app/views/issue/base.py:615). This will cause the migration updates to still generate activity logs, defeating the purpose of this fix.

Change to:

...(isMigrationUpdate ? { skip_activity: true } : {}),
Suggested change
...(isMigrationUpdate ? { no_activity: "true" } : {}),
...(isMigrationUpdate ? { skip_activity: true } : {}),

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (1)
apps/web/core/components/inbox/content/issue-root.tsx (1)

204-209: Keep payload semantics consistent with other description updates

This onSubmit change mirrors the peek‑overview implementation: it forwards isMigrationUpdate and conditionally adds no_activity: "true" to the update payload, which keeps behavior consistent across inbox and regular issue flows.

Same as the other call site, please verify that no_activity and its "true" value match what the backend expects for suppressing activity logs; if there’s already a canonical flag in use, this should align with it.

🧹 Nitpick comments (4)
apps/api/plane/app/views/intake/base.py (1)

325-326: Consider using .get() instead of .pop() for skip_activity to avoid side effects.

Using .pop() removes the skip_activity key from request.data, which could cause issues if the request data is accessed elsewhere in the codebase. Unless the removal is intentional (e.g., to prevent the field from being saved to the database), prefer .get() for reading values without modification.

Apply this diff:

-        skip_activity = request.data.pop("skip_activity", False)
+        skip_activity = request.data.get("skip_activity", False)
apps/api/plane/app/views/issue/base.py (1)

615-616: Consider using .get() instead of .pop() for skip_activity to avoid side effects.

Using .pop() removes the skip_activity key from request.data, which could cause issues if the request data is accessed elsewhere. Unless the removal is intentional (e.g., to prevent the field from being saved to the database), prefer .get() for reading values without modification.

Apply this diff:

-        skip_activity = request.data.pop("skip_activity", False)
+        skip_activity = request.data.get("skip_activity", False)
packages/editor/src/core/extensions/unique-id/utils.ts (1)

32-35: Good use of transaction metadata; consider guarding on actual changes

Tagging unique‑ID‑only transactions via tr.setMeta("uniqueIdOnlyChange", true) is a clean way to drive the migration flag downstream.

You might optionally tighten this a bit:

  • Only mark the transaction (and dispatch) when there are actual ID updates, e.g.:
if (nodesWithoutId.length === 0) return;

nodesWithoutId.forEach(...);
tr.setMeta("addToHistory", false);
tr.setMeta("uniqueIdOnlyChange", true);
view.dispatch(tr);
  • If this meta key will be shared elsewhere, consider extracting "uniqueIdOnlyChange" to a shared constant to avoid typos.

Both are non‑blocking polish items.

apps/web/core/components/editor/rich-text/description-input/root.tsx (1)

22-26: End‑to‑end migration flag plumbing through DescriptionInput looks sound

The way isMigrationUpdate is introduced and propagated here is internally consistent:

  • TFormData and useForm default values initialize isMigrationUpdate: false, and the reset effect also clears it, so entities don’t inherit a stale true flag.
  • handleDescriptionFormSubmit correctly forwards formData.isMigrationUpdate as the second argument to onSubmit, matching the updated prop type.
  • The RichTextEditor onChange handler updates the form field with options?.isMigrationUpdate ?? false, ensuring that autosave and unmount saves see the correct migration status for each transaction.

This cleanly bridges the editor‑level meta into your submit pipeline without altering existing behavior for normal edits.

One optional future‑proofing idea: if you anticipate more flags later, you might eventually switch the second argument of onSubmit to a small options object (e.g. { isMigrationUpdate?: boolean }) to keep the call sites self‑describing, but that’s not necessary for this PR.

Also applies to: 60-61, 109-113, 124-129, 135-135, 141-152, 215-218

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0bc2bd and 5d4d990.

📒 Files selected for processing (9)
  • apps/api/plane/app/views/intake/base.py (2 hunks)
  • apps/api/plane/app/views/issue/base.py (2 hunks)
  • apps/web/core/components/editor/rich-text/description-input/root.tsx (6 hunks)
  • apps/web/core/components/inbox/content/issue-root.tsx (1 hunks)
  • apps/web/core/components/issues/issue-detail/main-content.tsx (1 hunks)
  • apps/web/core/components/issues/peek-overview/issue-detail.tsx (1 hunks)
  • packages/editor/src/core/extensions/unique-id/utils.ts (1 hunks)
  • packages/editor/src/core/hooks/use-editor.ts (1 hunks)
  • packages/editor/src/core/types/editor.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,mts,cts}

📄 CodeRabbit inference engine (.github/instructions/typescript.instructions.md)

**/*.{ts,tsx,mts,cts}: Use const type parameters for more precise literal inference in TypeScript 5.0+
Use the satisfies operator to validate types without widening them
Leverage inferred type predicates to reduce the need for explicit is return types in filter/check functions
Use NoInfer<T> utility to block inference for specific type arguments when they should be determined by other arguments
Utilize narrowing in switch(true) blocks for control flow analysis (TypeScript 5.3+)
Rely on narrowing from direct boolean comparisons for type guards
Trust preserved narrowing in closures when variables aren't modified after the check (TypeScript 5.4+)
Use constant indices to narrow object/array properties (TypeScript 5.5+)
Use standard ECMAScript decorators (Stage 3) instead of legacy experimentalDecorators
Use using declarations for explicit resource management with Disposable pattern instead of manual cleanup (TypeScript 5.2+)
Use with { type: "json" } for import attributes; avoid deprecated assert syntax (TypeScript 5.3/5.8+)
Use import type explicitly when importing types to ensure they are erased during compilation, respecting verbatimModuleSyntax flag
Use .ts, .mts, .cts extensions in import type statements (TypeScript 5.2+)
Use import type { Type } from "mod" with { "resolution-mode": "import" } for specific module resolution contexts (TypeScript 5.3+)
Use new iterator methods (map, filter, etc.) if targeting modern environments (TypeScript 5.6+)
Utilize new Set methods like union, intersection, etc., when available (TypeScript 5.5+)
Use Object.groupBy / Map.groupBy standard methods for grouping instead of external libraries (TypeScript 5.4+)
Use Promise.withResolvers() for creating promises with exposed resolve/reject functions (TypeScript 5.7+)
Use copying array methods (toSorted, toSpliced, with) for immutable array operations (TypeScript 5.2+)
Avoid accessing instance fields via super in classes (TypeScript 5....

Files:

  • packages/editor/src/core/extensions/unique-id/utils.ts
  • apps/web/core/components/issues/issue-detail/main-content.tsx
  • packages/editor/src/core/types/editor.ts
  • packages/editor/src/core/hooks/use-editor.ts
  • apps/web/core/components/inbox/content/issue-root.tsx
  • apps/web/core/components/editor/rich-text/description-input/root.tsx
  • apps/web/core/components/issues/peek-overview/issue-detail.tsx
🧠 Learnings (2)
📚 Learning: 2025-06-16T07:23:39.497Z
Learnt from: vamsikrishnamathala
Repo: makeplane/plane PR: 7214
File: web/core/store/issue/helpers/base-issues.store.ts:117-117
Timestamp: 2025-06-16T07:23:39.497Z
Learning: In the updateIssueDates method of BaseIssuesStore (web/core/store/issue/helpers/base-issues.store.ts), the projectId parameter is intentionally made optional to support override implementations in subclasses. The base implementation requires projectId and includes an early return check, but making it optional allows derived classes to override the method with different parameter requirements.

Applied to files:

  • apps/web/core/components/inbox/content/issue-root.tsx
📚 Learning: 2025-10-10T13:25:14.810Z
Learnt from: gakshita
Repo: makeplane/plane PR: 7949
File: apps/web/core/components/issues/issue-modal/form.tsx:183-189
Timestamp: 2025-10-10T13:25:14.810Z
Learning: In `apps/web/core/components/issues/issue-modal/form.tsx`, the form reset effect uses a `dataResetProperties` dependency array prop (default: []) to give parent components explicit control over when the form resets. Do not suggest adding the `data` prop itself to the dependency array, as this would cause unwanted resets on every render when the data object reference changes, disrupting user input. The current pattern is intentional and allows the parent to trigger resets only when specific conditions are met.

Applied to files:

  • apps/web/core/components/editor/rich-text/description-input/root.tsx
🧬 Code graph analysis (5)
apps/web/core/components/issues/issue-detail/main-content.tsx (1)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/web/core/components/inbox/content/issue-root.tsx (1)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/api/plane/app/views/intake/base.py (1)
apps/api/plane/bgtasks/issue_activities_task.py (1)
  • issue_activity (1500-1600)
apps/web/core/components/issues/peek-overview/issue-detail.tsx (1)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/api/plane/app/views/issue/base.py (2)
apps/api/plane/bgtasks/issue_activities_task.py (1)
  • issue_activity (1500-1600)
apps/api/plane/bgtasks/webhook_task.py (1)
  • model_activity (460-502)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Agent
  • GitHub Check: CodeQL analysis (javascript-typescript)
  • GitHub Check: Build and lint web apps
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
packages/editor/src/core/types/editor.ts (1)

163-163: onChange signature extension looks correct and backward‑compatible

The added optional { isMigrationUpdate } third parameter matches how useEditor and the rich text flow now pass migration metadata, while keeping existing two‑argument call sites valid.

packages/editor/src/core/hooks/use-editor.ts (1)

83-87: Correct wiring of transaction meta into onChange

Using transaction.getMeta("uniqueIdOnlyChange") === true to derive isMigrationUpdate and passing it through as the third argument to onChange cleanly exposes migration‑only updates to consumers without breaking existing signatures.

If you introduce more places that read/write this meta key, consider centralizing the "uniqueIdOnlyChange" literal as a shared constant, but the current implementation is fine as‑is.

Comment on lines 137 to 142
onSubmit={async (value, isMigrationUpdate) => {
if (!issue.id || !issue.project_id) return;
await issueOperations.update(workspaceSlug, issue.project_id, issue.id, {
description_html: value,
...(isMigrationUpdate ? { no_activity: "true" } : {}),
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n "no_activity" -S

Repository: makeplane/plane

Length of output: 456


🏁 Script executed:

#!/bin/bash
rg -n "skip_activity" -S

Repository: makeplane/plane

Length of output: 488


🏁 Script executed:

#!/bin/bash
# Search for issue operations/update patterns to understand payload structure
rg -n "issueOperations\.update|description_html" -S -A 3 -B 1

Repository: makeplane/plane

Length of output: 50372


🏁 Script executed:

#!/bin/bash
# Check the exact backend logic for skip_activity in issue updates
sed -n '610,670p' apps/api/plane/app/views/issue/base.py

Repository: makeplane/plane

Length of output: 2688


🏁 Script executed:

#!/bin/bash
# Check intake view as well
sed -n '320,430p' apps/api/plane/app/views/intake/base.py

Repository: makeplane/plane

Length of output: 4883


Field name mismatch blocks activity suppression; rename no_activity to skip_activity

The handler sends no_activity: "true" but the backend's partial_update method (issue/base.py:615, intake/base.py:325) pops and checks for skip_activity. Because the field name does not match, the backend defaults skip_activity to False, causing activity to be logged on every migration update instead of suppressing it.

Additionally, the field is sent as a string "true" rather than a boolean. The backend's logic if not skip_activity or not is_description_update: expects a boolean value.

Rename no_activity to skip_activity and send it as a boolean (true instead of "true"):

...(isMigrationUpdate ? { skip_activity: true } : {}),
🤖 Prompt for AI Agents
In apps/web/core/components/issues/issue-detail/main-content.tsx around lines
137 to 142, the update payload uses the wrong field name and type for
suppressing activity: it sends no_activity: "true" but the backend expects
skip_activity as a boolean. Change the conditional payload to use skip_activity:
true (boolean) instead of no_activity: "true" so the backend's partial_update
logic correctly detects and respects activity suppression.

Comment on lines 137 to 142
onSubmit={async (value, isMigrationUpdate) => {
if (!issue.id || !issue.project_id) return;
await issueOperations.update(workspaceSlug, issue.project_id, issue.id, {
description_html: value,
...(isMigrationUpdate ? { no_activity: "true" } : {}),
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Search for no_activity usage patterns
rg -n "no_activity" -S --type-add 'web:tsx,ts' -t web

Repository: makeplane/plane

Length of output: 207


🏁 Script executed:

# Search for skip_activity or similar alternative patterns
rg -n "skip_activity|skipActivity" -S --type-add 'web:tsx,ts' -t web

Repository: makeplane/plane

Length of output: 207


🏁 Script executed:

# Search for issueOperations.update calls to see how no_activity is used
rg -B 2 -A 2 "issueOperations\.update" --type-add 'web:tsx,ts' -t web

Repository: makeplane/plane

Length of output: 207


🏁 Script executed:

# Check the issueOperations definition to understand the update signature
fd -e ts -e tsx | xargs grep -l "issueOperations\s*=" | head -5

Repository: makeplane/plane

Length of output: 484


🏁 Script executed:

# Search for no_activity without type restrictions
rg "no_activity" -n

Repository: makeplane/plane

Length of output: 456


🏁 Script executed:

# Search for skip_activity or similar patterns
rg "skip_activity|skipActivity" -n

Repository: makeplane/plane

Length of output: 488


🏁 Script executed:

# Search for issueOperations.update calls
rg "issueOperations\.update" -B 2 -A 2 -n

Repository: makeplane/plane

Length of output: 15603


🏁 Script executed:

# Inspect the target file
cat -n apps/web/core/components/issues/peek-overview/issue-detail.tsx | head -150

Repository: makeplane/plane

Length of output: 6562


🏁 Script executed:

# Search for issueOperations.update implementation to see how payload is sent
rg -n "const.*issueOperations.*=" --type-add 'web:tsx,ts,js' -A 5 | head -50

Repository: makeplane/plane

Length of output: 4914


🏁 Script executed:

# Look for the update method definition in issue operations
fd -e ts -e tsx | xargs grep -l "update.*workspaceSlug.*projectId" | grep -i operation

Repository: makeplane/plane

Length of output: 137


🏁 Script executed:

# Check for any API middleware or transformation
rg -n "no_activity|skip_activity" apps/web --type-add 'web:tsx,ts,js' -B 3 -A 3

Repository: makeplane/plane

Length of output: 2378


🏁 Script executed:

# Get the full issueOperations definition from peek-overview/root.tsx
cat -n apps/web/core/components/issues/peek-overview/root.tsx | sed -n '63,150p'

Repository: makeplane/plane

Length of output: 3922


🏁 Script executed:

# Search for the update method definition in issueOperations
rg -n "update.*async.*workspaceSlug" apps/web/core/components/issues/peek-overview/root.tsx -A 10

Repository: makeplane/plane

Length of output: 587


🏁 Script executed:

# Look for API service or client that processes the update payload
rg -n "class.*IssueService|export.*function.*update" --type-add 'web:tsx,ts,js' apps/web/services -A 3

Repository: makeplane/plane

Length of output: 116


🏁 Script executed:

# Find where issues.updateIssue is defined
rg -n "updateIssue.*async" --type-add 'web:tsx,ts,js' -A 5 | head -80

Repository: makeplane/plane

Length of output: 7001


🏁 Script executed:

# Search for issues store/hook definition
rg -n "useIssues|issues.*useMemo" apps/web/core/components/issues/peek-overview/root.tsx -B 5 -A 3

Repository: makeplane/plane

Length of output: 1158


🏁 Script executed:

# Find the actual store implementation
fd -type f -name "*.ts" -o -name "*.tsx" | xargs rg -l "updateIssue" | grep -E "store|hook" | head -5

Repository: makeplane/plane

Length of output: 472


🏁 Script executed:

# Get the full updateIssue implementation from issue.store.ts
cat -n apps/web/core/store/issue/issue-details/issue.store.ts | sed -n '175,220p'

Repository: makeplane/plane

Length of output: 2275


🏁 Script executed:

# Search for projectIssues service to see the actual API call
rg -n "projectIssues\." apps/web/core/store/issue/issue-details/issue.store.ts -B 2 -A 2

Repository: makeplane/plane

Length of output: 41


🏁 Script executed:

# Find where projectIssues is instantiated/imported
rg -n "projectIssues" apps/web/core/store/issue/issue-details/issue.store.ts | head -20

Repository: makeplane/plane

Length of output: 268


🏁 Script executed:

# Find rootIssueStore definition
rg -n "class.*RootIssueStore|projectIssues.*=" apps/web/core/store/issue/issue-details/root.store.ts -A 3 | head -40

Repository: makeplane/plane

Length of output: 41


🏁 Script executed:

# Search for projectIssues store file
fd -name "*project*issues*" -o -name "*root*store*" | grep -E "store|issue" | head -10

Repository: makeplane/plane

Length of output: 289


🏁 Script executed:

# Find the actual API service that sends the payload
rg -n "class.*ProjectIssues|updateIssue.*async" apps/web/core/store -A 5 | grep -A 5 "updateIssue"

Repository: makeplane/plane

Length of output: 2750


🏁 Script executed:

# Find BaseIssuesStore which likely has the actual updateIssue implementation
fd "base*issues*" -type f

Repository: makeplane/plane

Length of output: 229


🏁 Script executed:

# Search for the store file that contains updateIssue with API call
rg "updateIssue.*service\.|issueService\.update" --type-add 'web:tsx,ts,js' -B 3 -A 8

Repository: makeplane/plane

Length of output: 3137


🏁 Script executed:

# Look for where the data payload is actually sent (likely in a service file)
rg "PUT.*issue|issueService" apps/web/core/store -A 5 | head -60

Repository: makeplane/plane

Length of output: 4408


🏁 Script executed:

# Find IssueService definition
fd "issue.*service" -type f | head -5

Repository: makeplane/plane

Length of output: 229


🏁 Script executed:

# Search for IssueService class and updateIssue method
rg "class IssueService|updateIssue.*async" -A 10 | head -100

Repository: makeplane/plane

Length of output: 9263


🏁 Script executed:

# Get IssueService.updateIssue method
cat apps/web/core/services/issue/issue.service.ts | grep -n "updateIssue" -A 15 | head -50

Repository: makeplane/plane

Length of output: 1882


🏁 Script executed:

# Get the full IssueService file to find updateIssue method
wc -l apps/web/core/services/issue/issue.service.ts

Repository: makeplane/plane

Length of output: 108


🏁 Script executed:

# Search more specifically for updateIssue pattern
rg "updateIssue.*\(" apps/web/core/services/issue/issue.service.ts -A 10

Repository: makeplane/plane

Length of output: 1236


🏁 Script executed:

# Look at the full IssueService to see all methods
cat -n apps/web/core/services/issue/issue.service.ts | head -100

Repository: makeplane/plane

Length of output: 3673


🏁 Script executed:

# Search for BaseIssuesStore which extends or contains projectIssues
rg "class.*BaseIssues|updateIssue.*=" apps/web/core/store/issue/helpers/base-issues.store.ts -A 8 | head -100

Repository: makeplane/plane

Length of output: 390


🏁 Script executed:

# Search for updateIssue in BaseIssuesStore
rg "updateIssue.*=" apps/web/core/store/issue/helpers/base-issues.store.ts -A 20 | head -80

Repository: makeplane/plane

Length of output: 41


🏁 Script executed:

# Also check the size and search for issueUpdate which might be the method name
wc -l apps/web/core/store/issue/helpers/base-issues.store.ts

Repository: makeplane/plane

Length of output: 118


🏁 Script executed:

# Search for issueUpdate method
rg "issueUpdate\s*=" apps/web/core/store/issue/helpers/base-issues.store.ts -A 30 | head -100

Repository: makeplane/plane

Length of output: 41


🏁 Script executed:

# Also search for PATCH or patchIssue calls
rg "patchIssue\|issueService\.patch" apps/web/core/store/issue/helpers/base-issues.store.ts -B 3 -A 8 | head -80

Repository: makeplane/plane

Length of output: 41


🏁 Script executed:

# Find ProjectIssues store definition
fd "project.*issues.*store" -type f

Repository: makeplane/plane

Length of output: 229


🏁 Script executed:

# Search for class ProjectIssues
rg "class ProjectIssues" apps/web/core/store -A 30

Repository: makeplane/plane

Length of output: 4816


🏁 Script executed:

# Look at the root store to see how projectIssues is initialized
rg "projectIssues" apps/web/core/store/issue/root-issue-store.ts -B 2 -A 5 | head -50

Repository: makeplane/plane

Length of output: 144


🏁 Script executed:

# Search BaseIssuesStore for all methods containing "update" or "issue"
rg "^\s*(updateIssue|issueUpdate)\s*=" apps/web/core/store/issue/helpers/base-issues.store.ts -A 25

Repository: makeplane/plane

Length of output: 41


🏁 Script executed:

# More broad search - look for methods that call issueService
rg "this\.issueService\." apps/web/core/store/issue/helpers/base-issues.store.ts | head -20

Repository: makeplane/plane

Length of output: 1054


Field name and type mismatch: frontend sends no_activity: "true" but backend expects skip_activity as boolean

The code sends no_activity: "true" (string) to the backend, but the API expects skip_activity (boolean). Backend code in apps/api/plane/app/views/issue/base.py:615 explicitly pops skip_activity from the request payload:

skip_activity = request.data.pop("skip_activity", False)

The no_activity field will be silently ignored by the backend, and the migration flag won't suppress activity logging. Change the payload to:

...(isMigrationUpdate ? { skip_activity: true } : {})

This affects three files: peek-overview/issue-detail.tsx, issue-detail/main-content.tsx, and inbox/content/issue-root.tsx.

🤖 Prompt for AI Agents
In apps/web/core/components/issues/peek-overview/issue-detail.tsx around lines
137-142 (and likewise update issue-detail/main-content.tsx and
inbox/content/issue-root.tsx), the payload uses no_activity: "true" (a string)
which the backend ignores; change the migration flag to send skip_activity: true
(a boolean) when isMigrationUpdate is true so the backend's
request.data.pop("skip_activity", False) receives the correct boolean field and
suppresses activity logging.

iam-vipin and others added 3 commits December 8, 2025 21:57
@sriramveeraghanta sriramveeraghanta merged commit a9e9cb2 into preview Dec 8, 2025
7 checks passed
@sriramveeraghanta sriramveeraghanta deleted the fix-activity-tracking-description branch December 8, 2025 16:48
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.

5 participants