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:
@@ -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: []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user