mirror of
https://github.com/Unleash/unleash.git
synced 2024-12-22 19:07:54 +01:00
feat: add a button to download user access information (#4746)
This commit is contained in:
parent
53c40372dd
commit
7843c93dc5
17
frontend/src/component/accessOverview/AccessOverview.tsx
Normal file
17
frontend/src/component/accessOverview/AccessOverview.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||
import { PermissionGuard } from 'component/common/PermissionGuard/PermissionGuard';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature';
|
||||
import { IconButton } from '@mui/material';
|
||||
import { Download } from '@mui/icons-material';
|
||||
import { useAccessOverviewApi } from 'hooks/api/actions/useAccessOverviewApi/useAccessOverviewApi';
|
||||
|
||||
export const AccessOverview = () => {
|
||||
const { downloadCSV } = useAccessOverviewApi();
|
||||
|
||||
return (
|
||||
<IconButton onClick={downloadCSV}>
|
||||
<Download />
|
||||
</IconButton>
|
||||
);
|
||||
};
|
@ -6,6 +6,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
|
||||
import ConfirmUserAdded from '../ConfirmUserAdded/ConfirmUserAdded';
|
||||
import { useUsers } from 'hooks/api/getters/useUsers/useUsers';
|
||||
import useAdminUsersApi from 'hooks/api/actions/useAdminUsersApi/useAdminUsersApi';
|
||||
import { useAccessOverviewApi } from 'hooks/api/actions/useAccessOverviewApi/useAccessOverviewApi';
|
||||
import { IUser } from 'interfaces/user';
|
||||
import { IRole } from 'interfaces/role';
|
||||
import useToast from 'hooks/useToast';
|
||||
@ -13,7 +14,7 @@ import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import { useUsersPlan } from 'hooks/useUsersPlan';
|
||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||
import { Button, useMediaQuery } from '@mui/material';
|
||||
import { Button, IconButton, Tooltip, useMediaQuery } from '@mui/material';
|
||||
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||
import { UserTypeCell } from './UserTypeCell/UserTypeCell';
|
||||
import { useFlexLayout, useSortBy, useTable } from 'react-table';
|
||||
@ -31,12 +32,15 @@ import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColum
|
||||
import { UserLimitWarning } from './UserLimitWarning/UserLimitWarning';
|
||||
import { RoleCell } from 'component/common/Table/cells/RoleCell/RoleCell';
|
||||
import { useSearch } from 'hooks/useSearch';
|
||||
import { Download } from '@mui/icons-material';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
|
||||
const UsersList = () => {
|
||||
const navigate = useNavigate();
|
||||
const { users, roles, refetch, loading } = useUsers();
|
||||
const { setToastData, setToastApiError } = useToast();
|
||||
const { removeUser, userLoading, userApiErrors } = useAdminUsersApi();
|
||||
const { downloadCSV } = useAccessOverviewApi();
|
||||
const [pwDialog, setPwDialog] = useState<{ open: boolean; user?: IUser }>({
|
||||
open: false,
|
||||
});
|
||||
@ -47,6 +51,8 @@ const UsersList = () => {
|
||||
const [delUser, setDelUser] = useState<IUser>();
|
||||
const { planUsers, isBillingUsers } = useUsersPlan(users);
|
||||
|
||||
const accessOverviewEnabled = useUiFlag('accessOverview');
|
||||
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
|
||||
const isExtraSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
@ -263,6 +269,23 @@ const UsersList = () => {
|
||||
onChange={setSearchValue}
|
||||
/>
|
||||
<PageHeader.Divider />
|
||||
|
||||
<ConditionallyRender
|
||||
condition={Boolean(accessOverviewEnabled)}
|
||||
show={() => (
|
||||
<>
|
||||
<Tooltip
|
||||
title="Exports user access information"
|
||||
arrow
|
||||
describeChild
|
||||
>
|
||||
<IconButton onClick={downloadCSV}>
|
||||
<Download />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
|
@ -0,0 +1,30 @@
|
||||
import useAPI from '../useApi/useApi';
|
||||
|
||||
export const useAccessOverviewApi = () => {
|
||||
const { loading, makeRequest, createRequest, errors } = useAPI({
|
||||
propagateErrors: true,
|
||||
});
|
||||
|
||||
const downloadCSV = async () => {
|
||||
const requestId = 'downloadCSV';
|
||||
const req = createRequest(
|
||||
'api/admin/access/overview',
|
||||
{
|
||||
method: 'GET',
|
||||
responseType: 'blob',
|
||||
headers: { Accept: 'text/csv' },
|
||||
},
|
||||
requestId
|
||||
);
|
||||
|
||||
const file = await (await makeRequest(req.caller, req.id)).blob();
|
||||
const url = window.URL.createObjectURL(file);
|
||||
window.location.assign(url);
|
||||
};
|
||||
|
||||
return {
|
||||
downloadCSV,
|
||||
errors,
|
||||
loading,
|
||||
};
|
||||
};
|
@ -66,6 +66,7 @@ export type UiFlags = {
|
||||
doraMetrics?: boolean;
|
||||
variantTypeNumber?: boolean;
|
||||
privateProjects?: boolean;
|
||||
accessOverview?: boolean;
|
||||
[key: string]: boolean | Variant | undefined;
|
||||
};
|
||||
|
||||
|
@ -71,6 +71,7 @@ exports[`should create default config 1`] = `
|
||||
"isEnabled": [Function],
|
||||
},
|
||||
"flags": {
|
||||
"accessOverview": false,
|
||||
"anonymiseEventLog": false,
|
||||
"caseInsensitiveInOperators": false,
|
||||
"customRootRolesKillSwitch": false,
|
||||
@ -108,6 +109,7 @@ exports[`should create default config 1`] = `
|
||||
},
|
||||
"flagResolver": FlagResolver {
|
||||
"experiments": {
|
||||
"accessOverview": false,
|
||||
"anonymiseEventLog": false,
|
||||
"caseInsensitiveInOperators": false,
|
||||
"customRootRolesKillSwitch": false,
|
||||
|
@ -29,6 +29,7 @@ export type IFlagKey =
|
||||
| 'featureNamingPattern'
|
||||
| 'doraMetrics'
|
||||
| 'variantTypeNumber'
|
||||
| 'accessOverview'
|
||||
| 'privateProjects';
|
||||
|
||||
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
|
||||
@ -137,6 +138,10 @@ const flags: IFlags = {
|
||||
process.env.UNLEASH_EXPERIMENTAL_PRIVATE_PROJECTS,
|
||||
false,
|
||||
),
|
||||
accessOverview: parseEnvVarBoolean(
|
||||
process.env.UNLEASH_EXPERIMENTAL_ACCESS_OVERVIEW,
|
||||
false,
|
||||
),
|
||||
};
|
||||
|
||||
export const defaultExperimentalOptions: IExperimentalOptions = {
|
||||
|
@ -44,6 +44,7 @@ process.nextTick(async () => {
|
||||
doraMetrics: true,
|
||||
variantTypeNumber: true,
|
||||
privateProjects: true,
|
||||
accessOverview: true,
|
||||
},
|
||||
},
|
||||
authentication: {
|
||||
|
Loading…
Reference in New Issue
Block a user