Update actions, Add IFrame

This commit is contained in:
MrLetsplay 2025-02-03 22:37:25 +01:00
parent be55b1db77
commit 96c1c3b01b
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
10 changed files with 198 additions and 16 deletions

View File

@ -1,12 +1,17 @@
package me.mrletsplay.nojs; package me.mrletsplay.nojs;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import javax.imageio.ImageIO;
import org.slf4j.helpers.NOPLogger; import org.slf4j.helpers.NOPLogger;
import me.mrletsplay.nojs._test.DynPage; import me.mrletsplay.nojs._test.DynPage;
import me.mrletsplay.nojs._test.LinksPage; 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.HtmlDocument;
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement; import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
import me.mrletsplay.simplehttpserver.dom.html.element.HtmlButton; import me.mrletsplay.simplehttpserver.dom.html.element.HtmlButton;
@ -58,8 +63,25 @@ public class NoJS {
// new TestEndpoint().register(httpServer.getDocumentProvider()); // new TestEndpoint().register(httpServer.getDocumentProvider());
new DynPage().register(httpServer.getDocumentProvider(), "/dyn"); BufferedImage img = new BufferedImage(64, 64, BufferedImage.TYPE_3BYTE_BGR);
new LinksPage().register(httpServer.getDocumentProvider(), "/links"); 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, "/", () -> { httpServer.getDocumentProvider().register(HttpRequestMethod.POST, "/", () -> {
HttpRequestContext ctx = HttpRequestContext.getCurrentContext(); HttpRequestContext ctx = HttpRequestContext.getCurrentContext();

View File

@ -11,6 +11,7 @@ import me.mrletsplay.nojs.component.impl.Text;
import me.mrletsplay.nojs.page.Page; import me.mrletsplay.nojs.page.Page;
import me.mrletsplay.nojs.page.layout.GridLayout; import me.mrletsplay.nojs.page.layout.GridLayout;
import me.mrletsplay.nojs.page.layout.InsetLayout; import me.mrletsplay.nojs.page.layout.InsetLayout;
import me.mrletsplay.simplehttpserver.http.request.HttpRequestContext;
public class DynPage implements Page { public class DynPage implements Page {
@ -27,4 +28,15 @@ public class DynPage implements Page {
.vAlignment(GridLayout.VAlignment.CENTER)); .vAlignment(GridLayout.VAlignment.CENTER));
} }
@Override
public String getPath() {
return "/dyn";
}
@Override
public void createContent() {
HttpRequestContext.getCurrentContext().getServerHeader().getFields().add("Refresh", "10");
Page.super.createContent();
}
} }

View File

@ -1,16 +1,19 @@
package me.mrletsplay.nojs._test; package me.mrletsplay.nojs._test;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import me.mrletsplay.nojs.action.Action; import me.mrletsplay.nojs.action.Action;
import me.mrletsplay.nojs.action.ActionData; import me.mrletsplay.nojs.action.ActionData;
import me.mrletsplay.nojs.action.ActionEvent; import me.mrletsplay.nojs.action.ActionEvent;
import me.mrletsplay.nojs.action.ActionHandler; import me.mrletsplay.nojs.action.ActionHandler;
import me.mrletsplay.nojs.action.ActionResult;
import me.mrletsplay.nojs.component.Component; import me.mrletsplay.nojs.component.Component;
import me.mrletsplay.nojs.component.impl.Button; import me.mrletsplay.nojs.component.impl.Button;
import me.mrletsplay.nojs.component.impl.Form; import me.mrletsplay.nojs.component.impl.Form;
import me.mrletsplay.nojs.component.impl.Group; 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.Link;
import me.mrletsplay.nojs.component.impl.Message; import me.mrletsplay.nojs.component.impl.Message;
import me.mrletsplay.nojs.component.impl.Select; 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.Page;
import me.mrletsplay.nojs.page.layout.GridLayout; import me.mrletsplay.nojs.page.layout.GridLayout;
import me.mrletsplay.nojs.page.layout.HClampLayout; 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 { public class LinksPage implements Page {
private Map<String, String> links = new LinkedHashMap<>(); private Map<String, String> links = new LinkedHashMap<>();
private String error;
@Override @Override
public Component getContent() { public Component getContent() {
@ -54,11 +58,11 @@ public class LinksPage implements Page {
linksGroup.add(new Text().text("No links added yet")); 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() linksGroup.add(new Message()
.text(error) .text((String) query.getFirst("error"))
.type(Message.Type.ERROR)); .type(Message.Type.ERROR));
error = null;
} }
return new Group() return new Group()
@ -79,19 +83,27 @@ public class LinksPage implements Page {
.layout(GridLayout.ofColumns(1).gap("4px")) .layout(GridLayout.ofColumns(1).gap("4px"))
.action(new Action("addLink")) .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(GridLayout.ofColumns(1).gap("10px"))
) )
.layout(new HClampLayout("200px", "100%", "800px") .layout(new HClampLayout("200px", "100%", "800px")
.hAlignment(HClampLayout.HAlignment.CENTER)); .hAlignment(HClampLayout.HAlignment.CENTER));
} }
@Override
public String getPath() {
return "/links";
}
@ActionHandler("addLink") @ActionHandler("addLink")
public void addLink(ActionEvent event) { public void addLink(ActionEvent event) {
String linkName = event.getData("linkName"); String linkName = event.getData("linkName");
String link = event.getData("link"); String link = event.getData("link");
if(link == null || link.isBlank() || (!link.startsWith("http://") && !link.startsWith("https://")) if(link == null || link.isBlank() || (!link.startsWith("http://") && !link.startsWith("https://"))
|| linkName == null || linkName.isBlank()) { || linkName == null || linkName.isBlank()) {
error = "Invalid link"; UrlEncoded data = new UrlEncoded();
data.set("error", "Invalid link");
event.setResult(ActionResult.refresh(data));
return; return;
} }

View File

@ -5,9 +5,11 @@ import me.mrletsplay.simplehttpserver.http.request.urlencoded.UrlEncoded;
public class ActionEvent { public class ActionEvent {
private UrlEncoded data; private UrlEncoded data;
private ActionResult result;
public ActionEvent(UrlEncoded data) { public ActionEvent(UrlEncoded data) {
this.data = data; this.data = data;
this.result = ActionResult.refresh();
} }
public String getAction() { public String getAction() {
@ -18,4 +20,12 @@ public class ActionEvent {
return data.getFirst(name); return data.getFirst(name);
} }
public void setResult(ActionResult result) {
this.result = result != null ? result : ActionResult.refresh();
}
public ActionResult getResult() {
return result;
}
} }

View File

@ -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,
}
}

View File

@ -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;
}
}

View File

@ -11,7 +11,7 @@ public class Link implements Component {
public Link() { public Link() {
this.text = "Link"; this.text = "Link";
this.href = "#"; this.href = "";
this.target = Target.SELF; this.target = Target.SELF;
} }
@ -21,7 +21,7 @@ public class Link implements Component {
} }
public Link href(String href) { public Link href(String href) {
this.href = href != null ? href : "#"; this.href = href != null ? href : "";
return this; return this;
} }

View File

@ -21,6 +21,8 @@ public interface Page extends HttpDocument, ActionHandlers {
public Component getContent(); public Component getContent();
public String getPath();
public default HtmlDocument toHtml() { public default HtmlDocument toHtml() {
HtmlDocument doc = new HtmlDocument(); HtmlDocument doc = new HtmlDocument();
doc.addStyleSheet("/base.css"); doc.addStyleSheet("/base.css");
@ -49,16 +51,32 @@ public interface Page extends HttpDocument, ActionHandlers {
ActionEvent e = new ActionEvent(data); ActionEvent e = new ActionEvent(data);
onAction(e); 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; return;
} }
ctx.respond(HttpStatusCodes.OK_200, new HtmlResponse(toHtml())); 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.GET, path, this);
provider.register(HttpRequestMethod.POST, path, this); provider.register(HttpRequestMethod.POST, path, this);
} }
public static void register(DocumentProvider provider, Page... pages) {
for(Page page : pages) {
page.register(provider);
}
}
} }

View File

@ -26,21 +26,21 @@ public class GridLayout implements Layout {
} }
public GridLayout columns(Collection<String> columns) { public GridLayout columns(Collection<String> columns) {
this.columns = new ArrayList<>(columns == null ? Collections.emptyList() : columns); this.columns = new ArrayList<>(columns != null ? columns : Collections.emptyList());
return this; return this;
} }
public GridLayout rows(Collection<String> rows) { public GridLayout rows(Collection<String> rows) {
this.rows = new ArrayList<>(rows == null ? Collections.emptyList() : rows); this.rows = new ArrayList<>(rows != null ? rows : Collections.emptyList());
return this; return this;
} }
public GridLayout columns(String... columns) { 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) { 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) { public GridLayout gap(String gap) {
@ -49,7 +49,7 @@ public class GridLayout implements Layout {
} }
public GridLayout flow(Flow flow) { public GridLayout flow(Flow flow) {
this.flow = flow; this.flow = flow != null ? flow : Flow.ROW;
return this; return this;
} }

View File

@ -131,3 +131,7 @@ body {
.message:has(:checked) { .message:has(:checked) {
display: none; display: none;
} }
.iframe {
border: none;
}