From 078b3f259118b3437a4a73578ed1fe9c31ad8d3c Mon Sep 17 00:00:00 2001 From: DorraJaouad Date: Wed, 16 Oct 2024 10:50:05 +0200 Subject: [PATCH] feat(Call): allow moderators to download current attendance list Signed-off-by: DorraJaouad --- lib/Controller/CallController.php | 10 +++++++++- src/components/TopBar/TopBarMenu.vue | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/Controller/CallController.php b/lib/Controller/CallController.php index d1530793082..128e79c616c 100644 --- a/lib/Controller/CallController.php +++ b/lib/Controller/CallController.php @@ -127,6 +127,7 @@ public function getPeersForCall(): DataResponse { */ #[PublicPage] #[RequireModeratorParticipant] + #[Http\Attribute\NoCSRFRequired] public function downloadParticipantsForCall(string $format = 'csv'): DataDownloadResponse|Response { $timeout = $this->timeFactory->getTime() - Session::SESSION_TIMEOUT; $participants = $this->participantService->getParticipantsInCall($this->room, $timeout); @@ -158,7 +159,14 @@ public function downloadParticipantsForCall(string $format = 'csv'): DataDownloa fseek($output, 0); - return new DataDownloadResponse(stream_get_contents($output), 'participants.csv', 'text/csv'); + // Clean the room name + $cleanedRoomName = preg_replace('/[\/\\:*?"<>|\- ]+/', '-', $this->room->getName()); + // Limit to a reasonable length + $cleanedRoomName = substr($cleanedRoomName, 0, 100); + $date = $this->timeFactory->getDateTime()->format('Y-m-d'); + $fileName = $cleanedRoomName . ' ' . $date . '.csv'; + + return new DataDownloadResponse(stream_get_contents($output), $fileName, 'text/csv'); } /** diff --git a/src/components/TopBar/TopBarMenu.vue b/src/components/TopBar/TopBarMenu.vue index 18791370182..a5000e480b4 100644 --- a/src/components/TopBar/TopBarMenu.vue +++ b/src/components/TopBar/TopBarMenu.vue @@ -139,6 +139,14 @@ {{ t('spreed', 'Conversation settings') }} + + + {{ t('spreed', 'Download attendance list') }} + @@ -147,6 +155,7 @@ import Cog from 'vue-material-design-icons/Cog.vue' import DotsCircle from 'vue-material-design-icons/DotsCircle.vue' import DotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue' +import IconDownload from 'vue-material-design-icons/Download.vue' import File from 'vue-material-design-icons/File.vue' import Fullscreen from 'vue-material-design-icons/Fullscreen.vue' import FullscreenExit from 'vue-material-design-icons/FullscreenExit.vue' @@ -161,6 +170,7 @@ import GridView from 'vue-material-design-icons/ViewGrid.vue' import { showWarning } from '@nextcloud/dialogs' import { emit } from '@nextcloud/event-bus' import { t } from '@nextcloud/l10n' +import { generateOcsUrl } from '@nextcloud/router' import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' import NcActionLink from '@nextcloud/vue/dist/Components/NcActionLink.js' @@ -208,6 +218,7 @@ export default { FullscreenExit, GridView, HandBackLeft, + IconDownload, MicrophoneOff, PromotedView, RecordCircle, @@ -369,6 +380,10 @@ export default { showCallLayoutSwitch() { return !this.callViewStore.isEmptyCallView }, + + downloadCallParticipantsLink() { + return generateOcsUrl('apps/spreed/api/v4/call/{token}/download', { token: this.token }) + }, }, watch: {