Admin panel fixes (#10792)
<img width="573" alt="Screenshot 2025-03-12 at 17 36 44" src="https://github.com/user-attachments/assets/be6c20b0-626d-4a2c-810c-78a49e9f65ee" /> <img width="579" alt="Screenshot 2025-03-12 at 17 37 03" src="https://github.com/user-attachments/assets/23692ff8-ac88-4104-823e-1a06b3074551" /> <img width="590" alt="Screenshot 2025-03-12 at 17 37 14" src="https://github.com/user-attachments/assets/b46de1d3-a312-44cc-a54d-72208224453d" /> <img width="556" alt="Screenshot 2025-03-12 at 17 37 37" src="https://github.com/user-attachments/assets/12176d49-d76d-4fb1-abe6-1f7dc5349d94" /> <img width="607" alt="Screenshot 2025-03-12 at 17 37 50" src="https://github.com/user-attachments/assets/00e2edff-09db-45c5-a4df-6fd9ead830b6" />
This commit is contained in:
@ -1,8 +1,19 @@
|
||||
import { Button, H2Title, IconUser, Toggle } from 'twenty-ui';
|
||||
import {
|
||||
AvatarChip,
|
||||
Button,
|
||||
H2Title,
|
||||
IconEyeShare,
|
||||
IconHome,
|
||||
IconId,
|
||||
IconUser,
|
||||
Section,
|
||||
Toggle,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { canManageFeatureFlagsState } from '@/client-config/states/canManageFeatureFlagsState';
|
||||
import { SettingsAdminTableCard } from '@/settings/admin-panel/components/SettingsAdminTableCard';
|
||||
import { useFeatureFlagState } from '@/settings/admin-panel/hooks/useFeatureFlagState';
|
||||
import { useImpersonationAuth } from '@/settings/admin-panel/hooks/useImpersonationAuth';
|
||||
import { useImpersonationRedirect } from '@/settings/admin-panel/hooks/useImpersonationRedirect';
|
||||
@ -11,14 +22,18 @@ import { WorkspaceInfo } from '@/settings/admin-panel/types/WorkspaceInfo';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { Table } from '@/ui/layout/table/components/Table';
|
||||
import { TableBody } from '@/ui/layout/table/components/TableBody';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { DEFAULT_WORKSPACE_LOGO } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useState } from 'react';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { getImageAbsoluteURI, isDefined } from 'twenty-shared';
|
||||
import { REACT_APP_SERVER_BASE_URL } from '~/config';
|
||||
import {
|
||||
FeatureFlagKey,
|
||||
useImpersonateMutation,
|
||||
@ -29,7 +44,14 @@ type SettingsAdminWorkspaceContentProps = {
|
||||
activeWorkspace: WorkspaceInfo | undefined;
|
||||
};
|
||||
|
||||
const StyledTable = styled(Table)`
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(3)};
|
||||
margin-top: ${({ theme }) => theme.spacing(6)};
|
||||
`;
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
margin-top: ${({ theme }) => theme.spacing(3)};
|
||||
`;
|
||||
|
||||
@ -115,64 +137,101 @@ export const SettingsAdminWorkspaceContent = ({
|
||||
});
|
||||
};
|
||||
|
||||
const workspaceInfoItems = [
|
||||
{
|
||||
Icon: IconHome,
|
||||
label: t`Name`,
|
||||
value: (
|
||||
<AvatarChip
|
||||
name={activeWorkspace?.name ?? ''}
|
||||
avatarUrl={
|
||||
getImageAbsoluteURI({
|
||||
imageUrl: isNonEmptyString(activeWorkspace?.logo)
|
||||
? activeWorkspace?.logo
|
||||
: DEFAULT_WORKSPACE_LOGO,
|
||||
baseUrl: REACT_APP_SERVER_BASE_URL,
|
||||
}) ?? ''
|
||||
}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
Icon: IconId,
|
||||
label: t`ID`,
|
||||
value: activeWorkspace?.id,
|
||||
},
|
||||
{
|
||||
Icon: IconUser,
|
||||
label: t`Members`,
|
||||
value: activeWorkspace?.totalUsers,
|
||||
},
|
||||
];
|
||||
|
||||
if (!activeWorkspace) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<H2Title title={activeWorkspace.name} description={t`Workspace Name`} />
|
||||
<H2Title
|
||||
title={`${activeWorkspace.totalUsers} ${
|
||||
activeWorkspace.totalUsers > 1 ? t`Users` : t`User`
|
||||
}`}
|
||||
description={t`Total Users`}
|
||||
/>
|
||||
{currentUser?.canImpersonate && (
|
||||
<Button
|
||||
Icon={IconUser}
|
||||
variant="primary"
|
||||
accent="blue"
|
||||
title={t`Impersonate`}
|
||||
onClick={() => handleImpersonate(activeWorkspace.id)}
|
||||
disabled={
|
||||
isImpersonateLoading || activeWorkspace.allowImpersonation === false
|
||||
}
|
||||
dataTestId="impersonate-button"
|
||||
<StyledContainer>
|
||||
<Section>
|
||||
<H2Title
|
||||
title={t`Workspace Info`}
|
||||
description={t`About this workspace`}
|
||||
/>
|
||||
)}
|
||||
|
||||
<SettingsAdminTableCard
|
||||
items={workspaceInfoItems}
|
||||
gridAutoColumns="1fr 4fr"
|
||||
/>
|
||||
<StyledButtonContainer>
|
||||
{currentUser?.canImpersonate && (
|
||||
<Button
|
||||
Icon={IconEyeShare}
|
||||
variant="primary"
|
||||
accent="default"
|
||||
title={t`Impersonate`}
|
||||
onClick={() => handleImpersonate(activeWorkspace.id)}
|
||||
disabled={
|
||||
isImpersonateLoading ||
|
||||
activeWorkspace.allowImpersonation === false
|
||||
}
|
||||
dataTestId="impersonate-button"
|
||||
/>
|
||||
)}
|
||||
</StyledButtonContainer>
|
||||
</Section>
|
||||
{canManageFeatureFlags && (
|
||||
<StyledTable>
|
||||
<TableRow
|
||||
gridAutoColumns="1fr 100px"
|
||||
mobileGridAutoColumns="1fr 80px"
|
||||
>
|
||||
<TableHeader>{t`Feature Flag`}</TableHeader>
|
||||
<TableHeader align="right">{t`Status`}</TableHeader>
|
||||
</TableRow>
|
||||
|
||||
{activeWorkspace.featureFlags.map((flag) => (
|
||||
<Table>
|
||||
<TableBody>
|
||||
<TableRow
|
||||
gridAutoColumns="1fr 100px"
|
||||
mobileGridAutoColumns="1fr 80px"
|
||||
key={flag.key}
|
||||
>
|
||||
<TableCell>{flag.key}</TableCell>
|
||||
<TableCell align="right">
|
||||
<Toggle
|
||||
value={flag.value}
|
||||
onChange={(newValue) =>
|
||||
handleFeatureFlagUpdate(
|
||||
activeWorkspace.id,
|
||||
flag.key,
|
||||
newValue,
|
||||
)
|
||||
}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableHeader>{t`Feature Flag`}</TableHeader>
|
||||
<TableHeader align="right">{t`Status`}</TableHeader>
|
||||
</TableRow>
|
||||
))}
|
||||
</StyledTable>
|
||||
|
||||
{activeWorkspace.featureFlags.map((flag) => (
|
||||
<TableRow
|
||||
gridAutoColumns="1fr 100px"
|
||||
mobileGridAutoColumns="1fr 80px"
|
||||
key={flag.key}
|
||||
>
|
||||
<TableCell>{flag.key}</TableCell>
|
||||
<TableCell align="right">
|
||||
<Toggle
|
||||
value={flag.value}
|
||||
onChange={(newValue) =>
|
||||
handleFeatureFlagUpdate(
|
||||
activeWorkspace.id,
|
||||
flag.key,
|
||||
newValue,
|
||||
)
|
||||
}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
)}
|
||||
</>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user