Suggestions: Handle errors (#114868)
Co-authored-by: Paul Marbach <paul.marbach@grafana.com>
This commit is contained in:
co-authored by
Paul Marbach
parent
a46f0a222e
commit
7ae9f94de7
@@ -30,7 +30,17 @@ export interface Props {
|
|||||||
|
|
||||||
export function VisualizationSuggestions({ onChange, data, panel }: Props) {
|
export function VisualizationSuggestions({ onChange, data, panel }: Props) {
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
const { value: suggestions, loading, error } = useAsync(() => getAllSuggestions(data), [data]);
|
const {
|
||||||
|
value: suggestions,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
} = useAsync(async () => {
|
||||||
|
if (!hasData(data)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return await getAllSuggestions(data);
|
||||||
|
}, [data]);
|
||||||
const [suggestionHash, setSuggestionHash] = useState<string | null>(null);
|
const [suggestionHash, setSuggestionHash] = useState<string | null>(null);
|
||||||
const [firstCardRef, { width }] = useMeasure<HTMLDivElement>();
|
const [firstCardRef, { width }] = useMeasure<HTMLDivElement>();
|
||||||
const [firstCardHash, setFirstCardHash] = useState<string | null>(null);
|
const [firstCardHash, setFirstCardHash] = useState<string | null>(null);
|
||||||
@@ -89,7 +99,7 @@ export function VisualizationSuggestions({ onChange, data, panel }: Props) {
|
|||||||
}
|
}
|
||||||
}, [suggestions, suggestionHash, firstCardHash, isNewVizSuggestionsEnabled, isUnconfiguredPanel, applySuggestion]);
|
}, [suggestions, suggestionHash, firstCardHash, isNewVizSuggestionsEnabled, isUnconfiguredPanel, applySuggestion]);
|
||||||
|
|
||||||
if (loading) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.loadingContainer}>
|
<div className={styles.loadingContainer}>
|
||||||
<Spinner size="xxl" />
|
<Spinner size="xxl" />
|
||||||
@@ -120,10 +130,6 @@ export function VisualizationSuggestions({ onChange, data, panel }: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.grid}>
|
<div className={styles.grid}>
|
||||||
{isNewVizSuggestionsEnabled
|
{isNewVizSuggestionsEnabled
|
||||||
|
|||||||
@@ -17,35 +17,31 @@ import { panelsToCheckFirst } from './consts';
|
|||||||
/**
|
/**
|
||||||
* gather and cache the plugins which provide visualization suggestions so they can be invoked to build suggestions
|
* gather and cache the plugins which provide visualization suggestions so they can be invoked to build suggestions
|
||||||
*/
|
*/
|
||||||
let _pluginCache: PanelPlugin[] | null = null;
|
|
||||||
async function getPanelsWithSuggestions(): Promise<PanelPlugin[]> {
|
async function getPanelsWithSuggestions(): Promise<PanelPlugin[]> {
|
||||||
if (!_pluginCache) {
|
// list of plugins to load is determined by the feature flag
|
||||||
_pluginCache = [];
|
const pluginIds: string[] = config.featureToggles.externalVizSuggestions
|
||||||
|
? getAllPanelPluginMeta()
|
||||||
|
.filter((panel) => panel.suggestions)
|
||||||
|
.map((m) => m.id)
|
||||||
|
: panelsToCheckFirst;
|
||||||
|
|
||||||
// list of plugins to load is determined by the feature flag
|
// import the plugins in parallel using Promise.allSettled
|
||||||
const pluginIds: string[] = config.featureToggles.externalVizSuggestions
|
const plugins: PanelPlugin[] = [];
|
||||||
? getAllPanelPluginMeta()
|
const settledPromises = await Promise.allSettled(pluginIds.map((id) => importPanelPlugin(id)));
|
||||||
.filter((panel) => panel.suggestions)
|
for (let i = 0; i < settledPromises.length; i++) {
|
||||||
.map((m) => m.id)
|
const settled = settledPromises[i];
|
||||||
: panelsToCheckFirst;
|
|
||||||
|
|
||||||
// import the plugins in parallel using Promise.allSettled
|
if (settled.status === 'fulfilled') {
|
||||||
const settledPromises = await Promise.allSettled(pluginIds.map((id) => importPanelPlugin(id)));
|
plugins.push(settled.value);
|
||||||
for (let i = 0; i < settledPromises.length; i++) {
|
|
||||||
const settled = settledPromises[i];
|
|
||||||
|
|
||||||
if (settled.status === 'fulfilled') {
|
|
||||||
_pluginCache.push(settled.value);
|
|
||||||
}
|
|
||||||
// TODO: do we want to somehow log if there were errors loading some of the plugins?
|
|
||||||
}
|
}
|
||||||
|
// TODO: do we want to somehow log if there were errors loading some of the plugins?
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pluginCache.length === 0) {
|
if (plugins.length === 0) {
|
||||||
throw new Error('No panel plugins with visualization suggestions found');
|
throw new Error('No panel plugins with visualization suggestions found');
|
||||||
}
|
}
|
||||||
|
|
||||||
return _pluginCache;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,7 +79,7 @@ export function sortSuggestions(suggestions: PanelPluginVisualizationSuggestion[
|
|||||||
if (mappedA && dataSummary.hasPreferredVisualisationType(mappedA)) {
|
if (mappedA && dataSummary.hasPreferredVisualisationType(mappedA)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
const mappedB = mapPreferredVisualisationTypeToPlugin(a.pluginId);
|
const mappedB = mapPreferredVisualisationTypeToPlugin(b.pluginId);
|
||||||
if (mappedB && dataSummary.hasPreferredVisualisationType(mappedB)) {
|
if (mappedB && dataSummary.hasPreferredVisualisationType(mappedB)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -101,9 +97,8 @@ export function sortSuggestions(suggestions: PanelPluginVisualizationSuggestion[
|
|||||||
export async function getAllSuggestions(data?: PanelData): Promise<PanelPluginVisualizationSuggestion[]> {
|
export async function getAllSuggestions(data?: PanelData): Promise<PanelPluginVisualizationSuggestion[]> {
|
||||||
const dataSummary = getPanelDataSummary(data?.series);
|
const dataSummary = getPanelDataSummary(data?.series);
|
||||||
const list: PanelPluginVisualizationSuggestion[] = [];
|
const list: PanelPluginVisualizationSuggestion[] = [];
|
||||||
const plugins = await getPanelsWithSuggestions();
|
|
||||||
|
|
||||||
for (const plugin of plugins) {
|
for (const plugin of await getPanelsWithSuggestions()) {
|
||||||
const suggestions = plugin.getSuggestions(dataSummary);
|
const suggestions = plugin.getSuggestions(dataSummary);
|
||||||
if (suggestions) {
|
if (suggestions) {
|
||||||
list.push(...suggestions);
|
list.push(...suggestions);
|
||||||
|
|||||||
Reference in New Issue
Block a user