diff --git a/src/app/Shared/MatchExpressionEvaluator.tsx b/src/app/Shared/MatchExpressionEvaluator.tsx index e8e1c85fb..c9761625b 100644 --- a/src/app/Shared/MatchExpressionEvaluator.tsx +++ b/src/app/Shared/MatchExpressionEvaluator.tsx @@ -60,7 +60,7 @@ export const MatchExpressionEvaluator: React.FunctionComponent { if (!props.matchExpression || !target?.connectUrl) { diff --git a/src/app/TargetSelect/TargetSelect.tsx b/src/app/TargetSelect/TargetSelect.tsx index bdd65a8a7..0212a2e33 100644 --- a/src/app/TargetSelect/TargetSelect.tsx +++ b/src/app/TargetSelect/TargetSelect.tsx @@ -47,6 +47,7 @@ import { catchError, first } from 'rxjs/operators'; import { CreateTargetModal } from './CreateTargetModal'; import _ from 'lodash'; +import { NotificationCategory } from '@app/Shared/Services/NotificationChannel.service'; export interface TargetSelectProps { } @@ -63,13 +64,34 @@ export const TargetSelect: React.FunctionComponent = (props) const addSubscription = useSubscriptions(); React.useEffect(() => { - const sub = context.targets.targets().subscribe((targets) => { - setTargets(targets); - selectTargetFromCache(targets); - }); - return () => sub.unsubscribe(); + addSubscription( + context.targets.targets().subscribe((targets) => { + setTargets(targets); + selectTargetFromCache(targets); + }) + ); }, [context, context.targets, setTargets]); + React.useEffect(() => { + addSubscription( + context.notificationChannel.messages(NotificationCategory.TargetJvmDiscovery) + .subscribe(v => { + const evt: TargetDiscoveryEvent = v.message.event; + if (evt.kind === 'LOST') { + const target: Target = { + connectUrl: evt.serviceRef.connectUrl, + alias: evt.serviceRef.alias, + } + context.target.target().pipe(first()).subscribe((currentTarget) => { + if (currentTarget.connectUrl === target.connectUrl && currentTarget.alias === target.alias) { + selectNone(); + } + }) + } + }) + ); + }, [addSubscription, context, context.notificationChannel, context.target]); + const refreshTargetList = React.useCallback(() => { setLoading(true); addSubscription( @@ -126,7 +148,7 @@ export const TargetSelect: React.FunctionComponent = (props) } } setExpanded(false); - }, [context, selected, notifications, setExpanded]); + }, [context, context.target, selected, notifications, setExpanded]); const selectNone = React.useCallback(() => { onSelect(undefined, undefined, true); diff --git a/src/test/Rules/CreateRule.test.tsx b/src/test/Rules/CreateRule.test.tsx index 8d6876696..f4b3acb25 100644 --- a/src/test/Rules/CreateRule.test.tsx +++ b/src/test/Rules/CreateRule.test.tsx @@ -48,6 +48,7 @@ import { ServiceContext, defaultServices } from '@app/Shared/Services/Services'; import { CreateRule } from '@app/Rules/CreateRule'; import { EventTemplate } from '@app/CreateRecording/CreateRecording'; import { Target } from '@app/Shared/Services/Target.service'; +import { NotificationMessage } from '@app/Shared/Services/NotificationChannel.service'; const escapeKeyboardInput = (value: string) => { return value.replace(/[{[]/g, '$&$&'); @@ -82,6 +83,18 @@ const mockRule: Rule = { maxSizeBytes: 0 }; +const mockNewTarget: Target = { + connectUrl: 'service:jmx:rmi://someUrl1', + alias: 'someAlias', +} + +const mockTargetFoundNotification = { + message: { + event: { kind: 'FOUND', serviceRef: mockNewTarget } + } +} as NotificationMessage; + + const history = createMemoryHistory(); jest.mock('react-router-dom', () => ({ @@ -91,6 +104,7 @@ jest.mock('react-router-dom', () => ({ })); const createSpy = jest.spyOn(defaultServices.api, 'createRule').mockReturnValue(of(true)); +jest.spyOn(defaultServices.notificationChannel, 'messages').mockReturnValue(of(mockTargetFoundNotification)); jest.spyOn(defaultServices.api, 'doGet').mockReturnValue(of([mockEventTemplate])); jest.spyOn(defaultServices.target, 'target').mockReturnValue(of(mockTarget)); jest.spyOn(defaultServices.targets, 'targets').mockReturnValue(of([mockTarget]));