From e04f2010d5a2cb51e845329c2309aedac1db677b Mon Sep 17 00:00:00 2001 From: Ahmad Altaher Alfayad <93749906+taheralfayad@users.noreply.github.com> Date: Thu, 18 Apr 2024 18:19:37 -0400 Subject: [PATCH] Allow UDOIT to accept modern filetypes (#900) * Allow UDOIT to accept modern filetypes * Add apiDelete function * Added spanish translation for filetype error * Minor spelling fix to spanish translation addition --------- Co-authored-by: Daniel Molares --- assets/js/Components/FilesModal.js | 46 ++++++++++++++++++++++++++++-- assets/js/Components/FilesPage.js | 2 +- src/Lms/Canvas/CanvasApi.php | 35 +++++++++++++++++++++-- src/Lms/Canvas/CanvasLms.php | 4 +-- src/Lms/D2l/D2lLms.php | 2 +- src/Lms/LmsInterface.php | 2 +- src/Services/LmsPostService.php | 2 +- translations/en.json | 1 + translations/es.json | 1 + 9 files changed, 85 insertions(+), 10 deletions(-) diff --git a/assets/js/Components/FilesModal.js b/assets/js/Components/FilesModal.js index 993e24afb..aa7e04ae5 100644 --- a/assets/js/Components/FilesModal.js +++ b/assets/js/Components/FilesModal.js @@ -36,6 +36,7 @@ class FilesModal extends React.Component { this.handleDropAccept = this.handleDropAccept.bind(this) this.handleDropReject = this.handleDropReject.bind(this) this.handleFilePost = this.handleFilePost.bind(this) + this.setAcceptType = this.setAcceptType.bind(this) } componentDidUpdate(prevProps, prevState) { @@ -59,6 +60,46 @@ class FilesModal extends React.Component { return -1; } + setAcceptType(file) { + let accept = [] + + switch(file.fileType) { + case "doc": + accept = ["doc", "docx"] + break + + case "ppt": + accept = ["ppt", "pptx"] + break + + case "xls": + accept = ["xls", "xlsx"] + break + + default: + accept = fileType + break + } + + let extension = file.fileName.slice(-4) + + switch(extension) { + case "xlsx": + accept = "xlsx" + break + + case "pptx": + accept = "pptx" + break + + case "docx": + accept = "docx" + break + } + + return accept + } + // Handler for the previous and next buttons on the modal // Will wrap around if the index goes out of bounds handleFileChange(newIndex) { @@ -80,7 +121,8 @@ class FilesModal extends React.Component { } render() { - const { activeFile } = this.props + let { activeFile } = this.props + activeFile.acceptType = this.setAcceptType(activeFile) let activeIndex = this.findActiveIndex() return ( @@ -121,7 +163,7 @@ class FilesModal extends React.Component { {this.props.t('label.replace')} {this.props.t('label.replace.desc')} apiGet($url); $file = $fileResponse->getContent(); @@ -114,13 +114,16 @@ public function apiFilePost(string $url, array $options, string $filepath): LmsR // TODO: handle failed call $endpointOptions = [ - 'name' => urldecode($file['filename']), + 'name' => $newFileName, 'parent_folder_id' => $file['folder_id'], + 'content_type' => $file['content-type'], ]; $endpointResponse = $this->apiPost($options['postUrl'], ['query' => $endpointOptions], true); $endpointContent = $endpointResponse->getContent(); + $this->apiDelete($url); + // TODO: handle failed call $formFields = $endpointContent['upload_params']; @@ -158,4 +161,32 @@ public function apiPut($url, $options) return $lmsResponse; } + public function apiDelete($url) { + $lmsResponse = new LmsResponse(); + + if (strpos($url, 'https://') === false) { + $pattern = '/\/files\/\d+/'; + + preg_match($pattern, $url, $matches); + + $url = "https://" . $this->baseUrl . "/api/v1/" . $matches[0]; + } + + $response = $this->httpClient->request('DELETE', $url); + + $lmsResponse->setResponse($response); + + $content = $lmsResponse->getContent(); + if (!empty($content['errors'])) { + // TODO: If error is invalid token, refresh API token and try again + + foreach ($content['errors'] as $error) { + $lmsResponse->setError($error['message']); + } + } + + return $lmsResponse; + + } + } diff --git a/src/Lms/Canvas/CanvasLms.php b/src/Lms/Canvas/CanvasLms.php index ec30a2fc9..28ca0dbeb 100644 --- a/src/Lms/Canvas/CanvasLms.php +++ b/src/Lms/Canvas/CanvasLms.php @@ -370,7 +370,7 @@ public function postContentItem(ContentItem $contentItem) return $canvasApi->apiPut($url, ['body' => $options]); } - public function postFileItem(FileItem $file) + public function postFileItem(FileItem $file, string $newFileName) { $user = $this->security->getUser(); $apiDomain = $this->getApiDomain($user); @@ -382,7 +382,7 @@ public function postFileItem(FileItem $file) 'postUrl' => "courses/{$file->getCourse()->getLmsCourseId()}/files" ]; - $fileResponse = $canvasApi->apiFilePost($url, $options, $filepath); + $fileResponse = $canvasApi->apiFilePost($url, $options, $filepath, $newFileName); $fileObj = $fileResponse->getContent(); if (isset($fileObj['id'])) { diff --git a/src/Lms/D2l/D2lLms.php b/src/Lms/D2l/D2lLms.php index 1b403781f..055ff5229 100644 --- a/src/Lms/D2l/D2lLms.php +++ b/src/Lms/D2l/D2lLms.php @@ -381,7 +381,7 @@ public function updateFileItem(Course $course, $file) $this->entityManager->flush(); } - public function postFileItem(FileItem $file) + public function postFileItem(FileItem $file, string $newFileName) { return true; } diff --git a/src/Lms/LmsInterface.php b/src/Lms/LmsInterface.php index c155114db..acc6823ed 100644 --- a/src/Lms/LmsInterface.php +++ b/src/Lms/LmsInterface.php @@ -17,7 +17,7 @@ public function updateCourseData(Course $course, User $user); public function updateFileItem(Course $course, $file); public function updateContentItem(ContentItem $contentItem); public function postContentItem(ContentItem $contentItem); - public function postFileItem(FileItem $file); + public function postFileItem(FileItem $file, string $newFileName); public function getOauthUri(Institution $institution, UserSession $session); public function getAccountData(User $user, $accountId); public function getCourseUrl(Course $course, User $user); diff --git a/src/Services/LmsPostService.php b/src/Services/LmsPostService.php index 4313d7db7..81fd0207b 100644 --- a/src/Services/LmsPostService.php +++ b/src/Services/LmsPostService.php @@ -76,7 +76,7 @@ public function saveFileToLms(FileItem $file, UploadedFile $uploadedFile, User $ return; } - return $lms->postFileItem($file); + return $lms->postFileItem($file, $uploadedFile->getClientOriginalName()); } public function replaceContent(Issue $issue, ContentItem $contentItem) diff --git a/translations/en.json b/translations/en.json index 91cff0119..fbc217350 100644 --- a/translations/en.json +++ b/translations/en.json @@ -131,6 +131,7 @@ "msg.new_content": "Course scan complete. New content has been added.", "msg.sync.started": "Course scan started.", "msg.sync.failed": "Course scan failed. Course is missing.", + "msg.file.replace.file_type": "File type not accepted. Please input a file with the correct filetype.", "msg.sync.completed": "Course scan completed.", "msg.sync.course_inactive": "Course scan failed. Course is inactive.", diff --git a/translations/es.json b/translations/es.json index 6e8b3ed84..38f4863cd 100644 --- a/translations/es.json +++ b/translations/es.json @@ -131,6 +131,7 @@ "msg.new_content": "Escaneo del curso completo. Se ha agregado nuevo contenido.", "msg.sync.started": "Se inició el escaneo del curso.", "msg.sync.failed": "Falló el escaneo del curso. Falta el curso.", + "msg.file.replace.file_type": "El tipo de archivo no es válido. Por favor aporte un archivo de tipo correcto.", "msg.sync.completed": "Escaneo del curso completado.", "msg.sync.course_inactive": "Falló el escaneo del curso. El curso está inactivo.",