Closed skiffter1337 closed 1 year ago
Huh, interesting. Does that project happen to be open-source, or could you post the code of the component that uses
I'm using it in a large piece of code that renders different types of exercises(exerciseTypes.PUZZLE). Not an open-source project.
import React, {useState, useEffect, useRef, useContext} from 'react'; import {observer} from 'mobx-react'; import {superAxiosRequest} from 'axiosApi'; import {localisationMaster} from "Localisation/Localisation"; import {move} from "components/Modules/Ebook/functions" import {checkPermList} from "helpers"; import {permissions} from "settings/permissions"; import Stores from "Stores"; import asideModalStore from "Stores/asideModalStore"; import EbookChapterStore, {exerciseTypes} from 'Stores/ebookChapterStore'; import cogoToast from "cogo-toast"; import swal from "sweetalert"; import ModalExercise from "components/ContentBox/Global/GlobalModalSingle/templates/Ebooks/ModalExercise/ModalExercise"; import { QuestionImagesList, QuestionImagesThumb, QuestionSimpleText, QuestionUploadedVideo, QuestionAttention, } from 'components/ContentBox/Lessons/questions'; import { ImagesCarousel, EnterWords, SelectWords, DragWords, MatchWords, ImagesMatchText, MakeSentence, MakeSentences, MakeWord, MakeWords, QuestionAudios, QuestionTest, SimpleLink, VideoLinks, WritingEssay, GroupWords } from "./types" import {LessonContext} from "../../BookChapter/LessonContext"; import LessonTeacherStore from "components/Modules/Ebook/LessonTeacher/lessonTeacherStore"; import LessonStudentStore from "components/Modules/Ebook/LessonStudent/lessonStudentStore"; import AssignExercise from "components/ContentBox/Global/GlobalModalSingle/templates/Ebooks/AssignExercise"; import ExerciseHeader from "./components/ExerciseHeader"; import {MainExerciseImage} from "../MainExerciseImage/MainExerciseImage"; import SideMenuEbook from '../SideMenuEbook/SideMenuEbook'; import GradeRow from '../GradeRow/GradeRow'; import ExerciseEditPanel from "./components/ExerciseEditPanel"; import ExerciseAttemptsPanel from "components/Modules/Ebook/LessonStudent/ExerciseAttemptsPanel"; import st from "./Exercise.module.scss"; import AccentSaveAnswer from "../../LessonStudent/AccentSaveAnswer"; import WriteText from "./types/WriteText"; import ExerciseTitle from "./components/ExerciseTitle"; import OrderSentences from "./types/OrderSentences"; import ChooseSentencesForm from "./types/ChooseSentencesForm/ChooseSentencesForm"; import QuestionExample from "../../../../ContentBox/Lessons/questions/QuestionExample/QuestionExample"; import ImagesWriteText from "./types/ImagesWriteText"; import ImagesSelectText from "./types/ImagesSelectText"; import Crossword from "./types/Crossword"; import {Puzzle} from "./types/Puzzle/Puzzle";
const questionsWithAnswers = [ exerciseTypes.ESSAY, exerciseTypes.ENTER_WORDS, exerciseTypes.CROSSWORD, exerciseTypes.ORDER_SENTENCES, exerciseTypes.MAKE_SENTENCE, exerciseTypes.MAKE_SENTENCES, exerciseTypes.MAKE_WORD, exerciseTypes.MAKE_WORDS, exerciseTypes.CHOOSE_SENTENCES_FORM, exerciseTypes.WRITE_WORDS, exerciseTypes.WRITE_PHRASES, exerciseTypes.SELECT_WORDS, exerciseTypes.GROUP_WORDS, exerciseTypes.MATCH_WORDS_IMAGES, exerciseTypes.MATCH_WORDS, exerciseTypes.TEST, ]
const Exercise = ({translate, ex, ...props}) => { const refEx = useRef();
const {setSection, updateExercise, removeExercise, addExercise} = EbookChapterStore const {chapter, assignExercisesData, assignExercises, assignExercise, inHomework, addHomework} = LessonTeacherStore const {lessonData, lesson, addExAnswers, dropFocus, inFavorites} = LessonStudentStore
const context = useContext(LessonContext)
const isTeacher = checkPermList(permissions.add_init_lesson) const isStudent = Stores.isClient
const section = EbookChapterStore.section || LessonTeacherStore.section
const isResponseRequired = questionsWithAnswers.includes(ex.type_exercise) const [student, setStudent] = useState(null) const [answers, setAnswers] = useState([]) const [sendAnswersButtonActive, setSendAnswersButtonActive] = useState(true) const [activeTry, setActiveTry] = useState(1) const [attempts, setAttempts] = useState([])
// ΠΠΎΠΊΠΎΠ²ΡΠ΅ ΠΌΠ΅Π½Ρ Π΄Π»Ρ ΡΠ°Π·Π»ΠΈΡΠ½ΡΡ ΡΠ΅ΠΆΠΈΠΌΠΎΠ² const sideMenuSetting = [ // Π£ΡΠΈΡΠ΅Π»Ρ Π½Π° ΡΡΠΎΠΊΠ΅ [ {type: 'select_student', text: translate?.provide_exercise, action: () => teacherAction('show')}, {type: 'focus', text: translate?.focus, action:() => teacherAction('focus')}, ...(isResponseRequired && ex.type_exercise !== (exerciseTypes.ESSAY || exerciseTypes.ENTER_WORDS) ? [{ type: 'checkbox', text: translate?.show_answers, action: () => teacherAction('showRightAnswers') }] : []), { type: 'home', text: translate?.add_to_homework, isPressed: inHomework(ex.id), action: () => teacherAction('homework') }, ], // Π£ΡΠΈΡΠ΅Π»Ρ Π½Π° ΡΡΠΎΠΊΠ΅: ΠΡΠ±ΠΎΡ ΡΡΠ΅Π½ΠΈΠΊΠ° [ {type: 'users', text: translate?.select_student}, ], // Π£ΡΠ΅Π½ΠΈΠΊ Π½Π° ΡΡΠΎΠΊΠ΅ [ { type: 'save', text: translate?.save_answer, action: () => sendAnswersButtonActive && saveTry(), isDisabled: !sendAnswersButtonActive }, ], [ ...(inFavorites(ex.id) ? [{ type: 'dislike', text: "Dislike", isPressed: true, action: () => studentAction('remove_from_favorites') }] : [{ type: 'like', text: translate?.add_to_favorites, action: () => studentAction('add_to_favorites') }]) ], [ { type: 'delete_homework', text: translate?.delete, action: props.deleteExerciseFromHomework }, ], ]
// Π£ΡΠ»ΠΎΠ²ΠΈΡ, ΠΏΡΠΈ ΠΊΠΎΡΠΎΡΡΡ Π½Π΅ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ°Π΅ΡΡΡ Π³Π»Π°Π²Π½Π°Ρ ΠΊΠ°ΡΡΠΈΠ½ΠΊΠ° ΠΈ ΡΠ΅ΠΊΡΡ Π² Π½Π΅ΠΊΠΎΡΠΎΡΡΡ ΡΠΏΡΠ°ΠΆΠ½Π΅Π½ΠΈΡΡ const dontShowImageAndTextCond = ex.type_exercise !== exerciseTypes.ATTENTION
const dataForExTemplate = { isStudent: isStudent, isTeacher: isTeacher, is_teacher_view: isTeacher, // Π΄ΡΠ±Π»Ρ try: activeTry, // Π°ΠΊΡΠΈΠ²Π½Π°Ρ ΠΏΠΎΠΏΡΡΠΊΠ° handleAnswers: setAnswersFromQuestion, answers: answers, attempts, studentAnswer: attempts[activeTry - 1] }
// ΠΠ΅ΠΉΡΡΠ²ΠΈΡ ΠΏΠΎ ΡΠΏΡΠ°ΠΆΠ½Π΅Π½ΠΈΡ
const action = action => {
switch (action) {
case 'edit':
asideModalStore.activity({
title: 'Π Π΅Π΄Π°ΠΊΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠΏΡΠ°ΠΆΠ½Π΅Π½ΠΈΡ',
modalBodyComponent: () =>
superAxiosRequest({method: 'post', link: 'ebooks/copy_exercise'}, {exercise_id: ex.id})
.then(({data}) => addExercise(data));
break;
case 'off':
break;
case 'delete':
swal({
title: localisationMaster('text_2', 'alert'),
text: `ΠΡ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ Ρ
ΠΎΡΠΈΡΠ΅ ΡΠ΄Π°Π»ΠΈΡΡ ΡΠΏΡΠ°ΠΆΠ½Π΅Π½ΠΈΠ΅?`,
icon: "warning",
buttons: [localisationMaster('button_2', 'alert'), localisationMaster('button_1', 'alert')],
dangerMode: true,
}).then(yes => {
if (yes) {
const apiConf = {
method: 'delete',
link: 'ebooks/exercise/' + ex.id,
}
superAxiosRequest(apiConf).then(() => removeExercise(ex.id))
}
})
break;
case 'up':
case 'down':
let arr = section.exercises.map(x => x.id)
arr = move(arr, arr.indexOf(ex.id), arr.indexOf(ex.id) + (action === 'up' ? -1 : 1))
const apiConf = {
method: 'put',
//link: 'lessons/exercise_position/' + section.id
link: 'ebooks/exercise_position/' + section.id
}
let body = {
exercise_position: arr
}
superAxiosRequest(apiConf, body).then(res => {
props.scrollTo(res.data.exercises.findIndex(x => x.id === ex.id))
setSection(res.data)
}).catch(() => {
props.scrollTo(section.exercises.findIndex(x => x.id === ex.id))
})
break;
default:
break;
}
}
// ΠΠ΅ΠΉΡΡΠ²ΠΈΡ ΠΏΡΠ΅ΠΏΠΎΠ΄Π°Π²Π°ΡΠ΅Π»Ρ const teacherAction = action => { switch (action) { case 'show': const ms = { title: 'Select Students', modalBodyComponent: () => <AssignExercise allStudents={chapter.students} />, button: 'Save', link: 'ebooks/assign_exercise', onSubmitSuccess: assignExercise, } const md = { uuid: chapter.uuid, exercise_id: ex.id, students: assignExercises.find(x => x.exercise_id === ex.id)?.students.map(x => x.student_id) || [], } asideModalStore.activity(ms, md) break; case 'focus': const body = { type: "notifications.notify_focus_on_exercise", message: {exercise_id: ex.id}, } props.sendMessage(body)
cogoToast.info(
`Π£ΡΠ΅Π½ΠΈΠΊΠΈ ΡΡΠΎΠΊΡΡΠΈΡΠΎΠ²Π°Π»ΠΈΡΡ Π½Π° ΡΠΏΡΠ°ΠΆΠ½Π΅Π½ΠΈΠΈ ${props.number}`,
{position: "bottom-right"}
)
break;
case 'homework':
swal({
title: "ΠΠΎΠ±Π°Π²ΠΈΡΡ ΡΠΏΡΠ°ΠΆΠ½Π΅Π½ΠΈΠ΅ Π² Π΄ΠΎΠΌΠ°ΡΠ½Π΅Π΅ Π·Π°Π΄Π°Π½ΠΈΠ΅?",
icon: "info",
buttons: ["ΠΠ΅Ρ", "ΠΠ°"],
}).then(yes => {
if (yes) {
superAxiosRequest(
//{method: 'post', link: 'ebooks/add_to_hw'},
{method: 'post', link: 'ebooks/homework_exercise'},
{uuid: chapter.uuid, exersice_id: ex.id}
).then(res => {
addHomework(res.data.exercises)
}).catch(() => {
})
}
})
break;
case 'showRightAnswers':
superAxiosRequest(
{method: 'get', link: 'ebooks/correct_answers/' + ex.id},
).then(res => {
setAttempts([res.data])
setActiveTry(1)
setStudent(null)
}).catch((error) => {
console.log(`Some error occurred: ${error.response.data.error}`)
})
break;
default:
break;
}
}
// ΠΠ΅ΠΉΡΡΠ²ΠΈΡ ΡΡΠ΅Π½ΠΈΠΊΠ° const studentAction = action => { switch (action){ case 'add_to_favorites': LessonStudentStore.addToFavorites(ex.id) break; case 'remove_from_favorites': LessonStudentStore.removeFromFavorites(ex.id) break; default: break; } }
const viewAnswers = student => { setStudent(student)
const students = assignExercises.find(ae => ae.exercise_id === ex.id)?.students || []
const answers = students.find(x => x.student_id === student.id)?.answers
setAttempts(answers || [])
setActiveTry(1)
}
function setAnswersFromQuestion(ans, saveButtonIsActive) { //ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΠΎΡΠ²Π΅ΡΡ ΠΈΠ· ΡΠ°Π±Π»ΠΎΠ½Π° Π·Π°Π΄Π°Π½ΠΈΡ setAnswers(ans) //Π΅ΡΠ»ΠΈ Π² Π·Π°Π΄Π°Π½ΠΈΠΈ Π½Π΅Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ Π½Π° Π°ΠΊΡΠΈΠ²Π½ΠΎΡΡΡ ΠΊΠ½ΠΎΠΏΠΊΠΈ ΠΎΡΡΠ°Π²Π»ΡΠ΅ΠΌ Π΅Π΅ Π°ΠΊΡΠΈΠ²Π½ΠΎΠΉ if (saveButtonIsActive === undefined) return; //Π΅ΡΠ»ΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π΅ΡΡΡ ΠΏΡΠΈΡΠ²Π°ΠΈΠ²Π°Π΅ΠΌ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΈΠ· ΡΠ°Π±Π»ΠΎΠ½Π° Π²ΠΎΠΏΡΠΎΡΠ° setSendAnswersButtonActive(saveButtonIsActive) //Π΅ΡΠ»ΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π΅ΡΡΡ ΠΏΡΠΈΡΠ²Π°ΠΈΠ²Π°Π΅ΠΌ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΈΠ· ΡΠ°Π±Π»ΠΎΠ½Π° Π²ΠΎΠΏΡΠΎΡΠ° }
const saveTry = () => { setSendAnswersButtonActive(false) let answer const apiConf = { method: 'post', link: 'ebooks/answ_exrs', } switch (ex.type_exercise) { case exerciseTypes.SELECT_WORDS: case exerciseTypes.WRITE_PHRASES: case exerciseTypes.MAKE_WORD: case exerciseTypes.MAKE_SENTENCE: answer = answers.join('|') break; case exerciseTypes.WRITE_WORDS: answer = answers.map(el => el) break; case exerciseTypes.ORDER_SENTENCES: answer = answers.map(el => el) break; case exerciseTypes.CROSSWORD: answer = answers.map(el => el) break; case exerciseTypes.MAKE_WORDS: case exerciseTypes.CHOOSE_SENTENCES_FORM: answer = answers break; case exerciseTypes.MAKE_SENTENCES: answer = answers.map(arr => arr.join('|')) break; case exerciseTypes.MATCH_WORDS: answer = answers.map(pair => { const [word_1, word_2] = pair.split('~~~') return {word_1, word_2} }) break; case exerciseTypes.MATCH_WORDS_IMAGES: answer = answers.map(pair => ({text: pair.description, image: pair.link})) break; case exerciseTypes.GROUP_WORDS: answer = answers.map(ans => ({description: ans.description, value: ans.words.join('|')})) break; case exerciseTypes.ESSAY: answer = answers; break; case exerciseTypes.ENTER_WORDS: answer = answers.map(word => word) break; case exerciseTypes.TEST: answer = answers.slice(1).map((ans, idx) => ({ text: ex.data.questions[idx].text, variants: ans.map(a => ({text: a})) })) break; default: break; } const body = { exercise_id: ex.id, answers: answer, }
if (ex.type_exercise === exerciseTypes.TEST) {
body.time = answers[0];
}
superAxiosRequest(apiConf, body).then(res => {
addExAnswers(ex.id, res.data)
if (activeTry < 11) {
setAnswers([])
setActiveTry(activeTry + 1)
}
}).catch(err => {
if (err.response)
alert(err.response?.data.error)
}).finally(() => {
// setSendAnswersButtonActive(true)
})
}
const renderExTemplate = ({type_exercise: type, ...exercise}) => {
let body;
switch (type) {
case exerciseTypes.IMAGES:
switch (exercise.show_like) {
case 'sequence':
body =
default:
break;
}
break;
case exerciseTypes.GIF:
body = <QuestionImagesList images={exercise.items} text={exercise.text_exercise}/>
break;
case exerciseTypes.AUDIO:
body = <QuestionAudios items={exercise.items}
condition_exercise={exercise.condition_exercise}
text={exercise.text_exercise}/>
break;
case exerciseTypes.VIDEO_LINK:
body = <VideoLinks videos={exercise.data} text={exercise.text_exercise}/>
break;
case exerciseTypes.ESSAY:
body = <WritingEssay ex={exercise} {...dataForExTemplate}/>
break;
case exerciseTypes.PUZZLE:
body = <div className={st.puzzle}><Puzzle imageSrc={Stores.baseLink() + exercise.image} columns={2} rows={2} onSolved={() => swal('Success')}/></div>
// body = <WriteText ex={exercise} {...dataForExTemplate}/>
break;
case exerciseTypes.CROSSWORD:
body = <Crossword ex={exercise} {...dataForExTemplate}/>
break;
case exerciseTypes.MATCH_WORDS_IMAGES:
switch (exercise.subtype) {
case 'move':
body = <ImagesMatchText
data={exercise.data}
text={exercise.text_exercise}
{...dataForExTemplate}
/>
break;
case 'write':
body = <ImagesWriteText
data={exercise.data}
text={exercise.text_exercise}
{...dataForExTemplate}
/>
break;
case 'select':
body = <ImagesSelectText
data={exercise.data}
text={exercise.text_exercise}
{...dataForExTemplate}
/>
break;
default:
break;
}
break;
case exerciseTypes.MAKE_SENTENCE:
body = <MakeSentence sentence={exercise.data.sentence} {...dataForExTemplate} {...exercise}/>
break;
case exerciseTypes.MAKE_SENTENCES:
body = <MakeSentences {...dataForExTemplate} exercise={exercise}/>
break;
case exerciseTypes.GROUP_WORDS:
body = <GroupWords items={exercise.data} {...dataForExTemplate}/>
break;
case exerciseTypes.WRITE_PHRASES:
body = <DragWords items={exercise.data}
{...dataForExTemplate}/>
break;
case exerciseTypes.SELECT_WORDS:
body = <SelectWords items={exercise.data}
{...dataForExTemplate} mode={context.mode}/>
break;
case exerciseTypes.LINK:
body = <SimpleLink data={exercise.data || {}}/>
break;
case exerciseTypes.VIDEO:
body = <QuestionUploadedVideo videos={exercise.items || []} v_link={exercise.items?.[0]?.file || ''}
text={exercise.text_exercise}/>
break;
case exerciseTypes.WRITE_WORDS:
body = <EnterWords items={exercise.data}{...dataForExTemplate}/>
break;
case exerciseTypes.MAKE_WORD:
body = <MakeWord word={exercise.data} {...dataForExTemplate} {...exercise}/>
break;
case exerciseTypes.MAKE_WORDS:
body = <MakeWords {...dataForExTemplate} {...exercise}/>
break;
case exerciseTypes.CHOOSE_SENTENCES_FORM:
body = <ChooseSentencesForm {...dataForExTemplate} {...exercise}/>
break;
case exerciseTypes.MATCH_WORDS:
body = <MatchWords data={exercise.data} {...dataForExTemplate} {...exercise}/>
break;
case exerciseTypes.ORDER_SENTENCES:
body = <OrderSentences data={exercise.data} {...dataForExTemplate} {...exercise}/>
break;
//ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ ΠΏΡΠ΅ΠΏΠΎΠ΄Π°Π²Π°ΡΠ΅Π»Ρ
case exerciseTypes.TEST:
body = <QuestionTest
text={exercise.text_exercise}
questions={exercise.data.questions}
isTimer={exercise.data.is_timer}
time={exercise.data.time}
isPoint={exercise.data.is_point}
saveTry={saveTry}
{...dataForExTemplate}/>
break;
case exerciseTypes.ATTENTION:
body = <QuestionAttention images={exercise.items} image={ex.image} text={exercise.text_exercise}/>
break
default:
break;
}
return body;
}
const getStudentAnswers = st => { // ΠΡΠ΅ ΡΡΡΠ΄Π΅Π½ΡΡ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΡΠΏΡΠ°ΠΆΠ½Π΅Π½ΠΈΡ const students = assignExercises.find(ae => ae.exercise_id === ex.id)?.students || [] // ΠΡΠ²Π΅ΡΡ Π²ΡΠ±ΡΠ°Π½Π½ΠΎΠ³ΠΎ ΡΡΡΠ΄Π΅Π½ΡΠ° const answers = students.find(x => x.student_id === st.id)?.answers
let arr = []
for (let index = 1; index <= 10; index++) {
arr[index] = {
attempt: index,
result: answers?.[index - 1]?.result || null
}
}
if (answers) {
answers.forEach((item) => arr[item.attempt] = item)
}
return ({...st, answers: arr})
}
useEffect(() => { if (!props.focused) return; refEx.current.scrollIntoView({behavior: "smooth"}); dropFocus() }, [dropFocus, props.focused])
useEffect(() => { if (answers.length) return; setSendAnswersButtonActive(false) }, [answers])
useEffect(() => { let answers = [] if (context.mode === 'student'){ answers = lesson?.assign_exercises.find(ae => ae.exercise_id === ex.id)?.answers || [] setActiveTry(Math.min(answers.length + 1, 10)) } else if (context.mode === 'teacher') { const students = [...assignExercises].find(ae => ae.exercise_id === ex.id)?.students || [] if (student) { answers = students.find(st => st.student_id === student.id)?.answers || [] } } else if (context.mode === 'teacher-homework'){ answers = props.answers }
setAttempts(answers)
}, [assignExercisesData, lessonData, props.answers])
useEffect(() => { if (attempts.length <= activeTry) { setSendAnswersButtonActive(false) } }, [activeTry, attempts]);
const onClose = () => { setStudent(null) setAttempts([]) }
const isTitleEx = ex.type_exercise === exerciseTypes.TITLE;
return (
) }
export default observer(Exercise);
Hi, I really like your library, but I'm facing a problem. When I ran your project locally, no errors appeared, but when I tried to integrate the library into my project I received an error. When resizing the browser window, the following errors are displayed in the console:
ResizeObserver loop completed with undelivered notifications. at handleError (http://localhost:3001/static/js/bundle.js:349867:58) at http://localhost:3001/static/js/bundle.js:349886:7.
Has anyone encountered something similar?