diff --git a/src/app/CreateRecording/CustomRecordingForm.tsx b/src/app/CreateRecording/CustomRecordingForm.tsx
index afb6b5856..bb9e7c010 100644
--- a/src/app/CreateRecording/CustomRecordingForm.tsx
+++ b/src/app/CreateRecording/CustomRecordingForm.tsx
@@ -559,7 +559,8 @@ export const CustomRecordingForm: React.FC = () => {
- Write contents of buffer onto disk. If disabled, the buffer acts as circular buffer only keeping the most recent Recording information
+ Write contents of buffer onto disk. If disabled, the buffer acts as circular buffer only keeping the
+ most recent Recording information
diff --git a/src/app/Dashboard/Charts/mbean/MBeanMetricsChartCard.tsx b/src/app/Dashboard/Charts/mbean/MBeanMetricsChartCard.tsx
index eace6bedc..f48f0216d 100644
--- a/src/app/Dashboard/Charts/mbean/MBeanMetricsChartCard.tsx
+++ b/src/app/Dashboard/Charts/mbean/MBeanMetricsChartCard.tsx
@@ -399,6 +399,7 @@ export const MBeanMetricsChartCard: DashboardCardFC
React.useEffect(() => {
resizeObserver.current = getResizeObserver(containerRef.current, handleResize);
+ handleResize();
return resizeObserver.current;
}, [resizeObserver, containerRef, handleResize]);
diff --git a/src/app/Rules/CreateRule.tsx b/src/app/Rules/CreateRule.tsx
index be0d0868a..aa6c906a3 100644
--- a/src/app/Rules/CreateRule.tsx
+++ b/src/app/Rules/CreateRule.tsx
@@ -595,8 +595,8 @@ export const CreateRuleForm: React.FC = (_props) => {
- Initial delay before archiving starts. The first archived copy will be made this long after the Recording is started.
- The second archived copy will occur one Archival period later.
+ Initial delay before archiving starts. The first archived copy will be made this long after the Recording
+ is started. The second archived copy will occur one Archival period later.
@@ -631,7 +631,8 @@ export const CreateRuleForm: React.FC = (_props) => {
- The number of Archived Recording copies to preserve in archives for each target application affected by this rule.
+ The number of Archived Recording copies to preserve in archives for each target application affected by
+ this rule.
diff --git a/src/app/TargetView/TargetContextSelector.tsx b/src/app/TargetView/TargetContextSelector.tsx
index 236cca5ec..68a76d237 100644
--- a/src/app/TargetView/TargetContextSelector.tsx
+++ b/src/app/TargetView/TargetContextSelector.tsx
@@ -28,13 +28,14 @@ import {
SearchInput,
Dropdown,
DropdownGroup,
+ DropdownItem,
+ DropdownList,
MenuToggle,
MenuSearch,
MenuSearchInput,
- SelectOption,
- SelectGroup,
+ Split,
+ SplitItem,
} from '@patternfly/react-core';
-import { SearchIcon } from '@patternfly/react-icons';
import * as React from 'react';
import { Link } from 'react-router-dom';
@@ -49,20 +50,23 @@ export const TargetContextSelector: React.FC = ({ cl
const [targets, setTargets] = React.useState([]);
const [selectedTarget, setSelectedTarget] = React.useState();
const [favorites, setFavorites] = React.useState(getFromLocalStorage('TARGET_FAVORITES', []));
+ const [searchTerm, setSearchTerm] = React.useState('');
const [isTargetOpen, setIsTargetOpen] = React.useState(false);
const [isLoading, setLoading] = React.useState(false);
- const handleSelectToggle = React.useCallback(() => setIsTargetOpen((old) => !old), [setIsTargetOpen]);
+ const onToggleClick = React.useCallback(() => {
+ setIsTargetOpen((v) => !v);
+ }, [setIsTargetOpen]);
- const handleTargetSelect = React.useCallback(
- (_, { target }, isPlaceholder) => {
+ const onSelect = React.useCallback(
+ (_, target) => {
setIsTargetOpen(false);
- const toSelect: Target = isPlaceholder ? undefined : target;
- if (!isEqualTarget(toSelect, selectedTarget)) {
- context.target.setTarget(toSelect);
+ if (!isEqualTarget(target, selectedTarget)) {
+ setSelectedTarget(target);
+ context.target.setTarget(target);
}
},
- [setIsTargetOpen, selectedTarget, context.target],
+ [selectedTarget, setSelectedTarget, setIsTargetOpen, context.target],
);
React.useEffect(() => {
@@ -119,91 +123,67 @@ export const TargetContextSelector: React.FC = ({ cl
const selectOptions = React.useMemo(() => {
if (noOptions) {
return [
-
+
No target found
- ,
+ ,
];
}
- const favSet = new Set(favorites);
+ const matchExp = new RegExp(searchTerm, 'i');
+ const filteredTargets = targets.filter((t) =>
+ [t.alias, t.connectUrl, getAnnotation(t.annotations.cryostat, 'REALM') ?? ''].some((v) => matchExp.test(v)),
+ );
const groupNames = new Set();
- targets.forEach((t) => groupNames.add(getAnnotation(t.annotations.cryostat, 'REALM') || 'Others'));
+ filteredTargets.forEach((t) => groupNames.add(getAnnotation(t.annotations.cryostat, 'REALM') || 'Others'));
const options = Array.from(groupNames)
.map((name) => (
-
- {targets
+
+ {filteredTargets
.filter((t) => getAnnotation(t.annotations.cryostat, 'REALM') === name)
.map((t: Target) => (
- getTargetRepresentation(t),
- compareTo: (other) => other.target.connectUrl === t.connectUrl,
- ...{ target: t }, // Bypassing type checks
- }}
- />
+ description={t.connectUrl}
+ >
+ {t.alias}
+
))}
-
+
))
.sort((a, b) => `${a.props['label']}`.localeCompare(`${b.props['label']}`));
- const favGroup = favorites.length
- ? [
-
- {favorites
- .map((f) => targets.find((t) => t.connectUrl === f))
- .filter((t) => t !== undefined)
- .map((t: Target) => (
- getTargetRepresentation(t),
- compareTo: (other) => other.target.connectUrl === t.connectUrl,
- ...{ target: t },
- }}
- />
- ))}
- ,
- ,
- ]
- : [];
+ const favGroup =
+ !searchTerm && favorites.length
+ ? [
+
+ {favorites
+ .map((f) => targets.find((t) => t.connectUrl === f))
+ .filter((t) => t !== undefined)
+ .map((t: Target) => (
+
+ {t.alias}
+
+ ))}
+ ,
+ ,
+ ]
+ : [];
return favGroup.concat(options);
- }, [targets, noOptions, favorites]);
+ }, [targets, noOptions, favorites, searchTerm]);
- const handleTargetFilter = React.useCallback(
- (_, value: string) => {
- if (!value || noOptions) {
- // In case of empty options, placeholder is returned.
- return selectOptions;
+ const onFavoriteClick = React.useCallback(
+ (_, item: Target, actionId: string) => {
+ if (!actionId) {
+ return;
}
-
- const matchExp = new RegExp(value, 'i');
- return selectOptions
- .filter((grp) => grp.props.children)
- .map((grp) =>
- React.cloneElement(grp, {
- children: grp.props.children.filter((option) => {
- const { target } = option.props.value;
- return matchExp.test(target.connectUrl) || matchExp.test(target.alias);
- }),
- }),
- )
- .filter((grp) => grp.props.children.length > 0);
- },
- [selectOptions, noOptions],
- );
-
- const handleFavorite = React.useCallback(
- (itemId: string, isFavorite: boolean) => {
setFavorites((old) => {
- const toUpdate = !isFavorite ? [...old, itemId] : old.filter((f) => f !== itemId);
+ const prevFav = old.includes(item.connectUrl);
+ const toUpdate = prevFav ? old.filter((f) => f !== item.connectUrl) : [...old, item.connectUrl];
saveToLocalStorage('TARGET_FAVORITES', toUpdate);
return toUpdate;
});
@@ -211,6 +191,13 @@ export const TargetContextSelector: React.FC = ({ cl
[setFavorites],
);
+ const onClearSelection = React.useCallback(() => {
+ setIsTargetOpen(false);
+ removeFromLocalStorage('TARGET');
+ setSelectedTarget(undefined);
+ context.target.setTarget(undefined);
+ }, [setSelectedTarget, setIsTargetOpen, context.target]);
+
const selectionPrefix = React.useMemo(
() => (!selectedTarget ? undefined : Target:),
[selectedTarget],
@@ -218,11 +205,20 @@ export const TargetContextSelector: React.FC = ({ cl
const selectFooter = React.useMemo(
() => (
-
-
-
+
+
+
+
+
+
+
+
),
- [],
+ [onClearSelection],
);
return (
@@ -233,44 +229,41 @@ export const TargetContextSelector: React.FC = ({ cl
) : (
setIsTargetOpen(isOpen)}
+ onOpenChangeKeys={['Escape']}
+ onSelect={onSelect}
+ onActionClick={onFavoriteClick}
toggle={(toggleRef) => (
handleTargetSelect(undefined, { target: selectedTarget }, undefined)}
- variant="plain"
+ onClick={onToggleClick}
+ isExpanded={isTargetOpen}
+ variant="plainText"
icon={selectionPrefix}
>
- {!selectedTarget
- ? undefined
- : {
- toString: () => getTargetRepresentation(selectedTarget),
- compareTo: (other) => other.target.connectUrl === selectedTarget.connectUrl,
- ...{ target: selectedTarget },
- }}
+ {!selectedTarget ? 'Select a Target' : getTargetRepresentation(selectedTarget)}
)}
popperProps={{
enableFlip: true,
appendTo: portalRoot,
- //maxHeight: '30em',
}}
>
-
-
+ setSearchTerm(v)}
+ />
- {favorites}
- {handleFavorite}
- {selectOptions}
+
+ {selectOptions}
{selectFooter}
)}