m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagdalena GrodziƄska <mag.grodzinska@gmail.com>2019-11-21 10:46:21 +0100
committerGitHub <noreply@github.com>2019-11-21 10:46:21 +0100
commitd683a761b2710a252b0bfb1b3f0879a60247bb50 (patch)
tree06a0ccf7e2df0b8736f3f3889da039b39b617534
parent79c8f56efcf76e7916597c0ef0e554d9fb91f8f4 (diff)
parent02f98aed224580d05deb4b40eac4a11c36d39498 (diff)
Merge pull request #25 from m-chrzan/extend_frontend
Extend frontend
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/client/Attribute.java51
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/client/ClientController.java111
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java3
-rw-r--r--src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/attribForm.html50
-rw-r--r--src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/fragments/navbar.html5
-rw-r--r--src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/queryForm.html22
6 files changed, 218 insertions, 24 deletions
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/client/Attribute.java b/src/main/java/pl/edu/mimuw/cloudatlas/client/Attribute.java
new file mode 100644
index 0000000..abaa02a
--- /dev/null
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/client/Attribute.java
@@ -0,0 +1,51 @@
+package pl.edu.mimuw.cloudatlas.client;
+
+import pl.edu.mimuw.cloudatlas.model.Value;
+
+public class Attribute {
+ private String zoneName;
+ private String attributeName;
+ private String valueString;
+ private String attributeType;
+ private Value value;
+
+ public String getZoneName() {
+ return zoneName;
+ }
+
+ public void setZoneName(String zoneName) {
+ this.zoneName = zoneName;
+ }
+
+ public String getAttributeName() {
+ return attributeName;
+ }
+
+ public void setAttributeName(String attributeName) {
+ this.attributeName = attributeName;
+ }
+
+ public String getValueString() {
+ return valueString;
+ }
+
+ public void setValueString(String valueString) {
+ this.valueString = valueString;
+ }
+
+ public Value getValue() {
+ return value;
+ }
+
+ public void setValue(Value value) {
+ this.value = value;
+ }
+
+ public String getAttributeType() {
+ return attributeType;
+ }
+
+ public void setAttributeType(String attributeType) {
+ this.attributeType = attributeType;
+ }
+}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/client/ClientController.java b/src/main/java/pl/edu/mimuw/cloudatlas/client/ClientController.java
index 31d1c06..022c665 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/client/ClientController.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/client/ClientController.java
@@ -5,8 +5,7 @@ import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
import pl.edu.mimuw.cloudatlas.api.Api;
-import pl.edu.mimuw.cloudatlas.model.PathName;
-import pl.edu.mimuw.cloudatlas.model.ValueContact;
+import pl.edu.mimuw.cloudatlas.model.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -85,26 +84,34 @@ public class ClientController {
return "contactsForm";
}
- @PostMapping("/contacts")
- public String contactPage(@ModelAttribute ContactsString contactsObject, Model model) {
- boolean success = true;
+ private Set<ValueContact> parseContactsString(ContactsString contactsInput) throws Exception {
Gson gson = new Gson();
- Map<String, ArrayList> contactStrings = gson.fromJson(contactsObject.getString(), Map.class);
+ Map<String, ArrayList> contactStrings = gson.fromJson(contactsInput.getString(), Map.class);
Set<ValueContact> contactObjects = new HashSet<ValueContact>();
ArrayList<Double> cAddr;
byte[] inetArray = new byte[4];
- try {
- for (Map.Entry<String, ArrayList> cursor : contactStrings.entrySet()) {
- cAddr = cursor.getValue(); // gson always reads numerical values as doubles
- for (int i = 0; i < 4; i++) {
- inetArray[i] = (byte) cAddr.get(i).doubleValue();
- }
- contactObjects.add(new ValueContact(
- new PathName(cursor.getKey()),
- InetAddress.getByAddress(inetArray))
- );
+ for (Map.Entry<String, ArrayList> cursor : contactStrings.entrySet()) {
+ cAddr = cursor.getValue(); // gson always reads numerical values as doubles
+ for (int i = 0; i < 4; i++) {
+ inetArray[i] = (byte) cAddr.get(i).doubleValue();
}
+ contactObjects.add(new ValueContact(
+ new PathName(cursor.getKey()),
+ InetAddress.getByAddress(inetArray))
+ );
+ }
+
+ return contactObjects;
+ }
+
+ @PostMapping("/contacts")
+ public String contactPage(@ModelAttribute ContactsString contactsObject, Model model) {
+ boolean success = true;
+ Set<ValueContact> contactObjects;
+
+ try {
+ contactObjects = parseContactsString(contactsObject);
this.api.setFallbackContacts(contactObjects);
} catch (Exception e) {
success = false;
@@ -123,6 +130,78 @@ public class ClientController {
@GetMapping("/attribs")
public String attribPage(Model model) {
+ model.addAttribute("attributeObject", new Attribute());
+ return "attribForm";
+ }
+
+ private Value parseAttributeValue(Attribute attributeObject) throws Exception {
+ Value attributeValue = null;
+
+ switch (attributeObject.getAttributeType()) {
+ case "Boolean":
+ attributeValue = attributeObject.getValueString().toLowerCase().equals("true") ?
+ new ValueBoolean(true) :
+ new ValueBoolean(false);
+ break;
+ case "Double":
+ attributeValue = new ValueDouble(Double.parseDouble(attributeObject.getValueString()));
+ break;
+ case "Int":
+ attributeValue = new ValueInt(Long.parseLong(attributeObject.getValueString()));
+ break;
+ case "String":
+ attributeValue = new ValueString(attributeObject.getValueString());
+ break;
+ case "Time":
+ attributeValue = new ValueTime(Long.parseLong(attributeObject.getValueString()));
+ break;
+ case "Duration":
+ attributeValue = new ValueDuration(attributeObject.getValueString());
+ break;
+ case "Contact":
+ ContactsString contactsString = new ContactsString();
+ contactsString.setString(attributeObject.getValueString());
+ attributeValue = parseContactsString(contactsString).iterator().next();
+ break;
+ case "Query":
+ attributeValue = new ValueQuery(attributeObject.getValueString());
+ break;
+ default:
+ String errMsg = "Value type not supported: " + attributeObject.getAttributeType();
+ throw new UnsupportedOperationException(errMsg);
+ }
+
+ return attributeValue;
+ }
+
+ @PostMapping("/attribs")
+ public String attribPage(@ModelAttribute Attribute attributeObject, Model model) {
+ boolean success = true;
+ Value attributeValue;
+
+ try {
+ attributeValue = parseAttributeValue(attributeObject);
+ api.setAttributeValue(
+ attributeObject.getZoneName(),
+ attributeObject.getAttributeName(),
+ attributeValue);
+ } catch (Exception e) {
+ success = false;
+ System.err.println("Client exception:");
+ e.printStackTrace();
+ }
+
+ if (success) {
+ model.addAttribute("homeMessage", "Attribute submitted successfully");
+ } else {
+ model.addAttribute("homeMessage", "Attribute submission failed");
+ }
+
+ return "home";
+ }
+
+ @GetMapping("/values")
+ public String valuesPage(Model model) {
return "attribChart";
}
}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java b/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java
index a311c61..7f2f604 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java
@@ -27,6 +27,7 @@ package pl.edu.mimuw.cloudatlas.model;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -40,7 +41,7 @@ import com.esotericsoftware.kryo.io.Output;
* A zone management information object. This object is a single node in a zone hierarchy. It stores zone attributes as well as
* references to its father and sons in the tree.
*/
-public class ZMI implements Cloneable {
+public class ZMI implements Cloneable, Serializable {
public class NoSuchZoneException extends Exception {
public NoSuchZoneException(PathName path) {
super("No such zone: " + path);
diff --git a/src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/attribForm.html b/src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/attribForm.html
new file mode 100644
index 0000000..0499bc8
--- /dev/null
+++ b/src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/attribForm.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org">
+
+<head>
+ <meta charset="UTF-8">
+ <title>Query form</title>
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
+</head>
+
+<body>
+
+<div th:replace="fragments/navbar :: navbar"></div>
+<div id="queryForm">
+ <form action="#" th:action="@{/attribs}" th:object="${attributeObject}" method="post">
+ <div class="form-group">
+ <label for="ZoneName1">Enter zone name</label>
+ <input type="text" class="form-control" id="ZoneName1" rows="3" th:field="*{zoneName}"/>
+ </div>
+ <div class="form-group">
+ <label for="AttributeName1">Enter attribute name</label>
+ <input type="text" class="form-control" id="AttributeName1" rows="3" th:field="*{attributeName}"/>
+ </div>
+ <div class="form-group">
+ <label for="TypeSelect1">Enter attribute type</label>
+ <select class="form-control" id="TypeSelect1" th:field="*{attributeType}">
+ <option th:value="Boolean" th:text="Boolean"></option>
+ <option th:value="Double" th:text="Double"></option>
+ <option th:value="Int" th:text="Int"></option>
+ <option th:value="String" th:text="String"></option>
+ <option th:value="Time" th:text="Time"></option>
+ <option th:value="Duration" th:text="Duration"></option>
+ <option th:value="Contact" th:text="Contact"></option>
+ <option th:value="Query" th:text="Query"></option>
+ </select>
+ </div>
+ <div class="form-group">
+ <label for="Textarea1">Enter attribute value as a Json</label>
+ <textarea class="form-control" id="Textarea1" rows="3" th:field="*{valueString}"></textarea>
+ </div>
+ <button type="submit" class="btn btn-primary">Submit</button>
+ </form>
+</div>
+
+<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
+<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
+
+</body>
+
+</html>
diff --git a/src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/fragments/navbar.html b/src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/fragments/navbar.html
index c651f74..ca83cbb 100644
--- a/src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/fragments/navbar.html
+++ b/src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/fragments/navbar.html
@@ -27,7 +27,10 @@
<a class="nav-link" href="/contacts">Contacts</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="/attribs">Attribute values</a>
+ <a class="nav-link" href="/attribs">Attributes</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/values">Values</a>
</li>
</ul>
</div>
diff --git a/src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/queryForm.html b/src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/queryForm.html
index ac00645..08b4e89 100644
--- a/src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/queryForm.html
+++ b/src/main/resources/pl/edu/mimuw/cloudatlas/client/templates/queryForm.html
@@ -10,20 +10,30 @@
<body>
<div th:replace="fragments/navbar :: navbar"></div>
-<div id="queryForm">
+<div id="installQueryForm">
+ <h2 class="display-7">Install query</h2>
<form action="#" th:action="@{/query}" th:object="${queryObject}" method="post">
<div class="form-group">
- <label for="QueryName1">Enter query name</label>
- <input type="text" class="form-control" id="QueryName1" rows="3" th:field="*{name}"/>
+ <label for="InstallQueryName1">Enter query name</label>
+ <input type="text" class="form-control" id="InstallQueryName1" rows="3" th:field="*{name}"/>
</div>
<div class="form-group">
- <label for="Textarea1">Enter query</label>
- <textarea class="form-control" id="Textarea1" rows="3" th:field="*{value}"></textarea>
+ <label for="InstallTextarea1">Enter query</label>
+ <textarea class="form-control" id="InstallTextarea1" rows="3" th:field="*{value}"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
+</div>
- <div id="response"><p th:text="${responseText}"/></div>
+<div id="uninstallQueryForm">
+ <h2 class="display-7">Uninstall query</h2>
+ <form action="#" th:action="@{/query}" th:object="${queryObject}" method="post">
+ <div class="form-group">
+ <label for="UninstallQueryName1">Enter query name</label>
+ <input type="text" class="form-control" id="UninstallQueryName1" rows="3" th:field="*{name}"/>
+ </div>
+ <button type="submit" class="btn btn-primary">Submit</button>
+ </form>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>