From 6d7b065e9898e75069aa11035f9a090ffe97f32d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Przemek=20Draga=C5=84czuk?= <draganczukp@gmail.com>
Date: Sun, 16 Feb 2020 16:52:54 +0100
Subject: [PATCH] Added option to delete a URL

---
 src/main/java/tk/draganczuk/url/App.java     |  1 +
 src/main/java/tk/draganczuk/url/Routes.java  | 13 +++++++
 src/main/java/tk/draganczuk/url/UrlFile.java | 36 ++++++++++++++++----
 src/main/resources/public/index.html         |  1 +
 src/main/resources/public/js/main.js         | 17 +++++++++
 5 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/src/main/java/tk/draganczuk/url/App.java b/src/main/java/tk/draganczuk/url/App.java
index 93a220a..603e690 100644
--- a/src/main/java/tk/draganczuk/url/App.java
+++ b/src/main/java/tk/draganczuk/url/App.java
@@ -36,6 +36,7 @@ public class App {
 			before("/*", authFilter);
 			get("/all", Routes::getAll);
 			post("/new", Routes::addUrl);
+			delete("/:shortUrl", Routes::delete);
 		});
 
 		get("/:shortUrl", Routes::goToLongUrl);
diff --git a/src/main/java/tk/draganczuk/url/Routes.java b/src/main/java/tk/draganczuk/url/Routes.java
index 2ad5fd1..2e9b590 100644
--- a/src/main/java/tk/draganczuk/url/Routes.java
+++ b/src/main/java/tk/draganczuk/url/Routes.java
@@ -54,4 +54,17 @@ public class Routes {
 		return "";
 	}
 
+	public static String delete(Request req, Response res) {
+		String shortUrl = req.params("shortUrl");
+		var longUrlOpt = urlFile
+				.findForShortUrl(shortUrl);
+
+		if (longUrlOpt.isEmpty()) {
+			res.status(404);
+			return "";
+		}
+
+		urlFile.deleteEntry(String.format("%s,%s", shortUrl, longUrlOpt.get()));
+		return "";
+	}
 }
diff --git a/src/main/java/tk/draganczuk/url/UrlFile.java b/src/main/java/tk/draganczuk/url/UrlFile.java
index 858a5e2..f666fb2 100644
--- a/src/main/java/tk/draganczuk/url/UrlFile.java
+++ b/src/main/java/tk/draganczuk/url/UrlFile.java
@@ -3,6 +3,7 @@ package tk.draganczuk.url;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
 import java.nio.file.StandardOpenOption;
 import java.util.List;
 import java.util.Optional;
@@ -41,18 +42,41 @@ public class UrlFile {
 
 	public Optional<String> findForShortUrl(String shortUrl){
 		try {
-			return  Files.lines(file.toPath())
-				.map(this::splitLine)
-				.filter(pair -> pair.getLeft().equals(shortUrl))
-				.map(Pair::getRight)
-				.findAny();
+			return Files.lines(file.toPath())
+					.map(this::splitLine)
+					.filter(pair -> pair.getLeft().equals(shortUrl))
+					.map(Pair::getRight)
+					.findAny();
 		} catch (IOException e) {
 			return Optional.empty();
 		}
 	}
 
-	public Pair<String, String> splitLine(String line){
+	public Pair<String, String> splitLine(String line) {
 		var split = line.split(",");
 		return new Pair<>(split[0], split[1]);
 	}
+
+	public void deleteEntry(String entry) {
+		try {
+			File tmp = File.createTempFile(file.getName(), ".tmp");
+			if (!tmp.exists()) {
+				tmp.createNewFile();
+			}
+
+			Files.lines(file.toPath())
+					.filter(line -> !line.equals(entry))
+					.forEach(line -> {
+						try {
+							Files.writeString(tmp.toPath(), line + "\n", StandardOpenOption.APPEND);
+						} catch (IOException e) {
+							e.printStackTrace();
+						}
+					});
+
+			Files.move(tmp.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
 }
diff --git a/src/main/resources/public/index.html b/src/main/resources/public/index.html
index 897ebb3..15e29e4 100644
--- a/src/main/resources/public/index.html
+++ b/src/main/resources/public/index.html
@@ -50,6 +50,7 @@
         <tr>
             <td>Long URL</td>
             <td>Short url</td>
+            <td></td>
         </tr>
         </thead>
         <tbody id="url-table">
diff --git a/src/main/resources/public/js/main.js b/src/main/resources/public/js/main.js
index 850ff4e..a3c335a 100644
--- a/src/main/resources/public/js/main.js
+++ b/src/main/resources/public/js/main.js
@@ -23,9 +23,11 @@ const TR = (row) => {
     const tr = document.createElement("tr");
     const longTD = TD(A(row.long));
     const shortTD = TD(A_INT(row.short));
+    const btn = deleteButton(row.short);
 
     tr.appendChild(longTD);
     tr.appendChild(shortTD);
+    tr.appendChild(btn);
 
     return tr;
 };
@@ -33,6 +35,21 @@ const TR = (row) => {
 const A = (s) => `<a href='${s}'>${s}</a>`;
 const A_INT = (s) => `<a href='/${s}'>${window.location.host}/${s}</a>`;
 
+const deleteButton = (shortUrl) => {
+    const btn = document.createElement("button");
+
+    btn.innerHTML = "&times;";
+
+    btn.onclick = e => {
+        e.preventDefault();
+        fetch(`/api/${shortUrl}`, {
+            method: "DELETE"
+        }).then(_ => refreshData());
+    };
+
+    return btn;
+};
+
 const TD = (s) => {
     const td = document.createElement("td");
     td.innerHTML = s;