Skip to content

Commit

Permalink
feat(events): enable event and probe template UI to display without t…
Browse files Browse the repository at this point in the history
…arget selection (cryostatio#1498)
  • Loading branch information
andrewazores authored Dec 11, 2024
1 parent 7733f17 commit f0708be
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 21 deletions.
7 changes: 4 additions & 3 deletions src/app/Events/EventTemplates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { forkJoin, Observable, of } from 'rxjs';
import { catchError, concatMap, defaultIfEmpty, filter, first, tap } from 'rxjs/operators';
import { catchError, concatMap, defaultIfEmpty, first, tap } from 'rxjs/operators';

const tableColumns: TableColumn[] = [
{
Expand Down Expand Up @@ -165,9 +165,10 @@ export const EventTemplates: React.FC<EventTemplatesProps> = () => {
context.target
.target()
.pipe(
filter((target) => !!target),
first(),
concatMap((target: Target) => context.api.getTargetEventTemplates(target)),
concatMap((target: Target) =>
target ? context.api.getTargetEventTemplates(target) : context.api.getEventTemplates(),
),
)
.subscribe({
next: handleTemplates,
Expand Down
50 changes: 34 additions & 16 deletions src/app/Events/Events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
*/
import { AgentLiveProbes } from '@app/Agent/AgentLiveProbes';
import { AgentProbeTemplates } from '@app/Agent/AgentProbeTemplates';
import { BreadcrumbPage } from '@app/BreadcrumbPage/BreadcrumbPage';
import { ServiceContext } from '@app/Shared/Services/Services';
import { TargetView } from '@app/TargetView/TargetView';
import { TargetContextSelector } from '@app/TargetView/TargetContextSelector';
import { useSubscriptions } from '@app/utils/hooks/useSubscriptions';
import { getActiveTab, switchTab } from '@app/utils/utils';
import { Card, CardBody, Tab, Tabs, Tooltip } from '@patternfly/react-core';
Expand All @@ -30,19 +31,21 @@ export interface EventsProps {}

export const Events: React.FC<EventsProps> = ({ ...props }) => {
return (
<TargetView {...props} pageTitle="Events">
<Card isFullHeight>
<CardBody isFilled>
<EventTabs />
</CardBody>
</Card>
<Card isFullHeight>
<CardBody isFilled>
<AgentTabs />
</CardBody>
</Card>
<></>
</TargetView>
<>
<TargetContextSelector />
<BreadcrumbPage {...props} pageTitle="Events">
<Card isFullHeight>
<CardBody isFilled>
<EventTabs />
</CardBody>
</Card>
<Card isFullHeight>
<CardBody isFilled>
<AgentTabs />
</CardBody>
</Card>
</BreadcrumbPage>
</>
);
};

Expand All @@ -52,9 +55,18 @@ enum EventTab {
}

export const EventTabs: React.FC = () => {
const context = React.useContext(ServiceContext);
const addSubscription = useSubscriptions();

const { search, pathname } = useLocation();
const navigate = useNavigate();

const [targetSelected, setTargetSelected] = React.useState(false);

React.useEffect(() => {
addSubscription(context.target.target().subscribe((t) => setTargetSelected(!!t)));
}, [addSubscription, context, context.target]);

const activeTab = React.useMemo(() => {
return getActiveTab(search, 'eventTab', Object.values(EventTab), EventTab.EVENT_TEMPLATE);
}, [search]);
Expand All @@ -70,7 +82,7 @@ export const EventTabs: React.FC = () => {
<Tab eventKey={EventTab.EVENT_TEMPLATE} title="Event Templates">
<EventTemplates />
</Tab>
<Tab eventKey={EventTab.EVENT_TYPE} title="Event types">
<Tab isAriaDisabled={!targetSelected} eventKey={EventTab.EVENT_TYPE} title="Event types">
<EventTypes />
</Tab>
</Tabs>
Expand All @@ -89,6 +101,12 @@ export const AgentTabs: React.FC = () => {
const { search, pathname } = useLocation();
const navigate = useNavigate();

const [targetSelected, setTargetSelected] = React.useState(false);

React.useEffect(() => {
addSubscription(context.target.target().subscribe((t) => setTargetSelected(!!t)));
}, [addSubscription, context, context.target]);

const activeTab = React.useMemo(() => {
return getActiveTab(search, 'agentTab', Object.values(AgentTab), AgentTab.AGENT_TEMPLATE);
}, [search]);
Expand Down Expand Up @@ -121,7 +139,7 @@ export const AgentTabs: React.FC = () => {
<Tab
eventKey={AgentTab.AGENT_PROBE}
title="Live Configuration"
isAriaDisabled={!agentDetected}
isAriaDisabled={!targetSelected || !agentDetected}
tooltip={
agentDetected ? undefined : (
<Tooltip content="JMC ByteCode Instrumentation Agent not detected for the selected Target JVM" />
Expand Down
2 changes: 1 addition & 1 deletion src/app/Rules/CreateRule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ export const CreateRuleForm: React.FC<CreateRuleFormProps> = (_props) => {
: [];
}),
),
of([]),
context.api.getEventTemplates().pipe(catchError((_) => of<EventTemplate[]>([]))),
),
),
)
Expand Down
6 changes: 5 additions & 1 deletion src/app/Shared/Services/Api.service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ export class ApiService {

const body = new window.FormData();
body.append('template', file);
return this.sendLegacyRequest('v4', 'templates', 'Template Upload Failed', {
return this.sendLegacyRequest('v4', 'event_templates', 'Template Upload Failed', {
body: body,
method: 'POST',
headers: {},
Expand Down Expand Up @@ -1361,6 +1361,10 @@ export class ApiService {
return this.doGet(`targets/${target.id}/recordings`, 'v4', undefined, suppressNotifications, skipStatusCheck);
}

getEventTemplates(suppressNotifications = false, skipStatusCheck = false): Observable<EventTemplate[]> {
return this.doGet<EventTemplate[]>('event_templates', 'v4', undefined, suppressNotifications, skipStatusCheck);
}

getTargetEventTemplates(
target: TargetStub,
suppressNotifications = false,
Expand Down
7 changes: 7 additions & 0 deletions src/test/Rules/CreateRule.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ const mockEventTemplate: EventTemplate = {
provider: 'some provider',
description: 'some description',
};
const mockCustomEventTemplate: EventTemplate = {
name: 'CustomTemplate',
type: 'CUSTOM',
provider: 'some provider',
description: 'some description',
};

const mockRule: Rule = {
name: 'mockRule',
Expand All @@ -64,6 +70,7 @@ jest.mock('react-router-dom', () => ({
useNavigate: () => mockNavigate,
}));

jest.spyOn(defaultServices.api, 'getEventTemplates').mockReturnValue(of([mockCustomEventTemplate]));
jest.spyOn(defaultServices.api, 'getTargetEventTemplates').mockReturnValue(of([mockEventTemplate]));

jest.spyOn(defaultServices.targets, 'targets').mockReturnValue(of([mockTarget]));
Expand Down

0 comments on commit f0708be

Please sign in to comment.