mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
commit
600bb96603
34 changed files with 566 additions and 211 deletions
|
|
@ -22,6 +22,7 @@ import { Save } from "lucide-react";
|
||||||
import MathEquationBlock from "./Extensions/MathEquation/MathEquationBlock";
|
import MathEquationBlock from "./Extensions/MathEquation/MathEquationBlock";
|
||||||
import PDFBlockComponent from "./Extensions/PDF/PDFBlockComponent";
|
import PDFBlockComponent from "./Extensions/PDF/PDFBlockComponent";
|
||||||
import PDFBlock from "./Extensions/PDF/PDFBlock";
|
import PDFBlock from "./Extensions/PDF/PDFBlock";
|
||||||
|
import QuizBlock from "./Extensions/Quiz/QuizBlock";
|
||||||
|
|
||||||
interface Editor {
|
interface Editor {
|
||||||
content: string;
|
content: string;
|
||||||
|
|
@ -65,6 +66,10 @@ function Editor(props: Editor) {
|
||||||
editable: true,
|
editable: true,
|
||||||
lecture: props.lecture,
|
lecture: props.lecture,
|
||||||
}),
|
}),
|
||||||
|
QuizBlock.configure({
|
||||||
|
editable: true,
|
||||||
|
lecture: props.lecture,
|
||||||
|
}),
|
||||||
Youtube.configure({
|
Youtube.configure({
|
||||||
controls: true,
|
controls: true,
|
||||||
modestBranding: true,
|
modestBranding: true,
|
||||||
|
|
@ -114,7 +119,7 @@ function Editor(props: Editor) {
|
||||||
</EditorSaveButton>
|
</EditorSaveButton>
|
||||||
</EditorInfoWrapper>
|
</EditorInfoWrapper>
|
||||||
<EditorButtonsWrapper>
|
<EditorButtonsWrapper>
|
||||||
<ToolbarButtons editor={editor} />
|
<ToolbarButtons editor={editor} />
|
||||||
</EditorButtonsWrapper>
|
</EditorButtonsWrapper>
|
||||||
</EditorDocSection>
|
</EditorDocSection>
|
||||||
<EditorUsersSection>
|
<EditorUsersSection>
|
||||||
|
|
@ -279,8 +284,8 @@ export const EditorContentWrapper = styled.div`
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
|
padding-top: 20px;
|
||||||
|
|
||||||
padding-top: 1px;
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
outline-style: none !important;
|
outline-style: none !important;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ function ImageBlockComponent(props: any) {
|
||||||
{fileObject && (
|
{fileObject && (
|
||||||
<BlockImage>
|
<BlockImage>
|
||||||
<img
|
<img
|
||||||
src={`${getBackendUrl()}content/uploads/files/pictures/${props.extension.options.lecture.lecture_id}/${fileObject.file_id}.${
|
src={`${getBackendUrl()}content/uploads/files/images/${props.extension.options.lecture.lecture_id}/${fileObject.file_id}.${
|
||||||
fileObject.file_format
|
fileObject.file_format
|
||||||
}`}
|
}`}
|
||||||
alt=""
|
alt=""
|
||||||
|
|
|
||||||
35
front/components/Editor/Extensions/Quiz/QuizBlock.ts
Normal file
35
front/components/Editor/Extensions/Quiz/QuizBlock.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { mergeAttributes, Node } from "@tiptap/core";
|
||||||
|
import { ReactNodeViewRenderer } from "@tiptap/react";
|
||||||
|
|
||||||
|
import QuizBlockComponent from "./QuizBlockComponent";
|
||||||
|
|
||||||
|
export default Node.create({
|
||||||
|
name: "blockQuiz",
|
||||||
|
group: "block",
|
||||||
|
|
||||||
|
atom: true,
|
||||||
|
|
||||||
|
addAttributes() {
|
||||||
|
return {
|
||||||
|
quizId: {
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
parseHTML() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
tag: "block-quiz",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
renderHTML({ HTMLAttributes }) {
|
||||||
|
return ["block-quiz", mergeAttributes(HTMLAttributes), 0];
|
||||||
|
},
|
||||||
|
|
||||||
|
addNodeView() {
|
||||||
|
return ReactNodeViewRenderer(QuizBlockComponent);
|
||||||
|
},
|
||||||
|
});
|
||||||
164
front/components/Editor/Extensions/Quiz/QuizBlockComponent.tsx
Normal file
164
front/components/Editor/Extensions/Quiz/QuizBlockComponent.tsx
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
import { NodeViewWrapper } from "@tiptap/react";
|
||||||
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
import React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import { submitQuizBlock } from "@services/blocks/Quiz/quiz";
|
||||||
|
|
||||||
|
function ImageBlockComponent(props: any) {
|
||||||
|
const [questions, setQuestions] = React.useState([]) as any;
|
||||||
|
const [answers, setAnswers] = React.useState([]) as any;
|
||||||
|
|
||||||
|
function addSampleQuestion() {
|
||||||
|
setQuestions([
|
||||||
|
...questions,
|
||||||
|
{
|
||||||
|
question_id: "question_" + uuidv4(),
|
||||||
|
question_value: "",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
option_id: "option_" + uuidv4(),
|
||||||
|
option_data: "",
|
||||||
|
option_type: "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteQuestion = (index: number) => {
|
||||||
|
let modifiedQuestions = [...questions];
|
||||||
|
modifiedQuestions.splice(index, 1);
|
||||||
|
setQuestions(modifiedQuestions);
|
||||||
|
console.log(questions);
|
||||||
|
|
||||||
|
// remove the answers from the answers array
|
||||||
|
let modifiedAnswers = [...answers];
|
||||||
|
modifiedAnswers = modifiedAnswers.filter((answer: any) => answer.question_id !== questions[index].question_id);
|
||||||
|
setAnswers(modifiedAnswers);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onQuestionChange = (e: any, index: number) => {
|
||||||
|
let modifiedQuestions = [...questions];
|
||||||
|
modifiedQuestions[index].question_value = e.target.value;
|
||||||
|
setQuestions(modifiedQuestions);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addOption = (question_id: string) => {
|
||||||
|
// find the question index from the question_id and add the option to that question index
|
||||||
|
let modifiedQuestions = [...questions];
|
||||||
|
let questionIndex = modifiedQuestions.findIndex((question: any) => question.question_id === question_id);
|
||||||
|
modifiedQuestions[questionIndex].options.push({
|
||||||
|
option_id: "option_" + uuidv4(),
|
||||||
|
option_data: "",
|
||||||
|
option_type: "text",
|
||||||
|
});
|
||||||
|
setQuestions(modifiedQuestions);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteOption = (question_id: string, option_id: string) => {
|
||||||
|
// find the option index from the option_id and delete the option from that option index
|
||||||
|
let modifiedQuestions = [...questions];
|
||||||
|
let questionIndex = modifiedQuestions.findIndex((question: any) => question.question_id === question_id);
|
||||||
|
let optionIndex = modifiedQuestions[questionIndex].options.findIndex((option: any) => option.option_id === option_id);
|
||||||
|
modifiedQuestions[questionIndex].options.splice(optionIndex, 1);
|
||||||
|
setQuestions(modifiedQuestions);
|
||||||
|
|
||||||
|
// remove the answer from the answers array
|
||||||
|
let answerIndex = answers.findIndex((answer: any) => answer.option_id === option_id);
|
||||||
|
if (answerIndex !== -1) {
|
||||||
|
let modifiedAnswers = [...answers];
|
||||||
|
modifiedAnswers.splice(answerIndex, 1);
|
||||||
|
setAnswers(modifiedAnswers);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const markOptionAsCorrect = (question_id: string, option_id: string) => {
|
||||||
|
// find the option index from the option_id and mark the option as correct
|
||||||
|
let answer = {
|
||||||
|
question_id: question_id,
|
||||||
|
option_id: option_id,
|
||||||
|
};
|
||||||
|
setAnswers([...answers, answer]);
|
||||||
|
console.log(answers);
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveQuiz = async () => {
|
||||||
|
// save the questions and answers to the backend
|
||||||
|
console.log("saving quiz");
|
||||||
|
console.log(questions);
|
||||||
|
console.log(answers);
|
||||||
|
try {
|
||||||
|
let res = await submitQuizBlock(props.extension.options.lecture.lecture_id, {questions : questions , answers : answers})
|
||||||
|
console.log(res.block_id);
|
||||||
|
props.updateAttributes({
|
||||||
|
quizId: {
|
||||||
|
value : res.block_id
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOptionChange = (e: any, questionIndex: number, optionIndex: number) => {
|
||||||
|
let modifiedQuestions = [...questions];
|
||||||
|
modifiedQuestions[questionIndex].options[optionIndex].option_data = e.target.value;
|
||||||
|
setQuestions(modifiedQuestions);
|
||||||
|
};
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
// fetch the questions and options from the backend
|
||||||
|
console.log("fetching questions");
|
||||||
|
console.log(questions);
|
||||||
|
console.log(answers);
|
||||||
|
}, [questions, answers]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NodeViewWrapper className="block-quiz">
|
||||||
|
<QuizBlockWrapper>
|
||||||
|
Questions <button onClick={addSampleQuestion}>Add Question</button> <button onClick={() => saveQuiz()}>Save</button>
|
||||||
|
<hr />
|
||||||
|
{questions.map((question: any, qIndex: number) => (
|
||||||
|
<>
|
||||||
|
<div key={qIndex} style={{ marginTop: "10px" }}>
|
||||||
|
Question : <input type="text" value={question.question} onChange={(e) => onQuestionChange(e, qIndex)} />
|
||||||
|
<button onClick={() => deleteQuestion(qIndex)}>Delete</button>
|
||||||
|
</div>
|
||||||
|
Answers : <br />
|
||||||
|
{question.options.map((option: any, oIndex: number) => (
|
||||||
|
<>
|
||||||
|
<div key={oIndex}>
|
||||||
|
<input type="text" value={option.option_data} onChange={(e) => onOptionChange(e, qIndex, oIndex)} />
|
||||||
|
|
||||||
|
<button onClick={() => deleteOption(question.question_id, option.option_id)}>Delete</button>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
onChange={(e) =>
|
||||||
|
// check if checkbox is checked or not
|
||||||
|
// if checked then add the answer to the answers array
|
||||||
|
// if unchecked then remove the answer from the answers array
|
||||||
|
e.target.checked ? markOptionAsCorrect(question.question_id, option.option_id) : null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
<button onClick={() => addOption(question.question_id)}>Add Option</button>
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</QuizBlockWrapper>
|
||||||
|
</NodeViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QuizBlockWrapper = styled.div`
|
||||||
|
background-color: #0000001d;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 20px;
|
||||||
|
height: 100%;
|
||||||
|
`;
|
||||||
|
export default ImageBlockComponent;
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { FontBoldIcon, FontItalicIcon, StrikethroughIcon, ArrowLeftIcon, ArrowRightIcon, OpacityIcon } from "@radix-ui/react-icons";
|
import { FontBoldIcon, FontItalicIcon, StrikethroughIcon, ArrowLeftIcon, ArrowRightIcon, OpacityIcon } from "@radix-ui/react-icons";
|
||||||
import { AlertCircle, AlertTriangle, FileText, ImagePlus, Info, Sigma, Video, Youtube } from "lucide-react";
|
import { AlertCircle, AlertTriangle, FileText, GraduationCap, ImagePlus, Info, Sigma, Video, Youtube } from "lucide-react";
|
||||||
|
|
||||||
export const ToolbarButtons = ({ editor }: any) => {
|
export const ToolbarButtons = ({ editor, props }: any) => {
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -116,6 +116,19 @@ export const ToolbarButtons = ({ editor }: any) => {
|
||||||
>
|
>
|
||||||
<FileText size={15} />
|
<FileText size={15} />
|
||||||
</ToolBtn>
|
</ToolBtn>
|
||||||
|
<ToolBtn
|
||||||
|
onClick={() =>
|
||||||
|
editor
|
||||||
|
.chain()
|
||||||
|
.focus()
|
||||||
|
.insertContent({
|
||||||
|
type: "blockQuiz",
|
||||||
|
})
|
||||||
|
.run()
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<GraduationCap size={15} />
|
||||||
|
</ToolBtn>
|
||||||
</ToolButtonsWrapper>
|
</ToolButtonsWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,9 @@ const Overlay = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
background-color: #00000029;
|
||||||
|
backdrop-filter: blur(1px);
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Content = styled.div`
|
const Content = styled.div`
|
||||||
|
|
|
||||||
27
front/package-lock.json
generated
27
front/package-lock.json
generated
|
|
@ -26,6 +26,7 @@
|
||||||
"react-katex": "^3.0.1",
|
"react-katex": "^3.0.1",
|
||||||
"styled-components": "^6.0.0-beta.9",
|
"styled-components": "^6.0.0-beta.9",
|
||||||
"swr": "^2.0.1",
|
"swr": "^2.0.1",
|
||||||
|
"uuid": "^9.0.0",
|
||||||
"y-indexeddb": "^9.0.9",
|
"y-indexeddb": "^9.0.9",
|
||||||
"y-webrtc": "^10.2.3",
|
"y-webrtc": "^10.2.3",
|
||||||
"yjs": "^13.5.42"
|
"yjs": "^13.5.42"
|
||||||
|
|
@ -37,6 +38,7 @@
|
||||||
"@types/react-dom": "18.0.6",
|
"@types/react-dom": "18.0.6",
|
||||||
"@types/react-katex": "^3.0.0",
|
"@types/react-katex": "^3.0.0",
|
||||||
"@types/styled-components": "^5.1.26",
|
"@types/styled-components": "^5.1.26",
|
||||||
|
"@types/uuid": "^9.0.0",
|
||||||
"autoprefixer": "^10.4.12",
|
"autoprefixer": "^10.4.12",
|
||||||
"eslint": "8.23.1",
|
"eslint": "8.23.1",
|
||||||
"eslint-config-next": "^13.0.6",
|
"eslint-config-next": "^13.0.6",
|
||||||
|
|
@ -3058,6 +3060,12 @@
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/uuid": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "5.46.1",
|
"version": "5.46.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz",
|
||||||
|
|
@ -7088,6 +7096,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/w3c-keyname": {
|
"node_modules/w3c-keyname": {
|
||||||
"version": "2.2.6",
|
"version": "2.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
|
||||||
|
|
@ -9309,6 +9325,12 @@
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/uuid": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@typescript-eslint/parser": {
|
"@typescript-eslint/parser": {
|
||||||
"version": "5.46.1",
|
"version": "5.46.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz",
|
||||||
|
|
@ -12128,6 +12150,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||||
},
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg=="
|
||||||
|
},
|
||||||
"w3c-keyname": {
|
"w3c-keyname": {
|
||||||
"version": "2.2.6",
|
"version": "2.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
"react-katex": "^3.0.1",
|
"react-katex": "^3.0.1",
|
||||||
"styled-components": "^6.0.0-beta.9",
|
"styled-components": "^6.0.0-beta.9",
|
||||||
"swr": "^2.0.1",
|
"swr": "^2.0.1",
|
||||||
|
"uuid": "^9.0.0",
|
||||||
"y-indexeddb": "^9.0.9",
|
"y-indexeddb": "^9.0.9",
|
||||||
"y-webrtc": "^10.2.3",
|
"y-webrtc": "^10.2.3",
|
||||||
"yjs": "^13.5.42"
|
"yjs": "^13.5.42"
|
||||||
|
|
@ -38,6 +39,7 @@
|
||||||
"@types/react-dom": "18.0.6",
|
"@types/react-dom": "18.0.6",
|
||||||
"@types/react-katex": "^3.0.0",
|
"@types/react-katex": "^3.0.0",
|
||||||
"@types/styled-components": "^5.1.26",
|
"@types/styled-components": "^5.1.26",
|
||||||
|
"@types/uuid": "^9.0.0",
|
||||||
"autoprefixer": "^10.4.12",
|
"autoprefixer": "^10.4.12",
|
||||||
"eslint": "8.23.1",
|
"eslint": "8.23.1",
|
||||||
"eslint-config-next": "^13.0.6",
|
"eslint-config-next": "^13.0.6",
|
||||||
|
|
|
||||||
10
front/services/blocks/Quiz/quiz.ts
Normal file
10
front/services/blocks/Quiz/quiz.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { getAPIUrl } from "@services/config";
|
||||||
|
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
||||||
|
|
||||||
|
|
||||||
|
export async function submitQuizBlock(lecture_id: string, data: any) {
|
||||||
|
const result: any = await fetch(`${getAPIUrl()}blocks/quiz/${lecture_id}"`, RequestBody("POST", data))
|
||||||
|
.then((result) => result.json())
|
||||||
|
.catch((error) => console.log("error", error));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
@ -7,14 +7,14 @@ export async function uploadNewPDFFile(file: any, lecture_id: string) {
|
||||||
formData.append("file_object", file);
|
formData.append("file_object", file);
|
||||||
formData.append("lecture_id", lecture_id);
|
formData.append("lecture_id", lecture_id);
|
||||||
|
|
||||||
return fetch(`${getAPIUrl()}files/document`, RequestBodyForm("POST", formData))
|
return fetch(`${getAPIUrl()}blocks/document`, RequestBodyForm("POST", formData))
|
||||||
.then((result) => result.json())
|
.then((result) => result.json())
|
||||||
.catch((error) => console.log("error", error));
|
.catch((error) => console.log("error", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPDFFile(file_id: string) {
|
export async function getPDFFile(file_id: string) {
|
||||||
// todo : add course id to url
|
// todo : add course id to url
|
||||||
return fetch(`${getAPIUrl()}files/document?file_id=${file_id}`, RequestBody("GET", null))
|
return fetch(`${getAPIUrl()}blocks/document?file_id=${file_id}`, RequestBody("GET", null))
|
||||||
.then((result) => result.json())
|
.then((result) => result.json())
|
||||||
.catch((error) => console.log("error", error));
|
.catch((error) => console.log("error", error));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,14 @@ export async function uploadNewImageFile(file: any, lecture_id: string) {
|
||||||
formData.append("file_object", file);
|
formData.append("file_object", file);
|
||||||
formData.append("lecture_id", lecture_id);
|
formData.append("lecture_id", lecture_id);
|
||||||
|
|
||||||
return fetch(`${getAPIUrl()}files/picture`, RequestBodyForm("POST", formData))
|
return fetch(`${getAPIUrl()}blocks/image`, RequestBodyForm("POST", formData))
|
||||||
.then((result) => result.json())
|
.then((result) => result.json())
|
||||||
.catch((error) => console.log("error", error));
|
.catch((error) => console.log("error", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getImageFile(file_id: string) {
|
export async function getImageFile(file_id: string) {
|
||||||
// todo : add course id to url
|
// todo : add course id to url
|
||||||
return fetch(`${getAPIUrl()}files/picture?file_id=${file_id}`, RequestBody("GET", null))
|
return fetch(`${getAPIUrl()}blocks/image?file_id=${file_id}`, RequestBody("GET", null))
|
||||||
.then((result) => result.json())
|
.then((result) => result.json())
|
||||||
.catch((error) => console.log("error", error));
|
.catch((error) => console.log("error", error));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,13 @@ export async function uploadNewVideoFile(file: any, lecture_id: string) {
|
||||||
formData.append("file_object", file);
|
formData.append("file_object", file);
|
||||||
formData.append("lecture_id", lecture_id);
|
formData.append("lecture_id", lecture_id);
|
||||||
|
|
||||||
return fetch(`${getAPIUrl()}files/video`, RequestBodyForm("POST", formData))
|
return fetch(`${getAPIUrl()}blocks/video`, RequestBodyForm("POST", formData))
|
||||||
.then((result) => result.json())
|
.then((result) => result.json())
|
||||||
.catch((error) => console.log("error", error));
|
.catch((error) => console.log("error", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getVideoFile(file_id: string) {
|
export async function getVideoFile(file_id: string) {
|
||||||
return fetch(`${getAPIUrl()}files/video?file_id=${file_id}`, RequestBody("GET", null))
|
return fetch(`${getAPIUrl()}blocks/video?file_id=${file_id}`, RequestBody("GET", null))
|
||||||
.then((result) => result.json())
|
.then((result) => result.json())
|
||||||
.catch((error) => console.log("error", error));
|
.catch((error) => console.log("error", error));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
fastapi==0.89.1
|
fastapi==0.92.0
|
||||||
pydantic>=1.8.0,<2.0.0
|
pydantic>=1.8.0,<2.0.0
|
||||||
uvicorn==0.20.0
|
uvicorn==0.20.0
|
||||||
pymongo==4.1.1
|
pymongo==4.3.3
|
||||||
|
motor==3.1.1
|
||||||
python-multipart
|
python-multipart
|
||||||
python-jose
|
python-jose
|
||||||
passlib
|
passlib
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import logging
|
import logging
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
import pymongo
|
import motor.motor_asyncio
|
||||||
|
|
||||||
async def connect_to_db(app: FastAPI) :
|
async def connect_to_db(app: FastAPI) :
|
||||||
logging.info("Connecting to database...")
|
logging.info("Connecting to database...")
|
||||||
try:
|
try:
|
||||||
app.mongodb_client = pymongo.MongoClient("mongodb://learnhouse:learnhouse@mongo:27017/") # type: ignore
|
app.mongodb_client = motor.motor_asyncio.AsyncIOMotorClient("mongodb://learnhouse:learnhouse@mongo:27017/") # type: ignore
|
||||||
app.db = app.mongodb_client["learnhouse"] # type: ignore
|
app.db = app.mongodb_client["learnhouse"] # type: ignore
|
||||||
logging.info("Connected to database!")
|
logging.info("Connected to database!")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from src.routers import activity, users, auth, houses, orgs, roles, files
|
from src.routers import activity, blocks, users, auth, houses, orgs, roles
|
||||||
from src.routers.courses import chapters, collections, courses,lectures
|
from src.routers.courses import chapters, collections, courses,lectures
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -12,7 +12,7 @@ global_router.include_router(auth.router, prefix="/auth", tags=["auth"])
|
||||||
global_router.include_router(houses.router, prefix="/houses", tags=["houses"])
|
global_router.include_router(houses.router, prefix="/houses", tags=["houses"])
|
||||||
global_router.include_router(orgs.router, prefix="/orgs", tags=["orgs"])
|
global_router.include_router(orgs.router, prefix="/orgs", tags=["orgs"])
|
||||||
global_router.include_router(roles.router, prefix="/roles", tags=["roles"])
|
global_router.include_router(roles.router, prefix="/roles", tags=["roles"])
|
||||||
global_router.include_router(files.router, prefix="/files", tags=["files"])
|
global_router.include_router(blocks.router, prefix="/blocks", tags=["blocks"])
|
||||||
global_router.include_router(courses.router, prefix="/courses", tags=["courses"])
|
global_router.include_router(courses.router, prefix="/courses", tags=["courses"])
|
||||||
global_router.include_router(chapters.router, prefix="/chapters", tags=["chapters"])
|
global_router.include_router(chapters.router, prefix="/chapters", tags=["chapters"])
|
||||||
global_router.include_router(lectures.router, prefix="/lectures", tags=["lectures"])
|
global_router.include_router(lectures.router, prefix="/lectures", tags=["lectures"])
|
||||||
|
|
|
||||||
80
src/routers/blocks.py
Normal file
80
src/routers/blocks.py
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
from fastapi import APIRouter, Depends, UploadFile, Form, Request
|
||||||
|
from src.dependencies.auth import get_current_user
|
||||||
|
from fastapi import HTTPException, status, UploadFile
|
||||||
|
from src.services.blocks.imageBlock.images import create_image_file, get_image_file
|
||||||
|
from src.services.blocks.videoBlock.videos import create_video_file, get_video_file
|
||||||
|
from src.services.blocks.pdfBlock.documents import create_document_file, get_document_file
|
||||||
|
from src.services.blocks.quizBlock.quizBlock import create_quiz_block, get_quiz_block_answers, get_quiz_block_options, quizBlock
|
||||||
|
from src.services.users import PublicUser
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/image")
|
||||||
|
async def api_create_image_file_block(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Create new image file
|
||||||
|
"""
|
||||||
|
return await create_image_file(request, file_object, lecture_id)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/image")
|
||||||
|
async def api_get_image_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Get image file
|
||||||
|
"""
|
||||||
|
return await get_image_file(request, file_id, current_user)
|
||||||
|
|
||||||
|
@router.post("/video")
|
||||||
|
async def api_create_video_file_block(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Create new video file
|
||||||
|
"""
|
||||||
|
return await create_video_file(request, file_object, lecture_id)
|
||||||
|
|
||||||
|
@router.get("/video")
|
||||||
|
async def api_get_video_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Get video file
|
||||||
|
"""
|
||||||
|
return await get_video_file(request, file_id, current_user)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/document")
|
||||||
|
async def api_create_document_file_block(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Create new document file
|
||||||
|
"""
|
||||||
|
return await create_document_file(request, file_object, lecture_id)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/document")
|
||||||
|
async def api_get_document_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Get document file
|
||||||
|
"""
|
||||||
|
return await get_document_file(request, file_id, current_user)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/quiz/{lecture_id}")
|
||||||
|
async def api_create_quiz_block(request: Request, quiz_block: quizBlock, lecture_id: str, current_user: PublicUser = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Create new document file
|
||||||
|
"""
|
||||||
|
return await create_quiz_block(request, quiz_block, lecture_id, current_user)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/quiz/options")
|
||||||
|
async def api_get_quiz_options(request: Request, block_id: str, current_user: PublicUser = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Get quiz options
|
||||||
|
"""
|
||||||
|
return await get_quiz_block_options(request, block_id, current_user)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/quiz/answers")
|
||||||
|
async def api_get_quiz_answers(request: Request, block_id: str, current_user: PublicUser = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Get quiz answers
|
||||||
|
"""
|
||||||
|
return await get_quiz_block_answers(request, block_id, current_user)
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
from fastapi import APIRouter, Depends, UploadFile, Form, Request
|
|
||||||
from src.dependencies.auth import get_current_user
|
|
||||||
from fastapi import HTTPException, status, UploadFile
|
|
||||||
from src.services.files.documents import create_document_file, get_document_file
|
|
||||||
|
|
||||||
from src.services.files.pictures import create_picture_file, get_picture_file
|
|
||||||
from src.services.files.videos import create_video_file, get_video_file
|
|
||||||
from src.services.users import PublicUser
|
|
||||||
|
|
||||||
router = APIRouter()
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/picture")
|
|
||||||
async def api_create_picture_file(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
|
|
||||||
"""
|
|
||||||
Create new picture file
|
|
||||||
"""
|
|
||||||
return await create_picture_file(request, file_object, lecture_id)
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/video")
|
|
||||||
async def api_create_video_file(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
|
|
||||||
"""
|
|
||||||
Create new video file
|
|
||||||
"""
|
|
||||||
return await create_video_file(request, file_object, lecture_id)
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/picture")
|
|
||||||
async def api_get_picture_file(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
|
|
||||||
"""
|
|
||||||
Get picture file
|
|
||||||
"""
|
|
||||||
return await get_picture_file(request, file_id, current_user)
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/video")
|
|
||||||
async def api_get_video_file(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
|
|
||||||
"""
|
|
||||||
Get video file
|
|
||||||
"""
|
|
||||||
return await get_video_file(request, file_id, current_user)
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/document")
|
|
||||||
async def api_get_document_file(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
|
|
||||||
"""
|
|
||||||
Get document file
|
|
||||||
"""
|
|
||||||
return await get_document_file(request, file_id, current_user)
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/document")
|
|
||||||
async def api_create_document_file(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
|
|
||||||
"""
|
|
||||||
Create new document file
|
|
||||||
"""
|
|
||||||
return await create_document_file(request, file_object, lecture_id)
|
|
||||||
|
|
@ -35,13 +35,13 @@ async def create_activity(request: Request, user: PublicUser, activity_object: A
|
||||||
activities = request.app.db["activities"]
|
activities = request.app.db["activities"]
|
||||||
|
|
||||||
# find if the user has already started the course
|
# find if the user has already started the course
|
||||||
isActivityAlreadCreated = activities.find_one(
|
isActivityAlreadCreated = await activities.find_one(
|
||||||
{"course_id": activity_object.course_id, "user_id": user.user_id})
|
{"course_id": activity_object.course_id, "user_id": user.user_id})
|
||||||
|
|
||||||
if isActivityAlreadCreated:
|
if isActivityAlreadCreated:
|
||||||
if isActivityAlreadCreated['status'] == 'closed':
|
if isActivityAlreadCreated['status'] == 'closed':
|
||||||
activity_object.status = 'ongoing'
|
activity_object.status = 'ongoing'
|
||||||
activities.update_one(
|
await activities.update_one(
|
||||||
{"activity_id": isActivityAlreadCreated['activity_id']}, {"$set": activity_object.dict()})
|
{"activity_id": isActivityAlreadCreated['activity_id']}, {"$set": activity_object.dict()})
|
||||||
return activity_object
|
return activity_object
|
||||||
else:
|
else:
|
||||||
|
|
@ -54,7 +54,7 @@ async def create_activity(request: Request, user: PublicUser, activity_object: A
|
||||||
activity = ActivityInDB(**activity_object.dict(),activity_id=activity_id,
|
activity = ActivityInDB(**activity_object.dict(),activity_id=activity_id,
|
||||||
user_id=user.user_id, org_id=activity_object.course_id)
|
user_id=user.user_id, org_id=activity_object.course_id)
|
||||||
|
|
||||||
activities.insert_one(activity.dict())
|
await activities.insert_one(activity.dict())
|
||||||
|
|
||||||
return activity
|
return activity
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ async def get_user_activities(request: Request, user: PublicUser, org_id: str):
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="No activities found")
|
status_code=status.HTTP_409_CONFLICT, detail="No activities found")
|
||||||
|
|
||||||
for activity in user_activities:
|
for activity in await user_activities.to_list(length=100):
|
||||||
# get number of lectures in the course
|
# get number of lectures in the course
|
||||||
coursechapters = await get_coursechapters_meta(request, activity['course_id'], user)
|
coursechapters = await get_coursechapters_meta(request, activity['course_id'], user)
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ async def get_user_activities(request: Request, user: PublicUser, org_id: str):
|
||||||
progression = round(
|
progression = round(
|
||||||
len(activity['lectures_marked_complete']) / len(coursechapters['lectures']) * 100, 2)
|
len(activity['lectures_marked_complete']) / len(coursechapters['lectures']) * 100, 2)
|
||||||
|
|
||||||
course = courses.find_one({"course_id": activity['course_id']}, {'_id': 0})
|
course = await courses.find_one({"course_id": activity['course_id']}, {'_id': 0})
|
||||||
|
|
||||||
# add progression to the activity
|
# add progression to the activity
|
||||||
one_activity = {"course": course, "activitydata": activity, "progression": progression}
|
one_activity = {"course": course, "activitydata": activity, "progression": progression}
|
||||||
|
|
@ -103,7 +103,7 @@ async def get_user_activities_orgslug(request: Request, user: PublicUser, org_sl
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="No activities found")
|
status_code=status.HTTP_409_CONFLICT, detail="No activities found")
|
||||||
|
|
||||||
for activity in user_activities:
|
for activity in await user_activities.to_list(length=100):
|
||||||
# get number of lectures in the course
|
# get number of lectures in the course
|
||||||
coursechapters = await get_coursechapters_meta(request, activity['course_id'], user)
|
coursechapters = await get_coursechapters_meta(request, activity['course_id'], user)
|
||||||
|
|
||||||
|
|
@ -111,7 +111,7 @@ async def get_user_activities_orgslug(request: Request, user: PublicUser, org_sl
|
||||||
progression = round(
|
progression = round(
|
||||||
len(activity['lectures_marked_complete']) / len(coursechapters['lectures']) * 100, 2)
|
len(activity['lectures_marked_complete']) / len(coursechapters['lectures']) * 100, 2)
|
||||||
|
|
||||||
course = courses.find_one({"course_id": activity['course_id']}, {'_id': 0})
|
course = await courses.find_one({"course_id": activity['course_id']}, {'_id': 0})
|
||||||
|
|
||||||
# add progression to the activity
|
# add progression to the activity
|
||||||
one_activity = {"course": course, "activitydata": activity, "progression": progression}
|
one_activity = {"course": course, "activitydata": activity, "progression": progression}
|
||||||
|
|
@ -125,14 +125,14 @@ async def add_lecture_to_activity(request: Request, user: PublicUser, org_id: st
|
||||||
course_id = f"course_{course_id}"
|
course_id = f"course_{course_id}"
|
||||||
lecture_id = f"lecture_{lecture_id}"
|
lecture_id = f"lecture_{lecture_id}"
|
||||||
|
|
||||||
activity = activities.find_one(
|
activity = await activities.find_one(
|
||||||
{"course_id": course_id,
|
{"course_id": course_id,
|
||||||
"user_id": user.user_id
|
"user_id": user.user_id
|
||||||
}, {'_id': 0})
|
}, {'_id': 0})
|
||||||
|
|
||||||
if lecture_id not in activity['lectures_marked_complete']:
|
if lecture_id not in activity['lectures_marked_complete']:
|
||||||
activity['lectures_marked_complete'].append(str(lecture_id))
|
activity['lectures_marked_complete'].append(str(lecture_id))
|
||||||
activities.update_one(
|
await activities.update_one(
|
||||||
{"activity_id": activity['activity_id']}, {"$set": activity})
|
{"activity_id": activity['activity_id']}, {"$set": activity})
|
||||||
return activity
|
return activity
|
||||||
|
|
||||||
|
|
@ -147,7 +147,7 @@ async def add_lecture_to_activity(request: Request, user: PublicUser, org_id: st
|
||||||
|
|
||||||
async def close_activity(request: Request, user: PublicUser, activity_id: str, org_id: str,):
|
async def close_activity(request: Request, user: PublicUser, activity_id: str, org_id: str,):
|
||||||
activities = request.app.db["activities"]
|
activities = request.app.db["activities"]
|
||||||
activity = activities.find_one(
|
activity = await activities.find_one(
|
||||||
{"activity_id": activity_id, "user_id": user.user_id})
|
{"activity_id": activity_id, "user_id": user.user_id})
|
||||||
|
|
||||||
if not activity:
|
if not activity:
|
||||||
|
|
@ -156,7 +156,7 @@ async def close_activity(request: Request, user: PublicUser, activity_id: str,
|
||||||
|
|
||||||
activity['status'] = 'closed'
|
activity['status'] = 'closed'
|
||||||
|
|
||||||
activities.update_one(
|
await activities.update_one(
|
||||||
{"activity_id": activity['activity_id']}, {"$set": activity})
|
{"activity_id": activity['activity_id']}, {"$set": activity})
|
||||||
|
|
||||||
activity = ActivityInDB(**activity)
|
activity = ActivityInDB(**activity)
|
||||||
|
|
|
||||||
12
src/services/blocks/blocks.py
Normal file
12
src/services/blocks/blocks.py
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
from typing import Any, List, Literal
|
||||||
|
from uuid import uuid4
|
||||||
|
from fastapi import Request
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class Block(BaseModel):
|
||||||
|
block_id: str
|
||||||
|
lecture_id: str
|
||||||
|
block_type: Literal["quizBlock", "videoBlock", "pdfBlock"]
|
||||||
|
block_data: Any
|
||||||
|
|
@ -16,31 +16,31 @@ class PhotoFile(BaseModel):
|
||||||
lecture_id: str
|
lecture_id: str
|
||||||
|
|
||||||
|
|
||||||
async def create_picture_file(request: Request,picture_file: UploadFile, lecture_id: str):
|
async def create_image_file(request: Request,image_file: UploadFile, lecture_id: str):
|
||||||
photos = request.app.db["files"]
|
photos = request.app.db["files"]
|
||||||
|
|
||||||
# generate file_id
|
# generate file_id
|
||||||
file_id = str(f"file_{uuid4()}")
|
file_id = str(f"file_{uuid4()}")
|
||||||
|
|
||||||
# get file format
|
# get file format
|
||||||
file_format = picture_file.filename.split(".")[-1]
|
file_format = image_file.filename.split(".")[-1]
|
||||||
|
|
||||||
# validate file format
|
# validate file format
|
||||||
if file_format not in ["jpg", "jpeg", "png", "gif"]:
|
if file_format not in ["jpg", "jpeg", "png", "gif"]:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Picture file format not supported")
|
status_code=status.HTTP_409_CONFLICT, detail="Image file format not supported")
|
||||||
|
|
||||||
# create file
|
# create file
|
||||||
file = await picture_file.read()
|
file = await image_file.read()
|
||||||
|
|
||||||
# get file size
|
# get file size
|
||||||
file_size = len(file)
|
file_size = len(file)
|
||||||
|
|
||||||
# get file type
|
# get file type
|
||||||
file_type = picture_file.content_type
|
file_type = image_file.content_type
|
||||||
|
|
||||||
# get file name
|
# get file name
|
||||||
file_name = picture_file.filename
|
file_name = image_file.filename
|
||||||
|
|
||||||
# create file object
|
# create file object
|
||||||
uploadable_file = PhotoFile(
|
uploadable_file = PhotoFile(
|
||||||
|
|
@ -53,16 +53,16 @@ async def create_picture_file(request: Request,picture_file: UploadFile, lecture
|
||||||
)
|
)
|
||||||
|
|
||||||
# create folder for lecture
|
# create folder for lecture
|
||||||
if not os.path.exists(f"content/uploads/files/pictures/{lecture_id}"):
|
if not os.path.exists(f"content/uploads/files/images/{lecture_id}"):
|
||||||
os.mkdir(f"content/uploads/files/pictures/{lecture_id}")
|
os.mkdir(f"content/uploads/files/images/{lecture_id}")
|
||||||
|
|
||||||
# upload file to server
|
# upload file to server
|
||||||
with open(f"content/uploads/files/pictures/{lecture_id}/{file_id}.{file_format}", 'wb') as f:
|
with open(f"content/uploads/files/images/{lecture_id}/{file_id}.{file_format}", 'wb') as f:
|
||||||
f.write(file)
|
f.write(file)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
# insert file object into database
|
# insert file object into database
|
||||||
photo_file_in_db = photos.insert_one(uploadable_file.dict())
|
photo_file_in_db = await photos.insert_one(uploadable_file.dict())
|
||||||
|
|
||||||
if not photo_file_in_db:
|
if not photo_file_in_db:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -71,10 +71,10 @@ async def create_picture_file(request: Request,picture_file: UploadFile, lecture
|
||||||
return uploadable_file
|
return uploadable_file
|
||||||
|
|
||||||
|
|
||||||
async def get_picture_object(request: Request,file_id: str):
|
async def get_image_object(request: Request,file_id: str):
|
||||||
photos = request.app.db["files"]
|
photos = request.app.db["files"]
|
||||||
|
|
||||||
photo_file = photos.find_one({"file_id": file_id})
|
photo_file = await photos.find_one({"file_id": file_id})
|
||||||
|
|
||||||
if photo_file:
|
if photo_file:
|
||||||
photo_file = PhotoFile(**photo_file)
|
photo_file = PhotoFile(**photo_file)
|
||||||
|
|
@ -85,10 +85,10 @@ async def get_picture_object(request: Request,file_id: str):
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Photo file does not exist")
|
status_code=status.HTTP_409_CONFLICT, detail="Photo file does not exist")
|
||||||
|
|
||||||
|
|
||||||
async def get_picture_file(request: Request,file_id: str, current_user: PublicUser):
|
async def get_image_file(request: Request,file_id: str, current_user: PublicUser):
|
||||||
photos = request.app.db["files"]
|
photos = request.app.db["files"]
|
||||||
|
|
||||||
photo_file = photos.find_one({"file_id": file_id})
|
photo_file = await photos.find_one({"file_id": file_id})
|
||||||
|
|
||||||
# TODO : check if user has access to file
|
# TODO : check if user has access to file
|
||||||
|
|
||||||
|
|
@ -104,7 +104,7 @@ async def get_picture_file(request: Request,file_id: str, current_user: PublicUs
|
||||||
file_format = photo_file.file_format
|
file_format = photo_file.file_format
|
||||||
lecture_id = photo_file.lecture_id
|
lecture_id = photo_file.lecture_id
|
||||||
file = open(
|
file = open(
|
||||||
f"content/uploads/files/pictures/{lecture_id}/{file_id}.{file_format}", 'rb')
|
f"content/uploads/files/images/{lecture_id}/{file_id}.{file_format}", 'rb')
|
||||||
return StreamingResponse(file, media_type=photo_file.file_type)
|
return StreamingResponse(file, media_type=photo_file.file_type)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
@ -62,7 +62,7 @@ async def create_document_file(request: Request, document_file: UploadFile, lect
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
# insert file object into database
|
# insert file object into database
|
||||||
document_file_in_db = documents.insert_one(uploadable_file.dict())
|
document_file_in_db = await documents.insert_one(uploadable_file.dict())
|
||||||
|
|
||||||
if not document_file_in_db:
|
if not document_file_in_db:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -74,7 +74,7 @@ async def create_document_file(request: Request, document_file: UploadFile, lect
|
||||||
async def get_document_object(request: Request, file_id: str):
|
async def get_document_object(request: Request, file_id: str):
|
||||||
documents = request.app.db["files"]
|
documents = request.app.db["files"]
|
||||||
|
|
||||||
document_file = documents.find_one({"file_id": file_id})
|
document_file = await documents.find_one({"file_id": file_id})
|
||||||
|
|
||||||
if document_file:
|
if document_file:
|
||||||
document_file = DocumentFile(**document_file)
|
document_file = DocumentFile(**document_file)
|
||||||
|
|
@ -88,14 +88,14 @@ async def get_document_object(request: Request, file_id: str):
|
||||||
async def get_document_file(request: Request, file_id: str, current_user: PublicUser):
|
async def get_document_file(request: Request, file_id: str, current_user: PublicUser):
|
||||||
documents = request.app.db["files"]
|
documents = request.app.db["files"]
|
||||||
|
|
||||||
document_file = documents.find_one({"file_id": file_id})
|
document_file = await documents.find_one({"file_id": file_id})
|
||||||
|
|
||||||
# TODO : check if user has access to file
|
# TODO : check if user has access to file
|
||||||
|
|
||||||
if document_file:
|
if document_file:
|
||||||
|
|
||||||
# check media type
|
# check media type
|
||||||
if document_file.format not in ["jpg", "jpeg", "png", "gif"]:
|
if document_file.format not in ["pdf"]:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Document file format not supported")
|
status_code=status.HTTP_409_CONFLICT, detail="Document file format not supported")
|
||||||
|
|
||||||
60
src/services/blocks/quizBlock/quizBlock.py
Normal file
60
src/services/blocks/quizBlock/quizBlock.py
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
from typing import List, Literal
|
||||||
|
from uuid import uuid4
|
||||||
|
from fastapi import Request
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from src.services.blocks.blocks import Block
|
||||||
|
from src.services.users import PublicUser
|
||||||
|
|
||||||
|
|
||||||
|
class option(BaseModel):
|
||||||
|
option_id: str
|
||||||
|
option_type: Literal["text", "image"]
|
||||||
|
option_data: str
|
||||||
|
|
||||||
|
|
||||||
|
class answer(BaseModel):
|
||||||
|
question_id: str
|
||||||
|
option_id: str
|
||||||
|
|
||||||
|
|
||||||
|
class question(BaseModel):
|
||||||
|
question_id: str
|
||||||
|
question_value:str
|
||||||
|
options: List[option]
|
||||||
|
|
||||||
|
|
||||||
|
class quizBlock(BaseModel):
|
||||||
|
questions: List[question]
|
||||||
|
answers: List[answer]
|
||||||
|
|
||||||
|
|
||||||
|
async def create_quiz_block(request: Request, quizBlock: quizBlock, lecture_id: str, user: PublicUser):
|
||||||
|
blocks = request.app.db["blocks"]
|
||||||
|
block_id = str(f"block_{uuid4()}")
|
||||||
|
|
||||||
|
# create block
|
||||||
|
block = Block(block_id=block_id, lecture_id=lecture_id,
|
||||||
|
block_type="quizBlock", block_data=quizBlock)
|
||||||
|
|
||||||
|
# insert block
|
||||||
|
await blocks.insert_one(block.dict())
|
||||||
|
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
async def get_quiz_block_options(request: Request, block_id: str, user: PublicUser):
|
||||||
|
blocks = request.app.db["blocks"]
|
||||||
|
# find block but get only the options
|
||||||
|
block = await blocks.find_one({"block_id": block_id, }, {
|
||||||
|
"_id": 0, "block_data.answers": 0})
|
||||||
|
|
||||||
|
return block
|
||||||
|
|
||||||
|
async def get_quiz_block_answers(request: Request, block_id: str, user: PublicUser):
|
||||||
|
blocks = request.app.db["blocks"]
|
||||||
|
|
||||||
|
# find block but get only the answers
|
||||||
|
block = await blocks.find_one({"block_id": block_id, }, {
|
||||||
|
"_id": 0, "block_data.questions": 0})
|
||||||
|
|
||||||
|
return block
|
||||||
|
|
@ -62,7 +62,7 @@ async def create_video_file(request: Request,video_file: UploadFile, lecture_id:
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
# insert file object into database
|
# insert file object into database
|
||||||
video_file_in_db = files.insert_one(uploadable_file.dict())
|
video_file_in_db = await files.insert_one(uploadable_file.dict())
|
||||||
|
|
||||||
if not video_file_in_db:
|
if not video_file_in_db:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -74,7 +74,7 @@ async def create_video_file(request: Request,video_file: UploadFile, lecture_id:
|
||||||
async def get_video_object(request: Request,file_id: str, current_user: PublicUser):
|
async def get_video_object(request: Request,file_id: str, current_user: PublicUser):
|
||||||
photos = request.app.db["files"]
|
photos = request.app.db["files"]
|
||||||
|
|
||||||
video_file = photos.find_one({"file_id": file_id})
|
video_file = await photos.find_one({"file_id": file_id})
|
||||||
|
|
||||||
if video_file:
|
if video_file:
|
||||||
video_file = VideoFile(**video_file)
|
video_file = VideoFile(**video_file)
|
||||||
|
|
@ -88,7 +88,7 @@ async def get_video_object(request: Request,file_id: str, current_user: PublicUs
|
||||||
async def get_video_file(request: Request,file_id: str, current_user: PublicUser):
|
async def get_video_file(request: Request,file_id: str, current_user: PublicUser):
|
||||||
photos = request.app.db["files"]
|
photos = request.app.db["files"]
|
||||||
|
|
||||||
video_file = photos.find_one({"file_id": file_id})
|
video_file = await photos.find_one({"file_id": file_id})
|
||||||
|
|
||||||
# TODO : check if user has access to file
|
# TODO : check if user has access to file
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@ class CourseChapterInDB(CourseChapter):
|
||||||
# Frontend
|
# Frontend
|
||||||
class CourseChapterMetaData(BaseModel):
|
class CourseChapterMetaData(BaseModel):
|
||||||
chapterOrder: List[str]
|
chapterOrder: List[str]
|
||||||
chapters: object
|
chapters: dict
|
||||||
lectures: object
|
lectures: object
|
||||||
|
|
||||||
#### Classes ####################################################
|
#### Classes ####################################################
|
||||||
|
|
@ -52,7 +52,7 @@ async def create_coursechapter(request: Request,coursechapter_object: CourseChap
|
||||||
coursechapter = CourseChapterInDB(coursechapter_id=coursechapter_id, creationDate=str(
|
coursechapter = CourseChapterInDB(coursechapter_id=coursechapter_id, creationDate=str(
|
||||||
datetime.now()), updateDate=str(datetime.now()), course_id=course_id, **coursechapter_object.dict())
|
datetime.now()), updateDate=str(datetime.now()), course_id=course_id, **coursechapter_object.dict())
|
||||||
|
|
||||||
coursechapter_in_db = coursechapters.insert_one(coursechapter.dict())
|
coursechapter_in_db = await coursechapters.insert_one(coursechapter.dict())
|
||||||
courses.update_one({"course_id": course_id}, {
|
courses.update_one({"course_id": course_id}, {
|
||||||
"$addToSet": {"chapters": coursechapter_id}})
|
"$addToSet": {"chapters": coursechapter_id}})
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ async def create_coursechapter(request: Request,coursechapter_object: CourseChap
|
||||||
async def get_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser):
|
async def get_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser):
|
||||||
coursechapters = request.app.db["coursechapters"]
|
coursechapters = request.app.db["coursechapters"]
|
||||||
|
|
||||||
coursechapter = coursechapters.find_one(
|
coursechapter = await coursechapters.find_one(
|
||||||
{"coursechapter_id": coursechapter_id})
|
{"coursechapter_id": coursechapter_id})
|
||||||
|
|
||||||
if coursechapter:
|
if coursechapter:
|
||||||
|
|
@ -84,7 +84,7 @@ async def get_coursechapter(request: Request,coursechapter_id: str, current_user
|
||||||
async def update_coursechapter(request: Request,coursechapter_object: CourseChapter, coursechapter_id: str, current_user: PublicUser):
|
async def update_coursechapter(request: Request,coursechapter_object: CourseChapter, coursechapter_id: str, current_user: PublicUser):
|
||||||
coursechapters = request.app.db["coursechapters"]
|
coursechapters = request.app.db["coursechapters"]
|
||||||
|
|
||||||
coursechapter = coursechapters.find_one(
|
coursechapter = await coursechapters.find_one(
|
||||||
{"coursechapter_id": coursechapter_id})
|
{"coursechapter_id": coursechapter_id})
|
||||||
|
|
||||||
if coursechapter:
|
if coursechapter:
|
||||||
|
|
@ -98,7 +98,7 @@ async def update_coursechapter(request: Request,coursechapter_object: CourseChap
|
||||||
updated_coursechapter = CourseChapterInDB(
|
updated_coursechapter = CourseChapterInDB(
|
||||||
coursechapter_id=coursechapter_id, creationDate=creationDate, course_id=coursechapter["course_id"], updateDate=str(datetime_object), **coursechapter_object.dict())
|
coursechapter_id=coursechapter_id, creationDate=creationDate, course_id=coursechapter["course_id"], updateDate=str(datetime_object), **coursechapter_object.dict())
|
||||||
|
|
||||||
coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
|
await coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
|
||||||
"$set": updated_coursechapter.dict()})
|
"$set": updated_coursechapter.dict()})
|
||||||
|
|
||||||
return CourseChapterInDB(**updated_coursechapter.dict())
|
return CourseChapterInDB(**updated_coursechapter.dict())
|
||||||
|
|
@ -113,18 +113,18 @@ async def delete_coursechapter(request: Request,coursechapter_id: str, current_
|
||||||
coursechapters = request.app.db["coursechapters"]
|
coursechapters = request.app.db["coursechapters"]
|
||||||
courses = request.app.db["courses"]
|
courses = request.app.db["courses"]
|
||||||
|
|
||||||
coursechapter = coursechapters.find_one(
|
coursechapter = await coursechapters.find_one(
|
||||||
{"coursechapter_id": coursechapter_id})
|
{"coursechapter_id": coursechapter_id})
|
||||||
|
|
||||||
if coursechapter:
|
if coursechapter:
|
||||||
# verify course rights
|
# verify course rights
|
||||||
await verify_rights(request, coursechapter["course_id"], current_user, "delete")
|
await verify_rights(request, coursechapter["course_id"], current_user, "delete")
|
||||||
|
|
||||||
isDeleted = coursechapters.delete_one(
|
isDeleted = await coursechapters.delete_one(
|
||||||
{"coursechapter_id": coursechapter_id})
|
{"coursechapter_id": coursechapter_id})
|
||||||
|
|
||||||
# Remove coursechapter from course
|
# Remove coursechapter from course
|
||||||
courses.update_one({"course_id": coursechapter["course_id"]}, {
|
await courses.update_one({"course_id": coursechapter["course_id"]}, {
|
||||||
"$pull": {"chapters": coursechapter_id}})
|
"$pull": {"chapters": coursechapter_id}})
|
||||||
|
|
||||||
if isDeleted:
|
if isDeleted:
|
||||||
|
|
@ -149,7 +149,7 @@ async def get_coursechapters(request: Request,course_id: str, page: int = 1, lim
|
||||||
all_coursechapters = courses.find({"course_id": course_id}).sort(
|
all_coursechapters = courses.find({"course_id": course_id}).sort(
|
||||||
"name", 1).skip(10 * (page - 1)).limit(limit)
|
"name", 1).skip(10 * (page - 1)).limit(limit)
|
||||||
|
|
||||||
return [json.loads(json.dumps(coursechapter, default=str)) for coursechapter in all_coursechapters]
|
return [json.loads(json.dumps(coursechapter, default=str)) for coursechapter in await all_coursechapters.to_list(length=100)]
|
||||||
|
|
||||||
|
|
||||||
async def get_coursechapters_meta(request: Request, course_id: str, current_user: PublicUser):
|
async def get_coursechapters_meta(request: Request, course_id: str, current_user: PublicUser):
|
||||||
|
|
@ -160,7 +160,7 @@ async def get_coursechapters_meta(request: Request, course_id: str, current_user
|
||||||
coursechapters = coursechapters.find(
|
coursechapters = coursechapters.find(
|
||||||
{"course_id": course_id}).sort("name", 1)
|
{"course_id": course_id}).sort("name", 1)
|
||||||
|
|
||||||
course = courses.find_one({"course_id": course_id})
|
course = await courses.find_one({"course_id": course_id})
|
||||||
course = Course(**course) # type: ignore
|
course = Course(**course) # type: ignore
|
||||||
|
|
||||||
# lectures
|
# lectures
|
||||||
|
|
@ -168,7 +168,7 @@ async def get_coursechapters_meta(request: Request, course_id: str, current_user
|
||||||
|
|
||||||
# chapters
|
# chapters
|
||||||
chapters = {}
|
chapters = {}
|
||||||
for coursechapter in coursechapters:
|
for coursechapter in await coursechapters.to_list(length=100):
|
||||||
coursechapter = CourseChapterInDB(**coursechapter)
|
coursechapter = CourseChapterInDB(**coursechapter)
|
||||||
coursechapter_lectureIds = []
|
coursechapter_lectureIds = []
|
||||||
|
|
||||||
|
|
@ -182,7 +182,7 @@ async def get_coursechapters_meta(request: Request, course_id: str, current_user
|
||||||
|
|
||||||
# lectures
|
# lectures
|
||||||
lectures_list = {}
|
lectures_list = {}
|
||||||
for lecture in lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}):
|
for lecture in await lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}).to_list(length=100):
|
||||||
lecture = LectureInDB(**lecture)
|
lecture = LectureInDB(**lecture)
|
||||||
lectures_list[lecture.lecture_id] = {
|
lectures_list[lecture.lecture_id] = {
|
||||||
"id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content
|
"id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content
|
||||||
|
|
@ -202,14 +202,18 @@ async def update_coursechapters_meta(request: Request,course_id: str, coursechap
|
||||||
courses = request.app.db["courses"]
|
courses = request.app.db["courses"]
|
||||||
|
|
||||||
# update chapters in course
|
# update chapters in course
|
||||||
courseInDB = courses.update_one({"course_id": course_id}, {
|
courseInDB = await courses.update_one({"course_id": course_id}, {
|
||||||
"$set": {"chapters": coursechapters_metadata.chapterOrder}})
|
"$set": {"chapters": coursechapters_metadata.chapterOrder}})
|
||||||
|
|
||||||
# update lectures in coursechapters
|
if coursechapters_metadata.chapters is not None:
|
||||||
# TODO : performance/optimization improvement, this does not work anyway.
|
for coursechapter_id, chapter_metadata in coursechapters_metadata.chapters.items():
|
||||||
for coursechapter in coursechapters_metadata.chapters.__dict__.items():
|
filter_query = {"coursechapter_id": coursechapter_id}
|
||||||
coursechapters.update_one({"coursechapter_id": coursechapter}, {
|
update_query = {"$set": {"lectures": chapter_metadata["lectureIds"]}}
|
||||||
"$set": {"lectures": coursechapters_metadata.chapters[coursechapter]["lectureIds"]}}) # type: ignore
|
result = await coursechapters.update_one(filter_query, update_query)
|
||||||
|
if result.matched_count == 0:
|
||||||
|
# handle error when no documents are matched by the filter query
|
||||||
|
print(f"No documents found for course chapter ID {coursechapter_id}")
|
||||||
|
|
||||||
|
|
||||||
return {"detail": "coursechapters metadata updated"}
|
return {"detail": "coursechapters metadata updated"}
|
||||||
|
|
||||||
|
|
@ -219,7 +223,7 @@ async def update_coursechapters_meta(request: Request,course_id: str, coursechap
|
||||||
async def verify_rights(request: Request,course_id: str, current_user: PublicUser, action: str):
|
async def verify_rights(request: Request,course_id: str, current_user: PublicUser, action: str):
|
||||||
courses = request.app.db["courses"]
|
courses = request.app.db["courses"]
|
||||||
|
|
||||||
course = courses.find_one({"course_id": course_id})
|
course = await courses.find_one({"course_id": course_id})
|
||||||
|
|
||||||
if not course:
|
if not course:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ class CollectionInDB(Collection):
|
||||||
async def get_collection(request: Request,collection_id: str, current_user: PublicUser):
|
async def get_collection(request: Request,collection_id: str, current_user: PublicUser):
|
||||||
collections = request.app.db["collections"]
|
collections = request.app.db["collections"]
|
||||||
|
|
||||||
collection = collections.find_one({"collection_id": collection_id})
|
collection = await collections.find_one({"collection_id": collection_id})
|
||||||
|
|
||||||
# verify collection rights
|
# verify collection rights
|
||||||
await verify_collection_rights(request, collection_id, current_user, "read")
|
await verify_collection_rights(request, collection_id, current_user, "read")
|
||||||
|
|
@ -47,7 +47,7 @@ async def create_collection(request: Request,collection_object: Collection, curr
|
||||||
collections = request.app.db["collections"]
|
collections = request.app.db["collections"]
|
||||||
|
|
||||||
# find if collection already exists using name
|
# find if collection already exists using name
|
||||||
isCollectionNameAvailable = collections.find_one(
|
isCollectionNameAvailable = await collections.find_one(
|
||||||
{"name": collection_object.name})
|
{"name": collection_object.name})
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
@ -63,7 +63,7 @@ async def create_collection(request: Request,collection_object: Collection, curr
|
||||||
collection = CollectionInDB(
|
collection = CollectionInDB(
|
||||||
collection_id=collection_id, **collection_object.dict())
|
collection_id=collection_id, **collection_object.dict())
|
||||||
|
|
||||||
collection_in_db = collections.insert_one(collection.dict())
|
collection_in_db = await collections.insert_one(collection.dict())
|
||||||
|
|
||||||
if not collection_in_db:
|
if not collection_in_db:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -79,7 +79,7 @@ async def update_collection(request: Request,collection_object: Collection, coll
|
||||||
|
|
||||||
collections = request.app.db["collections"]
|
collections = request.app.db["collections"]
|
||||||
|
|
||||||
collection = collections.find_one({"collection_id": collection_id})
|
collection = await collections.find_one({"collection_id": collection_id})
|
||||||
|
|
||||||
if not collection:
|
if not collection:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -88,7 +88,7 @@ async def update_collection(request: Request,collection_object: Collection, coll
|
||||||
updated_collection = CollectionInDB(
|
updated_collection = CollectionInDB(
|
||||||
collection_id=collection_id, **collection_object.dict())
|
collection_id=collection_id, **collection_object.dict())
|
||||||
|
|
||||||
collections.update_one({"collection_id": collection_id}, {
|
await collections.update_one({"collection_id": collection_id}, {
|
||||||
"$set": updated_collection.dict()})
|
"$set": updated_collection.dict()})
|
||||||
|
|
||||||
return Collection(**updated_collection.dict())
|
return Collection(**updated_collection.dict())
|
||||||
|
|
@ -100,13 +100,13 @@ async def delete_collection(request: Request,collection_id: str, current_user: P
|
||||||
|
|
||||||
collections = request.app.db["collections"]
|
collections = request.app.db["collections"]
|
||||||
|
|
||||||
collection = collections.find_one({"collection_id": collection_id})
|
collection = await collections.find_one({"collection_id": collection_id})
|
||||||
|
|
||||||
if not collection:
|
if not collection:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Collection does not exist")
|
status_code=status.HTTP_409_CONFLICT, detail="Collection does not exist")
|
||||||
|
|
||||||
isDeleted = collections.delete_one({"collection_id": collection_id})
|
isDeleted = await collections.delete_one({"collection_id": collection_id})
|
||||||
|
|
||||||
if isDeleted:
|
if isDeleted:
|
||||||
return {"detail": "collection deleted"}
|
return {"detail": "collection deleted"}
|
||||||
|
|
@ -129,7 +129,7 @@ async def get_collections(request: Request,page: int = 1, limit: int = 10):
|
||||||
|
|
||||||
# create list of collections and include courses in each collection
|
# create list of collections and include courses in each collection
|
||||||
collections_list = []
|
collections_list = []
|
||||||
for collection in all_collections:
|
for collection in await all_collections.to_list(length=100):
|
||||||
collection = CollectionInDB(**collection)
|
collection = CollectionInDB(**collection)
|
||||||
collections_list.append(collection)
|
collections_list.append(collection)
|
||||||
|
|
||||||
|
|
@ -140,7 +140,7 @@ async def get_collections(request: Request,page: int = 1, limit: int = 10):
|
||||||
collection.courses = courses.find(
|
collection.courses = courses.find(
|
||||||
{"course_id": {"$in": collection_courses}}, {'_id': 0})
|
{"course_id": {"$in": collection_courses}}, {'_id': 0})
|
||||||
|
|
||||||
collection.courses = [course for course in collection.courses]
|
collection.courses = [course for course in await collection.courses.to_list(length=100)]
|
||||||
|
|
||||||
return collections_list
|
return collections_list
|
||||||
|
|
||||||
|
|
@ -150,7 +150,7 @@ async def get_collections(request: Request,page: int = 1, limit: int = 10):
|
||||||
async def verify_collection_rights(request: Request,collection_id: str, current_user: PublicUser, action: str):
|
async def verify_collection_rights(request: Request,collection_id: str, current_user: PublicUser, action: str):
|
||||||
collections = request.app.db["collections"]
|
collections = request.app.db["collections"]
|
||||||
|
|
||||||
collection = collections.find_one({"collection_id": collection_id})
|
collection = await collections.find_one({"collection_id": collection_id})
|
||||||
|
|
||||||
if not collection and action != "create":
|
if not collection and action != "create":
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ class CourseChapterInDB(CourseChapter):
|
||||||
async def get_course(request: Request, course_id: str, current_user: PublicUser):
|
async def get_course(request: Request, course_id: str, current_user: PublicUser):
|
||||||
courses = request.app.db["courses"]
|
courses = request.app.db["courses"]
|
||||||
|
|
||||||
course = courses.find_one({"course_id": course_id})
|
course = await courses.find_one({"course_id": course_id})
|
||||||
|
|
||||||
# verify course rights
|
# verify course rights
|
||||||
await verify_rights(request, course_id, current_user, "read")
|
await verify_rights(request, course_id, current_user, "read")
|
||||||
|
|
@ -74,7 +74,7 @@ async def get_course_meta(request: Request, course_id: str, current_user: Public
|
||||||
coursechapters = request.app.db["coursechapters"]
|
coursechapters = request.app.db["coursechapters"]
|
||||||
activities = request.app.db["activities"]
|
activities = request.app.db["activities"]
|
||||||
|
|
||||||
course = courses.find_one({"course_id": course_id})
|
course = await courses.find_one({"course_id": course_id})
|
||||||
lectures = request.app.db["lectures"]
|
lectures = request.app.db["lectures"]
|
||||||
|
|
||||||
# verify course rights
|
# verify course rights
|
||||||
|
|
@ -92,7 +92,7 @@ async def get_course_meta(request: Request, course_id: str, current_user: Public
|
||||||
|
|
||||||
# chapters
|
# chapters
|
||||||
chapters = {}
|
chapters = {}
|
||||||
for coursechapter in coursechapters:
|
for coursechapter in await coursechapters.to_list(length=100):
|
||||||
coursechapter = CourseChapterInDB(**coursechapter)
|
coursechapter = CourseChapterInDB(**coursechapter)
|
||||||
coursechapter_lectureIds = []
|
coursechapter_lectureIds = []
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ async def get_course_meta(request: Request, course_id: str, current_user: Public
|
||||||
|
|
||||||
# lectures
|
# lectures
|
||||||
lectures_list = {}
|
lectures_list = {}
|
||||||
for lecture in lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}):
|
for lecture in await lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}).to_list(length=100):
|
||||||
lecture = LectureInDB(**lecture)
|
lecture = LectureInDB(**lecture)
|
||||||
lectures_list[lecture.lecture_id] = {
|
lectures_list[lecture.lecture_id] = {
|
||||||
"id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content
|
"id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content
|
||||||
|
|
@ -119,7 +119,7 @@ async def get_course_meta(request: Request, course_id: str, current_user: Public
|
||||||
course = Course(**course)
|
course = Course(**course)
|
||||||
|
|
||||||
# Get activity by user
|
# Get activity by user
|
||||||
activity = activities.find_one(
|
activity = await activities.find_one(
|
||||||
{"course_id": course_id, "user_id": current_user.user_id})
|
{"course_id": course_id, "user_id": current_user.user_id})
|
||||||
if activity:
|
if activity:
|
||||||
activity = json.loads(json.dumps(activity, default=str))
|
activity = json.loads(json.dumps(activity, default=str))
|
||||||
|
|
@ -155,7 +155,7 @@ async def create_course(request: Request, course_object: Course, org_id: str, cu
|
||||||
course = CourseInDB(course_id=course_id, authors=[
|
course = CourseInDB(course_id=course_id, authors=[
|
||||||
current_user.user_id], creationDate=str(datetime.now()), updateDate=str(datetime.now()), **course_object.dict())
|
current_user.user_id], creationDate=str(datetime.now()), updateDate=str(datetime.now()), **course_object.dict())
|
||||||
|
|
||||||
course_in_db = courses.insert_one(course.dict())
|
course_in_db = await courses.insert_one(course.dict())
|
||||||
|
|
||||||
if not course_in_db:
|
if not course_in_db:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -171,7 +171,7 @@ async def update_course_thumbnail(request: Request, course_id: str, current_user
|
||||||
|
|
||||||
courses = request.app.db["courses"]
|
courses = request.app.db["courses"]
|
||||||
|
|
||||||
course = courses.find_one({"course_id": course_id})
|
course = await courses.find_one({"course_id": course_id})
|
||||||
# TODO(fix) : the implementation here is clearly not the best one
|
# TODO(fix) : the implementation here is clearly not the best one
|
||||||
if course:
|
if course:
|
||||||
creationDate = course["creationDate"]
|
creationDate = course["creationDate"]
|
||||||
|
|
@ -184,7 +184,7 @@ async def update_course_thumbnail(request: Request, course_id: str, current_user
|
||||||
updated_course = CourseInDB(course_id=course_id, creationDate=creationDate,
|
updated_course = CourseInDB(course_id=course_id, creationDate=creationDate,
|
||||||
authors=authors, updateDate=str(datetime.now()), **course.dict())
|
authors=authors, updateDate=str(datetime.now()), **course.dict())
|
||||||
|
|
||||||
courses.update_one({"course_id": course_id}, {
|
await courses.update_one({"course_id": course_id}, {
|
||||||
"$set": updated_course.dict()})
|
"$set": updated_course.dict()})
|
||||||
|
|
||||||
return CourseInDB(**updated_course.dict())
|
return CourseInDB(**updated_course.dict())
|
||||||
|
|
@ -201,7 +201,7 @@ async def update_course(request: Request, course_object: Course, course_id: str,
|
||||||
|
|
||||||
courses = request.app.db["courses"]
|
courses = request.app.db["courses"]
|
||||||
|
|
||||||
course = courses.find_one({"course_id": course_id})
|
course = await courses.find_one({"course_id": course_id})
|
||||||
|
|
||||||
if course:
|
if course:
|
||||||
creationDate = course["creationDate"]
|
creationDate = course["creationDate"]
|
||||||
|
|
@ -213,7 +213,7 @@ async def update_course(request: Request, course_object: Course, course_id: str,
|
||||||
updated_course = CourseInDB(
|
updated_course = CourseInDB(
|
||||||
course_id=course_id, creationDate=creationDate, authors=authors, updateDate=str(datetime_object), **course_object.dict())
|
course_id=course_id, creationDate=creationDate, authors=authors, updateDate=str(datetime_object), **course_object.dict())
|
||||||
|
|
||||||
courses.update_one({"course_id": course_id}, {
|
await courses.update_one({"course_id": course_id}, {
|
||||||
"$set": updated_course.dict()})
|
"$set": updated_course.dict()})
|
||||||
|
|
||||||
return CourseInDB(**updated_course.dict())
|
return CourseInDB(**updated_course.dict())
|
||||||
|
|
@ -230,13 +230,13 @@ async def delete_course(request: Request, course_id: str, current_user: PublicUs
|
||||||
|
|
||||||
courses = request.app.db["courses"]
|
courses = request.app.db["courses"]
|
||||||
|
|
||||||
course = courses.find_one({"course_id": course_id})
|
course = await courses.find_one({"course_id": course_id})
|
||||||
|
|
||||||
if not course:
|
if not course:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Course does not exist")
|
status_code=status.HTTP_409_CONFLICT, detail="Course does not exist")
|
||||||
|
|
||||||
isDeleted = courses.delete_one({"course_id": course_id})
|
isDeleted = await courses.delete_one({"course_id": course_id})
|
||||||
|
|
||||||
if isDeleted:
|
if isDeleted:
|
||||||
return {"detail": "Course deleted"}
|
return {"detail": "Course deleted"}
|
||||||
|
|
@ -256,7 +256,7 @@ async def get_courses(request: Request, page: int = 1, limit: int = 10, org_id:
|
||||||
all_courses = courses.find({"org_id": org_id}).sort(
|
all_courses = courses.find({"org_id": org_id}).sort(
|
||||||
"name", 1).skip(10 * (page - 1)).limit(limit)
|
"name", 1).skip(10 * (page - 1)).limit(limit)
|
||||||
|
|
||||||
return [json.loads(json.dumps(course, default=str)) for course in all_courses]
|
return [json.loads(json.dumps(course, default=str)) for course in await all_courses.to_list(length=100)]
|
||||||
|
|
||||||
async def get_courses_orgslug(request: Request, page: int = 1, limit: int = 10, org_slug: str | None = None):
|
async def get_courses_orgslug(request: Request, page: int = 1, limit: int = 10, org_slug: str | None = None):
|
||||||
courses = request.app.db["courses"]
|
courses = request.app.db["courses"]
|
||||||
|
|
@ -264,7 +264,7 @@ async def get_courses_orgslug(request: Request, page: int = 1, limit: int = 10,
|
||||||
# TODO : Get only courses that user is admin/has roles of
|
# TODO : Get only courses that user is admin/has roles of
|
||||||
|
|
||||||
# get org_id from slug
|
# get org_id from slug
|
||||||
org = orgs.find_one({"slug": org_slug})
|
org = await orgs.find_one({"slug": org_slug})
|
||||||
|
|
||||||
if not org:
|
if not org:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -274,7 +274,7 @@ async def get_courses_orgslug(request: Request, page: int = 1, limit: int = 10,
|
||||||
all_courses = courses.find({"org_id": org['org_id']}).sort(
|
all_courses = courses.find({"org_id": org['org_id']}).sort(
|
||||||
"name", 1).skip(10 * (page - 1)).limit(limit)
|
"name", 1).skip(10 * (page - 1)).limit(limit)
|
||||||
|
|
||||||
return [json.loads(json.dumps(course, default=str)) for course in all_courses]
|
return [json.loads(json.dumps(course, default=str)) for course in await all_courses.to_list(length=100)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -284,7 +284,7 @@ async def get_courses_orgslug(request: Request, page: int = 1, limit: int = 10,
|
||||||
async def verify_rights(request: Request, course_id: str, current_user: PublicUser, action: str):
|
async def verify_rights(request: Request, course_id: str, current_user: PublicUser, action: str):
|
||||||
courses = request.app.db["courses"]
|
courses = request.app.db["courses"]
|
||||||
|
|
||||||
course = courses.find_one({"course_id": course_id})
|
course = await courses.find_one({"course_id": course_id})
|
||||||
|
|
||||||
if not course:
|
if not course:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,10 @@ async def create_lecture(request: Request,lecture_object: Lecture, coursechapter
|
||||||
# create lecture
|
# create lecture
|
||||||
lecture = LectureInDB(**lecture_object.dict(), creationDate=str(
|
lecture = LectureInDB(**lecture_object.dict(), creationDate=str(
|
||||||
datetime.now()), coursechapter_id=coursechapter_id, updateDate=str(datetime.now()), lecture_id=lecture_id)
|
datetime.now()), coursechapter_id=coursechapter_id, updateDate=str(datetime.now()), lecture_id=lecture_id)
|
||||||
lectures.insert_one(lecture.dict())
|
await lectures.insert_one(lecture.dict())
|
||||||
|
|
||||||
# update chapter
|
# update chapter
|
||||||
coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
|
await coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
|
||||||
"$addToSet": {"lectures": lecture_id}})
|
"$addToSet": {"lectures": lecture_id}})
|
||||||
|
|
||||||
return lecture
|
return lecture
|
||||||
|
|
@ -56,7 +56,7 @@ async def create_lecture(request: Request,lecture_object: Lecture, coursechapter
|
||||||
async def get_lecture(request: Request,lecture_id: str, current_user: PublicUser):
|
async def get_lecture(request: Request,lecture_id: str, current_user: PublicUser):
|
||||||
lectures = request.app.db["lectures"]
|
lectures = request.app.db["lectures"]
|
||||||
|
|
||||||
lecture = lectures.find_one({"lecture_id": lecture_id})
|
lecture = await lectures.find_one({"lecture_id": lecture_id})
|
||||||
|
|
||||||
# verify course rights
|
# verify course rights
|
||||||
hasRoleRights = await verify_user_rights_with_roles(request,"read", current_user.user_id, lecture_id)
|
hasRoleRights = await verify_user_rights_with_roles(request,"read", current_user.user_id, lecture_id)
|
||||||
|
|
@ -80,7 +80,7 @@ async def update_lecture(request: Request,lecture_object: Lecture, lecture_id: s
|
||||||
|
|
||||||
lectures = request.app.db["lectures"]
|
lectures = request.app.db["lectures"]
|
||||||
|
|
||||||
lecture = lectures.find_one({"lecture_id": lecture_id})
|
lecture = await lectures.find_one({"lecture_id": lecture_id})
|
||||||
|
|
||||||
if lecture:
|
if lecture:
|
||||||
creationDate = lecture["creationDate"]
|
creationDate = lecture["creationDate"]
|
||||||
|
|
@ -91,7 +91,7 @@ async def update_lecture(request: Request,lecture_object: Lecture, lecture_id: s
|
||||||
updated_course = LectureInDB(
|
updated_course = LectureInDB(
|
||||||
lecture_id=lecture_id, coursechapter_id=lecture["coursechapter_id"], creationDate=creationDate, updateDate=str(datetime_object), **lecture_object.dict())
|
lecture_id=lecture_id, coursechapter_id=lecture["coursechapter_id"], creationDate=creationDate, updateDate=str(datetime_object), **lecture_object.dict())
|
||||||
|
|
||||||
lectures.update_one({"lecture_id": lecture_id}, {
|
await lectures.update_one({"lecture_id": lecture_id}, {
|
||||||
"$set": updated_course.dict()})
|
"$set": updated_course.dict()})
|
||||||
|
|
||||||
return LectureInDB(**updated_course.dict())
|
return LectureInDB(**updated_course.dict())
|
||||||
|
|
@ -108,13 +108,13 @@ async def delete_lecture(request: Request,lecture_id: str, current_user: PublicU
|
||||||
|
|
||||||
lectures = request.app.db["lectures"]
|
lectures = request.app.db["lectures"]
|
||||||
|
|
||||||
lecture = lectures.find_one({"lecture_id": lecture_id})
|
lecture = await lectures.find_one({"lecture_id": lecture_id})
|
||||||
|
|
||||||
if not lecture:
|
if not lecture:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="lecture does not exist")
|
status_code=status.HTTP_409_CONFLICT, detail="lecture does not exist")
|
||||||
|
|
||||||
isDeleted = lectures.delete_one({"lecture_id": lecture_id})
|
isDeleted = await lectures.delete_one({"lecture_id": lecture_id})
|
||||||
|
|
||||||
if isDeleted:
|
if isDeleted:
|
||||||
return {"detail": "lecture deleted"}
|
return {"detail": "lecture deleted"}
|
||||||
|
|
@ -137,11 +137,8 @@ async def get_lectures(request: Request,coursechapter_id: str, current_user: Pub
|
||||||
|
|
||||||
if not lectures:
|
if not lectures:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="No lectures found")
|
status_code=status.HTTP_409_CONFLICT, detail="Course does not exist")
|
||||||
|
|
||||||
lectures_list = []
|
lectures = [LectureInDB(**lecture) for lecture in await lectures.to_list(length=100)]
|
||||||
|
|
||||||
for lecture in lectures:
|
return lectures
|
||||||
lectures_list.append(Lecture(**lecture))
|
|
||||||
|
|
||||||
return lectures_list
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ async def create_video_lecture(request: Request,name: str, coursechapter_id: st
|
||||||
|
|
||||||
# create lecture
|
# create lecture
|
||||||
lecture = LectureInDB(**lecture_object.dict())
|
lecture = LectureInDB(**lecture_object.dict())
|
||||||
lectures.insert_one(lecture.dict())
|
await lectures.insert_one(lecture.dict())
|
||||||
|
|
||||||
# upload video
|
# upload video
|
||||||
if video_file:
|
if video_file:
|
||||||
|
|
@ -55,7 +55,7 @@ async def create_video_lecture(request: Request,name: str, coursechapter_id: st
|
||||||
|
|
||||||
# todo : choose whether to update the chapter or not
|
# todo : choose whether to update the chapter or not
|
||||||
# update chapter
|
# update chapter
|
||||||
coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
|
await coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
|
||||||
"$addToSet": {"lectures": lecture_id}})
|
"$addToSet": {"lectures": lecture_id}})
|
||||||
|
|
||||||
return lecture
|
return lecture
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ async def get_houses(request: Request,page: int = 1, limit: int = 10):
|
||||||
# get all houses from database
|
# get all houses from database
|
||||||
all_houses = houses.find().sort("name", 1).skip(10 * (page - 1)).limit(limit)
|
all_houses = houses.find().sort("name", 1).skip(10 * (page - 1)).limit(limit)
|
||||||
|
|
||||||
return [json.loads(json.dumps(house, default=str)) for house in all_houses]
|
return [json.loads(json.dumps(house, default=str)) for house in await all_houses.to_list(length=limit)]
|
||||||
|
|
||||||
|
|
||||||
#### Security ####################################################
|
#### Security ####################################################
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ async def create_initial_data(request: Request):
|
||||||
########################################
|
########################################
|
||||||
|
|
||||||
database_users = request.app.db["users"]
|
database_users = request.app.db["users"]
|
||||||
database_users.delete_many({})
|
await database_users.delete_many({})
|
||||||
|
|
||||||
users = []
|
users = []
|
||||||
admin_user = UserWithPassword(
|
admin_user = UserWithPassword(
|
||||||
|
|
@ -53,7 +53,7 @@ async def create_initial_data(request: Request):
|
||||||
|
|
||||||
# find admin user
|
# find admin user
|
||||||
users = request.app.db["users"]
|
users = request.app.db["users"]
|
||||||
admin_user = users.find_one({"username": "admin"})
|
admin_user = await users.find_one({"username": "admin"})
|
||||||
|
|
||||||
if admin_user:
|
if admin_user:
|
||||||
admin_user = UserInDB(**admin_user)
|
admin_user = UserInDB(**admin_user)
|
||||||
|
|
@ -65,7 +65,7 @@ async def create_initial_data(request: Request):
|
||||||
########################################
|
########################################
|
||||||
|
|
||||||
database_orgs = request.app.db["organizations"]
|
database_orgs = request.app.db["organizations"]
|
||||||
database_orgs.delete_many({})
|
await database_orgs.delete_many({})
|
||||||
|
|
||||||
organizations = []
|
organizations = []
|
||||||
for i in range(0, 5):
|
for i in range(0, 5):
|
||||||
|
|
@ -85,7 +85,7 @@ async def create_initial_data(request: Request):
|
||||||
########################################
|
########################################
|
||||||
|
|
||||||
database_roles = request.app.db["roles"]
|
database_roles = request.app.db["roles"]
|
||||||
database_roles.delete_many({})
|
await database_roles.delete_many({})
|
||||||
|
|
||||||
roles = []
|
roles = []
|
||||||
admin_role = Role(
|
admin_role = Role(
|
||||||
|
|
@ -117,14 +117,14 @@ async def create_initial_data(request: Request):
|
||||||
|
|
||||||
database_courses = request.app.db["courses"]
|
database_courses = request.app.db["courses"]
|
||||||
database_chapters = request.app.db["coursechapters"]
|
database_chapters = request.app.db["coursechapters"]
|
||||||
database_courses.delete_many({})
|
await database_courses.delete_many({})
|
||||||
database_chapters.delete_many({})
|
await database_chapters.delete_many({})
|
||||||
|
|
||||||
courses = []
|
courses = []
|
||||||
orgs = request.app.db["organizations"]
|
orgs = request.app.db["organizations"]
|
||||||
|
|
||||||
if orgs.count_documents({}) > 0:
|
if await orgs.count_documents({}) > 0:
|
||||||
for org in orgs.find():
|
for org in await orgs.find().to_list(length=100):
|
||||||
for i in range(0, 5):
|
for i in range(0, 5):
|
||||||
|
|
||||||
# get image in BinaryIO format from unsplash and save it to disk
|
# get image in BinaryIO format from unsplash and save it to disk
|
||||||
|
|
@ -161,7 +161,7 @@ async def create_initial_data(request: Request):
|
||||||
course.thumbnail = name_in_disk
|
course.thumbnail = name_in_disk
|
||||||
|
|
||||||
course = CourseInDB(**course.dict())
|
course = CourseInDB(**course.dict())
|
||||||
course_in_db = courses.insert_one(course.dict())
|
course_in_db = await courses.insert_one(course.dict())
|
||||||
|
|
||||||
# create chapters
|
# create chapters
|
||||||
for i in range(0, 5):
|
for i in range(0, 5):
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class PublicOrganization(Organization):
|
||||||
async def get_organization(request: Request, org_id: str):
|
async def get_organization(request: Request, org_id: str):
|
||||||
orgs = request.app.db["organizations"]
|
orgs = request.app.db["organizations"]
|
||||||
|
|
||||||
org = orgs.find_one({"org_id": org_id})
|
org = await orgs.find_one({"org_id": org_id})
|
||||||
|
|
||||||
if not org:
|
if not org:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -50,7 +50,7 @@ async def get_organization(request: Request, org_id: str):
|
||||||
async def get_organization_by_slug(request: Request, org_slug: str):
|
async def get_organization_by_slug(request: Request, org_slug: str):
|
||||||
orgs = request.app.db["organizations"]
|
orgs = request.app.db["organizations"]
|
||||||
|
|
||||||
org = orgs.find_one({"slug": org_slug})
|
org = await orgs.find_one({"slug": org_slug})
|
||||||
|
|
||||||
if not org:
|
if not org:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -64,7 +64,7 @@ async def create_org(request: Request, org_object: Organization, current_user: P
|
||||||
orgs = request.app.db["organizations"]
|
orgs = request.app.db["organizations"]
|
||||||
|
|
||||||
# find if org already exists using name
|
# find if org already exists using name
|
||||||
isOrgAvailable = orgs.find_one({"slug": org_object.slug})
|
isOrgAvailable = await orgs.find_one({"slug": org_object.slug})
|
||||||
|
|
||||||
if isOrgAvailable:
|
if isOrgAvailable:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -77,7 +77,7 @@ async def create_org(request: Request, org_object: Organization, current_user: P
|
||||||
current_user.user_id], admins=[
|
current_user.user_id], admins=[
|
||||||
current_user.user_id], **org_object.dict())
|
current_user.user_id], **org_object.dict())
|
||||||
|
|
||||||
org_in_db = orgs.insert_one(org.dict())
|
org_in_db = await orgs.insert_one(org.dict())
|
||||||
|
|
||||||
if not org_in_db:
|
if not org_in_db:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -93,7 +93,7 @@ async def update_org(request: Request, org_object: Organization, org_id: str, cu
|
||||||
|
|
||||||
orgs = request.app.db["organizations"]
|
orgs = request.app.db["organizations"]
|
||||||
|
|
||||||
org = orgs.find_one({"org_id": org_id})
|
org = await orgs.find_one({"org_id": org_id})
|
||||||
|
|
||||||
if org:
|
if org:
|
||||||
owners = org["owners"]
|
owners = org["owners"]
|
||||||
|
|
@ -106,7 +106,7 @@ async def update_org(request: Request, org_object: Organization, org_id: str, cu
|
||||||
updated_org = OrganizationInDB(
|
updated_org = OrganizationInDB(
|
||||||
org_id=org_id, owners=owners, admins=admins, **org_object.dict())
|
org_id=org_id, owners=owners, admins=admins, **org_object.dict())
|
||||||
|
|
||||||
orgs.update_one({"org_id": org_id}, {"$set": updated_org.dict()})
|
await orgs.update_one({"org_id": org_id}, {"$set": updated_org.dict()})
|
||||||
|
|
||||||
return Organization(**updated_org.dict())
|
return Organization(**updated_org.dict())
|
||||||
|
|
||||||
|
|
@ -117,13 +117,13 @@ async def delete_org(request: Request, org_id: str, current_user: PublicUser):
|
||||||
|
|
||||||
orgs = request.app.db["organizations"]
|
orgs = request.app.db["organizations"]
|
||||||
|
|
||||||
org = orgs.find_one({"org_id": org_id})
|
org = await orgs.find_one({"org_id": org_id})
|
||||||
|
|
||||||
if not org:
|
if not org:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist")
|
status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist")
|
||||||
|
|
||||||
isDeleted = orgs.delete_one({"org_id": org_id})
|
isDeleted = await orgs.delete_one({"org_id": org_id})
|
||||||
|
|
||||||
if isDeleted:
|
if isDeleted:
|
||||||
return {"detail": "Org deleted"}
|
return {"detail": "Org deleted"}
|
||||||
|
|
@ -137,9 +137,9 @@ async def get_orgs_by_user(request: Request, user_id: str, page: int = 1, limit:
|
||||||
|
|
||||||
# find all orgs where user_id is in owners or admins arrays
|
# find all orgs where user_id is in owners or admins arrays
|
||||||
all_orgs = orgs.find({"$or": [{"owners": user_id}, {"admins": user_id}]}).sort(
|
all_orgs = orgs.find({"$or": [{"owners": user_id}, {"admins": user_id}]}).sort(
|
||||||
"name", 1).skip(10 * (page - 1)).limit(limit)
|
"name", 1).skip(10 * (page - 1)).limit(100)
|
||||||
|
|
||||||
return [json.loads(json.dumps(org, default=str)) for org in all_orgs]
|
return [json.loads(json.dumps(org, default=str)) for org in await all_orgs.to_list(length=100)]
|
||||||
|
|
||||||
|
|
||||||
#### Security ####################################################
|
#### Security ####################################################
|
||||||
|
|
@ -147,7 +147,7 @@ async def get_orgs_by_user(request: Request, user_id: str, page: int = 1, limit:
|
||||||
async def verify_org_rights(request: Request, org_id: str, current_user: PublicUser, action: str,):
|
async def verify_org_rights(request: Request, org_id: str, current_user: PublicUser, action: str,):
|
||||||
orgs = request.app.db["organizations"]
|
orgs = request.app.db["organizations"]
|
||||||
|
|
||||||
org = orgs.find_one({"org_id": org_id})
|
org = await orgs.find_one({"org_id": org_id})
|
||||||
|
|
||||||
if not org:
|
if not org:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class RoleInDB(Role):
|
||||||
async def get_role(request: Request,role_id: str):
|
async def get_role(request: Request,role_id: str):
|
||||||
roles = request.app.db["roles"]
|
roles = request.app.db["roles"]
|
||||||
|
|
||||||
role = roles.find_one({"role_id": role_id})
|
role = await roles.find_one({"role_id": role_id})
|
||||||
|
|
||||||
if not role:
|
if not role:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -61,7 +61,7 @@ async def create_role(request: Request,role_object: Role, current_user: PublicUs
|
||||||
roles = request.app.db["roles"]
|
roles = request.app.db["roles"]
|
||||||
|
|
||||||
# find if house already exists using name
|
# find if house already exists using name
|
||||||
isRoleAvailable = roles.find_one({"name": role_object.name})
|
isRoleAvailable = await roles.find_one({"name": role_object.name})
|
||||||
|
|
||||||
if isRoleAvailable:
|
if isRoleAvailable:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -75,7 +75,7 @@ async def create_role(request: Request,role_object: Role, current_user: PublicUs
|
||||||
role = RoleInDB(role_id=role_id, creationDate=str(datetime.now()),
|
role = RoleInDB(role_id=role_id, creationDate=str(datetime.now()),
|
||||||
updateDate=str(datetime.now()), **role_object.dict())
|
updateDate=str(datetime.now()), **role_object.dict())
|
||||||
|
|
||||||
role_in_db = roles.insert_one(role.dict())
|
role_in_db = await roles.insert_one(role.dict())
|
||||||
|
|
||||||
if not role_in_db:
|
if not role_in_db:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -91,7 +91,7 @@ async def update_role(request: Request,role_object: Role, role_id: str, current_
|
||||||
|
|
||||||
roles = request.app.db["roles"]
|
roles = request.app.db["roles"]
|
||||||
|
|
||||||
role = roles.find_one({"role_id": role_id})
|
role = await roles.find_one({"role_id": role_id})
|
||||||
|
|
||||||
if not role:
|
if not role:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -100,7 +100,7 @@ async def update_role(request: Request,role_object: Role, role_id: str, current_
|
||||||
updated_role = RoleInDB(
|
updated_role = RoleInDB(
|
||||||
role_id=role_id, updateDate=str(datetime.now()), creationDate=role["creationDate"], **role_object.dict())
|
role_id=role_id, updateDate=str(datetime.now()), creationDate=role["creationDate"], **role_object.dict())
|
||||||
|
|
||||||
roles.update_one({"role_id": role_id}, {"$set": updated_role.dict()})
|
await roles.update_one({"role_id": role_id}, {"$set": updated_role.dict()})
|
||||||
|
|
||||||
return RoleInDB(**updated_role.dict())
|
return RoleInDB(**updated_role.dict())
|
||||||
|
|
||||||
|
|
@ -112,13 +112,13 @@ async def delete_role(request: Request,role_id: str, current_user: PublicUser):
|
||||||
|
|
||||||
roles = request.app.db["roles"]
|
roles = request.app.db["roles"]
|
||||||
|
|
||||||
role = roles.find_one({"role_id": role_id})
|
role = await roles.find_one({"role_id": role_id})
|
||||||
|
|
||||||
if not role:
|
if not role:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Role does not exist")
|
status_code=status.HTTP_409_CONFLICT, detail="Role does not exist")
|
||||||
|
|
||||||
isDeleted = roles.delete_one({"role_id": role_id})
|
isDeleted = await roles.delete_one({"role_id": role_id})
|
||||||
|
|
||||||
if isDeleted:
|
if isDeleted:
|
||||||
return {"detail": "Role deleted"}
|
return {"detail": "Role deleted"}
|
||||||
|
|
@ -133,7 +133,7 @@ async def get_roles(request: Request,page: int = 1, limit: int = 10):
|
||||||
# get all roles from database
|
# get all roles from database
|
||||||
all_roles = roles.find().sort("name", 1).skip(10 * (page - 1)).limit(limit)
|
all_roles = roles.find().sort("name", 1).skip(10 * (page - 1)).limit(limit)
|
||||||
|
|
||||||
return [json.loads(json.dumps(role, default=str)) for role in all_roles]
|
return [json.loads(json.dumps(role, default=str)) for role in await all_roles.to_list(length=limit)]
|
||||||
|
|
||||||
|
|
||||||
#### Security ####################################################
|
#### Security ####################################################
|
||||||
|
|
@ -141,7 +141,7 @@ async def get_roles(request: Request,page: int = 1, limit: int = 10):
|
||||||
async def verify_user_permissions_on_roles(request: Request,action: str, current_user: PublicUser):
|
async def verify_user_permissions_on_roles(request: Request,action: str, current_user: PublicUser):
|
||||||
users = request.app.db["users"]
|
users = request.app.db["users"]
|
||||||
|
|
||||||
user = users.find_one({"user_id": current_user.user_id})
|
user = await users.find_one({"user_id": current_user.user_id})
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ async def verify_user_rights_with_roles(request: Request,action: str, user_id: s
|
||||||
|
|
||||||
# Info: permission actions are: read, create, delete, update
|
# Info: permission actions are: read, create, delete, update
|
||||||
|
|
||||||
for role in user_roles_cursor:
|
for role in await user_roles_cursor.to_list(length=100):
|
||||||
user_roles.append(role)
|
user_roles.append(role)
|
||||||
|
|
||||||
for role in user_roles:
|
for role in user_roles:
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ class Role(BaseModel):
|
||||||
async def get_user(request: Request, username: str):
|
async def get_user(request: Request, username: str):
|
||||||
users = request.app.db["users"]
|
users = request.app.db["users"]
|
||||||
|
|
||||||
user = users.find_one({"username": username})
|
user = await users.find_one({"username": username})
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -71,7 +71,7 @@ async def get_profile_metadata(request: Request, user):
|
||||||
users = request.app.db["users"]
|
users = request.app.db["users"]
|
||||||
roles = request.app.db["roles"]
|
roles = request.app.db["roles"]
|
||||||
|
|
||||||
user = users.find_one({"user_id": user['user_id']})
|
user = await users.find_one({"user_id": user['user_id']})
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -81,7 +81,7 @@ async def get_profile_metadata(request: Request, user):
|
||||||
user_roles = roles.find({"linked_users": user['user_id']})
|
user_roles = roles.find({"linked_users": user['user_id']})
|
||||||
|
|
||||||
user_roles_list = []
|
user_roles_list = []
|
||||||
for role in user_roles:
|
for role in await user_roles.to_list(length=100):
|
||||||
print(role)
|
print(role)
|
||||||
user_roles_list.append(Role(**role))
|
user_roles_list.append(Role(**role))
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ async def get_profile_metadata(request: Request, user):
|
||||||
async def get_user_by_userid(request: Request, user_id: str):
|
async def get_user_by_userid(request: Request, user_id: str):
|
||||||
users = request.app.db["users"]
|
users = request.app.db["users"]
|
||||||
|
|
||||||
user = users.find_one({"user_id": user_id})
|
user = await users.find_one({"user_id": user_id})
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -107,7 +107,7 @@ async def get_user_by_userid(request: Request, user_id: str):
|
||||||
async def security_get_user(request: Request, email: str):
|
async def security_get_user(request: Request, email: str):
|
||||||
users = request.app.db["users"]
|
users = request.app.db["users"]
|
||||||
|
|
||||||
user = users.find_one({"email": email})
|
user = await users.find_one({"email": email})
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -119,7 +119,7 @@ async def security_get_user(request: Request, email: str):
|
||||||
async def get_userid_by_username(request: Request, username: str):
|
async def get_userid_by_username(request: Request, username: str):
|
||||||
users = request.app.db["users"]
|
users = request.app.db["users"]
|
||||||
|
|
||||||
user = users.find_one({"username": username})
|
user = await users.find_one({"username": username})
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -131,8 +131,8 @@ async def get_userid_by_username(request: Request, username: str):
|
||||||
async def update_user(request: Request, user_id: str, user_object: UserWithPassword):
|
async def update_user(request: Request, user_id: str, user_object: UserWithPassword):
|
||||||
users = request.app.db["users"]
|
users = request.app.db["users"]
|
||||||
|
|
||||||
isUserExists = users.find_one({"user_id": user_id})
|
isUserExists = await users.find_one({"user_id": user_id})
|
||||||
isUsernameAvailable = users.find_one({"username": user_object.username})
|
isUsernameAvailable = await users.find_one({"username": user_object.username})
|
||||||
|
|
||||||
if not isUserExists:
|
if not isUserExists:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -153,7 +153,7 @@ async def update_user(request: Request, user_id: str, user_object: UserWithPassw
|
||||||
async def delete_user(request: Request, user_id: str):
|
async def delete_user(request: Request, user_id: str):
|
||||||
users = request.app.db["users"]
|
users = request.app.db["users"]
|
||||||
|
|
||||||
isUserAvailable = users.find_one({"user_id": user_id})
|
isUserAvailable = await users.find_one({"user_id": user_id})
|
||||||
|
|
||||||
if not isUserAvailable:
|
if not isUserAvailable:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -167,7 +167,7 @@ async def delete_user(request: Request, user_id: str):
|
||||||
async def create_user(request: Request, user_object: UserWithPassword):
|
async def create_user(request: Request, user_object: UserWithPassword):
|
||||||
users = request.app.db["users"]
|
users = request.app.db["users"]
|
||||||
|
|
||||||
isUserAvailable = users.find_one({"username": user_object.username})
|
isUserAvailable = await users.find_one({"username": user_object.username})
|
||||||
|
|
||||||
if isUserAvailable:
|
if isUserAvailable:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -184,6 +184,6 @@ async def create_user(request: Request, user_object: UserWithPassword):
|
||||||
user = UserInDB(user_id=user_id, creationDate=str(datetime.now()),
|
user = UserInDB(user_id=user_id, creationDate=str(datetime.now()),
|
||||||
updateDate=str(datetime.now()), **user_object.dict())
|
updateDate=str(datetime.now()), **user_object.dict())
|
||||||
|
|
||||||
user_in_db = users.insert_one(user.dict())
|
user_in_db = await users.insert_one(user.dict())
|
||||||
|
|
||||||
return User(**user.dict())
|
return User(**user.dict())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue