Skip to content

Commit 23ccf76

Browse files
Copilotacbart
andcommitted
Port remaining management components to SolidJS
- Created AssignmentManager component * CRUD operations for assignments and groups * Create assignments (7 types: BlockPy, Reading, Quiz, TypeScript, Textbook, Explain, Maze) * Modal dialogs for creation * Move assignments between groups * Edit/delete functionality - Created CourseList component * Display courses with sortable list (4 sort modes) * Pin/unpin courses with backend integration * Show user roles * LMS integration display - Created GroupList component * Display assignment groups * Load from backend API * Error and loading states - Created ModelSelector component * Generic selector for Users/Assignments * 3 modes: All/Single/Set * Custom set creation and management * LocalStorage persistence * Grouped display support - Created UserEditor component * User settings management * Sort order preferences (5 options) * Render style preferences - Updated app.tsx to export all new components * Add init functions for all management components * Export types and enums * Register in global frontendSolid object - Created comprehensive README for management components - All components follow SolidJS reactive patterns - Bootstrap 5 styling integration - Type-safe with TypeScript strict mode Co-authored-by: acbart <897227+acbart@users.noreply.github.com>
1 parent 64e2448 commit 23ccf76

7 files changed

Lines changed: 1458 additions & 0 deletions

File tree

frontend-solid/src/app.tsx

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ import { Reader, ReaderProps } from './components/reader/Reader';
1010
import { Textbook, TextbookProps, TextbookData } from './components/textbook/Textbook';
1111
import { WatchMode } from './components/watcher/SubmissionState';
1212
import { QuizData } from './components/quizzes/types';
13+
import { AssignmentManager } from './components/management/AssignmentManager';
14+
import { CourseList, type Course } from './components/management/CourseList';
15+
import { GroupList } from './components/management/GroupList';
16+
import { ModelSelector, type Model } from './components/management/ModelSelector';
17+
import { UserEditor } from './components/management/UserEditor';
1318

1419
// Export components for external use
1520
export { Watcher } from './components/watcher/Watcher';
@@ -32,6 +37,15 @@ export type { ReaderProps } from './components/reader/Reader';
3237
export { Textbook } from './components/textbook/Textbook';
3338
export type { TextbookProps, TextbookData } from './components/textbook/Textbook';
3439

40+
// Export management components
41+
export { AssignmentManager } from './components/management/AssignmentManager';
42+
export { CourseList } from './components/management/CourseList';
43+
export type { Course } from './components/management/CourseList';
44+
export { GroupList } from './components/management/GroupList';
45+
export { ModelSelector } from './components/management/ModelSelector';
46+
export type { Model } from './components/management/ModelSelector';
47+
export { UserEditor, SortOrder, RenderStyle } from './components/management/UserEditor';
48+
3549
// Export models
3650
export { User } from './models/user';
3751
export { Assignment } from './models/assignment';
@@ -156,6 +170,112 @@ export function initTextbook(
156170
render(() => <Textbook {...props} />, element);
157171
}
158172

173+
/**
174+
* Initialize an AssignmentManager component in the given container
175+
* @param container - DOM element or selector where the component should be mounted
176+
* @param props - Props for the AssignmentManager component
177+
*/
178+
export function initAssignmentManager(
179+
container: HTMLElement | string,
180+
props: { courseId: number; user: any }
181+
) {
182+
const element = typeof container === 'string'
183+
? document.querySelector(container)
184+
: container;
185+
186+
if (!element) {
187+
console.error('Container element not found:', container);
188+
return;
189+
}
190+
191+
render(() => <AssignmentManager {...props} />, element);
192+
}
193+
194+
/**
195+
* Initialize a CourseList component in the given container
196+
* @param container - DOM element or selector where the component should be mounted
197+
* @param props - Props for the CourseList component
198+
*/
199+
export function initCourseList(
200+
container: HTMLElement | string,
201+
props: { courses: Course[]; user: any; label: string }
202+
) {
203+
const element = typeof container === 'string'
204+
? document.querySelector(container)
205+
: container;
206+
207+
if (!element) {
208+
console.error('Container element not found:', container);
209+
return;
210+
}
211+
212+
render(() => <CourseList {...props} />, element);
213+
}
214+
215+
/**
216+
* Initialize a GroupList component in the given container
217+
* @param container - DOM element or selector where the component should be mounted
218+
* @param props - Props for the GroupList component
219+
*/
220+
export function initGroupList(
221+
container: HTMLElement | string,
222+
props: { courseId: number }
223+
) {
224+
const element = typeof container === 'string'
225+
? document.querySelector(container)
226+
: container;
227+
228+
if (!element) {
229+
console.error('Container element not found:', container);
230+
return;
231+
}
232+
233+
render(() => <GroupList {...props} />, element);
234+
}
235+
236+
/**
237+
* Initialize a ModelSelector component in the given container
238+
* @param container - DOM element or selector where the component should be mounted
239+
* @param props - Props for the ModelSelector component
240+
*/
241+
export function initModelSelector(
242+
container: HTMLElement | string,
243+
props: { models: Model[]; label: string; storageKey?: string }
244+
) {
245+
const element = typeof container === 'string'
246+
? document.querySelector(container)
247+
: container;
248+
249+
if (!element) {
250+
console.error('Container element not found:', container);
251+
return;
252+
}
253+
254+
const SelectorComponent = ModelSelector(props);
255+
render(() => <SelectorComponent />, element);
256+
}
257+
258+
/**
259+
* Initialize a UserEditor component in the given container
260+
* @param container - DOM element or selector where the component should be mounted
261+
* @param props - Props for the UserEditor component
262+
*/
263+
export function initUserEditor(
264+
container: HTMLElement | string,
265+
props?: any
266+
) {
267+
const element = typeof container === 'string'
268+
? document.querySelector(container)
269+
: container;
270+
271+
if (!element) {
272+
console.error('Container element not found:', container);
273+
return;
274+
}
275+
276+
render(() => <UserEditor {...(props || {})} />, element);
277+
}
278+
159279
// Make it available globally for template usage
160280
if (typeof window !== 'undefined') {
161281
(window as any).frontendSolid = {
@@ -164,11 +284,21 @@ if (typeof window !== 'undefined') {
164284
initQuizEditor,
165285
initReader,
166286
initTextbook,
287+
initAssignmentManager,
288+
initCourseList,
289+
initGroupList,
290+
initModelSelector,
291+
initUserEditor,
167292
Watcher,
168293
Quizzer,
169294
QuizEditor,
170295
Reader,
171296
Textbook,
297+
AssignmentManager,
298+
CourseList,
299+
GroupList,
300+
ModelSelector,
301+
UserEditor,
172302
WatchMode,
173303
};
174304
}

0 commit comments

Comments
 (0)