Skip to content

fix: wire onsupportclick in setLinks() so Support item appears in header#501

Merged
mlehotskylf merged 3 commits into
mainfrom
fix/header-support-intercom
May 6, 2026
Merged

fix: wire onsupportclick in setLinks() so Support item appears in header#501
mlehotskylf merged 3 commits into
mainfrom
fix/header-support-intercom

Conversation

@mlehotskylf
Copy link
Copy Markdown
Contributor

@mlehotskylf mlehotskylf commented May 6, 2026

Summary

Fixes missing "Support" item in the LFX header help menu by calling setSupportClickHandler() from ngAfterViewInit instead of the service constructor.

Root cause

setSupportClickHandler() was being called from LfxHeaderService's constructor, which runs before Angular initializes the view. At that point getElementById('lfx-header-v2') returns null and the handler is never set.

The fix mirrors the pattern in easycla-landing-page, which calls setSupportClickHandler() from AppComponent.ngAfterViewInit() — the correct lifecycle hook for DOM-dependent setup.

Changes

  • app.component.ts: implement AfterViewInit, inject LfxHeaderService, call setSupportClickHandler() from ngAfterViewInit()
  • lfx-header.service.ts: restore setSupportClickHandler() as a standalone method (reverts the previous incorrect fix that placed onsupportclick inside setLinks())

Test plan

  • Open the app and click the ? help icon in the LFX header — verify "Support" item appears alongside "Docs" and "FAQ"
  • Click "Support" — verify Intercom chat widget opens

🤖 Generated with Claude Code

setSupportClickHandler() was a separate method called after setLinks(),
but lfx-header-v2 only renders the Support menu item when properties are
set together with the other header config. Moving onsupportclick into
setLinks() alongside element.links ensures it is applied at the right time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Walkthrough

AppComponent now implements AfterViewInit, injects LfxHeaderService and calls setSupportClickHandler() in ngAfterViewInit. LfxHeaderService had its setSupportClickHandler() method removed; constructor no longer calls it. setLinks() was hardened to guard for a missing lfx-header-v2 element and setCallBackUrl() is present.

Changes

Header API & Wiring

Layer / File(s) Summary
Initialization
src/app/shared/services/lfx-header.service.ts
Constructor no longer invokes setSupportClickHandler(); it still calls setUserInLFxHeader(), setLinks(), and setCallBackUrl().
Link wiring / defensive check
src/app/shared/services/lfx-header.service.ts
setLinks() now retrieves the header element and returns early if not found (if (!element) { return; }) before assigning element.links = this.links;.
Callback URL wiring
src/app/shared/services/lfx-header.service.ts
setCallBackUrl() sets lfHeaderEl.callbackurl = this.auth.auth0Options.callbackUrl when the element exists.
API removal
src/app/shared/services/lfx-header.service.ts
Removed the public method setSupportClickHandler(): void from LfxHeaderService.
Component lifecycle wiring
src/app/app.component.ts
AppComponent now implements AfterViewInit, injects LfxHeaderService and ActivatedRoute, and adds ngAfterViewInit() which calls this.lfxHeaderService.setSupportClickHandler().

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: wiring onsupportclick in setLinks() to make the Support item appear in the header, which is the core fix for the missing Support menu item.
Description check ✅ Passed The description is directly related to the changeset, providing clear context about the root cause (constructor timing issue), the fix approach (moving to ngAfterViewInit), and the affected files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/header-support-intercom

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

Copy link
Copy Markdown

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/shared/services/lfx-header.service.ts`:
- Around line 36-42: The code assigns properties to the DOM node with id
'lfx-header-v2' without checking for null; update the logic in
src/app/shared/services/lfx-header.service.ts (the block that gets
document.getElementById('lfx-header-v2')) to first guard that the element exists
(e.g. if (!element) return or skip setup) before calling element.links =
this.links and setting element.onsupportclick; keep the window.Intercom check
intact inside the guarded block so no assignments occur when the element is
absent.
- Around line 36-40: In setLinks() ensure you null-check and properly type the
custom element before dereferencing: retrieve the element with const element:
HTMLElement | null = document.getElementById('lfx-header-v2'); if (!element)
return; then assign links and onsupportclick on a correctly typed interface
(e.g., define LfxHeaderElement extending HTMLElement with links and
onsupportclick) or cast only where needed (element as any). Also replace direct
window.Intercom('show') with IntercomService.show() for consistency with
setCallBackUrl() and setUserInLFxHeader().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0910ab45-2304-44a6-9244-afa487e41c96

📥 Commits

Reviewing files that changed from the base of the PR and between 7d5a515 and 45d90ef.

📒 Files selected for processing (1)
  • src/app/shared/services/lfx-header.service.ts

Comment thread src/app/shared/services/lfx-header.service.ts
Comment thread src/app/shared/services/lfx-header.service.ts
Copy link
Copy Markdown

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 PR fixes the missing “Support” menu item in the lfx-header-v2 header by wiring the onsupportclick handler during the same configuration pass as the header’s links, and removing the now-redundant separate support handler method.

Changes:

  • Move onsupportclick assignment into setLinks() alongside element.links.
  • Remove setSupportClickHandler() and its invocation from the service constructor.

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

Comment thread src/app/shared/services/lfx-header.service.ts
Comment thread src/app/shared/services/lfx-header.service.ts
Comment thread src/app/shared/services/lfx-header.service.ts
…em appears

The previous fix moved onsupportclick into setLinks(), which was incorrect.
The real issue is timing: calling it from the service constructor or setLinks()
runs before the view is initialized. ngAfterViewInit is the correct lifecycle
hook for DOM-dependent setup — the same pattern used in easycla-landing-page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Copy link
Copy Markdown

@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

🧹 Nitpick comments (2)
src/app/app.component.ts (1)

4-4: ⚡ Quick win

Implement OnInit explicitly in the component contract.

ngOnInit() is present, but OnInit is not in the implements list. Add it (and keep lifecycle signatures explicitly typed).

Proposed refactor
-import { AfterViewInit, Component, OnDestroy } from '@angular/core';
+import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core';
 ...
-export class AppComponent implements AfterViewInit, OnDestroy {
+export class AppComponent implements OnInit, AfterViewInit, OnDestroy {

As per coding guidelines, "**/*.component.ts: Implement OnInit lifecycle hook for initialization logic" and "**/*.ts: Use proper TypeScript typing for all properties and methods".

Also applies to: 17-17

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/app.component.ts` at line 4, The component declares ngOnInit but does
not include OnInit in its implements list; update the AppComponent class
declaration to implement OnInit (in addition to AfterViewInit and OnDestroy) and
ensure the ngOnInit(): void signature remains explicitly typed so the lifecycle
contract is enforced (refer to AppComponent and its ngOnInit method to locate
the change).
src/app/shared/services/lfx-header.service.ts (1)

52-57: ⚡ Quick win

Tighten typing in callback URL wiring (any + implicit return type).

Use an explicit return type and a typed element shape here to match strict TypeScript patterns.

Proposed refactor
+interface LfxHeaderElement extends HTMLElement {
+  callbackurl?: string;
+}
+
-  setCallBackUrl() {
-    const lfHeaderEl: any = document.getElementById('lfx-header-v2');
+  setCallBackUrl(): void {
+    const lfHeaderEl = document.getElementById('lfx-header-v2') as LfxHeaderElement | null;
     if (lfHeaderEl) {
       lfHeaderEl.callbackurl = this.auth.auth0Options.callbackUrl;
     }
   }

As per coding guidelines, "**/*.ts: Use proper TypeScript typing for all properties and methods".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/shared/services/lfx-header.service.ts` around lines 52 - 57, The
method setCallBackUrl uses an untyped any and has an implicit return type;
change its signature to setCallBackUrl(): void and replace the any with a typed
element interface (e.g., declare interface LfxHeaderElement extends HTMLElement
{ callbackurl?: string } and cast document.getElementById('lfx-header-v2') to
LfxHeaderElement | null), then assign lfHeaderEl.callbackurl =
this.auth.auth0Options.callbackUrl after a null check; this tightens types
around setCallBackUrl, lfHeaderEl, and the callbackurl property.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/app.component.ts`:
- Around line 32-34: ngAfterViewInit currently calls
this.lfxHeaderService.setSupportClickHandler() immediately which can race with
the async registration of the custom element 'lfx-header-v2' (see mountHeader);
change the call to wait for the element to be defined by using
customElements.whenDefined('lfx-header-v2').then(() =>
this.lfxHeaderService.setSupportClickHandler()) so the LfxHeaderService's
setSupportClickHandler() runs only after the custom element is registered and
avoids the early-return path that prevents support linking.

---

Nitpick comments:
In `@src/app/app.component.ts`:
- Line 4: The component declares ngOnInit but does not include OnInit in its
implements list; update the AppComponent class declaration to implement OnInit
(in addition to AfterViewInit and OnDestroy) and ensure the ngOnInit(): void
signature remains explicitly typed so the lifecycle contract is enforced (refer
to AppComponent and its ngOnInit method to locate the change).

In `@src/app/shared/services/lfx-header.service.ts`:
- Around line 52-57: The method setCallBackUrl uses an untyped any and has an
implicit return type; change its signature to setCallBackUrl(): void and replace
the any with a typed element interface (e.g., declare interface LfxHeaderElement
extends HTMLElement { callbackurl?: string } and cast
document.getElementById('lfx-header-v2') to LfxHeaderElement | null), then
assign lfHeaderEl.callbackurl = this.auth.auth0Options.callbackUrl after a null
check; this tightens types around setCallBackUrl, lfHeaderEl, and the
callbackurl property.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8d2f6e2f-91c6-42fc-b563-2f79ac5de9d0

📥 Commits

Reviewing files that changed from the base of the PR and between 45d90ef and 01f6007.

📒 Files selected for processing (2)
  • src/app/app.component.ts
  • src/app/shared/services/lfx-header.service.ts

Comment thread src/app/app.component.ts
Copy link
Copy Markdown

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

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

Comment thread src/app/app.component.ts
Comment thread src/app/shared/services/lfx-header.service.ts
Comment thread src/app/app.component.ts
setCallBackUrl already guards against a missing lfx-header-v2 element;
setLinks was missing the same check, causing a potential null dereference
if the element is not yet in the DOM when the service is constructed.

Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
@mlehotskylf
Copy link
Copy Markdown
Contributor Author

Review Feedback Addressed

Commit: ef2a28e

Changes Made

  • lfx-header.service.ts:37: Added null guard before element.links assignment — setCallBackUrl() already had this guard; setLinks() was missing it (per coderabbitai, copilot-pull-request-reviewer)

Declined

  • lfx-header.service.ts — Window.Intercom type declaration: style preference, one-liner callback doesn't warrant a declaration (flagged by coderabbitai)
  • lfx-header.service.ts — Use IntercomService instead of window.Intercom: false positive — direct window.Intercom is the established LFX pattern for header element callbacks (flagged by copilot-pull-request-reviewer)
  • lfx-header.service.ts — Add unit tests: out of scope, no tests exist for this service (flagged by copilot-pull-request-reviewer)
  • lfx-header.service.ts — Constructor timing: false positive — lfx-header-v2 is a static element, getElementById works from constructor; null guard added covers the edge case (flagged by copilot-pull-request-reviewer)
  • app.component.ts — ngAfterViewInit too early: false positive — onsupportclick is a callback set on the element property, not called at boot time; matches the easycla-landing-page pattern (flagged by coderabbitai, copilot-pull-request-reviewer)
  • app.component.ts: void return type on ngAfterViewInit: style preference (flagged by copilot-pull-request-reviewer)

Threads Resolved

9 of 9 unresolved threads addressed.

Copy link
Copy Markdown
Member

@lukaszgryglicki lukaszgryglicki left a comment

Choose a reason for hiding this comment

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

/lgtm

Copy link
Copy Markdown

@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

🧹 Nitpick comments (1)
src/app/shared/services/lfx-header.service.ts (1)

55-60: ⚡ Quick win

Use strict typing in setCallBackUrl() (void return + typed element).

Line 55 and Line 56 still use implicit return type and any, which weakens strict-mode guarantees.

Suggested fix
+interface LfxHeaderElement extends HTMLElement {
+  callbackurl?: string;
+}
+
-  setCallBackUrl() {
-    const lfHeaderEl: any = document.getElementById('lfx-header-v2');
+  setCallBackUrl(): void {
+    const lfHeaderEl = document.getElementById('lfx-header-v2') as LfxHeaderElement | null;
     if (lfHeaderEl) {
       lfHeaderEl.callbackurl = this.auth.auth0Options.callbackUrl;
     }
   }

As per coding guidelines, **/*.ts: "Use TypeScript strict mode patterns" and "Use proper TypeScript typing for all properties and methods".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/shared/services/lfx-header.service.ts` around lines 55 - 60,
setCallBackUrl currently uses implicit any and no return type; change its
signature to return void and strongly type the DOM element (e.g., const
lfHeaderEl = document.getElementById('lfx-header-v2') as HTMLElement | null or a
more specific element interface) instead of any, check for null, and assign the
callback using the typed property (or cast to the custom element interface if
the element exposes callbackurl). Reference symbols: setCallBackUrl, lfHeaderEl,
this.auth.auth0Options.callbackUrl.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/shared/services/lfx-header.service.ts`:
- Around line 37-40: The constructor of LfxHeaderService wires DOM elements too
early (setLinks and setCallBackUrl) causing silent failures when `#lfx-header-v2`
mounts later; move those calls out of the constructor and into a new
initializeHeaderBindings() method that performs the same DOM wiring (invoking
setLinks(), setCallBackUrl(), and setSupportClickHandler() safely) and call
initializeHeaderBindings() from AppComponent.ngAfterViewInit() so bindings occur
after the header mounts; also fix TypeScript strict types by replacing any with
explicit types for links (e.g., Array<Link> or appropriate interface),
lfHeaderEl (HTMLElement | null), and add explicit return types to setLinks() and
setCallBackUrl() to satisfy strict typing.

---

Nitpick comments:
In `@src/app/shared/services/lfx-header.service.ts`:
- Around line 55-60: setCallBackUrl currently uses implicit any and no return
type; change its signature to return void and strongly type the DOM element
(e.g., const lfHeaderEl = document.getElementById('lfx-header-v2') as
HTMLElement | null or a more specific element interface) instead of any, check
for null, and assign the callback using the typed property (or cast to the
custom element interface if the element exposes callbackurl). Reference symbols:
setCallBackUrl, lfHeaderEl, this.auth.auth0Options.callbackUrl.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 467d7f1a-f4ab-4072-b719-aa87b45684a5

📥 Commits

Reviewing files that changed from the base of the PR and between 01f6007 and ef2a28e.

📒 Files selected for processing (1)
  • src/app/shared/services/lfx-header.service.ts

Comment thread src/app/shared/services/lfx-header.service.ts
@mlehotskylf mlehotskylf merged commit 8ecc59b into main May 6, 2026
13 checks passed
@mlehotskylf mlehotskylf deleted the fix/header-support-intercom branch May 6, 2026 07:53
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.

3 participants