ENCOA-307
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import useExamEditorStore from "@/stores/examEditor";
|
import useExamEditorStore from "@/stores/examEditor";
|
||||||
import ListeningContext from "./listening";
|
import ListeningContext from "./listening";
|
||||||
import ReadingContext from "./reading";
|
import ReadingContext from "./reading";
|
||||||
@@ -30,7 +29,7 @@ const LevelContext: React.FC<Props> = ({ sectionId }) => {
|
|||||||
)}
|
)}
|
||||||
{(readingSection || listeningSection || hasReadingContext) && (
|
{(readingSection || listeningSection || hasReadingContext) && (
|
||||||
<div className="space-y-4 mb-4">
|
<div className="space-y-4 mb-4">
|
||||||
{readingSection || hasReadingContext && <ReadingContext sectionId={sectionId} module="level" />}
|
{(readingSection !== undefined || hasReadingContext) && <ReadingContext sectionId={sectionId} module="level" />}
|
||||||
{listeningSection && <ListeningContext sectionId={sectionId} listeningSection={listeningSection} module="level" level={true} />}
|
{listeningSection && <ListeningContext sectionId={sectionId} listeningSection={listeningSection} module="level" level={true} />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -11,11 +11,10 @@ import { Module } from "@/interfaces";
|
|||||||
interface Props {
|
interface Props {
|
||||||
module: Module;
|
module: Module;
|
||||||
sectionId: number;
|
sectionId: number;
|
||||||
level?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const ReadingContext: React.FC<Props> = ({ sectionId, module, level = false }) => {
|
const ReadingContext: React.FC<Props> = ({ sectionId, module }) => {
|
||||||
const { dispatch } = useExamEditorStore();
|
const { dispatch } = useExamEditorStore();
|
||||||
const sectionState = useExamEditorStore(
|
const sectionState = useExamEditorStore(
|
||||||
(state) => state.modules[module].sections.find((section) => section.sectionId === sectionId)!
|
(state) => state.modules[module].sections.find((section) => section.sectionId === sectionId)!
|
||||||
@@ -74,7 +73,9 @@ const ReadingContext: React.FC<Props> = ({ sectionId, module, level = false }) =
|
|||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const passageRes = levelGenResults.find((res) => res.generating === "passage");
|
const passageRes = [...levelGenResults].reverse()
|
||||||
|
.find((res) => res.generating === "passage");
|
||||||
|
|
||||||
if (levelGenResults && passageRes) {
|
if (levelGenResults && passageRes) {
|
||||||
setEditing(true);
|
setEditing(true);
|
||||||
setTitle(passageRes.result[0].title);
|
setTitle(passageRes.result[0].title);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import Dropdown from "@/components/Dropdown";
|
|||||||
import useExamEditorStore from "@/stores/examEditor";
|
import useExamEditorStore from "@/stores/examEditor";
|
||||||
import Writing from "../../Exercises/Writing";
|
import Writing from "../../Exercises/Writing";
|
||||||
import Speaking from "../../Exercises/Speaking";
|
import Speaking from "../../Exercises/Speaking";
|
||||||
import { ReactElement, ReactNode, useEffect, useState } from "react";
|
import { ReactNode, useEffect } from "react";
|
||||||
import {
|
import {
|
||||||
DndContext,
|
DndContext,
|
||||||
PointerSensor,
|
PointerSensor,
|
||||||
@@ -43,7 +43,7 @@ const SectionExercises: React.FC<{ sectionId: number; }> = ({ sectionId }) => {
|
|||||||
|
|
||||||
const genResult = section?.genResult;
|
const genResult = section?.genResult;
|
||||||
const generating = section?.generating;
|
const generating = section?.generating;
|
||||||
const levelGenResults = section?.levelGenResults
|
const levelGenResults = section?.levelGenResults;
|
||||||
const levelGenerating = section?.levelGenerating;
|
const levelGenerating = section?.levelGenerating;
|
||||||
const sectionState = section?.state;
|
const sectionState = section?.state;
|
||||||
|
|
||||||
@@ -66,134 +66,146 @@ const SectionExercises: React.FC<{ sectionId: number; }> = ({ sectionId }) => {
|
|||||||
}, [genResult, dispatch, sectionId, currentModule]);
|
}, [genResult, dispatch, sectionId, currentModule]);
|
||||||
|
|
||||||
|
|
||||||
|
const handleExerciseGen = (
|
||||||
|
results: any[],
|
||||||
|
assignExercisesFn: (results: any[]) => any[],
|
||||||
|
{
|
||||||
|
sectionId,
|
||||||
|
currentModule,
|
||||||
|
sectionState,
|
||||||
|
levelGenerating,
|
||||||
|
levelGenResults
|
||||||
|
}: {
|
||||||
|
sectionId: number;
|
||||||
|
currentModule: string;
|
||||||
|
sectionState: ExamPart;
|
||||||
|
levelGenerating?: Generating[];
|
||||||
|
levelGenResults: any[];
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
const nonWritingOrSpeaking = results[0]?.generating.startsWith("exercises");
|
||||||
|
|
||||||
|
const updates = [
|
||||||
|
{
|
||||||
|
type: "UPDATE_SECTION_STATE",
|
||||||
|
payload: {
|
||||||
|
sectionId,
|
||||||
|
module: "level",
|
||||||
|
update: {
|
||||||
|
exercises: [
|
||||||
|
...sectionState.exercises,
|
||||||
|
...assignExercisesFn(results)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "UPDATE_SECTION_SINGLE_FIELD",
|
||||||
|
payload: {
|
||||||
|
sectionId,
|
||||||
|
module: currentModule,
|
||||||
|
field: "levelGenerating",
|
||||||
|
value: levelGenerating?.filter(g =>
|
||||||
|
nonWritingOrSpeaking
|
||||||
|
? !g?.startsWith("exercises")
|
||||||
|
: !results.flatMap(res => res.generating as Generating).includes(g)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "UPDATE_SECTION_SINGLE_FIELD",
|
||||||
|
payload: {
|
||||||
|
sectionId,
|
||||||
|
module: currentModule,
|
||||||
|
field: "levelGenResults",
|
||||||
|
value: levelGenResults.filter(res =>
|
||||||
|
nonWritingOrSpeaking
|
||||||
|
? !res.generating.startsWith("exercises")
|
||||||
|
: !results.flatMap(res => res.generating as Generating).includes(res.generating)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] as Action[];
|
||||||
|
|
||||||
|
updates.forEach(update => dispatch(update));
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (levelGenResults && levelGenResults.some(res => res.generating.startsWith("exercises"))) {
|
if (levelGenResults && levelGenResults?.some(res => res.generating.startsWith("exercises"))) {
|
||||||
const newExercises = levelGenResults
|
const results = levelGenResults.filter(res =>
|
||||||
.filter(res => res.generating.startsWith("exercises"))
|
res.generating.startsWith("exercises")
|
||||||
|
);
|
||||||
|
|
||||||
|
const assignExercises = (results: any[]) =>
|
||||||
|
results
|
||||||
.map(res => res.result[0].exercises)
|
.map(res => res.result[0].exercises)
|
||||||
.flat();
|
.flat();
|
||||||
|
|
||||||
const updates = [
|
handleExerciseGen(
|
||||||
|
results,
|
||||||
|
assignExercises,
|
||||||
{
|
{
|
||||||
type: "UPDATE_SECTION_STATE",
|
|
||||||
payload: {
|
|
||||||
sectionId,
|
sectionId,
|
||||||
module: "level",
|
currentModule,
|
||||||
update: {
|
sectionState: sectionState as ExamPart,
|
||||||
exercises: [...(sectionState as ExamPart).exercises, ...newExercises]
|
levelGenerating,
|
||||||
|
levelGenResults
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "UPDATE_SECTION_SINGLE_FIELD",
|
|
||||||
payload: {
|
|
||||||
sectionId,
|
|
||||||
module: currentModule,
|
|
||||||
field: "levelGenerating",
|
|
||||||
value: levelGenerating?.filter(g => !g?.startsWith("exercises"))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "UPDATE_SECTION_SINGLE_FIELD",
|
|
||||||
payload: {
|
|
||||||
sectionId,
|
|
||||||
module: currentModule,
|
|
||||||
field: "levelGenResults",
|
|
||||||
value: levelGenResults.filter(res => !res.generating.startsWith("exercises"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
] as Action[];
|
|
||||||
|
|
||||||
updates.forEach(update => dispatch(update));
|
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]);
|
}, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (levelGenResults && levelGenResults.some(res => res.generating === "writing_letter" || res.generating === "writing_2")) {
|
if (levelGenResults && levelGenResults?.some(res =>
|
||||||
const results = levelGenResults.filter(res => res.generating === "writing_letter" || res.generating === "writing_2");
|
res.generating === "writing_letter" || res.generating === "writing_2"
|
||||||
|
)) {
|
||||||
|
const results = levelGenResults.filter(res =>
|
||||||
|
res.generating === "writing_letter" || res.generating === "writing_2"
|
||||||
|
);
|
||||||
|
|
||||||
const updates = [
|
const assignExercises = (results: any[]) =>
|
||||||
{
|
results.map(res => ({
|
||||||
type: "UPDATE_SECTION_STATE",
|
|
||||||
payload: {
|
|
||||||
sectionId,
|
|
||||||
module: "level",
|
|
||||||
update: {
|
|
||||||
exercises: [...(sectionState as ExamPart).exercises,
|
|
||||||
...results.map((res) => {
|
|
||||||
return {
|
|
||||||
...writingTask(res.generating === "writing_letter" ? 1 : 2),
|
...writingTask(res.generating === "writing_letter" ? 1 : 2),
|
||||||
prompt: res.result[0].prompt,
|
prompt: res.result[0].prompt,
|
||||||
variant: res.generating === "writing_letter" ? "letter" : "essay"
|
variant: res.generating === "writing_letter" ? "letter" : "essay"
|
||||||
} as WritingExercise;
|
}) as WritingExercise);
|
||||||
})
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "UPDATE_SECTION_SINGLE_FIELD",
|
|
||||||
payload: {
|
|
||||||
sectionId,
|
|
||||||
module: currentModule,
|
|
||||||
field: "levelGenerating",
|
|
||||||
value: levelGenerating?.filter(g => !results.flatMap(res => res.generating as Generating).includes(g))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "UPDATE_SECTION_SINGLE_FIELD",
|
|
||||||
payload: {
|
|
||||||
sectionId,
|
|
||||||
module: currentModule,
|
|
||||||
field: "levelGenResults",
|
|
||||||
value: levelGenResults.filter(res => !results.flatMap(res => res.generating as Generating).includes(res.generating))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
] as Action[];
|
|
||||||
|
|
||||||
updates.forEach(update => dispatch(update));
|
handleExerciseGen(
|
||||||
|
results,
|
||||||
|
assignExercises,
|
||||||
|
{
|
||||||
|
sectionId,
|
||||||
|
currentModule,
|
||||||
|
sectionState: sectionState as ExamPart,
|
||||||
|
levelGenerating,
|
||||||
|
levelGenResults
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]);
|
}, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (levelGenResults && levelGenResults.some(res => res.generating.startsWith("speaking"))) {
|
if (levelGenResults && levelGenResults?.some(res => res.generating.startsWith("speaking"))) {
|
||||||
const results = levelGenResults.filter(res => res.generating.startsWith("speaking"));
|
const results = levelGenResults.filter(res =>
|
||||||
const updates = [
|
res.generating.startsWith("speaking")
|
||||||
{
|
);
|
||||||
type: "UPDATE_SECTION_STATE",
|
|
||||||
payload: {
|
|
||||||
sectionId,
|
|
||||||
module: "level",
|
|
||||||
update: {
|
|
||||||
exercises: [...(sectionState as ExamPart).exercises,
|
|
||||||
...results.map(createSpeakingExercise)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "UPDATE_SECTION_SINGLE_FIELD",
|
|
||||||
payload: {
|
|
||||||
sectionId,
|
|
||||||
module: currentModule,
|
|
||||||
field: "levelGenerating",
|
|
||||||
value: levelGenerating?.filter(g => !results.flatMap(res => res.generating as Generating).includes(g))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "UPDATE_SECTION_SINGLE_FIELD",
|
|
||||||
payload: {
|
|
||||||
sectionId,
|
|
||||||
module: currentModule,
|
|
||||||
field: "levelGenResults",
|
|
||||||
value: levelGenResults.filter(res => !results.flatMap(res => res.generating as Generating).includes(res.generating))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
] as Action[];
|
|
||||||
|
|
||||||
updates.forEach(update => dispatch(update));
|
const assignExercises = (results: any[]) =>
|
||||||
|
results.map(createSpeakingExercise);
|
||||||
|
|
||||||
|
handleExerciseGen(
|
||||||
|
results,
|
||||||
|
assignExercises,
|
||||||
|
{
|
||||||
|
sectionId,
|
||||||
|
currentModule,
|
||||||
|
sectionState: sectionState as ExamPart,
|
||||||
|
levelGenerating,
|
||||||
|
levelGenResults
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]);
|
}, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]);
|
||||||
|
|||||||
@@ -38,11 +38,7 @@ const SectionPicker: React.FC<Props> = ({
|
|||||||
const newValue = currentValue === value ? undefined : value;
|
const newValue = currentValue === value ? undefined : value;
|
||||||
setSelectedValue(newValue);
|
setSelectedValue(newValue);
|
||||||
let update = {};
|
let update = {};
|
||||||
if (module == "reading") {
|
if (module === "listening") {
|
||||||
update = {
|
|
||||||
text: undefined
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (state.audio?.source) {
|
if (state.audio?.source) {
|
||||||
URL.revokeObjectURL(state.audio.source)
|
URL.revokeObjectURL(state.audio.source)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,8 @@ import { usePersistentExamStore } from "@/stores/exam";
|
|||||||
import openDetachedTab from "@/utils/popout";
|
import openDetachedTab from "@/utils/popout";
|
||||||
import ListeningComponents from "./listening/components";
|
import ListeningComponents from "./listening/components";
|
||||||
import ReadingComponents from "./reading/components";
|
import ReadingComponents from "./reading/components";
|
||||||
import WritingComponents from "./writing/components";
|
|
||||||
import SpeakingComponents from "./speaking/components";
|
import SpeakingComponents from "./speaking/components";
|
||||||
import SectionPicker from "./Shared/SectionPicker";
|
import SectionPicker from "./Shared/SectionPicker";
|
||||||
import SettingsDropdown from "./Shared/SettingsDropdown";
|
|
||||||
|
|
||||||
|
|
||||||
const LevelSettings: React.FC = () => {
|
const LevelSettings: React.FC = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user