Compare commits

...

9 Commits

Author SHA1 Message Date
Sebastian Krupinski 4a4c1c3bc1
Merge c8626fb8c3 into 4711c64baa 2024-04-25 11:05:18 -04:00
Anna 4711c64baa
Merge pull request #5953 from nextcloud/fix/cleanup-appointments
fix(appointments): simplify booking response
2024-04-25 17:03:36 +02:00
SebastianKrupinski c8626fb8c3 fix: modified unit test to include arguments
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
2024-04-25 10:51:19 -04:00
Anna e2554308c7
Merge pull request #5952 from nextcloud/chore/adjust-renovate-tags
chore: adjust renovate tags and base branches
2024-04-25 14:13:39 +02:00
Anna Larch dad5191d6f chore: adjust renovate tags and base branches
Signed-off-by: Anna Larch <anna@nextcloud.com>
2024-04-25 14:09:15 +02:00
Nextcloud bot 6c930f2be0
Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-04-25 00:30:17 +00:00
SebastianKrupinski 4f3ed4a1a0 dev: updated unit tests and added new test for different time zones
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
2024-04-20 14:17:17 -04:00
Anna Larch 3acd93027c fix(appointments): simplify booking response
Signed-off-by: Anna Larch <anna@nextcloud.com>
2024-04-19 18:21:57 +02:00
SebastianKrupinski 01e7e2d68a fix: send requestee and requester correct date and time when timezones differ #5198
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
2024-04-16 14:12:29 -04:00
7 changed files with 216 additions and 14 deletions

View File

@ -55,6 +55,10 @@ OC.L10N.register(
"An error occurred, unable to change visibility of the calendar." : "Prodúxose un error, nun ye posible camudar la visibilidá del calendariu.",
"_Unsharing the calendar in {countdown} second_::_Unsharing the calendar in {countdown} seconds_" : ["Va dexar de compartise'l calendariu en {countdown} segundu","Va dexar de compartise'l calendariu en {countdown} segundos"],
"_Deleting the calendar in {countdown} second_::_Deleting the calendar in {countdown} seconds_" : ["Va desaniciase'l calendariu en {countdown} segundu","Va desaniciase'l calendariu en {countdown} segundos"],
"New calendar" : "Calendariu nuevu",
"Name for new calendar" : "Nome del calendariu nuevu",
"Creating calendar …" : "Creando'l calendariu…",
"Creating subscription …" : "Creando la soscripción…",
"An error occurred, unable to create the calendar." : "Prodúxose un error, nun ye posible crear el calendariu.",
"Copy subscription link" : "Copiar l'enllaz de soscripción",
"Copying link …" : "Copiando l'enllaz …",
@ -84,12 +88,17 @@ OC.L10N.register(
"Copy public link" : "Copiar l'enllaz públicu",
"Send link to calendar via email" : "Unviar l'enllaz del calendariu per corréu electrónicu",
"Enter one address" : "Introduz una direción",
"Sending email …" : "Unviando'l mensaxe…",
"Copy embedding code" : "Copiar el códigu pa empotrar",
"Copying code …" : "Copiando'l códigu …",
"Copied code" : "Copióse'l códigu",
"Could not copy code" : "Nun se pudo copiar el códigu",
"Delete share link" : "Desaniciar esti enllaz d'usu compartíu",
"Deleting share link …" : "Desaniciando l'enllaz d'usu compartíu…",
"An error occurred, unable to publish calendar." : "Prodúxose un error, nun ye posible espublizar el calendariu.",
"An error occurred, unable to send email." : "Prodúxose un error, nun ye posible unviar el mensaxe.",
"Embed code copied to clipboard." : "El códigu incrustáu copióse nel cartafueyu.",
"Embed code could not be copied to clipboard." : "El códigu incrustáu nun se pudo copiar nel cartafueyu.",
"Unshare with {displayName}" : "Dexar de compartir con {displayName}",
"An error occurred while unsharing the calendar." : "Prodúxose un error mentanto se dexaba de compartir el calendariu.",
"An error occurred, unable to change the permission of the share." : "Prodúxose un error, nun ye posible camudar el permisu del elementu compartíu.",
@ -105,7 +114,10 @@ OC.L10N.register(
"Cancel" : "Encaboxar",
"Invalid location selected" : "Seleicionóse una llocalización inválida",
"Automatic" : "Automáticu",
"or" : "o",
"Navigation" : "Navegación",
"Previous period" : "Periodu anterior",
"Next period" : "Periodu siguiente",
"Views" : "Vistes",
"Day view" : "Vista de díes",
"Week view" : "Vista de selmanes",
@ -191,18 +203,29 @@ OC.L10N.register(
"Accept" : "Aceptar",
"Decline" : "Refugar",
"Tentative" : "Provisional",
"The invitation has been accepted successfully." : "La invitación aceptóse correutamente.",
"Failed to accept the invitation." : "Nun se pue aceptar la invitación",
"The invitation has been declined successfully." : "La invitación refugóse correutamente.",
"Failed to decline the invitation." : "Nun se pue refugar la invitación",
"Your participation has been marked as tentative." : "La to participación marcóse como provisional.",
"Failed to set the participation status to tentative." : "Nun se pudo afitar l'estáu de la participación a provisional",
"Attendees" : "Asistentes",
"No attendees yet" : "Nun hai nengún asistente",
"You do not own this calendar, so you cannot add attendees to this event" : "Esti calendariu nun te pertenez, polo que nun pues amestar asistentes a esti eventu",
"Error creating Talk room" : "Hebo un error al crear la sala de Talk",
"_%n more guest_::_%n more guests_" : ["%n convidáu más","%n convidaos más"],
"Remove group" : "Quitar el grupu",
"_%n member_::_%n members_" : ["%n miembru","%n miembros"],
"No match found" : "Nun s'atopó nenguna coincidencia",
"Remove color" : "Quitar el color",
"Event title" : "Títulu del eventu",
"All day" : "Tol día",
"Repeat" : "Repitir",
"never" : "enxamás",
"first" : "primer",
"third" : "tercer",
"fourth" : "cuartu",
"fifth" : "quintu",
"_month_::_months_" : ["mes","meses"],
"_year_::_years_" : ["añu","años"],
"Suggestions" : "Suxerencies",
@ -211,6 +234,7 @@ OC.L10N.register(
"_{seatingCapacity} seat_::_{seatingCapacity} seats_" : ["{seatingCapacity} asientu","{seatingCapacity} asientos"],
"Projector" : "Proyeutor",
"Whiteboard" : "Pizarra",
"More details" : "Mas detalles",
"Pick a date" : "Escueyi una data",
"Please enter a valid date" : "Introduz una data válida",
"Global" : "Global",

View File

@ -53,6 +53,10 @@
"An error occurred, unable to change visibility of the calendar." : "Prodúxose un error, nun ye posible camudar la visibilidá del calendariu.",
"_Unsharing the calendar in {countdown} second_::_Unsharing the calendar in {countdown} seconds_" : ["Va dexar de compartise'l calendariu en {countdown} segundu","Va dexar de compartise'l calendariu en {countdown} segundos"],
"_Deleting the calendar in {countdown} second_::_Deleting the calendar in {countdown} seconds_" : ["Va desaniciase'l calendariu en {countdown} segundu","Va desaniciase'l calendariu en {countdown} segundos"],
"New calendar" : "Calendariu nuevu",
"Name for new calendar" : "Nome del calendariu nuevu",
"Creating calendar …" : "Creando'l calendariu…",
"Creating subscription …" : "Creando la soscripción…",
"An error occurred, unable to create the calendar." : "Prodúxose un error, nun ye posible crear el calendariu.",
"Copy subscription link" : "Copiar l'enllaz de soscripción",
"Copying link …" : "Copiando l'enllaz …",
@ -82,12 +86,17 @@
"Copy public link" : "Copiar l'enllaz públicu",
"Send link to calendar via email" : "Unviar l'enllaz del calendariu per corréu electrónicu",
"Enter one address" : "Introduz una direción",
"Sending email …" : "Unviando'l mensaxe…",
"Copy embedding code" : "Copiar el códigu pa empotrar",
"Copying code …" : "Copiando'l códigu …",
"Copied code" : "Copióse'l códigu",
"Could not copy code" : "Nun se pudo copiar el códigu",
"Delete share link" : "Desaniciar esti enllaz d'usu compartíu",
"Deleting share link …" : "Desaniciando l'enllaz d'usu compartíu…",
"An error occurred, unable to publish calendar." : "Prodúxose un error, nun ye posible espublizar el calendariu.",
"An error occurred, unable to send email." : "Prodúxose un error, nun ye posible unviar el mensaxe.",
"Embed code copied to clipboard." : "El códigu incrustáu copióse nel cartafueyu.",
"Embed code could not be copied to clipboard." : "El códigu incrustáu nun se pudo copiar nel cartafueyu.",
"Unshare with {displayName}" : "Dexar de compartir con {displayName}",
"An error occurred while unsharing the calendar." : "Prodúxose un error mentanto se dexaba de compartir el calendariu.",
"An error occurred, unable to change the permission of the share." : "Prodúxose un error, nun ye posible camudar el permisu del elementu compartíu.",
@ -103,7 +112,10 @@
"Cancel" : "Encaboxar",
"Invalid location selected" : "Seleicionóse una llocalización inválida",
"Automatic" : "Automáticu",
"or" : "o",
"Navigation" : "Navegación",
"Previous period" : "Periodu anterior",
"Next period" : "Periodu siguiente",
"Views" : "Vistes",
"Day view" : "Vista de díes",
"Week view" : "Vista de selmanes",
@ -189,18 +201,29 @@
"Accept" : "Aceptar",
"Decline" : "Refugar",
"Tentative" : "Provisional",
"The invitation has been accepted successfully." : "La invitación aceptóse correutamente.",
"Failed to accept the invitation." : "Nun se pue aceptar la invitación",
"The invitation has been declined successfully." : "La invitación refugóse correutamente.",
"Failed to decline the invitation." : "Nun se pue refugar la invitación",
"Your participation has been marked as tentative." : "La to participación marcóse como provisional.",
"Failed to set the participation status to tentative." : "Nun se pudo afitar l'estáu de la participación a provisional",
"Attendees" : "Asistentes",
"No attendees yet" : "Nun hai nengún asistente",
"You do not own this calendar, so you cannot add attendees to this event" : "Esti calendariu nun te pertenez, polo que nun pues amestar asistentes a esti eventu",
"Error creating Talk room" : "Hebo un error al crear la sala de Talk",
"_%n more guest_::_%n more guests_" : ["%n convidáu más","%n convidaos más"],
"Remove group" : "Quitar el grupu",
"_%n member_::_%n members_" : ["%n miembru","%n miembros"],
"No match found" : "Nun s'atopó nenguna coincidencia",
"Remove color" : "Quitar el color",
"Event title" : "Títulu del eventu",
"All day" : "Tol día",
"Repeat" : "Repitir",
"never" : "enxamás",
"first" : "primer",
"third" : "tercer",
"fourth" : "cuartu",
"fifth" : "quintu",
"_month_::_months_" : ["mes","meses"],
"_year_::_years_" : ["añu","años"],
"Suggestions" : "Suxerencies",
@ -209,6 +232,7 @@
"_{seatingCapacity} seat_::_{seatingCapacity} seats_" : ["{seatingCapacity} asientu","{seatingCapacity} asientos"],
"Projector" : "Proyeutor",
"Whiteboard" : "Pizarra",
"More details" : "Mas detalles",
"Pick a date" : "Escueyi una data",
"Please enter a valid date" : "Introduz una data válida",
"Global" : "Global",

View File

@ -214,7 +214,7 @@ class BookingController extends Controller {
);
}
return JsonResponse::success($booking);
return JsonResponse::success();
}
/**

View File

@ -189,6 +189,10 @@ class AppointmentConfig extends Entity implements JsonSerializable {
return $this;
}
public function getAvailabilityAsArray(): array {
return json_decode($this->getAvailability(), true);
}
#[ReturnTypeWillChange]
public function jsonSerialize() {
return [

View File

@ -130,7 +130,7 @@ class MailService {
}
// Create Booking overview
$this->addBulletList($template, $this->l10n, $booking, $config);
$this->addBulletList($template, $this->l10n, $booking, $config, false);
$bodyText = $this->l10n->t('This confirmation link expires in %s hours.', [(BookingService::EXPIRY / 3600)]);
$template->addBodyText($bodyText);
@ -200,7 +200,7 @@ class MailService {
}
// Create Booking overview
$this->addBulletList($template, $this->l10n, $booking, $config);
$this->addBulletList($template, $this->l10n, $booking, $config, false);
$bodyText = $this->l10n->t('If you wish to cancel the appointment after all, please contact your organizer by replying to this email or by visiting their profile page.');
$template->addBodyText($bodyText);
@ -230,15 +230,21 @@ class MailService {
private function addBulletList(IEMailTemplate $template,
IL10N $l10n,
Booking $booking,
AppointmentConfig $config):void {
AppointmentConfig $config,
bool $recipient):void {
$template->addBodyListItem($booking->getDisplayName(), $l10n->t('Appointment for:'));
// determain timezone depending on who is getting the message (Requestee/Requester)
$tzid = ($recipient) ? $config->getAvailabilityAsArray()['timezoneId'] : $booking->getTimezone();
$dtstart = new \DateTime("now", new \DateTimeZone($booking->getTimezone())); // generate DateTime with booking time zone
$dtstart->setTimestamp($booking->getStart()); // set booking time stamp
$l = $this->lFactory->findGenericLanguage();
$relativeDateTime = $this->dateFormatter->formatDateTimeRelativeDay(
$booking->getStart(),
$dtstart,
'long',
'short',
new \DateTimeZone($booking->getTimezone()),
new \DateTimeZone($tzid),
$this->lFactory->get('calendar', $l)
);
@ -309,7 +315,7 @@ class MailService {
}
// Create Booking overview
$this->addBulletList($template, $this->l10n, $booking, $config);
$this->addBulletList($template, $this->l10n, $booking, $config, true);
$template->addFooter();
$attachment = $this->mailer->createAttachment($calendar, 'appointment.ics', 'text/calendar');
@ -333,11 +339,16 @@ class MailService {
}
public function sendOrganizerBookingInformationNotification(Booking $booking, AppointmentConfig $config) {
$tzid = $config->getAvailabilityAsArray()['timezoneId']; // extract time zone from appointment configuration
$dtstart = new \DateTime("now", new \DateTimeZone($booking->getTimezone())); // generate DateTime with booking time zone
$dtstart->setTimestamp($booking->getStart()); // set booking time stamp
$relativeDateTime = $this->dateFormatter->formatDateTimeRelativeDay(
$booking->getStart(),
$dtstart,
'long',
'short',
new \DateTimeZone($booking->getTimezone()),
new \DateTimeZone($tzid),
$this->lFactory->get('calendar')
);

View File

@ -13,7 +13,7 @@
],
"labels": [
"dependencies",
"3 - to review"
"3. to review"
],
"commitMessageAction": "Bump",
"commitMessageTopic": "{{depName}}",
@ -23,8 +23,7 @@
"ignoreUnstable": false,
"baseBranches": [
"main",
"stable4.4",
"stable4.3"
"stable4.7"
],
"enabledManagers": [
"composer",
@ -71,7 +70,7 @@
"platformAutomerge": true,
"labels": [
"dependencies",
"4 - to release"
"4. to release"
],
"reviewers": []
},
@ -81,7 +80,7 @@
"automerge": false,
"labels": [
"dependencies",
"3 - to review"
"3. to review"
],
"reviewers": [
"GretaD",

View File

@ -346,6 +346,20 @@ class MailServiceTest extends TestCase {
$config = new AppointmentConfig();
$config->setUserId('test');
$config->setLocation('Test');
$config->setAvailabilityAsArray(
[
"timezoneId" => "Europe/Berlin",
"slots" => [
"MO" => [["start" => 1713153660, "end" => 1713239940]],
"TU" => [["start" => 1713153660, "end" => 1713239940]],
"WE" => [["start" => 1713153660, "end" => 1713239940]],
"TH" => [["start" => 1713153660, "end" => 1713239940]],
"FR" => [["start" => 1713153660, "end" => 1713239940]],
"SA" => [["start" => 1713153660, "end" => 1713239940]],
"SU" => [["start" => 1713153660, "end" => 1713239940]]
]
]
);
$this->userManager->expects(self::once())
->method('get')
->willReturn($this->createConfiguredMock(IUser::class, [
@ -505,6 +519,20 @@ class MailServiceTest extends TestCase {
$config = new AppointmentConfig();
$config->setUserId('test');
$config->setLocation('Test');
$config->setAvailabilityAsArray(
[
"timezoneId" => "Europe/Berlin",
"slots" => [
"MO" => [["start" => 1713153660, "end" => 1713239940]],
"TU" => [["start" => 1713153660, "end" => 1713239940]],
"WE" => [["start" => 1713153660, "end" => 1713239940]],
"TH" => [["start" => 1713153660, "end" => 1713239940]],
"FR" => [["start" => 1713153660, "end" => 1713239940]],
"SA" => [["start" => 1713153660, "end" => 1713239940]],
"SU" => [["start" => 1713153660, "end" => 1713239940]]
]
]
);
$this->userManager->expects(self::once())
->method('get')
->willReturn($this->createConfiguredMock(IUser::class, [
@ -563,6 +591,90 @@ class MailServiceTest extends TestCase {
$this->mailService->sendOrganizerBookingInformationEmail($booking, $config, 'abc');
}
public function testSendOrganizerBookingInformationEmailDifferentTZ(): void {
$booking = new Booking();
$booking->setEmail('test@test.com');
$booking->setDisplayName('Test');
$booking->setStart(time());
$booking->setTimezone('America/Toronto');
$booking->setDescription('Test');
$config = new AppointmentConfig();
$config->setUserId('test');
$config->setLocation('Test');
$config->setAvailabilityAsArray(
[
"timezoneId" => "Europe/Berlin",
"slots" => [
"MO" => [["start" => 1713153660, "end" => 1713239940]],
"TU" => [["start" => 1713153660, "end" => 1713239940]],
"WE" => [["start" => 1713153660, "end" => 1713239940]],
"TH" => [["start" => 1713153660, "end" => 1713239940]],
"FR" => [["start" => 1713153660, "end" => 1713239940]],
"SA" => [["start" => 1713153660, "end" => 1713239940]],
"SU" => [["start" => 1713153660, "end" => 1713239940]]
]
]
);
$this->userManager->expects(self::once())
->method('get')
->willReturn($this->createConfiguredMock(IUser::class, [
'getEmailAddress' => 'test@test.com',
'getDisplayName' => 'Test Test'
]));
$mailMessage = $this->createMock(IMessage::class);
$this->mailer->expects(self::once())
->method('createMessage')
->willReturn($mailMessage);
$mailMessage->expects(self::once())
->method('setFrom')
->willReturn($mailMessage);
$mailMessage->expects(self::once())
->method('setTo')
->willReturn($mailMessage);
$mailMessage->expects(self::once())
->method('useTemplate')
->willReturn($mailMessage);
$emailTemplate = $this->createMock(IEMailTemplate::class);
$this->mailer->expects(self::once())
->method('createEmailTemplate')
->willReturn($emailTemplate);
$emailTemplate->expects(self::once())
->method('addHeader');
$emailTemplate->expects(self::once())
->method('setSubject');
$emailTemplate->expects(self::once())
->method('addHeading');
$emailTemplate->expects(self::exactly(5))
->method('addBodyListItem');
$emailTemplate->expects(self::once())
->method('addFooter');
$this->mailer->expects(self::once())
->method('createEmailTemplate');
$this->mailer->expects(self::once())
->method('createAttachment');
$this->l10n->expects(self::exactly(6))
->method('t');
$this->lFactory->expects(self::once())
->method('findGenericLanguage')
->willReturn('en');
$this->lFactory->expects(self::once())
->method('get');
$this->dateFormatter->expects(self::once())
->method('formatDateTimeRelativeDay')
->with(self::anything(), self::anything(), self::anything(), 'Europe/Berlin')
->willReturn('Test');
$this->mailer->expects(self::once())
->method('send')
->willReturn([]);
$this->logger->expects(self::never())
->method('warning');
$this->logger->expects(self::never())
->method('debug');
$this->mailService->sendOrganizerBookingInformationEmail($booking, $config, 'abc');
}
public function testSendOrganizerBookingInformationEmailFailed(): void {
$booking = new Booking();
$booking->setEmail('test@test.com');
@ -573,6 +685,20 @@ class MailServiceTest extends TestCase {
$config = new AppointmentConfig();
$config->setUserId('test');
$config->setLocation('Test');
$config->setAvailabilityAsArray(
[
"timezoneId" => "Europe/Berlin",
"slots" => [
"MO" => [["start" => 1713153660, "end" => 1713239940]],
"TU" => [["start" => 1713153660, "end" => 1713239940]],
"WE" => [["start" => 1713153660, "end" => 1713239940]],
"TH" => [["start" => 1713153660, "end" => 1713239940]],
"FR" => [["start" => 1713153660, "end" => 1713239940]],
"SA" => [["start" => 1713153660, "end" => 1713239940]],
"SU" => [["start" => 1713153660, "end" => 1713239940]]
]
]
);
$this->userManager->expects(self::once())
->method('get')
->willReturn($this->createConfiguredMock(IUser::class, [
@ -654,6 +780,20 @@ class MailServiceTest extends TestCase {
$config = new AppointmentConfig();
$config->setUserId('test');
$config->setLocation('Test');
$config->setAvailabilityAsArray(
[
"timezoneId" => "Europe/Berlin",
"slots" => [
"MO" => [["start" => 1713153660, "end" => 1713239940]],
"TU" => [["start" => 1713153660, "end" => 1713239940]],
"WE" => [["start" => 1713153660, "end" => 1713239940]],
"TH" => [["start" => 1713153660, "end" => 1713239940]],
"FR" => [["start" => 1713153660, "end" => 1713239940]],
"SA" => [["start" => 1713153660, "end" => 1713239940]],
"SU" => [["start" => 1713153660, "end" => 1713239940]]
]
]
);
$notification = $this->createMock(INotification::class);
$this->lFactory->expects(self::once())