Skip to content

Conversation

thakaresakshi121
Copy link
Contributor

@thakaresakshi121 thakaresakshi121 commented Aug 25, 2025

What do you want to achieve?

  • fixed position of answer feedback icons

PR Checklist

  • I have tested it locally and all functionalities are working fine.
  • I have compared it with mocks and all design elements are the same.
  • I have tested it in IE Browser.

How was the code tested?

What new thing you came across while writing this code?

In case you fixed a bug then please describe the root cause of it?

Screenshot

NOTE: Make sure you're comparing your branch with the correct base branch

Summary by CodeRabbit

  • Improvements

    • Enhanced per-message control of feedback buttons and containers for clearer, more predictable visibility.
    • Delayed feedback UI positioning to allow rendering completion, improving placement accuracy.
    • Streamlined UI transitions when submitting feedback (show/hide states update more reliably).
  • Bug Fixes

    • Feedback listeners now attach only when helpful buttons are shown, preventing unnecessary event handling.
    • Resolved issues where feedback UI could appear at the wrong time or in the wrong state.

Copy link

Warnings
⚠️ Please add the JIRA issue key to the PR title (e.g. FW-123)
Messages
📖 New Files in this PR: - 0

Generated by 🚫 dangerJS against 782a443

Copy link
Contributor

coderabbitai bot commented Aug 25, 2025

Walkthrough

Introduces per-message visibility control and delayed positioning for the feedback UI in answer-feedback-service, and conditionally attaches feedback listeners in mck-sidebox based on showHelpfulButtons computed via handleFeedbackBtnVisible.

Changes

Cohort / File(s) Summary
Feedback UI logic and positioning
webplugin/js/app/components/answer-feedback-service.js
Adds per-message selectors; toggles visibility via kommunicateCommons.modifyClassList; hides feedback before positioning; delays positioning (500ms); on setFeedback, shows container, hides sticker, and triggers helpFulOnClick/notHelpFulOnClick accordingly.
Conditional listener attachment in sidebox
webplugin/js/app/mck-sidebox-1.0.js
Guards answerFeedbackService.attachEventListeners(...) behind showHelpfulButtons computed via handleFeedbackBtnVisible; attaches listeners only when buttons should be shown.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant SB as Sidebox (mck-sidebox)
  participant AFS as AnswerFeedbackService
  participant DOM as DOM/UI

  SB->>AFS: handleFeedbackBtnVisible(msg, floatWhere, contact)
  AFS-->>SB: showHelpfulButtons (bool)
  alt showHelpfulButtons == true
    SB->>AFS: attachEventListeners(msg,...)
    AFS->>DOM: Hide feedback container (vis->n-vis)
    AFS->>DOM: Set per-message selectors
    AFS->>AFS: setTimeout(500ms) position
    AFS->>DOM: Compute & apply position
  else
    SB-->>SB: Skip attaching listeners
  end
Loading
sequenceDiagram
  autonumber
  actor U as User
  participant AFS as AnswerFeedbackService
  participant DOM as DOM/UI
  participant H as Handlers

  U->>AFS: Select feedback (helpful/not)
  AFS->>DOM: Show container (n-vis->vis), hide sticker (vis->n-vis)
  alt helpful
    AFS->>H: helpFulOnClick(msg,...)
  else not helpful
    AFS->>H: notHelpFulOnClick(msg,...)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • devashishmamgain

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.1.2)
webplugin/js/app/mck-sidebox-1.0.js

The --json option is unstable/experimental and its output might change between patches/minor releases.
{"summary":{"changed":0,"unchanged":1,"matches":0,"duration":{"secs":11,"nanos":68166497},"scannerDuration":{"secs":0,"nanos":6408715},"errors":128,"warnings":0,"skipped":0,"suggestedFixesSkipped":0,"diagnosticsNotPrinted":0},"diagnostics":[{"category":"lint/suspicious/noDuplicateObjectKeys","severity":"error","description":"This property is later overwritten by an object member with the same name.","message":[{"elements":[],"content":"This property is later overwritten by an object member with the same name."}],"advices":{"advices":[{"log":["info",[{"elements":[],"content":"Overwritten with this property."}]]},{"frame":{"path":null,"span":[3238,3259],"sourceCode":"var MCK_GROUP_MAP = [];\nvar MCK_CLIENT_GROUP_MAP = [];\nvar MCK_EVENT_HISTORY = [];\nvar KM_PROGRESS_METER_RADIUS = 54;\nvar KM_PROGRESS_METER_CIRCUMFERENCE = 2 * Math.PI * KM_PROGRESS_METER_RADIUS;\nvar count = 0;\nvar is

... [truncated 99999690 characters] ...

g-12").after(elem);\n } else {\n console.log('msg.contentType === 23 && metadata.msg_type === BUTTON');\n Biome encountered an unexpected error

This is a bug in Biome, not an error in your code, and we would appreciate it if you could report it to https://github.com/biomejs/biome/issues/ along with the following information to help us fixing the issue.

When opening the issue, please provide a minimal reproduction, or identify and share the file/code that triggers it. Without a way to reproduce the error, the error can't be fixed:

Source Location: crates/biome_console/src/lib.rs:151:14
Thread Name: main
Message: called Result::unwrap() on an Err value: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" }

🔧 ast-grep (0.38.6)
webplugin/js/app/mck-sidebox-1.0.js
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ans-feedback-fix

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
webplugin/js/app/components/answer-feedback-service.js (1)

89-96: Unsafe backward traversal can throw when previousSibling is null

If metadata.KM_CONTEXT_QUESTION is falsy and there’s no right-aligned user message in the chain, question becomes undefined and question = question.previousSibling will throw. Guard the loop and use optional chaining when reading question.msg.

Apply this diff:

-        // find the user message
-        while (!metadata.KM_CONTEXT_QUESTION && question?.floatWhere !== 'mck-msg-right') {
-            question = question.previousSibling;
-        }
+        // find the user message (right-aligned); stop if chain ends
+        if (!metadata.KM_CONTEXT_QUESTION) {
+            while (question && question.floatWhere !== 'mck-msg-right') {
+                question = question.previousSibling;
+            }
+        }
@@
-        const questionText = question.msg.message;
+        const questionText = question?.msg?.message;
🧹 Nitpick comments (9)
webplugin/js/app/mck-sidebox-1.0.js (4)

8452-8456: Guard may misfire if showHelpfulButtons is a string like 'false'

Elsewhere in this file we compare metadata flags to the string 'true'. If showHelpfulButtons ever becomes a string, 'false' is truthy and will still attach listeners. Normalize to a strict boolean at source, or harden this guard.

Apply one of the following diffs:

Option A — minimal hardening at the call site:

-                showHelpfulButtons &&
-                    answerFeedbackService.attachEventListeners({
+                (showHelpfulButtons === true || String(showHelpfulButtons).toLowerCase() === 'true') &&
+                    answerFeedbackService.attachEventListeners({
                         msg,
                         assigneeKey: groupAssigneeKey,
                     });

Option B — preferred: ensure boolean earlier where showHelpfulButtons is computed (no change needed here). If you want a local readability tweak too, see next comment’s if-statement suggestion.


8452-8456: Prefer explicit if over short-circuit for side effects

Short-circuit with && hides control flow and complicates later logging/metrics. An explicit block reads clearer and is easier to extend.

Apply:

-                showHelpfulButtons &&
-                    answerFeedbackService.attachEventListeners({
-                        msg,
-                        assigneeKey: groupAssigneeKey,
-                    });
+                if (showHelpfulButtons) {
+                    answerFeedbackService.attachEventListeners({
+                        msg,
+                        assigneeKey: groupAssigneeKey,
+                    });
+                }

8452-8456: Ensure idempotent listener attachment to avoid duplicates across re-renders

This path can execute multiple times per message (e.g., message updates, DOM reflows). Verify answerFeedbackService.attachEventListeners is idempotent (e.g., checks a data-flag or removes existing listeners) to prevent duplicated handlers.

If not already handled inside the service, consider marking the container once wired:

  • Inside the service: set el.dataset.kmFeedbackWired = '1' and early-return if already set.
  • Or use { once: true } where applicable with addEventListener.
    Would you like a patch in answer-feedback-service.js to add this guard?

8452-8456: Wrap listener wiring in try/catch to isolate UI failures

If DOM nodes are missing or change during delayed positioning, attachEventListeners could throw and block the rest of message rendering.

Apply:

-                if (showHelpfulButtons) {
-                    answerFeedbackService.attachEventListeners({
-                        msg,
-                        assigneeKey: groupAssigneeKey,
-                    });
-                }
+                if (showHelpfulButtons) {
+                    try {
+                        answerFeedbackService.attachEventListeners({
+                            msg,
+                            assigneeKey: groupAssigneeKey,
+                        });
+                    } catch (e) {
+                        // Replace with project logger if available
+                        console.error('Failed to attach answer feedback listeners', e, { messageKey: msg?.key });
+                    }
+                }
webplugin/js/app/components/answer-feedback-service.js (5)

164-172: Redundant hide and premature DOM ops inside handleFeedbackPositioning

You’re hiding the container here and again at attach time. The double swap increases flicker risk and does work before confirming DOM nodes exist. Prefer hiding once (at attach), then only compute and set position here.

Apply this diff to drop the extra hide call:

-        const feedbackContainerSelector = `[data-msgKey="${msgKey}"] .km-answer-feedback`;
-        kommunicateCommons.modifyClassList(
-            {
-                class: [feedbackContainerSelector],
-            },
-            'vis',
-            'n-vis',
-            true
-        );

If you want to keep a defensive hide, move it below the null checks (after Line 178) and only when feedbackElement exists.


208-211: Avoid fixed 500 ms delay; use layout-driven scheduling

A hardcoded 500 ms can be flaky across devices and render paths. Prefer running positioning on the next paint (or when the element’s dimensions stabilize) via requestAnimationFrame or a ResizeObserver.

Minimal change:

-        setTimeout(() => {
-            this.handleFeedbackPositioning(msg.key);
-        }, 500);
+        requestAnimationFrame(() => {
+            this.handleFeedbackPositioning(msg.key);
+        });

More robust (optional): attach a one-shot ResizeObserver to feedbackElement and run handleFeedbackPositioning when its box has a non-zero width, then disconnect.


66-73: Missed in-memory metadata update when metadata was undefined

When result.code == 'SUCCESS' and metadata was previously undefined, you update a local object but don’t persist it back to the msg. Persist the merged metadata to keep UI state consistent without relying on a subsequent fetch.

Apply this diff:

-                if (result.code == 'SUCCESS') {
-                    const msgMeta = this.msgMap[data.msg.key]?.msg?.metadata || {};
-                    msgMeta.KM_ANSWER_FEEDBACK = feedback;
+                if (result.code == 'SUCCESS') {
+                    const msgObj = this.msgMap[data.msg.key];
+                    if (msgObj?.msg) {
+                        msgObj.msg.metadata = {
+                            ...(msgObj.msg.metadata || {}),
+                            KM_ANSWER_FEEDBACK: feedback,
+                        };
+                    }

191-196: Null-guard queried elements before adding listeners

If the container renders late or conditionally (per showHelpfulButtons), these queries can return null, and addEventListener will throw. Guard and bail out gracefully.

Example guard (outside diff scope):

const stickySticker = msgContainer?.querySelector('.mck-msg-feedback-sticker');
const helpfulButton = msgContainer?.querySelector('.answer-feedback-helpful');
const notHelpfulButton = msgContainer?.querySelector('.answer-feedback-not-helpful');

if (!stickySticker || !helpfulButton || !notHelpfulButton) {
  // Element(s) not yet in DOM; consider retrying once via rAF or a short timeout.
  return;
}

If you expect delayed render, consider moving listener binding into the same rAF used for positioning or using event delegation from msgContainer.


181-183: Magic numbers for positioning; consider CSS clamp or computed widths

left = msgBoxWidth + 40 with a 120 px floor is brittle across themes and zoom levels.

Consider expressing this in CSS with clamp(), or compute against the actual sticker/container widths. Example:

const minLeft = 120;
const offset = 40;
const left = Math.max(minLeft, msgBox.offsetWidth + offset);
feedbackElement.style.left = `${left}px`;

Or move to CSS: left: clamp(120px, calc(var(--msg-box-width) + 40px), 100vw).

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 55711db and 782a443.

📒 Files selected for processing (2)
  • webplugin/js/app/components/answer-feedback-service.js (2 hunks)
  • webplugin/js/app/mck-sidebox-1.0.js (1 hunks)
🔇 Additional comments (2)
webplugin/js/app/mck-sidebox-1.0.js (1)

8452-8456: Nice: conditionalizing listener wiring reduces unnecessary work

Attaching listeners only when the UI is intended to show is a good perf/readability win and aligns with the new per-message visibility logic in the service.

webplugin/js/app/components/answer-feedback-service.js (1)

217-224: Verify intended UX: setFeedback currently shows container and hides sticker

Typical flow is: after choosing feedback, hide the container and show the sticker with the selected icon. Your current swaps do the opposite. If that’s not intended, invert the class swaps below.

Proposed diff if you want “container -> sticker after selection”:

-            kommunicateCommons.modifyClassList(
-                {
-                    class: [feedbackContainerSelector],
-                },
-                'n-vis',
-                'vis',
-                true
-            );
+            // hide container after selection
+            kommunicateCommons.modifyClassList(
+                {
+                    class: [feedbackContainerSelector],
+                },
+                'vis',
+                'n-vis',
+                true
+            );
@@
-            kommunicateCommons.modifyClassList(
-                {
-                    class: [stickyStickerSelector],
-                },
-                'vis',
-                'n-vis',
-                true
-            );
+            // show sticker with chosen icon
+            kommunicateCommons.modifyClassList(
+                {
+                    class: [stickyStickerSelector],
+                },
+                'n-vis',
+                'vis',
+                true
+            );

If the current behavior is by design, ignore this.

Also applies to: 226-233

Comment on lines +197 to +205
// Initially hide the feedback container
kommunicateCommons.modifyClassList(
{
class: [feedbackContainerSelector],
},
'n-vis',
'vis',
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

Incorrect initial visibility toggle: this shows the container instead of hiding it

The comment says “Initially hide the feedback container,” but passing ('n-vis', 'vis') to modifyClassList removes n-vis and adds vis, which makes it visible. Invert the args to actually hide it.

Apply this diff:

-        // Initially hide the feedback container
-        kommunicateCommons.modifyClassList(
-            {
-                class: [feedbackContainerSelector],
-            },
-            'n-vis',
-            'vis',
-            true
-        );
+        // Initially hide the feedback container
+        kommunicateCommons.modifyClassList(
+            {
+                class: [feedbackContainerSelector],
+            },
+            'vis',
+            'n-vis',
+            true
+        );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Initially hide the feedback container
kommunicateCommons.modifyClassList(
{
class: [feedbackContainerSelector],
},
'n-vis',
'vis',
true
);
// Initially hide the feedback container
kommunicateCommons.modifyClassList(
{
class: [feedbackContainerSelector],
},
'vis',
'n-vis',
true
);
🤖 Prompt for AI Agents
In webplugin/js/app/components/answer-feedback-service.js around lines 197 to
205, the call to kommunicateCommons.modifyClassList currently passes ('n-vis',
'vis') which removes 'n-vis' and adds 'vis' (making the container visible)
contrary to the intent to hide it; swap the class arguments so the call removes
'vis' and adds 'n-vis' (e.g., pass 'vis' then 'n-vis' with the same boolean
flag) to actually hide the feedback container.

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.

2 participants