Mercurial > urweb
comparison demo/more/dbgrid.ur @ 930:51bc7681c47e
Nullable columns *might* be working, but too much JS is generated for the page to load in finite time
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sat, 12 Sep 2009 15:08:16 -0400 |
parents | 5e8b6fa5b48f |
children | 2422360c78a3 |
comparison
equal
deleted
inserted
replaced
929:095df8f710e0 | 930:51bc7681c47e |
---|---|
13 con colMeta = fn (row :: {Type}) (global_t :: (Type * Type)) => | 13 con colMeta = fn (row :: {Type}) (global_t :: (Type * Type)) => |
14 {Initialize : transaction global_t.1, | 14 {Initialize : transaction global_t.1, |
15 Handlers : global_t.1 -> colMeta' row global_t.2} | 15 Handlers : global_t.1 -> colMeta' row global_t.2} |
16 | 16 |
17 structure Direct = struct | 17 structure Direct = struct |
18 con metaBase = fn actual_input :: (Type * Type) => | |
19 {Display : actual_input.2 -> xbody, | |
20 Edit : actual_input.2 -> xbody, | |
21 Initialize : actual_input.1 -> transaction actual_input.2, | |
22 Parse : actual_input.2 -> signal (option actual_input.1)} | |
23 | |
24 datatype metaBoth actual input = | |
25 NonNull of metaBase (actual, input) * metaBase (option actual, input) | |
26 | Nullable of metaBase (actual, input) | |
27 | |
18 con meta = fn global_actual_input :: (Type * Type * Type) => | 28 con meta = fn global_actual_input :: (Type * Type * Type) => |
19 {Initialize : transaction global_actual_input.1, | 29 {Initialize : transaction global_actual_input.1, |
20 Handlers : global_actual_input.1 | 30 Handlers : global_actual_input.1 |
21 -> {Display : global_actual_input.3 -> xbody, | 31 -> metaBoth global_actual_input.2 global_actual_input.3} |
22 Edit : global_actual_input.3 -> xbody, | |
23 Initialize : global_actual_input.2 -> transaction global_actual_input.3, | |
24 Parse : global_actual_input.3 -> signal (option global_actual_input.2)}} | |
25 | 32 |
26 con editableState (ts :: (Type * Type * Type)) = (ts.1, ts.3) | 33 con editableState (ts :: (Type * Type * Type)) = (ts.1, ts.3) |
27 fun editable [ts] [rest] [nm :: Name] [[nm] ~ rest] name (m : meta ts) : colMeta ([nm = ts.2] ++ rest) | 34 fun editable [ts] [rest] [nm :: Name] [[nm] ~ rest] name (m : meta ts) : colMeta ([nm = ts.2] ++ rest) |
28 (editableState ts) = | 35 (editableState ts) = |
29 {Initialize = m.Initialize, | 36 let |
30 Handlers = fn data => {Header = name, | 37 fun doMr mr = {Header = name, |
31 Project = fn r => (m.Handlers data).Initialize r.nm, | 38 Project = fn r => mr.Initialize r.nm, |
32 Update = fn r s => | 39 Update = fn r s => |
33 vo <- current ((m.Handlers data).Parse s); | 40 vo <- current (mr.Parse s); |
34 return (case vo of | 41 return (case vo of |
35 None => r | 42 None => r |
36 | Some v => r -- nm ++ {nm = v}), | 43 | Some v => r -- nm ++ {nm = v}), |
37 Display = (m.Handlers data).Display, | 44 Display = mr.Display, |
38 Edit = (m.Handlers data).Edit, | 45 Edit = mr.Edit, |
39 Validate = fn s => vo <- (m.Handlers data).Parse s; return (Option.isSome vo)}} | 46 Validate = fn s => vo <- mr.Parse s; return (Option.isSome vo)} |
47 in | |
48 {Initialize = m.Initialize, | |
49 Handlers = fn data => case m.Handlers data of | |
50 NonNull (mr, _) => doMr mr | |
51 | Nullable mr => doMr mr} | |
52 end | |
40 | 53 |
41 con readOnlyState (ts :: (Type * Type * Type)) = (ts.1, ts.3) | 54 con readOnlyState (ts :: (Type * Type * Type)) = (ts.1, ts.3) |
42 fun readOnly [ts] [rest] [nm :: Name] [[nm] ~ rest] name (m : meta ts) : colMeta ([nm = ts.2] ++ rest) | 55 fun readOnly [ts] [rest] [nm :: Name] [[nm] ~ rest] name (m : meta ts) : colMeta ([nm = ts.2] ++ rest) |
43 (readOnlyState ts) = | 56 (readOnlyState ts) = |
44 {Initialize = m.Initialize, | 57 let |
45 Handlers = fn data => {Header = name, | 58 fun doMr mr = {Header = name, |
46 Project = fn r => (m.Handlers data).Initialize r.nm, | 59 Project = fn r => mr.Initialize r.nm, |
47 Update = fn r _ => return r, | 60 Update = fn r _ => return r, |
48 Display = (m.Handlers data).Display, | 61 Display = mr.Display, |
49 Edit = (m.Handlers data).Display, | 62 Edit = mr.Display, |
50 Validate = fn _ => return True}} | 63 Validate = fn _ => return True} |
64 in | |
65 {Initialize = m.Initialize, | |
66 Handlers = fn data => case m.Handlers data of | |
67 NonNull (mr, _) => doMr mr | |
68 | Nullable mr => doMr mr} | |
69 end | |
51 | 70 |
52 con metaBasic = fn actual_input :: (Type * Type) => | 71 con metaBasic = fn actual_input :: (Type * Type) => |
53 {Display : actual_input.2 -> xbody, | 72 {Display : actual_input.2 -> xbody, |
54 Edit : source actual_input.2 -> xbody, | 73 Edit : source actual_input.2 -> xbody, |
55 Initialize : actual_input.1 -> actual_input.2, | 74 Initialize : actual_input.1 -> actual_input.2, |
56 Parse : actual_input.2 -> option actual_input.1} | 75 InitializeNull : actual_input.2, |
76 IsNull : actual_input.2 -> bool, | |
77 Parse : actual_input.2 -> option actual_input.1} | |
57 | 78 |
58 con basicState = source | 79 con basicState = source |
59 fun basic [ts ::: (Type * Type)] (m : metaBasic ts) : meta (unit, ts.1, basicState ts.2) = | 80 fun basic [ts ::: (Type * Type)] (m : metaBasic ts) : meta (unit, ts.1, basicState ts.2) = |
60 {Initialize = return (), | 81 {Initialize = return (), |
61 Handlers = fn () => {Display = fn s => <xml><dyn signal={v <- signal s; return (m.Display v)}/></xml>, | 82 Handlers = fn () => NonNull ( |
83 {Display = fn s => <xml><dyn signal={v <- signal s; return (m.Display v)}/></xml>, | |
62 Edit = m.Edit, | 84 Edit = m.Edit, |
63 Initialize = fn v => source (m.Initialize v), | 85 Initialize = fn v => source (m.Initialize v), |
64 Parse = fn s => v <- signal s; return (m.Parse v)}} | 86 Parse = fn s => v <- signal s; return (m.Parse v)}, |
87 {Display = fn s => <xml><dyn signal={v <- signal s; return (m.Display v)}/></xml>, | |
88 Edit = m.Edit, | |
89 Initialize = fn v => source (case v of | |
90 None => m.InitializeNull | |
91 | Some v => m.Initialize v), | |
92 Parse = fn s => v <- signal s; | |
93 return (if m.IsNull v then | |
94 Some None | |
95 else | |
96 case m.Parse v of | |
97 None => None | |
98 | Some v' => Some (Some v'))})} | |
99 | |
100 fun nullable [global] [actual] [input] (m : meta (global, actual, input)) = | |
101 {Initialize = m.Initialize, | |
102 Handlers = fn d => case m.Handlers d of | |
103 Nullable _ => error <xml>Don't stack calls to Direct.nullable!</xml> | |
104 | NonNull (_, ho) => Nullable ho} | |
65 | 105 |
66 type intGlobal = unit | 106 type intGlobal = unit |
67 type intInput = basicState string | 107 type intInput = basicState string |
68 val int : meta (intGlobal, int, intInput) = | 108 val int : meta (intGlobal, int, intInput) = |
69 basic {Display = fn s => <xml>{[s]}</xml>, | 109 basic {Display = fn s => <xml>{[s]}</xml>, |
70 Edit = fn s => <xml><ctextbox source={s}/></xml>, | 110 Edit = fn s => <xml><ctextbox source={s}/></xml>, |
71 Initialize = fn n => show n, | 111 Initialize = fn n => show n, |
112 InitializeNull = "", | |
113 IsNull = eq "", | |
72 Parse = fn v => read v} | 114 Parse = fn v => read v} |
73 | 115 |
74 type stringGlobal = unit | 116 type stringGlobal = unit |
75 type stringInput = basicState string | 117 type stringInput = basicState string |
76 val string : meta (stringGlobal, string, stringInput) = | 118 val string : meta (stringGlobal, string, stringInput) = |
77 basic {Display = fn s => <xml>{[s]}</xml>, | 119 basic {Display = fn s => <xml>{[s]}</xml>, |
78 Edit = fn s => <xml><ctextbox source={s}/></xml>, | 120 Edit = fn s => <xml><ctextbox source={s}/></xml>, |
79 Initialize = fn s => s, | 121 Initialize = fn s => s, |
122 InitializeNull = "", | |
123 IsNull = eq "", | |
80 Parse = fn s => Some s} | 124 Parse = fn s => Some s} |
81 | 125 |
82 type boolGlobal = unit | 126 type boolGlobal = unit |
83 type boolInput = basicState bool | 127 type boolInput = basicState bool |
84 val bool : meta (boolGlobal, bool, boolInput) = | 128 val bool : meta (boolGlobal, bool, boolInput) = |
85 basic {Display = fn b => <xml>{[b]}</xml>, | 129 basic {Display = fn b => <xml>{[b]}</xml>, |
86 Edit = fn s => <xml><ccheckbox source={s}/></xml>, | 130 Edit = fn s => <xml><ccheckbox source={s}/></xml>, |
87 Initialize = fn b => b, | 131 Initialize = fn b => b, |
132 InitializeNull = False, | |
133 IsNull = fn _ => False, | |
88 Parse = fn b => Some b} | 134 Parse = fn b => Some b} |
89 | 135 |
90 functor Foreign (M : sig | 136 functor Foreign (M : sig |
91 con row :: {Type} | 137 con row :: {Type} |
92 con t :: Type | 138 con t :: Type |
100 val render : $([nm = t] ++ row) -> string | 146 val render : $([nm = t] ++ row) -> string |
101 end) = struct | 147 end) = struct |
102 open M | 148 open M |
103 | 149 |
104 con global = list (t * string) | 150 con global = list (t * string) |
105 con input = source string * t * $row | 151 con input = source string * option (t * $row) |
106 | 152 |
107 val getChoices = List.mapQuery (SELECT * FROM tab AS T) | 153 val getChoices = List.mapQuery (SELECT * FROM tab AS T) |
108 (fn r => (r.T.nm, render r.T)) | 154 (fn r => (r.T.nm, render r.T)) |
109 | 155 |
110 fun getChoice k = | 156 fun getChoice k = |
111 r <- oneRow (SELECT T.{{row}} FROM tab AS T WHERE T.{nm} = {[k]}); | 157 r <- oneRow (SELECT T.{{row}} FROM tab AS T WHERE T.{nm} = {[k]}); |
112 return r.T | 158 return r.T |
113 | 159 |
114 val meta = | 160 val meta : meta (global, M.t, input) = |
115 {Initialize = getChoices, | 161 {Initialize = getChoices, |
116 Handlers = fn choices => | 162 Handlers = fn choices => |
117 {Display = fn (_, k, r) => <xml>{[render ({nm = k} ++ r)]}</xml>, | 163 NonNull ( |
118 Edit = fn (s, k, _) => | 164 {Display = fn (_, kr) => case kr of |
165 None => error <xml>Unexpected Foreign null</xml> | |
166 | Some (k, r) => <xml>{[render ({nm = k} ++ r)]}</xml>, | |
167 Edit = fn (s, kr) => | |
119 <xml><cselect source={s}> | 168 <xml><cselect source={s}> |
120 {List.mapX (fn (k', rend) => | 169 {List.mapX (fn (k', rend) => |
121 <xml><coption value={show k'} selected={k' = k}>{[rend]}</coption> | 170 <xml><coption value={show k'} selected={case kr of |
171 None => False | |
172 | Some (k, _) => | |
173 k' = k}>{[rend]}</coption> | |
122 </xml>) | 174 </xml>) |
123 choices} | 175 choices} |
124 </cselect></xml>, | 176 </cselect></xml>, |
125 Initialize = fn k => s <- source (show k); | 177 Initialize = fn k => s <- source (show k); |
126 r <- rpc (getChoice k); | 178 r <- rpc (getChoice k); |
127 return (s, k, r), | 179 return (s, Some (k, r)), |
128 Parse = fn (s, _, _) => k <- signal s; return (read k)}} | 180 Parse = fn (s, _) => k <- signal s; return (read k : option t)}, |
181 {Display = fn (_, kr) => case kr of | |
182 None => <xml>NULL</xml> | |
183 | Some (k, r) => <xml>{[render ({nm = k} ++ r)]}</xml>, | |
184 Edit = fn (s, kr) => | |
185 <xml><cselect source={s}> | |
186 <coption value="" selected={case kr of | |
187 None => True | |
188 | _ => False}>NULL</coption> | |
189 {List.mapX (fn (k', rend) => | |
190 <xml><coption value={show k'} selected={case kr of | |
191 None => False | |
192 | Some (k, _) => | |
193 k' = k}>{[rend]}</coption> | |
194 </xml>) | |
195 choices} | |
196 </cselect></xml>, | |
197 Initialize = fn k => case k of | |
198 None => | |
199 s <- source ""; | |
200 return (s, None) | |
201 | Some k => | |
202 s <- source (show k); | |
203 r <- rpc (getChoice k); | |
204 return (s, Some (k, r)), | |
205 Parse = fn (s, _) => ks <- signal s; | |
206 return (case ks of | |
207 "" => Some None | |
208 | _ => case read ks : option t of | |
209 None => None | |
210 | Some k => Some (Some k))})} | |
129 end | 211 end |
130 end | 212 end |
131 | 213 |
132 con computedState = (unit, xbody) | 214 con computedState = (unit, xbody) |
133 fun computed [row] [t] (_ : show t) name (f : $row -> t) : colMeta row computedState = | 215 fun computed [row] [t] (_ : show t) name (f : $row -> t) : colMeta row computedState = |