Mercurial > urweb
comparison demo/more/grid.ur @ 915:5e8b6fa5b48f
Start 'more' demo with dbgrid
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 08 Sep 2009 07:48:57 -0400 |
parents | |
children | 2422360c78a3 |
comparison
equal
deleted
inserted
replaced
914:782f0b4eea67 | 915:5e8b6fa5b48f |
---|---|
1 con colMeta' = fn (row :: Type) (t :: Type) => | |
2 {Header : string, | |
3 Project : row -> transaction t, | |
4 Update : row -> t -> transaction row, | |
5 Display : t -> xbody, | |
6 Edit : t -> xbody, | |
7 Validate : t -> signal bool} | |
8 | |
9 con colMeta = fn (row :: Type) (global_t :: (Type * Type)) => | |
10 {Initialize : transaction global_t.1, | |
11 Handlers : global_t.1 -> colMeta' row global_t.2} | |
12 | |
13 functor Make(M : sig | |
14 type row | |
15 val list : transaction (list row) | |
16 val new : transaction row | |
17 val save : {Old : row, New : row} -> transaction unit | |
18 val delete : row -> transaction unit | |
19 | |
20 con cols :: {(Type * Type)} | |
21 val cols : $(map (colMeta row) cols) | |
22 | |
23 val folder : folder cols | |
24 end) = struct | |
25 style tabl | |
26 style tr | |
27 style th | |
28 style td | |
29 | |
30 fun make (row : M.row) [t] (m : colMeta' M.row t) : transaction t = m.Project row | |
31 | |
32 fun makeAll cols row = @@Monad.exec [transaction] _ [map snd M.cols] | |
33 (map2 [fst] [colMeta M.row] [fn p :: (Type * Type) => transaction p.2] | |
34 (fn [p] data meta => make row [_] (meta.Handlers data)) | |
35 [_] M.folder cols M.cols) | |
36 (@@Folder.mp [_] [_] M.folder) | |
37 | |
38 fun addRow cols rows row = | |
39 rowS <- source row; | |
40 cols <- makeAll cols row; | |
41 colsS <- source cols; | |
42 ud <- source False; | |
43 Monad.ignore (Dlist.append rows {Row = rowS, | |
44 Cols = colsS, | |
45 Updating = ud}) | |
46 | |
47 type grid = {Cols : $(map fst M.cols), | |
48 Rows : Dlist.dlist {Row : source M.row, Cols : source ($(map snd M.cols)), Updating : source bool}} | |
49 | |
50 val createMetas = Monad.mapR [colMeta M.row] [fst] | |
51 (fn [nm :: Name] [p :: (Type * Type)] meta => meta.Initialize) | |
52 [_] M.folder M.cols | |
53 | |
54 val grid = | |
55 cols <- createMetas; | |
56 rows <- Dlist.create; | |
57 return {Cols = cols, Rows = rows} | |
58 | |
59 fun sync {Cols = cols, Rows = rows} = | |
60 Dlist.clear rows; | |
61 init <- rpc M.list; | |
62 List.app (addRow cols rows) init | |
63 | |
64 fun render grid = <xml> | |
65 <table class={tabl}> | |
66 <tr class={tr}> | |
67 <th/> <th/> | |
68 {foldRX2 [fst] [colMeta M.row] [_] | |
69 (fn [nm :: Name] [p :: (Type * Type)] [rest :: {(Type * Type)}] [[nm] ~ rest] | |
70 data (meta : colMeta M.row p) => | |
71 <xml><th class={th}>{[(meta.Handlers data).Header]}</th></xml>) | |
72 [_] M.folder grid.Cols M.cols} | |
73 </tr> | |
74 | |
75 {Dlist.render (fn {Row = rowS, Cols = colsS, Updating = ud} pos => | |
76 let | |
77 val delete = | |
78 Dlist.delete pos; | |
79 row <- get rowS; | |
80 rpc (M.delete row) | |
81 | |
82 val update = set ud True | |
83 | |
84 val cancel = | |
85 set ud False; | |
86 row <- get rowS; | |
87 cols <- makeAll grid.Cols row; | |
88 set colsS cols | |
89 | |
90 val save = | |
91 cols <- get colsS; | |
92 errors <- Monad.foldR3 [fst] [colMeta M.row] [snd] [fn _ => option string] | |
93 (fn [nm :: Name] [p :: (Type * Type)] [rest :: {(Type * Type)}] | |
94 [[nm] ~ rest] data meta v errors => | |
95 b <- current ((meta.Handlers data).Validate v); | |
96 return (if b then | |
97 errors | |
98 else | |
99 case errors of | |
100 None => Some ((meta.Handlers data).Header) | |
101 | Some s => Some ((meta.Handlers data).Header | |
102 ^ ", " ^ s))) | |
103 None [_] M.folder grid.Cols M.cols cols; | |
104 | |
105 case errors of | |
106 Some s => alert ("Can't save because the following columns have invalid values:\n" | |
107 ^ s) | |
108 | None => | |
109 set ud False; | |
110 row <- get rowS; | |
111 row' <- Monad.foldR3 [fst] [colMeta M.row] [snd] [fn _ => M.row] | |
112 (fn [nm :: Name] [t :: (Type * Type)] | |
113 [rest :: {(Type * Type)}] | |
114 [[nm] ~ rest] data meta v row' => | |
115 (meta.Handlers data).Update row' v) | |
116 row [_] M.folder grid.Cols M.cols cols; | |
117 rpc (M.save {Old = row, New = row'}); | |
118 set rowS row'; | |
119 | |
120 cols <- makeAll grid.Cols row'; | |
121 set colsS cols | |
122 in | |
123 <xml><tr class={tr}> | |
124 <td> | |
125 <dyn signal={b <- signal ud; | |
126 return (if b then | |
127 <xml><button value="Save" onclick={save}/></xml> | |
128 else | |
129 <xml><button value="Update" onclick={update}/></xml>)}/> | |
130 </td> | |
131 <td><dyn signal={b <- signal ud; | |
132 return (if b then | |
133 <xml><button value="Cancel" onclick={cancel}/></xml> | |
134 else | |
135 <xml><button value="Delete" onclick={delete}/></xml>)}/> | |
136 </td> | |
137 | |
138 <dyn signal={cols <- signal colsS; | |
139 return (foldRX3 [fst] [colMeta M.row] [snd] [_] | |
140 (fn [nm :: Name] [t :: (Type * Type)] | |
141 [rest :: {(Type * Type)}] | |
142 [[nm] ~ rest] data meta v => | |
143 <xml><td class={td}> | |
144 <dyn signal={b <- signal ud; | |
145 return (if b then | |
146 (meta.Handlers data).Edit v | |
147 else | |
148 (meta.Handlers data).Display | |
149 v)}/> | |
150 <dyn signal={b <- signal ud; | |
151 if b then | |
152 valid <- | |
153 (meta.Handlers data).Validate v; | |
154 return (if valid then | |
155 <xml/> | |
156 else | |
157 <xml>!</xml>) | |
158 else | |
159 return <xml/>}/> | |
160 </td></xml>) | |
161 [_] M.folder grid.Cols M.cols cols)}/> | |
162 </tr></xml> | |
163 end) grid.Rows} | |
164 </table> | |
165 | |
166 <button value="New row" onclick={row <- rpc M.new; | |
167 addRow grid.Cols grid.Rows row}/> | |
168 <button value="Refresh" onclick={sync grid}/> | |
169 </xml> | |
170 end |