n2o_nitrogen.erl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. -module(n2o_nitrogen).
  2. -author('Maxim Sokhatsky').
  3. -include_lib("n2o/include/wf.hrl").
  4. -compile([export_all, nowarn_export_all]).
  5. % Nitrogen pickle handler
  6. info({init,Rest},Req,State) ->
  7. Module = State#cx.module,
  8. InitActionsReply = case Rest of
  9. <<>> -> try Elements = Module:main(),
  10. wf_render:render(Elements),
  11. {ok,[]}
  12. catch X:Y -> Stack = wf:stack(X,Y),
  13. wf:error(?MODULE,"Event Main: ~p:~p~n~p", Stack),
  14. {error,Stack} end;
  15. Binary -> Pid = wf:depickle(Binary),
  16. Pid ! {'N2O',self()},
  17. {ok,receive_actions(Req)} end,
  18. case InitActionsReply of
  19. {ok,InitActions} -> UserCx = try Module:event(init),
  20. case wf:config(n2o,auto_session) of
  21. disabled -> skip;
  22. _ -> n2o_session:ensure_sid([],?CTX,[]) end
  23. catch C:E -> Error = wf:stack(C,E),
  24. wf:error(?MODULE,"Event Init: ~p:~p~n~p",Error),
  25. {stack,Error} end,
  26. Actions = render_actions(wf:actions()),
  27. {reply,wf:format({io,iolist_to_binary([InitActions,Actions]),<<>>}),
  28. Req,wf:context(State,?MODULE,{init,UserCx})};
  29. {error,E} -> {reply,wf:format({io,<<>>,E}), Req, wf:context(State,?MODULE,{error,E})} end;
  30. info({pickle,_,_,_}=Event, Req, State) ->
  31. wf:actions([]),
  32. Result = try html_events(Event,State)
  33. catch E:R -> Stack = wf:stack(E,R),
  34. wf:error(?MODULE,"Catch: ~p:~p~n~p", Stack),
  35. {io,render_actions(wf:actions()),Stack} end,
  36. {reply,wf:format(Result),Req,wf:context(State,?MODULE,{pickle,Result})};
  37. info({flush,Actions}, Req, State) ->
  38. wf:actions([]),
  39. Render = iolist_to_binary(render_actions(Actions)),
  40. wf:info(?MODULE,"Flush Message: ~tp",[Render]),
  41. {reply,wf:format({io,Render,<<>>}),Req, State};
  42. info({direct,Message}, Req, State) ->
  43. wf:actions([]),
  44. Module = State#cx.module,
  45. Result = try Res = Module:event(Message), {direct,Res}
  46. catch E:R -> Stack = wf:stack(E, R),
  47. wf:error(?MODULE,"Catch: ~p:~p~n~p", Stack),
  48. {stack,Stack} end,
  49. {reply,wf:format({io,render_actions(wf:actions()),<<>>}),Req, wf:context(State,?MODULE,Result)};
  50. info(Message,Req,State) -> {unknown,Message,Req,State}.
  51. % double render: actions could generate actions
  52. render_actions(Actions) ->
  53. wf:actions([]),
  54. First = wf:render(Actions),
  55. Second = wf:render(wf:actions()),
  56. wf:actions([]),
  57. [First,Second].
  58. % N2O events
  59. html_events({pickle,Source,Pickled,Linked}=Pickle, State) ->
  60. wf:info(?MODULE,"Pickle: ~tp",[Pickle]),
  61. Ev = wf:depickle(Pickled),
  62. _Result = case Ev of
  63. #ev{} -> render_ev(Ev,Source,Linked,State);
  64. CustomEnvelop -> wf:error("Only #ev{} events for now: ~p",[CustomEnvelop]) end,
  65. {io,render_actions(wf:actions()),<<>>}.
  66. render_ev(#ev{module=M,name=F,msg=P,trigger=T},_Source,Linked,State) ->
  67. case F of
  68. api_event -> M:F(P,Linked,State);
  69. event -> lists:map(fun({K,V})-> put(K,wf:to_binary(V)) end,Linked), M:F(P);
  70. _UserCustomEvent -> M:F(P,T,State) end.
  71. receive_actions(Req) ->
  72. receive
  73. {actions,A} -> n2o_nitrogen:render_actions(A);
  74. _ -> receive_actions(Req)
  75. after 200 ->
  76. QS = element(14, Req),
  77. wf:redirect(case QS of <<>> -> ""; _ -> "?" ++ wf:to_list(QS) end),
  78. [] end.