From be171e84d7198f6f0439152f5527aa3661a0e7a9 Mon Sep 17 00:00:00 2001 From: Marie <51697796+ijreilly@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:20:34 +0200 Subject: [PATCH 1/4] Fix create task (#7498) Fixing issue introduced by [Add Skeleton loading for side panel](https://github.com/twentyhq/twenty/pull/7394/files#top): https://github.com/user-attachments/assets/6c8e299c-d663-4aa7-83ed-ca7041cd15e7 --- .../hooks/useOpenCreateActivityDrawer.ts | 2 +- .../components/RightDrawerRecord.tsx | 18 +++++++++++++++++- .../components/RecordShowContainer.tsx | 8 ++------ .../record-show/hooks/useRecordShowPage.ts | 6 +++--- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts index c35d278371219..1cc4af08a81e4 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts @@ -67,8 +67,8 @@ export const useOpenCreateActivityDrawer = ({ targetableObjects: ActivityTargetableObject[]; customAssignee?: WorkspaceMember; }) => { - openRightDrawer(RightDrawerPages.ViewRecord); setIsNewViewableRecordLoading(true); + openRightDrawer(RightDrawerPages.ViewRecord); setViewableRecordId(null); setViewableRecordNameSingular(activityObjectNameSingular); diff --git a/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx b/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx index 6a76206e6e754..3a747b0913a19 100644 --- a/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx +++ b/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx @@ -1,5 +1,6 @@ import { useRecoilValue } from 'recoil'; +import { isNewViewableRecordLoadingState } from '@/object-record/record-right-drawer/states/isNewViewableRecordLoading'; import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; import { RecordShowContainer } from '@/object-record/record-show/components/RecordShowContainer'; @@ -18,7 +19,19 @@ export const RightDrawerRecord = () => { const viewableRecordNameSingular = useRecoilValue( viewableRecordNameSingularState, ); + const isNewViewableRecordLoading = useRecoilValue( + isNewViewableRecordLoadingState, + ); const viewableRecordId = useRecoilValue(viewableRecordIdState); + + if (!viewableRecordNameSingular && !isNewViewableRecordLoading) { + throw new Error(`Object name is not defined`); + } + + if (!viewableRecordId && !isNewViewableRecordLoading) { + throw new Error(`Record id is not defined`); + } + const { objectNameSingular, objectRecordId } = useRecordShowPage( viewableRecordNameSingular ?? '', viewableRecordId ?? '', @@ -27,12 +40,15 @@ export const RightDrawerRecord = () => { return ( - + {!isNewViewableRecordLoading && ( + + )} diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx index f9176f4999137..9b1e10601ab49 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx @@ -21,7 +21,6 @@ import { RecordInlineCell } from '@/object-record/record-inline-cell/components/ import { PropertyBox } from '@/object-record/record-inline-cell/property-box/components/PropertyBox'; import { PropertyBoxSkeletonLoader } from '@/object-record/record-inline-cell/property-box/components/PropertyBoxSkeletonLoader'; import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope'; -import { isNewViewableRecordLoadingState } from '@/object-record/record-right-drawer/states/isNewViewableRecordLoading'; import { RecordDetailDuplicatesSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailDuplicatesSection'; import { RecordDetailRelationSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationSection'; import { recordLoadingFamilyState } from '@/object-record/record-store/states/recordLoadingFamilyState'; @@ -49,6 +48,7 @@ type RecordShowContainerProps = { objectRecordId: string; loading: boolean; isInRightDrawer?: boolean; + isNewRightDrawerItemLoading?: boolean; }; export const RecordShowContainer = ({ @@ -56,6 +56,7 @@ export const RecordShowContainer = ({ objectRecordId, loading, isInRightDrawer = false, + isNewRightDrawerItemLoading = false, }: RecordShowContainerProps) => { const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular, @@ -82,9 +83,6 @@ export const RecordShowContainer = ({ recordId: objectRecordId, }), ); - const isNewViewableRecordLoading = useRecoilValue( - isNewViewableRecordLoadingState, - ); const [uploadImage] = useUploadImageMutation(); const { updateOneRecord } = useUpdateOneRecord({ objectNameSingular }); @@ -166,8 +164,6 @@ export const RecordShowContainer = ({ const isReadOnly = objectMetadataItem.isRemote; const isMobile = useIsMobile() || isInRightDrawer; const isPrefetchLoading = useIsPrefetchLoading(); - const isNewRightDrawerItemLoading = - isInRightDrawer && isNewViewableRecordLoading; const summaryCard = !isNewRightDrawerItemLoading && isDefined(recordFromStore) ? ( diff --git a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts index 7bdaf0b4284bf..fb73b8ce9a523 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts +++ b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts @@ -23,10 +23,10 @@ export const useRecordShowPage = ( objectRecordId: paramObjectRecordId, } = useParams(); - const objectNameSingular = propsObjectNameSingular || paramObjectNameSingular; - const objectRecordId = propsObjectRecordId || paramObjectRecordId; + const objectNameSingular = propsObjectNameSingular ?? paramObjectNameSingular; + const objectRecordId = propsObjectRecordId ?? paramObjectRecordId; - if (!objectNameSingular || !objectRecordId) { + if (!isDefined(objectNameSingular) || !isDefined(objectRecordId)) { throw new Error('Object name or Record id is not defined'); } From 10e75174f5ae424eaf456777e4f9e18ec23a5d06 Mon Sep 17 00:00:00 2001 From: Vardhaman Bhandari <97441447+Vardhaman619@users.noreply.github.com> Date: Tue, 8 Oct 2024 20:12:13 +0530 Subject: [PATCH 2/4] Fix: Adjust chevron alignment to the right edge (#7438) This pull request addresses the alignment issue of the chevron icon, ensuring that it is positioned correctly on the right edge. Fixes [#7403](https://github.com/twentyhq/twenty/issues/7403) ![after fix](https://github.com/user-attachments/assets/84e6cd14-1d10-4331-8f25-da5423b15dd3) --------- Co-authored-by: Charles Bochet Co-authored-by: ehconitin --- .../components/SettingsApiKeysFieldItemTableRow.tsx | 3 ++- .../settings/developers/components/SettingsApiKeysTable.tsx | 2 +- .../components/SettingsDevelopersWebhookTableRow.tsx | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysFieldItemTableRow.tsx b/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysFieldItemTableRow.tsx index 4d4dc8d45e6f1..c8051eab0511a 100644 --- a/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysFieldItemTableRow.tsx +++ b/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysFieldItemTableRow.tsx @@ -7,7 +7,7 @@ import { TableCell } from '@/ui/layout/table/components/TableCell'; import { TableRow } from '@/ui/layout/table/components/TableRow'; export const StyledApisFieldTableRow = styled(TableRow)` - grid-template-columns: 312px 132px 68px; + grid-template-columns: 312px auto 28px; `; const StyledNameTableCell = styled(TableCell)` @@ -18,6 +18,7 @@ const StyledNameTableCell = styled(TableCell)` const StyledIconTableCell = styled(TableCell)` justify-content: center; padding-right: ${({ theme }) => theme.spacing(1)}; + padding-left: 0; `; const StyledIconChevronRight = styled(IconChevronRight)` diff --git a/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysTable.tsx b/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysTable.tsx index ede12c34bf6cb..6d70ada4c862f 100644 --- a/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysTable.tsx +++ b/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysTable.tsx @@ -18,7 +18,7 @@ const StyledTableBody = styled(TableBody)` `; const StyledTableRow = styled(TableRow)` - grid-template-columns: 312px 132px 68px; + grid-template-columns: 312px auto 28px; `; export const SettingsApiKeysTable = () => { diff --git a/packages/twenty-front/src/modules/settings/developers/components/SettingsDevelopersWebhookTableRow.tsx b/packages/twenty-front/src/modules/settings/developers/components/SettingsDevelopersWebhookTableRow.tsx index 0c093d5ecbd20..d559f89a200a9 100644 --- a/packages/twenty-front/src/modules/settings/developers/components/SettingsDevelopersWebhookTableRow.tsx +++ b/packages/twenty-front/src/modules/settings/developers/components/SettingsDevelopersWebhookTableRow.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { IconChevronRight } from 'twenty-ui'; @@ -8,12 +7,13 @@ import { TableCell } from '@/ui/layout/table/components/TableCell'; import { TableRow } from '@/ui/layout/table/components/TableRow'; export const StyledApisFieldTableRow = styled(TableRow)` - grid-template-columns: 444px 68px; + grid-template-columns: 1fr 28px; `; const StyledIconTableCell = styled(TableCell)` justify-content: center; padding-right: ${({ theme }) => theme.spacing(1)}; + padding-left: 0; `; const StyledUrlTableCell = styled(TableCell)` From 098551b7b882c158bd71e4d65cc4f6375085294e Mon Sep 17 00:00:00 2001 From: Harshit Singh <73997189+harshit078@users.noreply.github.com> Date: Tue, 8 Oct 2024 20:18:15 +0530 Subject: [PATCH 3/4] fix: Invite by email table overflows in mobile viewport (#7273) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ##Description - This PR solves the issue #7253 - Made the invite table mobile friendly for all media width ## Before https://github.com/user-attachments/assets/458bd47d-38fb-4ddc-a996-c1bb3908d014 Screenshot 2024-09-27 at 1 30 52 AM ## After Screenshot 2024-09-27 at 1 34 11 AM https://github.com/user-attachments/assets/7a4f6f9a-7fef-42f1-a226-59a1d73767f4 > [!Note] > I've added 2 implementations and if either doesn't follow design rules then it can be changed- > - Made the trash icon `accent danger` > - When emails are long, given scroll for ease of convience. --------- Co-authored-by: Nitin Koche --- .../settings/SettingsWorkspaceMembers.tsx | 114 ++++++++++++------ 1 file changed, 77 insertions(+), 37 deletions(-) diff --git a/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx b/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx index 0079fb8885013..63bbd6717d63a 100644 --- a/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx +++ b/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx @@ -7,8 +7,8 @@ import { IconUsers, IconReload, IconMail, - StyledText, Avatar, + MOBILE_VIEWPORT, } from 'twenty-ui'; import { isNonEmptyArray } from '@sniptt/guards'; import { useTheme } from '@emotion/react'; @@ -53,6 +53,47 @@ const StyledTable = styled(Table)` margin-top: ${({ theme }) => theme.spacing(0.5)}; `; +const StyledTableRow = styled(TableRow)` + @media (max-width: ${MOBILE_VIEWPORT}px) { + display: grid; + grid-template-columns: 3fr; + } +`; +const StyledTableCell = styled(TableCell)` + padding: ${({ theme }) => theme.spacing(1)}; + @media (max-width: ${MOBILE_VIEWPORT}px) { + &:first-child { + max-width: 100%; + padding-top: 2px; + white-space: nowrap; + overflow: scroll; + scroll-behavior: smooth; + } + } +`; +const StyledIconWrapper = styled.div` + left: 2px; + margin-right: ${({ theme }) => theme.spacing(2)}; + position: relative; + top: 1px; +`; + +const StyledScrollableTextContainer = styled.div` + max-width: 100%; + overflow-x: auto; + white-space: pre-line; +`; + +const StyledTextContainer = styled.div` + color: ${({ theme }) => theme.font.color.secondary}; + max-width: max-content; + overflow-x: auto; + position: absolute; + @media (min-width: 360px) and (max-width: 420px) { + max-width: 150px; + margin-top: ${({ theme }) => theme.spacing(1)}; + } +`; const StyledTableHeaderRow = styled(Table)` margin-bottom: ${({ theme }) => theme.spacing(1.5)}; `; @@ -165,28 +206,25 @@ export const SettingsWorkspaceMembers = () => { - - } - text={ - workspaceMember.name.firstName + + + + + + {workspaceMember.name.firstName + ' ' + - workspaceMember.name.lastName - } - /> + workspaceMember.name.lastName} + - + + {workspaceMember.userEmail} + {currentWorkspaceMember?.id !== workspaceMember.id && ( @@ -225,25 +263,27 @@ export const SettingsWorkspaceMembers = () => { {workspaceInvitations?.map((workspaceInvitation) => ( - - - - } - text={workspaceInvitation.email} - /> - - + + + + + + + {workspaceInvitation.email} + + + - - + + { @@ -266,8 +306,8 @@ export const SettingsWorkspaceMembers = () => { Icon={IconTrash} /> - - + + ))} From fcd60be110eb0a524f1f2eefe439c3249dd3086d Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 8 Oct 2024 16:52:15 +0200 Subject: [PATCH 4/4] Fix filtered INDEX view not loading (#7501) ## Context We have recently merged a refactoring of our view module. However, one case was forgotten which is to test our dynamic filtering logic. It is currently possible to pass unsaved filters through the URL and these filters will be applied to the currentView through `QueryParamsFiltersEffect`. This component was saving filters but also listening to them through useGetCurrentView hook. ## How 1) I'm removing this infinite loop by directly loading currentViewId through the right recoil atom. Bonus: I'm also removing the unmounting logic which seems wrong to me as unsaved filters are mounted on a specific view, there is no need to remove them while switching views in my opinion. --- .../components/RecordDetailRelationSection.tsx | 12 ++++++++++++ .../components/QueryParamsFiltersEffect.tsx | 16 +++++----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx index 23fc1f07096f5..edd49b3f84068 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx @@ -24,12 +24,15 @@ import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRela import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope'; import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; +import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { FilterQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; +import { View } from '@/views/types/View'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { RelationDefinitionType } from '~/generated-metadata/graphql'; @@ -119,12 +122,21 @@ export const RecordDetailRelationSection = ({ scopeId: dropdownId, }); + const { records: views } = usePrefetchedData(PrefetchKey.AllViews); + + const indexView = views.find( + (view) => + view.key === 'INDEX' && + view.objectMetadataId === relationObjectMetadataItem.id, + ); + const filterQueryParams: FilterQueryParams = { filter: { [relationFieldMetadataItem?.name || '']: { [ViewFilterOperand.Is]: [recordId], }, }, + view: indexView?.id, }; const filterLinkHref = `/objects/${ relationObjectMetadataItem.namePlural diff --git a/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx b/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx index 10ecdfa83b87e..f811df0ddf6ba 100644 --- a/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx @@ -1,23 +1,24 @@ import { useEffect } from 'react'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2'; import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; -import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; -import { isDefined } from 'twenty-ui'; export const QueryParamsFiltersEffect = () => { const { hasFiltersQueryParams, getFiltersFromQueryParams, viewIdQueryParam } = useViewFromQueryParams(); + const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState); + const setUnsavedViewFilter = useSetRecoilComponentFamilyStateV2( unsavedToUpsertViewFiltersComponentFamilyState, - { viewId: viewIdQueryParam }, + { viewId: viewIdQueryParam ?? currentViewId }, ); const { resetUnsavedViewStates } = useResetUnsavedViewStates(); - const { currentViewId } = useGetCurrentView(); useEffect(() => { if (!hasFiltersQueryParams) { @@ -29,18 +30,11 @@ export const QueryParamsFiltersEffect = () => { setUnsavedViewFilter(filtersFromParams); } }); - - return () => { - if (isDefined(currentViewId)) { - resetUnsavedViewStates(currentViewId); - } - }; }, [ getFiltersFromQueryParams, hasFiltersQueryParams, resetUnsavedViewStates, setUnsavedViewFilter, - currentViewId, ]); return <>;