Skip to content

Commit

Permalink
second commit
Browse files Browse the repository at this point in the history
  • Loading branch information
trecouvr committed Jul 22, 2011
1 parent b467e47 commit 630e3db
Show file tree
Hide file tree
Showing 13 changed files with 390 additions and 0 deletions.
29 changes: 29 additions & 0 deletions Makefile
@@ -0,0 +1,29 @@


OPA=opa
FILES=$(shell find src -name '*.opa')
EXE=main.exe

all: $(FILES)
$(OPA) $^ -o main.exe

run:
./$(EXE) --db-local db/db

new-db:
./$(EXE) --db-local db/db --db-force-upgrade

clean-db:
rm -rf db/*

clean:
rm -rf *.opx *.opx.broken
rm -f *.exe
rm -rf doc
rm -rf _build _tracks
rm -f *.log
rm -f *.apix
rm -f src/*.api
rm -rf *.opp
rm -f src/*.api-txt

Binary file added db/db_config
Binary file not shown.
Binary file added db/db_db_state
Binary file not shown.
Binary file added db/db_flags_file
Binary file not shown.
Empty file added db/db_lock
Empty file.
Binary file added db/db_node_file
Binary file not shown.
Binary file added db/db_timestamps_file
Binary file not shown.
Empty file added db/db_trans_file
Empty file.
Binary file added db/db_uid_file
Binary file not shown.
Binary file added db/db_uid_rev_file
Binary file not shown.
129 changes: 129 additions & 0 deletions src/example.opa
@@ -0,0 +1,129 @@


import bddc.tablebuilder

/**
*
*
* DATAS
*
*
*
*/

type vtest = {str : string i : int}
type vtest_k = {k : int v : vtest}
db /test : intmap(vtest)

init() =
if not(Db.exists(@/test[0])) then
do /test[0] <- {str="coucou" i=10}
do /test[1] <- {str="salut" i=1}
void
do init()
get_values() : list(vtest_k) =
Db.intmap_fold_range(
@/test,
(acc,k -> List.add({~k v=/test[k]},acc)),
[],0,none,(_->true)
)
add(new_v : vtest) : int =
key = Db.fresh_key(@/test)
do save(key, new_v)
key
save(key : int, new_v : vtest) =
/test[key] <- new_v
rm(key : int) =
Db.remove(@/test[key])
/**
*
*
* TABLE
*
*
*
*/
@client
mk_columns() = [
TableBuilder.mk_column(
<>String</>,
(r,_chan -> <>{r.v.str}</>),
some(r1, r2 -> String.ordering(r1.v.str, r2.v.str)),
none
),
TableBuilder.mk_column(
<>Int</>,
(r,_chan -> <>{r.v.i}</>),
some(r1, r2 -> Int.ordering(r1.v.i, r2.v.i)),
none
),
TableBuilder.mk_column(
<>Tool</>,
(r,chan ->
<button onclick={_-> do Session.send(chan, {del_filter=(v->v.k == r.k)}) rm(r.k)}>Del filter</button>
),
none,
none
)
]
onready() =
values = get_values()
spec = TableBuilder.mk_spec(
mk_columns(),
values
)
table = TableBuilder.make(spec)
key() = String.to_int(Dom.get_value(#key))
str() = Dom.get_value(#str)
i() = String.to_int(Dom.get_value(#int))
row_k() = {k=key() v={str=str() i=i()}}
row() = {str=str() i=i()}
// add
onadd(_) =
k=add(row())
row_k={~k v=row()}
Session.send(table.channel, {add=row_k})
// delete by key
ondelkey(_) =
do rm(key())
Session.send(table.channel, {del_key=key()})
// edit by key
oneditkey(_) =
do save(key(), row())
Session.send(table.channel, {edit_key={key=key() row=row_k()}})
xhtml =
<>
str : <input id=#str/>
int : <input id=#int />
key : <input id=#key/>
<button onclick={onadd}>Ajouter</button>
<button onclick={ondelkey}>Del key</button>
<button onclick={oneditkey}>Editer key</button>
{table.xhtml}
</>
Dom.transform([#onready <- xhtml])
/**
*
*
* SERVER
*
*
*
*/
main() =
<div id=#onready onready={_->onready()}></div>
server = Server.one_page_server("Test", main)
206 changes: 206 additions & 0 deletions src/tablebuilder.opa
@@ -0,0 +1,206 @@
/*
*
* @author Thomas Recouvreux
*
*/

package bddc.tablebuilder
import stdlib.core.rpc.core
import bddc.tools



type TableBuilder.message('row) =
{show} /
{sort : int} /
{del_key : int} /
{del_filter : ('row->bool)} /
{edit_key : {key:int row:'row}} /
{edit_filter : ('row->'row)} /
{add : 'row}
type TableBuilder.row_order('row) = ('row,'row -> Order.ordering)
type TableBuilder.row_filter('row) = ('row -> bool)
@abstract type TableBuilder.column('row) = {
label : xhtml
cell_maker : ('row,channel(TableBuilder.message('row)) -> xhtml)
order : option(TableBuilder.row_order('row))
sort_reverse : bool
filter : option(TableBuilder.row_filter('row))
filter_on : bool
}
@abstract type TableBuilder.spec('row) = {
id : string
columns : list(TableBuilder.column('row))
content : list('row)
sort_active : int
}
type TableBuilder.t('row) = {
xhtml : xhtml
channel : channel(TableBuilder.message('row))
}





TableBuilder = {{
mk_spec( columns : list(TableBuilder.column),
content : list('row)
) : TableBuilder.spec('row) =
{
id = Dom.fresh_id()
~columns
~content
sort_active=0
}
mk_column( label : xhtml,
cell_maker : ('row,channel(TableBuilder.message('row)) -> xhtml),
order : option(TableBuilder.row_order('row)),
filter : option(TableBuilder.row_filter('row))
) : TableBuilder.column =
{
~label
~cell_maker
~order
~filter
sort_reverse=true
filter_on=false
}

/**
Cré une session qui va contenir la spec du tableau, renvoi un record contenant
le channel pour communiquer et agir sur le tableau et le code xhtml necessaire
à l'affichage du tableau
@param spec
@return (TableBuilder.t)
*/
@client
make(spec : TableBuilder.spec('row)) : TableBuilder.t =
rec val channel = Session.make(spec, callback)
and callback(spec,message) =
do jlog("{message}")
new_spec = match message with
| {show} -> spec
| {~sort} -> onclick_sort(sort, spec)
| {~del_key} -> {spec with content=List.remove_at(del_key,spec.content)}
| {~del_filter} -> {spec with content=List.filter(v->not(del_filter(v)),spec.content)}
| {~edit_key} -> {spec with content=Tools.list.replace(edit_key.key, edit_key.row, spec.content)}
| {~edit_filter} -> {spec with content=List.map(edit_filter, spec.content)}
| {~add} -> {spec with content=List.add(add,spec.content)}
end
new_spec = sort(new_spec)
do Dom.transform([#{spec.id} <- xhtml_table(new_spec, channel)])
{set=new_spec}
{~channel xhtml=xhtml(spec,channel)}


set_sort(i_col : int, spec : TableBuilder.spec('row)) : TableBuilder.spec('row) =
{spec with sort_active=i_col}

set_reverse(i_col : int, value : bool, spec : TableBuilder.spec('row)) : TableBuilder.spec('row) =
col = List.get(i_col,spec.columns)
if Option.is_some(col) then
col = Option.get(col)
col = {col with sort_reverse=value}
{spec with columns = Tools.list.replace(i_col, col, spec.columns)}
else spec

/**
Fonction appellée quand on clique pour trier le tableau,
elle va modifier la spec pour préciser la colonne de trie choisie
et inverser l'ordre de tri de cette colonne
@param i_col la colonne à utiliser pour le tri
@param spec
@return spec
*/
@client
@private
onclick_sort(i_col : int, spec : TableBuilder.spec('row)) : TableBuilder.spec('row) =
Tools.option.perform_default(
(col -> set_sort(i_col, set_reverse(i_col, not(col.sort_reverse), spec))),
spec,
List.get(i_col,spec.columns)
)

/**
Trier la spec, la colonne à utiliséer pour le tri est précisée
dans la spec
@param spec
@return spec
*/
@client
@private
sort(spec : TableBuilder.spec('row)) : TableBuilder.spec('row) =
Tools.option.perform_default(
(col -> Tools.option.perform_default(
(ord ->
if col.sort_reverse then
{spec with content = List.rev(List.sort_with(ord,spec.content))}
else
{spec with content = List.sort_with(ord,spec.content)}
),
spec,
col.order
)),
spec,
List.get(spec.sort_active,spec.columns)
)

/**
Cré le tableau (seulement les balises exterieures)
@param spec
@param channel
@return (xhtml)
*/
@client
@private
xhtml(spec : TableBuilder.spec('row), channel : channel(TableBuilder.message('row))) : xhtml =
<table border=1 id=#{spec.id} onready={_->Session.send(channel,{show})}>
</table>

/**
Cré la contenu du tableau
@param spec
@param channel
@return (xhtml)
*/
@client
@private
xhtml_table(spec : TableBuilder.spec('row), channel : channel(TableBuilder.message('row))) : xhtml =
xhtml_header(s : TableBuilder.spec('row)) : xhtml =
List.foldi( (i,col,acc ->
<>{acc}<th>{col.label}<>{
if Option.is_some(col.order) then
<button onclick={_-> Session.send(channel,{sort=i})}>⇅</button>
else
<></>
}</></th></>
),
spec.columns,
<></>)
xhtml_body(s : TableBuilder.spec('row)) : xhtml =
List.fold( (row,acc ->
<>{acc}
<tr>
{List.fold( (col,acc ->
<>{acc}
<td>{col.cell_maker(row, channel)}</td>
</>
),
s.columns,
<></>
)}
</tr>
</>
),
spec.content,
<></>)
<thead>
{xhtml_header(spec)}
</thead>
<tbody>
{xhtml_body(spec)}
</tbody>

}}

26 changes: 26 additions & 0 deletions src/tools.opa
@@ -0,0 +1,26 @@
/*
* (c) Valdabondance.com - 2011
* @author Matthieu Guffroy - Thomas Recouvreux
*
*/

package bddc.tools

Tools = {{

list = {{
replace(key : int, new_v : 'new_v, l : list('a)) : list('a) =
List.mapi((i,v -> if i==key then new_v else v), l)
}}


option = {{
perform_default(f : ('o -> 'r), default : 'r, o : option('o)) : 'r =
if Option.is_some(o) then
f(Option.get(o))
else
default
}}


}}

0 comments on commit 630e3db

Please sign in to comment.