import React, { useEffect, useMemo, useState } from 'react'; import { take } from 'lodash'; import { InterpolateFunction, PanelProps } from '@grafana/data'; import { CustomScrollbar, Icon, useStyles } from '@grafana/ui'; import { getBackendSrv } from 'app/core/services/backend_srv'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import impressionSrv from 'app/core/services/impression_srv'; import { DashboardSearchHit } from 'app/features/search/types'; import { DashListOptions } from './types'; import { getStyles } from './styles'; type Dashboard = DashboardSearchHit & { isSearchResult?: boolean; isRecent?: boolean }; interface DashboardGroup { show: boolean; header: string; dashboards: Dashboard[]; } async function fetchDashboards(options: DashListOptions, replaceVars: InterpolateFunction) { let starredDashboards: Promise = Promise.resolve([]); if (options.showStarred) { const params = { limit: options.maxItems, starred: 'true' }; starredDashboards = getBackendSrv().search(params); } let recentDashboards: Promise = Promise.resolve([]); let dashIds: number[] = []; if (options.showRecentlyViewed) { dashIds = take(impressionSrv.getDashboardOpened(), options.maxItems); recentDashboards = getBackendSrv().search({ dashboardIds: dashIds, limit: options.maxItems }); } let searchedDashboards: Promise = Promise.resolve([]); if (options.showSearch) { const params = { limit: options.maxItems, query: replaceVars(options.query, {}, 'text'), folderIds: options.folderId, tag: options.tags.map((tag: string) => replaceVars(tag, {}, 'text')), type: 'dash-db', }; searchedDashboards = getBackendSrv().search(params); } const [starred, searched, recent] = await Promise.all([starredDashboards, searchedDashboards, recentDashboards]); // We deliberately deal with recent dashboards first so that the order of dash IDs is preserved let dashMap = new Map(); for (const dashId of dashIds) { const dash = recent.find((d) => d.id === dashId); if (dash) { dashMap.set(dashId, { ...dash, isRecent: true }); } } searched.forEach((dash) => { if (dashMap.has(dash.id)) { dashMap.get(dash.id)!.isSearchResult = true; } else { dashMap.set(dash.id, { ...dash, isSearchResult: true }); } }); starred.forEach((dash) => { if (dashMap.has(dash.id)) { dashMap.get(dash.id)!.isStarred = true; } else { dashMap.set(dash.id, { ...dash, isStarred: true }); } }); return dashMap; } export function DashList(props: PanelProps) { const [dashboards, setDashboards] = useState(new Map()); useEffect(() => { fetchDashboards(props.options, props.replaceVariables).then((dashes) => { setDashboards(dashes); }); }, [props.options, props.replaceVariables, props.renderCounter]); const toggleDashboardStar = async (e: React.SyntheticEvent, dash: Dashboard) => { e.preventDefault(); e.stopPropagation(); const isStarred = await getDashboardSrv().starDashboard(dash.id.toString(), dash.isStarred); const updatedDashboards = new Map(dashboards); updatedDashboards.set(dash.id, { ...dash, isStarred }); setDashboards(updatedDashboards); }; const [starredDashboards, recentDashboards, searchedDashboards] = useMemo(() => { const dashboardList = [...dashboards.values()]; return [ dashboardList.filter((dash) => dash.isStarred).sort((a, b) => a.title.localeCompare(b.title)), dashboardList.filter((dash) => dash.isRecent), dashboardList.filter((dash) => dash.isSearchResult).sort((a, b) => a.title.localeCompare(b.title)), ]; }, [dashboards]); const { showStarred, showRecentlyViewed, showHeadings, showSearch } = props.options; const dashboardGroups: DashboardGroup[] = [ { header: 'Starred dashboards', dashboards: starredDashboards, show: showStarred, }, { header: 'Recently viewed dashboards', dashboards: recentDashboards, show: showRecentlyViewed, }, { header: 'Search', dashboards: searchedDashboards, show: showSearch, }, ]; const css = useStyles(getStyles); return ( {dashboardGroups.map( ({ show, header, dashboards }, i) => show && (
{showHeadings &&
{header}
}
    {dashboards.map((dash) => (
  • {dash.title} {dash.folderTitle &&
    {dash.folderTitle}
    }
    toggleDashboardStar(e, dash)}>
  • ))}
) )}
); }