RepositoryList: Display managed resource count (#110916)
* RepositoryList: display managed resource count * display partial managed alert * Update public/app/features/provisioning/Wizard/hooks/useResourceStats.ts Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com> * Update public/locales/en-US/grafana.json Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com> * only count dashboard and folder --------- Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
This commit is contained in:
co-authored by
Alex Khomenko
parent
1b066c3565
commit
fc2de49b88
@@ -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 (
|
||||
<Stack direction={'column'} gap={3}>
|
||||
{!instanceConnected && (
|
||||
<Stack gap={2}>
|
||||
<FilterInput
|
||||
placeholder={t('provisioning.folder-repository-list.placeholder-search', 'Search')}
|
||||
value={query}
|
||||
onChange={setQuery}
|
||||
/>
|
||||
|
||||
const getResourceCountSection = () => {
|
||||
if (isProvisionedInstance) {
|
||||
return (
|
||||
<Box marginBottom={2}>
|
||||
<Stack alignItems="center">
|
||||
<Icon name="check" color="green" />
|
||||
<Trans i18nKey="provisioning.folder-repository-list.all-resources-managed" count={resourceCount}>
|
||||
All {{ count: resourceCount }} resources are managed
|
||||
</Trans>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
if (filteredItems.length) {
|
||||
return (
|
||||
<Stack>
|
||||
<Alert title={''} severity="info">
|
||||
<Trans
|
||||
i18nKey="provisioning.folder-repository-list.partial-managed"
|
||||
count={resourceCount}
|
||||
values={{ managedCount }}
|
||||
>
|
||||
{{ managedCount }}/{{ count: resourceCount }} resources managed. {{ unmanagedCount }} resources
|
||||
aren't managed as code yet.
|
||||
</Trans>
|
||||
</Alert>
|
||||
</Stack>
|
||||
)}
|
||||
<Stack direction={'column'} gap={2}>
|
||||
{filteredItems.length ? (
|
||||
filteredItems.map((item) => <RepositoryCard key={item.metadata?.name} repository={item} />)
|
||||
) : (
|
||||
<EmptyState
|
||||
variant="not-found"
|
||||
message={t(
|
||||
'provisioning.folder-repository-list.no-results-matching-your-query',
|
||||
'No results matching your query'
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{getResourceCountSection()}
|
||||
<Stack direction={'column'} gap={3}>
|
||||
{!instanceConnected && (
|
||||
<Stack gap={2}>
|
||||
<FilterInput
|
||||
placeholder={t('provisioning.folder-repository-list.placeholder-search', 'Search')}
|
||||
value={query}
|
||||
onChange={setQuery}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
<Stack direction={'column'} gap={2}>
|
||||
{filteredItems.length ? (
|
||||
filteredItems.map((item) => <RepositoryCard key={item.metadata?.name} repository={item} />)
|
||||
) : (
|
||||
<EmptyState
|
||||
variant="not-found"
|
||||
message={t(
|
||||
'provisioning.folder-repository-list.no-results-matching-your-query',
|
||||
'No results matching your query'
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user