From 5d2be607582b99930dd7226e03c7a16f22e5aa56 Mon Sep 17 00:00:00 2001 From: Weiko Date: Tue, 4 Mar 2025 18:09:23 +0100 Subject: [PATCH] Various frontend fixes for roles pages (#10654) --- .../hooks/useSettingsNavigationItems.tsx | 14 +-- .../roles/components/RolesTableHeader.tsx | 2 +- .../roles/components/RolesTableRow.tsx | 15 ++- .../components/RoleAssignment.tsx | 92 +++++++++---------- .../RoleAssignmentConfirmationModal.tsx | 2 +- ...oleAssignmentConfirmationModalSubtitle.tsx | 14 ++- .../components/RoleAssignmentTableHeader.tsx | 3 +- .../components/RoleAssignmentTableRow.tsx | 51 ++++++---- ...onfirmationModalSelectedWorkspaceMember.ts | 1 + .../components/RolePermissions.tsx | 39 +++++--- .../RolePermissionsSettingsTableRow.tsx | 2 + .../role-settings/components/RoleSettings.tsx | 7 +- .../pages/settings/roles/SettingsRoleEdit.tsx | 38 +------- .../src/input/components/Checkbox.tsx | 8 +- 14 files changed, 147 insertions(+), 141 deletions(-) diff --git a/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx b/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx index 30cdb1940..b823a8e44 100644 --- a/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx +++ b/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx @@ -118,13 +118,6 @@ const useSettingsNavigationItems = (): SettingsNavigationSection[] => { Icon: IconUsers, isHidden: !permissionMap[SettingsPermissions.WORKSPACE_MEMBERS], }, - { - label: t`Billing`, - path: SettingsPath.Billing, - Icon: IconCurrencyDollar, - isHidden: - !isBillingEnabled || !permissionMap[SettingsPermissions.WORKSPACE], - }, { label: t`Roles`, path: SettingsPath.Roles, @@ -133,6 +126,13 @@ const useSettingsNavigationItems = (): SettingsNavigationSection[] => { !featureFlags[FeatureFlagKey.IsPermissionsEnabled] || !permissionMap[SettingsPermissions.ROLES], }, + { + label: t`Billing`, + path: SettingsPath.Billing, + Icon: IconCurrencyDollar, + isHidden: + !isBillingEnabled || !permissionMap[SettingsPermissions.WORKSPACE], + }, { label: t`Data model`, path: SettingsPath.Objects, diff --git a/packages/twenty-front/src/modules/settings/roles/components/RolesTableHeader.tsx b/packages/twenty-front/src/modules/settings/roles/components/RolesTableHeader.tsx index 90f11175e..991666a2e 100644 --- a/packages/twenty-front/src/modules/settings/roles/components/RolesTableHeader.tsx +++ b/packages/twenty-front/src/modules/settings/roles/components/RolesTableHeader.tsx @@ -11,7 +11,7 @@ const StyledTableHeaderRow = styled(Table)` export const RolesTableHeader = () => { return ( - + Name diff --git a/packages/twenty-front/src/modules/settings/roles/components/RolesTableRow.tsx b/packages/twenty-front/src/modules/settings/roles/components/RolesTableRow.tsx index 8a9f7d33e..8c4ebf777 100644 --- a/packages/twenty-front/src/modules/settings/roles/components/RolesTableRow.tsx +++ b/packages/twenty-front/src/modules/settings/roles/components/RolesTableRow.tsx @@ -24,20 +24,21 @@ const StyledAvatarContainer = styled.div` `; const StyledAssignedText = styled.div` - color: ${({ theme }) => theme.font.color.primary}; - font-size: ${({ theme }) => theme.font.size.md}; + color: ${({ theme }) => theme.font.color.secondary}; + font-size: ${({ theme }) => theme.font.size.sm}; `; const StyledNameCell = styled.div` align-items: center; display: flex; - gap: ${({ theme }) => theme.spacing(2)}; + gap: ${({ theme }) => theme.spacing(1)}; + color: ${({ theme }) => theme.font.color.primary}; `; const StyledAssignedCell = styled.div` align-items: center; display: flex; - gap: ${({ theme }) => theme.spacing(1)}; + gap: ${({ theme }) => theme.spacing(4)}; `; const StyledAvatarGroup = styled.div` @@ -71,7 +72,11 @@ export const RolesTableRow = ({ role }: { role: Role }) => { }; return ( - handleRoleClick(role.id)}> + handleRoleClick(role.id)} + > diff --git a/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignment.tsx b/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignment.tsx index ffe2c5c33..62102c2c3 100644 --- a/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignment.tsx +++ b/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignment.tsx @@ -7,7 +7,6 @@ import { SettingsPath } from '@/types/SettingsPath'; import { TextInput } from '@/ui/input/components/TextInput'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; -import { Table } from '@/ui/layout/table/components/Table'; import styled from '@emotion/styled'; import { t } from '@lingui/core/macro'; import { useState } from 'react'; @@ -31,25 +30,22 @@ import { useNavigateSettings } from '~/hooks/useNavigateSettings'; import { RoleAssignmentConfirmationModal } from './RoleAssignmentConfirmationModal'; import { RoleAssignmentTableRow } from './RoleAssignmentTableRow'; -const StyledBottomSection = styled(Section)<{ hasRows: boolean }>` - ${({ hasRows, theme }) => - hasRows - ? ` - border-top: 1px solid ${theme.border.color.light}; - margin-top: ${theme.spacing(2)}; - padding-top: ${theme.spacing(4)}; - ` - : ` - margin-top: ${theme.spacing(8)}; - `} +const StyledAssignToMemberContainer = styled.div` display: flex; justify-content: flex-end; + padding-top: ${({ theme }) => theme.spacing(2)}; + padding-bottom: ${({ theme }) => theme.spacing(2)}; `; const StyledSearchContainer = styled.div` margin: ${({ theme }) => theme.spacing(2)} 0; `; +const StyledTable = styled.div<{ hasRows: boolean }>` + border-bottom: ${({ hasRows, theme }) => + hasRows ? `1px solid ${theme.border.color.light}` : 'none'}; +`; + const StyledSearchInput = styled(TextInput)` input { background: ${({ theme }) => theme.background.transparent.lighter}; @@ -134,6 +130,7 @@ export const RoleAssignment = ({ role }: RoleAssignmentProps) => { id: workspaceMember.id, name: `${workspaceMember.name.firstName} ${workspaceMember.name.lastName}`, role: existingRole, + avatarUrl: workspaceMember.avatarUrl, }); setConfirmationModalIsOpen(true); closeDropdown(); @@ -178,7 +175,7 @@ export const RoleAssignment = ({ role }: RoleAssignmentProps) => { sizeVariant="lg" /> - + 0}> {filteredWorkspaceMembers.map((workspaceMember) => ( { workspaceMember={workspaceMember} /> ))} -
- - 0}> - -
-
+
+ } + /> + + {confirmationModalIsOpen && selectedWorkspaceMember && ( ); }; diff --git a/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentConfirmationModalSubtitle.tsx b/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentConfirmationModalSubtitle.tsx index 158c02a49..cb20ec19b 100644 --- a/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentConfirmationModalSubtitle.tsx +++ b/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentConfirmationModalSubtitle.tsx @@ -2,10 +2,10 @@ import { SettingsCard } from '@/settings/components/SettingsCard'; import { RoleAssignmentConfirmationModalSelectedWorkspaceMember } from '@/settings/roles/role-assignment/types/RoleAssignmentConfirmationModalSelectedWorkspaceMember'; import styled from '@emotion/styled'; import { t } from '@lingui/core/macro'; -import { IconUser } from 'twenty-ui'; +import { Avatar } from 'twenty-ui'; const StyledSettingsCardContainer = styled.div` - margin-top: ${({ theme }) => theme.spacing(2)}; + margin-top: ${({ theme }) => theme.spacing(6)}; `; type RoleAssignmentConfirmationModalSubtitleProps = { @@ -25,7 +25,15 @@ export const RoleAssignmentConfirmationModalSubtitle = ({ } + Icon={ + + } onClick={() => selectedWorkspaceMember.role && onRoleClick(selectedWorkspaceMember.role.id) diff --git a/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentTableHeader.tsx b/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentTableHeader.tsx index 584a7c661..e8fdda18c 100644 --- a/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentTableHeader.tsx +++ b/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentTableHeader.tsx @@ -10,10 +10,9 @@ const StyledTableHeaderRow = styled(Table)` export const RoleAssignmentTableHeader = () => ( - + {t`Name`} {t`Email`} - ); diff --git a/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentTableRow.tsx b/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentTableRow.tsx index 6d36de04b..51393b83a 100644 --- a/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentTableRow.tsx +++ b/packages/twenty-front/src/modules/settings/roles/role-assignment/components/RoleAssignmentTableRow.tsx @@ -1,18 +1,31 @@ -import { Table } from '@/ui/layout/table/components/Table'; import { TableCell } from '@/ui/layout/table/components/TableCell'; import { TableRow } from '@/ui/layout/table/components/TableRow'; import styled from '@emotion/styled'; import { Avatar, OverflowingTextWithTooltip } from 'twenty-ui'; import { WorkspaceMember } from '~/generated-metadata/graphql'; -const StyledTable = styled(Table)` - margin-top: ${({ theme }) => theme.spacing(0.5)}; +const StyledIconWrapper = styled.div` + align-items: center; + display: flex; + flex-shrink: 0; + margin-right: ${({ theme }) => theme.spacing(2)}; `; -const StyledIconWrapper = styled.div` - display: flex; +const StyledNameCell = styled.div` + color: ${({ theme }) => theme.font.color.primary}; + flex: 1; + min-width: 0; +`; + +const StyledNameContainer = styled.div` align-items: center; - margin-right: ${({ theme }) => theme.spacing(2)}; + display: flex; + overflow: hidden; + width: 100%; +`; + +const StyledTableCell = styled(TableCell)` + overflow: hidden; `; type RoleAssignmentTableRowProps = { @@ -23,9 +36,9 @@ export const RoleAssignmentTableRow = ({ workspaceMember, }: RoleAssignmentTableRowProps) => { return ( - - - + + + - - - - - - - + + + + + + + + +
); }; diff --git a/packages/twenty-front/src/modules/settings/roles/role-assignment/types/RoleAssignmentConfirmationModalSelectedWorkspaceMember.ts b/packages/twenty-front/src/modules/settings/roles/role-assignment/types/RoleAssignmentConfirmationModalSelectedWorkspaceMember.ts index 4c86eebb6..29cfdbdde 100644 --- a/packages/twenty-front/src/modules/settings/roles/role-assignment/types/RoleAssignmentConfirmationModalSelectedWorkspaceMember.ts +++ b/packages/twenty-front/src/modules/settings/roles/role-assignment/types/RoleAssignmentConfirmationModalSelectedWorkspaceMember.ts @@ -2,4 +2,5 @@ export type RoleAssignmentConfirmationModalSelectedWorkspaceMember = { id: string; name: string; role?: { id: string; label: string }; + avatarUrl?: string | null; }; diff --git a/packages/twenty-front/src/modules/settings/roles/role-permissions/components/RolePermissions.tsx b/packages/twenty-front/src/modules/settings/roles/role-permissions/components/RolePermissions.tsx index 01d0e43c7..8bacd2e49 100644 --- a/packages/twenty-front/src/modules/settings/roles/role-permissions/components/RolePermissions.tsx +++ b/packages/twenty-front/src/modules/settings/roles/role-permissions/components/RolePermissions.tsx @@ -22,6 +22,11 @@ const StyledRolePermissionsContainer = styled.div` gap: ${({ theme }) => theme.spacing(8)}; `; +const StyledTable = styled.div` + border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; + padding-bottom: ${({ theme }) => theme.spacing(2)}; +`; + type RolePermissionsProps = { role: Pick< Role, @@ -114,25 +119,29 @@ export const RolePermissions = ({ role }: RolePermissionsProps) => { title={t`Objects`} description={t`Ability to interact with each object`} /> - - {objectPermissionsConfig.map((permission) => ( - - ))} + + + {objectPermissionsConfig.map((permission) => ( + + ))} +
- - {settingsPermissionsConfig.map((permission) => ( - + - ))} + {settingsPermissionsConfig.map((permission) => ( + + ))} +
); diff --git a/packages/twenty-front/src/modules/settings/roles/role-permissions/components/RolePermissionsSettingsTableRow.tsx b/packages/twenty-front/src/modules/settings/roles/role-permissions/components/RolePermissionsSettingsTableRow.tsx index 8ba459878..b7cd919c1 100644 --- a/packages/twenty-front/src/modules/settings/roles/role-permissions/components/RolePermissionsSettingsTableRow.tsx +++ b/packages/twenty-front/src/modules/settings/roles/role-permissions/components/RolePermissionsSettingsTableRow.tsx @@ -18,6 +18,8 @@ const StyledPermissionCell = styled(TableCell)` flex: 1; gap: ${({ 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)` diff --git a/packages/twenty-front/src/modules/settings/roles/role-settings/components/RoleSettings.tsx b/packages/twenty-front/src/modules/settings/roles/role-settings/components/RoleSettings.tsx index dabee39a4..2076ade1a 100644 --- a/packages/twenty-front/src/modules/settings/roles/role-settings/components/RoleSettings.tsx +++ b/packages/twenty-front/src/modules/settings/roles/role-settings/components/RoleSettings.tsx @@ -4,13 +4,14 @@ import { t } from '@lingui/core/macro'; import { IconPicker } from '@/ui/input/components/IconPicker'; import { TextArea } from '@/ui/input/components/TextArea'; import { TextInput } from '@/ui/input/components/TextInput'; +import { Section } from 'twenty-ui'; import { Role } from '~/generated-metadata/graphql'; const StyledInputsContainer = styled.div` display: flex; gap: ${({ theme }) => theme.spacing(2)}; - margin-bottom: ${({ theme }) => theme.spacing(2)}; width: 100%; + margin-bottom: ${({ theme }) => theme.spacing(2)}; `; const StyledInputContainer = styled.div` @@ -24,7 +25,7 @@ type RoleSettingsProps = { export const RoleSettings = ({ role }: RoleSettingsProps) => { return ( - <> +
{ value={role.description || ''} disabled /> - +
); }; diff --git a/packages/twenty-front/src/pages/settings/roles/SettingsRoleEdit.tsx b/packages/twenty-front/src/pages/settings/roles/SettingsRoleEdit.tsx index b12edd42e..8b8953c6e 100644 --- a/packages/twenty-front/src/pages/settings/roles/SettingsRoleEdit.tsx +++ b/packages/twenty-front/src/pages/settings/roles/SettingsRoleEdit.tsx @@ -1,14 +1,7 @@ -import styled from '@emotion/styled'; import { t } from '@lingui/core/macro'; import { useEffect } from 'react'; import { useParams } from 'react-router-dom'; -import { - H3Title, - IconLockOpen, - IconSettings, - IconUser, - IconUserPlus, -} from 'twenty-ui'; +import { H3Title, IconLockOpen, IconSettings, IconUserPlus } from 'twenty-ui'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { RoleAssignment } from '@/settings/roles/role-assignment/components/RoleAssignment'; @@ -18,27 +11,10 @@ import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer'; import { TabList } from '@/ui/layout/tab/components/TabList'; import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; -import { useTheme } from '@emotion/react'; import { useGetRolesQuery } from '~/generated/graphql'; import { useNavigateSettings } from '~/hooks/useNavigateSettings'; import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; -const StyledContentContainer = styled.div` - flex: 1; - width: 100%; - padding-left: 0; -`; - -const StyledTitleContainer = styled.div` - display: flex; - align-items: center; - gap: ${({ theme }) => theme.spacing(2)}; -`; - -const StyledIconUser = styled(IconUser)` - color: ${({ theme }) => theme.font.color.primary}; -`; - export const SETTINGS_ROLE_DETAIL_TABS = { COMPONENT_INSTANCE_ID: 'settings-role-detail-tabs', TABS_IDS: { @@ -50,7 +26,6 @@ export const SETTINGS_ROLE_DETAIL_TABS = { export const SettingsRoleEdit = () => { const { roleId = '' } = useParams(); - const theme = useTheme(); const navigateSettings = useNavigateSettings(); const { data: rolesData, loading: rolesLoading } = useGetRolesQuery({ fetchPolicy: 'network-only', @@ -106,12 +81,7 @@ export const SettingsRoleEdit = () => { return ( - - - - } + title={} links={[ { children: 'Workspace', @@ -132,9 +102,7 @@ export const SettingsRoleEdit = () => { tabs={tabs} className="tab-list" /> - - {renderActiveTabContent()} - + {renderActiveTabContent()} ); diff --git a/packages/twenty-ui/src/input/components/Checkbox.tsx b/packages/twenty-ui/src/input/components/Checkbox.tsx index 185f85a98..f48725e93 100644 --- a/packages/twenty-ui/src/input/components/Checkbox.tsx +++ b/packages/twenty-ui/src/input/components/Checkbox.tsx @@ -102,7 +102,7 @@ const StyledInput = styled.input` checkboxSize === CheckboxSize.Large ? '18px' : '12px'}; background: ${({ theme, indeterminate, isChecked, disabled }) => disabled && isChecked - ? theme.color.blue + ? theme.adaptiveColors.blue3 : indeterminate || isChecked ? theme.color.blue : 'transparent'}; @@ -115,9 +115,9 @@ const StyledInput = styled.input` }) => { switch (true) { case isChecked: - return theme.color.blue; + return disabled ? theme.adaptiveColors.blue3 : theme.color.blue; case disabled: - return theme.background.transparent.medium; + return theme.border.color.strong; case indeterminate || isChecked: return theme.color.blue; case variant === CheckboxVariant.Primary: @@ -166,7 +166,7 @@ export const Checkbox = ({ variant = CheckboxVariant.Primary, size = CheckboxSize.Small, shape = CheckboxShape.Squared, - hoverable = false, + hoverable = true, className, disabled = false, }: CheckboxProps) => {