diff options
author | Adam Chlipala <adamc@hcoop.net> | 2009-11-01 14:26:20 -0500 |
---|---|---|
committer | Adam Chlipala <adamc@hcoop.net> | 2009-11-01 14:26:20 -0500 |
commit | 70da89d392d5c9649157e53944db9a49d2149da3 (patch) | |
tree | 554465c7355d6fe0d310a16f4a7fa5a4e0675870 | |
parent | 7aaaa9a22a7eede386cda3cfbb3fc906619415d9 (diff) |
Initial form for paper assignment
-rw-r--r-- | demo/more/bid.ur | 92 | ||||
-rw-r--r-- | demo/more/checkGroup.ur | 15 | ||||
-rw-r--r-- | demo/more/checkGroup.urs | 5 | ||||
-rw-r--r-- | demo/more/conference.ur | 16 | ||||
-rw-r--r-- | demo/more/conference.urp | 2 | ||||
-rw-r--r-- | demo/more/conference.urs | 3 | ||||
-rw-r--r-- | demo/more/expandable.ur | 23 | ||||
-rw-r--r-- | demo/more/expandable.urs | 6 | ||||
-rw-r--r-- | include/urweb.h | 1 | ||||
-rw-r--r-- | src/c/urweb.c | 31 | ||||
-rw-r--r-- | src/jscomp.sml | 2 | ||||
-rw-r--r-- | src/monoize.sml | 2 |
12 files changed, 186 insertions, 12 deletions
diff --git a/demo/more/bid.ur b/demo/more/bid.ur index 692f8e14..931fc9c0 100644 --- a/demo/more/bid.ur +++ b/demo/more/bid.ur @@ -7,6 +7,79 @@ functor Make(M : Conference.INPUT) = struct table assignment : {User : userId, Paper : paperId} PRIMARY KEY (User, Paper) + fun intOut ch = + case ch of + #"_" => "Maybe" + | #"-" => "No" + | #"+" => "Yes" + | _ => error <xml>Bid: Invalid Interest code</xml> + + val linksForChair = + let + fun assignPapers () = + tup <- query (SELECT paper.Id, paper.{{M.paper}}, user.Id, user.Nam, bid.Interest + FROM paper JOIN bid ON bid.Paper = paper.Id + JOIN user ON bid.User = user.Id + ORDER BY paper.Id, bid.Interest, user.Nam) + (fn r (pid, int, acc, ints, papers) => + if pid = Some r.Paper.Id then + if int = r.Bid.Interest then + return (pid, int, (r.User.Id, r.User.Nam) :: acc, ints, papers) + else + return (pid, r.Bid.Interest, (r.User.Id, r.User.Nam) :: [], + (int, acc) :: ints, papers) + else + return (Some r.Paper.Id, r.Bid.Interest, + (r.User.Id, r.User.Nam) :: [], [], + case pid of + None => papers + | Some pid => (pid, (int, acc) :: ints) :: papers)) + (None, #" ", [], [], []); + let + val papersL = case tup.1 of + Some pid => (pid, (tup.2, tup.3) :: tup.4) :: tup.5 + | _ => [] + + fun makePapers () = List.mapM (fn (pid, ints) => + ints <- List.mapM (fn (int, users) => + cg <- CheckGroup.create + (List.mp + (fn (id, nam) => (id, txt nam, + False)) + users); + ex <- Expandable.create + (CheckGroup.render cg); + return (int, cg, ex)) ints; + return (pid, ints)) papersL + in + papers <- source []; + + return <xml><body onload={papersL <- makePapers (); + set papers papersL}> + <h1>Assign papers</h1> + + <dyn signal={papers <- signal papers; + return (List.mapX (fn (pid, ints) => <xml> + <hr/> + Paper #{[pid]}: + <dyn signal={n <- List.foldl (fn (_, cg, _) total => + this <- CheckGroup.selected cg; + total <- total; + return (List.length this + total)) (return 0) ints; + return (txt n)}/><br/> + + {List.mapX (fn (int, _, ex) => <xml> + {[intOut int]}: {Expandable.render ex} + </xml>) ints} + </xml>) papers)}/> + </body></xml> + end + in + <xml> + <li><a link={assignPapers ()}> Assign papers to people</a></li> + </xml> + end + val linksForPc = let fun yourBids () = @@ -14,16 +87,15 @@ functor Make(M : Conference.INPUT) = struct ps <- queryX (SELECT paper.Id, paper.{{M.paper}}, bid.Interest FROM paper LEFT JOIN bid ON bid.Paper = paper.Id AND bid.User = {[me.Id]}) - (fn r => <xml><entry> - <hidden{#Paper} value={show r.Paper.Id}/> - {useMore <xml><tr> - <td>{summarizePaper (r.Paper -- #Id)}</td> - <td><select{#Bid}> - {Select.selectChar ((#"-", "No") :: (#"_", "Maybe") :: (#"+", "Yes") :: []) - r.Bid.Interest} - </select></td> - </tr></xml>} - </entry></xml>); + (fn r => <xml><tr> + <td>{useMore (summarizePaper (r.Paper -- #Id))}</td> + <td><entry> + <hidden{#Paper} value={show r.Paper.Id}/> + <select{#Bid}> + {useMore (Select.selectChar ((#"-", "No") :: (#"_", "Maybe") :: (#"+", "Yes") :: []) + r.Bid.Interest)} + </select></entry></td> + </tr></xml>); return <xml><body> <h1>Bid on papers</h1> diff --git a/demo/more/checkGroup.ur b/demo/more/checkGroup.ur new file mode 100644 index 00000000..ab1cc781 --- /dev/null +++ b/demo/more/checkGroup.ur @@ -0,0 +1,15 @@ +con t ctx data = list (data * xml ctx [] [] * source bool) + +fun create [ctx] [data] (items : list (data * xml ctx [] [] * bool)) = + List.mapM (fn (d, x, b) => s <- source b; return (d, x, s)) items + +fun render [ctx] [data] [[Body] ~ ctx] (t : t ([Body] ++ ctx) data) = + List.mapX (fn (_, x, s) => <xml><ccheckbox source={s}/> {x}<br/></xml>) t + +fun selected [ctx] [data] (t : t ctx data) = + List.foldlM (fn (d, _, s) ls => + s <- signal s; + return (if s then + d :: ls + else + ls)) [] t diff --git a/demo/more/checkGroup.urs b/demo/more/checkGroup.urs new file mode 100644 index 00000000..d448527e --- /dev/null +++ b/demo/more/checkGroup.urs @@ -0,0 +1,5 @@ +con t :: {Unit} -> Type -> Type + +val create : ctx ::: {Unit} -> data ::: Type -> list (data * xml ctx [] [] * bool) -> transaction (t ctx data) +val render : ctx ::: {Unit} -> data ::: Type -> [[Body] ~ ctx] => t ([Body] ++ ctx) data -> xml ([Body] ++ ctx) [] [] +val selected : ctx ::: {Unit} -> data ::: Type -> t ctx data -> signal (list data) diff --git a/demo/more/conference.ur b/demo/more/conference.ur index e810043b..7b3d3d71 100644 --- a/demo/more/conference.ur +++ b/demo/more/conference.ur @@ -12,12 +12,14 @@ signature INPUT = sig val paperId_inj : sql_injectable_prim paperId val paperId_show : show paperId val paperId_read : read paperId + val paperId_eq : eq paperId table paper : ([Id = paperId, Document = blob] ++ paper) PRIMARY KEY Id val checkLogin : transaction (option {Id : userId, Nam : string, Chair : bool, OnPc : bool}) val getLogin : transaction {Id : userId, Nam : string, Chair : bool, OnPc : bool} val getPcLogin : transaction {Id : userId, Nam : string, Chair : bool} + val checkChair : transaction unit val summarizePaper : ctx ::: {Unit} -> [[Body] ~ ctx] => $paper -> xml ([Body] ++ ctx) [] [] end @@ -27,6 +29,7 @@ signature OUTPUT = sig type paperId val linksForPc : xbody + val linksForChair : xbody con yourPaperTables :: {{Type}} constraint [Paper] ~ yourPaperTables @@ -105,12 +108,20 @@ functor Make(M : sig else error <xml>You are not on the PC.</xml> + val checkChair = + r <- getLogin; + if r.Chair then + return () + else + error <xml>You are not a chair.</xml> + structure O = M.Make(struct val user = user val paper = paper val checkLogin = checkLogin val getLogin = getLogin val getPcLogin = getPcLogin + val checkChair = checkChair val summarizePaper = @@M.summarizePaper end) @@ -203,7 +214,10 @@ functor Make(M : sig <div>Welcome, {[me.Nam]}!</div> {if me.Chair then - <xml><li><a link={Users.main ()}>Manage users</a></li></xml> + <xml> + <li><a link={Users.main ()}>Manage users</a></li> + {O.linksForChair} + </xml> else <xml/>} diff --git a/demo/more/conference.urp b/demo/more/conference.urp index 844baed9..9e0d8eaa 100644 --- a/demo/more/conference.urp +++ b/demo/more/conference.urp @@ -9,4 +9,6 @@ dnat conference conferenceFields select +checkGroup +expandable bid diff --git a/demo/more/conference.urs b/demo/more/conference.urs index f9729851..2f24bac8 100644 --- a/demo/more/conference.urs +++ b/demo/more/conference.urs @@ -12,12 +12,14 @@ signature INPUT = sig val paperId_inj : sql_injectable_prim paperId val paperId_show : show paperId val paperId_read : read paperId + val paperId_eq : eq paperId table paper : ([Id = paperId, Document = blob] ++ paper) PRIMARY KEY Id val checkLogin : transaction (option {Id : userId, Nam : string, Chair : bool, OnPc : bool}) val getLogin : transaction {Id : userId, Nam : string, Chair : bool, OnPc : bool} val getPcLogin : transaction {Id : userId, Nam : string, Chair : bool} + val checkChair : transaction unit val summarizePaper : ctx ::: {Unit} -> [[Body] ~ ctx] => $paper -> xml ([Body] ++ ctx) [] [] end @@ -27,6 +29,7 @@ signature OUTPUT = sig type paperId val linksForPc : xbody + val linksForChair : xbody con yourPaperTables :: {{Type}} constraint [Paper] ~ yourPaperTables diff --git a/demo/more/expandable.ur b/demo/more/expandable.ur new file mode 100644 index 00000000..92d8743c --- /dev/null +++ b/demo/more/expandable.ur @@ -0,0 +1,23 @@ +con t ctx = source bool * xml ctx [] [] + +fun create [ctx] (x : xml ctx [] []) = + s <- source False; + return (s, x) + +fun expand [ctx] (t : t ctx) = + set t.1 True + +fun collapse [ctx] (t : t ctx) = + set t.1 False + +fun render [ctx] [[Body] ~ ctx] (t : t ([Body] ++ ctx)) = + <xml><dyn signal={b <- signal t.1; + return (if b then + <xml> + <button value="-" onclick={collapse t}/><br/> + {t.2} + </xml> + else + <xml> + <button value="+" onclick={expand t}/><br/> + </xml>)}/></xml> diff --git a/demo/more/expandable.urs b/demo/more/expandable.urs new file mode 100644 index 00000000..820b89b7 --- /dev/null +++ b/demo/more/expandable.urs @@ -0,0 +1,6 @@ +con t :: {Unit} -> Type + +val create : ctx ::: {Unit} -> xml ctx [] [] -> transaction (t ctx) +val render : ctx ::: {Unit} -> [[Body] ~ ctx] => t ([Body] ++ ctx) -> xml ([Body] ++ ctx) [] [] +val expand : ctx ::: {Unit} -> t ctx -> transaction unit +val collapse : ctx ::: {Unit} -> t ctx -> transaction unit diff --git a/include/urweb.h b/include/urweb.h index ef5fc5a4..0f753b71 100644 --- a/include/urweb.h +++ b/include/urweb.h @@ -153,6 +153,7 @@ uw_Basis_string uw_Basis_sqlifyTimeN(uw_context, uw_Basis_time*); char *uw_Basis_ensqlBool(uw_Basis_bool); char *uw_Basis_jsifyString(uw_context, uw_Basis_string); +char *uw_Basis_jsifyChar(uw_context, uw_Basis_char); char *uw_Basis_jsifyChannel(uw_context, uw_Basis_channel); uw_Basis_string uw_Basis_intToString(uw_context, uw_Basis_int); diff --git a/src/c/urweb.c b/src/c/urweb.c index 3cf8fd47..8d63d174 100644 --- a/src/c/urweb.c +++ b/src/c/urweb.c @@ -1232,6 +1232,37 @@ uw_Basis_string uw_Basis_jsifyString(uw_context ctx, uw_Basis_string s) { return r; } +uw_Basis_string uw_Basis_jsifyChar(uw_context ctx, uw_Basis_char c) { + char *r, *s2; + + uw_check_heap(ctx, 6); + + r = s2 = ctx->heap.front; + *s2++ = '"'; + + switch (c) { + case '"': + strcpy(s2, "\\\""); + s2 += 2; + break; + case '\\': + strcpy(s2, "\\\\"); + s2 += 2; + break; + default: + if (isprint(c)) + *s2++ = c; + else { + sprintf(s2, "\\%3o", c); + s2 += 4; + } + } + + strcpy(s2, "\""); + ctx->heap.front = s2 + 2; + return r; +} + uw_Basis_string uw_Basis_jsifyString_ws(uw_context ctx, uw_Basis_string s) { char *r, *s2; diff --git a/src/jscomp.sml b/src/jscomp.sml index c6b8e7b9..8b946b39 100644 --- a/src/jscomp.sml +++ b/src/jscomp.sml @@ -122,6 +122,7 @@ fun process file = end | TFfi ("Basis", "string") => ((EFfiApp ("Basis", "jsifyString", [e]), loc), st) + | TFfi ("Basis", "char") => ((EFfiApp ("Basis", "jsifyChar", [e]), loc), st) | TFfi ("Basis", "int") => ((EFfiApp ("Basis", "htmlifyInt", [e]), loc), st) | TFfi ("Basis", "float") => ((EFfiApp ("Basis", "htmlifyFloat", [e]), loc), st) | TFfi ("Basis", "channel") => ((EFfiApp ("Basis", "jsifyChannel", [e]), loc), st) @@ -307,6 +308,7 @@ fun process file = end | TFfi ("Basis", "string") => ("uu(t[i++])", st) + | TFfi ("Basis", "char") => ("uu(t[i++])", st) | TFfi ("Basis", "int") => ("parseInt(t[i++])", st) | TFfi ("Basis", "float") => ("parseFloat(t[i++])", st) | TFfi ("Basis", "channel") => ("(t[i++].length > 0 ? parseInt(t[i]) : null)", st) diff --git a/src/monoize.sml b/src/monoize.sml index 4e337388..3e3cc54f 100644 --- a/src/monoize.sml +++ b/src/monoize.sml @@ -3006,7 +3006,7 @@ fun monoExp (env, st, fm) (all as (e, loc)) = action in - ((L'.EStrcat ((L'.EStrcat ((L'.EPrim (Prim.String "<form method=\"post\""), loc), + ((L'.EStrcat ((L'.EStrcat ((L'.EPrim (Prim.String "<form method=\"get\""), loc), (L'.EStrcat (action, (L'.EPrim (Prim.String ">"), loc)), loc)), loc), (L'.EStrcat (xml, |