diff --git a/IntelliQ/backend/datastore/datastore-indexes-auto.xml b/IntelliQ/backend/datastore/datastore-indexes-auto.xml
index dd4f99f..6cfb091 100644
--- a/IntelliQ/backend/datastore/datastore-indexes-auto.xml
+++ b/IntelliQ/backend/datastore/datastore-indexes-auto.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/IntelliQ/backend/datastore/local_db.bin b/IntelliQ/backend/datastore/local_db.bin
index 36934e1..5f261b1 100644
Binary files a/IntelliQ/backend/datastore/local_db.bin and b/IntelliQ/backend/datastore/local_db.bin differ
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 2983ada..74bd994 100644
--- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/ImageServlet.java
+++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/ImageServlet.java
@@ -1,23 +1,18 @@
package com.intelliq.appengine;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.logging.Logger;
-
-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.Key;
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;
import com.intelliq.appengine.datastore.entries.BusinessEntry;
import com.intelliq.appengine.datastore.entries.ImageEntry;
+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.datastore.queries.ImageQuery;
import org.apache.commons.fileupload.FileItemIterator;
@@ -25,16 +20,29 @@
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.Logger;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
@SuppressWarnings("serial")
public class ImageServlet extends HttpServlet {
private static final Logger log = Logger.getLogger(ImageServlet.class.getName());
- @Override
- public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
+ // larger images will be rejected
+ private static final long MAXIMUM_UPLOAD_IMAGE_SIZE = 1024 * 1024 * 5;
- String requestUrl = req.getRequestURL().toString();
+ // larger images will be resized
+ private static final long MAXIMUM_PERSISTED_IMAGE_SIZE = 1024 * 1024; // 1 mb is the Data Store entity limit
+ private static final int MAXIMUM_PERSISTED_IMAGE_WIDTH = 2000;
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
try {
// image request pattern: .../image/[imageKeyId]/[size].jpg
@@ -58,24 +66,36 @@ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOExc
ImageQuery imageQuery = new ImageQuery();
ImageEntry image = imageQuery.getImageByKeyId(imageKeyId);
- if (image.getImageType() == null || image.getImage() == null) {
- // image = EntryManager.fetchImageFromUrl(image.getUrl());
+ if (image.getImageType() == null) {
+ throw new Exception("Image type unavailable");
+ }
+
+ if (image.getImage() == null) {
throw new Exception("Image data unavailable");
}
resp.setContentType(image.getImageType());
resp.getOutputStream().write(ImageHelper.resizeImage(image.getImage(), imageSizeString));
} catch (Exception e) {
+ log.warning("Unable to get image: " + e.getMessage());
resp.sendRedirect("/static/images/not_found.jpg");
}
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
+ ApiRequest apiRequest = new ApiRequest(req);
ApiResponse responseObject = new ApiResponse();
- String response = "";
+ String response;
try {
+ UserEntry user;
+ try {
+ user = apiRequest.getUserFromToken();
+ } catch (Exception ex) {
+ throw new Exception("Request requires an authorized user: " + ex.getMessage());
+ }
+
ServletFileUpload upload = new ServletFileUpload();
res.setContentType("text/plain");
@@ -90,55 +110,112 @@ public void doPost(HttpServletRequest req, HttpServletResponse res) throws Servl
if (item.isFormField()) {
String key = item.getFieldName();
String value = Streams.asString(stream);
- log.info("Form field: " + key + ", value = " + value);
-
if (key.equals("parentKeyId")) {
image.setParentKeyId(Long.parseLong(value));
} else if (key.equals("type")) {
image.setType(Byte.parseByte(value));
+ } else if (key.equals("image")) {
+ String contentType = item.getContentType();
+ image.setImageType(contentType);
+ image.setImage(ByteStreams.toByteArray(stream));
}
} else {
- log.info("File: " + item.getFieldName() + ", key = " + item.getName());
-
String contentType = item.getContentType();
-
image.setImageType(contentType);
image.setImage(ByteStreams.toByteArray(stream));
}
}
- if (image.getParentKeyId() > 0) {
+ // verify that parentKeyId is set
+ if (image.getParentKeyId() == 0) {
+ responseObject.setStatusCode(HttpServletResponse.SC_BAD_REQUEST);
+ throw new Exception("Invalid parentKeyId specified");
+ }
- Key imageKey = ImageHelper.saveEntry(image);
- image.setKey(imageKey);
+ // verify image type
+ if (image.getImageType() == null) {
+ responseObject.setStatusCode(HttpServletResponse.SC_BAD_REQUEST);
+ throw new Exception("No image type available");
+ }
- // add the new image key id to the parent business or queue
- if (image.getType() == ImageEntry.TYPE_LOGO) {
- BusinessEntry businessEntry = BusinessHelper.getEntryByKeyId(image.getParentKeyId());
- if (businessEntry != null) {
- businessEntry.setLogoImageKeyId(image.getKey().getId());
- } else {
- throw new Exception("Can't find parent business with Id: " + image.getParentKeyId());
- }
- BusinessHelper.saveEntry(businessEntry);
- } else {
- QueueEntry queueEntry = QueueHelper.getEntryByKeyId(image.getParentKeyId());
- if (queueEntry != null) {
- queueEntry.setPhotoImageKeyId(image.getKey().getId());
- } else {
- throw new Exception("Can't find parent queue with Id: " + image.getParentKeyId());
- }
- QueueHelper.saveEntry(queueEntry);
- }
+ // verify image data
+ if (image.getImage() == null) {
+ responseObject.setStatusCode(HttpServletResponse.SC_BAD_REQUEST);
+ throw new Exception("No image data available");
+ }
- // remove the image data to use the same object as response
- image.setImage(null);
+ // verify file size
+ if (image.getImage().length > MAXIMUM_UPLOAD_IMAGE_SIZE) {
+ String readableImageSize = Math.round(image.getImage().length / 1024) + " kb";
+ String readableMaximumSize = Math.round(MAXIMUM_UPLOAD_IMAGE_SIZE / 1024) + " kb";
+ responseObject.setStatusCode(HttpServletResponse.SC_BAD_REQUEST);
+ throw new Exception("Image exceeds the maximum file size. File size limit is "
+ + readableMaximumSize + ", uploaded image size is " + readableImageSize);
+ }
- responseObject.setContent(image);
- response = responseObject.toJSON();
+ // resize image
+ try {
+ image.resizeTo(MAXIMUM_PERSISTED_IMAGE_WIDTH, MAXIMUM_PERSISTED_IMAGE_SIZE);
+ } catch (Exception e) {
+ log.warning("Unable to resize image: " + e.getMessage());
+ }
+
+ // save image entry
+ Key imageKey = ImageHelper.saveEntry(image);
+ image.setKey(imageKey);
+
+ // add the new image key id to the parent business or queue
+ long oldImageKeyId;
+ if (image.getType() == ImageEntry.TYPE_LOGO) {
+ PermissionEntry editBusinessPermission = new PermissionEntry();
+ editBusinessPermission.setSubjectKeyId(image.getParentKeyId());
+ editBusinessPermission.setPermission(PermissionEntry.PERMISSION_EDIT);
+ if (!user.hasPermission(editBusinessPermission)) {
+ responseObject.setStatusCode(HttpServletResponse.SC_FORBIDDEN);
+ throw new Exception("User doesn't have the permission to edit this business");
+ }
+ BusinessEntry businessEntry = BusinessHelper.getEntryByKeyId(image.getParentKeyId());
+ if (businessEntry != null) {
+ oldImageKeyId = businessEntry.getLogoImageKeyId();
+ businessEntry.setLogoImageKeyId(image.getKey().getId());
+ } else {
+ throw new Exception("Can't find parent business with Id: " + image.getParentKeyId());
+ }
+ BusinessHelper.saveEntry(businessEntry);
} else {
- throw new Exception("Invalid parentKeyId specified");
+ PermissionEntry editQueuePermission = new PermissionEntry();
+ editQueuePermission.setSubjectKeyId(image.getParentKeyId());
+ editQueuePermission.setPermission(PermissionEntry.PERMISSION_EDIT);
+ if (!user.hasPermission(editQueuePermission)) {
+ responseObject.setStatusCode(HttpServletResponse.SC_FORBIDDEN);
+ throw new Exception("User doesn't have the permission to edit this business");
+ }
+ QueueEntry queueEntry = QueueHelper.getEntryByKeyId(image.getParentKeyId());
+ if (queueEntry != null) {
+ oldImageKeyId = queueEntry.getPhotoImageKeyId();
+ queueEntry.setPhotoImageKeyId(image.getKey().getId());
+ } else {
+ throw new Exception("Can't find parent queue with Id: " + image.getParentKeyId());
+ }
+ QueueHelper.saveEntry(queueEntry);
}
+
+ // delete the old image, if set
+ if (oldImageKeyId > 0) {
+ try {
+ ImageHelper.deleteImageByKeyId(oldImageKeyId);
+ } catch (Exception e) {
+ log.warning("Unable to delete old image: " + e.getMessage());
+ }
+ }
+
+ // remove the image data to use the same object as response
+ image.setImage(null);
+
+ // TODO: log image update to slack, re-verify business / queue
+
+ responseObject.setContent(image);
+ response = responseObject.toJSON();
} catch (Exception e) {
responseObject.setException(e);
response = responseObject.toJSON();
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 fb09f71..42ec1e1 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
@@ -6,6 +6,7 @@
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;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
@@ -15,6 +16,7 @@
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;
public class ImageHelper {
@@ -35,6 +37,15 @@ public static Key saveEntry(ImageEntry entry) throws Exception {
return entryKey;
}
+ public static void deleteImageByKeyId(long id) {
+ log.severe("Deleting image with keyId: " + id);
+ PersistenceManager pm = PMF.get().getPersistenceManager();
+ Key key = KeyFactory.createKey(ImageEntry.class.getSimpleName(), id);
+ ImageEntry entry = pm.getObjectById(ImageEntry.class, key);
+ pm.deletePersistent(entry);
+ pm.close();
+ }
+
public static ImageEntry fetchImageFromUrl(String url) throws Exception {
log.info("Fetching image from " + url);
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 68b847b..7372671 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
@@ -35,10 +35,10 @@ public static Key saveEntry(PermissionEntry entry) throws Exception {
}
public static boolean hasPermission(PermissionEntry permissionEntry) {
- return hasPermission(permissionEntry.getUserKeyId(), permissionEntry.getSubjectKeyId(), permissionEntry.getSubjectKind(), permissionEntry.getPermission());
+ return hasPermission(permissionEntry.getUserKeyId(), permissionEntry.getSubjectKeyId(), permissionEntry.getPermission());
}
- public static boolean hasPermission(long userKeyId, long subjectKeyId, String subjectKind, int permission) {
+ public static boolean hasPermission(long userKeyId, long subjectKeyId, int permission) {
// check if this permission exists
if (getPermission(userKeyId, subjectKeyId, permission) != null) {
return true;
diff --git a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/ImageEntry.java b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/ImageEntry.java
index 47e31ce..16c1554 100644
--- a/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/ImageEntry.java
+++ b/IntelliQ/backend/src/main/java/com/intelliq/appengine/datastore/entries/ImageEntry.java
@@ -1,15 +1,16 @@
package com.intelliq.appengine.datastore.entries;
+import com.google.appengine.api.datastore.Blob;
+import com.google.appengine.api.datastore.Key;
+import com.google.appengine.api.datastore.KeyFactory;
+import com.intelliq.appengine.datastore.ImageHelper;
+
import javax.jdo.annotations.Extension;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
-import com.google.appengine.api.datastore.Blob;
-import com.google.appengine.api.datastore.Key;
-import com.google.appengine.api.datastore.KeyFactory;
-
@PersistenceCapable(detachable = "true")
public class ImageEntry {
@@ -39,6 +40,32 @@ public ImageEntry() {
}
+ public void resizeTo(int maximumWidth) {
+ resizeTo(maximumWidth, 1024 * 1024 * 5);
+ }
+
+ /**
+ * Tries to resize the image until its smaller than the specified width and size.
+ *
+ * @param maximumWidth the maximum width in pixels
+ * @param maximumSize the maximum size in bytes
+ */
+ public void resizeTo(int maximumWidth, long maximumSize) {
+ if (image != null) {
+ int maximumOperations = 5;
+ int resizeWidth = maximumWidth;
+ byte[] resizedImage = image.getBytes();
+ for (int operation = 0; operation < maximumOperations; operation++) {
+ resizedImage = ImageHelper.resizeImage(image.getBytes(), resizeWidth, false);
+ if (resizedImage.length <= maximumSize) {
+ break;
+ }
+ resizeWidth = resizeWidth - (resizeWidth / 4);
+ }
+ setImage(resizedImage);
+ }
+ }
+
public Key getKey() {
return key;
}
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 f9a7144..3ecf4c4 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
@@ -33,12 +33,10 @@ public class PermissionEntry {
int permission;
public PermissionEntry() {
- super();
this.permission = PERMISSION_NONE;
}
public PermissionEntry(long userKeyId, long subjectKeyId, String subjectKind, int permission) {
- super();
this.userKeyId = userKeyId;
this.subjectKeyId = subjectKeyId;
this.subjectKind = subjectKind;
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 7ce8d8b..2869c78 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
@@ -93,11 +93,7 @@ public boolean hasPermission(PermissionEntry requestedPermission) {
}
// look up the PermissionEntry in the data store
- if (this.key != null) {
- return PermissionHelper.hasPermission(requestedPermission);
- } else {
- return false;
- }
+ return PermissionHelper.hasPermission(requestedPermission);
}
@Override
diff --git a/IntelliQ/backend/src/main/webapp/static/js/api.js b/IntelliQ/backend/src/main/webapp/static/js/api.js
index 275cd3e..04e780c 100644
--- a/IntelliQ/backend/src/main/webapp/static/js/api.js
+++ b/IntelliQ/backend/src/main/webapp/static/js/api.js
@@ -5,11 +5,7 @@ var intelliqApi = function(){
}
function useDevelopmentServer() {
- if (top.location.hostname == "localhost") {
- return true;
- } else {
- return false;
- }
+ return top.location.hostname == "localhost";
}
var api = {
@@ -31,12 +27,14 @@ var intelliqApi = function(){
api.HOST_APP_ENGINE = "https://intelliq-me.appspot.com/";
api.HOST_APP_ENGINE_VERSIONED = "https://" + api.APP_ENGINE_VERSION + "-dot-intelliq-me.appspot.com/";
- // Request endpoints
if (useDevelopmentServer()) {
- api.ENDPOINT_API = api.HOST_LOCAL + "api/";
+ api.HOST = api.HOST_LOCAL;
} else {
- api.ENDPOINT_API = api.HOST_APP_ENGINE + "api/";
+ api.HOST = api.HOST_APP_ENGINE;
}
+
+ // Request endpoints
+ api.ENDPOINT_API = api.HOST + "api/";
api.ENDPOINT_USER = api.ENDPOINT_API + "user/";
api.ENDPOINT_USER_GET = api.ENDPOINT_USER + "get/";
@@ -69,6 +67,8 @@ var intelliqApi = function(){
api.ENDPOINT_QUEUE_ITEM_STATUS = api.ENDPOINT_QUEUE_ITEM + "status/";
api.ENDPOINT_QUEUE_ITEM_REPORT = api.ENDPOINT_QUEUE_ITEM + "report/";
+ api.ENDPOINT_IMAGE = "image/";
+
// Webpages
if (useDevelopmentServer()) {
api.PAGE_LINK = api.HOST_LOCAL;
@@ -105,6 +105,11 @@ var intelliqApi = function(){
api.ENTRY_TYPE_QUEUE_ITEM = "QueueItemEntry";
api.ENTRY_TYPE_USER = "UserEntry";
api.ENTRY_TYPE_PERMISSION = "PermissionEntry";
+ api.ENTRY_TYPE_IMAGE = "ImageEntry";
+
+ // Image types
+ api.IMAGE_TYPE_LOGO = 0;
+ api.IMAGE_TYPE_PHOTO = 1;
// Update intervals
api.UPDATE_INTERVAL_CASUAL = 1000 * 30;
@@ -654,6 +659,54 @@ var intelliqApi = function(){
return request;
}
+ /*
+ Image endpoints
+ */
+ api.uploadImage = function(parentKeyId, type, file, googleIdToken) {
+ var promise = new Promise(function(resolve, reject) {
+ var formData = new FormData();
+ formData.append("parentKeyId", parentKeyId);
+ formData.append("type", type);
+ formData.append("image", file);
+
+ var request = new XMLHttpRequest();
+ request.onreadystatechange = function () {
+ if(request.readyState === XMLHttpRequest.DONE) {
+ console.log("onreadystatechange");
+
+ data = JSON.parse(request.responseText);
+ console.log(data);
+
+ // check if the API returned a valid response
+ if (data.statusCode != null && data.statusCode == 200) {
+ // looks good
+ resolve(data);
+ } else {
+ // something went wrong, try to extract error message
+ if (data.statusMessage != null) {
+ reject(data.statusMessage);
+ } else {
+ reject("Request didn't return a valid response: " + data);
+ }
+ }
+ }
+ };
+
+ var requestUrl = intelliqApi.HOST + intelliqApi.ENDPOINT_IMAGE + "?googleIdToken=" + googleIdToken;
+ request.open("POST", requestUrl);
+ request.send(formData);
+ });
+ return promise;
+ }
+
+ api.uploadBusinessLogo = function(businessKeyId, file, googleIdToken) {
+ return api.uploadImage(businessKeyId, api.IMAGE_TYPE_LOGO, file, googleIdToken);
+ }
+
+ api.uploadQueuePhoto = function(queueKeyId, file, googleIdToken) {
+ return api.uploadImage(queueKeyId, api.IMAGE_TYPE_PHOTO, file, googleIdToken);
+ }
+
/*
Response helper
*/
diff --git a/IntelliQ/backend/src/main/webapp/static/js/edit_business.js b/IntelliQ/backend/src/main/webapp/static/js/edit_business.js
index dc0a19e..8b51c42 100644
--- a/IntelliQ/backend/src/main/webapp/static/js/edit_business.js
+++ b/IntelliQ/backend/src/main/webapp/static/js/edit_business.js
@@ -3,10 +3,11 @@ var newBusiness; // holds the new business, created by the local changes
(function($){
$(function(){
-
$("#saveBusinessButton").click(saveNewBusiness);
updateFormWithUrlParameterData();
+ setupImageUpload();
+
var statusChangeListener = {
onUserAvailable: function(user) {
var businessKeyId = getUrlParam("businessKeyId");
@@ -49,11 +50,13 @@ function requestExistingBusinessData(businessKeyId) {
function showAddBusinessUi() {
$("#businessHeading").text(getString("addBusiness"));
$("#saveBusinessButton").text(getString("save"));
+ $("#changeImageContainer").addClass("hide");
}
function showEditBusinessUi() {
$("#businessHeading").text(getString("editBusiness"));
$("#saveBusinessButton").text(getString("applyChanges"));
+ $("#changeImageContainer").removeClass("hide");
}
// fills the form fields with data from URL params
@@ -74,6 +77,8 @@ function updateFormWithBusinessData(business) {
$("#form-key-id").val(business.key.id);
$("#form-name").val(business.name);
$("#form-mail").val(business.mail);
+
+ $("#changeImageButton").removeClass("disabled");
}
// creates a new business object by parsing the form data
@@ -135,4 +140,35 @@ function mergeBusinesses(existingBusiness, newBusiness) {
}
}
return existingBusiness;
+}
+
+function setupImageUpload() {
+ $("#changeImageButton").click(function() {
+ $("#imageUploadModal").openModal();
+ });
+
+ var imageFileInput = $("#imageFileInput").get(0);
+ imageFileInput.addEventListener('change', function(event) {
+ var businessKeyId = existingBusiness.key.id;
+ var files = $("#imageFileInput").get(0).files;
+ if (files.length < 1) {
+ return;
+ }
+
+ var file = files[0];
+
+ Materialize.toast(getString("uploadStarted"), 3000);
+ $(".loadingState").show();
+
+ intelliqApi.uploadBusinessLogo(businessKeyId, file, authenticator.getGoogleUserIdToken()).then(function(data){
+ Materialize.toast(getString("uploadSuccessful"), 3000);
+ $(".loadingState").hide();
+ $("#imageUploadModal").closeModal();
+ }).catch(function(error){
+ console.log(error);
+ Materialize.toast(getString("uploadFailed"), 3000);
+ ui.showErrorMessage(error);
+ $(".loadingState").hide();
+ });
+ });
}
\ No newline at end of file
diff --git a/IntelliQ/backend/src/main/webapp/static/js/edit_queue.js b/IntelliQ/backend/src/main/webapp/static/js/edit_queue.js
index 9c7dce6..7037cd1 100644
--- a/IntelliQ/backend/src/main/webapp/static/js/edit_queue.js
+++ b/IntelliQ/backend/src/main/webapp/static/js/edit_queue.js
@@ -11,6 +11,8 @@ var queueLocationMarker; // map marker for the new queue location
$("#saveQueueButton").click(saveNewQueue);
updateFormWithUrlParameterData();
+ setupImageUpload();
+
var statusChangeListener = {
onUserAvailable: function(user) {
var queueKeyId = getUrlParam("queueKeyId");
@@ -54,11 +56,13 @@ function requestExistingQueueData(queueKeyId) {
function showAddQueueUi() {
$("#businessHeading").text(getString("addQueue"));
$("#saveQueueButton").text(getString("save"));
+ $("#changeImageContainer").addClass("hide");
}
function showEditQueueUi() {
$("#businessHeading").text(getString("editQueue"));
$("#saveQueueButton").text(getString("applyChanges"));
+ $("#changeImageContainer").removeClass("hide");
}
// fills the form fields with data from URL params
@@ -87,6 +91,8 @@ function updateFormWithQueueData(queue) {
$("#form-name").val(queue.name);
$("#form-description").val(queue.description);
+ $("#changeImageButton").removeClass("disabled");
+
// waiting time
var enteredTimeUnit = $("#form-average-waiting-time-unit :selected").val();
if (enteredTimeUnit == "minutes") {
@@ -459,4 +465,35 @@ function geocodeLocation(latitude, longitude, geocoder, map) {
}
});
return promise;
+}
+
+function setupImageUpload() {
+ $("#changeImageButton").click(function() {
+ $("#imageUploadModal").openModal();
+ });
+
+ var imageFileInput = $("#imageFileInput").get(0);
+ imageFileInput.addEventListener('change', function(event) {
+ var queueKeyId = existingQueue.key.id;
+ var files = $("#imageFileInput").get(0).files;
+ if (files.length < 1) {
+ return;
+ }
+
+ var file = files[0];
+
+ Materialize.toast(getString("uploadStarted"), 3000);
+ $(".loadingState").show();
+
+ intelliqApi.uploadQueuePhoto(queueKeyId, file, authenticator.getGoogleUserIdToken()).then(function(data){
+ Materialize.toast(getString("uploadSuccessful"), 3000);
+ $(".loadingState").hide();
+ $("#imageUploadModal").closeModal();
+ }).catch(function(error){
+ console.log(error);
+ Materialize.toast(getString("uploadFailed"), 3000);
+ ui.showErrorMessage(error);
+ $(".loadingState").hide();
+ });
+ });
}
\ No newline at end of file
diff --git a/IntelliQ/backend/src/main/webapp/website/en/edit_business.jsp b/IntelliQ/backend/src/main/webapp/website/en/edit_business.jsp
index f615caa..506bfd5 100644
--- a/IntelliQ/backend/src/main/webapp/website/en/edit_business.jsp
+++ b/IntelliQ/backend/src/main/webapp/website/en/edit_business.jsp
@@ -33,22 +33,29 @@
-
-
-
+
+
+
+
+
+
+
+
Business Logo
+
+
Your logo will be visible in different parts of the app, mainly as small icon below queues that belong to your business. Square images with a transparent background will look best!
+
+
+
+
+
+
+
+
+
<%@include file="../includes/en/common_footer.jsp"%>
diff --git a/IntelliQ/backend/src/main/webapp/website/en/edit_queue.jsp b/IntelliQ/backend/src/main/webapp/website/en/edit_queue.jsp
index 3ff5a46..19d415e 100644
--- a/IntelliQ/backend/src/main/webapp/website/en/edit_queue.jsp
+++ b/IntelliQ/backend/src/main/webapp/website/en/edit_queue.jsp
@@ -53,6 +53,15 @@
+
+
+
+
+
+
+
+
Queue Photo
+
+
The photo of your queue will be publicly visible in all apps for every user. A vibrant photo without any text works best!
+
+
+
+
+
+
+
+
+
<%@include file="../includes/en/common_footer.jsp"%>
diff --git a/IntelliQ/backend/src/main/webapp/website/en/imprint.jsp b/IntelliQ/backend/src/main/webapp/website/en/imprint.jsp
index ca0e17c..86073c6 100644
--- a/IntelliQ/backend/src/main/webapp/website/en/imprint.jsp
+++ b/IntelliQ/backend/src/main/webapp/website/en/imprint.jsp
@@ -23,7 +23,7 @@
IntelliQ.me UG (haftungsbeschränkt)
Geschwister-Scholl-Str. 80
14471 Potsdan
- Branenburg, Germany
+ Brandenburg, Germany
diff --git a/IntelliQ/backend/src/main/webapp/website/includes/en/common_head.jsp b/IntelliQ/backend/src/main/webapp/website/includes/en/common_head.jsp
index 15f1f7d..e1caaf8 100644
--- a/IntelliQ/backend/src/main/webapp/website/includes/en/common_head.jsp
+++ b/IntelliQ/backend/src/main/webapp/website/includes/en/common_head.jsp
@@ -28,6 +28,9 @@
"applyChanges": "Apply Changes",
"save": "Save",
+ "uploadStarted": "Upload Started",
+ "uploadSuccessful": "Upload Finished",
+ "uploadFailed": "Upload Failed",
"status": "Status",
"statusWaiting": "Waiting",
diff --git a/IntelliQ/mobile/mobile.iml b/IntelliQ/mobile/mobile.iml
index 2497348..1eb7a2b 100755
--- a/IntelliQ/mobile/mobile.iml
+++ b/IntelliQ/mobile/mobile.iml
@@ -106,14 +106,6 @@
-
-
-
-
-
-
-
-
@@ -122,11 +114,15 @@
-
+
+
+
+
+
+
+
+
-
-
-
@@ -187,16 +183,11 @@
-
-
-
-
-
diff --git a/IntelliQ/wear/wear.iml b/IntelliQ/wear/wear.iml
index cef3668..52c0e99 100755
--- a/IntelliQ/wear/wear.iml
+++ b/IntelliQ/wear/wear.iml
@@ -66,14 +66,6 @@
-
-
-
-
-
-
-
-
@@ -82,11 +74,15 @@
-
+
+
+
+
+
+
+
+
-
-
-
@@ -95,20 +91,11 @@
-
-
-
-
-
-
-
-
-