✨ Finished Excel import
This commit is contained in:
@@ -111,14 +111,23 @@ async def generate_spreadsheet(quiz_results: dict, quiz: Quiz, player_fields: di
|
||||
return storage
|
||||
|
||||
|
||||
async def handle_import_from_excel(data: BinaryIO, user: User):
|
||||
def handle_import_from_excel(data: BinaryIO, user: User) -> Quiz:
|
||||
try:
|
||||
wb = load_workbook(filename=data)
|
||||
except KeyError:
|
||||
raise HTTPException(status_code=400, detail="File not in excel format")
|
||||
print(wb)
|
||||
ws = wb.active
|
||||
questions: list[QuizQuestion] = []
|
||||
questions: list[dict] = []
|
||||
title = ws["C5"].value
|
||||
description = ws["C6"].value
|
||||
if title is None:
|
||||
raise HTTPException(status_code=400, detail="Title missing")
|
||||
if description is None:
|
||||
raise HTTPException(status_code=400, detail="Description missing")
|
||||
if not 3 <= len(description) <= 500:
|
||||
raise HTTPException(status_code=400, detail="Description doesn't have the correct length")
|
||||
if not 3 <= len(title) <= 500:
|
||||
raise HTTPException(status_code=400, detail="Title doesn't have the correct length")
|
||||
for i, row in enumerate(ws.iter_rows(min_row=14, min_col=2, max_row=100, max_col=8, values_only=True)):
|
||||
if row[0] is None:
|
||||
continue
|
||||
@@ -144,8 +153,10 @@ async def handle_import_from_excel(data: BinaryIO, user: User):
|
||||
answers_list: list[ABCDQuizAnswer] = []
|
||||
for a, answer in enumerate(answers):
|
||||
answers_list.append(ABCDQuizAnswer(answer=answer, right=str(a + 1) in correct_answers))
|
||||
questions.append(QuizQuestion(question=question, answers=answers_list, time=str(time)))
|
||||
questions.append(QuizQuestion(question=question, answers=answers_list, time=str(time)).dict())
|
||||
quiz = Quiz(
|
||||
title=title,
|
||||
description=description,
|
||||
id=uuid.uuid4(),
|
||||
created_at=datetime.now(),
|
||||
updated_at=datetime.now(),
|
||||
|
||||
@@ -249,5 +249,6 @@ async def export_quiz_answers(export_token: str, game_pin: str):
|
||||
|
||||
|
||||
@router.post("/excel-import")
|
||||
async def import_from_excel(data: UploadFile = File(), user: User = Depends(get_current_user)):
|
||||
await handle_import_from_excel(data.file, user)
|
||||
async def import_from_excel(file: UploadFile = File(), user: User = Depends(get_current_user)) -> Quiz:
|
||||
quiz = handle_import_from_excel(file.file, user)
|
||||
return Quiz.parse_obj((await quiz.save()).dict(exclude={"user_id": ...}))
|
||||
|
||||
@@ -226,8 +226,10 @@
|
||||
"url_should_look_like_this": "The URL should look like this: https://create.kahoot.it/details/...",
|
||||
"side_import_kahoot": "On this side you can import quizzes, which live on Kahoot!.",
|
||||
"classquiz_quiz": "A ClassQuiz-Quiz",
|
||||
"upload_file_ending": "Upload the file ending in .cqa",
|
||||
"this_side_classquiz": "On this side you can import quizzes, which were exported from ClassQuiz."
|
||||
"upload_file_ending": "Upload the file ending in .cqa or .xlsx",
|
||||
"this_side_classquiz": "On this side you can import quizzes, which were exported from ClassQuiz.",
|
||||
"this_side_classquiz_excel": "You can also upload excel files, if you've filled out the following template.",
|
||||
"download_template_here": "Download the template"
|
||||
},
|
||||
"admin_page": {
|
||||
"already_registered_as_admin": "There is already an admin registered for this game.",
|
||||
|
||||
@@ -14,7 +14,7 @@ SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
const { t } = getLocalization();
|
||||
let url_input = '';
|
||||
let file_input;
|
||||
let file_input: File[];
|
||||
|
||||
let url_valid = false;
|
||||
let kahoot_regex = /^https:\/\/create\.kahoot\.it\/details\/([a-zA-Z-\d]{36})\/?$/;
|
||||
@@ -61,10 +61,23 @@ SPDX-License-Identifier: MPL-2.0
|
||||
is_loading = true;
|
||||
const formdata = new FormData();
|
||||
formdata.append('file', file_input[0]);
|
||||
const res = await fetch('/api/v1/eximport/', {
|
||||
method: 'POST',
|
||||
body: formdata
|
||||
});
|
||||
let res;
|
||||
if (file_input[0].name.includes('.xlsx')) {
|
||||
res = await fetch('/api/v1/quiz/excel-import', {
|
||||
method: 'POST',
|
||||
body: formdata
|
||||
});
|
||||
} else if (file_input[0].name.includes('.cqa')) {
|
||||
res = await fetch('/api/v1/eximport/', {
|
||||
method: 'POST',
|
||||
body: formdata
|
||||
});
|
||||
} else {
|
||||
alert('Wrong file type');
|
||||
is_loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.status === 200) {
|
||||
window.location.href = '/dashboard';
|
||||
} else {
|
||||
@@ -199,7 +212,7 @@ SPDX-License-Identifier: MPL-2.0
|
||||
bind:files={file_input}
|
||||
name="file"
|
||||
type="file"
|
||||
accept=".cqa"
|
||||
accept=".cqa,.xlsx"
|
||||
class="w-full peer bg-transparent h-10 rounded-lg py-1.5 text-gray-700 dark:text-white placeholder-transparent ring-2 px-2 ring-gray-500 focus:ring-sky-600 focus:outline-none focus:border-rose-600"
|
||||
class:ring-red-700={!file_input}
|
||||
class:ring-green-600={file_input}
|
||||
@@ -208,7 +221,15 @@ SPDX-License-Identifier: MPL-2.0
|
||||
</div>
|
||||
<p class="mt-2">
|
||||
{$t('import_page.this_side_classquiz')}
|
||||
<br />
|
||||
{$t('import_page.this_side_classquiz_excel')}
|
||||
</p>
|
||||
<a
|
||||
class="text-sm underline font-bold text-blue-500 dark:text-blue-400"
|
||||
download
|
||||
href="https://ncs3.classquiz.de/blog/classquiz/ClassQuizImportTemplate.xlsx"
|
||||
>{$t('import_page.download_template_here')}</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-center mt-auto">
|
||||
@@ -251,7 +272,7 @@ SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
<a
|
||||
href="/docs/import-from-kahoot"
|
||||
class="mx-2 text-sm font-bold text-blue-500 dark:text-blue-400 hover:underline"
|
||||
class="mx-2 text-sm font-bold text-blue-500 dark:text-blue-400 hover:underline transition-all"
|
||||
>{$t('import_page.visit_docs')}</a
|
||||
>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user