Fix permissions front followup (#10758)
This commit is contained in:
@ -7,16 +7,17 @@ import { RolesTableRow } from '@/settings/roles/components/RolesTableRow';
|
|||||||
import { Button, H2Title, IconPlus, Section } from 'twenty-ui';
|
import { Button, H2Title, IconPlus, Section } from 'twenty-ui';
|
||||||
import { Role } from '~/generated-metadata/graphql';
|
import { Role } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
const StyledTable = styled(Table)`
|
const StyledCreateRoleSection = styled(Section)`
|
||||||
margin-top: ${({ theme }) => theme.spacing(0.5)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledBottomSection = styled(Section)`
|
|
||||||
border-top: 1px solid ${({ theme }) => theme.border.color.light};
|
border-top: 1px solid ${({ theme }) => theme.border.color.light};
|
||||||
margin-top: ${({ theme }) => theme.spacing(2)};
|
|
||||||
padding-top: ${({ theme }) => theme.spacing(4)};
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
padding-top: ${({ theme }) => theme.spacing(2)};
|
||||||
|
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledTableRows = styled.div`
|
||||||
|
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
|
padding-top: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Roles = ({ roles }: { roles: Role[] }) => {
|
export const Roles = ({ roles }: { roles: Role[] }) => {
|
||||||
@ -26,13 +27,15 @@ export const Roles = ({ roles }: { roles: Role[] }) => {
|
|||||||
title={t`All roles`}
|
title={t`All roles`}
|
||||||
description={t`Assign roles to specify each member's access permissions`}
|
description={t`Assign roles to specify each member's access permissions`}
|
||||||
/>
|
/>
|
||||||
<StyledTable>
|
<Table>
|
||||||
<RolesTableHeader />
|
<RolesTableHeader />
|
||||||
{roles.map((role) => (
|
<StyledTableRows>
|
||||||
<RolesTableRow key={role.id} role={role} />
|
{roles.map((role) => (
|
||||||
))}
|
<RolesTableRow key={role.id} role={role} />
|
||||||
</StyledTable>
|
))}
|
||||||
<StyledBottomSection>
|
</StyledTableRows>
|
||||||
|
</Table>
|
||||||
|
<StyledCreateRoleSection>
|
||||||
<Button
|
<Button
|
||||||
Icon={IconPlus}
|
Icon={IconPlus}
|
||||||
title={t`Create Role`}
|
title={t`Create Role`}
|
||||||
@ -40,7 +43,7 @@ export const Roles = ({ roles }: { roles: Role[] }) => {
|
|||||||
size="small"
|
size="small"
|
||||||
soon
|
soon
|
||||||
/>
|
/>
|
||||||
</StyledBottomSection>
|
</StyledCreateRoleSection>
|
||||||
</Section>
|
</Section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,25 +1,20 @@
|
|||||||
import { Table } from '@/ui/layout/table/components/Table';
|
import { Table } from '@/ui/layout/table/components/Table';
|
||||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||||
import styled from '@emotion/styled';
|
|
||||||
import { Trans } from '@lingui/react/macro';
|
import { Trans } from '@lingui/react/macro';
|
||||||
|
|
||||||
const StyledTableHeaderRow = styled(Table)`
|
|
||||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const RolesTableHeader = () => {
|
export const RolesTableHeader = () => {
|
||||||
return (
|
return (
|
||||||
<StyledTableHeaderRow>
|
<Table>
|
||||||
<TableRow gridAutoColumns="3fr 2fr 1fr">
|
<TableRow gridAutoColumns="332px 3fr 2fr 1fr">
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<Trans>Name</Trans>
|
<Trans>Name</Trans>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableHeader align={'right'}>
|
<TableHeader align={'right'}>
|
||||||
<Trans>Assigned to</Trans>
|
<Trans>Assigned to</Trans>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableHeader align={'right'}></TableHeader>
|
<TableHeader></TableHeader>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</StyledTableHeaderRow>
|
</Table>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,36 +15,20 @@ import {
|
|||||||
import { Role } from '~/generated-metadata/graphql';
|
import { Role } from '~/generated-metadata/graphql';
|
||||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||||
|
|
||||||
const StyledIconChevronRight = styled(IconChevronRight)`
|
|
||||||
color: ${({ theme }) => theme.font.color.tertiary};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledAvatarContainer = styled.div`
|
|
||||||
border: 0px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledAssignedText = styled.div`
|
const StyledAssignedText = styled.div`
|
||||||
color: ${({ theme }) => theme.font.color.secondary};
|
color: ${({ theme }) => theme.font.color.secondary};
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledNameCell = styled.div`
|
const StyledNameCell = styled.div`
|
||||||
align-items: center;
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: ${({ theme }) => theme.spacing(1)};
|
gap: ${({ theme }) => theme.spacing(1)};
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledAssignedCell = styled.div`
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
gap: ${({ theme }) => theme.spacing(4)};
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledAvatarGroup = styled.div`
|
const StyledAvatarGroup = styled.div`
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-right: ${({ theme }) => theme.spacing(1)};
|
justify-content: flex-end;
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
margin-left: -5px;
|
margin-left: -5px;
|
||||||
@ -55,6 +39,12 @@ const StyledAvatarGroup = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledIconLockContainer = styled.div`
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
`;
|
||||||
|
|
||||||
const StyledTableRow = styled(TableRow)`
|
const StyledTableRow = styled(TableRow)`
|
||||||
&:hover {
|
&:hover {
|
||||||
background: ${({ theme }) => theme.background.transparent.light};
|
background: ${({ theme }) => theme.background.transparent.light};
|
||||||
@ -74,48 +64,57 @@ export const RolesTableRow = ({ role }: { role: Role }) => {
|
|||||||
return (
|
return (
|
||||||
<StyledTableRow
|
<StyledTableRow
|
||||||
key={role.id}
|
key={role.id}
|
||||||
gridAutoColumns="3fr 2fr 1fr"
|
gridAutoColumns="332px 3fr 2fr 1fr"
|
||||||
onClick={() => handleRoleClick(role.id)}
|
onClick={() => handleRoleClick(role.id)}
|
||||||
>
|
>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<StyledNameCell>
|
<StyledNameCell>
|
||||||
<IconUser size={theme.icon.size.md} />
|
<IconUser size={theme.icon.size.md} stroke={theme.icon.stroke.sm} />
|
||||||
{role.label}
|
{role.label}
|
||||||
{!role.isEditable && <IconLock size={theme.icon.size.sm} />}
|
{!role.isEditable && (
|
||||||
|
<StyledIconLockContainer>
|
||||||
|
<IconLock
|
||||||
|
color={theme.font.color.light}
|
||||||
|
stroke={theme.icon.stroke.sm}
|
||||||
|
size={theme.icon.size.sm}
|
||||||
|
/>
|
||||||
|
</StyledIconLockContainer>
|
||||||
|
)}
|
||||||
</StyledNameCell>
|
</StyledNameCell>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align={'right'}>
|
<TableCell align={'right'}>
|
||||||
<StyledAssignedCell>
|
<StyledAvatarGroup>
|
||||||
<StyledAvatarGroup>
|
{role.workspaceMembers.slice(0, 5).map((workspaceMember) => (
|
||||||
{role.workspaceMembers.slice(0, 5).map((workspaceMember) => (
|
<React.Fragment key={workspaceMember.id}>
|
||||||
<React.Fragment key={workspaceMember.id}>
|
<div id={`avatar-${workspaceMember.id}`}>
|
||||||
<StyledAvatarContainer id={`avatar-${workspaceMember.id}`}>
|
<Avatar
|
||||||
<Avatar
|
avatarUrl={workspaceMember.avatarUrl}
|
||||||
avatarUrl={workspaceMember.avatarUrl}
|
placeholderColorSeed={workspaceMember.id}
|
||||||
placeholderColorSeed={workspaceMember.id}
|
placeholder={workspaceMember.name.firstName ?? ''}
|
||||||
placeholder={workspaceMember.name.firstName ?? ''}
|
type="rounded"
|
||||||
type="rounded"
|
size="md"
|
||||||
size="md"
|
|
||||||
/>
|
|
||||||
</StyledAvatarContainer>
|
|
||||||
<AppTooltip
|
|
||||||
anchorSelect={`#avatar-${workspaceMember.id}`}
|
|
||||||
content={`${workspaceMember.name.firstName} ${workspaceMember.name.lastName}`}
|
|
||||||
noArrow
|
|
||||||
place="top"
|
|
||||||
positionStrategy="fixed"
|
|
||||||
delay={TooltipDelay.shortDelay}
|
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</div>
|
||||||
))}
|
<AppTooltip
|
||||||
</StyledAvatarGroup>
|
anchorSelect={`#avatar-${workspaceMember.id}`}
|
||||||
<StyledAssignedText>
|
content={`${workspaceMember.name.firstName} ${workspaceMember.name.lastName}`}
|
||||||
{role.workspaceMembers.length}
|
noArrow
|
||||||
</StyledAssignedText>
|
place="top"
|
||||||
</StyledAssignedCell>
|
positionStrategy="fixed"
|
||||||
|
delay={TooltipDelay.shortDelay}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</StyledAvatarGroup>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align={'left'}>
|
||||||
|
<StyledAssignedText>{role.workspaceMembers.length}</StyledAssignedText>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align={'right'}>
|
<TableCell align={'right'}>
|
||||||
<StyledIconChevronRight size={theme.icon.size.md} />
|
<IconChevronRight
|
||||||
|
size={theme.icon.size.md}
|
||||||
|
color={theme.font.color.tertiary}
|
||||||
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</StyledTableRow>
|
</StyledTableRow>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -38,7 +38,7 @@ const StyledAssignToMemberContainer = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledSearchContainer = styled.div`
|
const StyledSearchContainer = styled.div`
|
||||||
margin: ${({ theme }) => theme.spacing(2)} 0;
|
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTable = styled.div<{ hasRows: boolean }>`
|
const StyledTable = styled.div<{ hasRows: boolean }>`
|
||||||
@ -57,6 +57,12 @@ const StyledSearchInput = styled(TextInput)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledTableRows = styled.div`
|
||||||
|
gap: ${({ theme }) => theme.spacing(0.5)};
|
||||||
|
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
|
padding-top: ${({ theme }) => theme.spacing(2)};
|
||||||
|
`;
|
||||||
|
|
||||||
type RoleAssignmentProps = {
|
type RoleAssignmentProps = {
|
||||||
role: Pick<Role, 'id' | 'label' | 'canUpdateAllSettings'> & {
|
role: Pick<Role, 'id' | 'label' | 'canUpdateAllSettings'> & {
|
||||||
workspaceMembers: Array<WorkspaceMember>;
|
workspaceMembers: Array<WorkspaceMember>;
|
||||||
@ -177,12 +183,14 @@ export const RoleAssignment = ({ role }: RoleAssignmentProps) => {
|
|||||||
</StyledSearchContainer>
|
</StyledSearchContainer>
|
||||||
<StyledTable hasRows={filteredWorkspaceMembers.length > 0}>
|
<StyledTable hasRows={filteredWorkspaceMembers.length > 0}>
|
||||||
<RoleAssignmentTableHeader />
|
<RoleAssignmentTableHeader />
|
||||||
{filteredWorkspaceMembers.map((workspaceMember) => (
|
<StyledTableRows>
|
||||||
<RoleAssignmentTableRow
|
{filteredWorkspaceMembers.map((workspaceMember) => (
|
||||||
key={workspaceMember.id}
|
<RoleAssignmentTableRow
|
||||||
workspaceMember={workspaceMember}
|
key={workspaceMember.id}
|
||||||
/>
|
workspaceMember={workspaceMember}
|
||||||
))}
|
/>
|
||||||
|
))}
|
||||||
|
</StyledTableRows>
|
||||||
</StyledTable>
|
</StyledTable>
|
||||||
|
|
||||||
<StyledAssignToMemberContainer>
|
<StyledAssignToMemberContainer>
|
||||||
|
|||||||
@ -1,18 +1,13 @@
|
|||||||
import { Table } from '@/ui/layout/table/components/Table';
|
import { Table } from '@/ui/layout/table/components/Table';
|
||||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||||
import styled from '@emotion/styled';
|
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
|
|
||||||
const StyledTableHeaderRow = styled(Table)`
|
|
||||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const RoleAssignmentTableHeader = () => (
|
export const RoleAssignmentTableHeader = () => (
|
||||||
<StyledTableHeaderRow>
|
<Table>
|
||||||
<TableRow gridAutoColumns="2fr 4fr">
|
<TableRow gridAutoColumns="2fr 4fr">
|
||||||
<TableHeader>{t`Name`}</TableHeader>
|
<TableHeader>{t`Name`}</TableHeader>
|
||||||
<TableHeader>{t`Email`}</TableHeader>
|
<TableHeader>{t`Email`}</TableHeader>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</StyledTableHeaderRow>
|
</Table>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -18,8 +18,6 @@ const StyledPermissionCell = styled(TableCell)`
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
gap: ${({ theme }) => theme.spacing(2)};
|
gap: ${({ theme }) => theme.spacing(2)};
|
||||||
padding-left: ${({ theme }) => theme.spacing(2)};
|
padding-left: ${({ theme }) => theme.spacing(2)};
|
||||||
color: ${({ theme }) => theme.font.color.secondary};
|
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledCheckboxCell = styled(TableCell)`
|
const StyledCheckboxCell = styled(TableCell)`
|
||||||
|
|||||||
@ -43,8 +43,6 @@ export const SettingsRoleEdit = () => {
|
|||||||
}
|
}
|
||||||
}, [role, navigateSettings, rolesLoading]);
|
}, [role, navigateSettings, rolesLoading]);
|
||||||
|
|
||||||
if (!role) return null;
|
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
id: SETTINGS_ROLE_DETAIL_TABS.TABS_IDS.ASSIGNMENT,
|
id: SETTINGS_ROLE_DETAIL_TABS.TABS_IDS.ASSIGNMENT,
|
||||||
@ -67,6 +65,10 @@ export const SettingsRoleEdit = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const renderActiveTabContent = () => {
|
const renderActiveTabContent = () => {
|
||||||
|
if (!role) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
switch (activeTabId) {
|
switch (activeTabId) {
|
||||||
case SETTINGS_ROLE_DETAIL_TABS.TABS_IDS.ASSIGNMENT:
|
case SETTINGS_ROLE_DETAIL_TABS.TABS_IDS.ASSIGNMENT:
|
||||||
return <RoleAssignment role={role} />;
|
return <RoleAssignment role={role} />;
|
||||||
@ -81,7 +83,7 @@ export const SettingsRoleEdit = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<SubMenuTopBarContainer
|
<SubMenuTopBarContainer
|
||||||
title={<H3Title title={role.label} />}
|
title={role && <H3Title title={role.label} />}
|
||||||
links={[
|
links={[
|
||||||
{
|
{
|
||||||
children: 'Workspace',
|
children: 'Workspace',
|
||||||
@ -92,18 +94,22 @@ export const SettingsRoleEdit = () => {
|
|||||||
href: getSettingsPath(SettingsPath.Roles),
|
href: getSettingsPath(SettingsPath.Roles),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
children: role.label,
|
children: role?.label,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<SettingsPageContainer>
|
{!rolesLoading && role ? (
|
||||||
<TabList
|
<SettingsPageContainer>
|
||||||
tabListInstanceId={SETTINGS_ROLE_DETAIL_TABS.COMPONENT_INSTANCE_ID}
|
<TabList
|
||||||
tabs={tabs}
|
tabListInstanceId={SETTINGS_ROLE_DETAIL_TABS.COMPONENT_INSTANCE_ID}
|
||||||
className="tab-list"
|
tabs={tabs}
|
||||||
/>
|
className="tab-list"
|
||||||
{renderActiveTabContent()}
|
/>
|
||||||
</SettingsPageContainer>
|
{renderActiveTabContent()}
|
||||||
|
</SettingsPageContainer>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
</SubMenuTopBarContainer>
|
</SubMenuTopBarContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { Roles } from '@/settings/roles/components/Roles';
|
|||||||
import { RolesDefaultRole } from '@/settings/roles/components/RolesDefaultRole';
|
import { RolesDefaultRole } from '@/settings/roles/components/RolesDefaultRole';
|
||||||
import { SettingsPath } from '@/types/SettingsPath';
|
import { SettingsPath } from '@/types/SettingsPath';
|
||||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||||
|
import { H3Title } from 'twenty-ui';
|
||||||
import { useGetRolesQuery } from '~/generated/graphql';
|
import { useGetRolesQuery } from '~/generated/graphql';
|
||||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ export const SettingsRoles = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<SubMenuTopBarContainer
|
<SubMenuTopBarContainer
|
||||||
title={t`Roles`}
|
title={rolesData && <H3Title title={t`Roles`} />}
|
||||||
links={[
|
links={[
|
||||||
{
|
{
|
||||||
children: <Trans>Workspace</Trans>,
|
children: <Trans>Workspace</Trans>,
|
||||||
@ -26,10 +27,10 @@ export const SettingsRoles = () => {
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<SettingsPageContainer>
|
<SettingsPageContainer>
|
||||||
{!rolesLoading && (
|
{!rolesLoading && rolesData && (
|
||||||
<>
|
<>
|
||||||
<Roles roles={rolesData?.getRoles ?? []} />
|
<Roles roles={rolesData.getRoles ?? []} />
|
||||||
<RolesDefaultRole roles={rolesData?.getRoles ?? []} />
|
<RolesDefaultRole roles={rolesData.getRoles ?? []} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</SettingsPageContainer>
|
</SettingsPageContainer>
|
||||||
|
|||||||
@ -15,8 +15,6 @@ type Checkers = Parameters<typeof checker>[0];
|
|||||||
export default defineConfig(({ command, mode }) => {
|
export default defineConfig(({ command, mode }) => {
|
||||||
const env = loadEnv(mode, __dirname, '');
|
const env = loadEnv(mode, __dirname, '');
|
||||||
|
|
||||||
console.log(__dirname);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
REACT_APP_SERVER_BASE_URL,
|
REACT_APP_SERVER_BASE_URL,
|
||||||
VITE_BUILD_SOURCEMAP,
|
VITE_BUILD_SOURCEMAP,
|
||||||
|
|||||||
Reference in New Issue
Block a user