ENCOA-228 Now when user navigates between modules the generation items persist. Reading, listening and writing added to level module

This commit is contained in:
Carlos-Mesquita
2024-11-12 14:17:54 +00:00
parent 696c968ebc
commit fdf411d133
66 changed files with 2546 additions and 1635 deletions

View File

@@ -1,5 +1,5 @@
import { Module } from "@/interfaces"
import { Difficulty} from "@/interfaces/exam"
import { Difficulty } from "@/interfaces/exam"
import { sample } from "lodash"
import { ExamPart, ModuleState, SectionState } from "./types"
import { levelPart, listeningSection, readingPart, speakingTask, writingTask } from "@/stores/examEditor/sections"
@@ -18,21 +18,59 @@ const defaultSettings = (module: Module) => {
}
switch (module) {
case 'writing':
return {
...baseSettings,
writingTopic: '',
isWritingTopicOpen: false
}
case 'reading':
return {
...baseSettings,
isPassageOpen: false,
readingTopic: '',
isReadingTopicOpean: false,
}
case 'listening':
case 'listening':
return {
...baseSettings,
isAudioContextOpen: false,
isAudioGenerationOpen: false,
listeningTopic: '',
isListeningTopicOpen: false,
}
case 'speaking':
return {
...baseSettings,
isGenerateAudioOpen: false
speakingTopic: '',
speakingSecondTopic: '',
isSpeakingTopicOpen: false,
isGenerateVideoOpen: false,
}
case 'level':
return {
...baseSettings,
isReadingDropdownOpen: false,
isWritingDropdownOpen: false,
isSpeakingDropdownOpen: false,
isListeningDropdownOpen: false,
isWritingTopicOpen: false,
writingTopic: '',
isPassageOpen: false,
readingTopic: '',
isReadingTopicOpean: false,
isAudioContextOpen: false,
isAudioGenerationOpen: false,
listeningTopic: '',
isListeningTopicOpen: false,
speakingTopic: '',
speakingSecondTopic: '',
isSpeakingTopicOpen: false,
isGenerateVideoOpen: false,
}
default:
return baseSettings;
@@ -47,16 +85,16 @@ const sectionLabels = (module: Module) => {
label: `Passage ${index + 1}`
}));
case 'writing':
return [{id: 1, label: "Task 1"}, {id: 2, label: "Task 2"}];
return [{ id: 1, label: "Task 1" }, { id: 2, label: "Task 2" }];
case 'speaking':
return [{id: 1, label: "Speaking 1"}, {id: 2, label: "Speaking 2"}, {id: 3, label: "Interactive Speaking"}];
return [{ id: 1, label: "Speaking 1" }, { id: 2, label: "Speaking 2" }, { id: 3, label: "Interactive Speaking" }];
case 'listening':
return Array.from({ length: 4 }, (_, index) => ({
id: index + 1,
label: `Section ${index + 1}`
}));
case 'level':
return [{id: 1, label: "Part 1"}];
return [{ id: 1, label: "Part 1" }];
}
}
@@ -85,7 +123,7 @@ const defaultSection = (module: Module, sectionId: number) => {
return listeningSection(sectionId)
case 'speaking':
return speakingTask(sectionId)
case 'level':
case 'level':
return levelPart(sectionId)
}
}
@@ -99,8 +137,8 @@ export const defaultSectionSettings = (module: Module, sectionId: number, part?:
generating: undefined,
genResult: undefined,
expandedSubSections: [],
exercisePickerState: [],
selectedExercises: [],
levelGenerating: [],
levelGenResults: []
}
}

View File

@@ -17,6 +17,7 @@ export const rootReducer = (
state: ExamEditorStore,
action: Action
): Partial<ExamEditorStore> => {
console.log(action);
if (MODULE_ACTIONS.includes(action.type as any)) {
if (action.type === "REORDER_EXERCISES") {
const updatedState = sectionReducer(state, action as SectionActions);

View File

@@ -51,6 +51,7 @@ export const moduleReducer = (
case 'TOGGLE_SECTION':
const { sectionId } = action.payload;
console.log("TOGGLE SECTION TRIGGERED");
const prev = currentModuleState.sections;
const updatedSections = prev.some(section => section.sectionId === sectionId)

View File

@@ -6,9 +6,9 @@ import { reorderSection } from "../reorder/global";
export type SectionActions =
| { type: 'UPDATE_SECTION_SINGLE_FIELD'; payload: { module: Module; sectionId: number; field: string; value: any } }
| { type: 'UPDATE_SECTION_SETTINGS'; payload: { sectionId: number; update: Partial<SectionSettings | ReadingSectionSettings>; } }
| { type: 'UPDATE_SECTION_STATE'; payload: { sectionId: number; update: Partial<Section>; } }
| { type: 'REORDER_EXERCISES'; payload: { event: DragEndEvent, sectionId: number; } };
| { type: 'UPDATE_SECTION_SETTINGS'; payload: { sectionId: number; module: Module; update: Partial<SectionSettings | ReadingSectionSettings>; } }
| { type: 'UPDATE_SECTION_STATE'; payload: { sectionId: number; module: Module; update: Partial<Section>; } }
| { type: 'REORDER_EXERCISES'; payload: { event: DragEndEvent, module: Module; sectionId: number; } };
export const SECTION_ACTIONS = [
'UPDATE_SECTION_SETTINGS',
@@ -20,24 +20,16 @@ export const sectionReducer = (
state: ExamEditorStore,
action: SectionActions
): Partial<ExamEditorStore> => {
const currentModule = state.currentModule;
const modules = state.modules;
const sections = state.modules[currentModule].sections;
let sectionId: number;
if (action.payload && 'sectionId' in action.payload) {
sectionId = action.payload.sectionId;
}
switch (action.type) {
case 'UPDATE_SECTION_SINGLE_FIELD':
const { module, field, value } = action.payload;
case 'UPDATE_SECTION_SINGLE_FIELD':{
const { module, field, value, sectionId } = action.payload;
console.log(`Updating ${module}-${sectionId} ${field} to ${value}`);
return {
modules: {
...modules,
...state.modules,
[module]: {
...modules[module],
sections: sections.map((section: SectionState) =>
...state.modules[module],
sections: state.modules[module].sections.map((section: SectionState) =>
section.sectionId === sectionId
? {
...section,
@@ -48,22 +40,21 @@ export const sectionReducer = (
}
}
};
case 'UPDATE_SECTION_SETTINGS':
let updatedSettings = action.payload.update;
}
case 'UPDATE_SECTION_SETTINGS':{
const {module, sectionId, update} = action.payload;
return {
modules: {
...modules,
[currentModule]: {
...modules[currentModule],
sections: sections.map((section: SectionState) =>
...state.modules,
[module]: {
...state.modules[module],
sections: state.modules[module].sections.map((section: SectionState) =>
section.sectionId === sectionId
? {
...section,
settings: {
...section.settings,
...updatedSettings
...update
}
}
: section
@@ -71,30 +62,32 @@ export const sectionReducer = (
}
}
};
case 'UPDATE_SECTION_STATE':
const updatedState = action.payload.update;
}
case 'UPDATE_SECTION_STATE': {
const { update, module, sectionId }= action.payload;
return {
modules: {
...modules,
[currentModule]: {
...modules[currentModule],
sections: sections.map(section =>
...state.modules,
[module]: {
...state.modules[module],
sections: state.modules[module].sections.map(section =>
section.sectionId === sectionId
? { ...section, state: { ...section.state, ...updatedState } }
? { ...section, state: { ...section.state, ...update } }
: section
)
}
}
};
}
case 'REORDER_EXERCISES': {
const { active, over } = action.payload.event;
const { event, sectionId, module } = action.payload;
const {over, active} = event;
if (!over) return state;
const oldIndex = active.id as number;
const newIndex = over.id as number;
const currentSectionState = sections.find((s) => s.sectionId === sectionId)!.state as ReadingPart | ListeningPart | LevelPart;
const currentSectionState = state.modules[module].sections.find((s) => s.sectionId === sectionId)!.state as ReadingPart | ListeningPart | LevelPart;
const exercises = [...currentSectionState.exercises];
const [removed] = exercises.splice(oldIndex, 1);
exercises.splice(newIndex, 0, removed);
@@ -110,9 +103,9 @@ export const sectionReducer = (
...state,
modules: {
...state.modules,
[currentModule]: {
...modules[currentModule],
sections: sections.map(section =>
[module]: {
...state.modules[module],
sections: state.modules[module].sections.map(section =>
section.sectionId === sectionId
? { ...section, state: newSectionState }
: section

View File

@@ -1,4 +1,4 @@
import { Exercise, FillBlanksExercise, LevelPart, ListeningPart, MatchSentencesExercise, MultipleChoiceExercise, ReadingPart, TrueFalseExercise, WriteBlanksExercise } from "@/interfaces/exam";
import { Exercise, FillBlanksExercise, LevelPart, ListeningPart, MatchSentencesExercise, MultipleChoiceExercise, ReadingPart, TrueFalseExercise, WriteBlanksExercise, WritingExercise } from "@/interfaces/exam";
import { ModuleState } from "../types";
import ReorderResult from "./types";
@@ -143,7 +143,6 @@ const reorderSection = (exercises: Exercise[], startId: number): { exercises: Ex
switch (exercise.type) {
case 'fillBlanks':
console.log("Reordering FillBlanks");
result = reorderFillBlanks(exercise, currentId);
currentId = result.lastId;
return result.exercise;
@@ -168,7 +167,12 @@ const reorderSection = (exercises: Exercise[], startId: number): { exercises: Ex
currentId = result.lastId;
return result.exercise;
case 'writing':
exercise = { ...exercise, sectionId: currentId };
currentId += 1;
return exercise;
default:
console.log("HERE IT IS");
return exercise;
}
});

View File

@@ -11,7 +11,8 @@ export const writingTask = (task: number) => ({
wordCounter: {
limit: task == 1 ? 150 : 250,
type: "min",
}
},
order: 1
} as WritingExercise);
export const readingPart = (task: number) => {

View File

@@ -1,7 +1,7 @@
import { Difficulty, InteractiveSpeakingExercise, LevelPart, ListeningPart, ReadingPart, SpeakingExercise, WritingExercise } from "@/interfaces/exam";
import { Module } from "@/interfaces";
import Option from "@/interfaces/option";
import { ExerciseConfig } from "@/components/ExamEditor/Shared/ExercisePicker/ExerciseWizard";
import { ExerciseConfig } from "@/components/ExamEditor/ExercisePicker/ExerciseWizard";
export interface GeneratedExercises {
exercises: Record<string, string>[];
@@ -16,32 +16,70 @@ export interface SectionSettings {
currentIntro: string | undefined;
isCategoryDropdownOpen: boolean;
isIntroDropdownOpen: boolean;
isExerciseDropdownOpen: boolean;
topic?: string;
}
export interface SpeakingSectionSettings extends SectionSettings {
secondTopic?: string;
isGenerateAudioOpen: boolean;
speakingTopic: string;
speakingSecondTopic?: string;
isSpeakingTopicOpen: boolean;
isGenerateVideoOpen: boolean;
}
export interface ReadingSectionSettings extends SectionSettings {
isPassageOpen: boolean;
readingTopic: string;
isReadingTopicOpean: boolean;
}
export interface ListeningSectionSettings extends SectionSettings {
isAudioContextOpen: boolean;
isAudioGenerationOpen: boolean;
listeningTopic: string;
isListeningTopicOpen: boolean;
}
export interface WritingSectionSettings extends SectionSettings {
isWritingTopicOpen: boolean;
writingTopic: string;
}
export interface LevelSectionSettings extends SectionSettings {
readingDropdownOpen: boolean;
writingDropdownOpen: boolean;
speakingDropdownOpen: boolean;
listeningDropdownOpen: boolean;
isReadingDropdownOpen: boolean;
isWritingDropdownOpen: boolean;
isSpeakingDropdownOpen: boolean;
isListeningDropdownOpen: boolean;
isLevelDropdownOpen: boolean;
readingSection?: number;
listeningSection?: number;
// writing
isWritingTopicOpen: boolean;
writingTopic: string;
// reading
isPassageOpen: boolean;
readingTopic: string;
isReadingTopicOpean: boolean;
// listening
isAudioContextOpen: boolean;
isAudioGenerationOpen: boolean;
listeningTopic: string;
isListeningTopicOpen: boolean;
// speaking
speakingTopic?: string;
speakingSecondTopic?: string;
isSpeakingTopicOpen: boolean;
isGenerateVideoOpen: boolean;
// section picker
isReadingPickerOpen: boolean;
isListeningPickerOpen: boolean;
}
export type Generating = "context" | "exercises" | "media" | undefined;
export type Context = "passage" | "video" | "audio" | "listeningScript" | "speakingScript" | "writing";
export type Generating = Context | "exercises" | string | undefined;
export type Section = LevelPart | ReadingPart | ListeningPart | WritingExercise | SpeakingExercise | InteractiveSpeakingExercise;
export type ExamPart = ListeningPart | ReadingPart | LevelPart;
@@ -51,9 +89,14 @@ export interface SectionState {
state: Section;
expandedSubSections: number[];
generating: Generating;
genResult: Record<string, any>[] | undefined;
exercisePickerState: ExerciseConfig[];
selectedExercises: string[];
genResult: {generating: string, result: Record<string, any>[], module: Module} | undefined;
levelGenerating: Generating[];
levelGenResults: {generating: string, result: Record<string, any>[], module: Module}[];
focusedExercise?: number;
writingSection?: number;
speakingSection?: number;
readingSection?: number;
listeningSection?: number;
}
export interface ModuleState {