Date formatting per workspace member settings (#6408)
Implement date formatting per workspace member settings We'll need another round to maybe initialize all workspaces on the default settings. For now the default behavior is to take system settings if nothing is found in DB. --------- Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
@ -1,4 +1,3 @@
|
||||
import { useContext, useMemo, useState } from 'react';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import {
|
||||
@ -8,13 +7,14 @@ import {
|
||||
startOfMonth,
|
||||
} from 'date-fns';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useContext, useMemo, useState } from 'react';
|
||||
|
||||
import { CalendarContext } from '@/activities/calendar/contexts/CalendarContext';
|
||||
import { getCalendarEventEndDate } from '@/activities/calendar/utils/getCalendarEventEndDate';
|
||||
import { getCalendarEventStartDate } from '@/activities/calendar/utils/getCalendarEventStartDate';
|
||||
import { hasCalendarEventEnded } from '@/activities/calendar/utils/hasCalendarEventEnded';
|
||||
import { hasCalendarEventStarted } from '@/activities/calendar/utils/hasCalendarEventStarted';
|
||||
import { TimelineCalendarEvent } from '~/generated-metadata/graphql';
|
||||
import { TimelineCalendarEvent } from '~/generated/graphql';
|
||||
|
||||
type CalendarCurrentEventCursorProps = {
|
||||
calendarEvent: TimelineCalendarEvent;
|
||||
|
||||
@ -5,7 +5,7 @@ import { differenceInSeconds, endOfDay, format } from 'date-fns';
|
||||
import { CalendarEventRow } from '@/activities/calendar/components/CalendarEventRow';
|
||||
import { getCalendarEventStartDate } from '@/activities/calendar/utils/getCalendarEventStartDate';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
import { TimelineCalendarEvent } from '~/generated-metadata/graphql';
|
||||
import { TimelineCalendarEvent } from '~/generated/graphql';
|
||||
|
||||
type CalendarDayCardContentProps = {
|
||||
calendarEvents: TimelineCalendarEvent[];
|
||||
|
||||
@ -3,7 +3,13 @@ import styled from '@emotion/styled';
|
||||
import { format } from 'date-fns';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { Avatar, AvatarGroup, IconArrowRight, IconLock } from 'twenty-ui';
|
||||
import {
|
||||
Avatar,
|
||||
AvatarGroup,
|
||||
IconArrowRight,
|
||||
IconLock,
|
||||
isDefined,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { CalendarCurrentEventCursor } from '@/activities/calendar/components/CalendarCurrentEventCursor';
|
||||
import { CalendarContext } from '@/activities/calendar/contexts/CalendarContext';
|
||||
@ -14,9 +20,10 @@ import { hasCalendarEventEnded } from '@/activities/calendar/utils/hasCalendarEv
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
import { TimelineCalendarEvent } from '~/generated-metadata/graphql';
|
||||
import { CalendarChannelVisibility } from '~/generated/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import {
|
||||
CalendarChannelVisibility,
|
||||
TimelineCalendarEvent,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
type CalendarEventRowProps = {
|
||||
calendarEvent: TimelineCalendarEvent;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { createContext } from 'react';
|
||||
|
||||
import { TimelineCalendarEvent } from '~/generated-metadata/graphql';
|
||||
import { TimelineCalendarEvent } from '~/generated/graphql';
|
||||
|
||||
type CalendarContextValue = {
|
||||
calendarEventsByDayTime: Record<number, TimelineCalendarEvent[] | undefined>;
|
||||
|
||||
@ -1,41 +1,87 @@
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
|
||||
import { useCalendarEvents } from '@/activities/calendar/hooks/useCalendarEvents';
|
||||
import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
|
||||
import { CalendarChannelVisibility } from '~/generated/graphql';
|
||||
import {
|
||||
CalendarChannelVisibility,
|
||||
TimelineCalendarEvent,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
const calendarEvents: CalendarEvent[] = [
|
||||
const calendarEvents: TimelineCalendarEvent[] = [
|
||||
{
|
||||
id: '1234',
|
||||
externalCreatedAt: '2024-02-17T20:45:43.854Z',
|
||||
isFullDay: false,
|
||||
startsAt: '2024-02-17T21:45:27.822Z',
|
||||
visibility: CalendarChannelVisibility.Metadata,
|
||||
__typename: 'CalendarEvent',
|
||||
conferenceLink: {
|
||||
primaryLinkUrl: 'https://meet.google.com/abc-def-ghi',
|
||||
primaryLinkLabel: 'Google Meet',
|
||||
__typename: 'LinksMetadata',
|
||||
},
|
||||
conferenceSolution: 'GoogleMeet',
|
||||
description: 'Description',
|
||||
endsAt: '2024-02-17T22:45:27.822Z',
|
||||
isCanceled: false,
|
||||
location: 'Location',
|
||||
participants: [],
|
||||
title: 'Title',
|
||||
__typename: 'TimelineCalendarEvent',
|
||||
},
|
||||
{
|
||||
id: '5678',
|
||||
externalCreatedAt: '2024-02-18T19:43:37.854Z',
|
||||
isFullDay: false,
|
||||
startsAt: '2024-02-18T21:43:27.754Z',
|
||||
visibility: CalendarChannelVisibility.ShareEverything,
|
||||
__typename: 'CalendarEvent',
|
||||
conferenceLink: {
|
||||
primaryLinkUrl: 'https://meet.google.com/abc-def-ghi',
|
||||
primaryLinkLabel: 'Google Meet',
|
||||
__typename: 'LinksMetadata',
|
||||
},
|
||||
conferenceSolution: 'GoogleMeet',
|
||||
description: 'Description',
|
||||
endsAt: '2024-02-17T22:45:27.822Z',
|
||||
isCanceled: false,
|
||||
location: 'Location',
|
||||
participants: [],
|
||||
title: 'Title',
|
||||
__typename: 'TimelineCalendarEvent',
|
||||
},
|
||||
{
|
||||
id: '91011',
|
||||
externalCreatedAt: '2024-02-19T20:45:20.854Z',
|
||||
isFullDay: true,
|
||||
startsAt: '2024-02-19T22:05:27.653Z',
|
||||
visibility: CalendarChannelVisibility.Metadata,
|
||||
__typename: 'CalendarEvent',
|
||||
conferenceLink: {
|
||||
primaryLinkUrl: 'https://meet.google.com/abc-def-ghi',
|
||||
primaryLinkLabel: 'Google Meet',
|
||||
__typename: 'LinksMetadata',
|
||||
},
|
||||
conferenceSolution: 'GoogleMeet',
|
||||
description: 'Description',
|
||||
endsAt: '2024-02-17T22:45:27.822Z',
|
||||
isCanceled: false,
|
||||
location: 'Location',
|
||||
participants: [],
|
||||
title: 'Title',
|
||||
__typename: 'TimelineCalendarEvent',
|
||||
},
|
||||
{
|
||||
id: '121314',
|
||||
externalCreatedAt: '2024-02-20T20:45:12.854Z',
|
||||
isFullDay: true,
|
||||
startsAt: '2024-02-20T23:15:23.150Z',
|
||||
visibility: CalendarChannelVisibility.ShareEverything,
|
||||
__typename: 'CalendarEvent',
|
||||
conferenceLink: {
|
||||
primaryLinkUrl: 'https://meet.google.com/abc-def-ghi',
|
||||
primaryLinkLabel: 'Google Meet',
|
||||
__typename: 'LinksMetadata',
|
||||
},
|
||||
conferenceSolution: 'GoogleMeet',
|
||||
description: 'Description',
|
||||
endsAt: '2024-02-17T22:45:27.822Z',
|
||||
isCanceled: false,
|
||||
location: 'Location',
|
||||
participants: [],
|
||||
title: 'Title',
|
||||
__typename: 'TimelineCalendarEvent',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@ -1,21 +1,14 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { getYear, isThisMonth, startOfDay, startOfMonth } from 'date-fns';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
|
||||
import { findUpcomingCalendarEvent } from '@/activities/calendar/utils/findUpcomingCalendarEvent';
|
||||
import { getCalendarEventStartDate } from '@/activities/calendar/utils/getCalendarEventStartDate';
|
||||
import { TimelineCalendarEvent } from '~/generated/graphql';
|
||||
import { groupArrayItemsBy } from '~/utils/array/groupArrayItemsBy';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { sortDesc } from '~/utils/sort';
|
||||
|
||||
type CalendarEventGeneric = Omit<
|
||||
CalendarEvent,
|
||||
'participants' | 'externalCreatedAt' | '__typename'
|
||||
>;
|
||||
|
||||
export const useCalendarEvents = <T extends CalendarEventGeneric>(
|
||||
calendarEvents: T[],
|
||||
) => {
|
||||
export const useCalendarEvents = (calendarEvents: TimelineCalendarEvent[]) => {
|
||||
const calendarEventsByDayTime = groupArrayItemsBy(
|
||||
calendarEvents,
|
||||
(calendarEvent) =>
|
||||
@ -36,14 +29,14 @@ export const useCalendarEvents = <T extends CalendarEventGeneric>(
|
||||
|
||||
const monthTimesByYear = groupArrayItemsBy(sortedMonthTimes, getYear);
|
||||
|
||||
const getPreviousCalendarEvent = (calendarEvent: T) => {
|
||||
const getPreviousCalendarEvent = (calendarEvent: TimelineCalendarEvent) => {
|
||||
const calendarEventIndex = calendarEvents.indexOf(calendarEvent);
|
||||
return calendarEventIndex < calendarEvents.length - 1
|
||||
? calendarEvents[calendarEventIndex + 1]
|
||||
: undefined;
|
||||
};
|
||||
|
||||
const getNextCalendarEvent = (calendarEvent: T) => {
|
||||
const getNextCalendarEvent = (calendarEvent: TimelineCalendarEvent) => {
|
||||
const calendarEventIndex = calendarEvents.indexOf(calendarEvent);
|
||||
return calendarEventIndex > 0
|
||||
? calendarEvents[calendarEventIndex - 1]
|
||||
|
||||
@ -6,6 +6,8 @@ import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { UserContext } from '@/users/contexts/UserContext';
|
||||
import { useContext } from 'react';
|
||||
import {
|
||||
formatToHumanReadableDay,
|
||||
formatToHumanReadableMonth,
|
||||
@ -107,6 +109,8 @@ export const EventCardCalendarEvent = ({
|
||||
|
||||
const { openCalendarEventRightDrawer } = useOpenCalendarEventRightDrawer();
|
||||
|
||||
const { timeZone } = useContext(UserContext);
|
||||
|
||||
if (isDefined(error)) {
|
||||
const shouldHideMessageContent = error.graphQLErrors.some(
|
||||
(e) => e.extensions?.code === 'FORBIDDEN',
|
||||
@ -138,12 +142,14 @@ export const EventCardCalendarEvent = ({
|
||||
throw new Error("Can't render a calendarEvent without a start date");
|
||||
}
|
||||
|
||||
const startsAtMonth = formatToHumanReadableMonth(startsAtDate);
|
||||
const startsAtMonth = formatToHumanReadableMonth(startsAtDate, timeZone);
|
||||
|
||||
const startsAtDay = formatToHumanReadableDay(startsAtDate);
|
||||
const startsAtDay = formatToHumanReadableDay(startsAtDate, timeZone);
|
||||
|
||||
const startsAtHour = formatToHumanReadableTime(startsAtDate);
|
||||
const endsAtHour = endsAtDate ? formatToHumanReadableTime(endsAtDate) : null;
|
||||
const startsAtHour = formatToHumanReadableTime(startsAtDate, timeZone);
|
||||
const endsAtHour = endsAtDate
|
||||
? formatToHumanReadableTime(endsAtDate, timeZone)
|
||||
: null;
|
||||
|
||||
return (
|
||||
<StyledEventCardCalendarEventContainer
|
||||
|
||||
Reference in New Issue
Block a user