-
Notifications
You must be signed in to change notification settings - Fork 0
feat(ui): implement organization search with typeahead functionality #102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add OrganizationSearchComponent with search and manual input modes - Integrate organization API backend with debounced search via microservice proxy - Update member and registrant forms to use new search component - Enhance autocomplete component with template projection and appendTo - Add URL validation utilities for domain normalization - Create organization service, controller, and interfaces using microservice proxy pattern - Add comprehensive data-testid attributes for E2E testing References: LFXV2-575, LFXV2-576, LFXV2-577 Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <[email protected]>
|
Note Other AI code review bot(s) detectedCodeRabbit 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. WalkthroughAdds an organization search UI with autocomplete and manual-entry; replaces direct org name/URL inputs in member and registrant forms with OrganizationSearchComponent; adds client/server org search services, controller/routes, shared interfaces and URL utilities, autocomplete enhancements, and a normalize URL pipe. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as User
participant MF as Member/Registrant Form
participant OSC as OrganizationSearchComponent
participant AC as Autocomplete
participant FE as Client OrgService
participant API as /api/organizations
participant CTRL as OrgController
participant SVC as Server OrgService
participant MS as LFX_V2_SERVICE
U->>OSC: Type query
OSC->>AC: Set autocomplete value
AC-->>OSC: complete event (debounced)
OSC->>FE: searchOrganizations(query)
FE->>API: GET /organizations/search?query=...
API->>CTRL: route
CTRL->>SVC: searchOrganizations(req, query)
SVC->>MS: GET /query/orgs/suggest?q=...
MS-->>SVC: suggestions[]
SVC-->>CTRL: suggestions[]
CTRL-->>API: JSON { suggestions }
API-->>FE: suggestions[]
FE-->>OSC: suggestions[]
OSC-->>AC: render suggestions
U->>AC: Select organization
AC-->>OSC: select event
note over OSC: Update parent form controls (nameControl, domainControl normalized)
OSC-->>MF: Emit onOrganizationSelect (optional)
alt Manual mode
U->>OSC: Switch to manual
OSC->>MF: Populate name control from current search
note over OSC: Manual fields rendered
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Comment |
There was a problem hiding this 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 implements an organization search component with typeahead functionality, allowing users to search for organizations via a microservice API and fall back to manual entry when needed.
- Organization search component with debounced API integration and manual entry fallback
- Backend API endpoints for organization search using microservice proxy
- URL validation utilities for domain normalization and validation
Reviewed Changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shared/src/utils/url.utils.ts | Added URL validation and normalization utility functions |
| packages/shared/src/interfaces/organization.interface.ts | Defined organization search interfaces |
| packages/shared/src/interfaces/index.ts | Exported organization interfaces |
| apps/lfx-one/src/server/services/organization.service.ts | Backend service for organization search via microservice proxy |
| apps/lfx-one/src/server/server.ts | Added organizations router to server |
| apps/lfx-one/src/server/routes/organizations.route.ts | API route for organization search endpoint |
| apps/lfx-one/src/server/controllers/organization.controller.ts | Controller handling organization search requests |
| apps/lfx-one/src/app/shared/services/organization.service.ts | Frontend service for organization API calls |
| apps/lfx-one/src/app/shared/pipes/normalize-url.pipe.ts | Angular pipe for URL normalization |
| apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.ts | Main organization search component with typeahead |
| apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.html | Template for organization search component |
| apps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.ts | Enhanced autocomplete with template projection |
| apps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.html | Added empty template support |
| apps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.ts | Updated to use organization search |
| apps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.html | Replaced input with organization search component |
| apps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.ts | Updated to use organization search and removed custom validation |
| apps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.html | Replaced organization fields with search component |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
✅ E2E Tests PassedBrowser: chromium All E2E tests passed successfully. Test Configuration
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.ts (1)
62-66: Potential NPE: committee() may be undefined before accessing uid.Directly accessing this.committee().uid can throw. Use optional chaining.
- const committeeId = this.committee().uid; + const committeeId = this.committee()?.uid;
🧹 Nitpick comments (8)
apps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.ts (1)
32-32: NarrowappendTotypingPrimeNG accepts
string | HTMLElement. Prefer a precise type for better DX.Apply this diff:
- public appendTo = input<any>(undefined); + public appendTo = input<string | HTMLElement | null>(null);apps/lfx-one/src/server/server.ts (1)
22-23: Route wiring looks correct; consider resiliency controlsMounting
/api/organizationsafter auth is correct.Ensure the downstream org-suggest call uses:
- Per-request timeout and abort (e.g., 2–5s)
- Bounded retries with jittered backoff
- Circuit breaker or cache fallback for transient outages
If not already in
OrganizationService, add these to avoid request thread starvation during upstream latency spikes.Also applies to: 203-204
apps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.html (1)
68-77: Associate label with the actual input for a11y
for="org_name"won’t bind to the inner input generated bylfx-organization-search. Consider adding aninputIdinput to the search component that forwards to its internal input, then setforto that id.apps/lfx-one/src/server/controllers/organization.controller.ts (1)
14-15: Inject the service for testability (avoid hard new).Direct instantiation makes the controller harder to unit test/mocks. Prefer constructor injection with a sensible default.
-export class OrganizationController { - private organizationService: OrganizationService = new OrganizationService(); +export class OrganizationController { + private readonly organizationService: OrganizationService; + + public constructor(organizationService?: OrganizationService) { + this.organizationService = organizationService ?? new OrganizationService(); + }apps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.html (1)
48-61: Optional: Set appendTo to avoid overlay clipping.If OrganizationSearchComponent forwards appendTo to the underlying dropdown, consider appendTo="body" to prevent z-index/overflow issues in dialogs.
- panelStyleClass="text-sm w-full" + panelStyleClass="text-sm w-full" + appendTo="body"apps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.ts (2)
95-101: Normalize organization URL before submit.Apply normalizeToUrl() so servers receive a normalized URL (https prefix, etc.). It returns null for invalid inputs.
- website: formValue.organization_url || null, + website: normalizeToUrl(formValue.organization_url) || null,Add the import (outside this hunk):
// update existing import import { formatDateToISOString, parseISODateString, normalizeToUrl } from '@lfx-one/shared/utils';
157-173: Optional: adopt typed reactive forms.Defining a FormGroup with typed controls will improve safety over FormControl access and reduce runtime casts.
apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.ts (1)
73-85: Sync effect doesn’t clear the inner field when parent name is cleared.Add an else branch to reset
organizationSearchso modes stay in sync.if (parentForm && nameControlName) { const nameControlValue = parentForm.get(nameControlName)?.value; - if (nameControlValue && nameControlValue.trim()) { - this.organizationForm.get('organizationSearch')?.setValue(nameControlValue, { emitEvent: false }); - } + const searchCtrl = this.organizationForm.get('organizationSearch'); + if (nameControlValue && nameControlValue.trim()) { + searchCtrl?.setValue(nameControlValue, { emitEvent: false }); + } else { + searchCtrl?.setValue('', { emitEvent: false }); + } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (17)
apps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.html(1 hunks)apps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.ts(3 hunks)apps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.html(1 hunks)apps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.ts(1 hunks)apps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.html(1 hunks)apps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.ts(2 hunks)apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.html(1 hunks)apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.ts(1 hunks)apps/lfx-one/src/app/shared/pipes/normalize-url.pipe.ts(1 hunks)apps/lfx-one/src/app/shared/services/organization.service.ts(1 hunks)apps/lfx-one/src/server/controllers/organization.controller.ts(1 hunks)apps/lfx-one/src/server/routes/organizations.route.ts(1 hunks)apps/lfx-one/src/server/server.ts(2 hunks)apps/lfx-one/src/server/services/organization.service.ts(1 hunks)packages/shared/src/interfaces/index.ts(1 hunks)packages/shared/src/interfaces/organization.interface.ts(1 hunks)packages/shared/src/utils/url.utils.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript interfaces instead of union types for better maintainability
When defining PrimeNG-related types, reference the official PrimeNG component interfaces
Files:
apps/lfx-one/src/server/server.tsapps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.tsapps/lfx-one/src/server/services/organization.service.tspackages/shared/src/interfaces/organization.interface.tspackages/shared/src/interfaces/index.tsapps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.tsapps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.tsapps/lfx-one/src/app/shared/pipes/normalize-url.pipe.tsapps/lfx-one/src/server/routes/organizations.route.tsapps/lfx-one/src/server/controllers/organization.controller.tsapps/lfx-one/src/app/shared/services/organization.service.tsapps/lfx-one/src/app/shared/components/organization-search/organization-search.component.tspackages/shared/src/utils/url.utils.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}
📄 CodeRabbit inference engine (CLAUDE.md)
Include required license headers on all source files
Files:
apps/lfx-one/src/server/server.tsapps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.tsapps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.htmlapps/lfx-one/src/server/services/organization.service.tspackages/shared/src/interfaces/organization.interface.tspackages/shared/src/interfaces/index.tsapps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.tsapps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.tsapps/lfx-one/src/app/shared/pipes/normalize-url.pipe.tsapps/lfx-one/src/app/shared/components/organization-search/organization-search.component.htmlapps/lfx-one/src/server/routes/organizations.route.tsapps/lfx-one/src/server/controllers/organization.controller.tsapps/lfx-one/src/app/shared/services/organization.service.tsapps/lfx-one/src/app/shared/components/organization-search/organization-search.component.tspackages/shared/src/utils/url.utils.tsapps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.htmlapps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.html
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not nest ternary expressions
Files:
apps/lfx-one/src/server/server.tsapps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.tsapps/lfx-one/src/server/services/organization.service.tspackages/shared/src/interfaces/organization.interface.tspackages/shared/src/interfaces/index.tsapps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.tsapps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.tsapps/lfx-one/src/app/shared/pipes/normalize-url.pipe.tsapps/lfx-one/src/server/routes/organizations.route.tsapps/lfx-one/src/server/controllers/organization.controller.tsapps/lfx-one/src/app/shared/services/organization.service.tsapps/lfx-one/src/app/shared/components/organization-search/organization-search.component.tspackages/shared/src/utils/url.utils.ts
apps/lfx-one/src/**/*.html
📄 CodeRabbit inference engine (CLAUDE.md)
apps/lfx-one/src/**/*.html: Always add data-testid attributes when creating new Angular components for reliable test targeting
Use data-testid naming convention [section]-[component]-[element]
Files:
apps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.htmlapps/lfx-one/src/app/shared/components/organization-search/organization-search.component.htmlapps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.htmlapps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.html
packages/shared/src/interfaces/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Place all TypeScript interfaces in the shared package at packages/shared/src/interfaces
Files:
packages/shared/src/interfaces/organization.interface.tspackages/shared/src/interfaces/index.ts
**/index.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Do not use barrel exports; always use direct imports for standalone components
Files:
packages/shared/src/interfaces/index.ts
🧠 Learnings (1)
📚 Learning: 2025-09-16T03:32:46.518Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-16T03:32:46.518Z
Learning: Applies to packages/shared/src/interfaces/**/*.ts : Place all TypeScript interfaces in the shared package at packages/shared/src/interfaces
Applied to files:
packages/shared/src/interfaces/index.ts
🧬 Code graph analysis (8)
apps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.ts (1)
apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.ts (1)
Component(16-161)
apps/lfx-one/src/server/services/organization.service.ts (1)
packages/shared/src/interfaces/organization.interface.ts (2)
OrganizationSuggestion(8-13)OrganizationSuggestionsResponse(19-22)
apps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.ts (1)
apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.ts (1)
Component(16-161)
apps/lfx-one/src/app/shared/pipes/normalize-url.pipe.ts (1)
packages/shared/src/utils/url.utils.ts (1)
normalizeToUrl(152-171)
apps/lfx-one/src/server/routes/organizations.route.ts (1)
apps/lfx-one/src/server/controllers/organization.controller.ts (1)
OrganizationController(13-59)
apps/lfx-one/src/server/controllers/organization.controller.ts (1)
apps/lfx-one/src/server/services/organization.service.ts (1)
OrganizationService(9-32)
apps/lfx-one/src/app/shared/services/organization.service.ts (2)
apps/lfx-one/src/server/services/organization.service.ts (1)
OrganizationService(9-32)packages/shared/src/interfaces/organization.interface.ts (1)
OrganizationSuggestionsResponse(19-22)
apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.ts (5)
apps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.ts (1)
Component(19-174)apps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.ts (1)
Component(12-22)apps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.ts (1)
Component(9-45)packages/shared/src/interfaces/organization.interface.ts (1)
OrganizationSuggestion(8-13)packages/shared/src/utils/url.utils.ts (1)
normalizeToUrl(152-171)
🔇 Additional comments (10)
apps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.ts (1)
15-16: Confirm projected empty template is actually renderedYou capture
#emptyvia@ContentChild('empty'), but ensure the component template renders it inside PrimeNG with something like:
<ng-template pTemplate="empty"><ng-container *ngTemplateOutlet="emptyTemplate"></ng-container></ng-template>apps/lfx-one/src/app/modules/project/meetings/components/registrant-form/registrant-form.component.ts (1)
15-16: LGTM: proper integration of OrganizationSearchComponentStandalone import is correct and minimal; no logic changes.
packages/shared/src/interfaces/index.ts (1)
13-15: Interface export added correctlyExporting
organization.interfacehere aligns with how this index already aggregates interfaces.Note: Our guideline says avoid barrel exports in index.ts for standalone components. This file aggregates interfaces (not components). Confirm this is within team policy, else we can remove index barrels and use direct imports.
apps/lfx-one/src/server/routes/organizations.route.ts (1)
1-15: LGTM: minimal, clear routerLicense header present; binding with
.bindavoidsthisloss.apps/lfx-one/src/app/shared/pipes/normalize-url.pipe.ts (1)
7-24: LGTM: simple, safe wrapper around normalizeToUrlReturns null for falsy input; license header present.
apps/lfx-one/src/server/controllers/organization.controller.ts (1)
51-57: Confirm ServiceValidationError -> HTTP 400 mapping.Assuming your error middleware maps ServiceValidationError to a 400. Please verify to avoid returning 500 on invalid input.
apps/lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.html (1)
48-61: Verify data-testid propagation.You pass dataTestId; ensure the component renders data-testid attributes on its focusable input and panel elements following the [section]-[component]-[element] convention.
packages/shared/src/interfaces/organization.interface.ts (1)
8-22: LGTM — re-exported from interfaces barrel. Confirmed: packages/shared/src/interfaces/index.ts containsexport * from './organization.interface';(line 14).apps/lfx-one/src/server/services/organization.service.ts (1)
22-31: LGTM — timeouts enforced (30s via AbortSignal.timeout in ApiClientService)ApiClientService defaults timeout to 30000ms, sets requestInit.signal = AbortSignal.timeout(this.config.timeout) and maps AbortError to a 408 MicroserviceError; MicroserviceProxyService delegates to it, so outbound calls are aborted on timeout. (apps/lfx-one/src/server/services/api-client.service.ts)
apps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.html (1)
22-27: Append target + empty template usage is supported (PrimeNG ^19.1.4).apps/lfx-one/package.json lists primeng ^19.1.4; v19 docs confirm p-autocomplete supports appendTo, autoHighlight and pTemplate="empty" — no changes required.
...lfx-one/src/app/modules/project/committees/components/member-form/member-form.component.html
Show resolved
Hide resolved
apps/lfx-one/src/app/shared/components/autocomplete/autocomplete.component.ts
Show resolved
Hide resolved
apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.html
Show resolved
Hide resolved
apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.ts
Show resolved
Hide resolved
apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.ts
Show resolved
Hide resolved
- Use case-insensitive protocol detection with /^https?:\/\//i regex - Build HTTPS candidate from host (with optional path) when no protocol present - Fix critical validation flaw where domains with ports/paths were rejected - Improve type safety in OrganizationService and OrganizationSearchComponent - Remove debounceTime from organization search (handled by autocomplete) The previous validation incorrectly compared url.hostname to cleanDomain containing ports/paths/query parameters, causing valid domains like "example.com:8080/path" to be rejected. Now properly handles: - example.com:8080/path → https://example.com:8080/path ✅ - HTTPS://example.com → uses as-is ✅ - Http://example.com/path → uses as-is ✅ - example.com → https://example.com ✅ References: LFXV2-575, LFXV2-576 Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/lfx-one/src/app/shared/services/organization.service.ts (1)
14-14: Consider externalizing baseUrl to a config/token.
Helps with environment overrides and testing.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.ts(1 hunks)apps/lfx-one/src/app/shared/services/organization.service.ts(1 hunks)packages/shared/src/utils/url.utils.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/lfx-one/src/app/shared/components/organization-search/organization-search.component.ts
- packages/shared/src/utils/url.utils.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript interfaces instead of union types for better maintainability
When defining PrimeNG-related types, reference the official PrimeNG component interfaces
Files:
apps/lfx-one/src/app/shared/services/organization.service.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}
📄 CodeRabbit inference engine (CLAUDE.md)
Include required license headers on all source files
Files:
apps/lfx-one/src/app/shared/services/organization.service.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not nest ternary expressions
Files:
apps/lfx-one/src/app/shared/services/organization.service.ts
🧬 Code graph analysis (1)
apps/lfx-one/src/app/shared/services/organization.service.ts (2)
apps/lfx-one/src/server/services/organization.service.ts (1)
OrganizationService(9-32)packages/shared/src/interfaces/organization.interface.ts (2)
OrganizationSuggestion(8-13)OrganizationSuggestionsResponse(19-22)
⏰ 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). (1)
- GitHub Check: E2E Tests / Playwright E2E Tests
🔇 Additional comments (3)
apps/lfx-one/src/app/shared/services/organization.service.ts (3)
1-2: License header present and correct.
Meets the repo’s licensing requirement.
21-21: Strong typing for return type looks good.
Good change to Observable<OrganizationSuggestion[]>.
22-24: Trim before length check to avoid whitespace-only API calls.
Currently, " " (len >= 2) will call the API with an empty query after trim.Apply this diff:
public searchOrganizations(searchTerm: string): Observable<OrganizationSuggestion[]> { - if (!searchTerm || searchTerm.length < 2) { + const query = (searchTerm ?? '').trim(); + if (!query || query.length < 2) { return of([]); } return this.http .get<OrganizationSuggestionsResponse>(`${this.baseUrl}/search`, { - params: { query: searchTerm.trim() }, + params: { query }, }) .pipe( map((response) => response.suggestions || []), catchError((error) => { console.error('Error searching organizations:', error); return of([]); }) ); }Also applies to: 28-28
Summary
Technical Details
/query/orgs/suggest?v=1&query=<term>normalizeToUrl()andisValidDomain()utilities for consistent URL handlingAPI Integration
/api/organizations/search/query/orgs/suggest?v=1&query=<searchTerm>{ suggestions: [{ name: string, domain: string }] }Testing
JIRA References
🤖 Generated with Claude Code