diff --git a/.gitignore b/.gitignore index a467192..62ace4b 100755 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Google App Engine generated folder appengine-generated/ *.class -.DS_Store \ No newline at end of file +.DS_Store +keystore.properties diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/ImageServlet.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/ImageServlet.java index 74bd994..9414262 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/ImageServlet.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/ImageServlet.java @@ -4,7 +4,6 @@ import com.google.common.io.ByteStreams; import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; -import com.intelliq.appengine.api.PermissionSet; import com.intelliq.appengine.datastore.BusinessHelper; import com.intelliq.appengine.datastore.ImageHelper; import com.intelliq.appengine.datastore.QueueHelper; diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/ParserHelper.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/ParserHelper.java index 86c8379..617dd4c 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/ParserHelper.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/ParserHelper.java @@ -6,10 +6,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import com.google.appengine.api.urlfetch.HTTPResponse; -import com.google.appengine.api.urlfetch.URLFetchService; -import com.google.appengine.api.urlfetch.URLFetchServiceFactory; - public class ParserHelper { public static final int MODE_FIRST_FIRST = 0; diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/RequestFilter.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/RequestFilter.java index 2f2566c..a0c65b4 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/RequestFilter.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/RequestFilter.java @@ -40,7 +40,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha if (path.startsWith("/static") || path.startsWith("/_ah") || path.startsWith("/intelliq")) { // preserve special routes filterChain.doFilter(request, response); - } else if(uri.contains(".well-known/assetlinks.json")) { + } else if (uri.contains(".well-known/assetlinks.json")) { // redirect to Digital Asset Links JSON file RequestDispatcher rd = request.getRequestDispatcher("/static/assetlinks.json"); rd.forward(request, response); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/ApiRequest.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/ApiRequest.java index a1f4a25..3587736 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/ApiRequest.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/ApiRequest.java @@ -1,15 +1,14 @@ package com.intelliq.appengine.api; -import java.util.logging.Logger; - -import javax.servlet.http.HttpServletRequest; - import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; import com.intelliq.appengine.ParserHelper; -import com.intelliq.appengine.api.endpoint.EndpointManager; import com.intelliq.appengine.datastore.UserHelper; import com.intelliq.appengine.datastore.entries.UserEntry; +import java.util.logging.Logger; + +import javax.servlet.http.HttpServletRequest; + public class ApiRequest { private static final Logger log = Logger.getLogger(ApiRequest.class.getName()); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/ApiResponse.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/ApiResponse.java index c2242b8..6b0f5a1 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/ApiResponse.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/ApiResponse.java @@ -1,9 +1,9 @@ package com.intelliq.appengine.api; -import javax.servlet.http.HttpServletResponse; - import com.google.gson.Gson; +import javax.servlet.http.HttpServletResponse; + public class ApiResponse { int statusCode = HttpServletResponse.SC_OK; diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/PermissionSet.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/PermissionSet.java index e0f32cb..8e57c89 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/PermissionSet.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/PermissionSet.java @@ -1,10 +1,10 @@ package com.intelliq.appengine.api; +import com.intelliq.appengine.datastore.entries.PermissionEntry; + import java.util.ArrayList; import java.util.List; -import com.intelliq.appengine.datastore.entries.PermissionEntry; - public class PermissionSet { public static final byte REQUIRE_ANY = 0; diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/Endpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/Endpoint.java index 3981308..fb1fb6f 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/Endpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/Endpoint.java @@ -1,19 +1,17 @@ package com.intelliq.appengine.api.endpoint; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -import javax.servlet.http.HttpServletResponse; - import com.intelliq.appengine.ParserHelper; import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; -import com.intelliq.appengine.api.ApiServlet; import com.intelliq.appengine.api.PermissionSet; -import com.intelliq.appengine.datastore.entries.PermissionEntry; import com.intelliq.appengine.datastore.entries.UserEntry; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import javax.servlet.http.HttpServletResponse; + /** * Abstract endpoint that every API endpoint needs to extend. * Contains all basic methods and some that may need to be overwritten. diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/EndpointManager.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/EndpointManager.java index e480b36..a9bc26e 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/EndpointManager.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/EndpointManager.java @@ -1,14 +1,14 @@ package com.intelliq.appengine.api.endpoint; -import java.util.ArrayList; -import java.util.List; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.endpoint.business.BusinessEndpoint; import com.intelliq.appengine.api.endpoint.queue.QueueEndpoint; import com.intelliq.appengine.api.endpoint.queueitem.QueueItemEndpoint; import com.intelliq.appengine.api.endpoint.user.UserEndpoint; +import java.util.ArrayList; +import java.util.List; + public final class EndpointManager { public static final int API_VERSION = 1; diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/AddBusinessEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/AddBusinessEndpoint.java index bb9a9a2..4bc9158 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/AddBusinessEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/AddBusinessEndpoint.java @@ -1,14 +1,6 @@ package com.intelliq.appengine.api.endpoint.business; -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.http.HttpServletResponse; - -import java.util.logging.Logger; - import com.google.appengine.api.datastore.Key; -import com.intelliq.appengine.ParserHelper; import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; @@ -16,15 +8,19 @@ import com.intelliq.appengine.datastore.BusinessHelper; import com.intelliq.appengine.datastore.PermissionHelper; import com.intelliq.appengine.datastore.QueueHelper; -import com.intelliq.appengine.datastore.QueueItemHelper; import com.intelliq.appengine.datastore.UserHelper; import com.intelliq.appengine.datastore.entries.BusinessEntry; import com.intelliq.appengine.datastore.entries.PermissionEntry; import com.intelliq.appengine.datastore.entries.QueueEntry; -import com.intelliq.appengine.datastore.entries.QueueItemEntry; import com.intelliq.appengine.datastore.entries.UserEntry; import com.intelliq.appengine.logging.BusinessLogging; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import javax.servlet.http.HttpServletResponse; + public class AddBusinessEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/BusinessEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/BusinessEndpoint.java index 513bb53..e3f856c 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/BusinessEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/BusinessEndpoint.java @@ -1,13 +1,13 @@ package com.intelliq.appengine.api.endpoint.business; -import java.util.ArrayList; -import java.util.List; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; import com.intelliq.appengine.api.endpoint.EndpointManager; +import java.util.ArrayList; +import java.util.List; + public class BusinessEndpoint extends Endpoint { public static final List endpoints = getAvailableEndpoints(); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/EditBusinessEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/EditBusinessEndpoint.java index 433c3d3..ec98603 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/EditBusinessEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/EditBusinessEndpoint.java @@ -1,31 +1,22 @@ package com.intelliq.appengine.api.endpoint.business; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.jdo.JDOObjectNotFoundException; -import javax.servlet.http.HttpServletResponse; - -import com.google.appengine.api.datastore.Key; -import com.intelliq.appengine.ParserHelper; import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.PermissionSet; import com.intelliq.appengine.api.endpoint.Endpoint; import com.intelliq.appengine.api.endpoint.EndpointManager; import com.intelliq.appengine.datastore.BusinessHelper; -import com.intelliq.appengine.datastore.PermissionHelper; -import com.intelliq.appengine.datastore.QueueHelper; -import com.intelliq.appengine.datastore.QueueItemHelper; -import com.intelliq.appengine.datastore.UserHelper; import com.intelliq.appengine.datastore.entries.BusinessEntry; import com.intelliq.appengine.datastore.entries.PermissionEntry; -import com.intelliq.appengine.datastore.entries.QueueEntry; -import com.intelliq.appengine.datastore.entries.QueueItemEntry; import com.intelliq.appengine.datastore.entries.UserEntry; import com.intelliq.appengine.logging.BusinessLogging; +import java.util.ArrayList; +import java.util.List; + +import javax.jdo.JDOObjectNotFoundException; +import javax.servlet.http.HttpServletResponse; + public class EditBusinessEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/FromBusinessEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/FromBusinessEndpoint.java index 7dd307c..d5ad09e 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/FromBusinessEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/FromBusinessEndpoint.java @@ -1,25 +1,19 @@ package com.intelliq.appengine.api.endpoint.business; -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.http.HttpServletResponse; - -import org.datanucleus.exceptions.NucleusObjectNotFoundException; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; import com.intelliq.appengine.api.endpoint.EndpointManager; import com.intelliq.appengine.datastore.BusinessHelper; -import com.intelliq.appengine.datastore.QueueHelper; -import com.intelliq.appengine.datastore.QueueItemHelper; -import com.intelliq.appengine.datastore.UserHelper; import com.intelliq.appengine.datastore.entries.BusinessEntry; import com.intelliq.appengine.datastore.entries.PermissionEntry; -import com.intelliq.appengine.datastore.entries.QueueEntry; -import com.intelliq.appengine.datastore.entries.QueueItemEntry; -import com.intelliq.appengine.datastore.entries.UserEntry; + +import org.datanucleus.exceptions.NucleusObjectNotFoundException; + +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; public class FromBusinessEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/GetBusinessEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/GetBusinessEndpoint.java index bac5119..d562649 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/GetBusinessEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/business/GetBusinessEndpoint.java @@ -1,24 +1,21 @@ package com.intelliq.appengine.api.endpoint.business; -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.http.HttpServletResponse; - -import org.datanucleus.exceptions.NucleusObjectNotFoundException; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; import com.intelliq.appengine.api.endpoint.EndpointManager; import com.intelliq.appengine.datastore.BusinessHelper; import com.intelliq.appengine.datastore.QueueHelper; -import com.intelliq.appengine.datastore.QueueItemHelper; -import com.intelliq.appengine.datastore.UserHelper; import com.intelliq.appengine.datastore.entries.BusinessEntry; import com.intelliq.appengine.datastore.entries.QueueEntry; import com.intelliq.appengine.datastore.entries.QueueItemEntry; -import com.intelliq.appengine.datastore.entries.UserEntry; + +import org.datanucleus.exceptions.NucleusObjectNotFoundException; + +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; public class GetBusinessEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/AddQueueEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/AddQueueEndpoint.java index d82989e..7425ffb 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/AddQueueEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/AddQueueEndpoint.java @@ -1,11 +1,5 @@ package com.intelliq.appengine.api.endpoint.queue; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -import javax.servlet.http.HttpServletResponse; - import com.google.appengine.api.datastore.Key; import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; @@ -20,6 +14,12 @@ import com.intelliq.appengine.datastore.entries.UserEntry; import com.intelliq.appengine.logging.QueueLogging; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import javax.servlet.http.HttpServletResponse; + public class AddQueueEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/ClearQueueItemsEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/ClearQueueItemsEndpoint.java index 2a728fe..b5f110f 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/ClearQueueItemsEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/ClearQueueItemsEndpoint.java @@ -1,9 +1,5 @@ package com.intelliq.appengine.api.endpoint.queue; -import java.util.ArrayList; -import java.util.List; - -import com.intelliq.appengine.ParserHelper; import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.PermissionSet; @@ -11,9 +7,11 @@ import com.intelliq.appengine.api.endpoint.EndpointManager; import com.intelliq.appengine.datastore.QueueHelper; import com.intelliq.appengine.datastore.entries.PermissionEntry; -import com.intelliq.appengine.datastore.entries.QueueEntry; import com.intelliq.appengine.datastore.entries.QueueItemEntry; +import java.util.ArrayList; +import java.util.List; + public class ClearQueueItemsEndpoint extends Endpoint { @@ -73,7 +71,7 @@ public ApiResponse generateRequestResponse(ApiRequest request) throws Exception QueueHelper.deleteItemsInQueue(queueKeyId, status); } - List entries = QueueHelper.getItemsInQueue(queueKeyId, 0, 100); + List entries = QueueHelper.getItemsInQueue(queueKeyId, QueueItemEntry.STATUS_ALL, 0, 100); response.setContent(entries); return response; } diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/EditQueueEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/EditQueueEndpoint.java index f842ed1..25cff54 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/EditQueueEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/EditQueueEndpoint.java @@ -1,27 +1,22 @@ package com.intelliq.appengine.api.endpoint.queue; -import java.util.ArrayList; -import java.util.List; - -import javax.jdo.JDOObjectNotFoundException; -import javax.servlet.http.HttpServletResponse; - -import com.google.appengine.api.datastore.Key; import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.PermissionSet; import com.intelliq.appengine.api.endpoint.Endpoint; import com.intelliq.appengine.api.endpoint.EndpointManager; -import com.intelliq.appengine.datastore.BusinessHelper; -import com.intelliq.appengine.datastore.PermissionHelper; import com.intelliq.appengine.datastore.QueueHelper; -import com.intelliq.appengine.datastore.UserHelper; -import com.intelliq.appengine.datastore.entries.BusinessEntry; import com.intelliq.appengine.datastore.entries.PermissionEntry; import com.intelliq.appengine.datastore.entries.QueueEntry; import com.intelliq.appengine.datastore.entries.UserEntry; import com.intelliq.appengine.logging.QueueLogging; +import java.util.ArrayList; +import java.util.List; + +import javax.jdo.JDOObjectNotFoundException; +import javax.servlet.http.HttpServletResponse; + public class EditQueueEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetItemsInQueueEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetItemsInQueueEndpoint.java index 8f58f93..1174615 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetItemsInQueueEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetItemsInQueueEndpoint.java @@ -1,11 +1,5 @@ package com.intelliq.appengine.api.endpoint.queue; -import java.util.ArrayList; -import java.util.List; - -import javax.jdo.JDOObjectNotFoundException; -import javax.servlet.http.HttpServletResponse; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; @@ -13,6 +7,12 @@ import com.intelliq.appengine.datastore.QueueHelper; import com.intelliq.appengine.datastore.entries.QueueItemEntry; +import java.util.ArrayList; +import java.util.List; + +import javax.jdo.JDOObjectNotFoundException; +import javax.servlet.http.HttpServletResponse; + public class GetItemsInQueueEndpoint extends Endpoint { @@ -35,9 +35,10 @@ public ApiResponse generateRequestResponse(ApiRequest request) throws Exception long queueKeyId = request.getParameterAsLong("queueKeyId", -1); int offset = request.getParameterAsInt("offset", 0); int count = request.getParameterAsInt("count", 100); + byte status = (byte) request.getParameterAsInt("status", QueueItemEntry.STATUS_ALL); try { - List entries = QueueHelper.getItemsInQueue(queueKeyId, offset, count); + List entries = QueueHelper.getItemsInQueue(queueKeyId, status, offset, count); response.setContent(entries); } catch (JDOObjectNotFoundException exception) { response.setStatusCode(HttpServletResponse.SC_NOT_FOUND); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetNumberOfItemsInQueueEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetNumberOfItemsInQueueEndpoint.java index 73c43db..b6cb511 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetNumberOfItemsInQueueEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetNumberOfItemsInQueueEndpoint.java @@ -1,11 +1,5 @@ package com.intelliq.appengine.api.endpoint.queue; -import java.util.ArrayList; -import java.util.List; - -import javax.jdo.JDOObjectNotFoundException; -import javax.servlet.http.HttpServletResponse; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; @@ -13,6 +7,12 @@ import com.intelliq.appengine.datastore.QueueHelper; import com.intelliq.appengine.datastore.entries.QueueItemEntry; +import java.util.ArrayList; +import java.util.List; + +import javax.jdo.JDOObjectNotFoundException; +import javax.servlet.http.HttpServletResponse; + public class GetNumberOfItemsInQueueEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetQueueEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetQueueEndpoint.java index 2bfa43b..027cf34 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetQueueEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/GetQueueEndpoint.java @@ -1,11 +1,5 @@ package com.intelliq.appengine.api.endpoint.queue; -import java.util.ArrayList; -import java.util.List; - -import javax.jdo.JDOObjectNotFoundException; -import javax.servlet.http.HttpServletResponse; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; @@ -14,6 +8,12 @@ import com.intelliq.appengine.datastore.entries.QueueEntry; import com.intelliq.appengine.datastore.entries.QueueItemEntry; +import java.util.ArrayList; +import java.util.List; + +import javax.jdo.JDOObjectNotFoundException; +import javax.servlet.http.HttpServletResponse; + public class GetQueueEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/MarkAllQueueItemsAsDoneEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/MarkAllQueueItemsAsDoneEndpoint.java index bc8aa5a..b145d7b 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/MarkAllQueueItemsAsDoneEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/MarkAllQueueItemsAsDoneEndpoint.java @@ -1,11 +1,5 @@ package com.intelliq.appengine.api.endpoint.queue; -import java.util.ArrayList; -import java.util.List; - -import javax.jdo.JDOObjectNotFoundException; -import javax.servlet.http.HttpServletResponse; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.PermissionSet; @@ -14,6 +8,12 @@ import com.intelliq.appengine.datastore.QueueHelper; import com.intelliq.appengine.datastore.entries.PermissionEntry; +import java.util.ArrayList; +import java.util.List; + +import javax.jdo.JDOObjectNotFoundException; +import javax.servlet.http.HttpServletResponse; + public class MarkAllQueueItemsAsDoneEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/PopulateQueueEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/PopulateQueueEndpoint.java index 8ce153a..23e339f 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/PopulateQueueEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/PopulateQueueEndpoint.java @@ -1,11 +1,5 @@ package com.intelliq.appengine.api.endpoint.queue; -import java.util.ArrayList; -import java.util.List; - -import javax.jdo.JDOObjectNotFoundException; -import javax.servlet.http.HttpServletResponse; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.PermissionSet; @@ -14,6 +8,12 @@ import com.intelliq.appengine.datastore.QueueHelper; import com.intelliq.appengine.datastore.entries.PermissionEntry; +import java.util.ArrayList; +import java.util.List; + +import javax.jdo.JDOObjectNotFoundException; +import javax.servlet.http.HttpServletResponse; + public class PopulateQueueEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/QueueEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/QueueEndpoint.java index bea6ef0..fab1917 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/QueueEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queue/QueueEndpoint.java @@ -1,13 +1,13 @@ package com.intelliq.appengine.api.endpoint.queue; -import java.util.ArrayList; -import java.util.List; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; import com.intelliq.appengine.api.endpoint.EndpointManager; +import java.util.ArrayList; +import java.util.List; + public class QueueEndpoint extends Endpoint { public static final List endpoints = getAvailableEndpoints(); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/AddQueueItemEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/AddQueueItemEndpoint.java index ae0d08f..7fc20dc 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/AddQueueItemEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/AddQueueItemEndpoint.java @@ -1,12 +1,8 @@ package com.intelliq.appengine.api.endpoint.queueitem; -import java.util.ArrayList; -import java.util.List; - import com.google.appengine.api.datastore.Key; import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; -import com.intelliq.appengine.api.PermissionSet; import com.intelliq.appengine.api.endpoint.Endpoint; import com.intelliq.appengine.api.endpoint.EndpointManager; import com.intelliq.appengine.datastore.PermissionHelper; @@ -17,10 +13,18 @@ import com.intelliq.appengine.datastore.entries.QueueEntry; import com.intelliq.appengine.datastore.entries.QueueItemEntry; import com.intelliq.appengine.datastore.entries.UserEntry; +import com.intelliq.appengine.notification.NotificationException; +import com.intelliq.appengine.notification.text.TextNotification; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; public class AddQueueItemEndpoint extends Endpoint { + private static final Logger log = Logger.getLogger(AddQueueItemEndpoint.class.getName()); + @Override public String getEndpointPath() { return EndpointManager.ENDPOINT_QUEUE_ITEM_ADD; @@ -47,7 +51,9 @@ public List getRequiredParameters(ApiRequest request) { public ApiResponse generateRequestResponse(ApiRequest request) throws Exception { ApiResponse response = new ApiResponse(); + // get queue long queueKeyId = request.getParameterAsLong("queueKeyId", -1); + QueueEntry queueEntry = QueueHelper.getEntryByKeyId(queueKeyId); // create queue item QueueItemEntry queueItemEntry = new QueueItemEntry(queueKeyId); @@ -71,9 +77,16 @@ public ApiResponse generateRequestResponse(ApiRequest request) throws Exception if (queueItemEntry.getUserKeyId() > -1 && !addedByManagement) { QueueItemEntry existingQueueItemEntry = QueueItemHelper.getQueueItemByUserKeyId(queueItemEntry.getUserKeyId(), queueItemEntry.getQueueKeyId()); if (existingQueueItemEntry != null) { - // return the existing queue item - response.setContent(existingQueueItemEntry); - return response; + // check if the queue items has already been processed + if (existingQueueItemEntry.getStatus() == QueueItemEntry.STATUS_DONE) { + // create a new queue item + } else if (existingQueueItemEntry.getStatus() == QueueItemEntry.STATUS_CANCELED) { + // create a new queue item + } else { + // return the existing queue item + response.setContent(existingQueueItemEntry); + return response; + } } } @@ -95,8 +108,45 @@ public ApiResponse generateRequestResponse(ApiRequest request) throws Exception PermissionHelper.grantPermission(user, queueItemEntry, PermissionEntry.PERMISSION_OWN); } + // send notification + try { + sendQueueJoinedNotification(queueItemEntry, queueEntry); + } catch (NotificationException e) { + log.info("Unable to send notification: " + e.getMessage()); + } + response.setContent(queueItemEntry); return response; } + public static void sendQueueJoinedNotification(QueueItemEntry queueItemEntry, QueueEntry queueEntry) throws NotificationException { + if (!queueEntry.isTextNotificationsEnabled()) { + throw new NotificationException("Text notifications are not enabled for this queue"); + } + TextNotification notification = new TextNotification(); + notification.setRecipient(queueItemEntry.asTextNotificationRecipient()); + notification.setBody(generateQueueJoinedNotificationBody(queueItemEntry, queueEntry)); + notification.send(); + } + + public static String generateQueueJoinedNotificationBody(QueueItemEntry queueItemEntry, QueueEntry queueEntry) { + int waitingQueueItemEntries = QueueHelper.getNumberOfItemsInQueue(queueEntry.getKey().getId(), QueueItemEntry.STATUS_WAITING); + waitingQueueItemEntries -= 1; // current item is already included + long averageWaitingTime = queueEntry.getAverageWaitingTime(); + + StringBuilder sb = new StringBuilder() + .append("Your ticket number is ") + .append(queueItemEntry.getTicketNumber()) + .append(", you will be called as ") + .append(queueItemEntry.getName()) + .append(" in about ") + .append(QueueHelper.getReadableWaitingTimeEstimation(waitingQueueItemEntries, averageWaitingTime)) + .append("."); + + // TODO: localize message + // TODO: append link to ticket + + return sb.toString(); + } + } diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/DeleteQueueItemEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/DeleteQueueItemEndpoint.java index 174b5d8..0fb29fd 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/DeleteQueueItemEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/DeleteQueueItemEndpoint.java @@ -1,11 +1,5 @@ package com.intelliq.appengine.api.endpoint.queueitem; -import java.util.ArrayList; -import java.util.List; - -import javax.jdo.JDOObjectNotFoundException; -import javax.servlet.http.HttpServletResponse; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.PermissionSet; @@ -16,6 +10,12 @@ import com.intelliq.appengine.datastore.entries.PermissionEntry; import com.intelliq.appengine.datastore.entries.QueueEntry; +import java.util.ArrayList; +import java.util.List; + +import javax.jdo.JDOObjectNotFoundException; +import javax.servlet.http.HttpServletResponse; + public class DeleteQueueItemEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/GetLastItemInQueueEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/GetLastItemInQueueEndpoint.java index 5d309d4..d011508 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/GetLastItemInQueueEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/GetLastItemInQueueEndpoint.java @@ -1,17 +1,15 @@ package com.intelliq.appengine.api.endpoint.queueitem; -import java.util.ArrayList; -import java.util.List; - -import com.intelliq.appengine.ParserHelper; import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; import com.intelliq.appengine.api.endpoint.EndpointManager; import com.intelliq.appengine.datastore.QueueHelper; -import com.intelliq.appengine.datastore.entries.QueueEntry; import com.intelliq.appengine.datastore.entries.QueueItemEntry; +import java.util.ArrayList; +import java.util.List; + public class GetLastItemInQueueEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/GetQueueItemEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/GetQueueItemEndpoint.java index d9bf1ef..ab1d3b3 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/GetQueueItemEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/GetQueueItemEndpoint.java @@ -1,11 +1,5 @@ package com.intelliq.appengine.api.endpoint.queueitem; -import java.util.ArrayList; -import java.util.List; - -import javax.jdo.JDOObjectNotFoundException; -import javax.servlet.http.HttpServletResponse; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; @@ -13,6 +7,12 @@ import com.intelliq.appengine.datastore.QueueItemHelper; import com.intelliq.appengine.datastore.entries.QueueItemEntry; +import java.util.ArrayList; +import java.util.List; + +import javax.jdo.JDOObjectNotFoundException; +import javax.servlet.http.HttpServletResponse; + public class GetQueueItemEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/QueueItemEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/QueueItemEndpoint.java index b4fc677..f52a0de 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/QueueItemEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/QueueItemEndpoint.java @@ -1,13 +1,12 @@ package com.intelliq.appengine.api.endpoint.queueitem; -import java.util.ArrayList; -import java.util.List; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; import com.intelliq.appengine.api.endpoint.EndpointManager; -import com.intelliq.appengine.api.endpoint.queue.GetNearbyQueuesEndpoint; + +import java.util.ArrayList; +import java.util.List; public class QueueItemEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/SetQueueItemStatusEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/SetQueueItemStatusEndpoint.java index 989d859..43ac51d 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/SetQueueItemStatusEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/queueitem/SetQueueItemStatusEndpoint.java @@ -1,12 +1,5 @@ package com.intelliq.appengine.api.endpoint.queueitem; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.jdo.JDOObjectNotFoundException; -import javax.servlet.http.HttpServletResponse; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.PermissionSet; @@ -17,10 +10,22 @@ import com.intelliq.appengine.datastore.entries.PermissionEntry; import com.intelliq.appengine.datastore.entries.QueueEntry; import com.intelliq.appengine.datastore.entries.QueueItemEntry; +import com.intelliq.appengine.notification.NotificationException; +import com.intelliq.appengine.notification.text.TextNotification; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.logging.Logger; + +import javax.jdo.JDOObjectNotFoundException; +import javax.servlet.http.HttpServletResponse; public class SetQueueItemStatusEndpoint extends Endpoint { + private static final Logger log = Logger.getLogger(SetQueueItemStatusEndpoint.class.getName()); + @Override public String getEndpointPath() { return EndpointManager.ENDPOINT_QUEUE_ITEM_STATUS; @@ -88,11 +93,109 @@ public ApiResponse generateRequestResponse(ApiRequest request) throws Exception QueueItemHelper.saveEntry(queueItemEntry); response.setContent(queueItemEntry); + + QueueEntry queueEntry = QueueHelper.getEntryByKeyId(queueItemEntry.getQueueKeyId()); + + // send notifications + try { + notifyWaitingQueueItems(queueEntry); + } catch (NotificationException e) { + log.info("Unable to send called soon notification: " + e.getMessage()); + } + try { + sendStatusChangeNotification(queueItemEntry, queueEntry); + } catch (NotificationException e) { + log.info("Unable to send status change notification: " + e.getMessage()); + } } catch (JDOObjectNotFoundException exception) { response.setStatusCode(HttpServletResponse.SC_NOT_FOUND); response.setException(new Exception("Unable to find requested queue item")); } + return response; } + public static void notifyWaitingQueueItems(QueueEntry queueEntry) throws NotificationException { + int indexOfQueueItemToNotify = 3; // TODO: make adjustable, depend on average waiting time + List waitingQueueItems = new ArrayList<>(); + try { + waitingQueueItems = QueueHelper.getItemsInQueue(queueEntry.getKey().getId(), QueueItemEntry.STATUS_WAITING, indexOfQueueItemToNotify, 1); + if (waitingQueueItems.isEmpty()) { + // no waiting queue items (after index) + return; + } + + QueueItemEntry queueItemEntry = waitingQueueItems.get(0); + sendCalledSoonNotification(queueItemEntry, queueEntry); + } catch (JDOObjectNotFoundException e) { + throw new NotificationException("Unable to get waiting queue items: " + e.getMessage(), e); + } + } + + public static void sendCalledSoonNotification(QueueItemEntry queueItemEntry, QueueEntry queueEntry) throws NotificationException { + if (!queueEntry.isTextNotificationsEnabled()) { + throw new NotificationException("Text notifications are not enabled for this queue"); + } + TextNotification notification = new TextNotification(); + notification.setRecipient(queueItemEntry.asTextNotificationRecipient()); + notification.setBody(generateCalledSoonNotificationBody(queueItemEntry, queueEntry)); + notification.send(); + } + + public static String generateCalledSoonNotificationBody(QueueItemEntry queueItemEntry, QueueEntry queueEntry) { + StringBuilder sb = new StringBuilder() + .append(queueEntry.getName()) + .append(" will call you soon! Please get ready and check you ticket with number ") + .append(queueItemEntry.getTicketNumber()) + .append("."); + + // TODO: localize message + // TODO: append link to ticket + + return sb.toString(); + } + + public static void sendStatusChangeNotification(QueueItemEntry queueItemEntry, QueueEntry queueEntry) throws NotificationException { + if (!queueEntry.isTextNotificationsEnabled()) { + throw new NotificationException("Text notifications are not enabled for this queue"); + } + TextNotification notification = new TextNotification(); + notification.setRecipient(queueItemEntry.asTextNotificationRecipient()); + notification.setBody(generateStatusChangedNotificationBody(queueItemEntry, queueEntry)); + notification.send(); + } + + public static String generateStatusChangedNotificationBody(QueueItemEntry queueItemEntry, QueueEntry queueEntry) throws NotificationException { + StringBuilder sb = new StringBuilder(); + + switch (queueItemEntry.getStatus()) { + case QueueItemEntry.STATUS_CALLED: { + sb.append("You are called! Please get to ") + .append(queueEntry.getName()) + .append(" now."); + break; + } + case QueueItemEntry.STATUS_CANCELED: { + sb.append(queueEntry.getName()) + .append(" canceled your ticket."); + // TODO: ask for feedback + break; + } + case QueueItemEntry.STATUS_DONE: { + sb.append(queueEntry.getName()) + .append(" marked your ticket as done. We hope IntelliQ.me improved your waiting experience. Please let us know your feedback: https://intelliq.me"); + // TODO: adjust feedback url + break; + } + default: { + throw new NotificationException("Unable to generate notification body for status change to: " + queueItemEntry.getStatus()); + } + } + + // TODO: localize message + // TODO: append link to ticket + + return sb.toString(); + } + } diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/GetUserEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/GetUserEndpoint.java index e371221..4fc0909 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/GetUserEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/GetUserEndpoint.java @@ -1,11 +1,5 @@ package com.intelliq.appengine.api.endpoint.user; -import java.util.ArrayList; -import java.util.List; - -import javax.jdo.JDOObjectNotFoundException; -import javax.servlet.http.HttpServletResponse; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.PermissionSet; @@ -17,6 +11,12 @@ import com.intelliq.appengine.datastore.entries.UserEntry; import com.intelliq.appengine.logging.SlackLog; +import java.util.ArrayList; +import java.util.List; + +import javax.jdo.JDOObjectNotFoundException; +import javax.servlet.http.HttpServletResponse; + public class GetUserEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/SetUserLocationEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/SetUserLocationEndpoint.java index cba28a7..e52b947 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/SetUserLocationEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/SetUserLocationEndpoint.java @@ -1,13 +1,5 @@ package com.intelliq.appengine.api.endpoint.user; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.logging.Logger; - -import javax.servlet.http.HttpServletResponse; - -import com.google.appengine.api.datastore.Key; import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.PermissionSet; @@ -17,6 +9,11 @@ import com.intelliq.appengine.datastore.entries.PermissionEntry; import com.intelliq.appengine.datastore.entries.UserEntry; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.logging.Logger; + public class SetUserLocationEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/SignInUserEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/SignInUserEndpoint.java index 70807e3..ffc9583 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/SignInUserEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/SignInUserEndpoint.java @@ -1,12 +1,5 @@ package com.intelliq.appengine.api.endpoint.user; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.logging.Logger; - -import javax.servlet.http.HttpServletResponse; - import com.google.appengine.api.datastore.Key; import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; @@ -14,11 +7,12 @@ import com.intelliq.appengine.api.endpoint.EndpointManager; import com.intelliq.appengine.datastore.UserHelper; import com.intelliq.appengine.datastore.entries.UserEntry; -import com.intelliq.appengine.logging.SlackLog; import com.intelliq.appengine.logging.UserLogging; -import net.steppschuh.slackmessagebuilder.message.attachment.Attachment; -import net.steppschuh.slackmessagebuilder.message.attachment.AttachmentField; +import java.util.Date; +import java.util.logging.Logger; + +import javax.servlet.http.HttpServletResponse; public class SignInUserEndpoint extends Endpoint { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/UserEndpoint.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/UserEndpoint.java index e39ab77..4956f06 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/UserEndpoint.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/api/endpoint/user/UserEndpoint.java @@ -1,13 +1,13 @@ package com.intelliq.appengine.api.endpoint.user; -import java.util.ArrayList; -import java.util.List; - import com.intelliq.appengine.api.ApiRequest; import com.intelliq.appengine.api.ApiResponse; import com.intelliq.appengine.api.endpoint.Endpoint; import com.intelliq.appengine.api.endpoint.EndpointManager; +import java.util.ArrayList; +import java.util.List; + public class UserEndpoint extends Endpoint { public static final List endpoints = getAvailableEndpoints(); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/chron/ChronServlet.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/chron/ChronServlet.java index 365a5df..aed1da1 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/chron/ChronServlet.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/chron/ChronServlet.java @@ -1,37 +1,15 @@ package com.intelliq.appengine.chron; +import com.google.gson.Gson; + import java.io.IOException; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; import java.util.logging.Logger; -import javax.jdo.JDOHelper; -import javax.jdo.PersistenceManager; -import javax.jdo.PersistenceManagerFactory; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.google.appengine.api.datastore.DatastoreService; -import com.google.appengine.api.datastore.DatastoreServiceFactory; -import com.google.appengine.api.datastore.Entity; -import com.google.appengine.api.datastore.Key; -import com.google.appengine.api.datastore.KeyFactory; -import com.google.appengine.api.taskqueue.Queue; -import com.google.appengine.api.taskqueue.QueueFactory; -import com.google.appengine.api.taskqueue.TaskOptions; -import com.google.appengine.api.taskqueue.TaskOptions.Method; -import com.google.appengine.api.users.User; -import com.google.appengine.api.users.UserService; -import com.google.appengine.api.users.UserServiceFactory; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - @SuppressWarnings("serial") public class ChronServlet extends HttpServlet { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/BusinessHelper.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/BusinessHelper.java index 1cea1dd..044cbf2 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/BusinessHelper.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/BusinessHelper.java @@ -1,16 +1,16 @@ package com.intelliq.appengine.datastore; +import com.google.appengine.api.datastore.Key; +import com.google.appengine.api.datastore.KeyFactory; +import com.intelliq.appengine.datastore.entries.BusinessEntry; +import com.intelliq.appengine.datastore.entries.PermissionEntry; + import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import javax.jdo.PersistenceManager; -import com.google.appengine.api.datastore.Key; -import com.google.appengine.api.datastore.KeyFactory; -import com.intelliq.appengine.datastore.entries.BusinessEntry; -import com.intelliq.appengine.datastore.entries.PermissionEntry; - public class BusinessHelper { private static final Logger log = Logger.getLogger(BusinessHelper.class.getName()); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/ImageHelper.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/ImageHelper.java index 42ec1e1..853843e 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/ImageHelper.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/ImageHelper.java @@ -1,10 +1,5 @@ package com.intelliq.appengine.datastore; -import java.net.URL; -import java.util.logging.Logger; - -import javax.jdo.PersistenceManager; - import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import com.google.appengine.api.images.Image; @@ -16,7 +11,11 @@ import com.google.appengine.api.urlfetch.URLFetchService; import com.google.appengine.api.urlfetch.URLFetchServiceFactory; import com.intelliq.appengine.datastore.entries.ImageEntry; -import com.intelliq.appengine.datastore.entries.QueueItemEntry; + +import java.net.URL; +import java.util.logging.Logger; + +import javax.jdo.PersistenceManager; public class ImageHelper { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/MergeHelper.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/MergeHelper.java index 6f52861..6c4f06f 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/MergeHelper.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/MergeHelper.java @@ -1,10 +1,9 @@ package com.intelliq.appengine.datastore; -import java.util.Iterator; -import java.util.List; - import com.intelliq.appengine.ParserHelper; +import java.util.List; + public class MergeHelper { public static String mergeStrings(String existingValue, String newValue) { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/PermissionHelper.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/PermissionHelper.java index 7372671..7268179 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/PermissionHelper.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/PermissionHelper.java @@ -1,12 +1,5 @@ package com.intelliq.appengine.datastore; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -import javax.jdo.PersistenceManager; -import javax.jdo.Query; - import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import com.intelliq.appengine.datastore.entries.BusinessEntry; @@ -15,6 +8,13 @@ import com.intelliq.appengine.datastore.entries.QueueItemEntry; import com.intelliq.appengine.datastore.entries.UserEntry; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import javax.jdo.PersistenceManager; +import javax.jdo.Query; + public class PermissionHelper { private static final Logger log = Logger.getLogger(PermissionHelper.class.getSimpleName()); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/QueueHelper.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/QueueHelper.java index e024d94..55feda0 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/QueueHelper.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/QueueHelper.java @@ -1,5 +1,13 @@ package com.intelliq.appengine.datastore; +import com.google.appengine.api.datastore.Key; +import com.google.appengine.api.datastore.KeyFactory; +import com.intelliq.appengine.datastore.entries.BusinessEntry; +import com.intelliq.appengine.datastore.entries.QueueEntry; +import com.intelliq.appengine.datastore.entries.QueueItemEntry; +import com.intelliq.appengine.stuff.FakeData; +import com.intelliq.appengine.util.TimeUtils; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -8,13 +16,6 @@ import javax.jdo.PersistenceManager; import javax.jdo.Query; -import com.google.appengine.api.datastore.Key; -import com.google.appengine.api.datastore.KeyFactory; -import com.intelliq.appengine.datastore.entries.BusinessEntry; -import com.intelliq.appengine.datastore.entries.QueueEntry; -import com.intelliq.appengine.datastore.entries.QueueItemEntry; -import com.intelliq.appengine.stuff.FakeData; - public class QueueHelper { private static final Logger log = Logger.getLogger(QueueHelper.class.getName()); @@ -203,25 +204,28 @@ public static int getLastTicketNumberInQueue(long queueKeyId, byte status) { return -1; } - public static List getItemsInQueue(long queueKeyId, int startIndex, int count) { + public static List getItemsInQueue(long queueKeyId, byte status, int startIndex, int count) { PersistenceManager pm = PMF.get().getPersistenceManager(); Query query = pm.newQuery(QueueItemEntry.class); - query.setFilter("queueKeyId == value"); - query.setOrdering("entryTimestamp descending"); - query.declareParameters("long value"); - query.setRange(startIndex, count); query.setOrdering("ticketNumber ascending"); + query.setRange(startIndex, count); List results = new ArrayList(); try { - results = (List) query.execute(queueKeyId); + if (status == QueueItemEntry.STATUS_ALL) { + query.setFilter("queueKeyId == value"); + query.declareParameters("long value"); + results = (List) query.execute(queueKeyId); + } else { + query.setFilter("queueKeyId == value && status == value2"); + query.declareParameters("long value, byte value2"); + results = (List) query.execute(queueKeyId, status); + } results.size(); for (QueueItemEntry entry : results) { entry.getName(); - //log.info("Item found: " + entry.getName()); } - //log.info("Query execution returned " + results.size() + " item(s)"); } catch (Exception e) { e.printStackTrace(); } finally { @@ -300,6 +304,16 @@ public static int getNumberOfItemsInQueue(long queueKeyId, byte status) { return count; } + public static String getReadableWaitingTimeEstimation(QueueEntry queueEntry) { + int waitingQueueItemEntries = QueueHelper.getNumberOfItemsInQueue(queueEntry.getKey().getId(), QueueItemEntry.STATUS_WAITING); + long averageWaitingTime = queueEntry.getAverageWaitingTime(); + return getReadableWaitingTimeEstimation(waitingQueueItemEntries, averageWaitingTime); + } + + public static String getReadableWaitingTimeEstimation(int waitingQueueItemEntries, long averageWaitingTime) { + return TimeUtils.getReadableTimeFromMillis(waitingQueueItemEntries * averageWaitingTime); + } + public static QueueItemEntry getLastAssignedTicketInQueue(long queueKeyId, byte status) { PersistenceManager pm = PMF.get().getPersistenceManager(); Query query = pm.newQuery(QueueItemEntry.class); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/QueueItemHelper.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/QueueItemHelper.java index efb6719..66f7e11 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/QueueItemHelper.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/QueueItemHelper.java @@ -1,5 +1,9 @@ package com.intelliq.appengine.datastore; +import com.google.appengine.api.datastore.Key; +import com.google.appengine.api.datastore.KeyFactory; +import com.intelliq.appengine.datastore.entries.QueueItemEntry; + import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; @@ -7,11 +11,6 @@ import javax.jdo.PersistenceManager; import javax.jdo.Query; -import com.google.appengine.api.datastore.Key; -import com.google.appengine.api.datastore.KeyFactory; -import com.intelliq.appengine.datastore.entries.QueueItemEntry; -import com.intelliq.appengine.datastore.entries.UserEntry; - public class QueueItemHelper { private static final Logger log = Logger.getLogger(QueueItemHelper.class.getName()); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/UserHelper.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/UserHelper.java index 448e15b..67d40fb 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/UserHelper.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/UserHelper.java @@ -1,5 +1,12 @@ package com.intelliq.appengine.datastore; +import com.google.appengine.api.datastore.Key; +import com.google.appengine.api.datastore.KeyFactory; +import com.intelliq.appengine.datastore.entries.UserEntry; +import com.intelliq.appengine.datastore.entries.UserStatsEntry; + +import org.datanucleus.exceptions.NucleusObjectNotFoundException; + import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; @@ -7,15 +14,6 @@ import javax.jdo.PersistenceManager; import javax.jdo.Query; -import org.datanucleus.exceptions.NucleusObjectNotFoundException; - -import com.google.appengine.api.datastore.Key; -import com.google.appengine.api.datastore.KeyFactory; -import com.intelliq.appengine.datastore.entries.BusinessEntry; -import com.intelliq.appengine.datastore.entries.QueueEntry; -import com.intelliq.appengine.datastore.entries.UserEntry; -import com.intelliq.appengine.datastore.entries.UserStatsEntry; - public class UserHelper { private static final Logger log = Logger.getLogger(UserHelper.class.getName()); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/BusinessEntry.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/BusinessEntry.java index 336ac00..8b4174e 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/BusinessEntry.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/BusinessEntry.java @@ -1,5 +1,9 @@ package com.intelliq.appengine.datastore.entries; +import com.google.appengine.api.datastore.Key; +import com.google.appengine.api.datastore.KeyFactory; +import com.intelliq.appengine.api.ApiRequest; + import java.util.ArrayList; import javax.jdo.annotations.IdGeneratorStrategy; @@ -7,10 +11,6 @@ import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; -import com.google.appengine.api.datastore.Key; -import com.google.appengine.api.datastore.KeyFactory; -import com.intelliq.appengine.api.ApiRequest; - @PersistenceCapable(detachable = "true") public class BusinessEntry { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/PermissionEntry.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/PermissionEntry.java index 3ecf4c4..cd13675 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/PermissionEntry.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/PermissionEntry.java @@ -1,13 +1,12 @@ package com.intelliq.appengine.datastore.entries; +import com.google.appengine.api.datastore.Key; + import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; -import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; -import com.google.appengine.api.datastore.Key; - @PersistenceCapable(detachable = "true") public class PermissionEntry { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/QueueEntry.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/QueueEntry.java index 1959d64..2fed637 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/QueueEntry.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/QueueEntry.java @@ -1,18 +1,15 @@ package com.intelliq.appengine.datastore.entries; +import com.google.appengine.api.datastore.Key; +import com.google.appengine.api.datastore.KeyFactory; +import com.intelliq.appengine.api.ApiRequest; + import java.util.concurrent.TimeUnit; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; -import javax.servlet.http.HttpServletRequest; - -import com.google.appengine.api.datastore.Key; -import com.google.appengine.api.datastore.KeyFactory; -import com.intelliq.appengine.ParserHelper; -import com.intelliq.appengine.api.ApiRequest; -import com.intelliq.appengine.datastore.Location; @PersistenceCapable(detachable = "true") public class QueueEntry { @@ -45,6 +42,9 @@ public class QueueEntry { @Persistent boolean requiresSignIn; + @Persistent + boolean textNotificationsEnabled; + int waitingPeople; /** @@ -74,6 +74,7 @@ public QueueEntry(long businessKeyId) { latitude = -1; longitude = -1; requiresSignIn = false; + textNotificationsEnabled = false; averageWaitingTime = TimeUnit.MINUTES.toMillis(5); } @@ -170,7 +171,6 @@ public void setName(String name) { this.name = name; } - public String getDescription() { return description; } @@ -187,7 +187,6 @@ public void setVisibility(byte visibility) { this.visibility = visibility; } - public long getPhotoImageKeyId() { return photoImageKeyId; } @@ -275,4 +274,13 @@ public boolean getRequiresSignIn() { public void setRequiresSignIn(boolean requiresSignIn) { this.requiresSignIn = requiresSignIn; } + + public boolean isTextNotificationsEnabled() { + return textNotificationsEnabled; + } + + public void setTextNotificationsEnabled(boolean textNotificationsEnabled) { + this.textNotificationsEnabled = textNotificationsEnabled; + } + } diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/QueueItemEntry.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/QueueItemEntry.java index a4a74ae..9247633 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/QueueItemEntry.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/QueueItemEntry.java @@ -1,5 +1,11 @@ package com.intelliq.appengine.datastore.entries; +import com.google.appengine.api.datastore.Key; +import com.google.appengine.api.datastore.KeyFactory; +import com.intelliq.appengine.api.ApiRequest; +import com.intelliq.appengine.notification.NotificationException; +import com.intelliq.appengine.notification.text.TextNotificationRecipient; + import java.util.Comparator; import java.util.Date; import java.util.concurrent.TimeUnit; @@ -8,13 +14,6 @@ import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; -import javax.servlet.http.HttpServletRequest; - -import com.google.appengine.api.datastore.Key; -import com.google.appengine.api.datastore.KeyFactory; -import com.intelliq.appengine.ParserHelper; -import com.intelliq.appengine.api.ApiRequest; -import com.intelliq.appengine.datastore.Location; @PersistenceCapable(detachable = "true") public class QueueItemEntry { @@ -44,6 +43,9 @@ public class QueueItemEntry { @Persistent boolean usingApp; + @Persistent + String phoneNumber; + @Persistent long entryTimestamp; @@ -71,10 +73,24 @@ public void parseFromRequest(ApiRequest req) { queueKeyId = req.getParameterAsLong("queueKeyId", queueKeyId); userKeyId = req.getParameterAsLong("userKeyId", userKeyId); name = req.getParameter("name", name); + phoneNumber = req.getParameter("phoneNumber", phoneNumber); showName = req.getParameterAsBoolean("showName", showName); usingApp = req.getParameterAsBoolean("usingApp", usingApp); } + public TextNotificationRecipient asTextNotificationRecipient() throws NotificationException { + if (name == null || name.length() < 1) { + throw new NotificationException("Invalid recipient name"); + } + if (phoneNumber == null || phoneNumber.length() < 1) { + throw new NotificationException("Invalid recipient phone number"); + } + TextNotificationRecipient recipient = new TextNotificationRecipient(); + recipient.setName(name); + recipient.setMsisdn(phoneNumber); + return recipient; + } + public void makeDummyItem() { name = "Dummy Customer"; entryTimestamp = (long) (new Date().getTime() - (Math.random() * TimeUnit.MINUTES.toMillis(60))); @@ -128,6 +144,14 @@ public void setUsingApp(boolean usingApp) { this.usingApp = usingApp; } + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + public long getEntryTimestamp() { return entryTimestamp; } diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/UserEntry.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/UserEntry.java index 2869c78..fe16341 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/UserEntry.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/UserEntry.java @@ -1,15 +1,15 @@ package com.intelliq.appengine.datastore.entries; +import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; +import com.google.appengine.api.datastore.Key; +import com.intelliq.appengine.datastore.PermissionHelper; + import javax.jdo.annotations.Element; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; -import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; -import com.google.appengine.api.datastore.Key; -import com.intelliq.appengine.datastore.PermissionHelper; - @PersistenceCapable(detachable = "true") public class UserEntry { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/UserStatsEntry.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/UserStatsEntry.java index 6799725..3dff25e 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/UserStatsEntry.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/UserStatsEntry.java @@ -1,5 +1,7 @@ package com.intelliq.appengine.datastore.entries; +import com.google.appengine.api.datastore.Key; + import java.util.Date; import javax.jdo.annotations.IdGeneratorStrategy; @@ -7,8 +9,6 @@ import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; -import com.google.appengine.api.datastore.Key; - @PersistenceCapable(detachable = "true") public class UserStatsEntry { diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/queries/ImageQuery.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/queries/ImageQuery.java index 7b4e336..73ec78a 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/queries/ImageQuery.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/queries/ImageQuery.java @@ -1,5 +1,10 @@ package com.intelliq.appengine.datastore.queries; +import com.google.appengine.api.datastore.Key; +import com.google.appengine.api.datastore.KeyFactory; +import com.intelliq.appengine.datastore.PMF; +import com.intelliq.appengine.datastore.entries.ImageEntry; + import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; @@ -7,11 +12,6 @@ import javax.jdo.PersistenceManager; import javax.jdo.Query; -import com.google.appengine.api.datastore.Key; -import com.google.appengine.api.datastore.KeyFactory; -import com.intelliq.appengine.datastore.PMF; -import com.intelliq.appengine.datastore.entries.ImageEntry; - public class ImageQuery { private static final Logger log = Logger.getLogger(ImageQuery.class.getName()); diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/BusinessLogging.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/BusinessLogging.java index bd9088e..f98eaea 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/BusinessLogging.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/BusinessLogging.java @@ -1,9 +1,7 @@ package com.intelliq.appengine.logging; import com.intelliq.appengine.api.endpoint.business.BusinessEndpoint; -import com.intelliq.appengine.api.endpoint.queue.QueueEndpoint; import com.intelliq.appengine.datastore.entries.BusinessEntry; -import com.intelliq.appengine.datastore.entries.QueueEntry; import com.intelliq.appengine.datastore.entries.UserEntry; import net.steppschuh.slackmessagebuilder.message.attachment.Attachment; diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/QueueLogging.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/QueueLogging.java index daff60a..b3e1e52 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/QueueLogging.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/QueueLogging.java @@ -1,7 +1,6 @@ package com.intelliq.appengine.logging; import com.intelliq.appengine.api.endpoint.queue.QueueEndpoint; -import com.intelliq.appengine.api.endpoint.user.SignInUserEndpoint; import com.intelliq.appengine.datastore.entries.QueueEntry; import com.intelliq.appengine.datastore.entries.UserEntry; diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/UserLogging.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/UserLogging.java index 24d868e..0fd233d 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/UserLogging.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/logging/UserLogging.java @@ -1,6 +1,5 @@ package com.intelliq.appengine.logging; -import com.intelliq.appengine.api.endpoint.user.SignInUserEndpoint; import com.intelliq.appengine.api.endpoint.user.UserEndpoint; import com.intelliq.appengine.datastore.entries.UserEntry; diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/Notification.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/Notification.java new file mode 100644 index 0000000..dc023bd --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/Notification.java @@ -0,0 +1,62 @@ +package com.intelliq.appengine.notification; + +import java.util.Arrays; +import java.util.List; + +/** + * Created by Steppschuh on 04/03/2017. + */ + +public abstract class Notification { + + public static final String ORIGINATOR_INTELLIQ = "IntelliQ.me"; + + protected String originator = ORIGINATOR_INTELLIQ; + protected String body; + protected List recipients; + + public Notification() { + } + + public String getOriginator() { + return originator; + } + + public Notification setOriginator(String originator) { + this.originator = originator; + return this; + } + + public String getBody() { + return body; + } + + public Notification setBody(String body) { + this.body = body; + return this; + } + + public List getRecipients() { + return recipients; + } + + public Notification setRecipients(List recipients) { + this.recipients = recipients; + return this; + } + + public Notification setRecipient(T recipient) { + this.recipients = Arrays.asList(recipient); + return this; + } + + public Notification send() throws NotificationException { + if (NotificationManager.getInstance().canSendNotification(this)) { + NotificationManager.getInstance().sendNotification(this); + } else { + throw new NotificationException("Notification can not be sent"); + } + return this; + } + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationException.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationException.java new file mode 100644 index 0000000..092e077 --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationException.java @@ -0,0 +1,25 @@ +package com.intelliq.appengine.notification; + +/** + * Created by Steppschuh on 05/03/2017. + */ + +public class NotificationException extends Exception { + + public NotificationException() { + super(); + } + + public NotificationException(String message) { + super(message); + } + + public NotificationException(String message, Throwable cause) { + super(message, cause); + } + + public NotificationException(Throwable cause) { + super(cause); + } + +} \ No newline at end of file diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationManager.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationManager.java new file mode 100644 index 0000000..20e7548 --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationManager.java @@ -0,0 +1,66 @@ +package com.intelliq.appengine.notification; + +import com.intelliq.appengine.notification.text.MessageBird; +import com.intelliq.appengine.notification.text.TextNotificationSender; +import com.intelliq.appengine.util.KeyStore; + +import java.util.logging.Logger; + +/** + * Created by Steppschuh on 06/03/2017. + */ + +public final class NotificationManager extends NotificationSender { + + private static final Logger log = Logger.getLogger(NotificationManager.class.getName()); + + private static NotificationManager instance; + + private TextNotificationSender textNotificationSender; + + private NotificationManager() { + textNotificationSender = new MessageBird(KeyStore.getKey(KeyStore.MESSAGE_BIRD_KEY_PRODUCTION)); + } + + public static NotificationManager getInstance() { + if (instance == null) { + instance = new NotificationManager(); + } + return instance; + } + + @Override + public boolean canSendNotifications() { + return textNotificationSender.canSendNotifications(); + } + + @Override + public boolean canSendNotification(Notification notification) { + try { + return getBestNotificationSender(notification).canSendNotification(notification); + } catch (NotificationException e) { + log.warning("Unable to get NotificationSender: " + e.getMessage()); + return false; + } + } + + @Override + public void sendNotification(Notification notification) throws NotificationException { + getBestNotificationSender(notification).sendNotification(notification); + } + + /** + * Will return the NotificationSender which is best suited for delivering + * the specified notification. + * + * @param notification + */ + public NotificationSender getBestNotificationSender(Notification notification) throws NotificationException { + return textNotificationSender; + } + + public TextNotificationSender getTextNotificationSender() { + return textNotificationSender; + } + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationRecipient.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationRecipient.java new file mode 100644 index 0000000..20f8c94 --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationRecipient.java @@ -0,0 +1,23 @@ +package com.intelliq.appengine.notification; + +/** + * Created by Steppschuh on 06/03/2017. + */ + +public abstract class NotificationRecipient { + + private String name; + + public NotificationRecipient() { + } + + public String getName() { + return name; + } + + public NotificationRecipient setName(String name) { + this.name = name; + return this; + } + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationSender.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationSender.java new file mode 100644 index 0000000..d049a54 --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/NotificationSender.java @@ -0,0 +1,57 @@ +package com.intelliq.appengine.notification; + +/** + * Created by Steppschuh on 04/03/2017. + */ + +public abstract class NotificationSender { + + protected boolean serviceEnabled = true; + + public NotificationSender() { + } + + /** + * Checks if the notification sender is operational at all. + */ + public boolean canSendNotifications() { + return serviceEnabled; + } + + /** + * Checks if the specified notification can (potentially) be delivered. + * + * @param notification + */ + public boolean canSendNotification(T notification) { + if (!canSendNotifications()) { + return false; + } + + // check recipients + if (notification.getRecipients().isEmpty()) { + return false; + } + + // check body + if (notification.getBody() == null || notification.getBody().length() < 1) { + return false; + } + + // check originator + if (notification.getOriginator() == null || notification.getOriginator().length() < 1) { + return false; + } + + return true; + } + + /** + * Tries to deliver the specified notification + * + * @param notification + * @throws NotificationException if the notification could not be delivered + */ + public abstract void sendNotification(T notification) throws NotificationException; + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/MessageBird.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/MessageBird.java new file mode 100644 index 0000000..767b08f --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/MessageBird.java @@ -0,0 +1,100 @@ +package com.intelliq.appengine.notification.text; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.intelliq.appengine.notification.NotificationException; +import com.intelliq.appengine.notification.NotificationManager; +import com.intelliq.appengine.util.Request; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +/** + * Created by Steppschuh on 05/03/2017. + */ + +public class MessageBird extends TextNotificationSender { + + private static final Logger log = Logger.getLogger(NotificationManager.class.getName()); + + private static final String MESSAGE_API_ENDPOINT = "https://rest.messagebird.com/messages"; + + private static final String PARAMETER_RECIPIENTS = "recipients"; + private static final String PARAMETER_ORIGINATOR = "originator"; + private static final String PARAMETER_BODY = "body"; + + private static final String HEADER_AUTHORIZATION = "Authorization"; + private static final String HEADER_ACCEPT = "Accept"; + private static final String HEADER_CONTENT_TYPE = "Content-Type"; + + private static final String KEY_ERRORS = "errors"; + private static final String KEY_DESCRIPTION = "description"; + + private String apiKey; + + public MessageBird(String apiKey) { + this.apiKey = apiKey; + } + + @Override + public void sendNotification(TextNotification textNotification) throws NotificationException { + List msisdnNumbers = getMsisdnNumbersFromRecipients(textNotification.getRecipients()); + + try { + String response = new Request() + .setUrl(MESSAGE_API_ENDPOINT) + .setHeader(HEADER_AUTHORIZATION, getAuthorizationHeader(apiKey)) + .setHeader(HEADER_ACCEPT, "application/json") + .setHeader(HEADER_CONTENT_TYPE, "application/json") + .setJsonProperty(PARAMETER_RECIPIENTS, getAsCsvString(msisdnNumbers)) + .setJsonProperty(PARAMETER_BODY, textNotification.getBody()) + .setJsonProperty(PARAMETER_ORIGINATOR, textNotification.getOriginator()) + .postJson(); + + log.info("Response from MessageBird API:\n" + response); + + // check response for errors + JsonParser parser = new JsonParser(); + JsonObject jsonObject = parser.parse(response).getAsJsonObject(); + if (jsonObject.has(KEY_ERRORS)) { + JsonArray errors = jsonObject.get(KEY_ERRORS).getAsJsonArray(); + if (errors.size() > 0) { + JsonObject error = errors.get(0).getAsJsonObject(); + if (error.has(KEY_DESCRIPTION)) { + throw new MessageBirdException(error.get(KEY_DESCRIPTION).getAsString()); + } + } + throw new MessageBirdException("Unable to get error from response:\n" + response); + } + } catch (IOException | MessageBirdException e) { + throw new NotificationException("Unable to send notification: " + e.getMessage(), e); + } + } + + public static List getMsisdnNumbersFromRecipients(List recipients) { + List msisdnNumbers = new ArrayList<>(); + for (TextNotificationRecipient notificationRecipient : recipients) { + msisdnNumbers.add(notificationRecipient.getMsisdn()); + } + return msisdnNumbers; + } + + public static String getAsCsvString(List values) { + if (values == null || values.isEmpty()) { + return ""; + } + final StringBuilder sb = new StringBuilder(); + for (String value : values) { + sb.append(value).append(","); + } + return sb.substring(0, sb.length() - 1); + } + + public static String getAuthorizationHeader(String apiKey) { + return "AccessKey " + apiKey; + } + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/MessageBirdException.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/MessageBirdException.java new file mode 100644 index 0000000..3dda68a --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/MessageBirdException.java @@ -0,0 +1,25 @@ +package com.intelliq.appengine.notification.text; + +/** + * Created by Steppschuh on 07/03/2017. + */ + +public class MessageBirdException extends Exception { + + public MessageBirdException() { + super(); + } + + public MessageBirdException(String message) { + super(message); + } + + public MessageBirdException(String message, Throwable cause) { + super(message, cause); + } + + public MessageBirdException(Throwable cause) { + super(cause); + } + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/TextNotification.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/TextNotification.java new file mode 100644 index 0000000..cf71ff5 --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/TextNotification.java @@ -0,0 +1,14 @@ +package com.intelliq.appengine.notification.text; + +import com.intelliq.appengine.notification.Notification; + +/** + * Created by Steppschuh on 04/03/2017. + */ + +public class TextNotification extends Notification { + + public TextNotification() { + } + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/TextNotificationRecipient.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/TextNotificationRecipient.java new file mode 100644 index 0000000..01d090a --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/TextNotificationRecipient.java @@ -0,0 +1,29 @@ +package com.intelliq.appengine.notification.text; + +import com.intelliq.appengine.notification.NotificationRecipient; + +/** + * Created by Steppschuh on 06/03/2017. + */ + +public class TextNotificationRecipient extends NotificationRecipient { + + private String msisdn; + + public TextNotificationRecipient() { + } + + public TextNotificationRecipient(String msisdn) { + this.msisdn = msisdn; + } + + public String getMsisdn() { + return msisdn; + } + + public TextNotificationRecipient setMsisdn(String msisdn) { + this.msisdn = msisdn; + return this; + } + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/TextNotificationSender.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/TextNotificationSender.java new file mode 100644 index 0000000..f670393 --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/notification/text/TextNotificationSender.java @@ -0,0 +1,14 @@ +package com.intelliq.appengine.notification.text; + +import com.intelliq.appengine.notification.NotificationSender; + +/** + * Created by Steppschuh on 04/03/2017. + */ + +public abstract class TextNotificationSender extends NotificationSender { + + public TextNotificationSender() { + } + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/util/KeyStore.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/util/KeyStore.java new file mode 100644 index 0000000..4c58047 --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/util/KeyStore.java @@ -0,0 +1,109 @@ +package com.intelliq.appengine.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.logging.Logger; + +/** + * Created by Steppschuh on 03/03/2017. + */ + +public final class KeyStore { + + private static final Logger log = Logger.getLogger(KeyStore.class.getName()); + + private static final String KEYSTORE_PROPERTIES_FILE_NAME = "keystore.properties"; + + public static final String MESSAGE_BIRD_KEY_DEV = "MESSAGE_BIRD_KEY_DEV"; + public static final String MESSAGE_BIRD_KEY_PRODUCTION = "MESSAGE_BIRD_KEY_PRODUCTION"; + + private static KeyStore instance; + private Properties keys = new Properties(); + + private KeyStore() { + try { + InputStream inputStream = new FileInputStream(getPropertiesFile()); + keys.load(inputStream); + } catch (IOException e) { + log.severe("Unable to load keystore properties file: " + e.getMessage()); + e.printStackTrace(); + } + } + + public static KeyStore getInstance() { + if (instance == null) { + instance = new KeyStore(); + } + return instance; + } + + public static String getKey(String key) { + return getInstance().keys.getProperty(key, key); + } + + public Properties getKeys() { + return keys; + } + + /** + * Attempts to find the {@link #KEYSTORE_PROPERTIES_FILE_NAME} and returns it as File. + * + * @return + */ + private static File getPropertiesFile() throws FileNotFoundException { + List files = new ArrayList<>(); + files.add(new File("WEB-INF/" + KEYSTORE_PROPERTIES_FILE_NAME)); + files.add(new File(System.getProperty("user.dir") + "/backend/src/main/webapp/WEB-INF/" + KEYSTORE_PROPERTIES_FILE_NAME)); + + for (File file : files) { + if (file.exists()) { + return file; + } else { + log.info("Unable to find keystore properties file: " + file.getAbsolutePath()); + } + } + + File propertiesFile = findPropertiesFile(Paths.get(System.getProperty("user.dir"))); + if (propertiesFile.exists()) { + log.info("Found keystore properties file: " + propertiesFile.getAbsolutePath()); + return propertiesFile; + } else { + throw new FileNotFoundException("Unable to find any keystore properties file"); + } + } + + /** + * Traverses the specified directory and returns the first file that + * matches the {@link #KEYSTORE_PROPERTIES_FILE_NAME}. + * + * @param dir + * @return + */ + private static File findPropertiesFile(Path dir) throws FileNotFoundException { + try (DirectoryStream stream = Files.newDirectoryStream(dir)) { + for (Path path : stream) { + if (path.toFile().isDirectory()) { + return findPropertiesFile(path); + } else { + if (path.getFileName().toString().contains(KEYSTORE_PROPERTIES_FILE_NAME)) { + return path.toFile(); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + throw new FileNotFoundException("Unable to find file with name: " + KEYSTORE_PROPERTIES_FILE_NAME); + } + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/util/Request.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/util/Request.java new file mode 100644 index 0000000..e7a98db --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/util/Request.java @@ -0,0 +1,177 @@ +package com.intelliq.appengine.util; + +import com.google.gson.JsonObject; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +/** + * Created by Steppschuh on 06/03/2017. + */ + +public class Request { + + public static final String METHOD_GET = "GET"; + public static final String METHOD_POST = "POST"; + + private URL url; + private Map parameters; + private Map headers; + private JsonObject jsonObject = new JsonObject(); + + public Request() { + } + + public String post() throws IOException { + return post(url, parameters, headers); + } + + public String postJson() throws IOException { + return post(url, jsonObject.toString(), headers); + } + + public static String post(URL url, Map parameters, Map headers) throws IOException { + StringBuilder sb = new StringBuilder(); + for (Map.Entry parameterEntry : parameters.entrySet()) { + sb.append(parameterEntry.getKey()) + .append("=") + .append(parameterEntry.getValue()) + .append("\n"); + } + return post(url, sb.toString(), headers); + } + + public static String post(URL url, String data, Map headers) throws IOException { + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setRequestMethod(METHOD_POST); + + // set headers + for (Map.Entry headerEntry : headers.entrySet()) { + connection.setRequestProperty(headerEntry.getKey(), headerEntry.getValue()); + } + + // send data + OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); + writer.write(data); + writer.flush(); + writer.close(); + connection.getOutputStream().close(); + + // read response + InputStream stream; + try { + stream = connection.getInputStream(); + } catch (IOException e) { + stream = connection.getErrorStream(); + } + return readStreamToString(stream); + } + + public URL getUrl() { + return url; + } + + public Request setUrl(URL url) { + this.url = url; + return this; + } + + public Request setUrl(String url) { + try { + this.url = new URL(url); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + return this; + } + + public Map getParameters() { + return parameters; + } + + public Request setParameters(Map parameters) { + this.parameters = parameters; + return this; + } + + public Request setEncodedParameter(String key, Object value) { + try { + return setParameter(key, encode(value)); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return this; + } + + public Request setParameter(String key, Object value) { + if (parameters == null) { + parameters = new HashMap<>(); + } + parameters.put(key, value); + return this; + } + + public Map getHeaders() { + return headers; + } + + public Request setHeaders(Map headers) { + this.headers = headers; + return this; + } + + public Request setHeader(String key, String value) { + if (headers == null) { + headers = new HashMap<>(); + } + headers.put(key, value); + return this; + } + + public JsonObject getJsonObject() { + return jsonObject; + } + + public Request setJsonObject(JsonObject jsonObject) { + this.jsonObject = jsonObject; + return this; + } + + public Request setJsonProperty(String key, String value) { + if (jsonObject == null) { + jsonObject = new JsonObject(); + } + jsonObject.addProperty(key, value); + return this; + } + + + public static String readStreamToString(InputStream inputStream) throws IOException { + StringBuilder responseString = new StringBuilder(); + String line; + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + while ((line = reader.readLine()) != null) { + responseString.append(line); + } + reader.close(); + return responseString.toString(); + } + + public static String encode(Object value) throws UnsupportedEncodingException { + return URLEncoder.encode(value.toString(), StandardCharsets.UTF_8.name()); + } + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/util/TimeUtils.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/util/TimeUtils.java new file mode 100644 index 0000000..c0ada52 --- /dev/null +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/util/TimeUtils.java @@ -0,0 +1,58 @@ +package com.intelliq.appengine.util; + +import java.util.concurrent.TimeUnit; + +/** + * Created by Steppschuh on 07/03/2017. + */ + +public final class TimeUtils { + + public static final long roundMilliseconds(long milliseconds, long rounding) { + rounding = Math.max(1, rounding); + return (milliseconds / rounding) * rounding; + } + + public static final String getReadableTimeFromMillis(long milliseconds) { + long millis = Math.max(0, milliseconds); + long days = TimeUnit.MILLISECONDS.toDays(millis); + millis -= TimeUnit.DAYS.toMillis(days); + long hours = TimeUnit.MILLISECONDS.toHours(millis); + millis -= TimeUnit.HOURS.toMillis(hours); + long minutes = TimeUnit.MILLISECONDS.toMinutes(millis); + millis -= TimeUnit.MINUTES.toMillis(minutes); + long seconds = TimeUnit.MILLISECONDS.toSeconds(millis); + + StringBuilder sb = new StringBuilder(); + boolean appendDelimiter = false; + + if (days > 0) { + sb.append(days).append(" day").append(days != 1 ? "s" : ""); + appendDelimiter = true; + } + if (hours > 0) { + sb.append(appendDelimiter ? ", " : ""); + sb.append(hours).append(" hour").append(hours != 1 ? "s" : ""); + appendDelimiter = true; + } + if (minutes > 0) { + sb.append(appendDelimiter ? ", " : ""); + sb.append(minutes).append(" minute").append(minutes != 1 ? "s" : ""); + appendDelimiter = true; + } + if (seconds > 0 || sb.length() == 0) { + sb.append(appendDelimiter ? ", " : ""); + sb.append(seconds).append(" second").append(seconds != 1 ? "s" : ""); + } + + // replace last comma with and + String readableTime = sb.toString(); + int lastCommaIndex = readableTime.lastIndexOf(","); + if (lastCommaIndex != -1) { + readableTime = readableTime.substring(0, lastCommaIndex) + " and" + readableTime.substring(lastCommaIndex + 1); + } + + return readableTime; + } + +} diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/website/IntelliQServlet.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/website/IntelliQServlet.java index 5844935..a1b710c 100644 --- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/website/IntelliQServlet.java +++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/website/IntelliQServlet.java @@ -1,12 +1,14 @@ package com.intelliq.appengine.website; +import com.intelliq.appengine.RequestFilter; + import java.io.IOException; import java.util.logging.Logger; import javax.servlet.RequestDispatcher; -import javax.servlet.http.*; - -import com.intelliq.appengine.RequestFilter; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") public class IntelliQServlet extends HttpServlet { diff --git a/IntelliQ/backend/src/main/webapp/static/css/style.css b/IntelliQ/backend/src/main/webapp/static/css/style.css index efe06a7..e1f6f11 100644 --- a/IntelliQ/backend/src/main/webapp/static/css/style.css +++ b/IntelliQ/backend/src/main/webapp/static/css/style.css @@ -401,12 +401,14 @@ footer.page-footer { } /* label focus color */ .input-field input[type=text]:focus + label, +.input-field input[type=tel]:focus + label, .input-field input[type=number]:focus + label, .input-field input[type=email]:focus + label { color: #663fb4; } /* label underline focus color */ .input-field input[type=text]:focus, +.input-field input[type=tel]:focus, .input-field input[type=number]:focus, .input-field input[type=email]:focus { border-bottom: 1px solid #663fb4; @@ -414,6 +416,7 @@ footer.page-footer { } /* valid color */ .input-field input[type=text].valid, +.input-field input[type=tel].valid, .input-field input[type=number].valid, .input-field input[type=email].valid { border-bottom: 1px solid #000; diff --git a/IntelliQ/backend/src/main/webapp/static/js/api.js b/IntelliQ/backend/src/main/webapp/static/js/api.js index d713719..b039e61 100644 --- a/IntelliQ/backend/src/main/webapp/static/js/api.js +++ b/IntelliQ/backend/src/main/webapp/static/js/api.js @@ -579,6 +579,11 @@ var intelliqApi = function(){ return request; } + request.withPhoneNumber = function(value) { + request.addParameter("phoneNumber", value); + return request; + } + return request; } diff --git a/IntelliQ/backend/src/main/webapp/static/js/manage_queue.js b/IntelliQ/backend/src/main/webapp/static/js/manage_queue.js index 6b928a1..1f5e46c 100644 --- a/IntelliQ/backend/src/main/webapp/static/js/manage_queue.js +++ b/IntelliQ/backend/src/main/webapp/static/js/manage_queue.js @@ -417,6 +417,12 @@ function populateQueue() { function showAddNewQueueItemModal() { $("#newCustomerName").val(""); + $("#phoneNumber").val(""); + if (queue && queue.textNotificationsEnabled) { + $("#phoneNumberContainer").removeClass("hide"); + } else { + $("#phoneNumberContainer").addClass("hide"); + } $("#addCustomerModal").openModal(); $("#newCustomerName").focus(); tracking.trackEvent(tracking.CATEGORY_QUEUE_MANAGE, "Show new queue item modal"); @@ -425,12 +431,14 @@ function showAddNewQueueItemModal() { function onAddNewCustomerModalSubmitted() { try { var name = $("#newCustomerName").val(); + var phoneNumber = $("#phoneNumber").val(); var hideName = $("#newCustomerVisibility").prop("checked") == false; Materialize.toast(getString("adding", name), 3000); var request = intelliqApi.addQueueItem(queue.key.id) .withName(name) .hideName(hideName) + .withPhoneNumber(phoneNumber) .setGoogleIdToken(authenticator.getGoogleUserIdToken()); request.send().then(function(data){ @@ -442,6 +450,7 @@ function onAddNewCustomerModalSubmitted() { }); $("#addCustomerModal").closeModal(); tracking.trackEvent(tracking.CATEGORY_QUEUE_MANAGE, "Submit new queue item modal", name, hideName ? 1 : 0); + tracking.trackEvent(tracking.CATEGORY_QUEUE_MANAGE, "Phone number provided by management", phoneNumber); } catch(error) { console.log(error); ui.showErrorMessage(error); @@ -449,6 +458,9 @@ function onAddNewCustomerModalSubmitted() { } function showQueueItemDetailsModal(queueItem) { + console.log("Showing queue item details"); + console.log(queueItem); + var modal = $("#customerDetailsModal"); modal.find("h4").text(queueItem.name); @@ -462,6 +474,10 @@ function showQueueItemDetailsModal(queueItem) { modal.find("#customerQueueEntry").text(joined); modal.find("#customerStatusChange").text(changed); + if (queueItem.phoneNumber && queueItem.phoneNumber.length > 0) { + modal.find("#customerPhoneNumber").text(queueItem.phoneNumber); + } + modal.find("#reportCustomerButton").off().click(function() { reportQueueItem(queueItem); }); @@ -469,11 +485,13 @@ function showQueueItemDetailsModal(queueItem) { modal.openModal(); // request more user details + /* requestUser(queueItem.userKeyId).then(function(user) { console.log(user); }).catch(function(error) { console.log(error); }); + */ tracking.trackEvent(tracking.CATEGORY_QUEUE_MANAGE, "Show queue item details", queueItem.name, queueItem.ticketNumber); } diff --git a/IntelliQ/backend/src/main/webapp/static/js/webapp_queue.js b/IntelliQ/backend/src/main/webapp/static/js/webapp_queue.js index d2c7ba8..4185828 100644 --- a/IntelliQ/backend/src/main/webapp/static/js/webapp_queue.js +++ b/IntelliQ/backend/src/main/webapp/static/js/webapp_queue.js @@ -87,7 +87,7 @@ function requestQueueItem() { if (ticketActive) { onQueueJoined(queueItem); } else { - $("#joinQueueButton").addClass("disabled"); + onQueueLeft(); } } catch(error) { console.log(error); @@ -139,14 +139,7 @@ function leaveQueue(queue) { request.send().then(function(data){ try { console.log(data); - - // delete cookies - deleteCookie("queueKeyId"); - deleteCookie("queueItemKeyId"); - deleteCookie("queueItem"); - onQueueLeft(); - tracking.trackEvent(tracking.CATEGORY_WEBAPP, "Queue item canceled", queue.name, queue.key.id); location.reload(); } catch(error) { @@ -190,20 +183,29 @@ function showJoinQueueModal() { $("#newCustomerName").val(userName); } }); + + if (queue && queue.textNotificationsEnabled) { + $("#phoneNumberContainer").removeClass("hide"); + } else { + $("#phoneNumberContainer").addClass("hide"); + } + $("#joinQueueModal").openModal(); $("#newCustomerName").focus(); - tracking.trackEvent(tracking.CATEGORY_WEBAPP, "Show join queue modal"); + tracking.trackEvent(tracking.CATEGORY_WEBAPP, "Show join queue modal", queue.name, queue.key.id); } function onJoinQueueModalSubmitted() { try { var name = $("#newCustomerName").val(); var hideName = $("#newCustomerVisibility").prop("checked") == false; + var phoneNumber = $("#phoneNumber").val(); Materialize.toast(getString("joiningQueue"), 3000); var request = intelliqApi.addQueueItem(queue.key.id) .withName(name) .hideName(hideName) + .withPhoneNumber(phoneNumber) .usingApp(true); if (authenticator.getGoogleSignInStatus()) { @@ -218,14 +220,7 @@ function onJoinQueueModalSubmitted() { throw "Queue item not found"; } queueItem = queueItems[0]; - - // persist data in cookies - setCookie("queueKeyId", queueItem.queueKeyId); - setCookie("queueItemKeyId", queueItem.key.id); - setCookie("queueItem", JSON.stringify(queueItem)); - onQueueJoined(queueItem); - tracking.trackEvent(tracking.CATEGORY_WEBAPP, "Queue joined", queue.name, queue.key.id); // update url @@ -240,8 +235,12 @@ function onJoinQueueModalSubmitted() { console.log(error); ui.showErrorMessage(error); }); + $("#joinQueueModal").closeModal(); tracking.trackEvent(tracking.CATEGORY_WEBAPP, "Submit join queue modal", queue.name, queue.key.id); + if (phoneNumber && phoneNumber.length > 0) { + tracking.trackEvent(tracking.CATEGORY_WEBAPP, "Phone number provided by user", phoneNumber); + } } catch(error) { console.log(error); ui.showErrorMessage(error); @@ -249,17 +248,29 @@ function onJoinQueueModalSubmitted() { } function onQueueJoined(queueItem) { - onQueueItemsChanged(); + // set cookies + setCookie("queueKeyId", queueItem.queueKeyId); + setCookie("queueItemKeyId", queueItem.key.id); + setCookie("queueItem", JSON.stringify(queueItem)); + $("#joinQueueContainer").addClass("hide"); $("#joinQueueButton").addClass("disabled"); $("#leaveQueueContainer").removeClass("hide"); $("#leaveQueueButton").removeClass("disabled"); + + onQueueItemsChanged(); } function onQueueLeft() { - onQueueItemsChanged(); + // delete cookies + deleteCookie("queueKeyId"); + deleteCookie("queueItemKeyId"); + deleteCookie("queueItem"); + $("#joinQueueContainer").removeClass("hide"); $("#joinQueueButton").removeClass("disabled"); $("#leaveQueueContainer").addClass("hide"); $("#leaveQueueButton").addClass("disabled"); + + onQueueItemsChanged(); } \ No newline at end of file diff --git a/IntelliQ/backend/src/main/webapp/website/en/manage_overview.jsp b/IntelliQ/backend/src/main/webapp/website/en/manage_overview.jsp index f437943..bf97c24 100644 --- a/IntelliQ/backend/src/main/webapp/website/en/manage_overview.jsp +++ b/IntelliQ/backend/src/main/webapp/website/en/manage_overview.jsp @@ -35,7 +35,7 @@
business - Add Businenss + Add Business
Businesses are in charge of managing one or more queues. If you want other users to be able to manage a business or some of its queues, you can grant them permissions to do so. Other users won't be able to perform administrative operations, though.
diff --git a/IntelliQ/backend/src/main/webapp/website/en/manage_queue.jsp b/IntelliQ/backend/src/main/webapp/website/en/manage_queue.jsp index 1fcc137..48ab2b3 100644 --- a/IntelliQ/backend/src/main/webapp/website/en/manage_queue.jsp +++ b/IntelliQ/backend/src/main/webapp/website/en/manage_queue.jsp @@ -147,13 +147,19 @@