Skip to content

Commit

Permalink
Improved event handling in GUI.
Browse files Browse the repository at this point in the history
  • Loading branch information
nmihajlovski committed Sep 26, 2015
1 parent 0964f45 commit 3d40200
Show file tree
Hide file tree
Showing 17 changed files with 220 additions and 143 deletions.
39 changes: 0 additions & 39 deletions rapidoid-annotations/src/main/java/org/rapidoid/annotation/On.java

This file was deleted.

Expand Up @@ -36,7 +36,7 @@

boolean raw() default false;

boolean navbar() default true;
boolean navbar() default false;

boolean search() default false;

Expand Down
100 changes: 50 additions & 50 deletions rapidoid-app/src/main/java/org/rapidoid/app/AppHandler.java
Expand Up @@ -27,6 +27,7 @@

import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;
import org.rapidoid.cls.Cls;
import org.rapidoid.config.Conf;
import org.rapidoid.dispatch.DispatchResult;
import org.rapidoid.dispatch.PojoDispatchException;
Expand All @@ -42,9 +43,7 @@
import org.rapidoid.io.CustomizableClassLoader;
import org.rapidoid.io.Res;
import org.rapidoid.jackson.JSON;
import org.rapidoid.log.Log;
import org.rapidoid.plugins.templates.Templates;
import org.rapidoid.util.Constants;
import org.rapidoid.util.U;
import org.rapidoid.util.UTILS;
import org.rapidoid.webapp.AppCtx;
Expand Down Expand Up @@ -102,7 +101,6 @@ public Object processReq(HttpExchange x) {
}
}

@SuppressWarnings("unchecked")
public Object dispatch(HttpExchangeImpl x) {

// static files
Expand All @@ -114,67 +112,47 @@ public Object dispatch(HttpExchangeImpl x) {
WebApp app = AppCtx.app();
PojoDispatcher dispatcher = app.getDispatcher();

boolean hasEvent = false;

// Prepare GUI state

x.loadState();

// if an event was emitted, process it

if (x.isPostReq()) {
String event = x.posted("_event", null);
if (!U.isEmpty(event)) {
hasEvent = true;

String evArgs = x.posted("_args", null);
Object[] args = evArgs != null ? JSON.jacksonParse(evArgs, Object[].class) : Constants.EMPTY_ARRAY;

String inputstr = x.posted("_inputs");
U.notNull(inputstr, "inputs");
Map<String, Object> inputs = JSON.parse(inputstr, Map.class);

// bind inputs
for (Entry<String, Object> e : inputs.entrySet()) {
String inputId = e.getKey();
Object value = e.getValue();
boolean hasEvent = x.isPostReq() && !U.isEmpty(x.data("_event", null));

x.locals().put(inputId, UTILS.serializable(value));
}

DispatchResult dispatchResult = doDispatch(dispatcher, new WebReq(x));
Object result = null;

if (dispatchResult != null) {
U.must(dispatchResult.getKind() == DispatchReqKind.PAGE);
}
if (hasEvent) {
bindInputs(x);

// in case of binding or validation errors
if (x.hasErrors()) {
x.json();
return U.map("!errors", x.errors());
}
DispatchResult dispatchResult = doDispatch(dispatcher, new WebReq(x));
if (dispatchResult != null) {
U.must(dispatchResult.getKind() == DispatchReqKind.PAGE);
result = dispatchResult.getResult();
}

// call the command handler
DispatchResult dr = on(x, dispatcher, event, args);
if (dr == null) {
x.json();
Log.warn("No event handler was found!", "event", event, "page", x.path());
return U.map();
}
// in case of binding or validation errors
if (x.hasErrors()) {
x.json();
return U.map("!errors", x.errors());
}
}

Map<String, Object> config = null;

// dispatch REST services or views (as POJO methods)

DispatchResult dres = doDispatch(dispatcher, new WebReq(x));
Map<String, Object> config = dres != null ? dres.getConfig() : null;
if (result == null) {
DispatchResult dres = doDispatch(dispatcher, new WebReq(x));

Object result = null;
if (dres != null) {
result = dres.getResult();
if (dres != null) {
result = dres.getResult();
config = dres.getConfig();

if (dres.getKind() == DispatchReqKind.SERVICE) {
return result;
if (dres.getKind() == DispatchReqKind.SERVICE) {
x.json();
return result;
}
}
}

Expand All @@ -194,6 +172,20 @@ public Object dispatch(HttpExchangeImpl x) {
return view(x, result, hasEvent, config);
}

private void bindInputs(HttpExchangeImpl x) {
Map<String, Object> inputs = x.data("_inputs", null);

if (inputs != null) {
// bind inputs
for (Entry<String, Object> e : inputs.entrySet()) {
String inputId = e.getKey();
Object value = e.getValue();

x.locals().put(inputId, UTILS.serializable(value));
}
}
}

public static Object view(HttpExchange x, Object result, boolean hasEvent, Map<String, Object> config) {
// serve dynamic pages from file templates

Expand Down Expand Up @@ -226,7 +218,7 @@ public static boolean serveDynamicPage(HttpExchange x, Object result, boolean ha
String defaultFile = Conf.templatesPathDefault() + "/" + filename;
Res res = Res.from(filename, true, firstFile, defaultFile);

Map<String, Object> model = U.cast(U.map("navbar", true, "login", true, "profile", true));
Map<String, Object> model = U.cast(U.map("login", true, "profile", true));

if (res.exists()) {
model.putAll(pageModel(result, res));
Expand All @@ -238,15 +230,23 @@ public static boolean serveDynamicPage(HttpExchange x, Object result, boolean ha
}

WebApp app = AppCtx.app();
model.put("title", app.getTitle());

String title = app.getTitle();
model.put("title", title);
model.put("embedded", hasEvent || x.param("_embedded", null) != null);

// the @Page configuration overrides the previous
if (config != null) {
model.putAll(config);
}

if (hasEvent) {
if (!Cls.bool(model.get("navbar"))) {
model.put("navbar", U.isEmpty(title));
}

model.put("navbar", U.isEmpty(title));

if (hasEvent && x.param("_embedded", null) == null) {
serveEventResponse((HttpExchangeImpl) x, x.renderPageToHTML(model));
} else {
x.renderPage(model);
Expand Down
2 changes: 1 addition & 1 deletion rapidoid-app/src/main/java/org/rapidoid/app/Scripting.java
Expand Up @@ -95,7 +95,7 @@ protected static void runScript(HttpExchangeImpl x, CompiledScript script, boole
Map<String, Object> bindings = U.map();
Dollar dollar = new Dollar(x, bindings);

for (Entry<String, String> e : x.data().entrySet()) {
for (Entry<String, Object> e : x.data().entrySet()) {
bindings.put("$" + e.getKey(), e.getValue());
}

Expand Down
4 changes: 4 additions & 0 deletions rapidoid-cls/src/main/java/org/rapidoid/cls/Cls.java
Expand Up @@ -726,6 +726,10 @@ public static String str(Object value) {
return convert(value, String.class);
}

public static boolean bool(Object value) {
return U.or(convert(value, Boolean.class), false);
}

public static ParameterizedType generic(Type type) {
return (type instanceof ParameterizedType) ? ((ParameterizedType) type) : null;
}
Expand Down
@@ -1 +1,2 @@
<!--state::(~{req.renderState}~)-->
(~^error~)(~>page-navbar~)(~{content}~)(~/error~)(~#error~)(~>page-error~)(~/error~)
Expand Up @@ -88,17 +88,17 @@ public interface HttpExchange {
/**
* Data includes params + posted.
*/
Map<String, String> data();
Map<String, Object> data();

/**
* Data includes params + posted.
*/
String data(@P("name") String name);
<T> T data(@P("name") String name);

/**
* Data includes params + posted.
*/
String data(@P("name") String name, @P("defaultValue") String defaultValue);
<T> T data(@P("name") String name, @P("defaultValue") T defaultValue);

String home();

Expand Down
24 changes: 13 additions & 11 deletions rapidoid-http/src/main/java/org/rapidoid/http/HttpExchangeImpl.java
Expand Up @@ -110,7 +110,7 @@ public class HttpExchangeImpl extends DefaultExchange<HttpExchangeImpl> implemen

private HttpResponses responses;

private Map<String, String> data;
private Map<String, Object> data;
private Map<String, String> errors;

private Map<String, Object> model;
Expand Down Expand Up @@ -150,9 +150,9 @@ public class HttpExchangeImpl extends DefaultExchange<HttpExchangeImpl> implemen
private ClassLoader classLoader;
private SessionStore sessionStore;

private final Callable<Map<String, String>> lazyData = new Callable<Map<String, String>>() {
private final Callable<Map<String, Object>> lazyData = new Callable<Map<String, Object>>() {
@Override
public Map<String, String> call() throws Exception {
public Map<String, Object> call() throws Exception {
return data();
}
};
Expand Down Expand Up @@ -515,7 +515,7 @@ public synchronized byte[] file(String name, byte[] defaultValue) {
}

@Override
public synchronized Map<String, String> data() {
public synchronized Map<String, Object> data() {
if (data == null) {
data = U.synchronizedMap();
data.putAll(params());
Expand All @@ -525,14 +525,16 @@ public synchronized Map<String, String> data() {
return data;
}

@SuppressWarnings("unchecked")
@Override
public synchronized String data(String name) {
return U.notNull(data().get(name), "DATA[%s]", name);
public synchronized <T> T data(String name) {
return (T) U.notNull(data().get(name), "DATA[%s]", name);
}

@SuppressWarnings("unchecked")
@Override
public synchronized String data(String name, String defaultValue) {
return U.or(data().get(name), defaultValue);
public synchronized <T> T data(String name, T defaultValue) {
return (T) U.or(data().get(name), defaultValue);
}

@Override
Expand Down Expand Up @@ -811,8 +813,8 @@ public synchronized HttpExchange response(int httpResponseCode, String response,

if (err != null) {
String details = Conf.dev() ? HTMLHelpers.stackTrace(title, err) : "";
renderPage(U.map("title", title, "error", true, "code", httpResponseCode, "navbar", true, "content",
details));
renderPage(U.map("title", title, "error", true, "code", httpResponseCode, "navbar", !U.isEmpty(title),
"content", details));
} else {
renderPage(U.map("title", title, "code", httpResponseCode, "error", httpResponseCode >= 400));
}
Expand Down Expand Up @@ -1255,7 +1257,7 @@ public HttpExchange result(Object res) {
File file = (File) res;
sendFile(file);

} else if (res.getClass().getSimpleName().endsWith("Page")) {
} else if (UTILS.isRapidoidType(res.getClass())) {
html().write(res.toString());

} else {
Expand Down
Expand Up @@ -85,7 +85,7 @@ public String getId() {
}

public String getTitle() {
return config.option("title", "Untitled");
return config.option("title", null);
}

public void setTitle(String title) {
Expand Down
Expand Up @@ -30,7 +30,6 @@
import org.rapidoid.annotation.DELETE;
import org.rapidoid.annotation.GET;
import org.rapidoid.annotation.Header;
import org.rapidoid.annotation.On;
import org.rapidoid.annotation.POST;
import org.rapidoid.annotation.PUT;
import org.rapidoid.annotation.Page;
Expand Down Expand Up @@ -157,7 +156,6 @@ protected List<DispatchReq> getMethodActions(String componentPath, Method method

private List<DispatchReq> req(String componentPath, Annotation ann, Method method) {
String url;
String event = null;
Map<String, Object> config = U.synchronizedMap();

if (ann instanceof GET) {
Expand Down Expand Up @@ -186,11 +184,6 @@ private List<DispatchReq> req(String componentPath, Annotation ann, Method metho
config.put("title", page.title());
}

} else if (ann instanceof On) {
On on = (On) ann;
url = on.page();
event = on.event();

} else {
return null;
}
Expand All @@ -201,8 +194,6 @@ private List<DispatchReq> req(String componentPath, Annotation ann, Method metho
if (ann instanceof Page) {
return U.list(new DispatchReq("GET", path, DispatchReqKind.PAGE, config), new DispatchReq("POST", path,
DispatchReqKind.PAGE, config));
} else if (ann instanceof On) {
return U.list(new DispatchReq(event.toUpperCase(), path, DispatchReqKind.EVENT, config));
} else {
String verb = ann.annotationType().getSimpleName().toUpperCase();
return U.list(new DispatchReq(verb, path, DispatchReqKind.SERVICE, config));
Expand Down

0 comments on commit 3d40200

Please sign in to comment.