✨ 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
|
return storage
|
||||||
|
|
||||||
|
|
||||||
async def handle_import_from_excel(data: BinaryIO, user: User):
|
def handle_import_from_excel(data: BinaryIO, user: User) -> Quiz:
|
||||||
try:
|
try:
|
||||||
wb = load_workbook(filename=data)
|
wb = load_workbook(filename=data)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise HTTPException(status_code=400, detail="File not in excel format")
|
raise HTTPException(status_code=400, detail="File not in excel format")
|
||||||
print(wb)
|
|
||||||
ws = wb.active
|
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)):
|
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:
|
if row[0] is None:
|
||||||
continue
|
continue
|
||||||
@@ -144,8 +153,10 @@ async def handle_import_from_excel(data: BinaryIO, user: User):
|
|||||||
answers_list: list[ABCDQuizAnswer] = []
|
answers_list: list[ABCDQuizAnswer] = []
|
||||||
for a, answer in enumerate(answers):
|
for a, answer in enumerate(answers):
|
||||||
answers_list.append(ABCDQuizAnswer(answer=answer, right=str(a + 1) in correct_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(
|
quiz = Quiz(
|
||||||
|
title=title,
|
||||||
|
description=description,
|
||||||
id=uuid.uuid4(),
|
id=uuid.uuid4(),
|
||||||
created_at=datetime.now(),
|
created_at=datetime.now(),
|
||||||
updated_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")
|
@router.post("/excel-import")
|
||||||
async def import_from_excel(data: UploadFile = File(), user: User = Depends(get_current_user)):
|
async def import_from_excel(file: UploadFile = File(), user: User = Depends(get_current_user)) -> Quiz:
|
||||||
await handle_import_from_excel(data.file, user)
|
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/...",
|
"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!.",
|
"side_import_kahoot": "On this side you can import quizzes, which live on Kahoot!.",
|
||||||
"classquiz_quiz": "A ClassQuiz-Quiz",
|
"classquiz_quiz": "A ClassQuiz-Quiz",
|
||||||
"upload_file_ending": "Upload the file ending in .cqa",
|
"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": "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": {
|
"admin_page": {
|
||||||
"already_registered_as_admin": "There is already an admin registered for this game.",
|
"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();
|
const { t } = getLocalization();
|
||||||
let url_input = '';
|
let url_input = '';
|
||||||
let file_input;
|
let file_input: File[];
|
||||||
|
|
||||||
let url_valid = false;
|
let url_valid = false;
|
||||||
let kahoot_regex = /^https:\/\/create\.kahoot\.it\/details\/([a-zA-Z-\d]{36})\/?$/;
|
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;
|
is_loading = true;
|
||||||
const formdata = new FormData();
|
const formdata = new FormData();
|
||||||
formdata.append('file', file_input[0]);
|
formdata.append('file', file_input[0]);
|
||||||
const res = await fetch('/api/v1/eximport/', {
|
let res;
|
||||||
method: 'POST',
|
if (file_input[0].name.includes('.xlsx')) {
|
||||||
body: formdata
|
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) {
|
if (res.status === 200) {
|
||||||
window.location.href = '/dashboard';
|
window.location.href = '/dashboard';
|
||||||
} else {
|
} else {
|
||||||
@@ -199,7 +212,7 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
bind:files={file_input}
|
bind:files={file_input}
|
||||||
name="file"
|
name="file"
|
||||||
type="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="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-red-700={!file_input}
|
||||||
class:ring-green-600={file_input}
|
class:ring-green-600={file_input}
|
||||||
@@ -208,7 +221,15 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
</div>
|
</div>
|
||||||
<p class="mt-2">
|
<p class="mt-2">
|
||||||
{$t('import_page.this_side_classquiz')}
|
{$t('import_page.this_side_classquiz')}
|
||||||
|
<br />
|
||||||
|
{$t('import_page.this_side_classquiz_excel')}
|
||||||
</p>
|
</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>
|
||||||
|
|
||||||
<div class="flex items-center justify-center mt-auto">
|
<div class="flex items-center justify-center mt-auto">
|
||||||
@@ -251,7 +272,7 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
|
|
||||||
<a
|
<a
|
||||||
href="/docs/import-from-kahoot"
|
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
|
>{$t('import_page.visit_docs')}</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user