From 5f85f836964288d4195bd9e35f5c8dd14b61d9b2 Mon Sep 17 00:00:00 2001 From: Rohit Awate Date: Mon, 16 Jul 2018 22:04:38 +0530 Subject: [PATCH 01/45] Add foundation for single-Dashboard design --- .../controllers/BodyTabController.java | 10 ++-- .../controllers/DashboardController.java | 22 ++++----- .../controllers/HistoryItemController.java | 24 +++++----- .../controllers/HistoryPaneController.java | 16 +++---- .../controllers/HomeWindowController.java | 39 ++++++++++------ .../controllers/state/ComposerState.java | 46 +++++++++++++++++++ .../controllers/state/DashboardState.java | 33 ++++--------- .../everest/history/HistoryManager.java | 16 +++---- .../resources/fxml/homewindow/HomeWindow.fxml | 19 ++++---- 9 files changed, 132 insertions(+), 93 deletions(-) create mode 100644 src/main/java/com/rohitawate/everest/controllers/state/ComposerState.java diff --git a/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java b/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java index 4b86d25..27d2587 100644 --- a/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java +++ b/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java @@ -18,7 +18,7 @@ package com.rohitawate.everest.controllers; import com.rohitawate.everest.controllers.codearea.EverestCodeArea; import com.rohitawate.everest.controllers.codearea.EverestCodeArea.HighlightMode; -import com.rohitawate.everest.controllers.state.DashboardState; +import com.rohitawate.everest.controllers.state.ComposerState; import com.rohitawate.everest.controllers.state.FieldState; import com.rohitawate.everest.misc.Services; import com.rohitawate.everest.misc.ThemeManager; @@ -119,8 +119,8 @@ public class BodyTabController implements Initializable { filePathField.setText(filePath); } - public DashboardState getState() { - DashboardState state = new DashboardState(); + public ComposerState getState() { + ComposerState state = new ComposerState(); state.rawBodyType = rawInputTypeBox.getValue(); state.rawBody = rawInputArea.getText(); @@ -154,7 +154,7 @@ public class BodyTabController implements Initializable { return state; } - public void setState(DashboardState state) { + public void setState(ComposerState state) { // Adding URL tab's tuples if (state.urlStringTuples != null) for (FieldState fieldState : state.urlStringTuples) @@ -175,7 +175,7 @@ public class BodyTabController implements Initializable { filePathField.setText(state.binaryFilePath); } - private void setRawTab(DashboardState state) { + private void setRawTab(ComposerState state) { HighlightMode mode; if (state.rawBodyType != null && state.rawBody != null) { diff --git a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java index 616786c..789399e 100644 --- a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java +++ b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java @@ -21,7 +21,7 @@ import com.jfoenix.controls.JFXProgressBar; import com.jfoenix.controls.JFXSnackbar; import com.rohitawate.everest.controllers.codearea.EverestCodeArea; import com.rohitawate.everest.controllers.codearea.EverestCodeArea.HighlightMode; -import com.rohitawate.everest.controllers.state.DashboardState; +import com.rohitawate.everest.controllers.state.ComposerState; import com.rohitawate.everest.controllers.state.FieldState; import com.rohitawate.everest.exceptions.RedirectException; import com.rohitawate.everest.exceptions.UnreliableResponseException; @@ -557,25 +557,25 @@ public class DashboardController implements Initializable { /** * @return Current state of the Dashboard. */ - public DashboardState getState() { - DashboardState dashboardState; + public ComposerState getState() { + ComposerState composerState; switch (httpMethodBox.getValue()) { case "POST": case "PUT": case "PATCH": - dashboardState = bodyTabController.getState(); + composerState = bodyTabController.getState(); break; default: // For GET, DELETE requests - dashboardState = new DashboardState(); + composerState = new ComposerState(); } - dashboardState.target = addressField.getText(); - dashboardState.httpMethod = httpMethodBox.getValue(); - dashboardState.headers = headerTabController.getFieldStates(); - dashboardState.params = getParamFieldStates(); + composerState.target = addressField.getText(); + composerState.httpMethod = httpMethodBox.getValue(); + composerState.headers = headerTabController.getFieldStates(); + composerState.params = getParamFieldStates(); - return dashboardState; + return composerState; } /** @@ -583,7 +583,7 @@ public class DashboardController implements Initializable { * * @param state - State of the dashboard */ - public void setState(DashboardState state) { + public void setState(ComposerState state) { /* The only value from a set of constants in the state.json file is the httpMethod which, if manipulated to a non-standard value by the user, would still diff --git a/src/main/java/com/rohitawate/everest/controllers/HistoryItemController.java b/src/main/java/com/rohitawate/everest/controllers/HistoryItemController.java index 9c993cd..219ac53 100644 --- a/src/main/java/com/rohitawate/everest/controllers/HistoryItemController.java +++ b/src/main/java/com/rohitawate/everest/controllers/HistoryItemController.java @@ -16,41 +16,39 @@ package com.rohitawate.everest.controllers; -import java.net.MalformedURLException; -import java.net.URL; -import java.time.LocalDateTime; -import java.util.ResourceBundle; - -import javax.ws.rs.core.MediaType; - import com.rohitawate.everest.controllers.search.Searchable; -import com.rohitawate.everest.controllers.state.DashboardState; +import com.rohitawate.everest.controllers.state.ComposerState; import com.rohitawate.everest.controllers.state.FieldState; import com.rohitawate.everest.misc.Services; - import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Label; import javafx.scene.control.Tooltip; -public class HistoryItemController implements Initializable, Searchable { +import javax.ws.rs.core.MediaType; +import java.net.MalformedURLException; +import java.net.URL; +import java.time.LocalDateTime; +import java.util.ResourceBundle; + +public class HistoryItemController implements Initializable, Searchable { @FXML private Label requestType, address; @FXML private Tooltip tooltip; - private DashboardState state; + private ComposerState state; @Override public void initialize(URL location, ResourceBundle resources) { tooltip.textProperty().bind(address.textProperty()); } - public DashboardState getState() { + public ComposerState getState() { return state; } - public void setState(DashboardState state) { + public void setState(ComposerState state) { this.state = state; this.requestType.setText(state.httpMethod); this.address.setText(state.target); diff --git a/src/main/java/com/rohitawate/everest/controllers/HistoryPaneController.java b/src/main/java/com/rohitawate/everest/controllers/HistoryPaneController.java index eb29470..108f93b 100644 --- a/src/main/java/com/rohitawate/everest/controllers/HistoryPaneController.java +++ b/src/main/java/com/rohitawate/everest/controllers/HistoryPaneController.java @@ -17,7 +17,7 @@ package com.rohitawate.everest.controllers; import com.rohitawate.everest.controllers.search.SearchablePaneController; -import com.rohitawate.everest.controllers.state.DashboardState; +import com.rohitawate.everest.controllers.state.ComposerState; import com.rohitawate.everest.misc.Services; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; @@ -28,16 +28,16 @@ import java.util.LinkedList; import java.util.List; import java.util.function.Consumer; -public class HistoryPaneController extends SearchablePaneController { +public class HistoryPaneController extends SearchablePaneController { - private List> stateClickHandler = new LinkedList<>(); + private List> stateClickHandler = new LinkedList<>(); @Override - protected List loadInitialEntries() { + protected List loadInitialEntries() { return Services.historyManager.getHistory(); } - protected SearchEntry createEntryFromState(DashboardState state) throws IOException { + protected SearchEntry createEntryFromState(ComposerState state) throws IOException { FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/homewindow/HistoryItem.fxml")); Parent historyItem = loader.load(); @@ -53,13 +53,13 @@ public class HistoryPaneController extends SearchablePaneController(historyItem, controller); } - private void handleClick(DashboardState state) { - for (Consumer consumer : stateClickHandler) { + private void handleClick(ComposerState state) { + for (Consumer consumer : stateClickHandler) { consumer.accept(state); } } - public void addItemClickHandler(Consumer handler) { + public void addItemClickHandler(Consumer handler) { stateClickHandler.add(handler); } } diff --git a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java index ba51ed1..cb5d72e 100644 --- a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java +++ b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java @@ -17,7 +17,7 @@ package com.rohitawate.everest.controllers; import com.fasterxml.jackson.core.type.TypeReference; -import com.rohitawate.everest.controllers.state.DashboardState; +import com.rohitawate.everest.controllers.state.ComposerState; import com.rohitawate.everest.misc.EverestUtilities; import com.rohitawate.everest.misc.KeyMap; import com.rohitawate.everest.misc.Services; @@ -34,6 +34,7 @@ import javafx.scene.control.SplitPane; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; import javafx.stage.Stage; import java.io.File; @@ -54,11 +55,23 @@ public class HomeWindowController implements Initializable { private TabPane homeWindowTabPane; @FXML private HistoryPaneController historyPaneController; + @FXML + private VBox tabDashboardBox; private HashMap tabControllerMap; + private DashboardController dashboard; @Override public void initialize(URL location, ResourceBundle resources) { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/homewindow/Dashboard.fxml")); + try { + Parent dashboardFXML = loader.load(); + dashboard = loader.getController(); + tabDashboardBox.getChildren().add(dashboardFXML); + } catch (IOException e) { + e.printStackTrace(); + } + // Using LinkedHashMap because they retain order tabControllerMap = new LinkedHashMap<>(); recoverState(); @@ -138,15 +151,15 @@ public class HomeWindowController implements Initializable { addTab(null); } - private void addTab(DashboardState dashboardState) { + private void addTab(ComposerState composerState) { try { Tab newTab = new Tab(); FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/homewindow/Dashboard.fxml")); Parent dashboard = loader.load(); DashboardController controller = loader.getController(); - if (dashboardState != null) - controller.setState(dashboardState); + if (composerState != null) + controller.setState(composerState); newTab.setContent(dashboard); @@ -173,15 +186,15 @@ public class HomeWindowController implements Initializable { } private void saveState() { - ArrayList dashboardStates = new ArrayList<>(); + ArrayList composerStates = new ArrayList<>(); // Get the states of all the tabs for (DashboardController controller : tabControllerMap.values()) - dashboardStates.add(controller.getState()); + composerStates.add(controller.getState()); try { File stateFile = new File("Everest/config/state.json"); - EverestUtilities.jsonMapper.writeValue(stateFile, dashboardStates); + EverestUtilities.jsonMapper.writeValue(stateFile, composerStates); Services.loggingService.logInfo("Application state saved.", LocalDateTime.now()); } catch (IOException e) { Services.loggingService.logSevere("Failed to save application state.", e, LocalDateTime.now()); @@ -198,15 +211,15 @@ public class HomeWindowController implements Initializable { return; } - ArrayList dashboardStates = EverestUtilities.jsonMapper + ArrayList composerStates = EverestUtilities.jsonMapper .reader() - .forType(new TypeReference>() { + .forType(new TypeReference>() { }) .readValue(stateFile); - if (dashboardStates.size() > 0) { - for (DashboardState dashboardState : dashboardStates) - addTab(dashboardState); + if (composerStates.size() > 0) { + for (ComposerState composerState : composerStates) + addTab(composerState); } else { addTab(); } @@ -217,7 +230,7 @@ public class HomeWindowController implements Initializable { } } - public void addHistoryItem(DashboardState state) { + public void addHistoryItem(ComposerState state) { historyPaneController.addHistoryItem(state); } } diff --git a/src/main/java/com/rohitawate/everest/controllers/state/ComposerState.java b/src/main/java/com/rohitawate/everest/controllers/state/ComposerState.java new file mode 100644 index 0000000..c898de9 --- /dev/null +++ b/src/main/java/com/rohitawate/everest/controllers/state/ComposerState.java @@ -0,0 +1,46 @@ +/* + * Copyright 2018 Rohit Awate. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.rohitawate.everest.controllers.state; + +import java.util.ArrayList; + +/** + * Convenience class to abstract the state of the application. + */ +public class ComposerState { + public String target; + public String httpMethod; + public ArrayList params; + public ArrayList headers; + + // Determined from the active tab within the Body tab + public String contentType; + + // Body and content-type of requests with raw bodies + public String rawBody; + public String rawBodyType; + + // Tuples of URL-encoded requests + public ArrayList urlStringTuples; + + // String and file tuples of multipart-form requests + public ArrayList formStringTuples; + public ArrayList formFileTuples; + + // File path of application/octet-stream requests + public String binaryFilePath; +} diff --git a/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java b/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java index 0a1b65d..7b73033 100644 --- a/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java +++ b/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java @@ -16,31 +16,14 @@ package com.rohitawate.everest.controllers.state; -import java.util.ArrayList; +import java.util.HashMap; -/** - * Convenience class to abstract the state of the application. - */ public class DashboardState { - public String target; - public String httpMethod; - public ArrayList params; - public ArrayList headers; - - // Determined from the active tab within the Body tab - public String contentType; - - // Body and content-type of requests with raw bodies - public String rawBody; - public String rawBodyType; - - // Tuples of URL-encoded requests - public ArrayList urlStringTuples; - - // String and file tuples of multipart-form requests - public ArrayList formStringTuples; - public ArrayList formFileTuples; - - // File path of application/octet-stream requests - public String binaryFilePath; + public ComposerState composer; + public boolean showResponse; + public int statusCode; + public String responseType; + public int responseTime; + public int responseSize; + public HashMap responseHeaders; } diff --git a/src/main/java/com/rohitawate/everest/history/HistoryManager.java b/src/main/java/com/rohitawate/everest/history/HistoryManager.java index 3025d7b..d056b38 100644 --- a/src/main/java/com/rohitawate/everest/history/HistoryManager.java +++ b/src/main/java/com/rohitawate/everest/history/HistoryManager.java @@ -18,7 +18,7 @@ package com.rohitawate.everest.history; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.rohitawate.everest.controllers.state.DashboardState; +import com.rohitawate.everest.controllers.state.ComposerState; import com.rohitawate.everest.controllers.state.FieldState; import com.rohitawate.everest.misc.EverestUtilities; import com.rohitawate.everest.misc.Services; @@ -96,7 +96,7 @@ public class HistoryManager { * * @param state - The state of the Dashboard while making the request. */ - public synchronized void saveHistory(DashboardState state) { + public synchronized void saveHistory(ComposerState state) { if (isDuplicate(state)) return; @@ -110,8 +110,8 @@ public class HistoryManager { /** * Returns a list of all the recent requests. */ - public synchronized List getHistory() { - List history = new ArrayList<>(); + public synchronized List getHistory() { + List history = new ArrayList<>(); try { // Loads the requests from the last x number of days, x being Settings.showHistoryRange statement = conn.prepareStatement(EverestUtilities.trimString(queries.get("selectRecentRequests").toString())); @@ -120,9 +120,9 @@ public class HistoryManager { ResultSet resultSet = statement.executeQuery(); - DashboardState state; + ComposerState state; while (resultSet.next()) { - state = new DashboardState(); + state = new ComposerState(); state.target = resultSet.getString("Target"); @@ -241,7 +241,7 @@ public class HistoryManager { * @param newState The new request. * @return true, if request is same as the last one in the database. false, otherwise. */ - private boolean isDuplicate(DashboardState newState) { + private boolean isDuplicate(ComposerState newState) { try { statement = conn.prepareStatement(EverestUtilities.trimString(queries.get("selectMostRecentRequest").toString())); ResultSet RS = statement.executeQuery(); @@ -346,7 +346,7 @@ public class HistoryManager { } private class HistorySaver implements Runnable { - private DashboardState state; + private ComposerState state; @Override public void run() { diff --git a/src/main/resources/fxml/homewindow/HomeWindow.fxml b/src/main/resources/fxml/homewindow/HomeWindow.fxml index 7e373b3..1d48715 100644 --- a/src/main/resources/fxml/homewindow/HomeWindow.fxml +++ b/src/main/resources/fxml/homewindow/HomeWindow.fxml @@ -19,20 +19,19 @@ - - + + - + + + + + From 8cea5f006aaec430808a2ab8b5b39db2d334c198 Mon Sep 17 00:00:00 2001 From: Rohit Awate Date: Tue, 17 Jul 2018 13:20:17 +0530 Subject: [PATCH 02/45] Add basic tab switching --- .../controllers/BodyTabController.java | 9 +- .../controllers/DashboardController.java | 123 +++++++++++++----- .../controllers/FormDataTabController.java | 18 +++ .../controllers/HeaderTabController.java | 10 ++ .../controllers/HomeWindowController.java | 88 +++++-------- .../controllers/ResponseHeadersViewer.java | 21 ++- .../everest/controllers/URLTabController.java | 10 ++ .../controllers/state/DashboardState.java | 1 + 8 files changed, 192 insertions(+), 88 deletions(-) diff --git a/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java b/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java index 27d2587..d5aef9c 100644 --- a/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java +++ b/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java @@ -156,14 +156,18 @@ public class BodyTabController implements Initializable { public void setState(ComposerState state) { // Adding URL tab's tuples - if (state.urlStringTuples != null) + if (state.urlStringTuples != null) { + urlTabController.clear(); for (FieldState fieldState : state.urlStringTuples) urlTabController.addField(fieldState); + } // Adding Form tab's string tuples - if (state.formStringTuples != null) + formDataTabController.clear(); + if (state.formStringTuples != null) { for (FieldState fieldState : state.formStringTuples) formDataTabController.addStringField(fieldState); + } // Adding Form tab's file tuples if (state.formFileTuples != null) @@ -171,7 +175,6 @@ public class BodyTabController implements Initializable { formDataTabController.addFileField(fieldState); setRawTab(state); - filePathField.setText(state.binaryFilePath); } diff --git a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java index 789399e..01992df 100644 --- a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java +++ b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java @@ -22,6 +22,7 @@ import com.jfoenix.controls.JFXSnackbar; import com.rohitawate.everest.controllers.codearea.EverestCodeArea; import com.rohitawate.everest.controllers.codearea.EverestCodeArea.HighlightMode; import com.rohitawate.everest.controllers.state.ComposerState; +import com.rohitawate.everest.controllers.state.DashboardState; import com.rohitawate.everest.controllers.state.FieldState; import com.rohitawate.everest.exceptions.RedirectException; import com.rohitawate.everest.exceptions.UnreliableResponseException; @@ -314,7 +315,7 @@ public class DashboardController implements Initializable { default: loadingLayer.setVisible(false); } - Services.historyManager.saveHistory(getState()); + Services.historyManager.saveHistory(getState().composer); } catch (MalformedURLException MURLE) { promptLayer.setVisible(true); snackbar.show("Invalid address. Please verify and try again.", 3000); @@ -401,38 +402,41 @@ public class DashboardController implements Initializable { responseHeadersViewer.populate(response); } - private void prettifyResponseBody(EverestResponse response) { - String type; - - if (response.getMediaType() != null) - type = response.getMediaType().toString(); - else - type = null; - - String responseBody = response.getBody(); + private void displayResponse(DashboardState state) { + prettifyResponseBody(state.responseBody, state.responseType); + responseBox.getChildren().remove(responseDetails); + responseBox.getChildren().add(0, responseDetails); + statusCode.setText(Integer.toString(state.statusCode)); + statusCodeDescription.setText(Response.Status.fromStatusCode(state.statusCode).getReasonPhrase()); + responseTime.setText(Long.toString(state.responseTime) + " ms"); + responseSize.setText(Integer.toString(state.responseSize) + " B"); + responseHeadersViewer.populate(state.responseHeaders); + } + private void prettifyResponseBody(String body, String contentType) { visualizerTab.setDisable(true); visualizer.clear(); - try { - if (type != null) { - // Selects only the part preceding the ';', skipping the character encoding - type = type.split(";")[0]; - switch (type.toLowerCase()) { + try { + if (contentType != null) { + // Selects only the part preceding the ';', skipping the character encoding + contentType = contentType.split(";")[0]; + + switch (contentType.toLowerCase()) { case "application/json": responseTypeBox.setValue("JSON"); - JsonNode node = EverestUtilities.jsonMapper.readTree(responseBody); + JsonNode node = EverestUtilities.jsonMapper.readTree(body); responseArea.setText(EverestUtilities.jsonMapper.writeValueAsString(node), HighlightMode.JSON); visualizerTab.setDisable(false); visualizer.populate(node); break; case "application/xml": responseTypeBox.setValue("XML"); - responseArea.setText(responseBody, HighlightMode.XML); + responseArea.setText(body, HighlightMode.XML); break; case "text/html": responseTypeBox.setValue("HTML"); - responseArea.setText(responseBody, HighlightMode.HTML); + responseArea.setText(body, HighlightMode.HTML); if (Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { snackbar.show("Open link in browser?", "YES", 5000, e -> { snackbar.close(); @@ -448,7 +452,7 @@ public class DashboardController implements Initializable { break; default: responseTypeBox.setValue("PLAIN TEXT"); - responseArea.setText(responseBody, HighlightMode.PLAIN); + responseArea.setText(body, HighlightMode.PLAIN); } } else { responseTypeBox.setValue("PLAIN"); @@ -463,6 +467,20 @@ public class DashboardController implements Initializable { } } + + private void prettifyResponseBody(EverestResponse response) { + String type; + + if (response.getMediaType() != null) + type = response.getMediaType().toString(); + else + type = ""; + + String responseBody = response.getBody(); + + prettifyResponseBody(responseBody, type); + } + @FXML private void clearResponseArea() { responseBox.getChildren().remove(0); @@ -557,8 +575,10 @@ public class DashboardController implements Initializable { /** * @return Current state of the Dashboard. */ - public ComposerState getState() { + public DashboardState getState() { + DashboardState dashboardState = new DashboardState(); ComposerState composerState; + switch (httpMethodBox.getValue()) { case "POST": case "PUT": @@ -575,7 +595,26 @@ public class DashboardController implements Initializable { composerState.headers = headerTabController.getFieldStates(); composerState.params = getParamFieldStates(); - return composerState; + dashboardState.composer = composerState; + dashboardState.showResponse = responseArea.isVisible(); + + if (dashboardState.showResponse) { + dashboardState.responseHeaders = headerTabController.getHeaders(); + dashboardState.statusCode = Integer.parseInt(statusCode.getText()); + + String temp = responseSize.getText(); + temp = temp.substring(0, temp.length() - 2); + dashboardState.responseSize = Integer.parseInt(temp); + + temp = responseTime.getText(); + temp = temp.substring(0, temp.length() - 3); + dashboardState.responseTime = Integer.parseInt(temp); + + dashboardState.responseBody = responseArea.getText(); + dashboardState.responseType = responseTypeBox.getValue(); + } + + return dashboardState; } /** @@ -583,7 +622,14 @@ public class DashboardController implements Initializable { * * @param state - State of the dashboard */ - public void setState(ComposerState state) { + public void setState(DashboardState state) { + if (state.showResponse) { + displayResponse(state); + } + + if (state.composer == null) + return; + /* The only value from a set of constants in the state.json file is the httpMethod which, if manipulated to a non-standard value by the user, would still @@ -596,7 +642,7 @@ public class DashboardController implements Initializable { */ boolean validMethod = false; for (String method : httpMethods) { - if (state.httpMethod.equals(method)) + if (state.composer.httpMethod.equals(method)) validMethod = true; } @@ -605,20 +651,35 @@ public class DashboardController implements Initializable { return; } - httpMethodBox.setValue(state.httpMethod); + httpMethodBox.setValue(state.composer.httpMethod); - if (state.target != null) - addressField.setText(state.target); + if (state.composer.target != null) + addressField.setText(state.composer.target); - if (state.headers != null) - for (FieldState fieldState : state.headers) + if (state.composer.headers != null) { + headerTabController.clear(); + for (FieldState fieldState : state.composer.headers) headerTabController.addHeader(fieldState); + } - if (state.params != null) - for (FieldState fieldState : state.params) + if (state.composer.params != null) { + clearParams(); + for (FieldState fieldState : state.composer.params) addParamField(fieldState); + } if (!(httpMethodBox.getValue().equals("GET") || httpMethodBox.getValue().equals("DELETE"))) - bodyTabController.setState(state); + bodyTabController.setState(state.composer); + } + + void clearParams() { + if (params != null) + params.clear(); + + if (paramsControllers != null) + paramsControllers.clear(); + + paramsBox.getChildren().clear(); + addParamField(); } } diff --git a/src/main/java/com/rohitawate/everest/controllers/FormDataTabController.java b/src/main/java/com/rohitawate/everest/controllers/FormDataTabController.java index 10dbc1e..4c1a9ef 100644 --- a/src/main/java/com/rohitawate/everest/controllers/FormDataTabController.java +++ b/src/main/java/com/rohitawate/everest/controllers/FormDataTabController.java @@ -223,4 +223,22 @@ public class FormDataTabController implements Initializable { return states; } + + void clear() { + if (stringMap != null) + stringMap.clear(); + + if (fileMap != null) + fileMap.clear(); + + if (stringControllers != null) + stringControllers.clear(); + + if (fileControllers != null) + fileControllers.clear(); + + fieldsBox.getChildren().clear(); + addStringField(); + addFileField(); + } } diff --git a/src/main/java/com/rohitawate/everest/controllers/HeaderTabController.java b/src/main/java/com/rohitawate/everest/controllers/HeaderTabController.java index f197daf..332a28a 100644 --- a/src/main/java/com/rohitawate/everest/controllers/HeaderTabController.java +++ b/src/main/java/com/rohitawate/everest/controllers/HeaderTabController.java @@ -134,4 +134,14 @@ public class HeaderTabController implements Initializable { return states; } + + void clear() { + if (headers != null) + headers.clear(); + if (controllers != null) + controllers.clear(); + + headersBox.getChildren().clear(); + addHeader(); + } } \ No newline at end of file diff --git a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java index cb5d72e..6162335 100644 --- a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java +++ b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java @@ -18,6 +18,7 @@ package com.rohitawate.everest.controllers; import com.fasterxml.jackson.core.type.TypeReference; import com.rohitawate.everest.controllers.state.ComposerState; +import com.rohitawate.everest.controllers.state.DashboardState; import com.rohitawate.everest.misc.EverestUtilities; import com.rohitawate.everest.misc.KeyMap; import com.rohitawate.everest.misc.Services; @@ -25,6 +26,7 @@ import com.rohitawate.everest.misc.ThemeManager; import javafx.application.Platform; import javafx.beans.binding.Bindings; import javafx.beans.property.StringProperty; +import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; @@ -58,7 +60,7 @@ public class HomeWindowController implements Initializable { @FXML private VBox tabDashboardBox; - private HashMap tabControllerMap; + private HashMap tabStateMap; private DashboardController dashboard; @Override @@ -73,7 +75,7 @@ public class HomeWindowController implements Initializable { } // Using LinkedHashMap because they retain order - tabControllerMap = new LinkedHashMap<>(); + tabStateMap = new LinkedHashMap<>(); recoverState(); historyPaneController.addItemClickHandler(this::addTab); @@ -87,6 +89,16 @@ public class HomeWindowController implements Initializable { Stage thisStage = (Stage) homeWindowSP.getScene().getWindow(); thisStage.setOnCloseRequest(e -> saveState()); }); + + homeWindowTabPane.getSelectionModel().selectedItemProperty().addListener(this::onTabSwitched); + } + + private void onTabSwitched(ObservableValue obs, Tab prevTab, Tab newTab) { + DashboardState dashboardState = dashboard.getState(); + tabStateMap.replace(prevTab, dashboardState); + + dashboardState = tabStateMap.get(newTab); + dashboard.setState(dashboardState); } private void setGlobalShortcuts() { @@ -96,14 +108,11 @@ public class HomeWindowController implements Initializable { if (KeyMap.newTab.match(e)) { addTab(); } else if (KeyMap.focusAddressBar.match(e)) { - Tab activeTab = getActiveTab(); - tabControllerMap.get(activeTab).addressField.requestFocus(); + dashboard.addressField.requestFocus(); } else if (KeyMap.focusMethodBox.match(e)) { - Tab activeTab = getActiveTab(); - tabControllerMap.get(activeTab).httpMethodBox.show(); + dashboard.httpMethodBox.show(); } else if (KeyMap.sendRequest.match(e)) { - Tab activeTab = getActiveTab(); - tabControllerMap.get(activeTab).sendRequest(); + dashboard.sendRequest(); } else if (KeyMap.toggleHistory.match(e)) { toggleHistoryPane(); } else if (KeyMap.closeTab.match(e)) { @@ -111,27 +120,19 @@ public class HomeWindowController implements Initializable { if (homeWindowTabPane.getTabs().size() == 1) addTab(); homeWindowTabPane.getTabs().remove(activeTab); - tabControllerMap.remove(activeTab); + tabStateMap.remove(activeTab); } else if (KeyMap.searchHistory.match(e)) { historyPaneController.focusSearchField(); } else if (KeyMap.focusParams.match(e)) { - Tab activeTab = getActiveTab(); - DashboardController controller = tabControllerMap.get(activeTab); - controller.requestOptionsTab.getSelectionModel().select(controller.paramsTab); + dashboard.requestOptionsTab.getSelectionModel().select(dashboard.paramsTab); } else if (KeyMap.focusAuth.match(e)) { - Tab activeTab = getActiveTab(); - DashboardController controller = tabControllerMap.get(activeTab); - controller.requestOptionsTab.getSelectionModel().select(controller.authTab); + dashboard.requestOptionsTab.getSelectionModel().select(dashboard.authTab); } else if (KeyMap.focusHeaders.match(e)) { - Tab activeTab = getActiveTab(); - DashboardController controller = tabControllerMap.get(activeTab); - controller.requestOptionsTab.getSelectionModel().select(controller.headersTab); + dashboard.requestOptionsTab.getSelectionModel().select(dashboard.headersTab); } else if (KeyMap.focusBody.match(e)) { - Tab activeTab = getActiveTab(); - DashboardController controller = tabControllerMap.get(activeTab); - String httpMethod = controller.httpMethodBox.getValue(); + String httpMethod = dashboard.httpMethodBox.getValue(); if (!httpMethod.equals("GET") && !httpMethod.equals("DELETE")) { - controller.requestOptionsTab.getSelectionModel().select(controller.bodyTab); + dashboard.requestOptionsTab.getSelectionModel().select(dashboard.bodyTab); } } else if (KeyMap.refreshTheme.match(e)) { ThemeManager.refreshTheme(); @@ -152,45 +153,26 @@ public class HomeWindowController implements Initializable { } private void addTab(ComposerState composerState) { - try { - Tab newTab = new Tab(); - FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/homewindow/Dashboard.fxml")); - Parent dashboard = loader.load(); - DashboardController controller = loader.getController(); + Tab newTab = new Tab(); + homeWindowTabPane.getTabs().add(newTab); - if (composerState != null) - controller.setState(composerState); + StringProperty addressProperty = dashboard.addressField.textProperty(); + newTab.textProperty().bind( + Bindings.when(addressProperty.isNotEmpty()) + .then(addressProperty) + .otherwise("New Tab")); - newTab.setContent(dashboard); - - // Binds the addressField text to the Tab text - StringProperty addressProperty = controller.addressField.textProperty(); - newTab.textProperty().bind( - Bindings.when(addressProperty.isNotEmpty()) - .then(addressProperty) - .otherwise("New Tab")); - - // Tab closing procedure - newTab.setOnCloseRequest(e -> { - if (homeWindowTabPane.getTabs().size() == 1) - addTab(); - tabControllerMap.remove(newTab); - }); - - homeWindowTabPane.getTabs().add(newTab); - homeWindowTabPane.getSelectionModel().select(newTab); - tabControllerMap.put(newTab, controller); - } catch (IOException e) { - Services.loggingService.logSevere("Could not add a new tab.", e, LocalDateTime.now()); - } + DashboardState dashboardState = new DashboardState(); + dashboardState.composer = composerState; + tabStateMap.put(newTab, dashboardState); } private void saveState() { ArrayList composerStates = new ArrayList<>(); // Get the states of all the tabs - for (DashboardController controller : tabControllerMap.values()) - composerStates.add(controller.getState()); + for (DashboardState dashboardState : tabStateMap.values()) + composerStates.add(dashboardState.composer); try { File stateFile = new File("Everest/config/state.json"); diff --git a/src/main/java/com/rohitawate/everest/controllers/ResponseHeadersViewer.java b/src/main/java/com/rohitawate/everest/controllers/ResponseHeadersViewer.java index 23f2dce..b4a108f 100644 --- a/src/main/java/com/rohitawate/everest/controllers/ResponseHeadersViewer.java +++ b/src/main/java/com/rohitawate/everest/controllers/ResponseHeadersViewer.java @@ -23,8 +23,12 @@ import javafx.scene.control.ScrollPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; +import javax.ws.rs.core.MultivaluedHashMap; +import java.util.HashMap; + class ResponseHeadersViewer extends ScrollPane { private VBox container; + private MultivaluedHashMap map; ResponseHeadersViewer() { this.container = new VBox(); @@ -33,12 +37,26 @@ class ResponseHeadersViewer extends ScrollPane { this.setFitToHeight(true); this.setFitToWidth(true); + + map = new MultivaluedHashMap<>(); + } + + void populate(HashMap headers) { + map.clear(); + headers.forEach((key, value) -> map.putSingle(key, value)); + populate(); } void populate(EverestResponse response) { + map.clear(); + map = (MultivaluedHashMap) response.getHeaders(); + populate(); + } + + private void populate() { container.getChildren().clear(); - response.getHeaders().forEach((key, value) -> { + map.forEach((key, value) -> { Label keyLabel = new Label(key + ": "); keyLabel.getStyleClass().addAll("visualizerKeyLabel", "visualizerLabel"); @@ -47,5 +65,6 @@ class ResponseHeadersViewer extends ScrollPane { container.getChildren().add(new HBox(keyLabel, valueLabel)); }); + } } diff --git a/src/main/java/com/rohitawate/everest/controllers/URLTabController.java b/src/main/java/com/rohitawate/everest/controllers/URLTabController.java index 730f13c..316e602 100644 --- a/src/main/java/com/rohitawate/everest/controllers/URLTabController.java +++ b/src/main/java/com/rohitawate/everest/controllers/URLTabController.java @@ -135,4 +135,14 @@ public class URLTabController implements Initializable { return states; } + + void clear() { + if (tuples != null) + tuples.clear(); + if (controllers != null) + controllers.clear(); + + fieldsBox.getChildren().clear(); + addField(); + } } diff --git a/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java b/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java index 7b73033..27f3444 100644 --- a/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java +++ b/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java @@ -23,6 +23,7 @@ public class DashboardState { public boolean showResponse; public int statusCode; public String responseType; + public String responseBody; public int responseTime; public int responseSize; public HashMap responseHeaders; From 00ac1f27e99e7251a5f613a64bfbcec41b3a33c4 Mon Sep 17 00:00:00 2001 From: Rohit Awate Date: Tue, 17 Jul 2018 14:07:03 +0530 Subject: [PATCH 03/45] Add method to reset Dashboard --- .../everest/controllers/BodyTabController.java | 10 ++++++++-- .../everest/controllers/DashboardController.java | 10 ++++++++-- .../everest/controllers/HomeWindowController.java | 2 ++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java b/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java index d5aef9c..bd6f5c1 100644 --- a/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java +++ b/src/main/java/com/rohitawate/everest/controllers/BodyTabController.java @@ -157,13 +157,11 @@ public class BodyTabController implements Initializable { public void setState(ComposerState state) { // Adding URL tab's tuples if (state.urlStringTuples != null) { - urlTabController.clear(); for (FieldState fieldState : state.urlStringTuples) urlTabController.addField(fieldState); } // Adding Form tab's string tuples - formDataTabController.clear(); if (state.formStringTuples != null) { for (FieldState fieldState : state.formStringTuples) formDataTabController.addStringField(fieldState); @@ -178,6 +176,14 @@ public class BodyTabController implements Initializable { filePathField.setText(state.binaryFilePath); } + void reset() { + urlTabController.clear(); + formDataTabController.clear(); + rawInputArea.clear(); + rawInputTypeBox.setValue("PLAIN TEXT"); + filePathField.clear(); + } + private void setRawTab(ComposerState state) { HighlightMode mode; diff --git a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java index 01992df..a080809 100644 --- a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java +++ b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java @@ -657,13 +657,11 @@ public class DashboardController implements Initializable { addressField.setText(state.composer.target); if (state.composer.headers != null) { - headerTabController.clear(); for (FieldState fieldState : state.composer.headers) headerTabController.addHeader(fieldState); } if (state.composer.params != null) { - clearParams(); for (FieldState fieldState : state.composer.params) addParamField(fieldState); } @@ -672,6 +670,14 @@ public class DashboardController implements Initializable { bodyTabController.setState(state.composer); } + void reset() { + httpMethodBox.setValue("GET"); + addressField.clear(); + headerTabController.clear(); + clearParams(); + bodyTabController.reset(); + } + void clearParams() { if (params != null) params.clear(); diff --git a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java index 6162335..a0bc36b 100644 --- a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java +++ b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java @@ -98,6 +98,7 @@ public class HomeWindowController implements Initializable { tabStateMap.replace(prevTab, dashboardState); dashboardState = tabStateMap.get(newTab); + dashboard.reset(); dashboard.setState(dashboardState); } @@ -165,6 +166,7 @@ public class HomeWindowController implements Initializable { DashboardState dashboardState = new DashboardState(); dashboardState.composer = composerState; tabStateMap.put(newTab, dashboardState); + homeWindowTabPane.getSelectionModel().select(newTab); } private void saveState() { From a5b0f80b385793d01e12a9e360fb7c576849ba86 Mon Sep 17 00:00:00 2001 From: Rohit Awate Date: Tue, 17 Jul 2018 14:22:19 +0530 Subject: [PATCH 04/45] Refactor keymap logic into nested HomeWindowController.KeymapHandler --- .../controllers/HomeWindowController.java | 82 ++++++++++--------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java index a0bc36b..d3f316b 100644 --- a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java +++ b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java @@ -83,7 +83,7 @@ public class HomeWindowController implements Initializable { Platform.runLater(() -> { homeWindowSP.requestFocus(); - this.setGlobalShortcuts(); + new KeymapHandler(); // Saves the state of the application before closing Stage thisStage = (Stage) homeWindowSP.getScene().getWindow(); @@ -102,45 +102,6 @@ public class HomeWindowController implements Initializable { dashboard.setState(dashboardState); } - private void setGlobalShortcuts() { - Scene thisScene = homeWindowSP.getScene(); - - thisScene.setOnKeyPressed(e -> { - if (KeyMap.newTab.match(e)) { - addTab(); - } else if (KeyMap.focusAddressBar.match(e)) { - dashboard.addressField.requestFocus(); - } else if (KeyMap.focusMethodBox.match(e)) { - dashboard.httpMethodBox.show(); - } else if (KeyMap.sendRequest.match(e)) { - dashboard.sendRequest(); - } else if (KeyMap.toggleHistory.match(e)) { - toggleHistoryPane(); - } else if (KeyMap.closeTab.match(e)) { - Tab activeTab = getActiveTab(); - if (homeWindowTabPane.getTabs().size() == 1) - addTab(); - homeWindowTabPane.getTabs().remove(activeTab); - tabStateMap.remove(activeTab); - } else if (KeyMap.searchHistory.match(e)) { - historyPaneController.focusSearchField(); - } else if (KeyMap.focusParams.match(e)) { - dashboard.requestOptionsTab.getSelectionModel().select(dashboard.paramsTab); - } else if (KeyMap.focusAuth.match(e)) { - dashboard.requestOptionsTab.getSelectionModel().select(dashboard.authTab); - } else if (KeyMap.focusHeaders.match(e)) { - dashboard.requestOptionsTab.getSelectionModel().select(dashboard.headersTab); - } else if (KeyMap.focusBody.match(e)) { - String httpMethod = dashboard.httpMethodBox.getValue(); - if (!httpMethod.equals("GET") && !httpMethod.equals("DELETE")) { - dashboard.requestOptionsTab.getSelectionModel().select(dashboard.bodyTab); - } - } else if (KeyMap.refreshTheme.match(e)) { - ThemeManager.refreshTheme(); - } - }); - } - private Tab getActiveTab() { return homeWindowTabPane.getSelectionModel().getSelectedItem(); } @@ -217,4 +178,45 @@ public class HomeWindowController implements Initializable { public void addHistoryItem(ComposerState state) { historyPaneController.addHistoryItem(state); } + + private class KeymapHandler { + private KeymapHandler() { + Scene thisScene = homeWindowSP.getScene(); + + thisScene.setOnKeyPressed(e -> { + if (KeyMap.newTab.match(e)) { + addTab(); + } else if (KeyMap.focusAddressBar.match(e)) { + dashboard.addressField.requestFocus(); + } else if (KeyMap.focusMethodBox.match(e)) { + dashboard.httpMethodBox.show(); + } else if (KeyMap.sendRequest.match(e)) { + dashboard.sendRequest(); + } else if (KeyMap.toggleHistory.match(e)) { + toggleHistoryPane(); + } else if (KeyMap.closeTab.match(e)) { + Tab activeTab = getActiveTab(); + if (homeWindowTabPane.getTabs().size() == 1) + addTab(); + homeWindowTabPane.getTabs().remove(activeTab); + tabStateMap.remove(activeTab); + } else if (KeyMap.searchHistory.match(e)) { + historyPaneController.focusSearchField(); + } else if (KeyMap.focusParams.match(e)) { + dashboard.requestOptionsTab.getSelectionModel().select(dashboard.paramsTab); + } else if (KeyMap.focusAuth.match(e)) { + dashboard.requestOptionsTab.getSelectionModel().select(dashboard.authTab); + } else if (KeyMap.focusHeaders.match(e)) { + dashboard.requestOptionsTab.getSelectionModel().select(dashboard.headersTab); + } else if (KeyMap.focusBody.match(e)) { + String httpMethod = dashboard.httpMethodBox.getValue(); + if (!httpMethod.equals("GET") && !httpMethod.equals("DELETE")) { + dashboard.requestOptionsTab.getSelectionModel().select(dashboard.bodyTab); + } + } else if (KeyMap.refreshTheme.match(e)) { + ThemeManager.refreshTheme(); + } + }); + } + } } From 7f9c14d6f6055173fbba57736317bca1d17b39fb Mon Sep 17 00:00:00 2001 From: Rohit Awate Date: Tue, 17 Jul 2018 15:44:13 +0530 Subject: [PATCH 05/45] Add responseLayer maintenance while tab-switching --- .../controllers/DashboardController.java | 79 +++++++-- .../controllers/HomeWindowController.java | 28 ++- .../controllers/ResponseHeadersViewer.java | 2 +- .../resources/fxml/homewindow/Dashboard.fxml | 164 ++++++++++-------- 4 files changed, 182 insertions(+), 91 deletions(-) diff --git a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java index a080809..fbdf8c9 100644 --- a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java +++ b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java @@ -47,7 +47,6 @@ import javafx.scene.control.*; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.input.KeyCode; -import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.fxmisc.flowless.VirtualizedScrollPane; @@ -75,16 +74,14 @@ public class DashboardController implements Initializable { @FXML ComboBox httpMethodBox, responseTypeBox; @FXML - private VBox responseBox, loadingLayer, promptLayer, errorLayer, paramsBox; - @FXML - private HBox responseDetails; + private VBox responseBox, responseLayer, loadingLayer, promptLayer, errorLayer, paramsBox; @FXML private Label statusCode, statusCodeDescription, responseTime, responseSize, errorTitle, errorDetails; @FXML private JFXButton cancelButton, copyBodyButton; @FXML - TabPane requestOptionsTab; + TabPane requestOptionsTab, responseTabPane; @FXML Tab paramsTab, authTab, headersTab, bodyTab; @FXML @@ -109,6 +106,10 @@ public class DashboardController implements Initializable { private HashMap params; private EverestCodeArea responseArea; + private enum ResponseLayer { + PROMPT, LOADING, RESPONSE, ERROR + } + @Override public void initialize(URL url, ResourceBundle rb) { try { @@ -131,8 +132,7 @@ public class DashboardController implements Initializable { snackbar = new JFXSnackbar(dashboard); - responseBox.getChildren().remove(0); - promptLayer.setVisible(true); + displayLayer(ResponseLayer.PROMPT); httpMethodBox.getItems().addAll(httpMethods); // Select GET by default @@ -392,9 +392,38 @@ public class DashboardController implements Initializable { loadingLayer.setVisible(true); } + private void displayLayer(ResponseLayer layer) { + switch (layer) { + case ERROR: + errorLayer.setVisible(true); + loadingLayer.setVisible(false); + promptLayer.setVisible(false); + responseLayer.setVisible(false); + break; + case LOADING: + loadingLayer.setVisible(true); + errorLayer.setVisible(false); + promptLayer.setVisible(false); + responseLayer.setVisible(false); + break; + case RESPONSE: + responseLayer.setVisible(true); + errorLayer.setVisible(false); + loadingLayer.setVisible(false); + promptLayer.setVisible(false); + break; + case PROMPT: + default: + promptLayer.setVisible(true); + loadingLayer.setVisible(false); + errorLayer.setVisible(false); + responseLayer.setVisible(false); + break; + } + } + private void displayResponse(EverestResponse response) { prettifyResponseBody(response); - responseBox.getChildren().add(0, responseDetails); statusCode.setText(Integer.toString(response.getStatusCode())); statusCodeDescription.setText(Response.Status.fromStatusCode(response.getStatusCode()).getReasonPhrase()); responseTime.setText(Long.toString(response.getTime()) + " ms"); @@ -404,8 +433,6 @@ public class DashboardController implements Initializable { private void displayResponse(DashboardState state) { prettifyResponseBody(state.responseBody, state.responseType); - responseBox.getChildren().remove(responseDetails); - responseBox.getChildren().add(0, responseDetails); statusCode.setText(Integer.toString(state.statusCode)); statusCodeDescription.setText(Response.Status.fromStatusCode(state.statusCode).getReasonPhrase()); responseTime.setText(Long.toString(state.responseTime) + " ms"); @@ -414,6 +441,7 @@ public class DashboardController implements Initializable { } private void prettifyResponseBody(String body, String contentType) { + displayLayer(ResponseLayer.RESPONSE); visualizerTab.setDisable(true); visualizer.clear(); @@ -456,7 +484,7 @@ public class DashboardController implements Initializable { } } else { responseTypeBox.setValue("PLAIN"); - responseArea.setText("No rawBody found in the response.", HighlightMode.PLAIN); + responseArea.setText("No body found in the response.", HighlightMode.PLAIN); } } catch (Exception e) { snackbar.show("Response could not be parsed.", 5000); @@ -596,7 +624,7 @@ public class DashboardController implements Initializable { composerState.params = getParamFieldStates(); dashboardState.composer = composerState; - dashboardState.showResponse = responseArea.isVisible(); + dashboardState.showResponse = responseLayer.isVisible(); if (dashboardState.showResponse) { dashboardState.responseHeaders = headerTabController.getHeaders(); @@ -611,7 +639,23 @@ public class DashboardController implements Initializable { dashboardState.responseTime = Integer.parseInt(temp); dashboardState.responseBody = responseArea.getText(); - dashboardState.responseType = responseTypeBox.getValue(); + + String contentType; + switch (responseTypeBox.getValue()) { + case "JSON": + contentType = MediaType.APPLICATION_JSON; + break; + case "XML": + contentType = MediaType.APPLICATION_XML; + break; + case "HTML": + contentType = MediaType.TEXT_HTML; + break; + default: + contentType = MediaType.TEXT_PLAIN; + } + + dashboardState.responseType = contentType; } return dashboardState; @@ -623,9 +667,11 @@ public class DashboardController implements Initializable { * @param state - State of the dashboard */ public void setState(DashboardState state) { - if (state.showResponse) { + if (state == null) + return; + + if (state.showResponse) displayResponse(state); - } if (state.composer == null) return; @@ -676,6 +722,9 @@ public class DashboardController implements Initializable { headerTabController.clear(); clearParams(); bodyTabController.reset(); + responseArea.clear(); + displayLayer(ResponseLayer.PROMPT); + responseTabPane.getSelectionModel().select(0); } void clearParams() { diff --git a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java index d3f316b..fe053f9 100644 --- a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java +++ b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java @@ -128,12 +128,28 @@ public class HomeWindowController implements Initializable { dashboardState.composer = composerState; tabStateMap.put(newTab, dashboardState); homeWindowTabPane.getSelectionModel().select(newTab); + + newTab.setOnCloseRequest(e -> { + tabStateMap.remove(newTab); + + if (homeWindowTabPane.getTabs().size() == 1) { + Stage thisStage = (Stage) homeWindowSP.getScene().getWindow(); + thisStage.close(); + } + }); } private void saveState() { - ArrayList composerStates = new ArrayList<>(); + /* + Updating the state of the selected tab before saving it. + Other tabs will already have their states saved when they + were loaded from state.json or on a tab switch. + */ + Tab currentTab = homeWindowTabPane.getSelectionModel().getSelectedItem(); + DashboardState currentState = dashboard.getState(); + tabStateMap.put(currentTab, currentState); - // Get the states of all the tabs + ArrayList composerStates = new ArrayList<>(); for (DashboardState dashboardState : tabStateMap.values()) composerStates.add(dashboardState.composer); @@ -196,10 +212,12 @@ public class HomeWindowController implements Initializable { toggleHistoryPane(); } else if (KeyMap.closeTab.match(e)) { Tab activeTab = getActiveTab(); - if (homeWindowTabPane.getTabs().size() == 1) - addTab(); - homeWindowTabPane.getTabs().remove(activeTab); tabStateMap.remove(activeTab); + if (homeWindowTabPane.getTabs().size() == 1) { + Stage thisStage = (Stage) homeWindowSP.getScene().getWindow(); + thisStage.close(); + homeWindowTabPane.getTabs().remove(activeTab); + } } else if (KeyMap.searchHistory.match(e)) { historyPaneController.focusSearchField(); } else if (KeyMap.focusParams.match(e)) { diff --git a/src/main/java/com/rohitawate/everest/controllers/ResponseHeadersViewer.java b/src/main/java/com/rohitawate/everest/controllers/ResponseHeadersViewer.java index b4a108f..8d14f30 100644 --- a/src/main/java/com/rohitawate/everest/controllers/ResponseHeadersViewer.java +++ b/src/main/java/com/rohitawate/everest/controllers/ResponseHeadersViewer.java @@ -49,7 +49,7 @@ class ResponseHeadersViewer extends ScrollPane { void populate(EverestResponse response) { map.clear(); - map = (MultivaluedHashMap) response.getHeaders(); + response.getHeaders().forEach((key, value) -> map.putSingle(key, value.get(0))); populate(); } diff --git a/src/main/resources/fxml/homewindow/Dashboard.fxml b/src/main/resources/fxml/homewindow/Dashboard.fxml index 25ffbae..4082e61 100644 --- a/src/main/resources/fxml/homewindow/Dashboard.fxml +++ b/src/main/resources/fxml/homewindow/Dashboard.fxml @@ -22,7 +22,8 @@ - + @@ -134,77 +135,100 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/fxml/homewindow/HomeWindow.fxml b/src/main/resources/fxml/homewindow/HomeWindow.fxml index 1d48715..d6456c4 100644 --- a/src/main/resources/fxml/homewindow/HomeWindow.fxml +++ b/src/main/resources/fxml/homewindow/HomeWindow.fxml @@ -18,18 +18,18 @@ - - - + - + - - + - + + From 32dcc0bce29f5684559eba663cf523b8282b194f Mon Sep 17 00:00:00 2001 From: Rohit Awate Date: Wed, 18 Jul 2018 22:58:47 +0530 Subject: [PATCH 11/45] Re-implemented logic for changing tab-text with URL --- .../controllers/DashboardController.java | 15 +++--- .../controllers/HomeWindowController.java | 49 ++++++++++++------- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java index e95c35b..83466b6 100644 --- a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java +++ b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java @@ -119,14 +119,14 @@ public class DashboardController implements Initializable { headerTabController = headerTabLoader.getController(); headersTab.setContent(headerTabContent); - // Loading the rawBody tab + // Loading the body tab FXMLLoader bodyTabLoader = new FXMLLoader(getClass().getResource("/fxml/homewindow/BodyTab.fxml")); Parent bodyTabContent = bodyTabLoader.load(); ThemeManager.setTheme(bodyTabContent); bodyTabController = bodyTabLoader.getController(); bodyTab.setContent(bodyTabContent); } catch (IOException e) { - Services.loggingService.logSevere("Could not load headers/rawBody tabs.", e, LocalDateTime.now()); + Services.loggingService.logSevere("Could not load headers/body tabs.", e, LocalDateTime.now()); } snackbar = new JFXSnackbar(dashboard); @@ -360,7 +360,7 @@ public class DashboardController implements Initializable { if (requestManager.getClass() == DataDispatchRequestManager.class) { if (throwable.getCause() != null && throwable.getCause().getClass() == IllegalArgumentException.class) { errorTitle.setText("Did you forget something?"); - errorDetails.setText("Please specify at least one rawBody part for your " + httpMethodBox.getValue() + " request."); + errorDetails.setText("Please specify a body for your " + httpMethodBox.getValue() + " request."); } else if (throwable.getClass() == FileNotFoundException.class) { errorTitle.setText("File(s) not found:"); errorDetails.setText(throwable.getMessage()); @@ -372,23 +372,20 @@ public class DashboardController implements Initializable { } private void onCancelled() { - loadingLayer.setVisible(false); - promptLayer.setVisible(true); + displayLayer(ResponseLayer.PROMPT); snackbar.show("Request canceled.", 2000); requestManager.reset(); } private void onSucceeded() { displayResponse(requestManager.getValue()); - errorLayer.setVisible(false); - loadingLayer.setVisible(false); + displayLayer(ResponseLayer.RESPONSE); requestManager.reset(); } private void whileRunning() { responseArea.clear(); - errorLayer.setVisible(false); - loadingLayer.setVisible(true); + displayLayer(ResponseLayer.LOADING); } private void displayLayer(ResponseLayer layer) { diff --git a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java index 20368d7..421a167 100644 --- a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java +++ b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java @@ -58,6 +58,7 @@ public class HomeWindowController implements Initializable { private HashMap tabStateMap; private HistoryPaneController historyController; private DashboardController dashboard; + private StringProperty addressProperty; @Override public void initialize(URL location, ResourceBundle resources) { @@ -72,6 +73,7 @@ public class HomeWindowController implements Initializable { Parent dashboardFXML = dashboardLoader.load(); dashboard = dashboardLoader.getController(); dashboardContainer.getChildren().add(dashboardFXML); + addressProperty = dashboard.addressField.textProperty(); } catch (IOException e) { e.printStackTrace(); } @@ -139,25 +141,6 @@ public class HomeWindowController implements Initializable { private void addTab(ComposerState composerState) { Tab newTab = new Tab(); - StringProperty addressProperty = dashboard.addressField.textProperty(); - - newTab.textProperty().bind( - Bindings.when(addressProperty.isNotEmpty()) - .then(addressProperty) - .otherwise("New Tab")); - - newTab.setOnCloseRequest(e -> { - tabStateMap.remove(newTab); - tabPane.getTabs().remove(newTab); - - // Closes the application if the last tab is closed - if (tabPane.getTabs().size() == 0) { - saveState(); - Stage thisStage = (Stage) homeWindowSP.getScene().getWindow(); - thisStage.close(); - } - }); - DashboardState newState = new DashboardState(composerState); tabStateMap.put(newTab, newState); @@ -174,6 +157,34 @@ public class HomeWindowController implements Initializable { tabPane.getTabs().add(newTab); tabPane.getSelectionModel().select(newTab); onTabSwitched(prevState, prevTab, newTab); + + // Makes the Tab's text change with the URL + newTab.textProperty().bind( + Bindings.when(Bindings.and(addressProperty.isNotEmpty(), newTab.selectedProperty())) + .then(addressProperty) + .otherwise(getTabText(newTab)) + ); + + newTab.setOnCloseRequest(e -> { + tabStateMap.remove(newTab); + tabPane.getTabs().remove(newTab); + + // Closes the application if the last tab is closed + if (tabPane.getTabs().size() == 0) { + saveState(); + Stage thisStage = (Stage) homeWindowSP.getScene().getWindow(); + thisStage.close(); + } + }); + } + + private String getTabText(Tab newTab) { + DashboardState state = tabStateMap.get(newTab); + + if (state == null || state.composer == null || state.composer.target.equals("")) + return "New Tab"; + else + return state.composer.target; } private void saveState() { From 772ac377bd0e36aa5326b7862987899a47317506 Mon Sep 17 00:00:00 2001 From: Rohit Awate Date: Sat, 21 Jul 2018 16:04:12 +0530 Subject: [PATCH 12/45] Re-wrote tab text reflection logic --- .../controllers/HomeWindowController.java | 43 +++++++++++-------- .../controllers/state/ComposerState.java | 5 +++ src/main/resources/templates/LogsFile.html | 2 +- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java index 421a167..67adc19 100644 --- a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java +++ b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java @@ -24,7 +24,6 @@ import com.rohitawate.everest.misc.KeyMap; import com.rohitawate.everest.misc.Services; import com.rohitawate.everest.misc.ThemeManager; import javafx.application.Platform; -import javafx.beans.binding.Bindings; import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; @@ -94,6 +93,29 @@ public class HomeWindowController implements Initializable { }); tabPane.getSelectionModel().selectedItemProperty().addListener(this::onTabSwitched); + + initAddressReflection(); + } + + private void initAddressReflection() { + addressProperty.addListener(((observable, oldValue, newValue) -> { + Tab activeTab = tabPane.getSelectionModel().getSelectedItem(); + if (activeTab != null) { + if (newValue.equals("")) + activeTab.setText("New Tab"); + else + activeTab.setText(newValue); + } + })); + + // Initialize the text of tabs loaded by the state recovery logic + tabPane.getTabs().forEach(tab -> { + String target = tabStateMap.get(tab).composer.target; + if (target.equals("")) + tab.setText("New Tab"); + else + tab.setText(target); + }); } /** @@ -131,7 +153,7 @@ public class HomeWindowController implements Initializable { } private void addTab() { - addTab(null); + addTab(new ComposerState()); } /** @@ -140,6 +162,7 @@ public class HomeWindowController implements Initializable { */ private void addTab(ComposerState composerState) { Tab newTab = new Tab(); + newTab.setText("New Tab"); DashboardState newState = new DashboardState(composerState); tabStateMap.put(newTab, newState); @@ -158,13 +181,6 @@ public class HomeWindowController implements Initializable { tabPane.getSelectionModel().select(newTab); onTabSwitched(prevState, prevTab, newTab); - // Makes the Tab's text change with the URL - newTab.textProperty().bind( - Bindings.when(Bindings.and(addressProperty.isNotEmpty(), newTab.selectedProperty())) - .then(addressProperty) - .otherwise(getTabText(newTab)) - ); - newTab.setOnCloseRequest(e -> { tabStateMap.remove(newTab); tabPane.getTabs().remove(newTab); @@ -178,15 +194,6 @@ public class HomeWindowController implements Initializable { }); } - private String getTabText(Tab newTab) { - DashboardState state = tabStateMap.get(newTab); - - if (state == null || state.composer == null || state.composer.target.equals("")) - return "New Tab"; - else - return state.composer.target; - } - private void saveState() { /* Updating the state of the selected tab before saving it. diff --git a/src/main/java/com/rohitawate/everest/controllers/state/ComposerState.java b/src/main/java/com/rohitawate/everest/controllers/state/ComposerState.java index c898de9..32bc43d 100644 --- a/src/main/java/com/rohitawate/everest/controllers/state/ComposerState.java +++ b/src/main/java/com/rohitawate/everest/controllers/state/ComposerState.java @@ -23,6 +23,7 @@ import java.util.ArrayList; */ public class ComposerState { public String target; + public String httpMethod; public ArrayList params; public ArrayList headers; @@ -43,4 +44,8 @@ public class ComposerState { // File path of application/octet-stream requests public String binaryFilePath; + + public ComposerState() { + this.httpMethod = "GET"; + } } diff --git a/src/main/resources/templates/LogsFile.html b/src/main/resources/templates/LogsFile.html index bc47a82..91e276b 100644 --- a/src/main/resources/templates/LogsFile.html +++ b/src/main/resources/templates/LogsFile.html @@ -54,4 +54,4 @@ -

Everest Log: %% Date %%

+

Everest Logs: %% Date %%

From df1f61a5d81d942fff9bd3dcc2f0a6eb8a22795b Mon Sep 17 00:00:00 2001 From: Rohit Awate Date: Sat, 21 Jul 2018 17:14:42 +0530 Subject: [PATCH 13/45] Clean tab-text reflection logic and add ErrorLayer maintenance while switching tabs --- .../controllers/DashboardController.java | 122 ++++++++++-------- .../controllers/HomeWindowController.java | 44 ++++--- .../controllers/state/DashboardState.java | 13 +- 3 files changed, 106 insertions(+), 73 deletions(-) diff --git a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java index 83466b6..5b1a69d 100644 --- a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java +++ b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java @@ -104,8 +104,9 @@ public class DashboardController implements Initializable { private DELETERequest deleteRequest; private HashMap params; private EverestCodeArea responseArea; + private ResponseLayer visibleLayer; - private enum ResponseLayer { + public enum ResponseLayer { PROMPT, LOADING, RESPONSE, ERROR } @@ -131,7 +132,7 @@ public class DashboardController implements Initializable { snackbar = new JFXSnackbar(dashboard); - displayLayer(ResponseLayer.PROMPT); + showLayer(ResponseLayer.PROMPT); httpMethodBox.getItems().addAll(httpMethods); // Select GET by default @@ -209,7 +210,6 @@ public class DashboardController implements Initializable { return; } - promptLayer.setVisible(false); if (responseBox.getChildren().size() == 2) { responseBox.getChildren().remove(0); responseArea.clear(); @@ -219,7 +219,7 @@ public class DashboardController implements Initializable { String address = addressField.getText().trim(); if (address.equals("")) { - promptLayer.setVisible(true); + showLayer(ResponseLayer.PROMPT); snackbar.show("Please enter an address.", 3000); return; } @@ -312,15 +312,15 @@ public class DashboardController implements Initializable { requestManager.start(); break; default: - loadingLayer.setVisible(false); + showLayer(ResponseLayer.PROMPT); } Services.historyManager.saveHistory(getState().composer); } catch (MalformedURLException MURLE) { - promptLayer.setVisible(true); + showLayer(ResponseLayer.PROMPT); snackbar.show("Invalid address. Please verify and try again.", 3000); } catch (Exception E) { Services.loggingService.logSevere("Request execution failed.", E, LocalDateTime.now()); - errorLayer.setVisible(true); + showLayer(ResponseLayer.ERROR); errorTitle.setText("Oops... That's embarrassing!"); errorDetails.setText("Something went wrong. Try to make another request.\nRestart Everest if that doesn't work."); } @@ -335,8 +335,7 @@ public class DashboardController implements Initializable { } private void onFailed() { - loadingLayer.setVisible(false); - promptLayer.setVisible(false); + showLayer(ResponseLayer.ERROR); Throwable throwable = requestManager.getException(); Exception exception = (Exception) throwable; Services.loggingService.logWarning(httpMethodBox.getValue() + " request could not be processed.", exception, LocalDateTime.now()); @@ -367,28 +366,29 @@ public class DashboardController implements Initializable { } } - errorLayer.setVisible(true); requestManager.reset(); } private void onCancelled() { - displayLayer(ResponseLayer.PROMPT); + showLayer(ResponseLayer.PROMPT); snackbar.show("Request canceled.", 2000); requestManager.reset(); } private void onSucceeded() { - displayResponse(requestManager.getValue()); - displayLayer(ResponseLayer.RESPONSE); + showResponse(requestManager.getValue()); + showLayer(ResponseLayer.RESPONSE); requestManager.reset(); } private void whileRunning() { responseArea.clear(); - displayLayer(ResponseLayer.LOADING); + showLayer(ResponseLayer.LOADING); } - private void displayLayer(ResponseLayer layer) { + private void showLayer(ResponseLayer layer) { + this.visibleLayer = layer; + switch (layer) { case ERROR: errorLayer.setVisible(true); @@ -418,7 +418,7 @@ public class DashboardController implements Initializable { } } - private void displayResponse(EverestResponse response) { + private void showResponse(EverestResponse response) { prettifyResponseBody(response); statusCode.setText(Integer.toString(response.getStatusCode())); statusCodeDescription.setText(Response.Status.fromStatusCode(response.getStatusCode()).getReasonPhrase()); @@ -427,17 +427,17 @@ public class DashboardController implements Initializable { responseHeadersViewer.populate(response); } - private void displayResponse(DashboardState state) { + private void showResponse(DashboardState state) { prettifyResponseBody(state.responseBody, state.responseType); - statusCode.setText(Integer.toString(state.statusCode)); - statusCodeDescription.setText(Response.Status.fromStatusCode(state.statusCode).getReasonPhrase()); + statusCode.setText(Integer.toString(state.responseCode)); + statusCodeDescription.setText(Response.Status.fromStatusCode(state.responseCode).getReasonPhrase()); responseTime.setText(Long.toString(state.responseTime) + " ms"); responseSize.setText(Integer.toString(state.responseSize) + " B"); responseHeadersViewer.populate(state.responseHeaders); } private void prettifyResponseBody(String body, String contentType) { - displayLayer(ResponseLayer.RESPONSE); + showLayer(ResponseLayer.RESPONSE); visualizerTab.setDisable(true); visualizer.clear(); @@ -485,7 +485,7 @@ public class DashboardController implements Initializable { } catch (Exception e) { snackbar.show("Response could not be parsed.", 5000); Services.loggingService.logSevere("Response could not be parsed.", e, LocalDateTime.now()); - errorLayer.setVisible(true); + showLayer(ResponseLayer.ERROR); errorTitle.setText("Parsing Error"); errorDetails.setText("Everest could not parse the response."); } @@ -509,7 +509,7 @@ public class DashboardController implements Initializable { private void clearResponseArea() { responseBox.getChildren().remove(0); responseArea.clear(); - promptLayer.setVisible(true); + showLayer(ResponseLayer.PROMPT); } @FXML @@ -619,38 +619,44 @@ public class DashboardController implements Initializable { composerState.params = getParamFieldStates(); dashboardState.composer = composerState; - dashboardState.showResponse = responseLayer.isVisible(); + dashboardState.visibleLayer = visibleLayer; - if (dashboardState.showResponse) { - dashboardState.responseHeaders = responseHeadersViewer.getHeaders(); - dashboardState.statusCode = Integer.parseInt(statusCode.getText()); + switch (visibleLayer) { + case RESPONSE: + dashboardState.responseHeaders = responseHeadersViewer.getHeaders(); + dashboardState.responseCode = Integer.parseInt(statusCode.getText()); - String temp = responseSize.getText(); - temp = temp.substring(0, temp.length() - 2); - dashboardState.responseSize = Integer.parseInt(temp); + String temp = responseSize.getText(); + temp = temp.substring(0, temp.length() - 2); + dashboardState.responseSize = Integer.parseInt(temp); - temp = responseTime.getText(); - temp = temp.substring(0, temp.length() - 3); - dashboardState.responseTime = Integer.parseInt(temp); + temp = responseTime.getText(); + temp = temp.substring(0, temp.length() - 3); + dashboardState.responseTime = Integer.parseInt(temp); - dashboardState.responseBody = responseArea.getText(); + dashboardState.responseBody = responseArea.getText(); - String contentType; - switch (responseTypeBox.getValue()) { - case "JSON": - contentType = MediaType.APPLICATION_JSON; - break; - case "XML": - contentType = MediaType.APPLICATION_XML; - break; - case "HTML": - contentType = MediaType.TEXT_HTML; - break; - default: - contentType = MediaType.TEXT_PLAIN; - } + String contentType; + switch (responseTypeBox.getValue()) { + case "JSON": + contentType = MediaType.APPLICATION_JSON; + break; + case "XML": + contentType = MediaType.APPLICATION_XML; + break; + case "HTML": + contentType = MediaType.TEXT_HTML; + break; + default: + contentType = MediaType.TEXT_PLAIN; + } - dashboardState.responseType = contentType; + dashboardState.responseType = contentType; + break; + case ERROR: + dashboardState.errorTitle = errorTitle.getText(); + dashboardState.errorDetails = errorDetails.getText(); + break; } return dashboardState; @@ -665,8 +671,22 @@ public class DashboardController implements Initializable { if (state == null) return; - if (state.showResponse) - displayResponse(state); + if (state.visibleLayer != null) { + switch (state.visibleLayer) { + case RESPONSE: + showResponse(state); + break; + case ERROR: + errorTitle.setText(state.errorTitle); + errorDetails.setText(state.errorDetails); + showLayer(ResponseLayer.ERROR); + break; + } + if (state.visibleLayer.equals(ResponseLayer.RESPONSE)) + showResponse(state); + else + showLayer(state.visibleLayer); + } if (state.composer == null) return; @@ -718,7 +738,7 @@ public class DashboardController implements Initializable { clearParams(); bodyTabController.reset(); responseArea.clear(); - displayLayer(ResponseLayer.PROMPT); + showLayer(ResponseLayer.PROMPT); responseTabPane.getSelectionModel().select(0); } diff --git a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java index 67adc19..7663852 100644 --- a/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java +++ b/src/main/java/com/rohitawate/everest/controllers/HomeWindowController.java @@ -24,6 +24,7 @@ import com.rohitawate.everest.misc.KeyMap; import com.rohitawate.everest.misc.Services; import com.rohitawate.everest.misc.ThemeManager; import javafx.application.Platform; +import javafx.beans.Observable; import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; @@ -94,28 +95,22 @@ public class HomeWindowController implements Initializable { tabPane.getSelectionModel().selectedItemProperty().addListener(this::onTabSwitched); - initAddressReflection(); + addressProperty.addListener(this::onTargetChanged); } - private void initAddressReflection() { - addressProperty.addListener(((observable, oldValue, newValue) -> { - Tab activeTab = tabPane.getSelectionModel().getSelectedItem(); - if (activeTab != null) { - if (newValue.equals("")) - activeTab.setText("New Tab"); - else - activeTab.setText(newValue); - } - })); + /** + * Sets up the reflection of the address in the selected tab. + * Displays the current target if it is not empty, "New Tab" otherwise. + */ + private void onTargetChanged(Observable observable, String oldValue, String newValue) { + Tab activeTab = tabPane.getSelectionModel().getSelectedItem(); + if (activeTab == null) + return; - // Initialize the text of tabs loaded by the state recovery logic - tabPane.getTabs().forEach(tab -> { - String target = tabStateMap.get(tab).composer.target; - if (target.equals("")) - tab.setText("New Tab"); - else - tab.setText(target); - }); + if (newValue.equals("")) + activeTab.setText("New Tab"); + else + activeTab.setText(newValue); } /** @@ -162,7 +157,16 @@ public class HomeWindowController implements Initializable { */ private void addTab(ComposerState composerState) { Tab newTab = new Tab(); - newTab.setText("New Tab"); + + /* + Initializing the tab text based on the target in the ComposerState. + Further handling of the tab text is done by onTargetChanged(). + */ + String target = composerState.target; + if (target == null || target.equals("")) + newTab.setText("New Tab"); + else + newTab.setText(target); DashboardState newState = new DashboardState(composerState); tabStateMap.put(newTab, newState); diff --git a/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java b/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java index cff8ece..0981c2d 100644 --- a/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java +++ b/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java @@ -16,16 +16,25 @@ package com.rohitawate.everest.controllers.state; +import com.rohitawate.everest.controllers.DashboardController.ResponseLayer; + import java.util.HashMap; public class DashboardState { public ComposerState composer; - public boolean showResponse; - public int statusCode; + public ResponseLayer visibleLayer; + + // ResponseLayer parameters + public int responseCode; public String responseType; public String responseBody; public int responseTime; public int responseSize; + + // ErrorLayer parameters + public String errorTitle; + public String errorDetails; + public HashMap responseHeaders; public DashboardState() { From c739f2133775bf29291ac0a7b8bfce84c04c14ec Mon Sep 17 00:00:00 2001 From: Rohit Awate Date: Tue, 24 Jul 2018 15:52:31 +0530 Subject: [PATCH 14/45] Add LoadingLayer maintenance while switching tabs --- .../controllers/DashboardController.java | 6 +- .../controllers/state/DashboardState.java | 83 ++++++++++++++++++- .../requestmanager/RequestManager.java | 4 + .../resources/fxml/homewindow/Dashboard.fxml | 18 ++-- 4 files changed, 99 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java index 5b1a69d..96a33f8 100644 --- a/src/main/java/com/rohitawate/everest/controllers/DashboardController.java +++ b/src/main/java/com/rohitawate/everest/controllers/DashboardController.java @@ -188,9 +188,6 @@ public class DashboardController implements Initializable { responseArea.setMode(mode); }); - errorTitle.setText("Oops... That's embarrassing!"); - errorDetails.setText("Something went wrong. Try to make another request.\nRestart Everest if that doesn't work."); - visualizer = new Visualizer(); visualizerTab.setContent(visualizer); @@ -657,6 +654,9 @@ public class DashboardController implements Initializable { dashboardState.errorTitle = errorTitle.getText(); dashboardState.errorDetails = errorDetails.getText(); break; + case LOADING: + dashboardState.setRequestManager(requestManager); + break; } return dashboardState; diff --git a/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java b/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java index 0981c2d..8762d09 100644 --- a/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java +++ b/src/main/java/com/rohitawate/everest/controllers/state/DashboardState.java @@ -17,7 +17,20 @@ package com.rohitawate.everest.controllers.state; import com.rohitawate.everest.controllers.DashboardController.ResponseLayer; +import com.rohitawate.everest.exceptions.RedirectException; +import com.rohitawate.everest.exceptions.UnreliableResponseException; +import com.rohitawate.everest.misc.Services; +import com.rohitawate.everest.models.requests.EverestRequest; +import com.rohitawate.everest.models.responses.EverestResponse; +import com.rohitawate.everest.requestmanager.DataDispatchRequestManager; +import com.rohitawate.everest.requestmanager.RequestManager; +import javafx.concurrent.WorkerStateEvent; +import javafx.event.Event; +import javax.ws.rs.ProcessingException; +import java.io.FileNotFoundException; +import java.net.MalformedURLException; +import java.time.LocalDateTime; import java.util.HashMap; public class DashboardState { @@ -30,12 +43,40 @@ public class DashboardState { public String responseBody; public int responseTime; public int responseSize; + public HashMap responseHeaders; // ErrorLayer parameters public String errorTitle; public String errorDetails; - public HashMap responseHeaders; + // ResponseLayer parameters + private RequestManager requestManager; + + public void setRequestManager(RequestManager manager) { + this.requestManager = manager; + requestManager.removeEventHandler(WorkerStateEvent.WORKER_STATE_SUCCEEDED, requestManager.getOnSucceeded()); + requestManager.removeEventHandler(WorkerStateEvent.WORKER_STATE_FAILED, requestManager.getOnFailed()); + + requestManager.setOnFailed(this::onRequestFailed); + requestManager.setOnSucceeded(this::onRequestSucceeded); + } + + private void onRequestSucceeded(Event e) { + this.visibleLayer = ResponseLayer.RESPONSE; + EverestResponse response = requestManager.getValue(); + responseCode = response.getStatusCode(); + responseType = response.getMediaType().toString(); + responseTime = (int) response.getTime(); + responseSize = response.getSize(); + responseBody = response.getBody(); + + if (responseHeaders == null) + responseHeaders = new HashMap<>(); + else + responseHeaders.clear(); + + response.getHeaders().forEach((key, value) -> responseHeaders.put(key, value.get(0))); + } public DashboardState() { } @@ -43,4 +84,44 @@ public class DashboardState { public DashboardState(ComposerState composer) { this.composer = composer; } + + private void onRequestFailed(Event e) { + this.visibleLayer = ResponseLayer.ERROR; + Throwable throwable = requestManager.getException(); + Exception exception = (Exception) throwable; + Services.loggingService.logWarning(this.composer.httpMethod + " request could not be processed.", exception, LocalDateTime.now()); + + if (throwable.getClass() == UnreliableResponseException.class) { + UnreliableResponseException URE = (UnreliableResponseException) throwable; + errorTitle = URE.getExceptionTitle(); + errorDetails = URE.getExceptionDetails(); + } else if (throwable.getClass() == ProcessingException.class) { + errorTitle = "Everest couldn't connect."; + errorDetails = "Either you are not connected to the Internet or the server is offline."; + } else if (throwable.getClass() == RedirectException.class) { + RedirectException redirect = (RedirectException) throwable; + this.composer.target = redirect.getNewLocation(); + EverestRequest request = requestManager.getRequest(); + try { + request.setTarget(redirect.getNewLocation()); + requestManager.restart(); + } catch (MalformedURLException MURLE) { + Services.loggingService.logInfo("Invalid URL: " + this.composer.target, LocalDateTime.now()); + } + + return; + } + + if (requestManager.getClass() == DataDispatchRequestManager.class) { + if (throwable.getCause() != null && throwable.getCause().getClass() == IllegalArgumentException.class) { + errorTitle = "Did you forget something?"; + errorDetails = "Please specify a body for your " + this.composer.httpMethod + " request."; + } else if (throwable.getClass() == FileNotFoundException.class) { + errorTitle = "File(s) not found:"; + errorDetails = throwable.getMessage(); + } + } + + requestManager.reset(); + } } diff --git a/src/main/java/com/rohitawate/everest/requestmanager/RequestManager.java b/src/main/java/com/rohitawate/everest/requestmanager/RequestManager.java index 569ed23..b1d4431 100644 --- a/src/main/java/com/rohitawate/everest/requestmanager/RequestManager.java +++ b/src/main/java/com/rohitawate/everest/requestmanager/RequestManager.java @@ -68,6 +68,10 @@ public abstract class RequestManager extends Service { appendHeaders(); } + public EverestRequest getRequest() { + return this.request; + } + private void appendHeaders() { HashMap headers = request.getHeaders(); Map.Entry mapEntry; diff --git a/src/main/resources/fxml/homewindow/Dashboard.fxml b/src/main/resources/fxml/homewindow/Dashboard.fxml index aef9b25..59b8341 100644 --- a/src/main/resources/fxml/homewindow/Dashboard.fxml +++ b/src/main/resources/fxml/homewindow/Dashboard.fxml @@ -145,12 +145,12 @@ - + - + @@ -236,7 +236,7 @@ - + - +