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

Calendar events changes #6998

Merged
merged 20 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8745645
name layout change, all day events, 15mins distance
bobbykolev Oct 7, 2024
6f2ffc0
multi-days events support Create/Update
bobbykolev Oct 7, 2024
9031be6
Merge branch 'develop' into client-3912-calendar
bobbykolev Oct 8, 2024
5ee6663
support same day duration together with multi-days
bobbykolev Oct 9, 2024
f27d0a5
Merge branch 'client-3912-calendar' of https://github.com/alkem-io/cl…
bobbykolev Oct 9, 2024
1e0e7a9
event date-time validation
bobbykolev Oct 9, 2024
8f1e1e9
fix annoying console error
bobbykolev Oct 9, 2024
0ac1385
Rounded badge multi-day events display
bobbykolev Oct 10, 2024
8e94d2e
remove the location text from event default description
bobbykolev Oct 10, 2024
bd8ffc1
multi-day support in long event dates formatting - event details
bobbykolev Oct 10, 2024
8d4e20b
fix event details dates not visible on mobile
bobbykolev Oct 10, 2024
fc7572c
multi-day events support on the calendar
bobbykolev Oct 10, 2024
1391621
fix and format the tooltip on calendar events widget
bobbykolev Oct 10, 2024
725aa24
Event description not mandatory anymore, no default value for now
bobbykolev Oct 10, 2024
f3f8531
Merge branch 'develop' into client-3912-calendar
bobbykolev Oct 10, 2024
60119b5
Merge branch 'develop' into client-3912-calendar
bobbykolev Oct 13, 2024
0fe1825
PR fixes + optimizations
bobbykolev Oct 14, 2024
68c6da6
Merge branch 'client-3912-calendar' of https://github.com/alkem-io/cl…
bobbykolev Oct 14, 2024
f4b571b
Merge branch 'develop' into client-3912-calendar
bobbykolev Oct 14, 2024
36adc66
missed translation + wording update
bobbykolev Oct 14, 2024
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
4 changes: 4 additions & 0 deletions src/core/apollo/generated/apollo-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2970,6 +2970,10 @@ export const CalendarEventDetailsFragmentDoc = gql`
tagsets {
...TagsetDetails
}
location {
id
city
}
}
}
createdDate
Expand Down
4 changes: 4 additions & 0 deletions src/core/apollo/generated/graphql-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26220,6 +26220,7 @@ export type CalendarEventDetailsQuery = {
type: TagsetType;
}>
| undefined;
location?: { __typename?: 'Location'; id: string; city?: string | undefined } | undefined;
};
}
| undefined;
Expand Down Expand Up @@ -26418,6 +26419,7 @@ export type CalendarEventDetailsFragment = {
type: TagsetType;
}>
| undefined;
location?: { __typename?: 'Location'; id: string; city?: string | undefined } | undefined;
};
}
| undefined;
Expand Down Expand Up @@ -26610,6 +26612,7 @@ export type CreateCalendarEventMutation = {
type: TagsetType;
}>
| undefined;
location?: { __typename?: 'Location'; id: string; city?: string | undefined } | undefined;
};
}
| undefined;
Expand Down Expand Up @@ -26787,6 +26790,7 @@ export type UpdateCalendarEventMutation = {
type: TagsetType;
}>
| undefined;
location?: { __typename?: 'Location'; id: string; city?: string | undefined } | undefined;
};
}
| undefined;
Expand Down
2 changes: 1 addition & 1 deletion src/core/i18n/bg/translation.bg.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"no-upcoming-events": "Currently, there are no upcoming events to be displayed",
"past-events": "Past Events",
"show-calendar": "Show calendar",
"defaultEventDescription": "$t(common.location):\n\n$t(common.url):\n\n$t(common.description):"
"defaultEventDescription": ""
},
"buttons": {
"leave": "Напусни",
Expand Down
2 changes: 1 addition & 1 deletion src/core/i18n/de/translation.de.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"no-upcoming-events": "Zur Zeit gibt es keine anstehenden Events zum Anzeigen",
"past-events": "Vergangene Termine",
"show-calendar": "Kalender anzeigen",
"defaultEventDescription": "$t(common.location):\n\n$t(common.url):\n\n$t(common.description):"
"defaultEventDescription": ""
},
"buttons": {
"leave": "Verlassen",
Expand Down
2 changes: 1 addition & 1 deletion src/core/i18n/en/translation.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"no-upcoming-events": "Currently, there are no upcoming events to be displayed",
"past-events": "Past Events",
"show-calendar": "Show calendar",
"defaultEventDescription": "$t(common.location):\n\n$t(common.url):\n\n$t(common.description):",
"defaultEventDescription": "",
"adminsOnly": "Since there are no events, this block is only visible for admins and leads"
},
"buttons": {
Expand Down
2 changes: 1 addition & 1 deletion src/core/i18n/es/translation.es.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"no-upcoming-events": "Actualmente no hay eventos próximos que mostrar",
"past-events": "Eventos anteriores",
"show-calendar": "Mostrar Calendario",
"defaultEventDescription": "$t(common.location):\n\n$t(common.url):\n\n$t(common.description):"
"defaultEventDescription": ""
},
"buttons": {
"leave": "Salir",
Expand Down
2 changes: 1 addition & 1 deletion src/core/i18n/fr/translation.fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"no-upcoming-events": "Actuellement, il n'y a aucun événement à venir à afficher",
"past-events": "Événements passés",
"show-calendar": "Afficher le calendrier",
"defaultEventDescription": "$t(commun.location):\n\n$t(common.url):\n\n$t(common.description):"
"defaultEventDescription": ""
bobbykolev marked this conversation as resolved.
Show resolved Hide resolved
},
"buttons": {
"leave": "Partir",
Expand Down
2 changes: 1 addition & 1 deletion src/core/i18n/nl/translation.nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"no-upcoming-events": "Er zijn momenteel geen evenementen om weer te geven",
"past-events": "Afgelopen evenementen",
"show-calendar": "Toon Kalender",
"defaultEventDescription": "$t(common.location):\n\n$t(common.url):\n\n$t(common.description):"
"defaultEventDescription": ""
},
"buttons": {
"leave": "Verlaat",
Expand Down
2 changes: 1 addition & 1 deletion src/core/i18n/pt/translation.pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"no-upcoming-events": "Atualmente, não há eventos futuros para serem exibidos",
"past-events": "Eventos Anteriores",
"show-calendar": "Exibir calendário",
"defaultEventDescription": "$t(common.location):\n\n$t(common.url):\n\n$t(common.description):"
"defaultEventDescription": ""
bobbykolev marked this conversation as resolved.
Show resolved Hide resolved
},
"buttons": {
"leave": "Sair",
Expand Down
2 changes: 1 addition & 1 deletion src/core/i18n/ua/translation.ua.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"no-upcoming-events": "Currently, there are no upcoming events to be displayed",
"past-events": "Past Events",
"show-calendar": "Show calendar",
"defaultEventDescription": "$t(common.location):\n\n$t(common.url):\n\n$t(common.description):"
"defaultEventDescription": ""
},
"buttons": {
"leave": "Leave",
Expand Down
8 changes: 7 additions & 1 deletion src/core/ui/forms/DatePicker/AlkemioTimePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ const AlkemioTimePicker = ({
const djsDate = useMemo(() => dayjs(value).startOf('day'), [value]);

const timeSlots = useMemo(
() => times(24).flatMap(h => [djsDate.set('hour', h), djsDate.set('hour', h).set('minute', 30)]),
() =>
times(24).flatMap(h => [
djsDate.set('hour', h).set('minute', 0),
djsDate.set('hour', h).set('minute', 15),
djsDate.set('hour', h).set('minute', 30),
djsDate.set('hour', h).set('minute', 45),
]),
[djsDate]
);

Expand Down
10 changes: 9 additions & 1 deletion src/core/ui/forms/DatePicker/FormikDurationMinutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const FormikDurationMinutes = ({ name, startTimeFieldName, ...datePickerProps }:

const oldStartTimeRef = useRef(new Date(startTimeField.value));

useLayoutEffect(() => {
const updateDurationMinutes = () => {
// Normally we keep durationMinutes when startTime changes, except for the case when
// startTime was after endTime (negative durationMinutes) but then it got changed
// to be before endTime (valid combination).
Expand All @@ -56,6 +56,14 @@ const FormikDurationMinutes = ({ name, startTimeFieldName, ...datePickerProps }:
if (isStartTimeValid) {
oldStartTimeRef.current = startTime;
}
};

useLayoutEffect(() => {
updateDurationMinutes();
}, []);

useLayoutEffect(() => {
updateDurationMinutes();
bobbykolev marked this conversation as resolved.
Show resolved Hide resolved
}, [startTimeField.value]);

const date = addMinutes(startTimeField.value, field.value);
Expand Down
6 changes: 4 additions & 2 deletions src/core/ui/icon/RoundedBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { PropsWithChildren } from 'react';
import { Box, BoxProps, useTheme } from '@mui/material';
import { Box, BoxProps, SxProps, Theme, useTheme } from '@mui/material';

export type RoundedBadgeSize = 'medium' | 'small' | 'xsmall';

export interface RoundedBadgeProps extends BoxProps {
size: RoundedBadgeSize;
color?: string;
sx?: SxProps<Theme>;
}

const getSizeInSpacing = (size: RoundedBadgeSize) => {
Expand All @@ -22,6 +23,7 @@ const getSizeInSpacing = (size: RoundedBadgeSize) => {
const RoundedBadge = ({
size,
color = 'primary.main',
borderRadius = '50%',
children,
sx,
...containerProps
Expand All @@ -37,7 +39,7 @@ const RoundedBadge = ({
sx={{
backgroundColor: color,
color: 'common.white',
borderRadius: '50%',
borderRadius,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
Expand Down
120 changes: 109 additions & 11 deletions src/core/utils/time/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,104 @@ const LocaleId = 'en-GB';

export const DAYJS_DATEFORMAT = 'DD/MM/YYYY';

export const formatBadgeDate = (date: Date | undefined, defaultValue: string = '') => {
if (!date) {
return defaultValue;
export const getEndDateByDuration = (startDate: Date | string | undefined, durationMinutes: number) => {
if (!startDate) {
return new Date();
}
return new Date(date).toLocaleDateString(LocaleId, { day: '2-digit', month: '2-digit' });

return new Date(new Date(startDate).getTime() + durationMinutes * 60000);
bobbykolev marked this conversation as resolved.
Show resolved Hide resolved
};

export const formatTooltipDate = (date: Date | undefined, defaultValue: string = '') => {
if (!date) {
type BadgeDateProps = {
startDate: Date | undefined;
durationMinutes: number;
durationDays?: number;
defaultValue?: string;
};

// Badge component displays start and end dates
// we're calculating the end date (if such) by durationMinutes
export const formatBadgeDate = ({
startDate,
durationMinutes,
durationDays = 0,
defaultValue = '',
}: BadgeDateProps) => {
if (!startDate) {
return {
startDate: defaultValue,
endDate: null,
};
}

const startDateFormatted = new Date(startDate).toLocaleDateString(LocaleId, { day: '2-digit', month: '2-digit' });

if (!durationDays || durationDays < 1) {
return {
startDate: startDateFormatted,
endDate: null,
};
} else if (durationMinutes && durationMinutes > 0) {
bobbykolev marked this conversation as resolved.
Show resolved Hide resolved
const endDate = getEndDateByDuration(startDate, durationMinutes);

return {
startDate: startDateFormatted,
endDate: endDate.toLocaleDateString(LocaleId, { day: '2-digit', month: '2-digit' }),
};
}

return {
startDate: startDateFormatted,
endDate: null,
};
};
bobbykolev marked this conversation as resolved.
Show resolved Hide resolved

// either only startDateTime
// or startDateTime - endDateTime
export const formatLongDateTimeString = ({
startDate,
durationMinutes,
durationDays = 0,
defaultValue = '',
}: BadgeDateProps) => {
if (!startDate) {
return defaultValue;
}
return new Date(date).toLocaleDateString(LocaleId, {
weekday: 'long',

// note can't extract the formatting options beacuse of type error
let longDateTimeString = new Date(startDate).toLocaleDateString(LocaleId, {
weekday: 'short',
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
});

if ((durationDays || 0) > 0 && durationMinutes && durationMinutes > 0) {
const endDate = getEndDateByDuration(startDate, durationMinutes);

longDateTimeString +=
' - ' +
endDate.toLocaleDateString(LocaleId, {
weekday: 'short',
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
});
}
bobbykolev marked this conversation as resolved.
Show resolved Hide resolved

return longDateTimeString;
};

export const formatLongDate = (date: Date | undefined, defaultValue: string = '') => {
if (!date) {
return defaultValue;
}
return new Date(date).toLocaleDateString(LocaleId, {
weekday: 'long',
weekday: 'short',
day: '2-digit',
month: '2-digit',
year: 'numeric',
Expand All @@ -50,15 +121,16 @@ export function addMinutes(date: Date | string, minutes: number): Date {
}

export const formatTimeAndDuration = (
event: { startDate?: Date; durationMinutes?: number; wholeDay?: boolean },
event: { startDate?: Date; durationMinutes?: number; wholeDay?: boolean; durationDays?: number },
t: TFunction<'translation', undefined>
) => {
if (!event.startDate) return '';
if (event.wholeDay) {
return t('calendar.event.whole-day');
}
const startDate = new Date(event.startDate);
if (!event.durationMinutes) {

if (!event.durationMinutes || (event.durationDays ?? 0) > 0) {
return startDate.toLocaleTimeString(LocaleId, {
hour: '2-digit',
minute: '2-digit',
Expand All @@ -79,6 +151,17 @@ export const formatTimeAndDuration = (
}
};

export const formatTime = (date: Date | undefined) => {
if (!date) {
return null;
}

return date.toLocaleTimeString(LocaleId, {
hour: '2-digit',
minute: '2-digit',
});
};

export const dateRounded = (date: Date = new Date()) => {
const result = new Date(new Date(date).getTime() + 59 * 60000); // Round to the next hour
result.setMinutes(0);
Expand All @@ -99,3 +182,18 @@ export const startOfDay = (date: Date = new Date()) => {
export const formatDateTime = (date: Date) => {
return dayjs(date).format('DD/MM/YYYY[ at ]HH:mm');
};

export const isSameDay = (startDate: Date | undefined, endDate: number | Date | undefined) => {
if (!startDate || !endDate) {
return true;
}

const startDateOnly = new Date(startDate);
const endDateOnly = new Date(endDate);

return (
startDateOnly.getFullYear() === endDateOnly.getFullYear() &&
startDateOnly.getMonth() === endDateOnly.getMonth() &&
startDateOnly.getDate() === endDateOnly.getDate()
);
};
bobbykolev marked this conversation as resolved.
Show resolved Hide resolved
Loading