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 @@ -
+
-
- -
+
+ +
+ +
+
@@ -65,6 +72,34 @@
+ + + + <%@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 @@ + +
+ +
+
@@ -168,6 +177,34 @@
+ + + + <%@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 @@ - - - - - - - - -