Added HistoryTab

This commit is contained in:
Rohit Awate 2018-02-18 22:58:21 +05:30
parent 921654200d
commit 83f557dd38
16 changed files with 542 additions and 154 deletions

View file

@ -79,6 +79,8 @@ public class BodyTabController implements Initializable {
public DataDispatchRequest getBasicRequest(String requestType) {
DataDispatchRequest request = new DataDispatchRequest(requestType);
// Raw and binary types get saved in Body.
// Form and URL encoded types use tuple objects
if (rawTab.isSelected()) {
String contentType;
switch (rawInputTypeBox.getValue()) {

View file

@ -27,6 +27,7 @@ import com.rohitawate.restaurant.requestsmanager.DELETERequestManager;
import com.rohitawate.restaurant.requestsmanager.DataDispatchRequestManager;
import com.rohitawate.restaurant.requestsmanager.GETRequestManager;
import com.rohitawate.restaurant.requestsmanager.RequestManager;
import com.rohitawate.restaurant.util.Services;
import com.rohitawate.restaurant.util.settings.Settings;
import com.rohitawate.restaurant.util.themes.ThemeManager;
import javafx.beans.binding.Bindings;
@ -64,7 +65,7 @@ public class DashboardController implements Initializable {
@FXML
private Label statusCode, statusCodeDescription, responseTime, responseSize, errorTitle, errorDetails;
@FXML
private JFXButton cancelButton;
private JFXButton sendButton, cancelButton;
@FXML
private TabPane requestOptionsTab;
@FXML
@ -291,6 +292,7 @@ public class DashboardController implements Initializable {
default:
loadingLayer.setVisible(false);
}
Services.historyManager.saveHistory(getState());
} catch (MalformedURLException MURLE) {
promptLayer.setVisible(true);
snackBar.show("Invalid address. Please verify and try again.", 3000);
@ -394,7 +396,7 @@ public class DashboardController implements Initializable {
* @return DashboardState - Current state of the Dashboard
*/
public DashboardState getState() {
DashboardState dashboardState = null;
DashboardState dashboardState;
switch (httpMethodBox.getValue()) {
case "POST":
case "PUT":

View file

@ -0,0 +1,30 @@
package com.rohitawate.restaurant.homewindow;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import java.net.URL;
import java.util.ResourceBundle;
public class HistoryItemController {
@FXML
private Label requestType, address;
public void setRequestType(String requestType) {
this.requestType.setText(requestType);
}
public void setAddress(String address) {
this.address.setText(address);
}
public String getRequestType() {
return requestType.getText();
}
public String getAddress() {
return address.getText();
}
}

View file

@ -17,45 +17,91 @@
package com.rohitawate.restaurant.homewindow;
import com.rohitawate.restaurant.models.DashboardState;
import com.rohitawate.restaurant.models.requests.DataDispatchRequest;
import com.rohitawate.restaurant.models.requests.GETRequest;
import com.rohitawate.restaurant.models.requests.RestaurantRequest;
import com.rohitawate.restaurant.util.Services;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.ExecutionException;
public class HomeWindowController implements Initializable {
@FXML
private TabPane homeWindowTabPane;
@FXML
private VBox historyTab;
@FXML
private StackPane historyPromptLayer;
private KeyCombination newTab = new KeyCodeCombination(KeyCode.T, KeyCombination.CONTROL_DOWN);
private List<DashboardController> controllers;
private List<DashboardController> dashboardControllers;
private List<HistoryItemController> historyItemControllers;
@Override
public void initialize(URL location, ResourceBundle resources) {
controllers = new ArrayList<>();
dashboardControllers = new ArrayList<>();
historyItemControllers = new ArrayList<>();
recoverState();
Platform.runLater(() -> {
// Adds a new tab if the last tab is closed
Scene thisScene = homeWindowTabPane.getScene();
thisScene.setOnKeyPressed(e -> {
if (newTab.match(e))
addTab();
});
// Saves the state of the application before closing
Stage thisStage = (Stage) thisScene.getWindow();
thisStage.setOnCloseRequest(e -> saveState());
// Loads the history
Task<List<DashboardState>> historyLoader = new Task<List<DashboardState>>() {
@Override
protected List<DashboardState> call() throws Exception {
return Services.historyManager.getHistory();
}
};
// Appends the history items to the HistoryTab
historyLoader.setOnSucceeded(e -> {
try {
List<DashboardState> history = historyLoader.get();
if (history.size() == 0) {
historyPromptLayer.setVisible(true);
return;
}
for (DashboardState state : history)
addHistoryItem(state);
} catch (InterruptedException | ExecutionException E) {
E.printStackTrace();
}
});
historyLoader.setOnFailed(e -> historyLoader.getException().printStackTrace());
new Thread(historyLoader).start();
});
}
@ -79,10 +125,11 @@ public class HomeWindowController implements Initializable {
newTab.setOnCloseRequest(e -> {
if (homeWindowTabPane.getTabs().size() == 1)
addTab();
controllers.remove(controller);
dashboardControllers.remove(controller);
});
homeWindowTabPane.getTabs().add(newTab);
controllers.add(controller);
homeWindowTabPane.getSelectionModel().select(newTab);
dashboardControllers.add(controller);
} catch (IOException e) {
e.printStackTrace();
}
@ -92,7 +139,7 @@ public class HomeWindowController implements Initializable {
List<DashboardState> dashboardStates = new ArrayList<>();
// Get the states of all the tabs
for (DashboardController controller : controllers)
for (DashboardController controller : dashboardControllers)
dashboardStates.add(controller.getState());
try {
@ -139,4 +186,27 @@ public class HomeWindowController implements Initializable {
System.out.println("Application loaded.");
}
}
public void addHistoryItem(DashboardState state) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/homewindow/HistoryItem.fxml"));
Parent historyItem = loader.load();
HistoryItemController controller = loader.getController();
controller.setRequestType(state.getHttpMethod());
controller.setAddress(state.getTarget().toString());
historyTab.getChildren().add(0, historyItem);
historyItemControllers.add(controller);
// Clicking on HistoryItem opens it up in a new tab
historyItem.setOnMouseClicked(mouseEvent -> {
if (mouseEvent.getButton() == MouseButton.PRIMARY)
addTab(state);
});
} catch (IOException IOE) {
IOE.printStackTrace();
}
}
}

View file

@ -33,7 +33,9 @@ public class Main extends Application {
new Services();
Parent dashboard = FXMLLoader.load(getClass().getResource("/fxml/homewindow/HomeWindow.fxml"));
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/homewindow/HomeWindow.fxml"));
Parent dashboard = loader.load();
Services.homeWindowController = loader.getController();
Stage dashboardStage = new Stage();
ThemeManager.setTheme(dashboard);

View file

@ -39,8 +39,6 @@ public class DELETERequestManager extends RequestManager {
protected RestaurantResponse call() throws Exception {
DELETERequest deleteRequest = (DELETERequest) request;
Services.historyManager.saveHistory(deleteRequest);
RestaurantResponse response = new RestaurantResponse();
WebTarget target = client.target(deleteRequest.getTarget().toString());
Map.Entry<String, String> mapEntry;

View file

@ -54,8 +54,6 @@ public class DataDispatchRequestManager extends RequestManager {
DataDispatchRequest dataDispatchRequest = (DataDispatchRequest) request;
String requestType = dataDispatchRequest.getRequestType();
Services.historyManager.saveHistory(dataDispatchRequest);
RestaurantResponse response = new RestaurantResponse();
WebTarget target = client.target(dataDispatchRequest.getTarget().toString());
Map.Entry<String, String> mapEntry;

View file

@ -39,8 +39,6 @@ public class GETRequestManager extends RequestManager {
RestaurantResponse response = new RestaurantResponse();
WebTarget target = client.target(request.getTarget().toString());
Services.historyManager.saveHistory(request);
Builder requestBuilder = target.request();
HashMap<String, String> headers = request.getHeaders();

View file

@ -16,10 +16,12 @@
package com.rohitawate.restaurant.util;
import com.rohitawate.restaurant.homewindow.HomeWindowController;
import com.rohitawate.restaurant.util.history.HistoryManager;
public class Services {
public static HistoryManager historyManager;
public static HomeWindowController homeWindowController;
static {
historyManager = new HistoryManager();

View file

@ -18,16 +18,25 @@ package com.rohitawate.restaurant.util.history;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rohitawate.restaurant.models.DashboardState;
import com.rohitawate.restaurant.models.requests.DELETERequest;
import com.rohitawate.restaurant.models.requests.DataDispatchRequest;
import com.rohitawate.restaurant.models.requests.GETRequest;
import com.rohitawate.restaurant.models.requests.RestaurantRequest;
import com.rohitawate.restaurant.util.Services;
import com.rohitawate.restaurant.util.json.JSONUtils;
import com.rohitawate.restaurant.util.settings.Settings;
import javafx.util.Pair;
import javax.ws.rs.core.MediaType;
import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.sql.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HistoryManager {
@ -55,6 +64,18 @@ public class HistoryManager {
statement =
conn.prepareStatement(JSONUtils.trimString(queries.get("createHeadersTable").toString()));
statement.execute();
statement =
conn.prepareStatement(JSONUtils.trimString(queries.get("createRequestContentMapTable").toString()));
statement.execute();
statement =
conn.prepareStatement(JSONUtils.trimString(queries.get("createBodiesTable").toString()));
statement.execute();
statement =
conn.prepareStatement(JSONUtils.trimString(queries.get("createTuplesTable").toString()));
statement.execute();
} catch (Exception E) {
E.printStackTrace();
} finally {
@ -63,47 +84,225 @@ public class HistoryManager {
}
// Method is made synchronized to allow only one database transaction at a time.
public synchronized void saveHistory(RestaurantRequest request) {
try {
statement =
conn.prepareStatement(JSONUtils.trimString(queries.get("saveRequest").toString()));
public synchronized void saveHistory(DashboardState state) {
new Thread(() -> {
try {
statement =
conn.prepareStatement(JSONUtils.trimString(queries.get("saveRequest").toString()));
// Determines the request type
if (request.getClass() == GETRequest.class)
statement.setString(1, "GET");
else if (request.getClass() == DataDispatchRequest.class) {
if (((DataDispatchRequest) request).getRequestType().equals("POST"))
statement.setString(1, "POST");
else
statement.setString(1, "PUT");
} else if (request.getClass() == DELETERequest.class)
statement.setString(1, "DELETE");
statement.setString(1, state.getHttpMethod());
statement.setString(2, String.valueOf(state.getTarget()));
statement.setString(3, LocalDate.now().toString());
statement.setString(2, String.valueOf(request.getTarget()));
statement.setString(3, LocalDate.now().toString());
statement.executeUpdate();
statement.executeUpdate();
if (state.getHeaders().size() > 0) {
// Get latest RequestID to insert into Headers table
statement = conn.prepareStatement("SELECT MAX(ID) AS MaxID FROM Requests");
if (request.getHeaders().size() > 0) {
// Get latest RequestID to insert into Headers table
statement = conn.prepareStatement("SELECT MAX(ID) AS MaxID FROM Requests");
ResultSet RS = statement.executeQuery();
int requestID = -1;
if (RS.next())
requestID = RS.getInt("MaxID");
ResultSet RS = statement.executeQuery();
int requestID = -1;
if (RS.next())
requestID = RS.getInt("MaxID");
// Saves request headers
statement = conn.prepareStatement(JSONUtils.trimString(queries.get("saveHeader").toString()));
for (Map.Entry entry : state.getHeaders().entrySet()) {
statement.setInt(1, requestID);
statement.setString(2, entry.getKey().toString());
statement.setString(3, entry.getValue().toString());
statement = conn.prepareStatement(JSONUtils.trimString(queries.get("saveHeader").toString()));
for (Map.Entry entry : request.getHeaders().entrySet()) {
statement.setInt(1, requestID);
statement.setString(2, entry.getKey().toString());
statement.setString(3, entry.getValue().toString());
statement.executeUpdate();
}
statement.executeUpdate();
if (state.getHttpMethod().equals("POST") || state.getHttpMethod().equals("PUT")) {
// Maps the request to its ContentType for faster recovery
statement = conn.prepareStatement(JSONUtils.trimString(queries.get("saveRequestContentPair").toString()));
statement.setInt(1, requestID);
statement.setString(2, state.getContentType());
statement.executeUpdate();
// Determines where to fetch the body from, based on the ContentType
switch (state.getContentType()) {
case MediaType.TEXT_PLAIN:
case MediaType.APPLICATION_JSON:
case MediaType.APPLICATION_XML:
case MediaType.TEXT_HTML:
case MediaType.APPLICATION_OCTET_STREAM:
// Saves the body in case of raw content, or the file location in case of binary
statement = conn.prepareStatement(JSONUtils.trimString(queries.get("saveBody").toString()));
statement.setInt(1, requestID);
statement.setString(2, state.getBody());
statement.executeUpdate();
break;
case MediaType.APPLICATION_FORM_URLENCODED:
for (Map.Entry<String, String> entry : state.getStringTuples().entrySet()) {
// Saves the string tuples
statement = conn.prepareStatement(JSONUtils.trimString(queries.get("saveTuple").toString()));
statement.setInt(1, requestID);
statement.setString(2, "String");
statement.setString(3, entry.getKey());
statement.setString(4, entry.getValue());
statement.executeUpdate();
}
break;
case MediaType.MULTIPART_FORM_DATA:
for (Map.Entry<String, String> entry : state.getStringTuples().entrySet()) {
// Saves the string tuples
statement = conn.prepareStatement(JSONUtils.trimString(queries.get("saveTuple").toString()));
statement.setInt(1, requestID);
statement.setString(2, "String");
statement.setString(3, entry.getKey());
statement.setString(4, entry.getValue());
statement.executeUpdate();
}
for (Map.Entry<String, String> entry : state.getFileTuples().entrySet()) {
// Saves the file tuples
statement = conn.prepareStatement(JSONUtils.trimString(queries.get("saveTuple").toString()));
statement.setInt(1, requestID);
statement.setString(2, "File");
statement.setString(3, entry.getKey());
statement.setString(4, entry.getValue());
statement.executeUpdate();
}
break;
}
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}).start();
// Appends this history item to the HistoryTab
Services.homeWindowController.addHistoryItem(state);
}
public synchronized List<DashboardState> getHistory() {
List<DashboardState> history = new ArrayList<>();
try {
// Loads the requests from the last x number of days, x being stored in Settings.showHistoryRange
statement = conn.prepareStatement(JSONUtils.trimString(queries.get("selectRecentRequests").toString()));
String historyStartDate = LocalDate.now().minusDays(Settings.showHistoryRange).toString();
statement.setString(1, historyStartDate);
ResultSet resultSet = statement.executeQuery();
DashboardState state;
while (resultSet.next()) {
state = new DashboardState();
try {
state.setTarget(resultSet.getString("Target"));
} catch (MalformedURLException e) {
e.printStackTrace();
}
int requestID = resultSet.getInt("ID");
state.setHeaders(getRequestHeaders(requestID));
state.setHttpMethod(resultSet.getString("Type"));
if (state.getHttpMethod().equals("POST") || state.getHttpMethod().equals("PUT")) {
// Retrieves request body ContentType for querying corresponding table
statement = conn.prepareStatement(JSONUtils.trimString(queries.get("selectRequestContentType").toString()));
statement.setInt(1, requestID);
ResultSet RS = statement.executeQuery();
String contentType = "";
if (RS.next())
contentType = RS.getString("ContentType");
state.setContentType(contentType);
// Retrieves body from corresponding table
switch (contentType) {
case MediaType.TEXT_PLAIN:
case MediaType.APPLICATION_JSON:
case MediaType.APPLICATION_XML:
case MediaType.TEXT_HTML:
case MediaType.APPLICATION_OCTET_STREAM:
statement = conn.prepareStatement(JSONUtils.trimString(queries.get("selectRequestBody").toString()));
statement.setInt(1, requestID);
RS = statement.executeQuery();
if (RS.next())
state.setBody(resultSet.getString("Body"));
break;
case MediaType.APPLICATION_FORM_URLENCODED:
state.setStringTuples(getTuples(requestID, "String"));
break;
case MediaType.MULTIPART_FORM_DATA:
state.setStringTuples(getTuples(requestID, "String"));
state.setFileTuples(getTuples(requestID, "Files"));
break;
}
}
history.add(state);
}
} catch (SQLException e) {
e.printStackTrace();
}
return history;
}
private HashMap<String, String> getRequestHeaders(int requestID) {
HashMap<String, String> headers = new HashMap<>();
try {
PreparedStatement statement =
conn.prepareStatement(JSONUtils.trimString(queries.get("selectRequestHeaders").toString()));
statement.setInt(1, requestID);
ResultSet RS = statement.executeQuery();
String key, value;
while (RS.next()) {
key = RS.getString("Key");
value = RS.getString("Value");
headers.put(key, value);
}
} catch (SQLException e) {
e.printStackTrace();
}
return headers;
}
/**
*
* @param requestID Database ID of the request whose tuples are needed.
* @param type Type of tuples needed ('String' or 'File')
* @return tuples - Map of tuples of corresponding type
*/
private HashMap<String, String> getTuples(int requestID, String type) {
if (!type.equals("String") || !type.equals("File"))
return null;
HashMap<String, String> tuples = new HashMap<>();
try {
PreparedStatement statement =
conn.prepareStatement(JSONUtils.trimString(queries.get("selectTuples").toString()));
statement.setInt(1, requestID);
statement.setString(2, type);
ResultSet RS = statement.executeQuery();
String key, value;
while (RS.next()) {
key = RS.getString("Key");
value = RS.getString("Value");
tuples.put(key, value);
}
} catch (SQLException e) {
e.printStackTrace();
}
return tuples;
}
}

View file

@ -31,4 +31,5 @@ public class Settings {
public static int connectionReadTimeOut = 30000;
public static String theme = "Adreana";
public static long showHistoryRange = 7;
}

View file

@ -98,6 +98,7 @@
.scroll-pane .viewport,
.scroll-pane .scroll-bar:vertical {
-fx-background-color: #3d3d3d;
-fx-background-insets: 0px;
}
/* Tab attributes */
@ -141,11 +142,19 @@
-fx-background-color: #808080;
}
.split-pane,
.split-pane {
-fx-background-color: #505050;
-fx-padding: 0px;
}
.split-pane .split-pane-divider {
-fx-background-color: #505050;
}
.split-pane:horizontal .split-pane-divider {
-fx-padding: 0px;
}
#keyField, #valueField, #filePathField {
-fx-prompt-text-fill: #919191;
-fx-background-color: #303030;
@ -170,6 +179,22 @@
-fx-background-color: #a2a2a2;
}
/* History tab */
#historyPane, #historyTab {
-fx-background-color: #404040;
}
#historySearchField {
-fx-background-color: #505050;
-fx-text-fill: white;
}
/* History item */
#historyItemBox {
-fx-background-color: #353535;
}
/* SnackBar */
.jfx-snackbar-content {
-fx-background-color: black;
}

View file

@ -16,26 +16,37 @@
~ limitations under the License.
-->
<?import com.jfoenix.controls.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<StackPane fx:id="dashboard" stylesheets="@../../css/Adreana.css" xmlns="http://javafx.com/javafx/8.0.111"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.rohitawate.restaurant.homewindow.DashboardController">
<?import com.jfoenix.controls.JFXButton?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<StackPane fx:id="dashboard" stylesheets="@../../css/Adreana.css" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.rohitawate.restaurant.homewindow.DashboardController">
<children>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<HBox alignment="CENTER" maxHeight="100.0" VBox.vgrow="ALWAYS">
<children>
<ImageView fitHeight="80.0" fitWidth="80.0" pickOnBounds="true" preserveRatio="true"
HBox.hgrow="ALWAYS">
<ImageView fitHeight="80.0" fitWidth="80.0" pickOnBounds="true" preserveRatio="true" HBox.hgrow="ALWAYS">
<image>
<Image url="@../../assets/LogoWithoutText.png"/>
<Image url="@../../assets/LogoWithoutText.png" />
</image>
<HBox.margin>
<Insets right="20.0"/>
<Insets right="20.0" />
</HBox.margin>
</ImageView>
<TextField fx:id="addressField" maxWidth="800.0" promptText="URL" HBox.hgrow="ALWAYS">
@ -46,13 +57,12 @@
<Font size="18.0" />
</font>
</TextField>
<ComboBox fx:id="httpMethodBox" prefHeight="39.0" prefWidth="150.0" HBox.hgrow="ALWAYS">
<ComboBox fx:id="httpMethodBox" prefHeight="33.0" prefWidth="150.0" HBox.hgrow="ALWAYS">
<HBox.margin>
<Insets right="20.0" />
</HBox.margin>
</ComboBox>
<JFXButton fx:id="sendButton" buttonType="RAISED" defaultButton="true" onAction="#sendRequest"
prefHeight="39.0" prefWidth="100.0" text=" SEND" textFill="WHITE" HBox.hgrow="ALWAYS">
<JFXButton fx:id="sendButton" buttonType="RAISED" defaultButton="true" minWidth="110.0" onAction="#sendRequest" prefHeight="39.0" ripplerFill="WHITE" text=" SEND" textAlignment="CENTER" textFill="WHITE" HBox.hgrow="ALWAYS">
<padding>
<Insets bottom="5.0" left="15.0" right="15.0" top="5.0" />
</padding>
@ -65,7 +75,7 @@
<graphic>
<ImageView fitHeight="15.0" fitWidth="15.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../assets/Send.png"/>
<Image url="@../../assets/Send.png" />
</image>
</ImageView>
</graphic>
@ -76,210 +86,177 @@
<items>
<AnchorPane maxHeight="250.0">
<children>
<TabPane fx:id="requestOptionsTab" maxHeight="200.0" minHeight="200.0"
tabClosingPolicy="UNAVAILABLE" tabMinWidth="150.0" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0">
<TabPane fx:id="requestOptionsTab" maxHeight="200.0" minHeight="200.0" tabClosingPolicy="UNAVAILABLE" tabMinWidth="150.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<tabs>
<Tab fx:id="paramsTab" text="PARAMS">
<content>
<VBox>
<children>
<HBox alignment="CENTER" maxHeight="0.0" spacing="20.0"
VBox.vgrow="ALWAYS">
<HBox alignment="CENTER" maxHeight="0.0" spacing="20.0" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets/>
<Insets />
</VBox.margin>
<children>
<JFXButton fx:id="newParamButton" onAction="#addParamField"
text=" NEW PARAM" textFill="WHITE"
HBox.hgrow="ALWAYS">
<JFXButton fx:id="newParamButton" onAction="#addParamField" text=" NEW PARAM" textFill="WHITE" HBox.hgrow="ALWAYS">
<graphic>
<ImageView fitHeight="15.0" fitWidth="15.0"
pickOnBounds="true"
preserveRatio="true">
<ImageView fitHeight="15.0" fitWidth="15.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../assets/Plus.png"/>
<Image url="@../../assets/Plus.png" />
</image>
</ImageView>
</graphic>
<HBox.margin>
<Insets/>
<Insets />
</HBox.margin>
</JFXButton>
<JFXButton fx:id="appendParamsButton"
onAction="#appendParams" ripplerFill="WHITE"
text=" APPEND PARAMS" textFill="WHITE"
HBox.hgrow="ALWAYS">
<JFXButton fx:id="appendParamsButton" onAction="#appendParams" ripplerFill="WHITE" text=" APPEND PARAMS" textFill="WHITE" HBox.hgrow="ALWAYS">
<graphic>
<ImageView fitHeight="15.0" fitWidth="15.0"
pickOnBounds="true"
preserveRatio="true">
<ImageView fitHeight="15.0" fitWidth="15.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../assets/CheckMark.png"/>
<Image url="@../../assets/CheckMark.png" />
</image>
</ImageView>
</graphic>
<HBox.margin>
<Insets/>
<Insets />
</HBox.margin>
</JFXButton>
</children>
<padding>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0"/>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
</padding>
</HBox>
<ScrollPane fitToHeight="true" fitToWidth="true" hbarPolicy="NEVER"
VBox.vgrow="ALWAYS">
<ScrollPane fitToHeight="true" fitToWidth="true" hbarPolicy="NEVER" VBox.vgrow="ALWAYS">
<content>
<VBox fx:id="paramsBox" alignment="TOP_CENTER"/>
<VBox fx:id="paramsBox" alignment="TOP_CENTER" />
</content>
</ScrollPane>
</children>
</VBox>
</content>
</Tab>
<Tab fx:id="authTab" text="AUTHORIZATION"/>
<Tab fx:id="headersTab" text="HEADERS"/>
<Tab fx:id="bodyTab" text="BODY"/>
<Tab fx:id="authTab" text="AUTHORIZATION" />
<Tab fx:id="headersTab" text="HEADERS" />
<Tab fx:id="bodyTab" text="BODY" />
</tabs>
</TabPane>
</children>
</AnchorPane>
<AnchorPane>
<children>
<VBox fx:id="responseBox" alignment="CENTER" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<VBox fx:id="responseBox" alignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<HBox fx:id="responseDetails" alignment="CENTER_RIGHT" maxHeight="50.0"
minHeight="50.0" VBox.vgrow="ALWAYS">
<HBox fx:id="responseDetails" alignment="CENTER_RIGHT" maxHeight="50.0" minHeight="50.0" VBox.vgrow="ALWAYS">
<children>
<HBox alignment="CENTER_LEFT" HBox.hgrow="ALWAYS">
<children>
<Label fx:id="statusCode" text="404" textFill="WHITE"
HBox.hgrow="ALWAYS">
<Label fx:id="statusCode" text="404" textFill="WHITE" HBox.hgrow="ALWAYS">
<font>
<Font name="System Bold" size="35.0"/>
<Font name="System Bold" size="35.0" />
</font>
<HBox.margin>
<Insets right="10.0"/>
<Insets right="10.0" />
</HBox.margin>
</Label>
<Label fx:id="statusCodeDescription" text="Not Found"
textFill="WHITE" HBox.hgrow="ALWAYS">
<Label fx:id="statusCodeDescription" text="Not Found" textFill="WHITE" HBox.hgrow="ALWAYS">
<font>
<Font size="30.0"/>
<Font size="30.0" />
</font>
</Label>
</children>
</HBox>
<Label fx:id="responseTime" text="151 ms" textFill="WHITE"
HBox.hgrow="ALWAYS">
<Label fx:id="responseTime" text="151 ms" textFill="WHITE" HBox.hgrow="ALWAYS">
<HBox.margin>
<Insets right="30.0"/>
<Insets right="30.0" />
</HBox.margin>
<font>
<Font name="Liberation Mono" size="20.0"/>
<Font name="Liberation Mono" size="20.0" />
</font>
</Label>
<Label fx:id="responseSize" layoutX="1187.0" layoutY="23.0" text="1998 B"
textFill="WHITE" HBox.hgrow="ALWAYS">
<Label fx:id="responseSize" layoutX="1187.0" layoutY="23.0" text="1998 B" textFill="WHITE" HBox.hgrow="ALWAYS">
<font>
<Font name="Liberation Mono" size="20.0"/>
<Font name="Liberation Mono" size="20.0" />
</font>
<HBox.margin>
<Insets right="30.0"/>
<Insets right="30.0" />
</HBox.margin>
</Label>
<JFXButton fx:id="clearResponseAreaButton" buttonType="RAISED"
onAction="#clearResponseArea" ripplerFill="WHITE" text=" CLEAR"
textFill="WHITE" HBox.hgrow="ALWAYS">
<JFXButton fx:id="clearResponseAreaButton" buttonType="RAISED" onAction="#clearResponseArea" ripplerFill="WHITE" text=" CLEAR" textFill="WHITE" HBox.hgrow="ALWAYS">
<graphic>
<ImageView fitHeight="15.0" fitWidth="15.0" pickOnBounds="true"
preserveRatio="true">
<ImageView fitHeight="15.0" fitWidth="15.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../assets/CrossMark.png"/>
<Image url="@../../assets/CrossMark.png" />
</image>
</ImageView>
</graphic>
<tooltip>
<Tooltip autoHide="true"
text="Clears this bar and the response body below."/>
<Tooltip autoHide="true" text="Clears this bar and the response body below." />
</tooltip>
</JFXButton>
</children>
<padding>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0"/>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
</padding>
</HBox>
<StackPane VBox.vgrow="ALWAYS">
<children>
<TextArea fx:id="responseArea" editable="false" minHeight="300.0"
wrapText="true"/>
<TextArea fx:id="responseArea" editable="false" minHeight="300.0" wrapText="true" />
<VBox fx:id="loadingLayer" alignment="CENTER" visible="false">
<children>
<HBox alignment="CENTER">
<children>
<ImageView fitHeight="150.0" fitWidth="100.0"
pickOnBounds="true" preserveRatio="true">
<ImageView fitHeight="150.0" fitWidth="100.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../assets/LoadingCircle_WhiteOnOrange.gif"/>
<Image url="@../../assets/LoadingCircle_WhiteOnOrange.gif" />
</image>
</ImageView>
<Label text="LOADING" textFill="WHITE">
<font>
<Font size="70.0"/>
<Font size="70.0" />
</font>
</Label>
</children>
</HBox>
<JFXButton fx:id="cancelButton" text=" CANCEL" textFill="WHITE"
VBox.vgrow="ALWAYS">
<JFXButton fx:id="cancelButton" text=" CANCEL" textFill="WHITE" VBox.vgrow="ALWAYS">
<graphic>
<ImageView fitHeight="15.0" fitWidth="15.0"
pickOnBounds="true" preserveRatio="true">
<ImageView fitHeight="15.0" fitWidth="15.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../assets/CrossMark.png"/>
<Image url="@../../assets/CrossMark.png" />
</image>
</ImageView>
</graphic>
</JFXButton>
</children>
</VBox>
<VBox fx:id="promptLayer" alignment="CENTER" prefHeight="200.0"
prefWidth="100.0" visible="false">
<VBox fx:id="promptLayer" alignment="CENTER" prefHeight="200.0" prefWidth="100.0" visible="false">
<children>
<Label text="Enter an address, select a method and hit send. 🚀"
textFill="WHITE">
<Label text="Enter an address, select a method and hit send. 🚀" textFill="WHITE">
<font>
<Font size="32.0"/>
<Font size="32.0" />
</font>
</Label>
<Label text="It's not rocket science." textFill="#9e9e9e">
<font>
<Font name="System Italic" size="27.0"/>
<Font name="System Italic" size="27.0" />
</font>
</Label>
</children>
</VBox>
<VBox fx:id="errorLayer" alignment="CENTER" layoutX="10.0" layoutY="10.0"
prefHeight="200.0" prefWidth="100.0" visible="false">
<VBox fx:id="errorLayer" alignment="CENTER" layoutX="10.0" layoutY="10.0" prefHeight="200.0" prefWidth="100.0" visible="false">
<children>
<ImageView fitHeight="100.0" fitWidth="100.0" opacity="0.75"
pickOnBounds="true" preserveRatio="true">
<ImageView fitHeight="100.0" fitWidth="100.0" opacity="0.75" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../assets/Explosion.png"/>
<Image url="@../../assets/Explosion.png" />
</image>
</ImageView>
<Label fx:id="errorTitle" text="Error title" textFill="WHITE">
<font>
<Font name="System Bold" size="32.0"/>
<Font name="System Bold" size="32.0" />
</font>
</Label>
<Label fx:id="errorDetails" text="Error details"
textAlignment="CENTER" textFill="#c3c3c3">
<Label fx:id="errorDetails" text="Error details" textAlignment="CENTER" textFill="#c3c3c3">
<font>
<Font size="22.0"/>
<Font size="22.0" />
</font>
</Label>
</children>

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.text.Font?>
<HBox fx:id="historyItemBox" alignment="CENTER_LEFT" maxHeight="40.0" minHeight="40.0" minWidth="300.0" spacing="20.0" stylesheets="@../../css/Adreana.css" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.rohitawate.restaurant.homewindow.HistoryItemController">
<children>
<StackPane maxWidth="80.0" minWidth="80.0" HBox.hgrow="ALWAYS">
<children>
<Label fx:id="requestType" textFill="ORANGERED" textOverrun="WORD_ELLIPSIS">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Label>
</children>
</StackPane>
<Label fx:id="address" textFill="WHITE" HBox.hgrow="ALWAYS">
<font>
<Font size="15.0" />
</font>
</Label>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</HBox>

View file

@ -16,9 +16,54 @@
~ limitations under the License.
-->
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TabPane?>
<TabPane fx:id="homeWindowTabPane" prefHeight="760.0" prefWidth="1280.0" stylesheets="@../../css/Adreana.css"
tabClosingPolicy="ALL_TABS" tabMaxHeight="35.0" tabMaxWidth="200.0" tabMinHeight="35.0" tabMinWidth="200.0"
xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.rohitawate.restaurant.homewindow.HomeWindowController"/>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<SplitPane dividerPositions="0.3" stylesheets="@../../css/Adreana.css" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.rohitawate.restaurant.homewindow.HomeWindowController">
<items>
<VBox fx:id="historyPane" alignment="TOP_CENTER" maxWidth="500.0" minWidth="500.0" spacing="10.0" SplitPane.resizableWithParent="false">
<children>
<TextField fx:id="historySearchField" promptText="SEARCH" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</VBox.margin>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding></TextField>
<ScrollPane fitToHeight="true" fitToWidth="true" VBox.vgrow="ALWAYS">
<content>
<StackPane>
<children>
<VBox fx:id="historyTab" alignment="TOP_CENTER" spacing="5.0">
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" />
</padding>
</VBox>
<StackPane fx:id="historyPromptLayer">
<children>
<Label text="YOUR REQUESTS HISTORY WILL APPEAR HERE" textAlignment="CENTER" textFill="#575757" wrapText="true">
<font>
<Font size="25.0" />
</font>
</Label>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</StackPane>
</children>
</StackPane>
</content>
</ScrollPane>
</children>
</VBox>
<TabPane fx:id="homeWindowTabPane" prefHeight="760.0" prefWidth="1280.0" tabClosingPolicy="ALL_TABS" tabMaxHeight="30.0" tabMaxWidth="200.0" tabMinHeight="30.0" tabMinWidth="200.0" SplitPane.resizableWithParent="false" />
</items>
</SplitPane>

View file

@ -1,7 +1,17 @@
{
"createRequestsTable": "CREATE TABLE IF NOT EXISTS Requests(ID INTEGER PRIMARY KEY, Type TEXT NOT NULL, Target TEXT NOT NULL, Date TEXT NOT NULL)",
"createHeadersTable": "CREATE TABLE IF NOT EXISTS Headers(ID INTEGER, Key TEXT NOT NULL, Value TEXT NOT NULL, FOREIGN KEY(ID) REFERENCES Requests(ID))",
"selectAllRequests": "SELECT * FROM Requests, Headers",
"createHeadersTable": "CREATE TABLE IF NOT EXISTS Headers(RequestID INTEGER, Key TEXT NOT NULL, Value TEXT NOT NULL, FOREIGN KEY(RequestID) REFERENCES Requests(ID))",
"createRequestContentMapTable": "CREATE TABLE IF NOT EXISTS RequestContentMap(RequestID INTEGER, ContentType TEXT NOT NULL, FOREIGN KEY(RequestID) REFERENCES Requests(ID))",
"createBodiesTable": "CREATE TABLE IF NOT EXISTS Bodies(RequestID INTEGER, Body TEXT NOT NULL, FOREIGN KEY(RequestID) REFERENCES Requests(ID))",
"createTuplesTable": "CREATE TABLE IF NOT EXISTS Tuples(RequestID INTEGER, TupleType TEXT NOT NULL, Key TEXT NOT NULL, Value TEXT NOT NULL, FOREIGN KEY(RequestID) REFERENCES Requests(ID))",
"saveRequest": "INSERT INTO Requests(Type, Target, Date) VALUES(?, ?, ?)",
"saveHeader": "INSERT INTO Headers(ID, Key, Value) VALUES(?, ?, ?)"
"saveHeader": "INSERT INTO Headers(RequestID, Key, Value) VALUES(?, ?, ?)",
"saveRequestContentPair": "INSERT INTO RequestContentMap(ID, ContentType) VALUES(?, ?)",
"saveBody": "INSERT INTO Bodies(RequestID, Body) VALUES(?, ?)",
"saveTuple": "INSERT INTO Tuples(RequestID, TupleType, Key, Value) VALUES(?, ?, ?, ?)",
"selectRecentRequests": "SELECT * FROM Requests WHERE Requests.Date > ?",
"selectRequestHeaders": "SELECT * FROM Headers WHERE RequestID == ?",
"selectRequestContentType": "SELECT ContentType FROM RequestContentMap WHERE RequestID == ?",
"selectRequestBody": "SELECT Body FROM Bodies WHERE RequestID == ?",
"selectTuples": "SELECT * FROM Tuples WHERE RequestID == ? AND TupleType == ?"
}