Коммит bd5a6b53 создал по автору Radch-enko's avatar Radch-enko
Просмотр файлов

feat: add `isEditable` flag for bookings

Introduce an `isEditable` property in booking-related models, DTOs, and UI components. This flag determines if a booking can be edited or deleted within the tablet client. Adjusted UI behavior and backend logic to account for this property.
владелец 2c7917fd
......@@ -90,11 +90,7 @@ class GoogleCalendarProvider(
calendar.events().delete(defaultCalendar, eventId).execute()
} catch (e: GoogleJsonResponseException) {
logger.error("Failed to delete event: {}", e.details)
if (e.statusCode != 404 && e.statusCode != 410) {
throw e
}
// If the event doesn't exist (404) or has been deleted (410), ignore the exception
logger.warn("Event with ID {} not found or already deleted", eventId)
throw e
}
}
......@@ -344,6 +340,11 @@ class GoogleCalendarProvider(
matchResult?.groupValues?.get(1)
}
// Determine if the booking is editable based on the organizer
// If the organizer is the defaultCalendar, then the booking is editable
// Otherwise, it's not editable (created from Google Calendar)
val isEditable = organizer == defaultCalendar
return Booking(
id = event.id,
owner = owner,
......@@ -352,7 +353,8 @@ class GoogleCalendarProvider(
beginBooking = Instant.ofEpochMilli(event.start.dateTime.value),
endBooking = Instant.ofEpochMilli(event.end.dateTime.value),
recurrence = RecurrenceRuleConverter.fromGoogleRecurrenceRule(event.recurrence),
recurringBookingId = recurringBookingIdStr
recurringBookingId = recurringBookingIdStr,
isEditable = isEditable
)
}
......
......@@ -23,5 +23,6 @@ data class Booking(
val beginBooking: Instant,
val endBooking: Instant,
val recurrence: RecurrenceModel? = null,
val recurringBookingId: String? = null // ID of the recurring booking this booking belongs to
val recurringBookingId: String? = null, // ID of the recurring booking this booking belongs to
val isEditable: Boolean = true, // Flag indicating if booking can be edited/deleted from tablet client
)
......@@ -41,7 +41,10 @@ data class BookingDto(
val recurrence: RecurrenceDto? = null,
@Schema(description = "ID of the recurring booking this booking belongs to")
val recurringBookingId: String? = null
val recurringBookingId: String? = null,
@Schema(description = "Flag indicating if booking can be edited/deleted from tablet client", example = "true")
val isEditable: Boolean = true
) {
companion object {
/**
......@@ -56,7 +59,8 @@ data class BookingDto(
beginBooking = booking.beginBooking.toEpochMilli(),
endBooking = booking.endBooking.toEpochMilli(),
recurrence = booking.recurrence?.let { RecurrenceDto.fromDomain(it) },
recurringBookingId = booking.recurringBookingId
recurringBookingId = booking.recurringBookingId,
isEditable = booking.isEditable
)
}
}
......
......@@ -14,6 +14,7 @@ import kotlinx.serialization.Serializable
* @property endBooking End time of the booking (Unix timestamp)
* @property recurrence Recurrence pattern for recurring bookings
* @property recurringBookingId ID of the recurring booking series this booking belongs to
* @property isEditable Flag indicating if the booking can be edited or deleted from tablet client
*/
@Serializable
data class BookingResponseDTO(
......@@ -24,5 +25,6 @@ data class BookingResponseDTO(
val beginBooking: Long,
val endBooking: Long,
val recurrence: RecurrenceDTO? = null,
val recurringBookingId: String? = null
)
\ Нет новой строки в конце файла
val recurringBookingId: String? = null,
val isEditable: Boolean = true
)
......@@ -19,6 +19,7 @@ class EventInfoMapper {
finishTime = Instant.fromEpochMilliseconds(dto.endBooking).asLocalDateTime,
organizer = dto.owner?.toOrganizer() ?: Organizer.default,
isLoading = false,
isEditable = dto.isEditable,
)
fun mapToRequest(eventInfo: EventInfo, roomInfo: RoomInfo): BookingRequestDTO = BookingRequestDTO(
......@@ -28,4 +29,4 @@ class EventInfoMapper {
participantEmails = listOfNotNull(eventInfo.organizer.email),
workspaceId = roomInfo.id
)
}
\ Нет новой строки в конце файла
}
......@@ -14,6 +14,7 @@ data class EventInfo(
val organizer: Organizer,
val id: String,
val isLoading: Boolean,
val isEditable: Boolean = true,
) {
init {
// Validate that start time is before finish time
......
......@@ -16,6 +16,7 @@ import androidx.compose.ui.unit.dp
fun AlertButton(
modifier: Modifier = Modifier,
onClick: () -> Unit,
enabled: Boolean = true,
content: @Composable RowScope.() -> Unit
) {
Button(
......@@ -26,8 +27,9 @@ fun AlertButton(
color = MaterialTheme.colorScheme.onPrimary
),
colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent),
onClick = { onClick() }
onClick = { onClick() },
enabled = enabled
) {
content()
}
}
\ Нет новой строки в конце файла
}
......@@ -119,7 +119,8 @@ fun BookingEditor(
start = state.event.startTime.format(timeFormatter),
finish = state.event.finishTime.format(timeFormatter),
room = component.roomName,
isTimeInPastError = state.isTimeInPastError
isTimeInPastError = state.isTimeInPastError,
isEditable = state.event.isEditable
)
}
}
......@@ -161,7 +162,8 @@ private fun BookingEditor(
start: String,
finish: String,
room: String,
isTimeInPastError: Boolean
isTimeInPastError: Boolean,
isEditable: Boolean = true
) {
val snackbarHostState = remember { SnackbarHostState() }
val timeInPastErrorMessage = stringResource(Res.string.is_time_in_past_error)
......@@ -247,7 +249,7 @@ private fun BookingEditor(
SuccessButton(
modifier = Modifier.fillMaxWidth().height(60.dp),
onClick = onUpdateEvent,
enable = enableUpdateButton && !isUpdateLoad
enable = enableUpdateButton && !isUpdateLoad && isEditable
) {
when {
isUpdateLoad -> Loader()
......@@ -264,7 +266,8 @@ private fun BookingEditor(
Spacer(modifier = Modifier.height(10.dp))
AlertButton(
modifier = Modifier.fillMaxWidth().height(60.dp),
onClick = onDeleteEvent
onClick = onDeleteEvent,
enabled = isEditable
) {
when {
isDeleteLoad -> Loader()
......
......@@ -74,23 +74,25 @@ fun BusyRoomInfoComponent(
color = roomInfoColor
)
Spacer(modifier = Modifier.height(10.dp))
Button(
modifier = Modifier
.clip(shape = RoundedCornerShape(40.dp))
.height(45.dp)
.background(color = backgroundColor)
.border(
width = 3.dp,
color = roomInfoColor,
shape = RoundedCornerShape(40.dp),
if (event.isEditable) {
Button(
modifier = Modifier
.clip(shape = RoundedCornerShape(40.dp))
.height(45.dp)
.background(color = backgroundColor)
.border(
width = 3.dp,
color = roomInfoColor,
shape = RoundedCornerShape(40.dp),
),
colors = ButtonDefaults.buttonColors(
containerColor = colorButton
),
colors = ButtonDefaults.buttonColors(
containerColor = colorButton
),
interactionSource = interactionSource,
onClick = onButtonClick
) {
Text(text = stringResource(Res.string.stop_meeting_button), color = colorTextButton)
interactionSource = interactionSource,
onClick = onButtonClick
) {
Text(text = stringResource(Res.string.stop_meeting_button), color = colorTextButton)
}
}
}
}
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать