@@ -68,22 +68,46 @@ let tag_addremove list_id placeholder add_fun remove_fun =
6868 ] [ H. txt " \xe2\x9e\x96 " (* U+2796 heavy minus sign *) ];
6969 ]
7070
71+ let help_button name (title ,md_text ) =
72+ let dialog () =
73+ let text_div =
74+ let d =
75+ H. div []
76+ ~a: [H. a_class [" doc-popup-body" ]]
77+ in
78+ (* Manip.SetCss.maxHeight d "85vh";
79+ * Manip.SetCss.overflowY d "auto"; *)
80+ let doc_html_string =
81+ Omd. (md_text |> of_string |> to_html)
82+ in
83+ Manip. setInnerHtml d doc_html_string;
84+ d
85+ in
86+ Learnocaml_common. ext_alert ~title [text_div]
87+ in
88+ H. button ~a: [
89+ H. a_id (" button_help_" ^ name);
90+ H. a_onclick (fun _ -> dialog () ; true );
91+ H. a_style " margin-left: 1em;" ;
92+ ] [H. txt " ?" ]
93+
7194let rec teacher_tab token _select _params () =
7295 let action_new_token () =
73- retrieve (Learnocaml_api. Create_teacher_token token)
96+ Learnocaml_common. ask_string
97+ ~title: " NEW TEACHER TOKEN"
98+ [H. txt @@ " Enter a nickname for the new token:" ]
99+ >> = fun nickname ->
100+ let nick = match String. trim nickname with
101+ | "" -> None
102+ | s -> Some s
103+ in
104+ retrieve (Learnocaml_api. Create_teacher_token (token, nick))
74105 > |= fun new_token ->
75106 alert ~title: [% i" TEACHER TOKEN" ]
76107 (Printf. sprintf [% if " New teacher token created:\n %s\n\n \
77108 write it down." ]
78109 (Token. to_string new_token))
79110 in
80- let action_csv_export () =
81- retrieve (Learnocaml_api. Students_csv (token, [] , [] ))
82- > |= fun csv ->
83- Learnocaml_common. fake_download
84- ~name: " learnocaml.csv"
85- ~contents: (Js. string csv)
86- in
87111 let indent_style lvl =
88112 H. a_style (Printf. sprintf " text-align: left; padding-left: %dem;" lvl)
89113 in
@@ -183,6 +207,23 @@ let rec teacher_tab token _select _params () =
183207 let assignment_change = ref (fun _ -> assert false ) in
184208 let assignment_remove = ref (fun _ -> assert false ) in
185209
210+ let action_csv_export () =
211+ let exercises =
212+ Hashtbl. to_seq_keys selected_exercises |>
213+ List. of_seq
214+ in
215+ let students =
216+ Hashtbl. to_seq_keys selected_students |>
217+ Seq. filter_map (function `Token tk -> Some tk | `Any -> None ) |>
218+ List. of_seq
219+ in
220+ retrieve (Learnocaml_api. Students_csv (token, exercises, students))
221+ > |= fun csv ->
222+ Learnocaml_common. fake_download
223+ ~name: " learnocaml.csv"
224+ ~contents: (Js. string csv)
225+ in
226+
186227 (* Exercises table *)
187228 let rec mk_table group_level acc status group =
188229 match group with
@@ -211,7 +252,7 @@ let rec teacher_tab token _select _params () =
211252 in
212253 let open_partition_ () =
213254 Lwt. async (fun () ->
214- ask_string ~title: " Choose a function name "
255+ ask_string ~title: " Partitioning of student solutions "
215256 [H. txt @@ " Choose a function name to partition codes from " ^ id ^ " : " ]
216257 > |= fun funname ->
217258 let _win =
@@ -258,12 +299,13 @@ let rec teacher_tab token _select _params () =
258299 H. td [stars_div meta.Exercise.Meta. stars];
259300 H. td [
260301 let cls, text =
261- if Token.Map. is_empty ES. (st.assignments.token_map) then
262- match ES. (st.assignments.default) with
263- | ES. Open -> " exo_open" , [% i" Open" ]
264- | ES. Closed -> " exo_closed" , [% i" Closed" ]
265- | ES. Assigned _ -> " exo_assigned" , [% i" Assigned" ]
266- else " exo_assigned" , [% i" Assigned" ]
302+ match Token.Map. is_empty ES. (st.assignments.token_map),
303+ ES. (st.assignments.default) with
304+ | true , ES. Open -> " exo_open" , [% i" Open" ]
305+ | true , ES. Closed -> " exo_closed" , [% i" Closed" ]
306+ | _ , (ES. Assigned _ | ES. Closed ) ->
307+ " exo_assigned" , [% i" Assigned" ]
308+ | false , ES. Open -> " exo_assigned" , [% i" Open/Assg" ]
267309 in
268310 H. span ~a: [H. a_class [cls]] [H. txt text]
269311 ];
@@ -328,11 +370,14 @@ let rec teacher_tab token _select _params () =
328370 let exercise_skills_list_id = " exercise_skills_list" in
329371 let exercises_div =
330372 let legend =
331- H. legend ~a: [
332- H. a_onclick (fun _ ->
333- ! toggle_selected_exercises (all_exercises ! exercises_index);
334- true );
335- ] [H. txt [% i" Exercises" ]; H. txt " \xe2\x98\x90 " (* U+2610 *) ]
373+ H. legend [
374+ H. span
375+ [ H. txt [% i" Exercises" ]; H. txt " \xe2\x98\x90 " (* U+2610 *) ]
376+ ~a: [H. a_onclick (fun _ ->
377+ ! toggle_selected_exercises (all_exercises ! exercises_index);
378+ true )];
379+ help_button " exercises" Learnocaml_teacher_tab_doc. exercises_pane_md
380+ ]
336381 in
337382 H. div ~a: [H. a_id " exercises_pane" ; H. a_class [" learnocaml_pane" ]] [
338383 H. div ~a: [H. a_id " exercises_filter_box" ] [
@@ -530,23 +575,26 @@ let rec teacher_tab token _select _params () =
530575 in
531576 let students_div =
532577 let legend =
533- H. legend ~a: [
534- H. a_onclick (fun _ ->
535- let all =
536- Token.Map. fold (fun k _ acc -> (`Token k)::acc)
537- ! students_map [`Any ]
538- in
539- let all =
540- List. filter (fun t ->
541- not (Manip. hasClass (find_component (student_line_id t))
542- " student_hidden" ))
543- all
544- in
545- ! toggle_selected_students all;
546- true
547- );
548- ] [H. txt [% i" Students" ];
549- H. txt " \xe2\x98\x90 " (* U+2610 ballot box *) ]
578+ H. legend [
579+ H. span
580+ [ H. txt [% i" Students" ];
581+ H. txt " \xe2\x98\x90 " (* U+2610 ballot box *) ]
582+ ~a: [H. a_onclick (fun _ ->
583+ let all =
584+ Token.Map. fold (fun k _ acc -> (`Token k)::acc)
585+ ! students_map [`Any ]
586+ in
587+ let all =
588+ List. filter (fun t ->
589+ not (Manip. hasClass (find_component (student_line_id t))
590+ " student_hidden" ))
591+ all
592+ in
593+ ! toggle_selected_students all;
594+ true
595+ )];
596+ help_button " students" Learnocaml_teacher_tab_doc. students_pane_md
597+ ]
550598 in
551599 H. div ~a: [H. a_id " students_pane" ; H. a_class [" learnocaml_pane" ]] [
552600 H. div ~a: [H. a_id " students_filter_box" ] [
@@ -812,12 +860,10 @@ let rec teacher_tab token _select _params () =
812860 ES. (default_assignment st.assignments = Open ))
813861 ids
814862 then ES. (fun assg ->
815- (* fixme: invisible change if the exercise is assigned! *)
816863 match default_assignment assg with
817864 | Open -> set_default_assignment assg Closed
818865 | _ -> assg)
819866 else ES. (fun assg ->
820- (* fixme: invisible change if the exercise is assigned! *)
821867 match default_assignment assg with
822868 | Closed -> set_default_assignment assg Open
823869 | _ -> assg)
@@ -841,9 +887,16 @@ let rec teacher_tab token _select _params () =
841887 Manip. appendChild exercises_div exercise_control_div;
842888 let assignments_div = H. div [] in
843889 let control_div =
890+ let legend =
891+ H. legend [
892+ H. txt [% i" Assignments" ];
893+ help_button " assignments"
894+ Learnocaml_teacher_tab_doc. assignments_pane_md
895+ ]
896+ in
844897 H. div ~a: [H. a_id " control_pane" ] [
845898 H. fieldset
846- ~legend: ( H. legend [ H. txt [ % i " Assignments " ]])
899+ ~legend
847900 [assignments_div];
848901 ]
849902 in
@@ -932,7 +985,7 @@ let rec teacher_tab token _select _params () =
932985 H. li ~a: [ H. a_onclick (fun _ -> Lwt. async action_new_token; true ) ]
933986 [ H. txt [% i" Create new teacher token" ] ];
934987 H. li ~a: [ H. a_onclick (fun _ -> Lwt. async action_csv_export; true ) ]
935- [ H. txt [% i" Download student data as CSV" ] ];
988+ [ H. txt [% i" Download the data for selected students/exercises as CSV" ] ];
936989 ]
937990 ];
938991 ]
@@ -1102,10 +1155,16 @@ let rec teacher_tab token _select _params () =
11021155 if SMap. is_empty ! status_changes &&
11031156 Token.Map. is_empty ! students_changes then
11041157 (Manip. replaceChildren status_text_div [] ;
1105- Manip. removeClass status_text_div " warning" )
1158+ Manip. removeClass status_text_div " warning" ;
1159+ Option. iter
1160+ (fun b -> Manip. removeClass b " warning" )
1161+ (Manip. by_id " button_apply" ))
11061162 else
11071163 (Manip. replaceChildren status_text_div [H. txt [% i" Unsaved changes" ]];
1108- Manip. addClass status_text_div " warning" )
1164+ Manip. addClass status_text_div " warning" ;
1165+ Option. iter
1166+ (fun b -> Manip. addClass b " warning" )
1167+ (Manip. by_id " button_apply" ))
11091168 end;
11101169 toggle_selected_exercises := begin
11111170 fun ?force ?(update = force= None ) ids ->
0 commit comments