diff --git a/public/app/features/provisioning/Shared/RepositoryList.tsx b/public/app/features/provisioning/Shared/RepositoryList.tsx index 0aa0d63c301..c129564a9bd 100644 --- a/public/app/features/provisioning/Shared/RepositoryList.tsx +++ b/public/app/features/provisioning/Shared/RepositoryList.tsx @@ -1,10 +1,12 @@ import { useState } from 'react'; -import { t } from '@grafana/i18n'; -import { EmptyState, FilterInput, Stack } from '@grafana/ui'; +import { t, Trans } from '@grafana/i18n'; +import { Alert, Box, EmptyState, FilterInput, Icon, Stack } from '@grafana/ui'; import { Repository } from 'app/api/clients/provisioning/v0alpha1'; import { RepositoryCard } from '../Repository/RepositoryCard'; +import { useResourceStats } from '../Wizard/hooks/useResourceStats'; +import { useIsProvisionedInstance } from '../hooks/useIsProvisionedInstance'; import { checkSyncSettings } from '../utils/checkSyncSettings'; interface Props { @@ -13,33 +15,72 @@ interface Props { export function RepositoryList({ items }: Props) { const [query, setQuery] = useState(''); + const isProvisionedInstance = useIsProvisionedInstance(); + const { resourceCount, managedCount, unmanagedCount } = useResourceStats(items[0].metadata?.name); const filteredItems = items.filter((item) => item.metadata?.name?.includes(query)); const { instanceConnected } = checkSyncSettings(items); - return ( - - {!instanceConnected && ( - - + + const getResourceCountSection = () => { + if (isProvisionedInstance) { + return ( + + + + + All {{ count: resourceCount }} resources are managed + + + + ); + } + + if (filteredItems.length) { + return ( + + + + {{ managedCount }}/{{ count: resourceCount }} resources managed. {{ unmanagedCount }} resources + aren't managed as code yet. + + - )} - - {filteredItems.length ? ( - filteredItems.map((item) => ) - ) : ( - + ); + } + return null; + }; + + return ( + <> + {getResourceCountSection()} + + {!instanceConnected && ( + + + )} + + {filteredItems.length ? ( + filteredItems.map((item) => ) + ) : ( + + )} + - + ); } diff --git a/public/app/features/provisioning/Wizard/hooks/useResourceStats.ts b/public/app/features/provisioning/Wizard/hooks/useResourceStats.ts index 03d259303b8..edf90010ce4 100644 --- a/public/app/features/provisioning/Wizard/hooks/useResourceStats.ts +++ b/public/app/features/provisioning/Wizard/hooks/useResourceStats.ts @@ -5,10 +5,52 @@ import { t } from '@grafana/i18n'; import { GetRepositoryFilesApiResponse, GetResourceStatsApiResponse, + ManagerStats, + ResourceCount, useGetRepositoryFilesQuery, useGetResourceStatsQuery, } from 'app/api/clients/provisioning/v0alpha1'; +function getManagedCount(managed?: ManagerStats[]) { + let totalCount = 0; + + // Loop through each managed repository + managed?.forEach((manager) => { + // Loop through stats inside each manager and sum up the counts + manager.stats.forEach((stat) => { + if (stat.group === 'folder.grafana.app' || stat.group === 'dashboard.grafana.app') { + totalCount += stat.count; + } + }); + }); + + return totalCount; +} + +function getResourceCount(stats?: ResourceCount[]) { + let counts: string[] = []; + let resourceCount = 0; + + stats?.forEach((stat) => { + switch (stat.group) { + case 'folders': + case 'folder.grafana.app': + resourceCount += stat.count; + counts.push(t('provisioning.bootstrap-step.folders-count', '{{count}} folder', { count: stat.count })); + break; + case 'dashboard.grafana.app': + resourceCount += stat.count; + counts.push(t('provisioning.bootstrap-step.dashboards-count', '{{count}} dashboard', { count: stat.count })); + break; + } + }); + + return { + counts, + resourceCount, + }; +} + /** * Calculates resource statistics from API responses */ @@ -22,22 +64,7 @@ function getResourceStats(files?: GetRepositoryFilesApiResponse, stats?: GetReso return isSupportedFile(path); }).length; - let counts: string[] = []; - let resourceCount = 0; - - stats?.instance?.forEach((stat) => { - switch (stat.group) { - case 'folders': - case 'folder.grafana.app': - resourceCount += stat.count; - counts.push(t('provisioning.bootstrap-step.folders-count', '{{count}} folder', { count: stat.count })); - break; - case 'dashboard.grafana.app': - resourceCount += stat.count; - counts.push(t('provisioning.bootstrap-step.dashboards-count', '{{count}} dashboard', { count: stat.count })); - break; - } - }); + const { counts, resourceCount } = getResourceCount(stats?.instance); return { fileCount, @@ -60,6 +87,14 @@ export function useResourceStats(repoName?: string, isLegacyStorage?: boolean) { [filesQuery.data, resourceStatsQuery.data] ); + const { managedCount, unmanagedCount } = useMemo(() => { + return { + // managed does not exist in response when first time connecting to a repo + managedCount: getManagedCount(resourceStatsQuery.data?.managed), + unmanagedCount: getResourceCount(resourceStatsQuery.data?.unmanaged).resourceCount, + }; + }, [resourceStatsQuery.data]); + const requiresMigration = isLegacyStorage || resourceCount > 0; const shouldSkipSync = !requiresMigration && resourceCount === 0 && fileCount === 0; @@ -72,6 +107,8 @@ export function useResourceStats(repoName?: string, isLegacyStorage?: boolean) { : t('provisioning.bootstrap-step.empty', 'Empty'); return { + managedCount, + unmanagedCount, resourceCount, resourceCountString: resourceCountDisplay, fileCount, diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 2434af01c23..9e4a0376ac0 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -11384,7 +11384,11 @@ "label-sync-interval": "Sync Interval (seconds)" }, "folder-repository-list": { + "all-resources-managed_one": "All {{count}} resource is managed", + "all-resources-managed_other": "All {{count}} resources are managed", "no-results-matching-your-query": "No results matching your query", + "partial-managed_one": "{{managedCount}}/{{count}} resources managed. {{unmanagedCount}} resources aren't managed as code yet.", + "partial-managed_other": "{{managedCount}}/{{count}} resources managed. {{unmanagedCount}} resources aren't managed as code yet.", "placeholder-search": "Search" }, "get-default-values": {