Skip to content

Commit

Permalink
SAK-50690 Meetings add banner to register and add option to download …
Browse files Browse the repository at this point in the history
…assistance reports CSV (#13027)
  • Loading branch information
Aniii10 authored Dec 11, 2024
1 parent 02b2465 commit ca1e97b
Show file tree
Hide file tree
Showing 22 changed files with 768 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3666,6 +3666,11 @@
# DEFAULT: 2
# samigo.assessmentSortingColumn=9

# SAK-50690 Meetings: select message and option to show attendance reports
# Select whether to display the informational alert of the meetings tool.
# DEFAULT: false
# show.meeting.banner=true

#########################################
# SAMIGO SECURE DELIVERY (PROCTORING)
#########################################
Expand Down
65 changes: 65 additions & 0 deletions library/src/skins/default/src/sass/base/_extendables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,75 @@
margin-bottom: 0;
}
}
@mixin sakai-banner-meetings($bordercolor, $bgcolor, $color, $icon, $isInline: false) {
position: relative;
@if $isInline {
display: inline-block;
margin: 0;
padding: 0 $standard-space 0 calc(#{$standard-spacing} * 2 + 18px); // making room on either side of the icon plus the width of the icon;
} @else {
display: block;
clear: both;
margin: $standard-spacing 0;
padding: $standard-spacing $standard-spacing $standard-spacing calc(#{$standard-spacing} * 2 + 18px); // making room on either side of the icon plus the width of the icon;
}
border-left: calc( #{$standard-spacing} / 2) solid $bordercolor;
background-color: $bgcolor;
color: $color;

// display an icon indicating banner type on the left of the text
&:before {
content: '';
@extend .fa;
@extend .fa-fw; // fixed width icons
@extend #{$icon}; // icon passed in through mixin's parameter
top: calc(50% - 7px); // half the height of the icon
left: $standard-spacing;
margin-right: $standard-space; // space between icon and message text
color: $color;
}

// display a closing X on the right of the banner to indicate that the banner is dismissible
.dismiss {
@if $isInline == false {
position: absolute;
top: calc(50% - 10px); // vertically-align the icon with half its height
right: $standard-spacing; // space between icon and right edge of banner
} @else {
margin-left: $standard-space; // space between icon and end of message text
}
text-decoration: none;

span {
font-size: 0; // hide the accessible text
}

&:before {
content: '';
@extend .fa;
@extend .fa-fw; // fixed width icons
@extend .fa-close;
}
}

// any links in the banners should have the same text color contrast and be underlined
a[href] {
color: $color;
text-decoration: underline;
}

// remove end spacing from any paragraphs at the end of the banner
p:last-child {
margin-bottom: 0;
}
}

.sak-banner-info {
@include sakai-banner(var(--infoBanner-bordercolor), var(--infoBanner-bgcolor), var(--infoBanner-color), $infoBanner-icon, false);
}
.sak-banner-info-meetings {
@include sakai-banner-meetings(var(--infoBanner-bordercolor), var(--infoBanner-bgcolor), var(--infoBanner-color), $infoBanner-icon, false);
}
.sak-banner-info-inline {
@include sakai-banner(var(--infoBanner-bordercolor), var(--infoBanner-bgcolor), var(--infoBanner-color), $infoBanner-icon, true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public List<Meeting> getAllMeetingsFromSite(String siteId) {
return meetingRepository.getSiteMeetings(siteId);
}

public List<Meeting> getUserMeetings(String userId, String siteId, List <String> groupIds) {
public List<Meeting> getUserMeetings(String userId, String siteId, List<String> groupIds) {
return meetingRepository.getMeetings(userId, siteId, groupIds);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,23 @@
import java.time.Instant;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.List;
import java.util.Map;
import java.util.Collections;
import java.util.Collection;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.sakaiproject.component.api.ServerConfigurationService;
import org.sakaiproject.authz.api.Member;
import org.sakaiproject.authz.api.SecurityService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.meetings.api.MeetingService;
import org.sakaiproject.meetings.api.model.AttendeeType;
import org.sakaiproject.meetings.api.model.Meeting;
import org.sakaiproject.meetings.api.model.MeetingAttendee;
import org.sakaiproject.meetings.api.model.*;
import org.sakaiproject.meetings.controller.data.GroupData;
import org.sakaiproject.meetings.controller.data.MeetingData;
import org.sakaiproject.meetings.controller.data.NotificationType;
Expand All @@ -43,17 +44,17 @@
import org.sakaiproject.microsoft.api.MicrosoftCommonService;
import org.sakaiproject.microsoft.api.MicrosoftSynchronizationService;
import org.sakaiproject.microsoft.api.SakaiProxy;
import org.sakaiproject.microsoft.api.data.MeetingRecordingData;
import org.sakaiproject.microsoft.api.data.SakaiCalendarEvent;
import org.sakaiproject.microsoft.api.data.TeamsMeetingData;
import org.sakaiproject.microsoft.api.data.*;
import org.sakaiproject.microsoft.api.exceptions.MicrosoftCredentialsException;
import org.sakaiproject.site.api.Group;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.user.api.User;
import org.sakaiproject.util.ResourceLoader;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -79,7 +80,10 @@ public class MeetingsController {

/** Resource bundle using current language locale */
private static ResourceLoader rb = new ResourceLoader("Messages");


@Autowired
private ServerConfigurationService serverConfigurationService;

@Autowired
private MeetingService meetingService;

Expand All @@ -104,7 +108,21 @@ public class MeetingsController {
private static final String NOTIF_CONTENT = "notification.content";
private static final String SMTP_FROM = "[email protected]";
private static final String NO_REPLY = "no-reply@";

private static final String REPORT_FORMAT_CSV = "csv";
private static final String ATTENDANCE_REPORT_FILENAME = "attendance_report.csv";

/**
* Default meetings properties
* @return
*/
@GetMapping(value="/config", produces = MediaType.APPLICATION_JSON_VALUE)
public Map<String, Boolean> getConfig() {
boolean showMeetingBanner = serverConfigurationService.getBoolean( "show.meeting.banner", false);

return Map.of(
"showMeetingBanner", showMeetingBanner
);
}
/**
* Check if there's an user logged
* @return
Expand Down Expand Up @@ -593,6 +611,40 @@ public void deleteMeeting(@PathVariable String meetingId) throws MeetingsExcepti
throw new MeetingsException(e.getLocalizedMessage());
}
}

@GetMapping(value = "/meeting/{meetingId}/attendanceReport", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> getMeetingAttendanceReport(@PathVariable String meetingId, @RequestParam(required = false) String format) throws MeetingsException {
checkCurrentUserInMeeting(meetingId);
Meeting meeting = meetingService.getMeeting(meetingId);
String onlineMeetingId = meetingService.getMeetingProperty(meeting, ONLINE_MEETING_ID);
String organizerEmail = meetingService.getMeetingProperty(meeting, ORGANIZER_USER);
checkUpdatePermissions(meeting.getSiteId());
List<String> columnNames = Arrays.asList(
rb.getString("meeting.column_name"),
rb.getString("meeting.column_email"),
rb.getString("meeting.column_role"),
rb.getString("meeting.column_duration"),
rb.getString("meeting.entry_date"),
rb.getString("meeting.exit_date"),
rb.getString("meeting.interval_duration")
);

try {
List<AttendanceRecord> attendanceRecords = microsoftCommonService.getMeetingAttendanceReport(onlineMeetingId, organizerEmail);
if (REPORT_FORMAT_CSV.equalsIgnoreCase(format)) {
byte[] csvContent = microsoftCommonService.createAttendanceReportCsv(attendanceRecords, columnNames);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + ATTENDANCE_REPORT_FILENAME + "\"")
.contentType(MediaType.TEXT_PLAIN)
.body(csvContent);
} else {
return ResponseEntity.ok(attendanceRecords);
}
} catch (Exception e) {
log.error("Error when obtaining the attendance report", e);
throw new MeetingsException(e.getLocalizedMessage());
}
}

/**
* Get i18n bundle
Expand Down
9 changes: 9 additions & 0 deletions meetings/tool/src/main/resources/Messages.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
notification.subject=A new meeting \u0027{0}\u0027 has been published in the site \u0027{1}\u0027
notification.content=You have been invited to participate in the meeting <i>{0}</i>.

#Meetings
meeting.column_name=Name
meeting.column_email=Email
meeting.column_role=Role
meeting.column_duration=Duration (seconds)
meeting.entry_date=Entry Date
meeting.exit_date=Exit Date
meeting.interval_duration=Interval Duration (seconds)
11 changes: 10 additions & 1 deletion meetings/tool/src/main/resources/Messages_ca.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
notification.subject=S\u2019ha publicat una nova reuni\u00F3 \u0027{0}\u0027 a l\u2019espai {1}
notification.content=Ha sigut convidat a participar en la reuni\u00F3 <i>{0}</i>.
notification.content=Ha sigut convidat a participar en la reuni\u00F3 <i>{0}</i>.

#Meetings
meeting.column_name=Nom
meeting.column_email=Correu
meeting.column_role=Rol
meeting.column_duration=Duraci\u00F3 (segons)
meeting.entry_date=Data d\u2019entrada
meeting.exit_date=Data de sortida
meeting.interval_duration=Interval de Duraci\u00F3 (segons)
9 changes: 9 additions & 0 deletions meetings/tool/src/main/resources/Messages_es.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
notification.subject=Se ha publicado una nueva reuni\u00f3n '{0}' en el sitio {1}
notification.content=Ha sido invitado a participar en la reuni\u00f3n <i>{0}</i>.

#Meetings
meeting.column_name=Nombre
meeting.column_email=Correo
meeting.column_role=Rol
meeting.column_duration=Duraci\u00f3n (segundos)
meeting.entry_date=Fecha de entrada
meeting.exit_date=Fecha de salida
meeting.interval_duration=Intervalo de Duraci\u00f3n (segundos)
7 changes: 7 additions & 0 deletions meetings/tool/src/main/resources/card.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ status_text_unknown=unknown status
status_text_waiting=waiting for start
edit_action=Edit
delete_action=Delete
close_action= Close
attendance_report_action=Attendance report
download_report_excel= Download in csv
download_report_error_message= Support data has not been loaded correctly. Try it later.
loading_report_data=Loading data...
preview_report= Preview report
no_preview_report=No attendance records available.
get_link_action=Get Link
message_link_copied=Link copied to clipboard
check_recordings_action=Check recordings
Expand Down
9 changes: 8 additions & 1 deletion meetings/tool/src/main/resources/card_ca.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,16 @@ status_text_unknown=estat descononegut
status_text_waiting=esperant per a comen\u00E7ar
edit_action=Editar
delete_action=Eliminar
close_action= Tancar
attendance_report_action=Informes d\u2019assist\u00e8ncia
download_report_excel= Descarregar en csv
download_report_error_message=Les dades d\u2019assist\u00e8ncia no s\u2019han carregat correctament. Proveu-ho m\u00E9s tard.
loading_report_data=Carregant les dades...
preview_report= Previsualitzar els informes
no_preview_report=No hi ha registres d\u2019assist\u00e8ncia disponibles.
get_link_action=Obtindre Enlla\u00E7
message_link_copied=Enlla\u00E7 copiat al portapapers
check_recordings_action=Comprovar gravacions
availableParticipants=Participants disponibles:
availableParticipants=Participants disponibles:
and_x_more=i {} m\u00E9s.
join_action=Afegir-se a la reuni\u00F3
7 changes: 7 additions & 0 deletions meetings/tool/src/main/resources/card_es.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ status_text_unknown=estado desconocido
status_text_waiting=esperando para comenzar
edit_action=Editar
delete_action=Eliminar
close_action=Cerrar
attendance_report_action=Informes de asistencia
download_report_excel= Descargar en csv
download_report_error_message=Los datos de asistencia no se han cargado correctamente. Probarlo m\u00e1s tarde.
loading_report_data=Cargando los datos...
preview_report= Previsualizar los informes
no_preview_report=No hay registros de asistencia disponibles.
get_link_action=Obtener Enlace
message_link_copied=Enlace copiado al portapapeles
check_recordings_action=Comprobar grabaciones
Expand Down
6 changes: 6 additions & 0 deletions meetings/tool/src/main/resources/main.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ past=Past
search_results=Search results
search=Search for meetings
today=Today
meeting_alert=To have all the Teams functionalities, it is essential to use the Microsoft application.
meeting_login_application=Start session with the application.
meeting_not_application_installed=If you do not have the application installed, clicking on
meeting_link=it
meeting_download_by_link=will allow you to download it.
meeting_limited_funcionality=Alternatively, with limited functionality, you can use the web browser to access Teams.
7 changes: 6 additions & 1 deletion meetings/tool/src/main/resources/main_ca.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@ past=Anteriors
search_results=Resultats de cerca
search=Cerca de reunions
today=Hui

meeting_alert=Per disposar de totes les funcionalitats de Teams, \u00E9s imprescindible usar l\u2019aplicaci\u00F3 de Microsoft i validar\u2212se amb les credencials UdL.
meeting_login_application=Inicia sessi\u00F3 amb l\u2019aplicaci\u00F3.
meeting_not_application_installed=En cas de no tenir l\u2019aplicaci\u00F3 instal.lada, aquest
meeting_link=enlla\u00E7
meeting_download_by_link=et permetr\u00E0 descarregar\u2212te\u2212la.
meeting_limited_funcionality=Altrament, amb funcionalitats limitades, pots usar el navegador web per accedir al Teams.
6 changes: 6 additions & 0 deletions meetings/tool/src/main/resources/main_es.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ past=Anteriores
search_results=Resultados de b\u00fasqueda
search=B\u00fasqueda de reuniones
today=Hoy
meeting_alert=Para disponer de todas las funcionalidades de Teams, es imprescindible usar la aplicaci\u00F3n de Microsoft.
meeting_login_application=Inicia sessi\u00F3n con la aplicaci\u00F3n.
meeting_not_application_installed=En caso de no tener la aplicaci\u00F3n instalada, este
meeting_link=enlace
meeting_download_by_link=te permitir\u00E1 descarg\u00E1rtela.
meeting_limited_funcionality=Alternativamente, con una funcionalidad limitada, puede utilizar el navegador web para acceder a Teams.
Loading

0 comments on commit ca1e97b

Please sign in to comment.