From ef49c570e596d0c2cd4e9478817e7c6037f53a2f Mon Sep 17 00:00:00 2001 From: jymao Date: Tue, 12 Jul 2022 22:44:23 -0400 Subject: [PATCH 1/4] Get data from datastore and display data summary using charts --- src/main/java/com/servlets/List.java | 67 ++++++++++++++++++++++++++++ src/main/webapp/piechart.html | 11 +++++ src/main/webapp/progress.js | 34 ++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 src/main/java/com/servlets/List.java create mode 100644 src/main/webapp/piechart.html create mode 100644 src/main/webapp/progress.js diff --git a/src/main/java/com/servlets/List.java b/src/main/java/com/servlets/List.java new file mode 100644 index 0000000..fb98b0e --- /dev/null +++ b/src/main/java/com/servlets/List.java @@ -0,0 +1,67 @@ +// Copyright 2019 Google LLC +// +// 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 +// +// https://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. + +import com.google.cloud.datastore.Datastore; +import com.google.cloud.datastore.DatastoreOptions; +import com.google.cloud.datastore.Entity; +import com.google.cloud.datastore.Query; +import com.google.cloud.datastore.QueryResults; +import com.google.cloud.datastore.StructuredQuery.OrderBy; +import com.google.gson.Gson; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** Servlet responsible for listing time breakdown. */ +@WebServlet("/time-breakdown") +public class ListRecordsServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + Datastore datastore = DatastoreOptions.getDefaultInstance().getService(); + + // TODO: add time (today, this month, this year...) and user as a filter to fetch data + String userId; + String date; + Query query = Query.newEntityQueryBuilder().setKind("Record") + .setFilter(CompositeFilter.and( + PropertyFilter.eq("userId", userId), PropertyFilter.eq("date", date))) + .build(); + QueryResults results = datastore.run(query); + + // Calculate the sum of time spent for each catagory + HashMap recordSum = new HashMap(); + while (results.hasNext()) { + Entity entity = results.next(); + // each Record entity should at least have the following properties: + // catagory(String), time(Double), userId(String), date(String) + String catagory = entity.getString("catagory"); + long time = entity.getLong("time"); + if (recordSum.containsKey(catagory)) { + recordSum.replace(catagory, recordSum.get(catagory) + time); + } else { + recordSum.put(catagory, time); + } + } + // pass the result as JSON back to client + Gson gson = new Gson(); + response.setContentType("application/json;"); + response.getWriter().println(gson.toJson(recordSum)); + } +} diff --git a/src/main/webapp/piechart.html b/src/main/webapp/piechart.html new file mode 100644 index 0000000..5cbc8e1 --- /dev/null +++ b/src/main/webapp/piechart.html @@ -0,0 +1,11 @@ + + + + + + + + +
+ + \ No newline at end of file diff --git a/src/main/webapp/progress.js b/src/main/webapp/progress.js new file mode 100644 index 0000000..6f57d1c --- /dev/null +++ b/src/main/webapp/progress.js @@ -0,0 +1,34 @@ +// Load the Visualization API and the corechart package. +google.charts.load('current', {'packages':['corechart']}); + +// Set a callback to run when the Google Visualization API is loaded. +google.charts.setOnLoadCallback(drawPieChart); + +// Callback that creates and populates a data table, +// instantiates the pie chart, passes in the data and +// draws it. +function drawPieChart() { + + // Create the data table. + var data = new google.visualization.DataTable(); + data.addColumn('string', 'Catagories'); + data.addColumn('number', 'Time'); + + // fetch data(JSON) from server, iterate through each catagory + // and add it to the DataTable for the chart + fetch('/time-breakdown').then(response => response.json()).then((records) => { + Object.keys(records).forEach(function(key) { + data.addRows(key, records[key]); // + }) + }); + + // Set chart options + var options = {'title':'How you spent your time today', + 'is3D':true, + 'width':1000, + 'height':750}; + + // Instantiate and draw our chart, passing in some options. + var chart = new google.visualization.PieChart(document.getElementById('chart_div')); + chart.draw(data, options); +} \ No newline at end of file From 78769a1aa299087df540c5e034bc8a8a0f4432d0 Mon Sep 17 00:00:00 2001 From: jymao Date: Sun, 17 Jul 2022 22:22:05 -0700 Subject: [PATCH 2/4] update config files and add getting today's date in query --- src/main/appengine/app.yaml | 1 + src/main/java/com/google/sps/ServerMain.java | 51 +++++++ .../com/{ => google/sps}/servlets/List.java | 16 +- src/main/java/com/servlets/test.java | 0 src/main/pom.xml | 140 ++++++++++++++++++ 5 files changed, 204 insertions(+), 4 deletions(-) create mode 100644 src/main/appengine/app.yaml create mode 100644 src/main/java/com/google/sps/ServerMain.java rename src/main/java/com/{ => google/sps}/servlets/List.java (83%) delete mode 100644 src/main/java/com/servlets/test.java create mode 100644 src/main/pom.xml diff --git a/src/main/appengine/app.yaml b/src/main/appengine/app.yaml new file mode 100644 index 0000000..3c6c656 --- /dev/null +++ b/src/main/appengine/app.yaml @@ -0,0 +1 @@ +runtime: java11 diff --git a/src/main/java/com/google/sps/ServerMain.java b/src/main/java/com/google/sps/ServerMain.java new file mode 100644 index 0000000..fb722c4 --- /dev/null +++ b/src/main/java/com/google/sps/ServerMain.java @@ -0,0 +1,51 @@ +package com.google.sps; + +import java.net.URL; +import org.eclipse.jetty.annotations.AnnotationConfiguration; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.webapp.Configuration; +import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.jetty.webapp.WebInfConfiguration; + +/** + * Starts up the server, including a DefaultServlet that handles static files, and any servlet + * classes annotated with the @WebServlet annotation. + */ +public class ServerMain { + + public static void main(String[] args) throws Exception { + + // Create a server that listens on port 8080. + Server server = new Server(8080); + WebAppContext webAppContext = new WebAppContext(); + server.setHandler(webAppContext); + + // Load static content from inside the jar file. + URL webAppDir = ServerMain.class.getClassLoader().getResource("META-INF/resources"); + webAppContext.setResourceBase(webAppDir.toURI().toString()); + + // Enable annotations so the server sees classes annotated with @WebServlet. + webAppContext.setConfigurations( + new Configuration[] { + new AnnotationConfiguration(), new WebInfConfiguration(), + }); + + // Look for annotations in the classes directory (dev server) and in the jar file (live server) + webAppContext.setAttribute( + "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", + ".*/target/classes/|.*\\.jar"); + + // Handle static resources, e.g. html files. + ServletHolder defaultServletHolder = webAppContext.addServlet(DefaultServlet.class, "/"); + defaultServletHolder.setInitParameter("cacheControl", "no-store, max-age=0"); + + // Start the server! 🚀 + server.start(); + System.out.println("Server started!"); + + // Keep the main thread alive while the server is running. + server.join(); + } +} diff --git a/src/main/java/com/servlets/List.java b/src/main/java/com/google/sps/servlets/List.java similarity index 83% rename from src/main/java/com/servlets/List.java rename to src/main/java/com/google/sps/servlets/List.java index fb98b0e..762e7fc 100644 --- a/src/main/java/com/servlets/List.java +++ b/src/main/java/com/google/sps/servlets/List.java @@ -27,6 +27,8 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.time.LocalDate; +import java.time.Month; /** Servlet responsible for listing time breakdown. */ @WebServlet("/time-breakdown") @@ -36,12 +38,18 @@ public class ListRecordsServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { Datastore datastore = DatastoreOptions.getDefaultInstance().getService(); - // TODO: add time (today, this month, this year...) and user as a filter to fetch data + // TODO: add userid as a filter to fetch data String userId; - String date; + + // get today's date as int + LocalDate currentdate = LocalDate.now(); + int currentDay = currentdate.getDayOfMonth(); + int currentMonth = currentdate.getMonth().getValue(); + int currentYear = currentdate.getYear(); Query query = Query.newEntityQueryBuilder().setKind("Record") .setFilter(CompositeFilter.and( - PropertyFilter.eq("userId", userId), PropertyFilter.eq("date", date))) + PropertyFilter.eq("userId", userId), PropertyFilter.eq("year", currentYear), + PropertyFilter.eq("month", currentMonth), PropertyFilter.eq("day", currentDay))) .build(); QueryResults results = datastore.run(query); @@ -52,7 +60,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro // each Record entity should at least have the following properties: // catagory(String), time(Double), userId(String), date(String) String catagory = entity.getString("catagory"); - long time = entity.getLong("time"); + long time = entity.getDouble("time"); if (recordSum.containsKey(catagory)) { recordSum.replace(catagory, recordSum.get(catagory) + time); } else { diff --git a/src/main/java/com/servlets/test.java b/src/main/java/com/servlets/test.java deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/pom.xml b/src/main/pom.xml new file mode 100644 index 0000000..e3d84ab --- /dev/null +++ b/src/main/pom.xml @@ -0,0 +1,140 @@ + + 4.0.0 + + com.google.sps + StudentHelper + 1 + + + + 11 + 11 + UTF-8 + 9.4.41.v20210516 + + + com.google.sps.ServerMain + summer22-sps-11 + + + + + + javax.servlet + javax.servlet-api + 4.0.1 + + + + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + org.eclipse.jetty + jetty-annotations + ${jetty.version} + + + + + com.google.cloud + google-cloud-storage + 1.113.0 + + + + + com.google.cloud + google-cloud-vision + 1.100.0 + + + + + com.google.cloud + google-cloud-datastore + 1.104.0 + + + + + org.jsoup + jsoup + 1.14.2 + + + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + + copy-web-resources + compile + copy-resources + + + ${project.build.directory}/classes/META-INF/resources + + + ./src/main/webapp + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + shade + + false + + + ${exec.mainClass} + + + + + *:* + + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.2.0 + + ${googleCloudProjectId} + 1 + + + + + From ec83b5fdbf919ffb5850e09a6ae7b37ccd623483 Mon Sep 17 00:00:00 2001 From: jymao Date: Sun, 24 Jul 2022 16:48:11 -0400 Subject: [PATCH 3/4] add getting userid for date query --- .../java/com/google/sps/servlets/List.java | 11 ++++------- src/main/webapp/progress.js | 19 +++++++++++++------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/google/sps/servlets/List.java b/src/main/java/com/google/sps/servlets/List.java index 762e7fc..752ffa5 100644 --- a/src/main/java/com/google/sps/servlets/List.java +++ b/src/main/java/com/google/sps/servlets/List.java @@ -38,17 +38,16 @@ public class ListRecordsServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { Datastore datastore = DatastoreOptions.getDefaultInstance().getService(); - // TODO: add userid as a filter to fetch data - String userId; - - // get today's date as int + String username = request.getParameter("username"); + // get today's date, month, year as int LocalDate currentdate = LocalDate.now(); int currentDay = currentdate.getDayOfMonth(); int currentMonth = currentdate.getMonth().getValue(); int currentYear = currentdate.getYear(); + Query query = Query.newEntityQueryBuilder().setKind("Record") .setFilter(CompositeFilter.and( - PropertyFilter.eq("userId", userId), PropertyFilter.eq("year", currentYear), + PropertyFilter.eq("username", username), PropertyFilter.eq("year", currentYear), PropertyFilter.eq("month", currentMonth), PropertyFilter.eq("day", currentDay))) .build(); QueryResults results = datastore.run(query); @@ -57,8 +56,6 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro HashMap recordSum = new HashMap(); while (results.hasNext()) { Entity entity = results.next(); - // each Record entity should at least have the following properties: - // catagory(String), time(Double), userId(String), date(String) String catagory = entity.getString("catagory"); long time = entity.getDouble("time"); if (recordSum.containsKey(catagory)) { diff --git a/src/main/webapp/progress.js b/src/main/webapp/progress.js index 6f57d1c..6171121 100644 --- a/src/main/webapp/progress.js +++ b/src/main/webapp/progress.js @@ -13,14 +13,21 @@ function drawPieChart() { var data = new google.visualization.DataTable(); data.addColumn('string', 'Catagories'); data.addColumn('number', 'Time'); - + // fetch data(JSON) from server, iterate through each catagory // and add it to the DataTable for the chart - fetch('/time-breakdown').then(response => response.json()).then((records) => { - Object.keys(records).forEach(function(key) { - data.addRows(key, records[key]); // - }) - }); + let username = sessionStorage.getItem("username"); + $.ajax({ + url: '/time-breakdown', + data: { username: username}, + type: 'GET', + dataType: "json", + success: function (records) { + for (let key in records) { + data.addRows(key, records[key]); + } + } + });​ // Set chart options var options = {'title':'How you spent your time today', From 606a5f44c084ca62071f4909f785b66475ddfd92 Mon Sep 17 00:00:00 2001 From: jymao Date: Tue, 26 Jul 2022 11:41:57 -0400 Subject: [PATCH 4/4] Fix map type error --- src/main/java/com/google/sps/servlets/List.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/google/sps/servlets/List.java b/src/main/java/com/google/sps/servlets/List.java index 752ffa5..9f912d2 100644 --- a/src/main/java/com/google/sps/servlets/List.java +++ b/src/main/java/com/google/sps/servlets/List.java @@ -53,7 +53,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro QueryResults results = datastore.run(query); // Calculate the sum of time spent for each catagory - HashMap recordSum = new HashMap(); + Map recordSum = new HashMap(); while (results.hasNext()) { Entity entity = results.next(); String catagory = entity.getString("catagory");