Suggestions: Handle errors (#114868)
Co-authored-by: Paul Marbach <paul.marbach@grafana.com>
This commit is contained in:
@@ -30,7 +30,17 @@ export interface Props {
|
||||
|
||||
export function VisualizationSuggestions({ onChange, data, panel }: Props) {
|
||||
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 [firstCardRef, { width }] = useMeasure<HTMLDivElement>();
|
||||
const [firstCardHash, setFirstCardHash] = useState<string | null>(null);
|
||||
@@ -89,7 +99,7 @@ export function VisualizationSuggestions({ onChange, data, panel }: Props) {
|
||||
}
|
||||
}, [suggestions, suggestionHash, firstCardHash, isNewVizSuggestionsEnabled, isUnconfiguredPanel, applySuggestion]);
|
||||
|
||||
if (loading) {
|
||||
if (loading || !data) {
|
||||
return (
|
||||
<div className={styles.loadingContainer}>
|
||||
<Spinner size="xxl" />
|
||||
@@ -120,10 +130,6 @@ export function VisualizationSuggestions({ onChange, data, panel }: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.grid}>
|
||||
{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
|
||||
*/
|
||||
let _pluginCache: PanelPlugin[] | null = null;
|
||||
async function getPanelsWithSuggestions(): Promise<PanelPlugin[]> {
|
||||
if (!_pluginCache) {
|
||||
_pluginCache = [];
|
||||
// list of plugins to load is determined by the feature flag
|
||||
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
|
||||
const pluginIds: string[] = config.featureToggles.externalVizSuggestions
|
||||
? getAllPanelPluginMeta()
|
||||
.filter((panel) => panel.suggestions)
|
||||
.map((m) => m.id)
|
||||
: panelsToCheckFirst;
|
||||
// import the plugins in parallel using Promise.allSettled
|
||||
const plugins: PanelPlugin[] = [];
|
||||
const settledPromises = await Promise.allSettled(pluginIds.map((id) => importPanelPlugin(id)));
|
||||
for (let i = 0; i < settledPromises.length; i++) {
|
||||
const settled = settledPromises[i];
|
||||
|
||||
// import the plugins in parallel using Promise.allSettled
|
||||
const settledPromises = await Promise.allSettled(pluginIds.map((id) => importPanelPlugin(id)));
|
||||
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?
|
||||
if (settled.status === 'fulfilled') {
|
||||
plugins.push(settled.value);
|
||||
}
|
||||
// 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');
|
||||
}
|
||||
|
||||
return _pluginCache;
|
||||
return plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +79,7 @@ export function sortSuggestions(suggestions: PanelPluginVisualizationSuggestion[
|
||||
if (mappedA && dataSummary.hasPreferredVisualisationType(mappedA)) {
|
||||
return -1;
|
||||
}
|
||||
const mappedB = mapPreferredVisualisationTypeToPlugin(a.pluginId);
|
||||
const mappedB = mapPreferredVisualisationTypeToPlugin(b.pluginId);
|
||||
if (mappedB && dataSummary.hasPreferredVisualisationType(mappedB)) {
|
||||
return 1;
|
||||
}
|
||||
@@ -101,9 +97,8 @@ export function sortSuggestions(suggestions: PanelPluginVisualizationSuggestion[
|
||||
export async function getAllSuggestions(data?: PanelData): Promise<PanelPluginVisualizationSuggestion[]> {
|
||||
const dataSummary = getPanelDataSummary(data?.series);
|
||||
const list: PanelPluginVisualizationSuggestion[] = [];
|
||||
const plugins = await getPanelsWithSuggestions();
|
||||
|
||||
for (const plugin of plugins) {
|
||||
for (const plugin of await getPanelsWithSuggestions()) {
|
||||
const suggestions = plugin.getSuggestions(dataSummary);
|
||||
if (suggestions) {
|
||||
list.push(...suggestions);
|
||||
|
||||
Reference in New Issue
Block a user