Remove custom widget from calendarEvent page layout (#22046)
## Before <img width="608" height="759" alt="image" src="https://github.com/user-attachments/assets/e75f6cc9-aef8-4247-a88d-6992b3936d3d" /> ## After <img width="844" height="658" alt="image" src="https://github.com/user-attachments/assets/446a13f2-e40c-4e1c-a1ed-0920fe5065b3" /> remove https://github.com/twentyhq/twenty/pull/22016 custom widget and replace with regular field widget does not match figma design but avoid introducing specific behavior for calendarEvent <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22046?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
-43
@@ -1,43 +0,0 @@
|
||||
import groupBy from 'lodash.groupby';
|
||||
|
||||
import { CalendarEventParticipantsResponseStatusField } from '@/activities/calendar/components/CalendarEventParticipantsResponseStatusField';
|
||||
import { type CalendarEventParticipant } from '@/activities/calendar/types/CalendarEventParticipant';
|
||||
import { PropertyBox } from '@/object-record/record-inline-cell/property-box/components/PropertyBox';
|
||||
|
||||
export const CalendarEventParticipantsResponseStatus = ({
|
||||
participants,
|
||||
}: {
|
||||
participants: CalendarEventParticipant[];
|
||||
}) => {
|
||||
const groupedParticipants = groupBy(participants, (participant) => {
|
||||
switch (participant.responseStatus) {
|
||||
case 'ACCEPTED':
|
||||
return 'Yes';
|
||||
case 'DECLINED':
|
||||
return 'No';
|
||||
case 'NEEDS_ACTION':
|
||||
case 'TENTATIVE':
|
||||
return 'Maybe';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
const responseStatusOrder: Array<'Yes' | 'Maybe' | 'No'> = [
|
||||
'Yes',
|
||||
'Maybe',
|
||||
'No',
|
||||
];
|
||||
|
||||
return (
|
||||
<PropertyBox>
|
||||
{responseStatusOrder.map((responseStatus) => (
|
||||
<CalendarEventParticipantsResponseStatusField
|
||||
key={responseStatus}
|
||||
responseStatus={responseStatus}
|
||||
participants={groupedParticipants[responseStatus] ?? []}
|
||||
/>
|
||||
))}
|
||||
</PropertyBox>
|
||||
);
|
||||
};
|
||||
-95
@@ -1,95 +0,0 @@
|
||||
import { styled } from '@linaria/react';
|
||||
import { useContext, useRef } from 'react';
|
||||
|
||||
import { ParticipantChip } from '@/activities/components/ParticipantChip';
|
||||
import { type CalendarEventParticipant } from '@/activities/calendar/types/CalendarEventParticipant';
|
||||
import { EllipsisDisplay } from '@/ui/field/display/components/EllipsisDisplay';
|
||||
import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList';
|
||||
import { IconCheck, IconQuestionMark, IconX } from 'twenty-ui/icon';
|
||||
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledResponseStatusRow = styled.div`
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
min-height: ${themeCssVariables.spacing[6]};
|
||||
position: relative;
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledIconContainer = styled.div`
|
||||
align-items: center;
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
display: flex;
|
||||
width: 16px;
|
||||
|
||||
svg {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 16px;
|
||||
justify-content: center;
|
||||
width: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledLabelAndIconContainer = styled.div`
|
||||
align-items: center;
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
display: flex;
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledLabelContainer = styled.div<{ width?: number }>`
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
font-size: ${themeCssVariables.font.size.sm};
|
||||
width: ${({ width }) => (width !== undefined ? `${width}px` : 'auto')};
|
||||
`;
|
||||
|
||||
const StyledParticipantsContainer = styled.div`
|
||||
max-width: 70%;
|
||||
`;
|
||||
|
||||
export const CalendarEventParticipantsResponseStatusField = ({
|
||||
responseStatus,
|
||||
participants,
|
||||
}: {
|
||||
responseStatus: 'Yes' | 'Maybe' | 'No';
|
||||
participants: CalendarEventParticipant[];
|
||||
}) => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const Icon = {
|
||||
Yes: <IconCheck stroke={theme.icon.stroke.sm} />,
|
||||
Maybe: <IconQuestionMark stroke={theme.icon.stroke.sm} />,
|
||||
No: <IconX stroke={theme.icon.stroke.sm} />,
|
||||
}[responseStatus];
|
||||
|
||||
const orderedParticipants = [
|
||||
...participants.filter((participant) => participant.person),
|
||||
...participants.filter((participant) => participant.workspaceMember),
|
||||
...participants.filter(
|
||||
(participant) => !participant.person && !participant.workspaceMember,
|
||||
),
|
||||
];
|
||||
|
||||
const participantsContainerRef = useRef<HTMLDivElement>(null);
|
||||
const styledChips = orderedParticipants.map((participant) => (
|
||||
<ParticipantChip key={participant.id} participant={participant} />
|
||||
));
|
||||
|
||||
return (
|
||||
<StyledResponseStatusRow>
|
||||
<StyledLabelAndIconContainer>
|
||||
<StyledIconContainer>{Icon}</StyledIconContainer>
|
||||
<StyledLabelContainer width={72}>
|
||||
<EllipsisDisplay>{responseStatus}</EllipsisDisplay>
|
||||
</StyledLabelContainer>
|
||||
</StyledLabelAndIconContainer>
|
||||
<StyledParticipantsContainer ref={participantsContainerRef}>
|
||||
<ExpandableList isChipCountDisplayed>{styledChips}</ExpandableList>
|
||||
</StyledParticipantsContainer>
|
||||
</StyledResponseStatusRow>
|
||||
);
|
||||
};
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
import { CalendarEventParticipantsResponseStatus } from '@/activities/calendar/components/CalendarEventParticipantsResponseStatus';
|
||||
import { type CalendarEventParticipant } from '@/activities/calendar/types/CalendarEventParticipant';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
|
||||
const CALENDAR_EVENT_PARTICIPANT_OBJECT_NAME_SINGULAR =
|
||||
'calendarEventParticipant';
|
||||
|
||||
type CalendarEventParticipantsFieldWidgetProps = {
|
||||
recordId: string;
|
||||
};
|
||||
|
||||
type CalendarEventParticipantRecord = CalendarEventParticipant & {
|
||||
__typename: 'CalendarEventParticipant';
|
||||
};
|
||||
|
||||
export const CalendarEventParticipantsFieldWidget = ({
|
||||
recordId,
|
||||
}: CalendarEventParticipantsFieldWidgetProps) => {
|
||||
const { records: calendarEventParticipants } =
|
||||
useFindManyRecords<CalendarEventParticipantRecord>({
|
||||
objectNameSingular: CALENDAR_EVENT_PARTICIPANT_OBJECT_NAME_SINGULAR,
|
||||
filter: {
|
||||
calendarEventId: {
|
||||
eq: recordId,
|
||||
},
|
||||
},
|
||||
recordGqlFields: {
|
||||
id: true,
|
||||
person: true,
|
||||
workspaceMember: true,
|
||||
isOrganizer: true,
|
||||
responseStatus: true,
|
||||
handle: true,
|
||||
displayName: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (calendarEventParticipants.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<CalendarEventParticipantsResponseStatus
|
||||
participants={calendarEventParticipants}
|
||||
/>
|
||||
);
|
||||
};
|
||||
-15
@@ -9,7 +9,6 @@ import { hasJunctionConfig } from '@/object-record/record-field/ui/utils/junctio
|
||||
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
|
||||
import { useResolveFieldMetadataIdFromNameOrId } from '@/page-layout/hooks/useResolveFieldMetadataIdFromNameOrId';
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import { CalendarEventParticipantsFieldWidget } from '@/page-layout/widgets/field/components/CalendarEventParticipantsFieldWidget';
|
||||
import { FieldWidgetDisplay } from '@/page-layout/widgets/field/components/FieldWidgetDisplay';
|
||||
import { FieldWidgetJunctionRelationCard } from '@/page-layout/widgets/field/components/FieldWidgetJunctionRelationCard';
|
||||
import { FieldWidgetJunctionRelationField } from '@/page-layout/widgets/field/components/FieldWidgetJunctionRelationField';
|
||||
@@ -27,7 +26,6 @@ import { SidePanelProvider } from '@/ui/layout/side-panel/contexts/SidePanelCont
|
||||
import { useAtomFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilySelectorValue';
|
||||
import { styled } from '@linaria/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CoreObjectNameSingular } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
AnimatedPlaceholder,
|
||||
@@ -101,19 +99,6 @@ export const FieldWidget = ({ widget }: FieldWidgetProps) => {
|
||||
|
||||
const fieldDisplayMode = widget.configuration.fieldDisplayMode;
|
||||
|
||||
const isCalendarEventParticipantsField =
|
||||
targetRecord.targetObjectNameSingular ===
|
||||
CoreObjectNameSingular.CalendarEvent &&
|
||||
fieldMetadataItem.name === 'calendarEventParticipants';
|
||||
|
||||
if (isCalendarEventParticipantsField) {
|
||||
return (
|
||||
<SidePanelProvider value={{ isInSidePanel }}>
|
||||
<CalendarEventParticipantsFieldWidget recordId={targetRecord.id} />
|
||||
</SidePanelProvider>
|
||||
);
|
||||
}
|
||||
|
||||
if (isFieldMorphRelation(fieldDefinition)) {
|
||||
if (fieldDisplayMode === FieldDisplayMode.CARD) {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user