ISSUE-845 Edit in XXX calendar

This commit is contained in:
Benoit TELLIER
2026-04-28 11:48:19 +02:00
parent c910f3e3a9
commit 2f849b5323
7 changed files with 76 additions and 6 deletions
@@ -1,4 +1,4 @@
import { Box, IconButton } from '@linagora/twake-mui'
import { Box, IconButton, Tooltip } from '@linagora/twake-mui'
import CloseIcon from '@mui/icons-material/Close'
import EditIcon from '@mui/icons-material/Edit'
import FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined'
@@ -13,23 +13,26 @@ interface EventPreviewHeaderProps {
isOwn: boolean
isWriteDelegated: boolean
isNotPrivate: boolean
canEdit: boolean
onClose: () => void
onEdit: () => void
onMoreClick: (e: React.MouseEvent<HTMLElement>) => void
onEditInOrganizerCalendar?: () => void
editInOrganizerCalendarTooltip?: string
}
export function EventPreviewHeader({
event,
eventId,
isOrganizer,
isOwn,
isWriteDelegated,
isNotPrivate,
canEdit,
onClose,
onEdit,
onMoreClick
onMoreClick,
onEditInOrganizerCalendar,
editInOrganizerCalendarTooltip
}: EventPreviewHeaderProps) {
const canEdit = isOrganizer && (isOwn || (isWriteDelegated && isNotPrivate))
const canSeeMore = isNotPrivate || isOwn
return (
@@ -70,6 +73,13 @@ export function EventPreviewHeader({
<EditIcon />
</IconButton>
)}
{!canEdit && onEditInOrganizerCalendar && (
<Tooltip title={editInOrganizerCalendarTooltip} placement="top">
<IconButton size="small" onClick={onEditInOrganizerCalendar}>
<EditIcon />
</IconButton>
</Tooltip>
)}
{canSeeMore && (
<IconButton size="small" onClick={onMoreClick}>
<MoreVertIcon />
@@ -43,6 +43,8 @@ export default function EventPreviewModal({
isWriteDelegated,
isOrganizer,
isNotPrivate,
canEdit,
organizerWritableCalendar,
openUpdateModal,
setOpenUpdateModal,
openDuplicateModal,
@@ -51,6 +53,7 @@ export default function EventPreviewModal({
setHidePreview,
toggleActionMenu,
setToggleActionMenu,
updateModalCalId,
openEditModePopup,
setOpenEditModePopup,
setTypeOfAction,
@@ -58,6 +61,7 @@ export default function EventPreviewModal({
setAfterChoiceFunc,
resolvedTypeOfAction,
handleEditClick,
handleEditInOrganizerCalendar,
handleDeleteClick,
handleDuplicateClick
} = useEventPreviewState(eventId, calId, tempEvent, open, onClose)
@@ -101,9 +105,23 @@ export default function EventPreviewModal({
isOwn={isOwn}
isWriteDelegated={isWriteDelegated}
isNotPrivate={isNotPrivate}
canEdit={canEdit}
onClose={() => onClose({}, 'backdropClick')}
onEdit={handleEditClick}
onMoreClick={e => setToggleActionMenu(e.currentTarget)}
onEditInOrganizerCalendar={
organizerWritableCalendar
? handleEditInOrganizerCalendar
: undefined
}
editInOrganizerCalendarTooltip={
organizerWritableCalendar
? t('eventPreview.editInOrganizerCalendar').replace(
'%{calendarName}',
organizerWritableCalendar.name
)
: undefined
}
/>
}
actions={
@@ -209,7 +227,7 @@ export default function EventPreviewModal({
onClose({}, 'backdropClick')
}}
eventId={eventId}
calId={calId}
calId={updateModalCalId}
typeOfAction={resolvedTypeOfAction}
/>
@@ -1,4 +1,5 @@
import { useAppDispatch, useAppSelector } from '@/app/hooks'
import { Calendar } from '@/features/Calendars/CalendarTypes'
import { assertThunkSuccess } from '@/utils/assertThunkSuccess'
import { getEffectiveEmail } from '@/utils/getEffectiveEmail'
import { isEventOrganiser } from '@/utils/isEventOrganiser'
@@ -31,6 +32,7 @@ export function useEventPreviewState(
const [openDuplicateModal, setOpenDuplicateModal] = useState(false)
const [hidePreview, setHidePreview] = useState(false)
const [toggleActionMenu, setToggleActionMenu] = useState<Element | null>(null)
const [updateModalCalId, setUpdateModalCalId] = useState(calId)
// Recurring event handling
const [openEditModePopup, setOpenEditModePopup] = useState<string | null>(
@@ -68,6 +70,22 @@ export function useEventPreviewState(
const isNotPrivate =
event?.class !== 'PRIVATE' && event?.class !== 'CONFIDENTIAL'
const canEdit = isOrganizer && (isOwn || (isWriteDelegated && isNotPrivate))
// If the user cannot edit here but has write access to the organizer's delegated
// calendar, surface a shortcut so they don't have to hunt for the source event.
const organizerEmail = event?.organizer?.cal_address?.toLowerCase()
const organizerWritableCalendar: Calendar | undefined =
!canEdit && organizerEmail
? Object.values(calendars.list).find(
cal =>
cal.delegated &&
cal.access?.write &&
cal.owner?.emails?.some(e => e.toLowerCase() === organizerEmail) &&
cal.events[eventId] !== undefined
)
: undefined
const contextualizedEvent =
event && calendar && user ? createEventContext(event, calendar, user) : null
@@ -97,6 +115,22 @@ export function useEventPreviewState(
// Action handlers
const handleEditClick = () => {
setUpdateModalCalId(calId)
if (isRecurring) {
setAfterChoiceFunc(() => () => {
setHidePreview(true)
setOpenUpdateModal(true)
})
setOpenEditModePopup('edit')
} else {
setHidePreview(true)
setOpenUpdateModal(true)
}
}
const handleEditInOrganizerCalendar = () => {
if (!organizerWritableCalendar) return
setUpdateModalCalId(organizerWritableCalendar.id)
if (isRecurring) {
setAfterChoiceFunc(() => () => {
setHidePreview(true)
@@ -158,6 +192,8 @@ export function useEventPreviewState(
isWriteDelegated,
isOrganizer,
isNotPrivate,
canEdit,
organizerWritableCalendar,
// Modal state
openUpdateModal,
@@ -168,6 +204,7 @@ export function useEventPreviewState(
setHidePreview,
toggleActionMenu,
setToggleActionMenu,
updateModalCalId,
// Recurring state
openEditModePopup,
@@ -180,6 +217,7 @@ export function useEventPreviewState(
// Handlers
handleEditClick,
handleEditInOrganizerCalendar,
handleDeleteClick,
handleDuplicateClick,
+1
View File
@@ -319,6 +319,7 @@
},
"showMore": "Show more",
"showLess": "Show less",
"editInOrganizerCalendar": "Edit in %{calendarName}",
"joinVideo": "Join the video conference",
"joinVideoShort": "Join",
"guests": "%{count} guests",
+1
View File
@@ -320,6 +320,7 @@
},
"showMore": "Afficher plus",
"showLess": "Afficher moins",
"editInOrganizerCalendar": "Modifier dans %{calendarName}",
"joinVideo": "Rejoindre la visioconférence",
"joinVideoShort": "Rejoindre",
"guests": "%{count} participants",
+1
View File
@@ -320,6 +320,7 @@
},
"showMore": "Показать больше",
"showLess": "Показать меньше",
"editInOrganizerCalendar": "Редактировать в %{calendarName}",
"joinVideo": "Присоединиться к видеоконференции",
"joinVideoShort": "Присоединиться",
"guests": "%{count} гостей",
+1
View File
@@ -318,6 +318,7 @@
},
"showMore": "Xem thêm",
"showLess": "Thu gọn",
"editInOrganizerCalendar": "Chỉnh sửa trong %{calendarName}",
"joinVideo": "Tham gia cuộc họp video",
"joinVideoShort": "Tham gia",
"guests": "%{count} khách",