diff --git a/src/main/java/me/mrletsplay/nojs/NoJS.java b/src/main/java/me/mrletsplay/nojs/NoJS.java index 9aab75c..870839d 100644 --- a/src/main/java/me/mrletsplay/nojs/NoJS.java +++ b/src/main/java/me/mrletsplay/nojs/NoJS.java @@ -1,12 +1,17 @@ package me.mrletsplay.nojs; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import javax.imageio.ImageIO; + import org.slf4j.helpers.NOPLogger; import me.mrletsplay.nojs._test.DynPage; import me.mrletsplay.nojs._test.LinksPage; +import me.mrletsplay.nojs.page.Page; import me.mrletsplay.simplehttpserver.dom.html.HtmlDocument; import me.mrletsplay.simplehttpserver.dom.html.HtmlElement; import me.mrletsplay.simplehttpserver.dom.html.element.HtmlButton; @@ -58,8 +63,25 @@ public class NoJS { // new TestEndpoint().register(httpServer.getDocumentProvider()); - new DynPage().register(httpServer.getDocumentProvider(), "/dyn"); - new LinksPage().register(httpServer.getDocumentProvider(), "/links"); + BufferedImage img = new BufferedImage(64, 64, BufferedImage.TYPE_3BYTE_BGR); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + try { + ImageIO.write(img, "PNG", bOut); + } catch (IOException e) { + e.printStackTrace(); + } + byte[] bytes = bOut.toByteArray(); + + httpServer.getDocumentProvider().register(HttpRequestMethod.GET, "/favicon.ico", () -> { + HttpRequestContext ctx = HttpRequestContext.getCurrentContext(); + ctx.getServerHeader().setContent(MimeType.PNG, bytes); + }); + + Page.register( + httpServer.getDocumentProvider(), + new DynPage(), + new LinksPage() + ); httpServer.getDocumentProvider().register(HttpRequestMethod.POST, "/", () -> { HttpRequestContext ctx = HttpRequestContext.getCurrentContext(); diff --git a/src/main/java/me/mrletsplay/nojs/_test/DynPage.java b/src/main/java/me/mrletsplay/nojs/_test/DynPage.java index 8b8e934..61ce9cc 100644 --- a/src/main/java/me/mrletsplay/nojs/_test/DynPage.java +++ b/src/main/java/me/mrletsplay/nojs/_test/DynPage.java @@ -11,6 +11,7 @@ import me.mrletsplay.nojs.component.impl.Text; import me.mrletsplay.nojs.page.Page; import me.mrletsplay.nojs.page.layout.GridLayout; import me.mrletsplay.nojs.page.layout.InsetLayout; +import me.mrletsplay.simplehttpserver.http.request.HttpRequestContext; public class DynPage implements Page { @@ -27,4 +28,15 @@ public class DynPage implements Page { .vAlignment(GridLayout.VAlignment.CENTER)); } + @Override + public String getPath() { + return "/dyn"; + } + + @Override + public void createContent() { + HttpRequestContext.getCurrentContext().getServerHeader().getFields().add("Refresh", "10"); + Page.super.createContent(); + } + } diff --git a/src/main/java/me/mrletsplay/nojs/_test/LinksPage.java b/src/main/java/me/mrletsplay/nojs/_test/LinksPage.java index f97b416..11d3b06 100644 --- a/src/main/java/me/mrletsplay/nojs/_test/LinksPage.java +++ b/src/main/java/me/mrletsplay/nojs/_test/LinksPage.java @@ -1,16 +1,19 @@ package me.mrletsplay.nojs._test; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import me.mrletsplay.nojs.action.Action; import me.mrletsplay.nojs.action.ActionData; import me.mrletsplay.nojs.action.ActionEvent; import me.mrletsplay.nojs.action.ActionHandler; +import me.mrletsplay.nojs.action.ActionResult; import me.mrletsplay.nojs.component.Component; import me.mrletsplay.nojs.component.impl.Button; import me.mrletsplay.nojs.component.impl.Form; import me.mrletsplay.nojs.component.impl.Group; +import me.mrletsplay.nojs.component.impl.IFrame; import me.mrletsplay.nojs.component.impl.Link; import me.mrletsplay.nojs.component.impl.Message; import me.mrletsplay.nojs.component.impl.Select; @@ -19,11 +22,12 @@ import me.mrletsplay.nojs.component.impl.TextInput; import me.mrletsplay.nojs.page.Page; import me.mrletsplay.nojs.page.layout.GridLayout; import me.mrletsplay.nojs.page.layout.HClampLayout; +import me.mrletsplay.simplehttpserver.http.request.HttpRequestContext; +import me.mrletsplay.simplehttpserver.http.request.urlencoded.UrlEncoded; public class LinksPage implements Page { private Map links = new LinkedHashMap<>(); - private String error; @Override public Component getContent() { @@ -54,11 +58,11 @@ public class LinksPage implements Page { linksGroup.add(new Text().text("No links added yet")); } - if(error != null) { + UrlEncoded query = HttpRequestContext.getCurrentContext().getRequestedPath().getQuery(); + if(query.has("error")) { linksGroup.add(new Message() - .text(error) + .text((String) query.getFirst("error")) .type(Message.Type.ERROR)); - error = null; } return new Group() @@ -79,19 +83,27 @@ public class LinksPage implements Page { .layout(GridLayout.ofColumns(1).gap("4px")) .action(new Action("addLink")) ) + .add(new IFrame(new DynPage()).data(new UrlEncoded(Map.of("error", List.of("Sussy baka iframe"))))) .layout(GridLayout.ofColumns(1).gap("10px")) ) .layout(new HClampLayout("200px", "100%", "800px") .hAlignment(HClampLayout.HAlignment.CENTER)); } + @Override + public String getPath() { + return "/links"; + } + @ActionHandler("addLink") public void addLink(ActionEvent event) { String linkName = event.getData("linkName"); String link = event.getData("link"); if(link == null || link.isBlank() || (!link.startsWith("http://") && !link.startsWith("https://")) || linkName == null || linkName.isBlank()) { - error = "Invalid link"; + UrlEncoded data = new UrlEncoded(); + data.set("error", "Invalid link"); + event.setResult(ActionResult.refresh(data)); return; } diff --git a/src/main/java/me/mrletsplay/nojs/action/ActionEvent.java b/src/main/java/me/mrletsplay/nojs/action/ActionEvent.java index eb985f0..dcfa963 100644 --- a/src/main/java/me/mrletsplay/nojs/action/ActionEvent.java +++ b/src/main/java/me/mrletsplay/nojs/action/ActionEvent.java @@ -5,9 +5,11 @@ import me.mrletsplay.simplehttpserver.http.request.urlencoded.UrlEncoded; public class ActionEvent { private UrlEncoded data; + private ActionResult result; public ActionEvent(UrlEncoded data) { this.data = data; + this.result = ActionResult.refresh(); } public String getAction() { @@ -18,4 +20,12 @@ public class ActionEvent { return data.getFirst(name); } + public void setResult(ActionResult result) { + this.result = result != null ? result : ActionResult.refresh(); + } + + public ActionResult getResult() { + return result; + } + } diff --git a/src/main/java/me/mrletsplay/nojs/action/ActionResult.java b/src/main/java/me/mrletsplay/nojs/action/ActionResult.java new file mode 100644 index 0000000..55e950a --- /dev/null +++ b/src/main/java/me/mrletsplay/nojs/action/ActionResult.java @@ -0,0 +1,63 @@ +package me.mrletsplay.nojs.action; + +import me.mrletsplay.nojs.page.Page; +import me.mrletsplay.simplehttpserver.http.request.urlencoded.UrlEncoded; + +public class ActionResult { + + private static final ActionResult REFRESH = new ActionResult(Type.REFRESH, null, null); + + private Type type; + private String url; + private UrlEncoded data; + + private ActionResult(Type type, String url, UrlEncoded data) { + this.type = type; + this.url = url; + this.data = data; + } + + public Type getType() { + return type; + } + + public String getUrl() { + return url; + } + + public UrlEncoded getData() { + return data; + } + + public static ActionResult refresh(UrlEncoded data) { + return new ActionResult(Type.REFRESH, null, data); + } + + public static ActionResult refresh() { + return REFRESH; + } + + public static ActionResult redirectTo(String url, UrlEncoded data) { + return new ActionResult(Type.REDIRECT, url, data); + } + + public static ActionResult redirectTo(String url) { + return redirectTo(url, null); + } + + public static ActionResult redirectTo(Page page, UrlEncoded data) { + return redirectTo(page.getPath(), data); + } + + public static ActionResult redirectTo(Page page) { + return redirectTo(page, null); + } + + public static enum Type { + + REFRESH, + REDIRECT, + + } + +} diff --git a/src/main/java/me/mrletsplay/nojs/component/impl/IFrame.java b/src/main/java/me/mrletsplay/nojs/component/impl/IFrame.java new file mode 100644 index 0000000..3bbe94c --- /dev/null +++ b/src/main/java/me/mrletsplay/nojs/component/impl/IFrame.java @@ -0,0 +1,41 @@ +package me.mrletsplay.nojs.component.impl; + +import java.util.Objects; + +import me.mrletsplay.nojs.component.Component; +import me.mrletsplay.nojs.page.Page; +import me.mrletsplay.simplehttpserver.dom.html.HtmlElement; +import me.mrletsplay.simplehttpserver.http.request.urlencoded.UrlEncoded; + +public class IFrame implements Component { + + private Page page; + private UrlEncoded data; +// private Duration autoRefresh; TODO: auto refresh + + public IFrame(Page page) { + Objects.requireNonNull(page, "page"); + + this.page = page; + } + + public IFrame data(UrlEncoded data) { + this.data = data; + return this; + } + + @Override + public HtmlElement toHtml() { + HtmlElement iframe = HtmlElement.of("iframe"); + iframe.addClass("iframe"); + + String path = page.getPath(); + if(data != null) { + path += "?" + data.toString(); + } + + iframe.setAttribute("src", path); + return iframe; + } + +} diff --git a/src/main/java/me/mrletsplay/nojs/component/impl/Link.java b/src/main/java/me/mrletsplay/nojs/component/impl/Link.java index 63b321c..d15777c 100644 --- a/src/main/java/me/mrletsplay/nojs/component/impl/Link.java +++ b/src/main/java/me/mrletsplay/nojs/component/impl/Link.java @@ -11,7 +11,7 @@ public class Link implements Component { public Link() { this.text = "Link"; - this.href = "#"; + this.href = ""; this.target = Target.SELF; } @@ -21,7 +21,7 @@ public class Link implements Component { } public Link href(String href) { - this.href = href != null ? href : "#"; + this.href = href != null ? href : ""; return this; } diff --git a/src/main/java/me/mrletsplay/nojs/page/Page.java b/src/main/java/me/mrletsplay/nojs/page/Page.java index bb32c10..938c988 100644 --- a/src/main/java/me/mrletsplay/nojs/page/Page.java +++ b/src/main/java/me/mrletsplay/nojs/page/Page.java @@ -21,6 +21,8 @@ public interface Page extends HttpDocument, ActionHandlers { public Component getContent(); + public String getPath(); + public default HtmlDocument toHtml() { HtmlDocument doc = new HtmlDocument(); doc.addStyleSheet("/base.css"); @@ -49,16 +51,32 @@ public interface Page extends HttpDocument, ActionHandlers { ActionEvent e = new ActionEvent(data); onAction(e); - ctx.redirect(HttpStatusCodes.SEE_OTHER_303, ctx.getClientHeader().getPath().toString()); + String path = ctx.getClientHeader().getPath().getDocumentPath(); + if(e.getResult().getUrl() != null) { + path = e.getResult().getUrl(); + } + + if(e.getResult().getData() != null) { + path += "?" + e.getResult().getData().toString(); + } + + ctx.redirect(HttpStatusCodes.SEE_OTHER_303, path); return; } ctx.respond(HttpStatusCodes.OK_200, new HtmlResponse(toHtml())); } - public default void register(DocumentProvider provider, String path) { + public default void register(DocumentProvider provider) { + String path = getPath(); provider.register(HttpRequestMethod.GET, path, this); provider.register(HttpRequestMethod.POST, path, this); } + public static void register(DocumentProvider provider, Page... pages) { + for(Page page : pages) { + page.register(provider); + } + } + } diff --git a/src/main/java/me/mrletsplay/nojs/page/layout/GridLayout.java b/src/main/java/me/mrletsplay/nojs/page/layout/GridLayout.java index f39eb5f..1a6bd09 100644 --- a/src/main/java/me/mrletsplay/nojs/page/layout/GridLayout.java +++ b/src/main/java/me/mrletsplay/nojs/page/layout/GridLayout.java @@ -26,21 +26,21 @@ public class GridLayout implements Layout { } public GridLayout columns(Collection columns) { - this.columns = new ArrayList<>(columns == null ? Collections.emptyList() : columns); + this.columns = new ArrayList<>(columns != null ? columns : Collections.emptyList()); return this; } public GridLayout rows(Collection rows) { - this.rows = new ArrayList<>(rows == null ? Collections.emptyList() : rows); + this.rows = new ArrayList<>(rows != null ? rows : Collections.emptyList()); return this; } public GridLayout columns(String... columns) { - return columns(columns == null ? null : Arrays.asList(columns)); + return columns(columns != null ? Arrays.asList(columns) : null); } public GridLayout rows(String... rows) { - return rows(rows == null ? null : Arrays.asList(rows)); + return rows(rows != null ? Arrays.asList(rows) : null); } public GridLayout gap(String gap) { @@ -49,7 +49,7 @@ public class GridLayout implements Layout { } public GridLayout flow(Flow flow) { - this.flow = flow; + this.flow = flow != null ? flow : Flow.ROW; return this; } diff --git a/src/main/resources/style/base.css b/src/main/resources/style/base.css index 911755a..5fde0e0 100644 --- a/src/main/resources/style/base.css +++ b/src/main/resources/style/base.css @@ -131,3 +131,7 @@ body { .message:has(:checked) { display: none; } + +.iframe { + border: none; +}