Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

fix: subscription on deal drag and drop - #8636

#8636
Merged
batorshih merged 9 commits into
erxes:mainerxes/erxes:mainfrom
batorshih:fix/salesbatorshih/erxes:fix/salesCopy head branch name to clipboard
Jul 8, 2026
Merged

fix: subscription on deal drag and drop#8636
batorshih merged 9 commits into
erxes:mainerxes/erxes:mainfrom
batorshih:fix/salesbatorshih/erxes:fix/salesCopy head branch name to clipboard

Conversation

@batorshih

@batorshih batorshih commented Jul 8, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Deal boards now update in real time when pipeline order changes, keeping card positions in sync across views.
  • Bug Fixes

    • Reduced duplicate cards and repeated deal IDs during drag-and-drop and board refreshes.
    • Improved deal detail display by removing duplicate product entries.
    • Made board updates more stable when items move within the same pipeline stage.

@deepsource-io

deepsource-io Bot commented Jul 8, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in 71d4a31...277281e on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
JavaScript Jul 8, 2026 7:48a.m. Review ↗
Docker Jul 8, 2026 7:48a.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

@gitguardian

gitguardian Bot commented Jul 8, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

Since your pull request originates from a forked repository, GitGuardian is not able to associate the secrets uncovered with secret incidents on your GitGuardian dashboard.
Skipping this check run and merging your pull request will create secret incidents on your GitGuardian dashboard.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
34048589 Triggered Generic Password a30a2a2 backend/plugins/erxes-agent_api/deploy/langfuse/docker-compose.yml View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ca7e1008-d7eb-4520-a65c-dddf6ce39ec6

📥 Commits

Reviewing files that changed from the base of the PR and between 71d4a31 and 277281e.

📒 Files selected for processing (12)
  • backend/plugins/sales_api/src/apollo/subscription.ts
  • backend/plugins/sales_api/src/modules/sales/graphql/resolvers/mutations/utils.ts
  • backend/plugins/sales_api/src/modules/sales/graphql/resolvers/utils.ts
  • backend/plugins/sales_api/src/modules/sales/graphql/schemas/board.ts
  • frontend/plugins/sales_ui/src/modules/deals/boards/components/DealsBoard.tsx
  • frontend/plugins/sales_ui/src/modules/deals/boards/components/DealsBoardCard.tsx
  • frontend/plugins/sales_ui/src/modules/deals/boards/components/DealsBoardCardDetails.tsx
  • frontend/plugins/sales_ui/src/modules/deals/boards/components/DealsBoardColumn.tsx
  • frontend/plugins/sales_ui/src/modules/deals/boards/components/common/GenericBoard.tsx
  • frontend/plugins/sales_ui/src/modules/deals/boards/hooks/usePipelineChanged.ts
  • frontend/plugins/sales_ui/src/modules/deals/cards/hooks/useDeals.tsx
  • frontend/plugins/sales_ui/src/modules/deals/graphql/subscriptions/pipelineChange.ts

📝 Walkthrough

Walkthrough

Adds a salesPipelinesChanged GraphQL subscription (schema, resolvers, PubSub publishing) triggered when deals move stages, wiring processId/sourceStageId through changeDeal. Frontend adds usePipelineChanged hook to sync board state from subscription events, plus several duplicate-ID fixes in board column/product rendering.

Changes

Sales Pipeline Change Subscription

Layer / File(s) Summary
GraphQL schema and subscription wiring
backend/plugins/sales_api/src/apollo/subscription.ts, backend/plugins/sales_api/src/modules/sales/graphql/schemas/board.ts
Adds SalesPipelineChangeResponse type and salesPipelinesChanged(_id: String!) subscription with resolve/subscribe handlers backed by graphqlPubsub.
Backend publish logic
backend/plugins/sales_api/src/modules/sales/graphql/resolvers/utils.ts, .../mutations/utils.ts
Adds resolveDealSubscriptionItem and publishPipelineOrderUpdated helpers; changeDeal now accepts sourceStageId/processId, loads destination stage early, and publishes pipeline order updates after moving a deal.
Frontend subscription hook and mutation wiring
frontend/plugins/sales_ui/.../hooks/usePipelineChanged.ts, .../graphql/subscriptions/pipelineChange.ts, DealsBoard.tsx, useDeals.tsx
Adds PIPELINE_CHANGED subscription document and usePipelineChanged hook that updates board/deals state on remote stage moves while ignoring self-originated processId events; changeDeals/moveDealStage now generate and pass a processId.

Board Column Duplicate ID Fixes

Layer / File(s) Summary
Deduplicate column items and product lists
DealsBoardColumn.tsx, common/GenericBoard.tsx, DealsBoardCard.tsx, DealsBoardCardDetails.tsx
Applies Set-based deduplication to column item ID arrays during drag-over insertion and rendering, dedupes filtered product lists by _id, and updates a list item React key.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant DealsBoard
  participant changeDeal_mutation
  participant Backend
  participant graphqlPubsub
  participant OtherClient_usePipelineChanged

  User->>DealsBoard: drag deal to new stage
  DealsBoard->>changeDeal_mutation: mutate(itemId, destinationStageId, processId)
  changeDeal_mutation->>Backend: changeDeal(sourceStageId, destinationStageId, processId)
  Backend->>Backend: update deal, resolveDealSubscriptionItem
  Backend->>graphqlPubsub: publishPipelineOrderUpdated(pipelineIds, item, processId, oldStageId)
  graphqlPubsub-->>OtherClient_usePipelineChanged: salesPipelinesChanged event
  OtherClient_usePipelineChanged->>OtherClient_usePipelineChanged: compare processId to localStorage
  OtherClient_usePipelineChanged->>OtherClient_usePipelineChanged: update board columns and allDealsMap
Loading

Possibly related PRs

  • erxes/erxes#7932: The backend changeDeal flow (now taking processId/sourceStageId and publishing salesPipelinesChanged events) is directly extended by this PR's new cpDealsChange resolver logic.
  • erxes/erxes#7991: Refactors stage selection/move triggering via DealSelect/MoveDealDropdown, complementing this PR's move mutation and pipeline-change subscription behavior using processId.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@batorshih batorshih changed the title Fix/sales fix: subscription on deal drag and drop Jul 8, 2026
@batorshih
batorshih merged commit f51d409 into erxes:main Jul 8, 2026
9 of 11 checks passed
processId,
},
}).finally(() => {
delete locallyMovedIdsRef.current[draggedItemId];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Do not delete dynamically computed property keys


Deleting dynamically computed keys can be dangerous and in some cases not well optimized.

.map((p) => {
const product = productMap.get(p.productId || '');
if (!product) return null;
const filterProducts = (tickUsed: boolean) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Documentation comment not found for arrow function `filterProducts`


It is recommended to have documentation comments above, or right inside a function/class declaration.
This helps developers, users and even the author understand the purpose of a code snippet or API function in the future.

NOTE: If you want to stop this issue from getting raised on certain constructs (arrow functions, class expressions, methods etc.), consider using the skip_doc_coverage option under the analyzers.meta property in your .deepsource.toml file.
For example, the following configuration will silence this issue for class expressions and method definitions:

[analyzers.meta]
    skip_doc_coverage = ["class-expression", "method-definition"]

});
};

export const resolveDealSubscriptionItem = async (

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Documentation comment not found for arrow function `resolveDealSubscriptionItem`


It is recommended to have documentation comments above, or right inside a function/class declaration.
This helps developers, users and even the author understand the purpose of a code snippet or API function in the future.

NOTE: If you want to stop this issue from getting raised on certain constructs (arrow functions, class expressions, methods etc.), consider using the skip_doc_coverage option under the analyzers.meta property in your .deepsource.toml file.
For example, the following configuration will silence this issue for class expressions and method definitions:

[analyzers.meta]
    skip_doc_coverage = ["class-expression", "method-definition"]

};
};

export const publishPipelineOrderUpdated = async ({

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Documentation comment not found for arrow function `publishPipelineOrderUpdated`


It is recommended to have documentation comments above, or right inside a function/class declaration.
This helps developers, users and even the author understand the purpose of a code snippet or API function in the future.

NOTE: If you want to stop this issue from getting raised on certain constructs (arrow functions, class expressions, methods etc.), consider using the skip_doc_coverage option under the analyzers.meta property in your .deepsource.toml file.
For example, the following configuration will silence this issue for class expressions and method definitions:

[analyzers.meta]
    skip_doc_coverage = ["class-expression", "method-definition"]

@@ -32,7 +32,7 @@ export const DealCardDetails = ({
>
{visibleItems.map((item: any, index: number) => (

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unexpected any. Specify a different type


The any type can sometimes leak into your codebase. TypeScript compiler skips the type checking of the any typed variables, so it creates a potential safety hole, and source of bugs in your codebase. We recommend using unknown or never type variable.

{visibleItems.map((item: any, index: number) => (
<div
key={item._id || index}
key={`${item._id ?? 'item'}-${index}`}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Do not use Array index in keys


When rendering a list of items in React, it is necessary to pass a "key" prop.
This key is used by React to identify which items have changed, are added, or are removed and should be stable.
It is not recommended to use the index of an element as key because it doesn't uniquely identify the element.
When elements are added/removed from an array, the index of an element may change, which will result in unnecessary re-renders.

};
}

export const usePipelineChanged = (pipelineId?: string) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Documentation comment not found for arrow function `usePipelineChanged`


It is recommended to have documentation comments above, or right inside a function/class declaration.
This helps developers, users and even the author understand the purpose of a code snippet or API function in the future.

NOTE: If you want to stop this issue from getting raised on certain constructs (arrow functions, class expressions, methods etc.), consider using the skip_doc_coverage option under the analyzers.meta property in your .deepsource.toml file.
For example, the following configuration will silence this issue for class expressions and method definitions:

[analyzers.meta]
    skip_doc_coverage = ["class-expression", "method-definition"]

@sonarqubecloud

sonarqubecloud Bot commented Jul 8, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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.

1 participant

Morty Proxy This is a proxified and sanitized view of the page, visit original site.