commit 26feb57f493e75c5a9847733d13a5b21e16efc43
Author: Pavel Fidranský <fidransky@outlook.com>
Date:   Tue Aug 28 12:50:38 2018 +0200

    minor frontend changes

diff --git a/sources/src/main/webapp/css/main.css b/sources/src/main/webapp/css/main.css
index 074564f..844de49 100644
--- a/sources/src/main/webapp/css/main.css
+++ b/sources/src/main/webapp/css/main.css
@@ -6,72 +6,67 @@ body {
     overflow: hidden;
 }
 
-.hidden {
-	display: none !important;
+ul {
+	list-style: none;
+	padding-left: 0;
 }
 
-.header {
-    width: 100%;
-    background: -webkit-linear-gradient(top, #f0f9ff 0%,#cbebff 47%,#a1dbff 100%);
+.hidden {
+	display: none !important;
 }
 
 .row {
 	display: flex;
 }
 
-.upload-content {
-	text-align: center;
+.form-field {
+	margin-bottom: 20px;
 }
 
-.upload-content ul {
-	list-style: none;
-	padding-left: 0;
-}
+/**
+ * UPLOAD SCREEN
+ */
 
-#logged_user_menu {
+.upload-form {
     width: 200px;
-    padding: 20px 10px;
-    float: left;
-    text-align: left;
-    height: 500px;
-    background: #CFEAFE;
-    box-shadow: 3px 3px 10px #888;
-}
-
-.upload-forms {
-    display: inline-block;
-    min-height: 150px;
-    text-align: left;
     margin: 20px auto;
     padding: 10px;
     background-color: #CFEAFE;
     box-shadow: 3px 3px 10px #888;
 }
 
-.upload-forms input[type="submit"] {
+.upload-form button[type="submit"] {
 	display: block;
-	width: 200px;
-	margin: 0 auto;
+	width: 100%;
 }
 
-#uploadedComponent li {
-    padding: 8px 5px;
-    min-width: 450px;
-    background: #f5f4f4;
+.diagrams-menu {
+	width: 200px;
+    margin: 20px auto;
+	padding: 10px;
+	background-color: #CFEAFE;
+	box-shadow: 3px 3px 10px #888;
 }
 
-#uploadedComponent li:nth-child(odd) {
-    background: #e0dfdf;
+.diagrams-menu li button {
+	float: right;
+    width: 20px;
+    height: 20px;
+    padding: 0;
 }
 
-#uploadedComponent #deleteAll {
-    margin-bottom: 20px;
+.diagrams-menu li img {
+	max-width: 100%;
 }
 
-.imgDelete {
-    width: 16px;
-    height: 16px;
-    float: right;
+/**
+ * HEADER
+ */
+
+.header {
+    position: relative;
+    width: 100%;
+    background: -webkit-linear-gradient(top, #f0f9ff 0%,#cbebff 47%,#a1dbff 100%);
 }
 
 .header-logo {
@@ -148,6 +143,10 @@ body {
 	line-height: 30px;
 }
 
+/**
+ * NAVBAR
+ */
+
 .navbar {
     background: -webkit-linear-gradient(top, #1e5799 0%,#7db9e8 100%);
     color: #cceefc;
@@ -224,6 +223,10 @@ body {
     vertical-align: middle;
 }
 
+/**
+ * LOADER
+ */
+
 .loader {
     position: absolute;
     top: 0;
@@ -248,6 +251,10 @@ body {
 	display: none;
 }
 
+/**
+ * GRAPH
+ */
+
 .graph-content {
 	display: flex;
 	height: calc(100vh - 60px - 43px);
@@ -341,6 +348,10 @@ body {
 	pointer-events: bounding-box;
 }
 
+/**
+ * CONTEXT MENU
+ */
+
 .context-menu {
 	position: absolute;
 	font-family: 'Arial', sans-serif;
@@ -378,7 +389,11 @@ body {
 	vertical-align: -3px;
 }
 
-.popover {
+/**
+ * POPOVER
+ */
+
+ .popover {
 	position: absolute;
 	z-index: 1;
 	font-family: 'Arial', sans-serif;
@@ -401,7 +416,11 @@ body {
 	padding: 0 0.5em 0.5em 0.5em;
 }
 
-.viewport .neighbour-node-symbol {
+/**
+ * VIEWPORT
+ */
+
+ .viewport .neighbour-node-symbol {
     stroke: #000;
     stroke-width: 1;
 }
@@ -414,6 +433,11 @@ body {
 	user-select: none;
 }
 
+.viewport .group .group-viewport {
+	stroke: #000;
+	stroke-width: 0;
+}
+
 .viewport .group .group-symbol {
 	font-size: 48px;
 }
@@ -450,6 +474,10 @@ body {
 	display: none;
 }
 
+.viewport .group:not(.group--expanded) .group-viewport {
+    display: none;
+}
+
 .viewport .group--expanded .expand-button {
 	display: none;
 }
@@ -462,6 +490,10 @@ body {
 	width: 220px;
 }
 
+/**
+ * SIDEBAR
+ */
+
 .sidebar {
 	display: flex;
 	flex-basis: 350px;
@@ -706,6 +738,8 @@ body {
     display: none;
 }
 
+/* sorting */
+
 .sort-list {
 	font-size: 0.8em;
 	list-style: none;
@@ -733,6 +767,8 @@ body {
 	content: "▼";
 }
 
+/* minimap */
+
 .minimap {
 	border-top: 1px solid #7db9e8;
 	background-color: #fff;
@@ -750,6 +786,8 @@ body {
 	stroke: #000;
 }
 
+/* status bar */
+
 .status-bar {
     font-size: 11px;
     z-index: 1;
@@ -768,37 +806,6 @@ body {
 	cursor: pointer;
 }
 
-/**
- * MODAL WINDOW
- **/
-
-.modal {
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    left: 0;
-	right: 0;
-	padding: 20px 40px;
-    background: rgba(255, 255, 255, 0.7);
-}
-
-.modal-content {
-	position: relative;
-    height: 100%;
-    background-color: #fff;
-    border: 1px solid #7db9e8;
-}
-
-.modal-content .close-button {
-	position: absolute;
-	top: 10px;
-	right: 10px;
-	display: block;
-    width: 20px;
-    height: 20px;
-    padding: 0;
-}
-
 /**
  * TOOLTIP
  **/
diff --git a/sources/src/main/webapp/js/app.js b/sources/src/main/webapp/js/app.js
index 85ae958..c231543 100644
--- a/sources/src/main/webapp/js/app.js
+++ b/sources/src/main/webapp/js/app.js
@@ -268,7 +268,7 @@ function App() {
 				document.getElementById('applyLayoutImg').setAttribute('src', 'images/layout_on.png');
 
 				layouting = true;
-				layoutingInterval = window.setInterval(app.viewportComponent.forceDirected.run, 10);
+				layoutingInterval = window.setInterval(self.viewportComponent.forceDirected.run, 10);
 			}
 		});
 		
diff --git a/sources/src/main/webapp/js/components/attribute.js b/sources/src/main/webapp/js/components/attribute.js
index 4eae0eb..01857c3 100644
--- a/sources/src/main/webapp/js/components/attribute.js
+++ b/sources/src/main/webapp/js/components/attribute.js
@@ -1,5 +1,5 @@
 /**
- * TODO: jsDoc
+ * Class representing an attribute of vertex/edge. Output is formatted based on attribute name and datatype of its value.
  * @constructor
  * @param {array} props Details of the attribute.
  */
diff --git a/sources/src/main/webapp/js/components/group.js b/sources/src/main/webapp/js/components/group.js
index 5c31520..ecf125c 100644
--- a/sources/src/main/webapp/js/components/group.js
+++ b/sources/src/main/webapp/js/components/group.js
@@ -163,6 +163,8 @@ function Group(props) {
 	 * @returns {array<Edge>} List of all edges related to vertices added to the group.
 	 */
 	this.getEdgeList = function() {
+		// TODO: some edges get duplicated in the resulting array this way
+
 		return [].concat(this.getInEdgeList(), this.getOutEdgeList());
 	};
 
diff --git a/sources/src/main/webapp/js/components/minimap.js b/sources/src/main/webapp/js/components/minimap.js
index fab59ce..029d08b 100644
--- a/sources/src/main/webapp/js/components/minimap.js
+++ b/sources/src/main/webapp/js/components/minimap.js
@@ -1,20 +1,21 @@
 /**
+ * Class representing minimap of the viewport displayed in sidebar. It is used to have a quick overview of the current viewport layout.
  * @constructor
  */
 function Minimap() {
 	var rootElement;
 	var viewportElement;
 
-	var zoom = 0.1;
+	var scale = 0.1;
 	var useElement = '#graph';
 
 	/**
-	 * 
+	 * Resizes the minimap viewport using current viewport size and minimap scale.
 	 * @param {object} size Object holding current dimensions of the viewport component.
 	 */
 	this.setViewportSize = function(size) {
-		viewportElement.setAttribute('width', size.width * zoom);
-		viewportElement.setAttribute('height', size.height * zoom);
+		viewportElement.setAttribute('width', size.width * scale);
+		viewportElement.setAttribute('height', size.height * scale);
 	};
 
 	/**
@@ -28,12 +29,12 @@ function Minimap() {
 	};
 
 	/**
-	 * TODO: jsDoc
+	 * Moves the minimap viewport to a new position based on current viewport position and minimap scale.
 	 * @param {Coordinates} coords Coordinates of the viewport.
 	 */
 	this.setViewportPosition = function(coords) {
-		viewportElement.setAttribute('x', coords.x * -1 * zoom);
-		viewportElement.setAttribute('y', coords.y * -1 * zoom);
+		viewportElement.setAttribute('x', coords.x * -1 * scale);
+		viewportElement.setAttribute('y', coords.y * -1 * scale);
 	};
 
 	/**
@@ -48,7 +49,7 @@ function Minimap() {
 		});
 
 		var graphElement = app.dom.createSvgElement('use', {
-			'transform': `scale(${zoom})`,
+			'transform': `scale(${scale})`,
 		});
 		graphElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', useElement);
 		rootElement.appendChild(graphElement);
@@ -78,7 +79,7 @@ function Minimap() {
 			viewportElement.setAttribute('x', minimapViewportPosition.x - offset.x);
 			viewportElement.setAttribute('y', minimapViewportPosition.y - offset.y);
 
-			app.viewportComponent.setPosition(new Coordinates(viewportPosition.x + (1 / zoom) * offset.x, viewportPosition.y + (1 / zoom) * offset.y));
+			app.viewportComponent.setPosition(new Coordinates(viewportPosition.x + (1 / scale) * offset.x, viewportPosition.y + (1 / scale) * offset.y));
 		}
 
 		function mouseUp(e) {
diff --git a/sources/src/main/webapp/js/utils/utils.js b/sources/src/main/webapp/js/utils/utils.js
index 0404ded..57c2bd6 100644
--- a/sources/src/main/webapp/js/utils/utils.js
+++ b/sources/src/main/webapp/js/utils/utils.js
@@ -53,7 +53,7 @@ function Utils() {
 
 	/**
 	 * Returns a new promise that is resolved at the moment when all promises passed as function parameter are resolved.
-	 * https://stackoverflow.com/a/35825493
+	 * {@link https://stackoverflow.com/a/35825493}
 	 * 
 	 * @param promises Array of promises to wait for.
 	 * @return New promise.
diff --git a/sources/src/main/webapp/uploadFiles.jsp b/sources/src/main/webapp/uploadFiles.jsp
index 3e981a1..fce3466 100644
--- a/sources/src/main/webapp/uploadFiles.jsp
+++ b/sources/src/main/webapp/uploadFiles.jsp
@@ -27,20 +27,21 @@
 			<%@ include file="userMenu.jsp" %>
 		</header>
 
-		<main class="upload-content">
-			<div class="upload-forms">
+		<main>
+			<div class="upload-form">
+				<h3>New diagram</h3>
+
 				<c:if test="${not empty errorMessage}">
 					<p class="alert">${errorMessage}</p>
 				</c:if>
 
-				<strong>Upload SPADe data:</strong>
-
 				<form method="post" enctype="multipart/form-data">
 					<div class="form-field">
-						<input type="file" name="file">
+						<label for="file">Select SPADe data file:</label><br>
+						<input type="file" name="file" id="file">
 					</div>
 
-					<input type="submit" value="Start visualization">
+					<button type="submit">Start visualization</button>
 				</form>
 			</div>
 
