fix
[libxsql.git] / www / xsql.erl
blob08f2db3d303469d99cb6a13db691ec25fc3e94e8
1 -module(xsql).
2 -export([parse_json/1, parse/1, to_html/1, test/0, mkid/2, ls/1]).
4 -record(content, {
5 status=fail,
6 data
7 }).
9 -record(dir, {
10 name,
11 content
12 }).
13 -record(file, {
14 name,
15 params=[],
16 path
17 }).
18 -record(param, {
19 label,
20 type
21 }).
23 parse(Data) ->
24 {Content} = Data,
25 parse(Content, #content{}).
27 parse_json(Json) ->
28 parse(jiffy:decode(Json)).
31 parse([{<<"status">>,0}|T], R) ->
32 parse(T, R#content{status=ok});
33 parse([{<<"data">>,Data}|T], R) ->
34 parse(T, R#content{data=Data});
35 parse([_H|T], R) ->
36 parse(T, R);
37 parse([], R) ->
38 parse_content(R#content.data, []).
40 parse_content([{Item}|T], R) ->
41 case lists:keyfind(<<"is_dir">>, 1, Item) of
42 {_, true} -> parse_content(T, [parse_dir(Item, #dir{})|R]);
43 {_, false} -> parse_content(T, [parse_file(Item, #file{})|R]);
44 _ -> parse_content(T, R)
45 end;
46 parse_content([_H|T], D) -> parse_content(T, D);
47 parse_content([], R) -> lists:sort(R).
49 parse_dir([{<<"name">>,Name}|T], #dir{}=R) ->
50 parse_dir(T, R#dir{name=binary_to_list(Name)});
51 parse_dir([{<<"content">>,Content}|T], #dir{}=R) ->
52 parse_dir(T, R#dir{content=parse_content(Content, [])});
53 parse_dir([_|T], R) -> parse_dir(T, R);
54 parse_dir([], R) -> R.
56 parse_file([{<<"name">>,Name}|T], #file{}=R) ->
57 parse_file(T, R#file{name=binary_to_list(Name)});
58 parse_file([{<<"path">>,Path}|T], #file{}=R) ->
59 parse_file(T, R#file{path=binary_to_list(Path)});
60 parse_file([{<<"params">>,Params}|T], #file{}=R) ->
61 parse_file(T, R#file{params=parse_params(Params, [])});
62 parse_file([_|T], R) -> parse_file(T, R);
63 parse_file([], R) -> R.
65 parse_params([{Param}|T], R) ->
66 parse_params(T, [parse_any_param(Param, #param{})|R]);
67 parse_params([], R) -> lists:reverse(R).
69 parse_any_param([{<<"label">>,Label}|T], #param{}=R) ->
70 parse_any_param(T, R#param{label=binary_to_list(Label)});
71 parse_any_param([{<<"type">>,Type}|T], #param{}=R) ->
72 parse_any_param(T, R#param{type=binary_to_list(Type)});
73 parse_any_param([_|T], R) ->parse_any_param(T, R);
74 parse_any_param([], R) -> R.
76 test() -> ls("/").
78 err(Status) ->
79 [{status, Status}, {header, {connection, "close"}}].
81 mkurl(Host, Port, Url) ->
82 lists:concat([Host, ":", Port, Url]).
84 ls(Url) ->
85 case get("config") of
86 undefined ->
87 Conf = xsqlconf:load("xsql.rc"),
88 put("config", Conf),
89 inets:start(),
90 ls(Url, Conf);
91 Conf ->
92 ls(Url, Conf)
93 end.
94 ls(Url, Conf) ->
95 Port = dict:find("port", Conf),
96 Host = dict:find("host", Conf),
97 case (Port /= error) and (Host /= error) of
98 true -> ls(Url, Conf, Host, Port);
99 false -> err(502)
100 end.
101 ls(Url, _Conf, {ok,Host}, {ok,Port}) ->
102 RequestUrl = mkurl(Host, Port, Url),
103 case httpc:request(RequestUrl) of
104 {ok, {{_Ver, 200, _Phrase}, _Hdrs, Body}} ->
105 to_html(Body);
106 {error,Reason} ->
107 err(502)
108 end.
110 merge([H|T], R) -> merge(T, [H|R]);
111 merge([], R) -> R.
113 mrg(N, R) -> mrg(merge(integer_to_list(N), R)).
114 mrg(R) -> [$-|R].
116 mkid(N, I) -> mkid(N, I, []).
117 mkid(_N, 0, R) -> "item" ++ R;
118 mkid(N, I, R) -> mkid(N, I-1, mrg(N, R)).
120 to_html(Content) ->
121 case parse_json(Content) of
122 {fail, _} -> {ehtml, "error"};
123 Data -> {ehtml, [{'div', [{class,"css-treeview"}], [to_html(Data, [], 0, 1)]}]}
124 end.
125 to_html([#file{}=X|T], R, N, I) ->
126 to_html(T, [{li, [], {a, [{href, X#file.path}], X#file.name}}|R], N+1, I+1);
127 to_html([#dir{}=X|T], R, N, I) ->
128 Id = mkid(N, I),
129 to_html(T, [{ul, [], {li, [], [{input, [{type,"checkbox"},{id,Id}]}, {label, [{for,Id}], X#dir.name}, {ul, [], to_html(X#dir.content, [], N, I+1)}]}}|R], N+1, I);
130 to_html([], R, _N, _I) -> lists:reverse(R).