Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default role to workspace #10444

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 27 additions & 18 deletions packages/twenty-front/src/generated/graphql.tsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createState } from '@ui/utilities/state/utils/createState';

import { Workspace } from '~/generated/graphql';
import { Role, Workspace } from '~/generated/graphql';

export type CurrentWorkspace = Pick<
Workspace,
Expand All @@ -23,7 +23,9 @@ export type CurrentWorkspace = Pick<
| 'customDomain'
| 'workspaceUrls'
| 'metadataVersion'
>;
> & {
defaultRole: Omit<Role, 'workspaceMembers'> | null;
};

export const currentWorkspaceState = createState<CurrentWorkspace | null>({
key: 'currentWorkspaceState',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ export const UserProviderEffect = () => {
setCurrentUser(queryData.currentUser);

if (isDefined(queryData.currentUser.currentWorkspace)) {
setCurrentWorkspace(queryData.currentUser.currentWorkspace);
setCurrentWorkspace({
...queryData.currentUser.currentWorkspace,
defaultRole: queryData.currentUser.currentWorkspace.defaultRole ?? null,
});
}

if (isDefined(queryData.currentUser.currentUserWorkspace)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { ROLE_FRAGMENT } from '@/settings/roles/graphql/fragments/roleFragment';
import { WORKSPACE_MEMBER_QUERY_FRAGMENT } from '@/workspace-member/graphql/fragments/workspaceMemberQueryFragment';
import { gql } from '@apollo/client';

export const USER_QUERY_FRAGMENT = gql`
${ROLE_FRAGMENT}
fragment UserQueryFragment on User {
id
firstName
Expand Down Expand Up @@ -63,6 +65,9 @@ export const USER_QUERY_FRAGMENT = gql`
status
}
workspaceMembersCount
defaultRole {
...RoleFragment
}
}
workspaces {
workspace {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ROLE_FRAGMENT } from '@/settings/roles/graphql/fragments/roleFragment';
import { gql } from '@apollo/client';

export const UPDATE_WORKSPACE = gql`
${ROLE_FRAGMENT}
mutation UpdateWorkspace($input: UpdateWorkspaceInput!) {
updateWorkspace(data: $input) {
id
Expand All @@ -13,6 +15,9 @@ export const UPDATE_WORKSPACE = gql`
isGoogleAuthEnabled
isMicrosoftAuthEnabled
isPasswordAuthEnabled
defaultRole {
...RoleFragment
}
}
}
`;
181 changes: 8 additions & 173 deletions packages/twenty-front/src/pages/settings/roles/SettingsRoles.tsx
Original file line number Diff line number Diff line change
@@ -1,106 +1,19 @@
import styled from '@emotion/styled';
import { Trans, useLingui } from '@lingui/react/macro';
import {
AppTooltip,
Avatar,
Button,
H2Title,
IconChevronRight,
IconLock,
IconPlus,
IconUser,
Section,
TooltipDelay,
} from 'twenty-ui';

import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { Table } from '@/ui/layout/table/components/Table';
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 { useTheme } from '@emotion/react';
import React from 'react';
import { useGetRolesQuery } from '~/generated/graphql';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { Roles } from '~/pages/settings/roles/components/Roles';
import { RolesDefaultRole } from '~/pages/settings/roles/components/RolesDefaultRole';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';

const StyledTable = styled(Table)`
margin-top: ${({ theme }) => theme.spacing(0.5)};
`;

const StyledTableRow = styled(TableRow)`
&:hover {
background: ${({ theme }) => theme.background.transparent.light};
cursor: pointer;
}
`;

const StyledNameCell = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
`;

const StyledAssignedCell = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
`;

const StyledAvatarGroup = styled.div`
align-items: center;
display: flex;
margin-right: ${({ theme }) => theme.spacing(1)};

> * {
margin-left: -5px;

&:first-of-type {
margin-left: 0;
}
}
`;

const StyledTableHeaderRow = styled(Table)`
margin-bottom: ${({ theme }) => theme.spacing(2)};
`;

const StyledBottomSection = styled(Section)`
border-top: 1px solid ${({ theme }) => theme.border.color.light};
margin-top: ${({ theme }) => theme.spacing(2)};
padding-top: ${({ theme }) => theme.spacing(4)};
display: flex;
justify-content: flex-end;
`;

const StyledIconChevronRight = styled(IconChevronRight)`
color: ${({ theme }) => theme.font.color.tertiary};
`;

const StyledAvatarContainer = styled.div`
border: 0px;
`;

const StyledAssignedText = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.md};
`;

export const SettingsRoles = () => {
const { t } = useLingui();

const theme = useTheme();
const navigateSettings = useNavigateSettings();
const { data: rolesData, loading: rolesLoading } = useGetRolesQuery({
fetchPolicy: 'network-only',
});

const handleRoleClick = (roleId: string) => {
navigateSettings(SettingsPath.RoleDetail, { roleId });
};

return (
<SubMenuTopBarContainer
title={t`Roles`}
Expand All @@ -113,90 +26,12 @@ export const SettingsRoles = () => {
]}
>
<SettingsPageContainer>
<Section>
<H2Title
title={t`All roles`}
description={t`Assign roles to specify each member's access permissions`}
/>
<StyledTable>
<StyledTableHeaderRow>
<TableRow>
<TableHeader>
<Trans>Name</Trans>
</TableHeader>
<TableHeader align={'right'}>
<Trans>Assigned to</Trans>
</TableHeader>
<TableHeader align={'right'}></TableHeader>
</TableRow>
</StyledTableHeaderRow>
{!rolesLoading &&
rolesData?.getRoles.map((role) => (
<StyledTableRow
key={role.id}
onClick={() => handleRoleClick(role.id)}
>
<TableCell>
<StyledNameCell>
<IconUser size={theme.icon.size.md} />
{role.label}
{!role.isEditable && (
<IconLock size={theme.icon.size.sm} />
)}
</StyledNameCell>
</TableCell>
<TableCell align={'right'}>
<StyledAssignedCell>
<StyledAvatarGroup>
{role.workspaceMembers
.slice(0, 5)
.map((workspaceMember) => (
<React.Fragment key={workspaceMember.id}>
<StyledAvatarContainer
id={`avatar-${workspaceMember.id}`}
>
<Avatar
avatarUrl={workspaceMember.avatarUrl}
placeholderColorSeed={workspaceMember.id}
placeholder={
workspaceMember.name.firstName ?? ''
}
type="rounded"
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>
))}
</StyledAvatarGroup>
<StyledAssignedText>
{role.workspaceMembers.length}
</StyledAssignedText>
</StyledAssignedCell>
</TableCell>
<TableCell align={'right'}>
<StyledIconChevronRight size={theme.icon.size.md} />
</TableCell>
</StyledTableRow>
))}
</StyledTable>
<StyledBottomSection>
<Button
Icon={IconPlus}
title={t`Create Role`}
variant="secondary"
size="small"
soon
/>
</StyledBottomSection>
</Section>
{!rolesLoading && (
<>
<Roles roles={rolesData?.getRoles ?? []} />
<RolesDefaultRole roles={rolesData?.getRoles ?? []} />
</>
)}
</SettingsPageContainer>
</SubMenuTopBarContainer>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Table } from '@/ui/layout/table/components/Table';
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';

import { Button, H2Title, IconPlus, Section } from 'twenty-ui';
import { Role } from '~/generated-metadata/graphql';
import { RolesTableHeader } from '~/pages/settings/roles/components/RolesTableHeader';
import { RolesTableRow } from '~/pages/settings/roles/components/RolesTableRow';

const StyledTable = styled(Table)`
margin-top: ${({ theme }) => theme.spacing(0.5)};
`;

const StyledBottomSection = styled(Section)`
border-top: 1px solid ${({ theme }) => theme.border.color.light};
margin-top: ${({ theme }) => theme.spacing(2)};
padding-top: ${({ theme }) => theme.spacing(4)};
display: flex;
justify-content: flex-end;
`;

export const Roles = ({ roles }: { roles: Role[] }) => {
return (
<Section>
<H2Title
title={t`All roles`}
description={t`Assign roles to specify each member's access permissions`}
/>
<StyledTable>
<RolesTableHeader />
{roles.map((role) => (
<RolesTableRow key={role.id} role={role} />
))}
</StyledTable>
<StyledBottomSection>
<Button
Icon={IconPlus}
title={t`Create Role`}
variant="secondary"
size="small"
soon
/>
</StyledBottomSection>
</Section>
);
};
Loading
Loading