From cf1b3f3607d0c4c370a79d42300e1dd6cfc251fc Mon Sep 17 00:00:00 2001 From: azkahi <azkaimtiyaz@gmail.com> Date: Wed, 30 Nov 2016 05:36:23 +0800 Subject: [PATCH] Added retrieval of status and indicator whether they're online --- .../java/org/ChatService/RetrieveStatus.java | 120 +++ .../src/java/org/ChatService/TokenSaver.java | 17 +- KAA-JSP/build/web/catalog.jsp | 733 +++++++++--------- KAA-JSP/build/web/css/style.css | 8 +- KAA-JSP/web/catalog.jsp | 733 +++++++++--------- KAA-JSP/web/css/style.css | 8 +- KAA-JSP/web/img/off.png | Bin 0 -> 2565 bytes KAA-JSP/web/img/on.png | Bin 0 -> 12351 bytes 8 files changed, 883 insertions(+), 736 deletions(-) create mode 100644 ChatService/src/java/org/ChatService/RetrieveStatus.java create mode 100644 KAA-JSP/web/img/off.png create mode 100644 KAA-JSP/web/img/on.png diff --git a/ChatService/src/java/org/ChatService/RetrieveStatus.java b/ChatService/src/java/org/ChatService/RetrieveStatus.java new file mode 100644 index 0000000..be0ba34 --- /dev/null +++ b/ChatService/src/java/org/ChatService/RetrieveStatus.java @@ -0,0 +1,120 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.ChatService; + +import java.io.IOException; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.json.simple.JSONObject; + +/** + * + * @author Azka Hanif Imtiyaz + */ +@WebServlet(name = "RetrieveStatus", urlPatterns = {"/RetrieveStatus"}) +public class RetrieveStatus extends HttpServlet { + + /** + * Processes requests for both HTTP <code>GET</code> and <code>POST</code> + * methods. + * + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + protected void processRequest(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + JSONObject json = new JSONObject(); + try { + Connection conn = DBChatToken.getConnection(); + if (conn != null) { + Statement stmt = conn.createStatement(); + String sql; + String user_id = request.getParameter("user_id"); + sql = "SELECT * FROM chattoken WHERE user_id =" + user_id; + ResultSet rs = stmt.executeQuery(sql); + + if (rs.next()){ + json.put("status", "ON"); + } else { + json.put("status", "OFF"); + } + + PrintWriter out = response.getWriter(); + + out.print(json.toString()); + } else { + try (PrintWriter out = response.getWriter()) { + /* TODO output your page here. You may use following sample code. */ + out.println("<!DOCTYPE html>"); + out.println("<html>"); + out.println("<head>"); + out.println("<title>Servlet login</title>"); + out.println("</head>"); + out.println("<body>"); + out.println("<h1>Connection NULL!!</h1>"); + out.println("</body>"); + out.println("</html>"); + } + } + } catch (SQLException ex) { + Logger.getLogger(TokenSaver.class.getName()).log(Level.SEVERE, null, ex); + } + } + + // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."> + /** + * Handles the HTTP <code>GET</code> method. + * + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } + + /** + * Handles the HTTP <code>POST</code> method. + * + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } + + /** + * Returns a short description of the servlet. + * + * @return a String containing servlet description + */ + @Override + public String getServletInfo() { + return "Short description"; + }// </editor-fold> + +} diff --git a/ChatService/src/java/org/ChatService/TokenSaver.java b/ChatService/src/java/org/ChatService/TokenSaver.java index 0b76821..1163e51 100644 --- a/ChatService/src/java/org/ChatService/TokenSaver.java +++ b/ChatService/src/java/org/ChatService/TokenSaver.java @@ -5,7 +5,6 @@ package org.ChatService; * To change this template file, choose Tools | Templates * and open the template in the editor. */ - import org.ChatService.DBChatToken; import java.io.IOException; import java.io.PrintWriter; @@ -21,7 +20,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.json.simple.JSONObject; - /** * * @author khrs @@ -46,21 +44,25 @@ public class TokenSaver extends HttpServlet { JSONObject json = new JSONObject(); try { Connection conn = DBChatToken.getConnection(); - if (conn != null){ + if (conn != null) { Statement stmt = conn.createStatement(); String sql; String user_id = request.getParameter("user_id"); String chattoken = request.getParameter("chattoken"); - sql = "insert into chattoken values (\""+ chattoken+ "\",\""+user_id+"\")"; + sql = "insert into chattoken values (\"" + chattoken + "\",\"" + user_id + "\")"; stmt.executeUpdate(sql); - } - else{ + + PrintWriter out = response.getWriter(); + + json.put("status", "ON"); + out.print(json.toString()); + } else { try (PrintWriter out = response.getWriter()) { /* TODO output your page here. You may use following sample code. */ out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); - out.println("<title>Servlet login</title>"); + out.println("<title>Servlet login</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Connection NULL!!</h1>"); @@ -85,7 +87,6 @@ public class TokenSaver extends HttpServlet { out.println("</body>"); out.println("</html>"); }*/ - } // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."> diff --git a/KAA-JSP/build/web/catalog.jsp b/KAA-JSP/build/web/catalog.jsp index de004ad..0ea015e 100644 --- a/KAA-JSP/build/web/catalog.jsp +++ b/KAA-JSP/build/web/catalog.jsp @@ -22,11 +22,11 @@ <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> - <title>Sale Project - Catalog</title> - <link href="css/style.css" rel="stylesheet" type="text/css"> + <title>Sale Project - Catalog</title> + <link href="css/style.css" rel="stylesheet" type="text/css"> <!-- Firebase --> <script src="https://www.gstatic.com/firebasejs/3.6.1/firebase.js"></script> - <!--Angular --> + <!--Angular --> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> <!--<script src="https://cdn.firebase.com/js/client/2.0.4/firebase.js"></script>--> <!--<script src="https://www.gstatic.com/firebasejs/3.6.1/firebase-app.js"></script> @@ -35,400 +35,407 @@ <script src="https://www.gstatic.com/firebasejs/3.6.1/firebase-messaging.js"></script> <!-- <script src="https://www.gstatic.com/firebasejs/3.6.1/firebase-storage.js"></script> --> <!-- AngularFire --> -<!-- <script src="https://cdn.firebase.com/libs/angularfire/0.9.2/angularfire.min.js"></script>--> - + <!-- <script src="https://cdn.firebase.com/libs/angularfire/0.9.2/angularfire.min.js"></script>--> + <script> - // Initialize Firebase + // Initialize Firebase + + /*var config = { + apiKey: "AIzaSyAN43gCcqFx095nCBy-4abeRGkoZB1-Rok", + authDomain: "kaa-saleproject.firebaseapp.com", + databaseURL: "https://kaa-saleproject.firebaseio.com", + storageBucket: "kaa-saleproject.appspot.com", + messagingSenderId: "815161898662" + };*/ + /* var config = { + apiKey: "AIzaSyAQ2WIB6GWOxmtwMdGd8eHawL4PWxK8evU", + authDomain: "tugas-besar-wbd.firebaseapp.com", + databaseURL: "https://tugas-besar-wbd.firebaseio.com", + storageBucket: "tugas-besar-wbd.appspot.com", + messagingSenderId: "1049009619420" + }; + firebase.initializeApp(config); + + const messaging = firebase.messaging(); + messaging.requestPermission() + .then(function() { + console.log('Notification permission granted.'); + return messaging.getToken(); + // TODO(developer): Retrieve an Instance ID token for use with FCM. + // ... + }) + .then(function(token){ + console.log(token); + }) + .catch(function(err) { + console.log('Unable to get permission to notify.', err); + });*/ + - /*var config = { - apiKey: "AIzaSyAN43gCcqFx095nCBy-4abeRGkoZB1-Rok", - authDomain: "kaa-saleproject.firebaseapp.com", - databaseURL: "https://kaa-saleproject.firebaseio.com", - storageBucket: "kaa-saleproject.appspot.com", - messagingSenderId: "815161898662" - };*/ -/* var config = { - apiKey: "AIzaSyAQ2WIB6GWOxmtwMdGd8eHawL4PWxK8evU", - authDomain: "tugas-besar-wbd.firebaseapp.com", - databaseURL: "https://tugas-besar-wbd.firebaseio.com", - storageBucket: "tugas-besar-wbd.appspot.com", - messagingSenderId: "1049009619420" - }; - firebase.initializeApp(config); - - const messaging = firebase.messaging(); - messaging.requestPermission() - .then(function() { - console.log('Notification permission granted.'); - return messaging.getToken(); - // TODO(developer): Retrieve an Instance ID token for use with FCM. - // ... - }) - .then(function(token){ - console.log(token); - }) - .catch(function(err) { - console.log('Unable to get permission to notify.', err); - });*/ - - - /*messaging.requestPermission().then(function(){ - console.log('Notification permission granted'); - messaging.getToken().then(function(){ - if(currentToken){ - sendTokenToServer(currentToken); - updateUIForPushEnabled(currentToken); - console.log('Token retrieved, ',currentToken); - //abis itu send ke tokensaver chatservice di sini atau di bawah - } else { - console.log('No Instance ID token available. Request permission to generate one'); - updateUIForPushPermissionRequired(); - setTokenToServer(false); - } - }).catch(function(err){ - console.log('An error occured while retrieving token. ',err); - showToken('Error retrieving Instance ID token. ',err); - setTokenToServer(false); - }); - }).catch(function(err){ - console.log('Unable to get permission to notify',err); - }); - - messaging.onTokenRefresh(function(){ - mesagging.getToken().then(function(refreshedToken){ - console.log('Token refreshed.'); - setTokenSentToServer(false); - sendTokenToServer(refreshedToken); - }); - }).catch(function(err){ - console.log('Unable to retrieve refreshed token. ',err); - showToken('Unable to retrieve refreshed token. ',err); - }); - - messaging.onMessage(function(payload){ - console.log("Message received. ",payload); - });*/ + /*messaging.requestPermission().then(function(){ + console.log('Notification permission granted'); + messaging.getToken().then(function(){ + if(currentToken){ + sendTokenToServer(currentToken); + updateUIForPushEnabled(currentToken); + console.log('Token retrieved, ',currentToken); + //abis itu send ke tokensaver chatservice di sini atau di bawah + } else { + console.log('No Instance ID token available. Request permission to generate one'); + updateUIForPushPermissionRequired(); + setTokenToServer(false); + } + }).catch(function(err){ + console.log('An error occured while retrieving token. ',err); + showToken('Error retrieving Instance ID token. ',err); + setTokenToServer(false); + }); + }).catch(function(err){ + console.log('Unable to get permission to notify',err); + }); + + messaging.onTokenRefresh(function(){ + mesagging.getToken().then(function(refreshedToken){ + console.log('Token refreshed.'); + setTokenSentToServer(false); + sendTokenToServer(refreshedToken); + }); + }).catch(function(err){ + console.log('Unable to retrieve refreshed token. ',err); + showToken('Unable to retrieve refreshed token. ',err); + }); + + messaging.onMessage(function(payload){ + console.log("Message received. ",payload); + });*/ </script> <!--Application --> <script src="scripts/app.js"></script> - + </head> <body ng-app="chatApp" ng-controller="chatController"> - <div class="catalog_content"> - <div class="logo"> - <span id="red">Sale</span><span id="blue">Project</span> - </div> - <div class="information"> - <span> - <% -/* FirebaseOptions options = new FirebaseOptions.Builder() - .setServiceAccount(new FileInputStream("path/to/serviceAccountKey.json")) - .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/") - .build(); + <div class="catalog_content"> + <div class="logo"> + <span id="red">Sale</span><span id="blue">Project</span> + </div> + <div class="information"> + <span> + <% + /* FirebaseOptions options = new FirebaseOptions.Builder() + .setServiceAccount(new FileInputStream("path/to/serviceAccountKey.json")) + .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/") + .build(); - FirebaseApp.initializeApp(options);*/ - - JSONObject responseJSON = new JSONObject(); - JSONObject responseJSON1 = new JSONObject(); - org.kaa.marketplaceservice.service.MarketPlaceService_Service service = new org.kaa.marketplaceservice.service.MarketPlaceService_Service(); - org.kaa.marketplaceservice.service.MarketPlaceService port = service.getMarketPlaceServicePort(); - String query; - String APIURL; - String ParameterURL; - - /* Showing username of user */ - String user_token = request.getParameter("token"); - if (request.getParameter("like") != null){ - String productId = request.getParameter("product_id"); - boolean like; - if (request.getParameter("like").equals("yes")){ - like = true; - } else { - like = false; - } - ProcedureStatus result = port.processLike(user_token, productId, like); - if (result.getStatus().equals("OK")){ - //Do nothing - } else if (result.getStatus().equals("EXPIRED")) { - response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" - + "message=Expired"); - } else { - response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." - + "jsp?token="+user_token+"&message=error"); - } - } - - if ((request.getParameter("logout") == null) && - (request.getParameter("token")!= null)){ - /* Consume REST API */ - ParameterURL = "token="+ request.getParameter("token"); - APIURL = "http://localhost:8080/IdentService/validate?"; - RestAPI_consumer consumer = new RestAPI_consumer(APIURL,ParameterURL); - consumer.execute(); - responseJSON = consumer.getOutput(); - - /* Checking the response */ - String status = (String)responseJSON.get("status"); - if (status.equals("OK")){ - String user = (String)responseJSON.get("user_name"); - out.println("Hello, " + user); - //out.println("<script>setUser('"+user+"');</script>"); - } - else{ - response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." - + "jsp?token="+user_token); - } - } - /* Logout */ - else if ((request.getParameter("logout") != null) && - (request.getParameter("token")!= null)){ - URL obj1 = null; - try{ - /* Consume REST API */ - ParameterURL = "token="+ user_token; - APIURL = "http://localhost:8080/IdentService/logout?"; - RestAPI_consumer consumer1 = new RestAPI_consumer(APIURL,ParameterURL); - consumer1.execute(); - responseJSON1 = consumer1.getOutput(); - - /* Checking the response */ - String status1 = (String)responseJSON1.get("status"); - if (status1.equals("OK")){ - response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" - + "message=logout"); - } - else{ - response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." - + "jsp?token="+user_token); - } - } - catch(Exception e){ - e.printStackTrace(); - } - } + FirebaseApp.initializeApp(options);*/ - /* Firebase here - String uid = "some-uid"; + JSONObject responseJSON = new JSONObject(); + JSONObject responseJSON1 = new JSONObject(); + org.kaa.marketplaceservice.service.MarketPlaceService_Service service = new org.kaa.marketplaceservice.service.MarketPlaceService_Service(); + org.kaa.marketplaceservice.service.MarketPlaceService port = service.getMarketPlaceServicePort(); + String query; + String APIURL; + String ParameterURL; - FirebaseAuth.getInstance().createCustomToken(uid) - .addOnSuccessListener(new OnSuccessListener<String>() { - @Override - public void onSuccess(String customToken) { - // Send token back to client - } - });*/ - %> - </span> + String urlParamChat; + String urlRequest2 = "http://localhost:8080/ChatService/RetrieveStatus?"; - </br> - <a href=" - <% - String logoutURL = "http://localhost:8080/KAA-JSP/catalog.jsp?token="+user_token+"&logout=on"; - out.println(logoutURL); - %> - " class="logout"><span class="link">Logout</span> - </a><br/> - </div> - <table class="menu"> - <th class="menupart" id="active"> - <a href=" - <% - out.println("http://localhost:8080/KAA-JSP/catalog.jsp?token="+user_token); - %> - "> - Catalog - </a> - </th> - <th class="menupart"> - <a href=" - <% - out.println("http://localhost:8080/KAA-JSP/yourproduct.jsp?token="+user_token); - %> - "> - Your Products - </a> - </th> - <th class="menupart"> - <a href=" - <% - out.println("http://localhost:8080/KAA-JSP/addproduct.jsp?token="+user_token); - %> - "> - Add Product - </a> - </th> - <th class="menupart"> - <a href=" - <% - out.println("http://localhost:8080/KAA-JSP/sales.jsp?token="+user_token); - %> - "> - Sales - </a> - </th> - <th class="menupart"> + /* Showing username of user */ + String user_token = request.getParameter("token"); + if (request.getParameter("like") != null) { + String productId = request.getParameter("product_id"); + boolean like; + if (request.getParameter("like").equals("yes")) { + like = true; + } else { + like = false; + } + ProcedureStatus result = port.processLike(user_token, productId, like); + if (result.getStatus().equals("OK")) { + //Do nothing + } else if (result.getStatus().equals("EXPIRED")) { + response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" + + "message=Expired"); + } else { + response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." + + "jsp?token=" + user_token + "&message=error"); + } + } + + if ((request.getParameter("logout") == null) + && (request.getParameter("token") != null)) { + /* Consume REST API */ + ParameterURL = "token=" + request.getParameter("token"); + APIURL = "http://localhost:8080/IdentService/validate?"; + RestAPI_consumer consumer = new RestAPI_consumer(APIURL, ParameterURL); + consumer.execute(); + responseJSON = consumer.getOutput(); + + /* Checking the response */ + String status = (String) responseJSON.get("status"); + if (status.equals("OK")) { + String user = (String) responseJSON.get("user_name"); + out.println("Hello, " + user); + //out.println("<script>setUser('"+user+"');</script>"); + } else { + response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." + + "jsp?token=" + user_token); + } + } /* Logout */ else if ((request.getParameter("logout") != null) + && (request.getParameter("token") != null)) { + URL obj1 = null; + try { + /* Consume REST API */ + ParameterURL = "token=" + user_token; + APIURL = "http://localhost:8080/IdentService/logout?"; + RestAPI_consumer consumer1 = new RestAPI_consumer(APIURL, ParameterURL); + consumer1.execute(); + responseJSON1 = consumer1.getOutput(); + + /* Checking the response */ + String status1 = (String) responseJSON1.get("status"); + if (status1.equals("OK")) { + response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" + + "message=logout"); + } else { + response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." + + "jsp?token=" + user_token); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /* Firebase here + String uid = "some-uid"; + + FirebaseAuth.getInstance().createCustomToken(uid) + .addOnSuccessListener(new OnSuccessListener<String>() { + @Override + public void onSuccess(String customToken) { + // Send token back to client + } + });*/ + %> + </span> + + </br> <a href=" - <% - out.println("http://localhost:8080/KAA-JSP/purchases.jsp?token="+user_token); + <% String logoutURL = "http://localhost:8080/KAA-JSP/catalog.jsp?token=" + user_token + "&logout=on"; + out.println(logoutURL); %> - ">Purchases - </a> - </th> - </table> - <br/> - <p class="title">What are you going to buy today?</p> - <hr/> - <br/> - <div class="add_product_content"> + " class="logout"><span class="link">Logout</span> + </a><br/> + </div> + <table class="menu"> + <th class="menupart" id="active"> + <a href=" + <% + out.println("http://localhost:8080/KAA-JSP/catalog.jsp?token=" + user_token); + %> + "> + Catalog + </a> + </th> + <th class="menupart"> + <a href=" + <% + out.println("http://localhost:8080/KAA-JSP/yourproduct.jsp?token=" + user_token); + %> + "> + Your Products + </a> + </th> + <th class="menupart"> + <a href=" + <% + out.println("http://localhost:8080/KAA-JSP/addproduct.jsp?token=" + user_token); + %> + "> + Add Product + </a> + </th> + <th class="menupart"> + <a href=" + <% + out.println("http://localhost:8080/KAA-JSP/sales.jsp?token=" + user_token); + %> + "> + Sales + </a> + </th> + <th class="menupart"> + <a href=" + <% + out.println("http://localhost:8080/KAA-JSP/purchases.jsp?token=" + user_token); + %> + ">Purchases + </a> + </th> + </table> + <br/> + <p class="title">What are you going to buy today?</p> + <hr/> + <br/> + <div class="add_product_content"> <form method="GET" enctype="multipart/form-data"> - <div class="input_catalog"> - <input type="hidden" name="token" value=<% - out.println(user_token); - %> > - <input type="text" placeholder="Search catalog ..." - name="search" style="width:90%; height: 35px; border:none;" - class="auto-style1" hidefocus="hidefocus"> - <input type="submit" value="GO" style="width: 10%; height: 35px; font-weight: bold"><br/> - by - <input class="radio" type="radio" name="choice" value="product" checked="checked" /> - <label><span>product</span></label><br /> - <input class="radio" type="radio" name="choice" value="store" style="margin-left:25px;" /> - <label><span>store</span></label> - </div> + <div class="input_catalog"> + <input type="hidden" name="token" value=<% + out.println(user_token); + %> > + <input type="text" placeholder="Search catalog ..." + name="search" style="width:90%; height: 35px; border:none;" + class="auto-style1" hidefocus="hidefocus"> + <input type="submit" value="GO" style="width: 10%; height: 35px; font-weight: bold"><br/> + by + <input class="radio" type="radio" name="choice" value="product" checked="checked" /> + <label><span>product</span></label><br /> + <input class="radio" type="radio" name="choice" value="store" style="margin-left:25px;" /> + <label><span>store</span></label> + </div> </form> - </div> - <% - if(request.getParameter("search") == null){ - // Ketika pertama kali membuka catalog (tidak ada parameter search) - List<Product> result = port.retrieveAllProduct(user_token); - - // Ketika token sudah expired - if (result == null){ - response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" - + "message=expired"); - } else { - if (result.size() == 0){ - out.print("<p>No product to be sold.</p>"); - } else { - for (int i = 0; i < result.size(); i++) { - out.print("<a href=\"\"><div ng-click=\"setReceiver('"+result.get(i).getUsername()+"')\"><p><b>" + result.get(i).getUsername() + "</a></b><br/>"); - out.print("added this on " + result.get(i).getDate().getDate() + "</p></div>"); - out.print("<hr/>"); - out.print("<table>"); - out.print("<tr class = \"container\">"); - out.print("<td>"); - out.print("<img \" width=120px height=120px src=\"" + result.get(i).getImage() + "\">"); - out.print("</td>"); - out.print("<td class=\"product_description\">"); - out.print("<p class=\"catalog_title\">" + result.get(i).getName() + " <br/></p>"); - out.print("<p class=\"catalog_price\">IDR " + result.get(i).getPrice() + "<br/></p>"); - out.print("<p class=\"catalog_desc\">" + result.get(i).getDescription() + "</p>"); - out.print("</td>"); - out.print("<td class=\"product_misc\">"); - out.print("<br/>"); - out.print("<p>" + port.getLikes(result.get(i).getProductId()) + " likes </p><br/>"); - out.print("<p>" + port.getPurchases(result.get(i).getProductId()) + " purchases <br/>"); - out.print(port.isLiked(user_token, result.get(i).getProductId())); - out.print("<a href=\"http://localhost:8080/KAA-JSP/confirmation_purchase.jsp?token=" + user_token + "&product_id=" + result.get(i).getProductId() + "\"><p id=\"buy\">BUY</a></p>"); - out.print("</td>"); - out.print("</tr>"); - out.print("</table>"); - out.print("<hr/>"); - out.print("<br/>"); - out.print("<br/>"); - } - } - } - } else { - // Ketika ada parameter untuk search - String search = request.getParameter("search"); - String choice = request.getParameter("choice"); - /* Melakukan Searching dengan Method search_product pada MarketService */ - try{ - int choice_int = 0; - if (choice.equals("product")){ - choice_int = 0; - } else if (choice.equals("store")) { - choice_int = 1; - } - - List<Product> result = port.searchProduct(search, user_token, choice_int); - - /* Jika expired */ - if (result == null){ + </div> + <% + if (request.getParameter("search") == null) { + // Ketika pertama kali membuka catalog (tidak ada parameter search) + List<Product> result = port.retrieveAllProduct(user_token); + + // Ketika token sudah expired + if (result == null) { response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" + "message=expired"); } else { - if (result.size() == 0){ - out.print("<p>Nothing matches your search.</p>"); + if (result.size() == 0) { + out.print("<p>No product to be sold.</p>"); } else { for (int i = 0; i < result.size(); i++) { - out.print("<a href=\"\"><div ng-click=\"setReceiver('"+result.get(i).getUsername()+"')\"><b>" + result.get(i).getUsername() + "</a></b></div><br/>"); + urlParamChat = "user_id=" + result.get(i).getUserId(); + RestAPI_consumer consumer2 = new RestAPI_consumer(urlRequest2, urlParamChat); + consumer2.execute(); + responseJSON = consumer2.getOutput(); + if (responseJSON.get("status").equals("ON")) { + out.print("<img style=\"border: none; padding: 0px 10px 0px 0px; float:left\" height=15px width=15px src=\"img/on.png\">"); + out.print("<a href=\"\"><div ng-click=\"setReceiver('" + result.get(i).getUsername() + "')\"><p><b>" + result.get(i).getUsername() + "</a></b><br/>"); + } else { + out.print("<img style=\"border: none; padding: 0px 10px 0px 0px; float:left\" height=15px width=15px src=\"img/off.png\">"); + out.print("<a href=\"\"><div ng-click=\"setReceiver('" + result.get(i).getUsername() + "')\"><p><b>" + result.get(i).getUsername() + "</a></b><br/>"); + } out.print("added this on " + result.get(i).getDate().getDate() + "</p></div>"); out.print("<hr/>"); out.print("<table>"); out.print("<tr class = \"container\">"); out.print("<td>"); - out.print("<img \" width=120px height=120px src=\"" + result.get(i).getImage() + "\">"); - out.print("</td>"); - out.print("<td class=\"product_description\">"); - out.print("<p class=\"catalog_title\">" + result.get(i).getName() + " <br/></p>"); - out.print("<p class=\"catalog_price\">IDR " + result.get(i).getPrice() + "<br/></p>"); - out.print("<p class=\"catalog_desc\">" + result.get(i).getDescription() + "</p>"); - out.print("</td>"); - out.print("<td class=\"product_misc\">"); - out.print("<br/>"); - out.print("<p>" + port.getLikes(result.get(i).getProductId()) + " likes </p><br/>"); - out.print("<p>" + port.getPurchases(result.get(i).getProductId()) + " purchases <br/>"); - out.print(port.isLiked(user_token, result.get(i).getProductId())); - out.print("<a href=\"http://localhost:8080/KAA-JSP/confirmation_purchase.jsp?token=" + user_token + "&product_id=" + result.get(i).getProductId() + "\"><p id=\"buy\">BUY</a></p>"); - out.print("</td>"); - out.print("</tr>"); - out.print("</table>"); - out.print("<hr/>"); - out.print("<br/>"); + out.print("<img \" width=120px height=120px src=\"" + result.get(i).getImage() + "\">"); + out.print("</td>"); + out.print("<td class=\"product_description\">"); + out.print("<p class=\"catalog_title\">" + result.get(i).getName() + " <br/></p>"); + out.print("<p class=\"catalog_price\">IDR " + result.get(i).getPrice() + "<br/></p>"); + out.print("<p class=\"catalog_desc\">" + result.get(i).getDescription() + "</p>"); + out.print("</td>"); + out.print("<td class=\"product_misc\">"); + out.print("<br/>"); + out.print("<p>" + port.getLikes(result.get(i).getProductId()) + " likes </p><br/>"); + out.print("<p>" + port.getPurchases(result.get(i).getProductId()) + " purchases <br/>"); + out.print(port.isLiked(user_token, result.get(i).getProductId())); + out.print("<a href=\"http://localhost:8080/KAA-JSP/confirmation_purchase.jsp?token=" + user_token + "&product_id=" + result.get(i).getProductId() + "\"><p id=\"buy\">BUY</a></p>"); + out.print("</td>"); + out.print("</tr>"); + out.print("</table>"); + out.print("<hr/>"); + out.print("<br/>"); out.print("<br/>"); } } } - } catch (Exception ex) { - // TODO handle custom exceptions here + } else { + // Ketika ada parameter untuk search + String search = request.getParameter("search"); + String choice = request.getParameter("choice"); + /* Melakukan Searching dengan Method search_product pada MarketService */ + try { + int choice_int = 0; + if (choice.equals("product")) { + choice_int = 0; + } else if (choice.equals("store")) { + choice_int = 1; + } + + List<Product> result = port.searchProduct(search, user_token, choice_int); + + /* Jika expired */ + if (result == null) { + response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" + + "message=expired"); + } else { + if (result.size() == 0) { + out.print("<p>Nothing matches your search.</p>"); + } else { + for (int i = 0; i < result.size(); i++) { + out.print("<a href=\"\"><div ng-click=\"setReceiver('" + result.get(i).getUsername() + "')\"><b>" + result.get(i).getUsername() + "</a></b></div><br/>"); + out.print("added this on " + result.get(i).getDate().getDate() + "</p></div>"); + out.print("<hr/>"); + out.print("<table>"); + out.print("<tr class = \"container\">"); + out.print("<td>"); + out.print("<img \" width=120px height=120px src=\"" + result.get(i).getImage() + "\">"); + out.print("</td>"); + out.print("<td class=\"product_description\">"); + out.print("<p class=\"catalog_title\">" + result.get(i).getName() + " <br/></p>"); + out.print("<p class=\"catalog_price\">IDR " + result.get(i).getPrice() + "<br/></p>"); + out.print("<p class=\"catalog_desc\">" + result.get(i).getDescription() + "</p>"); + out.print("</td>"); + out.print("<td class=\"product_misc\">"); + out.print("<br/>"); + out.print("<p>" + port.getLikes(result.get(i).getProductId()) + " likes </p><br/>"); + out.print("<p>" + port.getPurchases(result.get(i).getProductId()) + " purchases <br/>"); + out.print(port.isLiked(user_token, result.get(i).getProductId())); + out.print("<a href=\"http://localhost:8080/KAA-JSP/confirmation_purchase.jsp?token=" + user_token + "&product_id=" + result.get(i).getProductId() + "\"><p id=\"buy\">BUY</a></p>"); + out.print("</td>"); + out.print("</tr>"); + out.print("</table>"); + out.print("<hr/>"); + out.print("<br/>"); + out.print("<br/>"); + } + } + } + } catch (Exception ex) { + // TODO handle custom exceptions here + } } - } - %> + %> - {{user}} - <br> - <div class="popup-box chat-popup" id="1" ng-show="isReceiverSet()" style="right: 0px; display: block;"> - <div class="popup-head"> - <div class="popup-head-left">{{receiver}}</div> - <div class="popup-head-right" ng-click="setReceiver('')"><a href="">✕</a></div> - <div style="clear: both"></div> + {{user}} + <br> + <div class="popup-box chat-popup" id="1" ng-show="isReceiverSet()" style="right: 0px; display: block;"> + <div class="popup-head"> + <div class="popup-head-left">{{receiver}}</div> + <div class="popup-head-right" ng-click="setReceiver('')"><a href="">✕</a></div> + <div style="clear: both"></div> + </div> + <div class="popup-messages">Tes</div> + <div class="popup-input"> + <input type="text" style="height: 100%" name="chat" class="auto-style1" hidefocus="hidefocus" /> + </div> </div> - <div class="popup-messages">Tes</div> - <div class="popup-input"> - <input type="text" style="height: 100%" name="chat" class="auto-style1" hidefocus="hidefocus" /> - </div> - </div> - -<!-- <div ng-app="chatApp" ng-controller="chatController"> - <p>Name: <input type="text" ng-model="newmessage.user"></p> - <p>Message: <input type="text" ng-model="newmessage.text"></p> - <button ng-click="insert(newmessage)">Send</button> - - <ul> - <li ng-repeat="message in messages"> - {{message.user}} send: {{message.text}} - </li> - </ul> - </div> --> - - <script> - /*document.getElementById("catalog").style.background="#0066ff"; - document.getElementById("catalog").style.color="#ffffff";*/ - </script> + <!-- <div ng-app="chatApp" ng-controller="chatController"> + <p>Name: <input type="text" ng-model="newmessage.user"></p> + <p>Message: <input type="text" ng-model="newmessage.text"></p> + <button ng-click="insert(newmessage)">Send</button> + + <ul> + <li ng-repeat="message in messages"> + {{message.user}} send: {{message.text}} + </li> + </ul> + </div> --> + + + <script> + /*document.getElementById("catalog").style.background="#0066ff"; + document.getElementById("catalog").style.color="#ffffff";*/ + </script> </body> </html> diff --git a/KAA-JSP/build/web/css/style.css b/KAA-JSP/build/web/css/style.css index 60760a0..2a859c3 100644 --- a/KAA-JSP/build/web/css/style.css +++ b/KAA-JSP/build/web/css/style.css @@ -337,11 +337,17 @@ ul { margin: 0px 0px 0px 20px; padding: 0px 0px 0px 10px; } -ul li { + +ul li .on { color: green; list-style-type: disc; } +ul li .off { + color: gray; + list-style-type: disc; +} + ul li span{ color: black; } \ No newline at end of file diff --git a/KAA-JSP/web/catalog.jsp b/KAA-JSP/web/catalog.jsp index de004ad..0ea015e 100644 --- a/KAA-JSP/web/catalog.jsp +++ b/KAA-JSP/web/catalog.jsp @@ -22,11 +22,11 @@ <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> - <title>Sale Project - Catalog</title> - <link href="css/style.css" rel="stylesheet" type="text/css"> + <title>Sale Project - Catalog</title> + <link href="css/style.css" rel="stylesheet" type="text/css"> <!-- Firebase --> <script src="https://www.gstatic.com/firebasejs/3.6.1/firebase.js"></script> - <!--Angular --> + <!--Angular --> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> <!--<script src="https://cdn.firebase.com/js/client/2.0.4/firebase.js"></script>--> <!--<script src="https://www.gstatic.com/firebasejs/3.6.1/firebase-app.js"></script> @@ -35,400 +35,407 @@ <script src="https://www.gstatic.com/firebasejs/3.6.1/firebase-messaging.js"></script> <!-- <script src="https://www.gstatic.com/firebasejs/3.6.1/firebase-storage.js"></script> --> <!-- AngularFire --> -<!-- <script src="https://cdn.firebase.com/libs/angularfire/0.9.2/angularfire.min.js"></script>--> - + <!-- <script src="https://cdn.firebase.com/libs/angularfire/0.9.2/angularfire.min.js"></script>--> + <script> - // Initialize Firebase + // Initialize Firebase + + /*var config = { + apiKey: "AIzaSyAN43gCcqFx095nCBy-4abeRGkoZB1-Rok", + authDomain: "kaa-saleproject.firebaseapp.com", + databaseURL: "https://kaa-saleproject.firebaseio.com", + storageBucket: "kaa-saleproject.appspot.com", + messagingSenderId: "815161898662" + };*/ + /* var config = { + apiKey: "AIzaSyAQ2WIB6GWOxmtwMdGd8eHawL4PWxK8evU", + authDomain: "tugas-besar-wbd.firebaseapp.com", + databaseURL: "https://tugas-besar-wbd.firebaseio.com", + storageBucket: "tugas-besar-wbd.appspot.com", + messagingSenderId: "1049009619420" + }; + firebase.initializeApp(config); + + const messaging = firebase.messaging(); + messaging.requestPermission() + .then(function() { + console.log('Notification permission granted.'); + return messaging.getToken(); + // TODO(developer): Retrieve an Instance ID token for use with FCM. + // ... + }) + .then(function(token){ + console.log(token); + }) + .catch(function(err) { + console.log('Unable to get permission to notify.', err); + });*/ + - /*var config = { - apiKey: "AIzaSyAN43gCcqFx095nCBy-4abeRGkoZB1-Rok", - authDomain: "kaa-saleproject.firebaseapp.com", - databaseURL: "https://kaa-saleproject.firebaseio.com", - storageBucket: "kaa-saleproject.appspot.com", - messagingSenderId: "815161898662" - };*/ -/* var config = { - apiKey: "AIzaSyAQ2WIB6GWOxmtwMdGd8eHawL4PWxK8evU", - authDomain: "tugas-besar-wbd.firebaseapp.com", - databaseURL: "https://tugas-besar-wbd.firebaseio.com", - storageBucket: "tugas-besar-wbd.appspot.com", - messagingSenderId: "1049009619420" - }; - firebase.initializeApp(config); - - const messaging = firebase.messaging(); - messaging.requestPermission() - .then(function() { - console.log('Notification permission granted.'); - return messaging.getToken(); - // TODO(developer): Retrieve an Instance ID token for use with FCM. - // ... - }) - .then(function(token){ - console.log(token); - }) - .catch(function(err) { - console.log('Unable to get permission to notify.', err); - });*/ - - - /*messaging.requestPermission().then(function(){ - console.log('Notification permission granted'); - messaging.getToken().then(function(){ - if(currentToken){ - sendTokenToServer(currentToken); - updateUIForPushEnabled(currentToken); - console.log('Token retrieved, ',currentToken); - //abis itu send ke tokensaver chatservice di sini atau di bawah - } else { - console.log('No Instance ID token available. Request permission to generate one'); - updateUIForPushPermissionRequired(); - setTokenToServer(false); - } - }).catch(function(err){ - console.log('An error occured while retrieving token. ',err); - showToken('Error retrieving Instance ID token. ',err); - setTokenToServer(false); - }); - }).catch(function(err){ - console.log('Unable to get permission to notify',err); - }); - - messaging.onTokenRefresh(function(){ - mesagging.getToken().then(function(refreshedToken){ - console.log('Token refreshed.'); - setTokenSentToServer(false); - sendTokenToServer(refreshedToken); - }); - }).catch(function(err){ - console.log('Unable to retrieve refreshed token. ',err); - showToken('Unable to retrieve refreshed token. ',err); - }); - - messaging.onMessage(function(payload){ - console.log("Message received. ",payload); - });*/ + /*messaging.requestPermission().then(function(){ + console.log('Notification permission granted'); + messaging.getToken().then(function(){ + if(currentToken){ + sendTokenToServer(currentToken); + updateUIForPushEnabled(currentToken); + console.log('Token retrieved, ',currentToken); + //abis itu send ke tokensaver chatservice di sini atau di bawah + } else { + console.log('No Instance ID token available. Request permission to generate one'); + updateUIForPushPermissionRequired(); + setTokenToServer(false); + } + }).catch(function(err){ + console.log('An error occured while retrieving token. ',err); + showToken('Error retrieving Instance ID token. ',err); + setTokenToServer(false); + }); + }).catch(function(err){ + console.log('Unable to get permission to notify',err); + }); + + messaging.onTokenRefresh(function(){ + mesagging.getToken().then(function(refreshedToken){ + console.log('Token refreshed.'); + setTokenSentToServer(false); + sendTokenToServer(refreshedToken); + }); + }).catch(function(err){ + console.log('Unable to retrieve refreshed token. ',err); + showToken('Unable to retrieve refreshed token. ',err); + }); + + messaging.onMessage(function(payload){ + console.log("Message received. ",payload); + });*/ </script> <!--Application --> <script src="scripts/app.js"></script> - + </head> <body ng-app="chatApp" ng-controller="chatController"> - <div class="catalog_content"> - <div class="logo"> - <span id="red">Sale</span><span id="blue">Project</span> - </div> - <div class="information"> - <span> - <% -/* FirebaseOptions options = new FirebaseOptions.Builder() - .setServiceAccount(new FileInputStream("path/to/serviceAccountKey.json")) - .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/") - .build(); + <div class="catalog_content"> + <div class="logo"> + <span id="red">Sale</span><span id="blue">Project</span> + </div> + <div class="information"> + <span> + <% + /* FirebaseOptions options = new FirebaseOptions.Builder() + .setServiceAccount(new FileInputStream("path/to/serviceAccountKey.json")) + .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/") + .build(); - FirebaseApp.initializeApp(options);*/ - - JSONObject responseJSON = new JSONObject(); - JSONObject responseJSON1 = new JSONObject(); - org.kaa.marketplaceservice.service.MarketPlaceService_Service service = new org.kaa.marketplaceservice.service.MarketPlaceService_Service(); - org.kaa.marketplaceservice.service.MarketPlaceService port = service.getMarketPlaceServicePort(); - String query; - String APIURL; - String ParameterURL; - - /* Showing username of user */ - String user_token = request.getParameter("token"); - if (request.getParameter("like") != null){ - String productId = request.getParameter("product_id"); - boolean like; - if (request.getParameter("like").equals("yes")){ - like = true; - } else { - like = false; - } - ProcedureStatus result = port.processLike(user_token, productId, like); - if (result.getStatus().equals("OK")){ - //Do nothing - } else if (result.getStatus().equals("EXPIRED")) { - response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" - + "message=Expired"); - } else { - response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." - + "jsp?token="+user_token+"&message=error"); - } - } - - if ((request.getParameter("logout") == null) && - (request.getParameter("token")!= null)){ - /* Consume REST API */ - ParameterURL = "token="+ request.getParameter("token"); - APIURL = "http://localhost:8080/IdentService/validate?"; - RestAPI_consumer consumer = new RestAPI_consumer(APIURL,ParameterURL); - consumer.execute(); - responseJSON = consumer.getOutput(); - - /* Checking the response */ - String status = (String)responseJSON.get("status"); - if (status.equals("OK")){ - String user = (String)responseJSON.get("user_name"); - out.println("Hello, " + user); - //out.println("<script>setUser('"+user+"');</script>"); - } - else{ - response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." - + "jsp?token="+user_token); - } - } - /* Logout */ - else if ((request.getParameter("logout") != null) && - (request.getParameter("token")!= null)){ - URL obj1 = null; - try{ - /* Consume REST API */ - ParameterURL = "token="+ user_token; - APIURL = "http://localhost:8080/IdentService/logout?"; - RestAPI_consumer consumer1 = new RestAPI_consumer(APIURL,ParameterURL); - consumer1.execute(); - responseJSON1 = consumer1.getOutput(); - - /* Checking the response */ - String status1 = (String)responseJSON1.get("status"); - if (status1.equals("OK")){ - response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" - + "message=logout"); - } - else{ - response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." - + "jsp?token="+user_token); - } - } - catch(Exception e){ - e.printStackTrace(); - } - } + FirebaseApp.initializeApp(options);*/ - /* Firebase here - String uid = "some-uid"; + JSONObject responseJSON = new JSONObject(); + JSONObject responseJSON1 = new JSONObject(); + org.kaa.marketplaceservice.service.MarketPlaceService_Service service = new org.kaa.marketplaceservice.service.MarketPlaceService_Service(); + org.kaa.marketplaceservice.service.MarketPlaceService port = service.getMarketPlaceServicePort(); + String query; + String APIURL; + String ParameterURL; - FirebaseAuth.getInstance().createCustomToken(uid) - .addOnSuccessListener(new OnSuccessListener<String>() { - @Override - public void onSuccess(String customToken) { - // Send token back to client - } - });*/ - %> - </span> + String urlParamChat; + String urlRequest2 = "http://localhost:8080/ChatService/RetrieveStatus?"; - </br> - <a href=" - <% - String logoutURL = "http://localhost:8080/KAA-JSP/catalog.jsp?token="+user_token+"&logout=on"; - out.println(logoutURL); - %> - " class="logout"><span class="link">Logout</span> - </a><br/> - </div> - <table class="menu"> - <th class="menupart" id="active"> - <a href=" - <% - out.println("http://localhost:8080/KAA-JSP/catalog.jsp?token="+user_token); - %> - "> - Catalog - </a> - </th> - <th class="menupart"> - <a href=" - <% - out.println("http://localhost:8080/KAA-JSP/yourproduct.jsp?token="+user_token); - %> - "> - Your Products - </a> - </th> - <th class="menupart"> - <a href=" - <% - out.println("http://localhost:8080/KAA-JSP/addproduct.jsp?token="+user_token); - %> - "> - Add Product - </a> - </th> - <th class="menupart"> - <a href=" - <% - out.println("http://localhost:8080/KAA-JSP/sales.jsp?token="+user_token); - %> - "> - Sales - </a> - </th> - <th class="menupart"> + /* Showing username of user */ + String user_token = request.getParameter("token"); + if (request.getParameter("like") != null) { + String productId = request.getParameter("product_id"); + boolean like; + if (request.getParameter("like").equals("yes")) { + like = true; + } else { + like = false; + } + ProcedureStatus result = port.processLike(user_token, productId, like); + if (result.getStatus().equals("OK")) { + //Do nothing + } else if (result.getStatus().equals("EXPIRED")) { + response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" + + "message=Expired"); + } else { + response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." + + "jsp?token=" + user_token + "&message=error"); + } + } + + if ((request.getParameter("logout") == null) + && (request.getParameter("token") != null)) { + /* Consume REST API */ + ParameterURL = "token=" + request.getParameter("token"); + APIURL = "http://localhost:8080/IdentService/validate?"; + RestAPI_consumer consumer = new RestAPI_consumer(APIURL, ParameterURL); + consumer.execute(); + responseJSON = consumer.getOutput(); + + /* Checking the response */ + String status = (String) responseJSON.get("status"); + if (status.equals("OK")) { + String user = (String) responseJSON.get("user_name"); + out.println("Hello, " + user); + //out.println("<script>setUser('"+user+"');</script>"); + } else { + response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." + + "jsp?token=" + user_token); + } + } /* Logout */ else if ((request.getParameter("logout") != null) + && (request.getParameter("token") != null)) { + URL obj1 = null; + try { + /* Consume REST API */ + ParameterURL = "token=" + user_token; + APIURL = "http://localhost:8080/IdentService/logout?"; + RestAPI_consumer consumer1 = new RestAPI_consumer(APIURL, ParameterURL); + consumer1.execute(); + responseJSON1 = consumer1.getOutput(); + + /* Checking the response */ + String status1 = (String) responseJSON1.get("status"); + if (status1.equals("OK")) { + response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" + + "message=logout"); + } else { + response.sendRedirect("http://localhost:8080/KAA-JSP/catalog." + + "jsp?token=" + user_token); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /* Firebase here + String uid = "some-uid"; + + FirebaseAuth.getInstance().createCustomToken(uid) + .addOnSuccessListener(new OnSuccessListener<String>() { + @Override + public void onSuccess(String customToken) { + // Send token back to client + } + });*/ + %> + </span> + + </br> <a href=" - <% - out.println("http://localhost:8080/KAA-JSP/purchases.jsp?token="+user_token); + <% String logoutURL = "http://localhost:8080/KAA-JSP/catalog.jsp?token=" + user_token + "&logout=on"; + out.println(logoutURL); %> - ">Purchases - </a> - </th> - </table> - <br/> - <p class="title">What are you going to buy today?</p> - <hr/> - <br/> - <div class="add_product_content"> + " class="logout"><span class="link">Logout</span> + </a><br/> + </div> + <table class="menu"> + <th class="menupart" id="active"> + <a href=" + <% + out.println("http://localhost:8080/KAA-JSP/catalog.jsp?token=" + user_token); + %> + "> + Catalog + </a> + </th> + <th class="menupart"> + <a href=" + <% + out.println("http://localhost:8080/KAA-JSP/yourproduct.jsp?token=" + user_token); + %> + "> + Your Products + </a> + </th> + <th class="menupart"> + <a href=" + <% + out.println("http://localhost:8080/KAA-JSP/addproduct.jsp?token=" + user_token); + %> + "> + Add Product + </a> + </th> + <th class="menupart"> + <a href=" + <% + out.println("http://localhost:8080/KAA-JSP/sales.jsp?token=" + user_token); + %> + "> + Sales + </a> + </th> + <th class="menupart"> + <a href=" + <% + out.println("http://localhost:8080/KAA-JSP/purchases.jsp?token=" + user_token); + %> + ">Purchases + </a> + </th> + </table> + <br/> + <p class="title">What are you going to buy today?</p> + <hr/> + <br/> + <div class="add_product_content"> <form method="GET" enctype="multipart/form-data"> - <div class="input_catalog"> - <input type="hidden" name="token" value=<% - out.println(user_token); - %> > - <input type="text" placeholder="Search catalog ..." - name="search" style="width:90%; height: 35px; border:none;" - class="auto-style1" hidefocus="hidefocus"> - <input type="submit" value="GO" style="width: 10%; height: 35px; font-weight: bold"><br/> - by - <input class="radio" type="radio" name="choice" value="product" checked="checked" /> - <label><span>product</span></label><br /> - <input class="radio" type="radio" name="choice" value="store" style="margin-left:25px;" /> - <label><span>store</span></label> - </div> + <div class="input_catalog"> + <input type="hidden" name="token" value=<% + out.println(user_token); + %> > + <input type="text" placeholder="Search catalog ..." + name="search" style="width:90%; height: 35px; border:none;" + class="auto-style1" hidefocus="hidefocus"> + <input type="submit" value="GO" style="width: 10%; height: 35px; font-weight: bold"><br/> + by + <input class="radio" type="radio" name="choice" value="product" checked="checked" /> + <label><span>product</span></label><br /> + <input class="radio" type="radio" name="choice" value="store" style="margin-left:25px;" /> + <label><span>store</span></label> + </div> </form> - </div> - <% - if(request.getParameter("search") == null){ - // Ketika pertama kali membuka catalog (tidak ada parameter search) - List<Product> result = port.retrieveAllProduct(user_token); - - // Ketika token sudah expired - if (result == null){ - response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" - + "message=expired"); - } else { - if (result.size() == 0){ - out.print("<p>No product to be sold.</p>"); - } else { - for (int i = 0; i < result.size(); i++) { - out.print("<a href=\"\"><div ng-click=\"setReceiver('"+result.get(i).getUsername()+"')\"><p><b>" + result.get(i).getUsername() + "</a></b><br/>"); - out.print("added this on " + result.get(i).getDate().getDate() + "</p></div>"); - out.print("<hr/>"); - out.print("<table>"); - out.print("<tr class = \"container\">"); - out.print("<td>"); - out.print("<img \" width=120px height=120px src=\"" + result.get(i).getImage() + "\">"); - out.print("</td>"); - out.print("<td class=\"product_description\">"); - out.print("<p class=\"catalog_title\">" + result.get(i).getName() + " <br/></p>"); - out.print("<p class=\"catalog_price\">IDR " + result.get(i).getPrice() + "<br/></p>"); - out.print("<p class=\"catalog_desc\">" + result.get(i).getDescription() + "</p>"); - out.print("</td>"); - out.print("<td class=\"product_misc\">"); - out.print("<br/>"); - out.print("<p>" + port.getLikes(result.get(i).getProductId()) + " likes </p><br/>"); - out.print("<p>" + port.getPurchases(result.get(i).getProductId()) + " purchases <br/>"); - out.print(port.isLiked(user_token, result.get(i).getProductId())); - out.print("<a href=\"http://localhost:8080/KAA-JSP/confirmation_purchase.jsp?token=" + user_token + "&product_id=" + result.get(i).getProductId() + "\"><p id=\"buy\">BUY</a></p>"); - out.print("</td>"); - out.print("</tr>"); - out.print("</table>"); - out.print("<hr/>"); - out.print("<br/>"); - out.print("<br/>"); - } - } - } - } else { - // Ketika ada parameter untuk search - String search = request.getParameter("search"); - String choice = request.getParameter("choice"); - /* Melakukan Searching dengan Method search_product pada MarketService */ - try{ - int choice_int = 0; - if (choice.equals("product")){ - choice_int = 0; - } else if (choice.equals("store")) { - choice_int = 1; - } - - List<Product> result = port.searchProduct(search, user_token, choice_int); - - /* Jika expired */ - if (result == null){ + </div> + <% + if (request.getParameter("search") == null) { + // Ketika pertama kali membuka catalog (tidak ada parameter search) + List<Product> result = port.retrieveAllProduct(user_token); + + // Ketika token sudah expired + if (result == null) { response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" + "message=expired"); } else { - if (result.size() == 0){ - out.print("<p>Nothing matches your search.</p>"); + if (result.size() == 0) { + out.print("<p>No product to be sold.</p>"); } else { for (int i = 0; i < result.size(); i++) { - out.print("<a href=\"\"><div ng-click=\"setReceiver('"+result.get(i).getUsername()+"')\"><b>" + result.get(i).getUsername() + "</a></b></div><br/>"); + urlParamChat = "user_id=" + result.get(i).getUserId(); + RestAPI_consumer consumer2 = new RestAPI_consumer(urlRequest2, urlParamChat); + consumer2.execute(); + responseJSON = consumer2.getOutput(); + if (responseJSON.get("status").equals("ON")) { + out.print("<img style=\"border: none; padding: 0px 10px 0px 0px; float:left\" height=15px width=15px src=\"img/on.png\">"); + out.print("<a href=\"\"><div ng-click=\"setReceiver('" + result.get(i).getUsername() + "')\"><p><b>" + result.get(i).getUsername() + "</a></b><br/>"); + } else { + out.print("<img style=\"border: none; padding: 0px 10px 0px 0px; float:left\" height=15px width=15px src=\"img/off.png\">"); + out.print("<a href=\"\"><div ng-click=\"setReceiver('" + result.get(i).getUsername() + "')\"><p><b>" + result.get(i).getUsername() + "</a></b><br/>"); + } out.print("added this on " + result.get(i).getDate().getDate() + "</p></div>"); out.print("<hr/>"); out.print("<table>"); out.print("<tr class = \"container\">"); out.print("<td>"); - out.print("<img \" width=120px height=120px src=\"" + result.get(i).getImage() + "\">"); - out.print("</td>"); - out.print("<td class=\"product_description\">"); - out.print("<p class=\"catalog_title\">" + result.get(i).getName() + " <br/></p>"); - out.print("<p class=\"catalog_price\">IDR " + result.get(i).getPrice() + "<br/></p>"); - out.print("<p class=\"catalog_desc\">" + result.get(i).getDescription() + "</p>"); - out.print("</td>"); - out.print("<td class=\"product_misc\">"); - out.print("<br/>"); - out.print("<p>" + port.getLikes(result.get(i).getProductId()) + " likes </p><br/>"); - out.print("<p>" + port.getPurchases(result.get(i).getProductId()) + " purchases <br/>"); - out.print(port.isLiked(user_token, result.get(i).getProductId())); - out.print("<a href=\"http://localhost:8080/KAA-JSP/confirmation_purchase.jsp?token=" + user_token + "&product_id=" + result.get(i).getProductId() + "\"><p id=\"buy\">BUY</a></p>"); - out.print("</td>"); - out.print("</tr>"); - out.print("</table>"); - out.print("<hr/>"); - out.print("<br/>"); + out.print("<img \" width=120px height=120px src=\"" + result.get(i).getImage() + "\">"); + out.print("</td>"); + out.print("<td class=\"product_description\">"); + out.print("<p class=\"catalog_title\">" + result.get(i).getName() + " <br/></p>"); + out.print("<p class=\"catalog_price\">IDR " + result.get(i).getPrice() + "<br/></p>"); + out.print("<p class=\"catalog_desc\">" + result.get(i).getDescription() + "</p>"); + out.print("</td>"); + out.print("<td class=\"product_misc\">"); + out.print("<br/>"); + out.print("<p>" + port.getLikes(result.get(i).getProductId()) + " likes </p><br/>"); + out.print("<p>" + port.getPurchases(result.get(i).getProductId()) + " purchases <br/>"); + out.print(port.isLiked(user_token, result.get(i).getProductId())); + out.print("<a href=\"http://localhost:8080/KAA-JSP/confirmation_purchase.jsp?token=" + user_token + "&product_id=" + result.get(i).getProductId() + "\"><p id=\"buy\">BUY</a></p>"); + out.print("</td>"); + out.print("</tr>"); + out.print("</table>"); + out.print("<hr/>"); + out.print("<br/>"); out.print("<br/>"); } } } - } catch (Exception ex) { - // TODO handle custom exceptions here + } else { + // Ketika ada parameter untuk search + String search = request.getParameter("search"); + String choice = request.getParameter("choice"); + /* Melakukan Searching dengan Method search_product pada MarketService */ + try { + int choice_int = 0; + if (choice.equals("product")) { + choice_int = 0; + } else if (choice.equals("store")) { + choice_int = 1; + } + + List<Product> result = port.searchProduct(search, user_token, choice_int); + + /* Jika expired */ + if (result == null) { + response.sendRedirect("http://localhost:8080/KAA-JSP/login.jsp?" + + "message=expired"); + } else { + if (result.size() == 0) { + out.print("<p>Nothing matches your search.</p>"); + } else { + for (int i = 0; i < result.size(); i++) { + out.print("<a href=\"\"><div ng-click=\"setReceiver('" + result.get(i).getUsername() + "')\"><b>" + result.get(i).getUsername() + "</a></b></div><br/>"); + out.print("added this on " + result.get(i).getDate().getDate() + "</p></div>"); + out.print("<hr/>"); + out.print("<table>"); + out.print("<tr class = \"container\">"); + out.print("<td>"); + out.print("<img \" width=120px height=120px src=\"" + result.get(i).getImage() + "\">"); + out.print("</td>"); + out.print("<td class=\"product_description\">"); + out.print("<p class=\"catalog_title\">" + result.get(i).getName() + " <br/></p>"); + out.print("<p class=\"catalog_price\">IDR " + result.get(i).getPrice() + "<br/></p>"); + out.print("<p class=\"catalog_desc\">" + result.get(i).getDescription() + "</p>"); + out.print("</td>"); + out.print("<td class=\"product_misc\">"); + out.print("<br/>"); + out.print("<p>" + port.getLikes(result.get(i).getProductId()) + " likes </p><br/>"); + out.print("<p>" + port.getPurchases(result.get(i).getProductId()) + " purchases <br/>"); + out.print(port.isLiked(user_token, result.get(i).getProductId())); + out.print("<a href=\"http://localhost:8080/KAA-JSP/confirmation_purchase.jsp?token=" + user_token + "&product_id=" + result.get(i).getProductId() + "\"><p id=\"buy\">BUY</a></p>"); + out.print("</td>"); + out.print("</tr>"); + out.print("</table>"); + out.print("<hr/>"); + out.print("<br/>"); + out.print("<br/>"); + } + } + } + } catch (Exception ex) { + // TODO handle custom exceptions here + } } - } - %> + %> - {{user}} - <br> - <div class="popup-box chat-popup" id="1" ng-show="isReceiverSet()" style="right: 0px; display: block;"> - <div class="popup-head"> - <div class="popup-head-left">{{receiver}}</div> - <div class="popup-head-right" ng-click="setReceiver('')"><a href="">✕</a></div> - <div style="clear: both"></div> + {{user}} + <br> + <div class="popup-box chat-popup" id="1" ng-show="isReceiverSet()" style="right: 0px; display: block;"> + <div class="popup-head"> + <div class="popup-head-left">{{receiver}}</div> + <div class="popup-head-right" ng-click="setReceiver('')"><a href="">✕</a></div> + <div style="clear: both"></div> + </div> + <div class="popup-messages">Tes</div> + <div class="popup-input"> + <input type="text" style="height: 100%" name="chat" class="auto-style1" hidefocus="hidefocus" /> + </div> </div> - <div class="popup-messages">Tes</div> - <div class="popup-input"> - <input type="text" style="height: 100%" name="chat" class="auto-style1" hidefocus="hidefocus" /> - </div> - </div> - -<!-- <div ng-app="chatApp" ng-controller="chatController"> - <p>Name: <input type="text" ng-model="newmessage.user"></p> - <p>Message: <input type="text" ng-model="newmessage.text"></p> - <button ng-click="insert(newmessage)">Send</button> - - <ul> - <li ng-repeat="message in messages"> - {{message.user}} send: {{message.text}} - </li> - </ul> - </div> --> - - <script> - /*document.getElementById("catalog").style.background="#0066ff"; - document.getElementById("catalog").style.color="#ffffff";*/ - </script> + <!-- <div ng-app="chatApp" ng-controller="chatController"> + <p>Name: <input type="text" ng-model="newmessage.user"></p> + <p>Message: <input type="text" ng-model="newmessage.text"></p> + <button ng-click="insert(newmessage)">Send</button> + + <ul> + <li ng-repeat="message in messages"> + {{message.user}} send: {{message.text}} + </li> + </ul> + </div> --> + + + <script> + /*document.getElementById("catalog").style.background="#0066ff"; + document.getElementById("catalog").style.color="#ffffff";*/ + </script> </body> </html> diff --git a/KAA-JSP/web/css/style.css b/KAA-JSP/web/css/style.css index 60760a0..2a859c3 100644 --- a/KAA-JSP/web/css/style.css +++ b/KAA-JSP/web/css/style.css @@ -337,11 +337,17 @@ ul { margin: 0px 0px 0px 20px; padding: 0px 0px 0px 10px; } -ul li { + +ul li .on { color: green; list-style-type: disc; } +ul li .off { + color: gray; + list-style-type: disc; +} + ul li span{ color: black; } \ No newline at end of file diff --git a/KAA-JSP/web/img/off.png b/KAA-JSP/web/img/off.png new file mode 100644 index 0000000000000000000000000000000000000000..ab25ccd0ba6ebcd24761b13779cfd0a0065d4356 GIT binary patch literal 2565 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 bJ)8d@2h88dDnsp?00000NkvXXu0mjfSV-Jd literal 0 HcmV?d00001 diff --git a/KAA-JSP/web/img/on.png b/KAA-JSP/web/img/on.png new file mode 100644 index 0000000000000000000000000000000000000000..25325bda7c1e388b2cd709242f7e16268f078c31 GIT binary patch literal 12351 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 literal 0 HcmV?d00001 -- GitLab