From 9fd31a94434ecac348a6c6297173e0ed5fa630b2 Mon Sep 17 00:00:00 2001 From: voommen-livefront Date: Tue, 22 Jul 2025 11:05:47 -0500 Subject: [PATCH] PM-23825 setup crowdstrike card --- .../integrations/integrations.component.ts | 9 ++++++ .../integration-card.component.html | 20 ++++++++++++- .../integration-card.component.spec.ts | 30 +++++++++++++++++-- .../integration-card.component.ts | 13 ++++++++ .../integration-grid.component.html | 3 ++ .../shared/components/integrations/models.ts | 3 ++ .../integrations/logo-crowdstrike-black.svg | 22 ++++++++++++++ apps/web/src/locales/en/messages.json | 12 ++++++++ 8 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 apps/web/src/images/integrations/logo-crowdstrike-black.svg diff --git a/apps/web/src/app/admin-console/organizations/integrations/integrations.component.ts b/apps/web/src/app/admin-console/organizations/integrations/integrations.component.ts index e6a62b1db73..5c6fa72c311 100644 --- a/apps/web/src/app/admin-console/organizations/integrations/integrations.component.ts +++ b/apps/web/src/app/admin-console/organizations/integrations/integrations.component.ts @@ -228,6 +228,15 @@ export class AdminConsoleIntegrationsComponent implements OnInit { image: "../../../../../../../images/integrations/logo-microsoft-intune-color.svg", type: IntegrationType.DEVICE, }, + { + name: "Crowdstrike", + linkURL: "", + image: "../../../../../../../images/integrations/logo-crowdstrike-black.svg", + type: IntegrationType.EVENT, + description: "crowdstrikeEventIntegrationDesc", + isConnected: false, + canSetupConnection: true, + }, ]; } diff --git a/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-card/integration-card.component.html b/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-card/integration-card.component.html index e96fbef270c..d0afda4c0ae 100644 --- a/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-card/integration-card.component.html +++ b/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-card/integration-card.component.html @@ -17,8 +17,26 @@
-

{{ name }}

+

+ {{ name }} + + {{ "on" | i18n }} + {{ "off" | i18n }} + +

+

{{ description }}

+ + { let component: IntegrationCardComponent; let fixture: ComponentFixture; + const mockI18nService = mock(); const systemTheme$ = new BehaviorSubject(ThemeType.Light); const usersPreferenceTheme$ = new BehaviorSubject(ThemeType.Light); @@ -41,7 +42,7 @@ describe("IntegrationCardComponent", () => { }, { provide: I18nService, - useValue: mock(), + useValue: mockI18nService, }, ], }).compileComponents(); @@ -55,6 +56,7 @@ describe("IntegrationCardComponent", () => { component.image = "test-image.png"; component.linkURL = "https://example.com/"; + mockI18nService.t.mockImplementation((key) => key); fixture.detectChanges(); }); @@ -67,7 +69,7 @@ describe("IntegrationCardComponent", () => { it("renders card body", () => { const name = fixture.nativeElement.querySelector("h3"); - expect(name.textContent).toBe("Integration Name"); + expect(name.textContent).toContain("Integration Name"); }); it("assigns external rel attribute", () => { @@ -182,4 +184,28 @@ describe("IntegrationCardComponent", () => { }); }); }); + + describe("connected badge", () => { + it("shows connected badge when isConnected is true", () => { + component.isConnected = true; + + expect(component.showConnectedBadge()).toBe(true); + }); + + it("does not show connected badge when isConnected is false", () => { + component.isConnected = false; + fixture.detectChanges(); + const name = fixture.nativeElement.querySelector("h3 > span > span > span"); + + expect(name.textContent).toContain("off"); + // when isConnected is true/false, the badge should be shown as on/off + // when isConnected is undefined, the badge should not be shown + expect(component.showConnectedBadge()).toBe(true); + }); + + it("does not show connected badge when isConnected is undefined", () => { + component.isConnected = undefined; + expect(component.showConnectedBadge()).toBe(false); + }); + }); }); diff --git a/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-card/integration-card.component.ts b/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-card/integration-card.component.ts index 20e4028e9df..4188579bef9 100644 --- a/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-card/integration-card.component.ts +++ b/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-card/integration-card.component.ts @@ -41,6 +41,9 @@ export class IntegrationCardComponent implements AfterViewInit, OnDestroy { * @example "2024-12-31" */ @Input() newBadgeExpiration?: string; + @Input() description?: string; + @Input() isConnected?: boolean; + @Input() canSetupConnection?: boolean; constructor( private themeStateService: ThemeStateService, @@ -93,4 +96,14 @@ export class IntegrationCardComponent implements AfterViewInit, OnDestroy { return expirationDate > new Date(); } + + showConnectedBadge(): boolean { + return this.isConnected !== undefined; + } + + setupConnection(app: string) { + // This method can be used to handle the connection logic for the integration + // For example, it could open a modal or redirect to a setup page + this.isConnected = !this.isConnected; // Toggle connection state for demonstration + } } diff --git a/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-grid/integration-grid.component.html b/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-grid/integration-grid.component.html index 4b4b3ac972b..b4eaff993f0 100644 --- a/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-grid/integration-grid.component.html +++ b/apps/web/src/app/admin-console/organizations/shared/components/integrations/integration-grid/integration-grid.component.html @@ -13,6 +13,9 @@ [imageDarkMode]="integration.imageDarkMode" [externalURL]="integration.type === IntegrationType.SDK" [newBadgeExpiration]="integration.newBadgeExpiration" + [description]="integration.description | i18n" + [isConnected]="integration.isConnected" + [canSetupConnection]="integration.canSetupConnection" > diff --git a/apps/web/src/app/admin-console/organizations/shared/components/integrations/models.ts b/apps/web/src/app/admin-console/organizations/shared/components/integrations/models.ts index 765b1d44a2e..a231523b578 100644 --- a/apps/web/src/app/admin-console/organizations/shared/components/integrations/models.ts +++ b/apps/web/src/app/admin-console/organizations/shared/components/integrations/models.ts @@ -17,4 +17,7 @@ export type Integration = { * @example "2024-12-31" */ newBadgeExpiration?: string; + description?: string; + isConnected?: boolean; + canSetupConnection?: boolean; }; diff --git a/apps/web/src/images/integrations/logo-crowdstrike-black.svg b/apps/web/src/images/integrations/logo-crowdstrike-black.svg new file mode 100644 index 00000000000..25875d705cb --- /dev/null +++ b/apps/web/src/images/integrations/logo-crowdstrike-black.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json index d5ded3c75ea..5f6570a24d9 100644 --- a/apps/web/src/locales/en/messages.json +++ b/apps/web/src/locales/en/messages.json @@ -9469,6 +9469,9 @@ "deviceManagementDesc": { "message": "Configure device management for Bitwarden using the implementation guide for your platform." }, + "crowdstrikeEventIntegrationDesc": { + "message": "Send event data to your Logscale instance" + }, "deviceIdMissing": { "message": "Device ID is missing" }, @@ -9484,6 +9487,15 @@ "reopenLinkOnDesktop": { "message": "Reopen this link from your email on a desktop." }, + "connectIntegrationButtonDesc": { + "message": "Connect $INTEGRATION$", + "placeholders": { + "integration": { + "content": "$1", + "example": "Crowdstrike" + } + } + }, "integrationCardTooltip": { "message": "Launch $INTEGRATION$ implementation guide.", "placeholders": {