Dashboard: Add loading state in Permissions tab (#111962)

This commit is contained in:
Dhruv Jain
2025-10-09 09:55:04 -06:00
committed by GitHub
parent 0d9b5fafc8
commit b296ea27b8
4 changed files with 24 additions and 28 deletions
@@ -1,11 +1,12 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import { sortBy } from 'lodash'; import { sortBy } from 'lodash';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import * as React from 'react'; import * as React from 'react';
import useAsyncFn from 'react-use/lib/useAsyncFn';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { Trans, t } from '@grafana/i18n'; import { Trans, t } from '@grafana/i18n';
import { Text, Box, Button, useStyles2 } from '@grafana/ui'; import { Text, Box, Button, useStyles2, LoadingPlaceholder } from '@grafana/ui';
import { SlideDown } from 'app/core/components/Animations/SlideDown'; import { SlideDown } from 'app/core/components/Animations/SlideDown';
import { getBackendSrv } from 'app/core/services/backend_srv'; import { getBackendSrv } from 'app/core/services/backend_srv';
import { DescendantCount } from 'app/features/browse-dashboards/components/BrowseActions/DescendantCount'; import { DescendantCount } from 'app/features/browse-dashboards/components/BrowseActions/DescendantCount';
@@ -30,7 +31,6 @@ type ResourceId = string | number;
type Type = 'users' | 'teams' | 'serviceAccounts' | 'builtInRoles'; type Type = 'users' | 'teams' | 'serviceAccounts' | 'builtInRoles';
export type Props = { export type Props = {
title?: string;
buttonLabel?: string; buttonLabel?: string;
emptyLabel?: string; emptyLabel?: string;
addPermissionTitle?: string; addPermissionTitle?: string;
@@ -42,7 +42,6 @@ export type Props = {
}; };
export const Permissions = ({ export const Permissions = ({
title = t('access-control.permissions.title', 'Permissions'),
buttonLabel = t('access-control.permissions.add-label', 'Add a permission'), buttonLabel = t('access-control.permissions.add-label', 'Add a permission'),
emptyLabel = t('access-control.permissions.no-permissions', 'There are no permissions'), emptyLabel = t('access-control.permissions.no-permissions', 'There are no permissions'),
resource, resource,
@@ -54,23 +53,22 @@ export const Permissions = ({
}: Props) => { }: Props) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const [isAdding, setIsAdding] = useState(false); const [isAdding, setIsAdding] = useState(false);
const [items, setItems] = useState<ResourcePermission[]>([]);
const [desc, setDesc] = useState(INITIAL_DESCRIPTION); const [desc, setDesc] = useState(INITIAL_DESCRIPTION);
const fetchItems = useCallback(async () => { const [permissions, fetchPermissions] = useAsyncFn(async () => {
let items = await getPermissions(resource, resourceId); let items = await getPermissions(resource, resourceId);
if (getWarnings) { if (getWarnings) {
items = getWarnings(items); items = getWarnings(items);
} }
setItems(items); return items;
}, [resource, resourceId, getWarnings]); }, [resource, resourceId, getWarnings]);
useEffect(() => { useEffect(() => {
getDescription(resource).then((r) => { getDescription(resource).then((r) => {
setDesc(r); setDesc(r);
return fetchItems(); return fetchPermissions();
}); });
}, [resource, resourceId, fetchItems]); }, [resource, fetchPermissions]);
const onAdd = (state: SetPermission) => { const onAdd = (state: SetPermission) => {
let promise: Promise<void> | null = null; let promise: Promise<void> | null = null;
@@ -83,7 +81,7 @@ export const Permissions = ({
} }
if (promise !== null) { if (promise !== null) {
promise.then(fetchItems); promise.then(fetchPermissions);
} }
}; };
@@ -98,7 +96,7 @@ export const Permissions = ({
} }
if (promise !== null) { if (promise !== null) {
promise.then(fetchItems); promise.then(fetchPermissions);
} }
}; };
@@ -119,34 +117,34 @@ export const Permissions = ({
const teams = useMemo( const teams = useMemo(
() => () =>
sortBy( sortBy(
items.filter((i) => i.teamId), (permissions.value || []).filter((i) => i.teamId),
['team', 'isManaged'] ['team', 'isManaged']
), ),
[items] [permissions.value]
); );
const users = useMemo( const users = useMemo(
() => () =>
sortBy( sortBy(
items.filter((i) => i.userId && !i.isServiceAccount), (permissions.value || []).filter((i) => i.userId && !i.isServiceAccount),
['userLogin', 'isManaged'] ['userLogin', 'isManaged']
), ),
[items] [permissions.value]
); );
const serviceAccounts = useMemo( const serviceAccounts = useMemo(
() => () =>
sortBy( sortBy(
items.filter((i) => i.userId && i.isServiceAccount), (permissions.value || []).filter((i) => i.userId && i.isServiceAccount),
['userLogin', 'isManaged'] ['userLogin', 'isManaged']
), ),
[items] [permissions.value]
); );
const builtInRoles = useMemo( const builtInRoles = useMemo(
() => () =>
sortBy( sortBy(
items.filter((i) => i.builtInRole), (permissions.value || []).filter((i) => i.builtInRole),
['builtInRole', 'isManaged'] ['builtInRole', 'isManaged']
), ),
[items] [permissions.value]
); );
const titleRole = t('access-control.permissions.role', 'Role'); const titleRole = t('access-control.permissions.role', 'Role');
@@ -154,6 +152,10 @@ export const Permissions = ({
const titleServiceAccount = t('access-control.permissions.serviceaccount', 'Service Account'); const titleServiceAccount = t('access-control.permissions.serviceaccount', 'Service Account');
const titleTeam = t('access-control.permissions.team', 'Team'); const titleTeam = t('access-control.permissions.team', 'Team');
if (permissions.loading) {
return <LoadingPlaceholder text={t('access-control.permissions.loading', 'Loading permissions...')} />;
}
return ( return (
<> <>
<div> <div>
@@ -172,7 +174,7 @@ export const Permissions = ({
/> />
</Box> </Box>
)} )}
{items.length === 0 && ( {permissions.value?.length === 0 && (
<Box> <Box>
<Text>{emptyLabel}</Text> <Text>{emptyLabel}</Text>
</Box> </Box>
@@ -236,7 +238,7 @@ export const Permissions = ({
</> </>
)} )}
</div> </div>
{epilogue && epilogue(items)} {epilogue && epilogue(permissions.value || [])}
</> </>
); );
}; };
@@ -1,4 +1,3 @@
import { t } from '@grafana/i18n';
import { Permissions } from 'app/core/components/AccessControl'; import { Permissions } from 'app/core/components/AccessControl';
import { contextSrv } from 'app/core/services/context_srv'; import { contextSrv } from 'app/core/services/context_srv';
import { AccessControlAction } from 'app/types/accessControl'; import { AccessControlAction } from 'app/types/accessControl';
@@ -16,7 +15,6 @@ export const ServiceAccountPermissions = (props: ServiceAccountPermissionsProps)
return ( return (
<Permissions <Permissions
title={t('serviceaccounts.service-account-permissions.title-permissions', 'Permissions')}
addPermissionTitle="Add permission" addPermissionTitle="Add permission"
buttonLabel="Add permission" buttonLabel="Add permission"
resource="serviceaccounts" resource="serviceaccounts"
@@ -20,7 +20,6 @@ const TeamPermissions = (props: TeamPermissionsProps) => {
return ( return (
<Permissions <Permissions
title=""
addPermissionTitle="Add member" addPermissionTitle="Add member"
buttonLabel="Add member" buttonLabel="Add member"
emptyLabel="There are no members in this team or you do not have the permissions to list the current members." emptyLabel="There are no members in this team or you do not have the permissions to list the current members."
+1 -4
View File
@@ -27,12 +27,12 @@
}, },
"permissions": { "permissions": {
"add-label": "Add a permission", "add-label": "Add a permission",
"loading": "Loading permissions...",
"no-permissions": "There are no permissions", "no-permissions": "There are no permissions",
"permissions-change-warning": "This will change permissions for this folder and all its descendants. In total, this will affect:", "permissions-change-warning": "This will change permissions for this folder and all its descendants. In total, this will affect:",
"role": "Role", "role": "Role",
"serviceaccount": "Service Account", "serviceaccount": "Service Account",
"team": "Team", "team": "Team",
"title": "Permissions",
"user": "User" "user": "User"
} }
}, },
@@ -12285,9 +12285,6 @@
"tokens": "Tokens", "tokens": "Tokens",
"tooltip-managed-service-account-cannot-modified": "This is a managed service account and cannot be modified" "tooltip-managed-service-account-cannot-modified": "This is a managed service account and cannot be modified"
}, },
"service-account-permissions": {
"title-permissions": "Permissions"
},
"service-account-profile": { "service-account-profile": {
"information": "Information", "information": "Information",
"label-creation-date": "Creation date", "label-creation-date": "Creation date",