View raw

1 open Dream_html 2 open Page_kit 3 open Page_shell 4 5 (* The authenticated application feedback page. It keeps writing and reviewing 6 feedback in separate tabs, while both tabs remain plain links for no-script 7 use and progressive enhancement. *) 8 9 let app_feedback_form request ?error () = 10 let error_block = 11 match error with None -> [] | Some message -> [ alert message ] 12 in 13 tag "form" 14 [ 15 action Routes.submit_app_feedback; 16 post_form; 17 class_ "app-feedback-form"; 18 Dream_html.attr "data-hito-app-form"; 19 ] 20 (Dream_html.csrf_tag request 21 :: tag "label" 22 [ Dream_html.string_attr "for" "app-feedback-message" ] 23 [ txt "Your feedback" ] 24 :: tag "textarea" 25 [ 26 name "message"; 27 id "app-feedback-message"; 28 Dream_html.string_attr "rows" "8"; 29 required; 30 Dream_html.string_attr "placeholder" 31 "Tell us what works well or what needs attention."; 32 ] 33 [] 34 :: error_block 35 @ [ void "input" [ type_ "submit"; value "Submit feedback" ] ]) 36 37 let app_feedback_vote_form request (report : View_model.App_feedback.t) = 38 if report.viewer_owns then 39 tag "p" [ class_ "app-feedback-own" ] [ txt "Your feedback" ] 40 else 41 let label = 42 if report.viewer_upvoted then "Upvoted" 43 else Printf.sprintf "Upvote (%d)" report.upvotes 44 in 45 let attrs = 46 [ 47 action Routes.upvote_app_feedback report.id; 48 post_form; 49 class_ "app-feedback-vote"; 50 Dream_html.attr "data-hito-app-form"; 51 ] 52 in 53 let attrs = 54 if report.viewer_upvoted then Dream_html.attr "disabled" :: attrs 55 else attrs 56 in 57 tag "form" attrs 58 [ 59 Dream_html.csrf_tag request; 60 void "input" 61 [ type_ "submit"; Dream_html.string_attr "value" "%s" label ]; 62 ] 63 64 let app_feedback_edit_form request (report : View_model.App_feedback.t) = 65 tag "form" 66 [ 67 action Routes.edit_app_feedback report.id; 68 post_form; 69 class_ "app-feedback-edit-form"; 70 Dream_html.attr "data-hito-app-form"; 71 ] 72 [ 73 Dream_html.csrf_tag request; 74 tag "label" 75 [ Dream_html.string_attr "for" "app-feedback-edit-%s" report.id ] 76 [ txt "Edit feedback" ]; 77 tag "textarea" 78 [ 79 name "message"; 80 Dream_html.string_attr "id" "app-feedback-edit-%s" report.id; 81 Dream_html.string_attr "rows" "4"; 82 required; 83 ] 84 [ txt "%s" report.message ]; 85 void "input" [ type_ "submit"; value "Save edit" ]; 86 ] 87 88 let app_feedback_remove_form request (report : View_model.App_feedback.t) = 89 tag "form" 90 [ 91 action Routes.remove_app_feedback report.id; 92 post_form; 93 class_ "app-feedback-remove-form"; 94 Dream_html.attr "data-hito-app-form"; 95 ] 96 [ 97 Dream_html.csrf_tag request; 98 void "input" [ type_ "submit"; value "Remove feedback" ]; 99 ] 100 101 let app_feedback_actions request (report : View_model.App_feedback.t) = 102 if report.viewer_owns then 103 tag "div" 104 [ class_ "app-feedback-actions" ] 105 [ 106 app_feedback_edit_form request report; 107 app_feedback_remove_form request report; 108 ] 109 else 110 tag "div" 111 [ class_ "app-feedback-actions" ] 112 [ app_feedback_vote_form request report ] 113 114 let app_feedback request ?workout_started ~viewer ?(tab = `Write) ?error reports 115 = 116 let panel = 117 match tab with 118 | `Write -> 119 [ 120 tag "h2" [] [ txt "Write feedback" ]; 121 tag "p" [] 122 [ txt "Tell us about your experience using the application." ]; 123 app_feedback_form request ?error (); 124 ] 125 | `Submitted -> 126 [ 127 tag "h2" [] [ txt "Submitted feedback" ]; 128 (if reports = [] then 129 tag "p" [] 130 [ txt "You have not submitted any application feedback." ] 131 else 132 tag "ul" 133 [ class_ "app-feedback-list" ] 134 (List.map 135 (fun (report : View_model.App_feedback.t) -> 136 tag "li" [] 137 [ 138 tag "p" 139 [ class_ "app-feedback-author" ] 140 [ 141 txt "%s — %d contributions" report.author 142 report.contributions; 143 ]; 144 tag "time" 145 [ 146 class_ "app-feedback-time"; 147 Dream_html.string_attr "datetime" "%s" 148 report.submitted_at; 149 ] 150 [ txt "%s" report.submitted_at ]; 151 tag "p" 152 [ class_ "app-feedback-message" ] 153 [ txt "%s" report.message ]; 154 tag "p" 155 [ class_ "app-feedback-upvotes" ] 156 [ txt "Upvotes: %d" report.upvotes ]; 157 app_feedback_actions request report; 158 ]) 159 reports)); 160 ] 161 in 162 html_page ~viewer ~request ~active:"app-feedback" ?workout_started 163 "App Feedback" 164 ([ 165 tag "h1" [] [ txt "App Feedback" ]; 166 tag "p" [] [ txt "Help us improve hito by sharing your experience." ]; 167 link_tabs ~aria_label:"App feedback views" 168 ~active: 169 (match tab with `Write -> "write" | `Submitted -> "submitted") 170 [ 171 ("write", "Write feedback", "/app-feedback?tab=write"); 172 ("submitted", "Submitted feedback", "/app-feedback?tab=submitted"); 173 ]; 174 ] 175 @ panel) 176