diff --git a/files/style.css b/files/style.css index 2167f94..e3f3890 100644 --- a/files/style.css +++ b/files/style.css @@ -1,13 +1,83 @@ -body { - font-family: Verdana,Geneva,Arial,Sans-serif; - font-size: 12px; - background-color : #FFFFFF + * { + box-sizing: border-box; +} + +.grid-container { + display: grid; + grid-template-columns: auto; + gap: 10px; + padding: 10px; +} + +@media only screen and (min-width: 768px) { + .grid-container { grid-template-columns: 300px auto;} +} + +ul.topbar { + list-style-type: none; + margin: 0; + padding: 0; + overflow: hidden; + border: 1px solid #e7e7e7; + background-color: #f3f3f3; +} + +ul.topbar li { + height: 100%; + display: block; + float: left; + height: 50px; +} + +ul.topbar li a { + display: block; + color: #666; + text-align: center; + padding: 14px 16px; + text-decoration: none; + text-align: center; + height: 50px; +} + +ul.topbar li a:hover:not(.active) {background-color: #ddd;} + +ul.topbar li a.active {background-color: #04AA6D;} + +ul.topbar li.right {float: right;} + +@media screen and (max-width: 768px) { + ul.topbar li.right, + ul.topbar li { + float: none; + border: 1px solid #e7e7e7; + } +} + +.center-horizontal { + display: grid; + grid-template-columns: auto auto; + align-items: center; + justify-content: center; + height: 55%; + padding: 0; + margin: 0; +} + +body { + font-family: Verdana,Geneva,Arial,Sans-serif; + font-size: 12px; + background-color : #FFFFFF; + margin: 0; } img { border: 0px none; } +.topbar img { + padding-right: 5px; +} + a:visited { color : #000080; ; text-decoration : underline; } a:link { color : #2222FF; ; text-decoration : underline; } a:hover { text-decoration : none; } @@ -25,12 +95,6 @@ a.missing_page:visited { color : Red; text-decoration : underline; } a.missing_page:link { color : Red; text-decoration : underline; } a.missing_page:hover { color : Red; text-decoration : none; } -/* Accesskey'd links -- first letter underlined */ -a.ak { text-decoration: underline; } -a.ak:hover { color:#2222FF; text-decoration: none;} -a.ak:focus { color:#2222FF; text-decoration: none;} -a.ak:first-letter { color:#2222FF; text-decoration: none; font-weight:bold; } - a.palette0 { color:rgb(128, 6, 25); } a.palette1 { color:rgb(0, 104, 28); } a.palette2 { color:rgb(0, 148, 145); } @@ -101,7 +165,7 @@ h1 { } h1.left_aligned { - text-align: left; + text-align: left; } h4 { @@ -139,7 +203,7 @@ html, body { #login_align_middle { position:absolute; - top: 35%; + top: 35%; left: 30%; text-align:left; padding: 5px; @@ -174,7 +238,7 @@ table.login_box { color:#000; } -.undo_link { +.undo_link { color:#338; } @@ -202,17 +266,13 @@ table.login_box { } #navbar { - width: 300px; - float: left; - margin-left: 0px; margin-top: 2px; padding: 12px; + background-color: #f1f1f1; } - - + #content { padding: 5px; - margin-left: 400px; } a#login_help_url { diff --git a/ocsigenserver.conf.in b/ocsigenserver.conf.in index 58345b9..f12def9 100644 --- a/ocsigenserver.conf.in +++ b/ocsigenserver.conf.in @@ -16,8 +16,9 @@ - + + diff --git a/src/database.ml b/src/database.ml index f275350..9ef205e 100644 --- a/src/database.ml +++ b/src/database.ml @@ -22,8 +22,6 @@ open Config type connection = Psql.connection -let ( |> ) f g = g f - module ConnectionPool = struct open Psql diff --git a/src/history.ml b/src/history.ml index 8c51054..ab35e12 100644 --- a/src/history.ml +++ b/src/history.ml @@ -32,8 +32,6 @@ open CalendarLib module Db = Database -let ( & ) f x = f x - let n_log_items_per_page = 300 let descr_of_activity_type = function @@ -203,7 +201,7 @@ let view_history_page ~cur_user ~nth_page = [tr [td ~a:[a_class ["no_break"; "h_date_heading"]] date_text]] @ lst_acc, prettified_date)) activity_groups ([],"")))) in - return & Html_util.html_stub ~title:"History" + return @@ Html_util.html_stub ~title:"History" (Html_util.navbar_html ~cur_user ([h1 [txt "Blast from the past"]] @ (page_links nth_page n_total_pages) @ [br (); br ()] @ diff --git a/src/html_util.ml b/src/html_util.ml index bc9a897..77bfcd6 100644 --- a/src/html_util.ml +++ b/src/html_util.ml @@ -41,11 +41,12 @@ let html_stub ?(javascript=[]) ~title body_html = html ~a:[a_xmlns `W3_org_1999_xhtml] (head (Eliom_content.Html.F.title (txt (title ^ " — Nurpawiki"))) - ((scripts) @ - [css_link ~a:[] ~uri:(make_uri ~service:(static_dir ()) - ["style.css"]) (); - css_link ~a:[] ~uri:(make_uri ~service:(static_dir ()) - ["jscalendar"; "calendar-blue2.css"]) ()])) + (meta ~a:[ a_name "viewport"; a_content "width=device-width, initial-scale=1" ] () :: + css_link ~a:[] ~uri:(make_uri ~service:(static_dir ()) + ["style.css"]) ():: + css_link ~a:[] ~uri:(make_uri ~service:(static_dir ()) + ["jscalendar"; "calendar-blue2.css"]) ():: + scripts)) (body body_html) let is_guest user = @@ -54,23 +55,23 @@ let is_guest user = let navbar_html ~cur_user ?(top_info_bar=[]) ?(wiki_revisions_link=[]) ?(wiki_page_links=[]) ?(todo_list_table=[]) content = let home_link link_text = a ~service:wiki_view_page - ~a:[a_accesskey 'h'; a_class ["ak"]] link_text + ~a:[a_accesskey 'h'] link_text (Config.site.cfg_homepage, (None, (None, None))) in let scheduler_link = a ~service:scheduler_page - ~a:[a_accesskey 'r'; a_class ["ak"]] - [img ~alt:"Scheduler" ~src:(make_static_uri ["calendar.png"]) (); - txt "Scheduler"] () in + ~a:[a_accesskey 'r'] + [div ~a:[a_class ["center-horizontal"]] [img ~alt:"Scheduler" ~src:(make_static_uri ["calendar.png"]) (); + txt "Scheduler"]] () in let history_link = a ~service:history_page - ~a:[a_accesskey 'r'; a_class ["ak"]] - [img ~alt:"History" ~src:(make_static_uri ["home.png"]) (); - txt "History"] None in + ~a:[a_accesskey 'r'] + [div ~a:[a_class ["center-horizontal"]] [img ~alt:"History" ~src:(make_static_uri ["home.png"]) (); + txt "History"]] None in let search_input = [get_form ~service:search_page (fun (chain : ([`One of string] param_name)) -> - [p [input ~input_type:`Submit ~value:"Search" Form.string; + [p [input ~a:[a_class ["button"]] ~input_type:`Submit ~value:"Search" Form.string; input ~input_type:`Text ~name:chain Form.string]])] in (* Greet user and offer Login link if guest *) @@ -89,48 +90,39 @@ let navbar_html ~cur_user ?(top_info_bar=[]) ?(wiki_revisions_link=[]) ?(wiki_pa [] in let disconnect_link = - if is_guest cur_user then [] else [disconnect_box "Logout"] in + if is_guest cur_user then [] else [li ~a:[a_class ["right"]] [disconnect_box "Logout"]] in let my_preferences_link = if is_guest cur_user then [] else - [a ~service:edit_user_page [txt "My Preferences"] - (None,cur_user.user_login)] in + [li ~a:[a_class ["right"]] [a ~service:edit_user_page [txt "My Preferences"] + (None,cur_user.user_login)]] in let edit_users_link = if Privileges.can_view_users cur_user then - [a ~service:user_admin_page [txt "Edit Users"] ()] + [li ~a:[a_class ["right"]] [a ~service:user_admin_page [txt "Edit Users"] ()]] else [] in - [div ~a:[a_id "topbar"] - [table ~a:[a_class ["top_menu_size"]] - [tr - [td ~a:[a_class ["top_menu_left_align"]] - [table - [tr [td [home_link - [img ~alt:"Home" ~src:(make_static_uri ["home.png"]) (); - txt "Home"]]; - td [scheduler_link]; - td [history_link]; - td wiki_page_links]] - ]; - td ~a:[a_class ["top_menu_right_align"]] - ([a ~service:about_page [txt "About"] ()] @ - [txt " "] @ - my_preferences_link @ - [txt " "] @ - edit_users_link @ - [txt " "] @ - disconnect_link)]]]] - @ + ul ~a:[a_class ["top_menu_size"; "topbar"]] + ([li [home_link [div ~a:[a_class ["center-horizontal"]] [img ~alt:"Home" + ~src:(make_static_uri ["home.png"]) (); txt "Home"]]]; + li [scheduler_link]; + li [history_link]] @ + List.map (fun l -> li [l]) wiki_page_links @ + [li ~a:[a_class ["right"]] [a ~service:about_page [txt "About"] ()]] @ + my_preferences_link @ + edit_users_link @ + disconnect_link) + :: (if top_info_bar = [] then [] else [div ~a:[a_id "top_action_bar"] top_info_bar]) @ - [div ~a:[a_id "navbar"] - (user_greeting @ [br ()] @ search_input @ wiki_revisions_link @ todo_list_table); - div ~a:[a_id "content"] - content] + [div ~a:[a_id "page"; a_class ["grid-container"]] + [div [div ~a:[a_id "navbar";] + (user_greeting @ [br ()] @ search_input @ wiki_revisions_link @ todo_list_table)]; + div ~a:[a_id "content"] + content]] let error text = span ~a:[a_class ["error"]] [txt text] diff --git a/src/main.ml b/src/main.ml index 3493752..f8a1480 100644 --- a/src/main.ml +++ b/src/main.ml @@ -33,19 +33,7 @@ module Psql = Postgresql module P = Printf (* TODO no need to extract here *) -let matches_pcre rex s = - try ignore (Pcre.extract ~rex s); true with Not_found -> false - -let ( |> ) f g = g f -let ( & ) f g = f g - -let rec filter_map f = function - | [] -> return [] - | x::xs -> - let%lwt ys = filter_map f xs in - match%lwt f x with - | Some y -> return & y::ys - | None -> return ys +let matches_pcre rex s = Pcre.pmatch ~rex s let newline_re = Pcre.regexp "\n" @@ -57,7 +45,7 @@ let task_side_effect_complete task_id () = begin Db.complete_task ~user_id:user.user_id task_id;%lwt let table = Eliom_request_info.get_request_cache () in - return & Polytables.set ~table ~key:action_completed_task ~value:task_id + return @@ Polytables.set ~table ~key:action_completed_task ~value:task_id end else return ()) @@ -80,7 +68,7 @@ let task_side_effect_mod_priority (task_id, dir) () = else Db.up_task_priority task_id;%lwt let table = Eliom_request_info.get_request_cache () in - return & Polytables.set ~table ~key:action_task_priority_changed ~value:task_id + return @@ Polytables.set ~table ~key:action_task_priority_changed ~value:task_id end else return ()) @@ -262,7 +250,7 @@ module WikiML = else (* External link *) let url = scheme^":"^page in let t = if text = "" then url else text in - return & Raw.a ~a:[a_href (uri_of_string (fun () -> url))] [ext_img; txt t] in + return @@ Raw.a ~a:[a_href (uri_of_string (fun () -> url))] [ext_img; txt t] in let add_html html_acc html = html::html_acc in @@ -301,7 +289,7 @@ module WikiML = let wiki_error s charpos = let s = (String.sub s charpos ((String.length s)-charpos)) in - return & + return @@ add_html acc (Html_util.error ("WIKI SYNTAX ERROR on line: '"^s^"'")) in @@ -383,7 +371,7 @@ module WikiML = let (after_bullets,bullets) = take_while is_list_or_empty lst in let%lwt list_items = - filter_map + Lwt_list.filter_map_s (function (`Wiki e) as wl -> if matches_pcre ws_or_empty_re e then @@ -395,7 +383,7 @@ module WikiML = Some r -> let n_stars = String.length r.(1) in let%lwt x = parse_text [] r.(2) in - return & Some (n_stars, x) + return @@ Some (n_stars, x) | None -> assert false end @@ -418,7 +406,7 @@ module WikiML = end | (`NoWiki x::xs) -> loop (pre [txt (String.concat "\n" x)]::acc) xs - | [] -> return & List.rev acc in + | [] -> return @@ List.rev acc in loop [] preprocessed_lines @@ -446,7 +434,7 @@ let todo_list_table_html ~cur_user cur_page todos = let priority_changes = Session.any_task_priority_changes () in - return & + return @@ table ~a:[a_class ["todo_table"]] @@ (tr [th [txt "Id"]; th [txt "Description"]]) :: @@ -475,12 +463,13 @@ let wiki_page_menu_html ~cur_user page content = let edit_link = [a ~service:wiki_edit_page ~a:[a_accesskey '1'; a_class ["ak"]] - [img ~alt:"Edit" ~src:(make_static_uri ["edit.png"]) (); - txt "Edit page"] page] in + [div ~a:[a_class ["center-horizontal"]] [img ~alt:"Edit" ~src:(make_static_uri ["edit.png"]) (); + txt "Edit page"]] page] in let printable_link = [a ~service:wiki_view_page - ~a:[a_accesskey 'p'; a_class ["ak"]] [txt "Print"] + ~a:[a_accesskey 'p'; a_class ["ak"]] + [div ~a:[a_class ["center-horizontal"]] [txt "Print"]] (page, (Some true,(None,None)))] in let revisions_link = @@ -504,8 +493,8 @@ let wiki_page_menu_html ~cur_user page content = ~service:task_side_effect_undo_complete_action [txt "Undo"] id]] in - return & Html_util.navbar_html ~cur_user - ~wiki_page_links:(edit_link @ [txt " "] @ printable_link) + return @@ Html_util.navbar_html ~cur_user + ~wiki_page_links:(edit_link @ printable_link) ~wiki_revisions_link:revisions_link ~top_info_bar ~todo_list_table:[todo_list] content @@ -519,14 +508,14 @@ let view_page ~cur_user ?(revision_id=None) page_id page_name ~printable = if printable <> None && Option.get printable = true then let%lwt page_content = wikiml_to_html ~cur_user page_id page_name ~revision_id todos in - return & Html_util.html_stub ~title:page_name page_content + return @@ Html_util.html_stub ~title:page_name page_content else let%lwt page_content = (wiki_page_contents_html ~cur_user page_id page_name ~revision_id todos ()) in - return & Html_util.html_stub ~title:page_name page_content + return @@ Html_util.html_stub ~title:page_name page_content (* Parse existing todo's from the current to-be-saved wiki page and update the DB relation on what todos are on the page. @@ -601,16 +590,16 @@ let check_new_and_removed_todos ~cur_user page_id lines = | None -> return ())) | None -> return ()) page_todos;%lwt - filter_map + Lwt_list.filter_map_s (fun e -> let id = int_of_string (fst e) in let%lwt b = Db.todo_exists id in - if b then return & Some id else return & None) page_todos >>= + if b then return @@ Some id else return @@ None) page_todos >>= (* Update DB "todos in pages" relation *) Db.update_page_todos page_id let global_substitute ?groups pat subst s = - Pcre.substitute_substrings ~rex:pat ~subst:(fun r -> subst r) s + Pcre.substitute_substrings ~rex:pat ~subst s let new_todo_re = Pcre.regexp ("\\[todo ("^WikiML.accepted_chars^")\\]") @@ -684,7 +673,7 @@ let _ = let%lwt page_id = Db.page_id_of_page_name page_name in let%lwt current_page_todos = Db.query_page_todos page_id in let%lwt x = load_wiki_page page_id ~revision_id:None in - return & + return @@ (page_id, current_page_todos, annotate_old_todo_items page_name current_page_todos x) @@ -709,7 +698,7 @@ let _ = wiki_page_contents_html ~cur_user ~revision_id:None page_id page_name page_todos ~content:[f] () in - return & Html_util.html_stub ~title:("Edit " ^ page_name) h + return @@ Html_util.html_stub ~title:("Edit " ^ page_name) h in Eliom_registration.Html.register ~service:wiki_edit_page @@ -727,7 +716,7 @@ let view_wiki_page ~cur_user (page_name, (printable, (revision_id, _))) = let f = a ~service:wiki_edit_page [txt "Create new page"] page_name in let%lwt h = wiki_page_menu_html ~cur_user page_name [f] in - return & Html_util.html_stub ~title:page_name h + return @@ Html_util.html_stub ~title:page_name h (* /view?p=Page *) let _ = diff --git a/src/scheduler.ml b/src/scheduler.ml index 2667d67..4961ad9 100644 --- a/src/scheduler.ml +++ b/src/scheduler.ml @@ -29,8 +29,6 @@ open Types open Util open CalendarLib -let ( & ) f x = f x - module Db = Database let clamp_date_to_today date = @@ -141,7 +139,7 @@ let view_scheduler_page ~cur_user = let table' = Form.post_form ~service:edit_todo_page table (ET_scheduler, None) in - return & + return @@ Html_util.html_stub ~title:"Scheduler" ~javascript:[["nurpawiki_scheduler.js"]] (Html_util.navbar_html ~cur_user ([h1 [txt "Road ahead"]] @ [table'])) in @@ -256,7 +254,7 @@ let rec render_todo_editor ~cur_user (src_page_cont, todos_to_edit) = [tr [td [Form.input ~input_type:`Submit ~value:"Save" Form.string; cancel_page src_page_cont]]])] in - return & + return @@ Form.post_form ~service:service_save_todo_item create_listform src_page_cont in let heading = [txt ("Edit TODOs "^todos_str)] in @@ -270,7 +268,7 @@ let rec render_todo_editor ~cur_user (src_page_cont, todos_to_edit) = ["nurpawiki_calendar.js"]] in - return & + return @@ Html_util.html_stub ~title:"Edit TODO(s)" ~javascript:calendar_js (Html_util.navbar_html ~cur_user ((h1 heading)::[help_str; br(); f]))