1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-15 01:16:22 +02:00

feat: licensed users ui rework (#8809)

1. Moved link creation bottom next to licensed users view
2. Created licensed users component
3. Added flag

OSS:

![image](https://github.com/user-attachments/assets/cfb2b971-3861-4093-91a5-f3118b906029)
All others

![image](https://github.com/user-attachments/assets/e8cf712f-7e66-44f6-9965-1bb785e4f3fc)
This commit is contained in:
Jaanus Sellin 2024-11-21 11:46:40 +02:00 committed by GitHub
parent 6d75ad73d4
commit c18952f374
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 117 additions and 27 deletions

View File

@ -1,5 +1,4 @@
import type { VFC } from 'react';
import { Box } from '@mui/material';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
import { InviteLinkBarContent } from './InviteLinkBarContent';
@ -15,24 +14,5 @@ export const InviteLinkBar: VFC = () => {
});
};
return (
<Box
sx={(theme) => ({
backgroundColor: theme.palette.background.paper,
py: 2,
px: 4,
mb: 2,
borderRadius: `${theme.shape.borderRadiusLarge}px`,
display: 'flex',
flexDirection: {
xs: 'column',
md: 'row',
},
border: '2px solid',
borderColor: theme.palette.background.alternative,
})}
>
<InviteLinkBarContent onActionClick={onInviteLinkActionClick} />
</Box>
);
return <InviteLinkBarContent onActionClick={onInviteLinkActionClick} />;
};

View File

@ -104,9 +104,8 @@ export const InviteLinkBarContent = ({
}
elseShow={
<Typography variant='body2' data-loading>
You can easily create an invite link here that you
can share and use to invite people from your company
to your Unleash setup.
Create a link to invite people from your company to
your Unleash setup.
</Typography>
}
/>

View File

@ -1,7 +1,6 @@
import UsersList from './UsersList/UsersList';
import { ADMIN } from 'component/providers/AccessProvider/permissions';
import { PermissionGuard } from 'component/common/PermissionGuard/PermissionGuard';
import { InviteLinkBar } from './InviteLinkBar/InviteLinkBar';
import { Route, Routes } from 'react-router-dom';
import EditUser from './EditUser/EditUser';
import NotFound from 'component/common/NotFound/NotFound';
@ -21,7 +20,6 @@ export const UsersAdmin = () => {
index
element={
<>
<InviteLinkBar />
<UsersList />
</>
}

View File

@ -0,0 +1,56 @@
import { Box, Button, styled, Typography } from '@mui/material';
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
const StyledContainer = styled(Box)(({ theme }) => ({
display: 'flex',
flexDirection: 'row',
width: '100%',
justifyContent: 'space-between',
alignItems: 'center',
}));
const StyledColumn = styled(Box)({
display: 'flex',
flexDirection: 'column',
});
const RightColumn = styled(StyledColumn)({
alignItems: 'flex-end',
});
const StyledButton = styled(Button)(({ theme }) => ({
fontSize: theme.spacing(1.75),
textDecoration: 'underline',
'&:hover': {
backgroundColor: theme.palette.background.paper,
},
fontWeight: theme.typography.h4.fontWeight,
}));
export const LicensedUsersBox = () => {
return (
<StyledContainer>
<StyledColumn>
<Typography variant='body1' fontWeight='bold'>
11/25
</Typography>
<Typography variant='body2'>Seats used last 30 days</Typography>
</StyledColumn>
<RightColumn>
<HelpIcon
htmlTooltip
tooltip={
<Box>
A licensed seat is a unique user that had access to
your instance within the last 30 days, and thereby
occupied a seat.
</Box>
}
/>
<StyledButton onClick={() => {}}>
View graph over time
</StyledButton>
</RightColumn>
</StyledContainer>
);
};

View File

@ -0,0 +1,47 @@
import { Box, styled } from '@mui/material';
import { InviteLinkBar } from '../InviteLinkBar/InviteLinkBar';
import { useUiFlag } from 'hooks/useUiFlag';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { LicensedUsersBox } from './LicensedUsersBox';
interface StyledContainerProps {
licensedUsersEnabled: boolean;
}
const StyledContainer = styled(Box)<StyledContainerProps>(
({ theme, licensedUsersEnabled }) => ({
display: 'grid',
gridTemplateColumns: licensedUsersEnabled ? '60% 40%' : '100%',
gap: theme.spacing(2),
paddingBottom: theme.spacing(3),
}),
);
const StyledElement = styled(Box)(({ theme }) => ({
backgroundColor: theme.palette.background.paper,
padding: theme.spacing(2, 3, 2, 2),
borderRadius: `${theme.shape.borderRadiusLarge}px`,
display: 'flex',
border: '2px solid',
borderColor: theme.palette.background.alternative,
}));
export const UsersHeader = () => {
const licensedUsers = useUiFlag('licensedUsers');
const { isOss } = useUiConfig();
const licensedUsersEnabled = licensedUsers && isOss();
return (
<StyledContainer licensedUsersEnabled={licensedUsersEnabled}>
<StyledElement>
<InviteLinkBar />
</StyledElement>
{licensedUsersEnabled && (
<StyledElement>
<LicensedUsersBox />
</StyledElement>
)}
</StyledContainer>
);
};

View File

@ -40,6 +40,7 @@ import { useUiFlag } from 'hooks/useUiFlag';
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
import { useScimSettings } from 'hooks/api/getters/useScimSettings/useScimSettings';
import { UserSessionsCell } from './UserSessionsCell/UserSessionsCell';
import { UsersHeader } from '../UsersHeader/UsersHeader';
import { UpgradeSSO } from './UpgradeSSO';
const UsersList = () => {
@ -355,6 +356,7 @@ const UsersList = () => {
</StyledUsersLinkDiv>
}
/>
<UsersHeader />
<SearchHighlightProvider value={getSearchText(searchValue)}>
<VirtualizedTable
rows={rows}
@ -362,6 +364,7 @@ const UsersList = () => {
prepareRow={prepareRow}
/>
</SearchHighlightProvider>
<ConditionallyRender
condition={rows.length === 0}
show={

View File

@ -95,6 +95,7 @@ export type UiFlags = {
productivityReportEmail?: boolean;
showUserDeviceCount?: boolean;
flagOverviewRedesign?: boolean;
licensedUsers?: boolean;
};
export interface IVersionInfo {

View File

@ -61,7 +61,8 @@ export type IFlagKey =
| 'flagOverviewRedesign'
| 'showUserDeviceCount'
| 'deleteStaleUserSessions'
| 'memorizeStats';
| 'memorizeStats'
| 'licensedUsers';
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
@ -289,6 +290,10 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_FLAG_OVERVIEW_REDESIGN,
false,
),
licensedUsers: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_FLAG_LICENSED_USERS,
false,
),
};
export const defaultExperimentalOptions: IExperimentalOptions = {

View File

@ -57,6 +57,7 @@ process.nextTick(async () => {
simplifyProjectOverview: true,
showUserDeviceCount: true,
flagOverviewRedesign: false,
licensedUsers: true,
},
},
authentication: {