adamc@944: con colMeta' = fn (row :: Type) (input :: Type) (filter :: Type) => adamc@915: {Header : string, adamc@944: Project : row -> transaction input, adamc@944: Update : row -> input -> transaction row, adamc@944: Display : input -> xbody, adamc@944: Edit : input -> xbody, adamc@944: Validate : input -> signal bool, adamc@944: CreateFilter : transaction filter, adamc@944: DisplayFilter : filter -> xbody, adamc@961: Filter : filter -> row -> signal bool, adamc@961: Sort : option (row -> row -> bool)} adamc@915: adamc@1002: con colMeta = fn (row :: Type) (global :: Type, input :: Type, filter :: Type) => adamc@1002: {Initialize : transaction global, adamc@1002: Handlers : global -> colMeta' row input filter} adamc@915: adamc@935: con aggregateMeta = fn (row :: Type) (acc :: Type) => adamc@935: {Initial : acc, adamc@935: Step : row -> acc -> acc, adamc@935: Display : acc -> xbody} adamc@935: adamc@915: functor Make(M : sig adamc@915: type row adamc@936: type key adamc@936: val keyOf : row -> key adamc@936: adamc@915: val list : transaction (list row) adamc@915: val new : transaction row adamc@936: val save : key -> row -> transaction unit adamc@936: val delete : key -> transaction unit adamc@915: adamc@944: con cols :: {(Type * Type * Type)} adamc@915: val cols : $(map (colMeta row) cols) adamc@915: adamc@915: val folder : folder cols adamc@935: adamc@935: con aggregates :: {Type} adamc@935: val aggregates : $(map (aggregateMeta row) aggregates) adamc@937: val aggFolder : folder aggregates adamc@964: adamc@964: val pageLength : option int adamc@915: end) : sig adamc@915: type grid adamc@915: adamc@915: val grid : transaction grid adamc@915: val sync : grid -> transaction unit adamc@915: val render : grid -> xbody adamc@940: adamc@940: val showSelection : grid -> source bool adamc@940: val selection : grid -> signal (list M.row) adamc@940: adam@1833: style tab adam@1833: style row adam@1833: style header adam@1833: style data adamc@943: style agg adamc@915: end