initial commit
This commit is contained in:
commit
c6eec9364f
40
.classpath
Normal file
40
.classpath
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target/
|
23
.project
Normal file
23
.project
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>NoJS</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
3
.settings/org.eclipse.core.resources.prefs
Normal file
3
.settings/org.eclipse.core.resources.prefs
Normal file
@ -0,0 +1,3 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/test/java=UTF-8
|
8
.settings/org.eclipse.jdt.core.prefs
Normal file
8
.settings/org.eclipse.jdt.core.prefs
Normal file
@ -0,0 +1,8 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
|
||||
org.eclipse.jdt.core.compiler.compliance=11
|
||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
||||
org.eclipse.jdt.core.compiler.release=enabled
|
||||
org.eclipse.jdt.core.compiler.source=11
|
4
.settings/org.eclipse.m2e.core.prefs
Normal file
4
.settings/org.eclipse.m2e.core.prefs
Normal file
@ -0,0 +1,4 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
67
pom.xml
Normal file
67
pom.xml
Normal file
@ -0,0 +1,67 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>me.mrletsplay</groupId>
|
||||
<artifactId>NoJS</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<build>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<configuration>
|
||||
<release>11</release>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<configuration>
|
||||
<source>11</source>
|
||||
<encoding>UTF-8</encoding>
|
||||
<sourcepath>src/main/java</sourcepath>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>Graphite-Official</id>
|
||||
<url>https://maven.graphite-official.com/releases</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.mrletsplay</groupId>
|
||||
<artifactId>SimpleHTTPServer</artifactId>
|
||||
<version>2.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
109
src/main/java/me/mrletsplay/nojs/NoJS.java
Normal file
109
src/main/java/me/mrletsplay/nojs/NoJS.java
Normal file
@ -0,0 +1,109 @@
|
||||
package me.mrletsplay.nojs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.slf4j.helpers.NOPLogger;
|
||||
|
||||
import me.mrletsplay.nojs._test.DynPage;
|
||||
import me.mrletsplay.nojs._test.LinksPage;
|
||||
import me.mrletsplay.nojs._test.TestPage;
|
||||
import me.mrletsplay.nojs.action.Action;
|
||||
import me.mrletsplay.nojs.action.ActionData;
|
||||
import me.mrletsplay.nojs.component.impl.Button;
|
||||
import me.mrletsplay.nojs.component.impl.Button.Style;
|
||||
import me.mrletsplay.nojs.component.impl.Form;
|
||||
import me.mrletsplay.nojs.component.impl.Link;
|
||||
import me.mrletsplay.nojs.component.impl.TextInput;
|
||||
import me.mrletsplay.nojs.page.StaticPage;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlDocument;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.element.HtmlButton;
|
||||
import me.mrletsplay.simplehttpserver.http.HttpRequestMethod;
|
||||
import me.mrletsplay.simplehttpserver.http.HttpStatusCodes;
|
||||
import me.mrletsplay.simplehttpserver.http.header.DefaultClientContentTypes;
|
||||
import me.mrletsplay.simplehttpserver.http.request.HttpRequestContext;
|
||||
import me.mrletsplay.simplehttpserver.http.request.urlencoded.UrlEncoded;
|
||||
import me.mrletsplay.simplehttpserver.http.response.HtmlResponse;
|
||||
import me.mrletsplay.simplehttpserver.http.response.TextResponse;
|
||||
import me.mrletsplay.simplehttpserver.http.server.HttpServer;
|
||||
import me.mrletsplay.simplehttpserver.http.util.MimeType;
|
||||
|
||||
public class NoJS {
|
||||
|
||||
public static void main(String[] args) {
|
||||
HttpServer httpServer = new HttpServer(HttpServer.newConfigurationBuilder()
|
||||
.hostBindAll()
|
||||
.port(6969)
|
||||
.poolSize(10)
|
||||
.ioWorkers(2)
|
||||
.debugMode(true)
|
||||
.logger(NOPLogger.NOP_LOGGER)
|
||||
.create());
|
||||
|
||||
httpServer.getDocumentProvider().register(HttpRequestMethod.GET, "/", () -> {
|
||||
HttpRequestContext ctx = HttpRequestContext.getCurrentContext();
|
||||
HtmlDocument doc = new HtmlDocument();
|
||||
|
||||
doc.setTitle("Test");
|
||||
doc.setIcon("/amogus.png");
|
||||
doc.setDescription("Just testing");
|
||||
|
||||
HtmlElement form = HtmlElement.of("form");
|
||||
form.setAttribute("method", "post");
|
||||
|
||||
HtmlElement input = HtmlElement.of("input");
|
||||
input.setAttribute("name", "texttest");
|
||||
form.appendChild(input);
|
||||
|
||||
HtmlButton button = HtmlElement.button();
|
||||
button.setText("Click me!");
|
||||
form.appendChild(button);
|
||||
|
||||
doc.getBodyNode().appendChild(form);
|
||||
|
||||
ctx.respond(HttpStatusCodes.OK_200, new HtmlResponse(doc));
|
||||
});
|
||||
|
||||
// new TestEndpoint().register(httpServer.getDocumentProvider());
|
||||
|
||||
StaticPage test = new StaticPage()
|
||||
.add(new Button().text("Click me!").action(new Action("poopy").extraData(new ActionData().put("test", "abc"))).style(Style.LINK))
|
||||
.add(new Link().text("Click me!").href("#"))
|
||||
.add(new Form()
|
||||
.add(new TextInput("username").placeholder("Username"))
|
||||
.add(new TextInput("password").placeholder("Password"))
|
||||
.add(new Button().text("Login"))
|
||||
.add(new Button().text("Can't click here").enabled(false))
|
||||
.action(new Action("beans"))
|
||||
);
|
||||
test.register(httpServer.getDocumentProvider(), "/test");
|
||||
|
||||
new TestPage().register(httpServer.getDocumentProvider(), "/test2");
|
||||
new DynPage().register(httpServer.getDocumentProvider(), "/dyn");
|
||||
new LinksPage().register(httpServer.getDocumentProvider(), "/links");
|
||||
|
||||
httpServer.getDocumentProvider().register(HttpRequestMethod.POST, "/", () -> {
|
||||
HttpRequestContext ctx = HttpRequestContext.getCurrentContext();
|
||||
UrlEncoded data = ctx.getClientHeader().getPostData().getParsedAs(DefaultClientContentTypes.URLENCODED);
|
||||
ctx.respond(HttpStatusCodes.OK_200, new TextResponse(data.toString()));
|
||||
});
|
||||
|
||||
httpServer.getDocumentProvider().register(HttpRequestMethod.GET, "/base.css", () -> {
|
||||
try(InputStream in = NoJS.class.getResourceAsStream("/style/base.css")) {
|
||||
HttpRequestContext ctx = HttpRequestContext.getCurrentContext();
|
||||
ctx.getServerHeader().setContent(MimeType.CSS, in.readAllBytes());
|
||||
} catch(IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
// httpServer.getDocumentProvider().registerPattern(HttpRequestMethod.GET, "/{path...?}", () -> {
|
||||
// HttpRequestContext ctx = HttpRequestContext.getCurrentContext();
|
||||
// ctx.respond(HttpStatusCodes.OK_200, new TextResponse(ctx.getPathParameters().get("path")));
|
||||
// });
|
||||
|
||||
httpServer.start();
|
||||
}
|
||||
|
||||
}
|
37
src/main/java/me/mrletsplay/nojs/_test/DynPage.java
Normal file
37
src/main/java/me/mrletsplay/nojs/_test/DynPage.java
Normal file
@ -0,0 +1,37 @@
|
||||
package me.mrletsplay.nojs._test;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import me.mrletsplay.nojs.action.Action;
|
||||
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.Text;
|
||||
import me.mrletsplay.nojs.page.Page;
|
||||
import me.mrletsplay.nojs.page.layout.GridLayout;
|
||||
import me.mrletsplay.nojs.page.layout.InsetLayout;
|
||||
import me.mrletsplay.nojs.page.layout.Layout;
|
||||
|
||||
public class DynPage implements Page {
|
||||
|
||||
@Override
|
||||
public List<Component> getComponents() {
|
||||
return List.of(
|
||||
new Text().text(new Date().toString()),
|
||||
new Form()
|
||||
.action(Action.empty())
|
||||
.layout(new InsetLayout(GridLayout.ofColumns(1), "100px"))
|
||||
.add(new Button().text("Refresh")),
|
||||
new Group()
|
||||
.add(new Text().text("Your name is"))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Layout getLayout() {
|
||||
return GridLayout.ofColumns(1);
|
||||
}
|
||||
|
||||
}
|
76
src/main/java/me/mrletsplay/nojs/_test/LinksPage.java
Normal file
76
src/main/java/me/mrletsplay/nojs/_test/LinksPage.java
Normal file
@ -0,0 +1,76 @@
|
||||
package me.mrletsplay.nojs._test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import me.mrletsplay.nojs.action.Action;
|
||||
import me.mrletsplay.nojs.action.ActionEvent;
|
||||
import me.mrletsplay.nojs.action.ActionHandler;
|
||||
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.Link;
|
||||
import me.mrletsplay.nojs.component.impl.Message;
|
||||
import me.mrletsplay.nojs.component.impl.Text;
|
||||
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.Layout;
|
||||
|
||||
public class LinksPage implements Page {
|
||||
|
||||
private List<String> links = new ArrayList<>();
|
||||
private String error;
|
||||
|
||||
@Override
|
||||
public List<Component> getComponents() {
|
||||
Group linksGroup = new Group()
|
||||
.layout(GridLayout.ofColumns(1)
|
||||
.gap("2px"));
|
||||
|
||||
for(String s : links) {
|
||||
linksGroup.add(new Link().href(s).text(s));
|
||||
}
|
||||
|
||||
if(links.isEmpty()) {
|
||||
linksGroup.add(new Text().text("No links added yet"));
|
||||
}
|
||||
|
||||
if(error != null) {
|
||||
linksGroup.add(new Message().text(error));
|
||||
error = null;
|
||||
}
|
||||
|
||||
return List.of(
|
||||
linksGroup,
|
||||
new Form()
|
||||
.add(new Text().text("Add a new link:"))
|
||||
.add(new Group()
|
||||
.add(new TextInput("link").placeholder("Insert link here"))
|
||||
.add(new Button().text("Add Link"))
|
||||
.layout(new GridLayout().columns("1fr", "auto").gap("4px"))
|
||||
)
|
||||
.layout(GridLayout.ofColumns(1).gap("4px"))
|
||||
.action(new Action("addLink"))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Layout getLayout() {
|
||||
return GridLayout.ofColumns(1)
|
||||
.gap("10px");
|
||||
}
|
||||
|
||||
@ActionHandler("addLink")
|
||||
public void addLink(ActionEvent event) {
|
||||
String link = event.getData("link");
|
||||
if(link == null || link.isBlank()) {
|
||||
error = "Invalid link";
|
||||
return;
|
||||
}
|
||||
|
||||
links.add(event.getData("link"));
|
||||
}
|
||||
|
||||
}
|
30
src/main/java/me/mrletsplay/nojs/_test/TestPage.java
Normal file
30
src/main/java/me/mrletsplay/nojs/_test/TestPage.java
Normal file
@ -0,0 +1,30 @@
|
||||
package me.mrletsplay.nojs._test;
|
||||
|
||||
import me.mrletsplay.nojs.action.Action;
|
||||
import me.mrletsplay.nojs.action.ActionEvent;
|
||||
import me.mrletsplay.nojs.action.ActionHandler;
|
||||
import me.mrletsplay.nojs.component.impl.Button;
|
||||
import me.mrletsplay.nojs.component.impl.Form;
|
||||
import me.mrletsplay.nojs.component.impl.Link;
|
||||
import me.mrletsplay.nojs.component.impl.TextInput;
|
||||
import me.mrletsplay.nojs.page.StaticPage;
|
||||
import me.mrletsplay.nojs.page.layout.GridLayout;
|
||||
|
||||
public class TestPage extends StaticPage {
|
||||
|
||||
public TestPage() {
|
||||
add(new Form()
|
||||
.add(new TextInput("beans"))
|
||||
.add(new Button())
|
||||
.add(new Link().href("/test").text("Link to other page"))
|
||||
.action(new Action("submit"))
|
||||
.layout(GridLayout.ofSize(2, 2))
|
||||
);
|
||||
}
|
||||
|
||||
@ActionHandler("submit")
|
||||
public void onSubmit(ActionEvent event) {
|
||||
System.out.println("Got event " + event.getAction());
|
||||
}
|
||||
|
||||
}
|
54
src/main/java/me/mrletsplay/nojs/action/Action.java
Normal file
54
src/main/java/me/mrletsplay/nojs/action/Action.java
Normal file
@ -0,0 +1,54 @@
|
||||
package me.mrletsplay.nojs.action;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
|
||||
public class Action {
|
||||
|
||||
public static final String ACTION_NAME = "_action";
|
||||
|
||||
private String name;
|
||||
private ActionData extraData;
|
||||
|
||||
public Action(String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
|
||||
this.name = name;
|
||||
this.extraData = ActionData.EMPTY_DATA;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Action extraData(ActionData extraData) {
|
||||
this.extraData = extraData != null ? extraData : ActionData.EMPTY_DATA;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ActionData getExtraData() {
|
||||
return extraData;
|
||||
}
|
||||
|
||||
public List<HtmlElement> createFormElements() {
|
||||
List<HtmlElement> elements = new ArrayList<>();
|
||||
|
||||
HtmlElement action = HtmlElement.of("input");
|
||||
action.setAttribute("name", ACTION_NAME);
|
||||
action.setAttribute("value", name);
|
||||
action.setAttribute("hidden");
|
||||
elements.add(action);
|
||||
|
||||
elements.addAll(extraData.createFormElements());
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
public static Action empty() {
|
||||
return new Action("");
|
||||
}
|
||||
|
||||
}
|
49
src/main/java/me/mrletsplay/nojs/action/ActionData.java
Normal file
49
src/main/java/me/mrletsplay/nojs/action/ActionData.java
Normal file
@ -0,0 +1,49 @@
|
||||
package me.mrletsplay.nojs.action;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
|
||||
public class ActionData {
|
||||
|
||||
public static final ActionData EMPTY_DATA = new ActionData(Collections.emptyMap());
|
||||
|
||||
private Map<String, String> data;
|
||||
|
||||
private ActionData(Map<String, String> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public ActionData() {
|
||||
this.data = new HashMap<>();
|
||||
}
|
||||
|
||||
public ActionData put(String key, String value) {
|
||||
Objects.requireNonNull(key, "key");
|
||||
Objects.requireNonNull(value, "value");
|
||||
|
||||
data.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<HtmlElement> createFormElements() {
|
||||
if(data.isEmpty()) return Collections.emptyList();
|
||||
|
||||
List<HtmlElement> elements = new ArrayList<>();
|
||||
for(Map.Entry<String, String> d : data.entrySet()) {
|
||||
HtmlElement e = HtmlElement.of("input");
|
||||
e.setAttribute("name", d.getKey());
|
||||
e.setAttribute("value", d.getValue());
|
||||
e.setAttribute("hidden");
|
||||
elements.add(e);
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
}
|
21
src/main/java/me/mrletsplay/nojs/action/ActionEvent.java
Normal file
21
src/main/java/me/mrletsplay/nojs/action/ActionEvent.java
Normal file
@ -0,0 +1,21 @@
|
||||
package me.mrletsplay.nojs.action;
|
||||
|
||||
import me.mrletsplay.simplehttpserver.http.request.urlencoded.UrlEncoded;
|
||||
|
||||
public class ActionEvent {
|
||||
|
||||
private UrlEncoded data;
|
||||
|
||||
public ActionEvent(UrlEncoded data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return data.getFirst(Action.ACTION_NAME);
|
||||
}
|
||||
|
||||
public String getData(String name) {
|
||||
return data.getFirst(name);
|
||||
}
|
||||
|
||||
}
|
14
src/main/java/me/mrletsplay/nojs/action/ActionHandler.java
Normal file
14
src/main/java/me/mrletsplay/nojs/action/ActionHandler.java
Normal file
@ -0,0 +1,14 @@
|
||||
package me.mrletsplay.nojs.action;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ActionHandler {
|
||||
|
||||
public String value();
|
||||
|
||||
}
|
29
src/main/java/me/mrletsplay/nojs/action/ActionHandlers.java
Normal file
29
src/main/java/me/mrletsplay/nojs/action/ActionHandlers.java
Normal file
@ -0,0 +1,29 @@
|
||||
package me.mrletsplay.nojs.action;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public interface ActionHandlers {
|
||||
|
||||
public default void onAction(ActionEvent event) {
|
||||
if(event.getAction() == null) return;
|
||||
|
||||
for(Method m : getClass().getDeclaredMethods()) {
|
||||
ActionHandler handler = m.getAnnotation(ActionHandler.class);
|
||||
if(handler == null) continue;
|
||||
if(!handler.value().equals(event.getAction())) continue;
|
||||
|
||||
if(m.getParameterCount() != 1 || m.getParameters()[0].getType() != ActionEvent.class) {
|
||||
System.err.println("Invalid action handler found: " + m.getName() + ". Must have one parameter of type ActionEvent");
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
m.invoke(this, event);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e); // TODO: exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package me.mrletsplay.nojs.component;
|
||||
|
||||
import me.mrletsplay.nojs.action.Action;
|
||||
|
||||
public interface ActionableComponent extends Component {
|
||||
|
||||
public ActionableComponent action(Action action);
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package me.mrletsplay.nojs.component;
|
||||
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
|
||||
public interface Component {
|
||||
|
||||
public HtmlElement toHtml();
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package me.mrletsplay.nojs.component;
|
||||
|
||||
import me.mrletsplay.nojs.page.layout.Layout;
|
||||
|
||||
public interface ContainerComponent extends Component {
|
||||
|
||||
public ContainerComponent add(Component component);
|
||||
|
||||
public ContainerComponent layout(Layout layout);
|
||||
|
||||
}
|
76
src/main/java/me/mrletsplay/nojs/component/impl/Button.java
Normal file
76
src/main/java/me/mrletsplay/nojs/component/impl/Button.java
Normal file
@ -0,0 +1,76 @@
|
||||
package me.mrletsplay.nojs.component.impl;
|
||||
|
||||
import me.mrletsplay.nojs.action.Action;
|
||||
import me.mrletsplay.nojs.component.ActionableComponent;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.element.HtmlButton;
|
||||
|
||||
public class Button implements ActionableComponent {
|
||||
|
||||
private String text;
|
||||
private Style style;
|
||||
private boolean enabled;
|
||||
private Action action;
|
||||
|
||||
public Button() {
|
||||
this.text = "Button";
|
||||
this.style = Style.NORMAL;
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
public Button text(String text) {
|
||||
this.text = text != null ? text : "Button";
|
||||
return this;
|
||||
}
|
||||
|
||||
public Button style(Style style) {
|
||||
this.style = style != null ? style : Style.NORMAL;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Button enabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Button action(Action action) {
|
||||
this.action = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HtmlElement toHtml() {
|
||||
HtmlButton button = HtmlElement.button();
|
||||
button.addClass("button");
|
||||
|
||||
if(style != null) {
|
||||
button.setAttribute("data-style", style.name().toLowerCase());
|
||||
}
|
||||
|
||||
if(!enabled) {
|
||||
button.setAttribute("disabled");
|
||||
}
|
||||
|
||||
button.setText(text);
|
||||
|
||||
if(action != null) {
|
||||
button.setAttribute("data-action");
|
||||
|
||||
HtmlElement form = Form.createElement(action, null);
|
||||
form.appendChild(button);
|
||||
return form;
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
public static enum Style { // TODO
|
||||
|
||||
NORMAL,
|
||||
LINK,
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
}
|
73
src/main/java/me/mrletsplay/nojs/component/impl/Form.java
Normal file
73
src/main/java/me/mrletsplay/nojs/component/impl/Form.java
Normal file
@ -0,0 +1,73 @@
|
||||
package me.mrletsplay.nojs.component.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import me.mrletsplay.nojs.action.Action;
|
||||
import me.mrletsplay.nojs.component.ActionableComponent;
|
||||
import me.mrletsplay.nojs.component.Component;
|
||||
import me.mrletsplay.nojs.component.ContainerComponent;
|
||||
import me.mrletsplay.nojs.page.layout.Layout;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
|
||||
public class Form implements ActionableComponent, ContainerComponent {
|
||||
|
||||
private Action action;
|
||||
private List<Component> components;
|
||||
private Layout layout;
|
||||
|
||||
public Form() {
|
||||
this.components = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Form add(Component component) {
|
||||
components.add(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Form layout(Layout layout) {
|
||||
this.layout = layout;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Form action(Action action) {
|
||||
this.action = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HtmlElement toHtml() {
|
||||
HtmlElement form = createElement(action, layout);
|
||||
|
||||
for(Component c : components) {
|
||||
// TODO: check for nested forms
|
||||
|
||||
form.appendChild(c.toHtml());
|
||||
}
|
||||
|
||||
return form;
|
||||
}
|
||||
|
||||
public static HtmlElement createElement(Action action, Layout layout) {
|
||||
HtmlElement form = HtmlElement.of("form");
|
||||
form.addClass("form");
|
||||
form.setAttribute("action", "");
|
||||
form.setAttribute("method", "post");
|
||||
|
||||
if(layout != null) {
|
||||
layout.apply(form);
|
||||
}
|
||||
|
||||
if(action != null) {
|
||||
for(HtmlElement e : action.createFormElements()) {
|
||||
form.appendChild(e);
|
||||
}
|
||||
}
|
||||
|
||||
return form;
|
||||
}
|
||||
|
||||
}
|
47
src/main/java/me/mrletsplay/nojs/component/impl/Group.java
Normal file
47
src/main/java/me/mrletsplay/nojs/component/impl/Group.java
Normal file
@ -0,0 +1,47 @@
|
||||
package me.mrletsplay.nojs.component.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import me.mrletsplay.nojs.component.Component;
|
||||
import me.mrletsplay.nojs.component.ContainerComponent;
|
||||
import me.mrletsplay.nojs.page.layout.Layout;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
|
||||
public class Group implements ContainerComponent {
|
||||
|
||||
private List<Component> components;
|
||||
private Layout layout;
|
||||
|
||||
public Group() {
|
||||
this.components = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group add(Component component) {
|
||||
components.add(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group layout(Layout layout) {
|
||||
this.layout = layout;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HtmlElement toHtml() {
|
||||
HtmlElement div = HtmlElement.of("div");
|
||||
div.addClass("group");
|
||||
|
||||
if(layout != null) {
|
||||
layout.apply(div);
|
||||
}
|
||||
|
||||
for(Component c : components) {
|
||||
div.appendChild(c.toHtml());
|
||||
}
|
||||
|
||||
return div;
|
||||
}
|
||||
}
|
35
src/main/java/me/mrletsplay/nojs/component/impl/Link.java
Normal file
35
src/main/java/me/mrletsplay/nojs/component/impl/Link.java
Normal file
@ -0,0 +1,35 @@
|
||||
package me.mrletsplay.nojs.component.impl;
|
||||
|
||||
import me.mrletsplay.nojs.component.Component;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
|
||||
public class Link implements Component {
|
||||
|
||||
private String text;
|
||||
private String href;
|
||||
|
||||
public Link() {
|
||||
this.text = "Link";
|
||||
this.href = "#";
|
||||
}
|
||||
|
||||
public Link text(String text) {
|
||||
this.text = text != null ? text : "Link";
|
||||
return this;
|
||||
}
|
||||
|
||||
public Link href(String href) {
|
||||
this.href = href != null ? href : "#";
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HtmlElement toHtml() {
|
||||
HtmlElement link = HtmlElement.of("a");
|
||||
link.addClass("link");
|
||||
link.setText(text);
|
||||
link.setAttribute("href", href);
|
||||
return link;
|
||||
}
|
||||
|
||||
}
|
49
src/main/java/me/mrletsplay/nojs/component/impl/Message.java
Normal file
49
src/main/java/me/mrletsplay/nojs/component/impl/Message.java
Normal file
@ -0,0 +1,49 @@
|
||||
package me.mrletsplay.nojs.component.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import me.mrletsplay.nojs.NoJS;
|
||||
import me.mrletsplay.nojs.component.Component;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.element.HtmlRaw;
|
||||
|
||||
public class Message implements Component {
|
||||
|
||||
private String text;
|
||||
|
||||
public Message() {
|
||||
this.text = "Message";
|
||||
}
|
||||
|
||||
public Message text(String text) {
|
||||
this.text = text != null ? text : "Message";
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HtmlElement toHtml() {
|
||||
HtmlElement message = HtmlElement.of("div");
|
||||
message.addClass("message");
|
||||
|
||||
HtmlElement textSpan = HtmlElement.of("span");
|
||||
textSpan.setText(text);
|
||||
message.appendChild(textSpan);
|
||||
|
||||
HtmlElement checkLabel = HtmlElement.of("label");
|
||||
message.appendChild(checkLabel);
|
||||
|
||||
HtmlElement check = HtmlElement.of("input");
|
||||
check.setAttribute("type", "checkbox");
|
||||
check.setAttribute("autocomplete", "off"); // Clear on reload
|
||||
checkLabel.appendChild(check);
|
||||
|
||||
try(InputStream in = NoJS.class.getResourceAsStream("/icon/x.svg")) {
|
||||
checkLabel.appendChild(new HtmlRaw(new String(in.readAllBytes(), StandardCharsets.UTF_8)));
|
||||
}catch(IOException ex) {}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
42
src/main/java/me/mrletsplay/nojs/component/impl/Text.java
Normal file
42
src/main/java/me/mrletsplay/nojs/component/impl/Text.java
Normal file
@ -0,0 +1,42 @@
|
||||
package me.mrletsplay.nojs.component.impl;
|
||||
|
||||
import me.mrletsplay.nojs.component.Component;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
|
||||
public class Text implements Component {
|
||||
|
||||
private Type type;
|
||||
private String text;
|
||||
|
||||
public Text() {
|
||||
this.type = Type.PLAIN;
|
||||
this.text = "Text";
|
||||
}
|
||||
|
||||
public Text type(Type type) {
|
||||
this.type = type == null ? Type.PLAIN : type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Text text(String text) {
|
||||
this.text = text != null ? text : "Text";
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HtmlElement toHtml() {
|
||||
HtmlElement text = HtmlElement.of(type == Type.PLAIN ? "span" : "p");
|
||||
text.addClass("text");
|
||||
text.setText(this.text);
|
||||
return text;
|
||||
}
|
||||
|
||||
public static enum Type {
|
||||
|
||||
PLAIN,
|
||||
PARAGRAPH,
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package me.mrletsplay.nojs.component.impl;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import me.mrletsplay.nojs.component.Component;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
|
||||
public class TextInput implements Component {
|
||||
|
||||
private String name;
|
||||
private String placeholder;
|
||||
private String value;
|
||||
private boolean hidden;
|
||||
|
||||
public TextInput(String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
|
||||
this.name = name;
|
||||
this.placeholder = "";
|
||||
this.value = "";
|
||||
this.hidden = false;
|
||||
}
|
||||
|
||||
public TextInput placeholder(String placeholder) {
|
||||
this.placeholder = placeholder != null ? placeholder : "";
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextInput value(String value) {
|
||||
this.value = value != null ? value : "";
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextInput hidden(boolean hidden) {
|
||||
this.hidden = hidden;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HtmlElement toHtml() {
|
||||
HtmlElement input = HtmlElement.of("input");
|
||||
input.addClass("input");
|
||||
input.setAttribute("name", name);
|
||||
|
||||
if(!placeholder.isEmpty()) {
|
||||
input.setAttribute("placeholder", placeholder);
|
||||
}
|
||||
|
||||
if(!value.isEmpty()) {
|
||||
input.setAttribute("value", value);
|
||||
}
|
||||
|
||||
if(hidden) {
|
||||
input.setAttribute("hidden");
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
}
|
79
src/main/java/me/mrletsplay/nojs/page/Page.java
Normal file
79
src/main/java/me/mrletsplay/nojs/page/Page.java
Normal file
@ -0,0 +1,79 @@
|
||||
package me.mrletsplay.nojs.page;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import me.mrletsplay.nojs.action.ActionEvent;
|
||||
import me.mrletsplay.nojs.action.ActionHandlers;
|
||||
import me.mrletsplay.nojs.component.Component;
|
||||
import me.mrletsplay.nojs.page.layout.Layout;
|
||||
import me.mrletsplay.simplehttpserver.dom.css.CssElement;
|
||||
import me.mrletsplay.simplehttpserver.dom.css.CssSelector;
|
||||
import me.mrletsplay.simplehttpserver.dom.css.StyleSheet;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlDocument;
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
import me.mrletsplay.simplehttpserver.http.HttpRequestMethod;
|
||||
import me.mrletsplay.simplehttpserver.http.HttpStatusCodes;
|
||||
import me.mrletsplay.simplehttpserver.http.document.DocumentProvider;
|
||||
import me.mrletsplay.simplehttpserver.http.document.HttpDocument;
|
||||
import me.mrletsplay.simplehttpserver.http.header.DefaultClientContentTypes;
|
||||
import me.mrletsplay.simplehttpserver.http.request.HttpRequestContext;
|
||||
import me.mrletsplay.simplehttpserver.http.request.urlencoded.UrlEncoded;
|
||||
import me.mrletsplay.simplehttpserver.http.response.HtmlResponse;
|
||||
|
||||
public interface Page extends HttpDocument, ActionHandlers {
|
||||
|
||||
public List<Component> getComponents();
|
||||
|
||||
public default Layout getLayout() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public default HtmlDocument toHtml() {
|
||||
HtmlDocument doc = new HtmlDocument();
|
||||
doc.addStyleSheet("/base.css");
|
||||
|
||||
StyleSheet sheet = new StyleSheet();
|
||||
|
||||
CssElement cssE = new CssElement(CssSelector.selectClass("ee"));
|
||||
cssE.setProperty("text", "red");
|
||||
sheet.addElement(cssE);
|
||||
|
||||
doc.getHeadNode().appendChild(HtmlElement.style(sheet));
|
||||
|
||||
Layout layout = getLayout();
|
||||
if(layout != null) {
|
||||
layout.apply(doc.getBodyNode());
|
||||
}
|
||||
|
||||
for(Component c : getComponents()) {
|
||||
doc.getBodyNode().appendChild(c.toHtml());
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public default void createContent() {
|
||||
HttpRequestContext ctx = HttpRequestContext.getCurrentContext();
|
||||
|
||||
if(ctx.getClientHeader().getMethod() == HttpRequestMethod.POST) {
|
||||
// TODO: error handling
|
||||
UrlEncoded data = ctx.getClientHeader().getPostData().getParsedAs(DefaultClientContentTypes.URLENCODED);
|
||||
System.out.println(data);
|
||||
|
||||
ActionEvent e = new ActionEvent(data);
|
||||
onAction(e);
|
||||
|
||||
ctx.redirect(HttpStatusCodes.SEE_OTHER_303, ctx.getClientHeader().getPath().toString());
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.respond(HttpStatusCodes.OK_200, new HtmlResponse(toHtml()));
|
||||
}
|
||||
|
||||
public default void register(DocumentProvider provider, String path) {
|
||||
provider.register(HttpRequestMethod.GET, path, this);
|
||||
provider.register(HttpRequestMethod.POST, path, this);
|
||||
}
|
||||
|
||||
}
|
56
src/main/java/me/mrletsplay/nojs/page/StaticPage.java
Normal file
56
src/main/java/me/mrletsplay/nojs/page/StaticPage.java
Normal file
@ -0,0 +1,56 @@
|
||||
package me.mrletsplay.nojs.page;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import me.mrletsplay.nojs.action.ActionEvent;
|
||||
import me.mrletsplay.nojs.action.ActionHandlers;
|
||||
import me.mrletsplay.nojs.component.Component;
|
||||
import me.mrletsplay.nojs.page.layout.Layout;
|
||||
|
||||
public class StaticPage implements Page {
|
||||
|
||||
private List<Component> components;
|
||||
private Layout layout;
|
||||
private List<ActionHandlers> actionHandlers;
|
||||
|
||||
public StaticPage() {
|
||||
this.components = new ArrayList<>();
|
||||
this.actionHandlers = new ArrayList<>();
|
||||
}
|
||||
|
||||
public StaticPage add(Component component) {
|
||||
components.add(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StaticPage layout(Layout layout) {
|
||||
this.layout = layout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StaticPage addActionHandler(ActionHandlers handler) {
|
||||
actionHandlers.add(handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Component> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Layout getLayout() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAction(ActionEvent event) {
|
||||
Page.super.onAction(event);
|
||||
|
||||
for(ActionHandlers handler : actionHandlers) {
|
||||
handler.onAction(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
115
src/main/java/me/mrletsplay/nojs/page/layout/GridLayout.java
Normal file
115
src/main/java/me/mrletsplay/nojs/page/layout/GridLayout.java
Normal file
@ -0,0 +1,115 @@
|
||||
package me.mrletsplay.nojs.page.layout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
|
||||
public class GridLayout implements Layout {
|
||||
|
||||
private List<String> columns;
|
||||
private List<String> rows;
|
||||
private String gap;
|
||||
private Flow flow;
|
||||
|
||||
public GridLayout() {
|
||||
this.columns = new ArrayList<>();
|
||||
this.rows = new ArrayList<>();
|
||||
this.flow = Flow.ROW;
|
||||
}
|
||||
|
||||
public GridLayout columns(Collection<String> columns) {
|
||||
this.columns = new ArrayList<>(columns == null ? Collections.emptyList() : columns);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GridLayout rows(Collection<String> rows) {
|
||||
this.rows = new ArrayList<>(rows == null ? Collections.emptyList() : rows);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GridLayout columns(String... columns) {
|
||||
return columns(columns == null ? null : Arrays.asList(columns));
|
||||
}
|
||||
|
||||
public GridLayout rows(String... rows) {
|
||||
return rows(rows == null ? null : Arrays.asList(rows));
|
||||
}
|
||||
|
||||
public GridLayout gap(String gap) {
|
||||
this.gap = gap;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GridLayout flow(Flow flow) {
|
||||
this.flow = flow;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(HtmlElement html) {
|
||||
String css = "display:grid;";
|
||||
|
||||
if(!columns.isEmpty()) {
|
||||
css += "grid-template-columns:" + String.join(" ", columns) + ";";
|
||||
}
|
||||
|
||||
if(!rows.isEmpty()) {
|
||||
css += "grid-template-rows:" + String.join(" ", rows) + ";";
|
||||
}
|
||||
|
||||
if(gap != null) {
|
||||
css += "gap:" + gap + ";";
|
||||
}
|
||||
|
||||
if(flow != Flow.ROW) {
|
||||
css += "grid-auto-flow:" + flow.name().toLowerCase() + ";";
|
||||
}
|
||||
|
||||
html.setAttribute("style", css);
|
||||
}
|
||||
|
||||
public static GridLayout ofColumns(int columns) {
|
||||
List<String> colSizes = new ArrayList<>();
|
||||
for(int i = 0; i < columns; i++) {
|
||||
colSizes.add("auto");
|
||||
}
|
||||
|
||||
return new GridLayout()
|
||||
.columns(colSizes);
|
||||
}
|
||||
|
||||
public static GridLayout ofRows(int rows) {
|
||||
List<String> rowSizes = new ArrayList<>();
|
||||
for(int i = 0; i < rows; i++) {
|
||||
rowSizes.add("auto");
|
||||
}
|
||||
|
||||
return new GridLayout()
|
||||
.flow(Flow.COLUMN)
|
||||
.rows(rowSizes);
|
||||
}
|
||||
|
||||
public static GridLayout ofSize(int columns, int rows) {
|
||||
List<String> colsAndRows = new ArrayList<>();
|
||||
for(int i = 0; i < Math.max(columns, rows); i++) {
|
||||
colsAndRows.add("auto");
|
||||
}
|
||||
|
||||
return new GridLayout()
|
||||
.columns(colsAndRows.subList(0, columns))
|
||||
.rows(colsAndRows.subList(0, rows));
|
||||
}
|
||||
|
||||
public static enum Flow {
|
||||
|
||||
ROW,
|
||||
COLUMN,
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package me.mrletsplay.nojs.page.layout;
|
||||
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
|
||||
public class InsetLayout implements Layout {
|
||||
|
||||
private Layout layout;
|
||||
private String inset;
|
||||
|
||||
public InsetLayout(Layout layout, String inset) {
|
||||
this.layout = layout;
|
||||
this.inset = inset == null ? "0" : inset;
|
||||
}
|
||||
|
||||
public void apply(HtmlElement html) {
|
||||
if(layout != null) layout.apply(html);
|
||||
html.appendAttribute("style", "margin:" + inset + ";");
|
||||
}
|
||||
|
||||
}
|
9
src/main/java/me/mrletsplay/nojs/page/layout/Layout.java
Normal file
9
src/main/java/me/mrletsplay/nojs/page/layout/Layout.java
Normal file
@ -0,0 +1,9 @@
|
||||
package me.mrletsplay.nojs.page.layout;
|
||||
|
||||
import me.mrletsplay.simplehttpserver.dom.html.HtmlElement;
|
||||
|
||||
public interface Layout {
|
||||
|
||||
public void apply(HtmlElement html);
|
||||
|
||||
}
|
28
src/main/java/me/mrletsplay/nojs/rest/TestEndpoint.java
Normal file
28
src/main/java/me/mrletsplay/nojs/rest/TestEndpoint.java
Normal file
@ -0,0 +1,28 @@
|
||||
package me.mrletsplay.nojs.rest;
|
||||
|
||||
import me.mrletsplay.simplehttpserver.http.HttpRequestMethod;
|
||||
import me.mrletsplay.simplehttpserver.http.HttpStatusCodes;
|
||||
import me.mrletsplay.simplehttpserver.http.endpoint.Endpoint;
|
||||
import me.mrletsplay.simplehttpserver.http.endpoint.EndpointCollection;
|
||||
import me.mrletsplay.simplehttpserver.http.header.DefaultClientContentTypes;
|
||||
import me.mrletsplay.simplehttpserver.http.request.HttpRequestContext;
|
||||
import me.mrletsplay.simplehttpserver.http.request.urlencoded.UrlEncoded;
|
||||
import me.mrletsplay.simplehttpserver.http.response.TextResponse;
|
||||
|
||||
public class TestEndpoint implements EndpointCollection {
|
||||
|
||||
@Endpoint(method = HttpRequestMethod.POST, path = "/test")
|
||||
public void test() {
|
||||
HttpRequestContext ctx = HttpRequestContext.getCurrentContext();
|
||||
|
||||
UrlEncoded encoded = ctx.getClientHeader().getPostData().getParsedAs(DefaultClientContentTypes.URLENCODED);
|
||||
|
||||
ctx.respond(HttpStatusCodes.OK_200, new TextResponse(encoded.getFirst("test")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBasePath() {
|
||||
return "/api";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package me.mrletsplay.nojs.util;
|
||||
|
||||
public class ValidationException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 5956388648233218085L;
|
||||
|
||||
public ValidationException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ValidationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ValidationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ValidationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
41
src/main/resources/icon/x.svg
Normal file
41
src/main/resources/icon/x.svg
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="31.999998"
|
||||
height="31.999998"
|
||||
viewBox="0 0 8.466666 8.466666"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="layer1">
|
||||
<g
|
||||
id="g7"
|
||||
style="fill-opacity:1">
|
||||
<rect
|
||||
style="fill-opacity:1;stroke-width:0.184"
|
||||
id="rect6"
|
||||
width="1.0583333"
|
||||
height="8.4666662"
|
||||
x="5.4576707"
|
||||
y="-4.2333331"
|
||||
rx="0.26458332"
|
||||
ry="0.26458332"
|
||||
transform="rotate(45)" />
|
||||
<rect
|
||||
style="fill-opacity:1;stroke-width:0.184"
|
||||
id="rect6-3"
|
||||
width="1.0583333"
|
||||
height="8.4666662"
|
||||
x="-0.52916664"
|
||||
y="1.7535037"
|
||||
rx="0.26458332"
|
||||
ry="0.26458332"
|
||||
transform="matrix(-0.70710678,0.70710678,0.70710678,0.70710678,0,0)" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1023 B |
119
src/main/resources/style/base.css
Normal file
119
src/main/resources/style/base.css
Normal file
@ -0,0 +1,119 @@
|
||||
html {
|
||||
--background: #222;
|
||||
--foreground: #444;
|
||||
--accent: #3584e4;
|
||||
--text: #fff;
|
||||
--link: var(--accent);
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: system-ui;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
/*.button, .link, .input {
|
||||
margin: 2px;
|
||||
}*/
|
||||
|
||||
.button {
|
||||
background: var(--accent);
|
||||
color: var(--text);
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.button:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.input {
|
||||
background: #2c3444;
|
||||
border: none;
|
||||
color: var(--text);
|
||||
border-radius: 5px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.input:focus, .button:focus, .link:focus {
|
||||
outline: 2px solid var(--accent);
|
||||
}
|
||||
|
||||
.link, .button[data-style="link"] {
|
||||
background: unset;
|
||||
color: var(--link);
|
||||
text-decoration: none;
|
||||
padding: 0;
|
||||
font-weight: normal;
|
||||
font-size: 1em;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.link:hover, .button[data-style="link"]:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.message {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
min-height: 30px;
|
||||
background-color: orangered;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.message>label>input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.message>*:first-child {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.message>*:last-child {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.message>label {
|
||||
position: relative;
|
||||
/*background: var(--accent);*/
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.message>label>svg {
|
||||
fill: white;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/*.message>label:after {
|
||||
display: block;
|
||||
text-align: center;
|
||||
content: "x";
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}*/
|
||||
|
||||
.message:has(:checked) {
|
||||
display: none;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user