123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- -module(n4u_nitrogen).
- -include_lib("n4u/include/n4u.hrl").
- -export([info/3]).
- -export([render_actions/1, html_events/2, render_ev/4, receive_actions/1]).
- % todo compare here and in nitro - render_actions, html_events, render_ev, receive_actions
- % nitrogen pickle handler
- info({init, Rest}, Req, State) ->
- Module = State#cx.module,
- InitActionsReply = case Rest of
- <<>> ->
- try Elements = Module:main(),
- nitro:render(Elements),
- {ok, []}
- catch E1:R1:Stk1 ->
- wf:error(?MODULE, "main: E:R:Stk: ~p ~p~n ~p~n", [E1, R1, Stk1]),
- {error, [E1, R1, Stk1]}
- end;
-
- Binary ->
- Pid = wf:depickle(Binary),
- Pid ! {'N4U', erlang:self()},
- {ok, receive_actions(Req)}
- end,
-
- case InitActionsReply of
- {ok, InitActions} ->
- UserCx = try Module:event(init),
- case application:get_env(n4u, auto_session, "") of
- disabled -> skip;
- _ -> n4u_session:ensure_sid([], ?CTX, [])
- end
- catch E2:R2:Stk2 ->
- wf:error(?MODULE, "init: E:R:Stk: ~p ~p~n ~p~n", [E2, R2, Stk2]),
- {stack, [E2, R2, Stk2]}
- end,
- Actions = render_actions(erlang:get(actions)),
- {reply, wf:format({io, erlang:iolist_to_binary([InitActions, Actions]), <<>>}),
- Req, n4u_cx:context(State, ?MODULE, {init, UserCx})};
-
- {error, E} ->
- {reply, wf:format({io, <<>>, E}), Req,
- n4u_cx:context(State, ?MODULE, {error, E})}
- end;
- info({pickle, _, _, _} = Event, Req, State) ->
- erlang:put(actions, []),
- Result = try html_events(Event, State)
- catch E:R:Stk ->
- wf:error(?MODULE, "info pickle E:R:Stk: ~p ~p~n ~p~n", [E, R, Stk]),
- {io, render_actions(erlang:get(actions)), [E, R, Stk]}
- end,
- {reply, wf:format(Result), Req,
- n4u_cx:context(State, ?MODULE, {pickle, Result})};
- info({flush, Actions}, Req, State) ->
- erlang:put(actions, []),
- Render = erlang:iolist_to_binary(render_actions(Actions)),
- wf:info(?MODULE, "Flush Message: ~tp~n", [Render]),
- {reply, wf:format({io, Render, <<>>}), Req, State};
- info({direct, Message}, Req, State) ->
- erlang:put(actions, []),
- Module = State#cx.module,
- Result = try Res = Module:event(Message),
- {direct, Res}
- catch E:R:Stk ->
- wf:error(?MODULE, "info direct E:R:Stk: ~p ~p~n ~p~n", [E, R, Stk]),
- {stack, [E, R, Stk]}
- end,
- {reply, wf:format({io, render_actions(erlang:get(actions)), <<>>}),
- Req, n4u_cx:context(State, ?MODULE, Result)};
- info(Message, Req, State) -> {unknown, Message, Req, State}.
- % double render: actions could generate actions
- render_actions(Actions) ->
- erlang:put(actions, []),
- First = nitro:render(Actions),
- Second = nitro:render(erlang:get(actions)),
- erlang:put(actions, []),
- [First, Second].
- % N4U events
- html_events({pickle, Source, Pickled, Linked} = Pickle, State) ->
- wf:info(?MODULE, "Pickle: ~tp~n", [Pickle]),
- Ev = wf:depickle(Pickled),
- _Result = case Ev of
- #ev{} ->
- render_ev(Ev, Source, Linked, State);
- Custom_Envelop ->
- wf:error("Only #ev{} events for now: ~p~n", [Custom_Envelop])
- end,
- {io, render_actions(erlang:get(actions)), <<>>}.
- render_ev(#ev{module = M, name = F, msg = P, trigger = T}, _Source, Linked, State) ->
- case F of
- api_event ->
- M:F(P, Linked, State);
-
- event ->
- lists:map(fun({K, V}) ->
- erlang:put(K, nitro:to_binary(V))
- end, Linked),
- M:F(P);
-
- _UserCustomEvent ->
- M:F(P, T, State)
- end.
- receive_actions(Req) ->
- receive
- {actions, A} ->
- n4u_nitrogen:render_actions(A);
- _ ->
- receive_actions(Req)
- after 200 ->
- #{qs := QS} = Req,
- R = case QS of
- <<"">> -> "";
- _ -> "?" ++ nitro:to_list(QS)
- end,
- wf:redirect(R),
- []
- end.
|