From 3bfb580cc59c8ffef0f4861b6596613526862569 Mon Sep 17 00:00:00 2001 From: Anthony Massaad Date: Fri, 1 Dec 2023 10:35:54 -0500 Subject: [PATCH 1/5] successfully edit a survey --- .../opinionowl/controllers/APIController.java | 96 +++++++++++++++++++ .../controllers/PageController.java | 22 +++++ src/main/resources/static/css/globals.css | 2 +- .../resources/static/scripts/createSurvey.js | 64 ++++++++----- .../resources/static/scripts/editSurvey.js | 68 +++++++++++++ .../resources/templates/createSurvey.html | 2 +- src/main/resources/templates/editSurvey.html | 32 +++++++ .../resources/templates/manageSurvey.html | 4 +- 8 files changed, 263 insertions(+), 27 deletions(-) create mode 100644 src/main/resources/static/scripts/editSurvey.js create mode 100644 src/main/resources/templates/editSurvey.html diff --git a/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java b/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java index f2eb4f1..5060461 100644 --- a/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java +++ b/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java @@ -364,4 +364,100 @@ public int logoutUser(HttpServletResponse response, HttpServletRequest request) } return 200; } + + @GetMapping("/getSurveyQuestions/{id}") + public String getSurveyQuestions(@PathVariable("id") String id, HttpServletRequest request) throws JSONException { + System.out.println("getSurveyResults() API"); + + String userid = CookieController.getUserIdFromCookie(request); + if (userid == null){ + System.out.println("You must be logged in first"); + return ""; + } + + Optional s = surveyRepo.findById(Long.valueOf(id)); + JSONObject resObject = new JSONObject(); + if (s.isPresent()) { + Survey survey = s.get(); + if (!survey.getUser().getId().equals(Long.valueOf(userid))){ + return ""; + } + JSONObject questionObject = new JSONObject(); + for (Question q : survey.getQuestions()) { + JSONObject indQObject = new JSONObject(); + indQObject.put("type", q.getType().getType()); + indQObject.put("prompt", q.getPrompt()); + if (q.getType() == QuestionType.RANGE) { + RangeQuestion rangeQuestion = (RangeQuestion) q; + int[] ranges = {rangeQuestion.getLower(), rangeQuestion.getUpper()}; + indQObject.put("ranges", ranges); + } else if (q.getType() == QuestionType.RADIO_CHOICE) { + indQObject.put("choices", ((RadioChoiceQuestion) q).getChoices()); + } + questionObject.put(q.getId().toString(), indQObject); + } + resObject.put("questions", questionObject); + } + System.out.println(resObject); + return resObject.toString(); + } + + @PostMapping("/updateSurvey/{id}") + public int updateSurvey(@PathVariable("id") String id, HttpServletRequest request) throws IOException { + System.out.println("Updating survey API()"); + + String userid = CookieController.getUserIdFromCookie(request); + if (userid == null){ + System.out.println("You must be logged in first"); + return 400; + } + + String jsonData = this.JSONBuilder(request); + ObjectMapper objectMapper = new ObjectMapper(); + HashMap surveyData = objectMapper.readValue(jsonData, new TypeReference>() {}); + // Extract specific data from the parsed JSON + String title = (String) surveyData.get("title"); + List textQuestions = (List) surveyData.get("textQuestions"); + HashMap> radioQuestions = (HashMap>) surveyData.get("radioQuestions"); + HashMap> numericRanges = (HashMap>) surveyData.get("numericRanges"); + + AppUser appUser = userRepository.findById(Long.valueOf(userid)).orElse(null); + Survey currSurvey = surveyRepo.findById((Long.valueOf(id))).orElse(null); + Survey newSurvey = new Survey(appUser, title); + + if (appUser == null) { + System.out.println("Could not find the user!"); + return 400; + } + + if (currSurvey == null) { + System.out.println("Could not find survey"); + return 400; + } + + if (!Objects.equals(currSurvey.getUser().getId(), appUser.getId())) { + System.out.println("Not the user associated with the user"); + return 400; + } + + appUser.removeSurvey(currSurvey.getId()); + surveyRepo.deleteById(currSurvey.getId()); + // add all the question types to the survey + for (String questionTitle : textQuestions) { + newSurvey.addQuestion(new LongAnswerQuestion(newSurvey, questionTitle, 50)); + } + + for (String questionTitle : radioQuestions.keySet()) { + String[] radioQuestionsArr = new String[radioQuestions.get(questionTitle).size()]; + newSurvey.addQuestion(new RadioChoiceQuestion(newSurvey, questionTitle, radioQuestions.get(questionTitle).toArray(radioQuestionsArr))); + } + + for (String questionTitle : numericRanges.keySet()) { + List ranges = numericRanges.get(questionTitle); + newSurvey.addQuestion(new RangeQuestion(newSurvey, questionTitle, ranges.get(0), ranges.get(1), 1)); + } + appUser.addSurvey(newSurvey); + surveyRepo.save(newSurvey); + return 200; + } } diff --git a/src/main/java/com/opinionowl/opinionowl/controllers/PageController.java b/src/main/java/com/opinionowl/opinionowl/controllers/PageController.java index 5521fa3..80d412e 100644 --- a/src/main/java/com/opinionowl/opinionowl/controllers/PageController.java +++ b/src/main/java/com/opinionowl/opinionowl/controllers/PageController.java @@ -124,6 +124,28 @@ public String getAnswerSurveyPage(@RequestParam(value = "surveyId") Long surveyI return "answerSurvey"; } + @GetMapping("/editSurvey") + public String editSurveyPage(@RequestParam(value = "surveyId") Long surveyId, Model model, HttpServletRequest request) { + String cookieUserId = CookieController.getUserIdFromCookie(request); + if (cookieUserId == null){ + System.out.println("You must be logged in first"); + return "redirect:/"; + } + CookieController.setUsernameCookie(model, request); + Optional surveyO = surveyRepo.findById(surveyId); + if (surveyO.isPresent()) { + // was able to obtain a survey from the database by id, and grab it from the Optional Object + Survey survey = surveyO.get(); + if (!Long.valueOf(cookieUserId).equals(survey.getUser().getId())) { + System.out.println("You do not have access!"); + return "redirect:/"; + } + model.addAttribute("surveyTitle", survey.getTitle()); + model.addAttribute("surveyId", survey.getId()); + } + return "editSurvey"; + } + /** *

Route to direct the client to view the survey responses.

*
diff --git a/src/main/resources/static/css/globals.css b/src/main/resources/static/css/globals.css index b7c7701..39de364 100644 --- a/src/main/resources/static/css/globals.css +++ b/src/main/resources/static/css/globals.css @@ -492,7 +492,7 @@ header .header-contents nav .btn { margin-top: 0.5rem; } -.manage-survey-page .button-container button { +.manage-survey-page .button-container :is(.editable, .close-survey) { width: 100%; padding: 0.5rem; } diff --git a/src/main/resources/static/scripts/createSurvey.js b/src/main/resources/static/scripts/createSurvey.js index e301a62..a63f9fb 100644 --- a/src/main/resources/static/scripts/createSurvey.js +++ b/src/main/resources/static/scripts/createSurvey.js @@ -6,8 +6,9 @@ const survey = $("#survey"); const addTextQuestion = $("#add-text"); const addRadioChoice = $("#add-radio-choice"); const addNumericRange = $("#add-numeric-range"); +const formButton = $(".create-edit-submit-btn"); const submitButton = $("#create-survey"); -submitButton.attr("disabled", true); +formButton.attr("disabled", true); const generateUniqueID = () => { counter++; return `unique-${counter}-${Math.floor(Math.random() * 1000)}`; @@ -16,15 +17,15 @@ const generateUniqueID = () => { /** * * @param {string} radioQuestionContainer - * @param {string} uniqueName + * @param {string} prompt */ -const addMoreRadioOptions = (radioQuestionContainer, uniqueName) => { +const addMoreRadioOptions = (radioQuestionContainer, prompt= "Sample") => { const uniqueId = generateUniqueID(); const divId = generateUniqueID(); $(radioQuestionContainer).append(`
- +
`); @@ -60,18 +61,17 @@ const removeTableRow = (tableRowId) => { const incrementNumOfQuestions = () => { numOfQuestions++; - submitButton.removeAttr('disabled'); + formButton.removeAttr('disabled'); }; const decrementNumOfQuestion = () => { numOfQuestions--; if (numOfQuestions === 0){ - submitButton.attr("disabled", true); + formButton.attr("disabled", true); } }; -addTextQuestion.click((e) => { - e.preventDefault(); +const addTextQuestionRow = (prompt = "Question Title") => { const rowId = generateUniqueID(); const question = ` @@ -79,20 +79,23 @@ addTextQuestion.click((e) => { - + `; survey.append(question); incrementNumOfQuestions(); -}); +} -addRadioChoice.click((e) => { +addTextQuestion.click((e) => { e.preventDefault(); + addTextQuestionRow(); +}); + +const addRadioChoicesRow = (prompt= "Question title", choices= ["Sample"]) => { const rowId = generateUniqueID(); const radioQuestionContainer = generateUniqueID(); - const uniqueName = generateUniqueID(); const question = ` @@ -101,19 +104,25 @@ addRadioChoice.click((e) => {
- +
- + `; survey.append(question); - addMoreRadioOptions(`#${radioQuestionContainer}`, `#${uniqueName}`) + for (const choice of choices) { + addMoreRadioOptions(`#${radioQuestionContainer}`, choice); + } incrementNumOfQuestions(); -}); +} -addNumericRange.click((e) => { +addRadioChoice.click((e) => { e.preventDefault(); + addRadioChoicesRow(); +}); + +const addRangeQuestionRow = (prompt = "Question Title", ranges = [0, 10]) => { const rowId = generateUniqueID(); const question = ` @@ -121,21 +130,25 @@ addNumericRange.click((e) => { - +
- 0 + ${ranges[0]} - 11 + ${ranges[1]}
`; survey.append(question); incrementNumOfQuestions(); -}); +} -submitButton.click((e) => { +addNumericRange.click((e) => { e.preventDefault(); + addRangeQuestionRow(); +}); + +const parseSurveyFormData = () => { const dataDictionary = {}; dataDictionary["radioQuestions"] = {}; dataDictionary["numericRanges"] = {}; @@ -202,8 +215,13 @@ submitButton.click((e) => { return; } - console.log(dataDictionary); + return dataDictionary; +} +submitButton.click((e) => { + e.preventDefault(); + const dataDictionary = parseSurveyFormData(); + console.log(dataDictionary); // send post using ajax const dataJson = JSON.stringify(dataDictionary); $.ajax({ diff --git a/src/main/resources/static/scripts/editSurvey.js b/src/main/resources/static/scripts/editSurvey.js new file mode 100644 index 0000000..f25bd4c --- /dev/null +++ b/src/main/resources/static/scripts/editSurvey.js @@ -0,0 +1,68 @@ +const updateSurveyBtn = $("#update-survey"); + +const addEditableQuestions = (questionsJson) => { + const jsonRes = JSON.parse(questionsJson); + const questions = jsonRes['questions']; + Object.values(questions).map((question) => { + const type = question['type']; + const prompt = question['prompt']; + if (type === "Long Answer") { + addTextQuestionRow(prompt); + } else if (type === "Radio Choice") { + // Handle Radio Choice + addRadioChoicesRow(prompt, question['choices']); + } else if (type === "Range") { + // Handle Range + addRangeQuestionRow(prompt, type['ranges']); + } + }); +} + +updateSurveyBtn.click((e) => { + e.preventDefault(); + const surveyId = $("#surveyId").text(); + const dataDictionary = parseSurveyFormData(); + console.log(dataDictionary); + // send post using ajax + const dataJson = JSON.stringify(dataDictionary); + $.ajax({ + type: $("#survey-container").attr("method"), + url: '/api/v1/updateSurvey/' + surveyId, + data: dataJson, + contentType: 'application/json', + success: function(res) { + // success handling + if (res === 200) { + console.log('Survey updated successfully'); + window.location.href = "/"; + } else { + alert('You cannot update this survey at this timme.'); + } + }, + error: function(xhr, status, error) { + // error handling + console.error('Error creating survey:', error); + } + }); +}); + +$(document).ready(function (){ + let surveyId = $("#surveyId").text(); + $.ajax({ + type: 'GET', + url: '/api/v1/getSurveyQuestions/' + surveyId, + success: function(res) { + // success handling + if (res !== ""){ + addEditableQuestions(res); + } else { + alert('You cannot complete this request'); + } + }, + error: function(xhr, status, error) { + // error handling + console.error('Error creating survey:', error); + } + }); +}); + diff --git a/src/main/resources/templates/createSurvey.html b/src/main/resources/templates/createSurvey.html index 1c0dcfa..399af0b 100644 --- a/src/main/resources/templates/createSurvey.html +++ b/src/main/resources/templates/createSurvey.html @@ -22,7 +22,7 @@

Form Title

- + diff --git a/src/main/resources/templates/editSurvey.html b/src/main/resources/templates/editSurvey.html new file mode 100644 index 0000000..b24e298 --- /dev/null +++ b/src/main/resources/templates/editSurvey.html @@ -0,0 +1,32 @@ + + + + OpinionOwl | Edit Survey + + + + + +
+
+

Editing Survey#

+
+ + + +
+ +
+
+

+ +
+ +
+
+
+
+ + + + diff --git a/src/main/resources/templates/manageSurvey.html b/src/main/resources/templates/manageSurvey.html index 56f06d1..61c6834 100644 --- a/src/main/resources/templates/manageSurvey.html +++ b/src/main/resources/templates/manageSurvey.html @@ -17,8 +17,8 @@

Manage Surveys

- - + +
From 8966351ebe2aaa874e161368d48ff87c9120691a Mon Sep 17 00:00:00 2001 From: Anthony Massaad Date: Fri, 1 Dec 2023 11:10:43 -0500 Subject: [PATCH 2/5] fixed ui for manage survey --- src/main/resources/static/css/globals.css | 9 +++++++-- src/main/resources/templates/manageSurvey.html | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/resources/static/css/globals.css b/src/main/resources/static/css/globals.css index 39de364..32896ed 100644 --- a/src/main/resources/static/css/globals.css +++ b/src/main/resources/static/css/globals.css @@ -122,7 +122,8 @@ form input { transition: box-shadow 0.2s ease-in-out; } -.btn:disabled { +.btn:disabled, +.btn.pointer-none { opacity: 0.7; pointer-events: none; } @@ -482,7 +483,11 @@ header .header-contents nav .btn { margin-bottom: 2px; } -.manage-survey-page .button-container .view button { +.manage-survey-page .button-container .btn { + text-align: center; +} + +.manage-survey-page .button-container .view { width: 100%; } diff --git a/src/main/resources/templates/manageSurvey.html b/src/main/resources/templates/manageSurvey.html index 61c6834..bd353af 100644 --- a/src/main/resources/templates/manageSurvey.html +++ b/src/main/resources/templates/manageSurvey.html @@ -15,9 +15,9 @@

Manage Surveys

Survey #:

Number of Questions:

From 006dfb0326e704228f79b0ae5ed9f3204ea9835a Mon Sep 17 00:00:00 2001 From: Anthony Massaad Date: Fri, 1 Dec 2023 11:41:16 -0500 Subject: [PATCH 3/5] added docs --- .../opinionowl/controllers/APIController.java | 33 +++++++++++++++++++ .../resources/static/scripts/editSurvey.js | 10 ++++++ 2 files changed, 43 insertions(+) diff --git a/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java b/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java index 5060461..e8fbf1b 100644 --- a/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java +++ b/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java @@ -365,6 +365,32 @@ public int logoutUser(HttpServletResponse response, HttpServletRequest request) return 200; } + /** + *

Handler for retrieving the survey questions based on its ID as a JSON

+ * Example return json will full data of questions + *
+     *     returnJson = {
+     *         "1": {
+     *             "type": "Long Answer",
+     *             "prompt": "Question prompt",
+     *         },
+     *         "2": {
+     *             "type": "Radio Choice",
+     *             "prompt": "Question prompt",
+     *             "choices": ["choice 1", "choice 2"],
+     *         },
+     *         "3": {
+     *             "type": "Range",
+     *             "prompt": "Question prompt",
+     *             "ranges": [0, 22],
+     *         }
+     *     }
+     * 
+ * @param id String, the survey ID + * @param request + * @return JSON of survey questions + * @throws JSONException + */ @GetMapping("/getSurveyQuestions/{id}") public String getSurveyQuestions(@PathVariable("id") String id, HttpServletRequest request) throws JSONException { System.out.println("getSurveyResults() API"); @@ -402,6 +428,13 @@ public String getSurveyQuestions(@PathVariable("id") String id, HttpServletReque return resObject.toString(); } + /** + *

Handle the update of a survey based on its ID

+ * @param id The survey ID + * @param request + * @return 200 if successful, otherwise 400 + * @throws IOException + */ @PostMapping("/updateSurvey/{id}") public int updateSurvey(@PathVariable("id") String id, HttpServletRequest request) throws IOException { System.out.println("Updating survey API()"); diff --git a/src/main/resources/static/scripts/editSurvey.js b/src/main/resources/static/scripts/editSurvey.js index f25bd4c..efbc658 100644 --- a/src/main/resources/static/scripts/editSurvey.js +++ b/src/main/resources/static/scripts/editSurvey.js @@ -1,5 +1,9 @@ const updateSurveyBtn = $("#update-survey"); +/** + * Add survey questions to the survey + * @param {object} questionsJson + */ const addEditableQuestions = (questionsJson) => { const jsonRes = JSON.parse(questionsJson); const questions = jsonRes['questions']; @@ -18,6 +22,9 @@ const addEditableQuestions = (questionsJson) => { }); } +/** + * Handle the survey update button functionality + */ updateSurveyBtn.click((e) => { e.preventDefault(); const surveyId = $("#surveyId").text(); @@ -46,6 +53,9 @@ updateSurveyBtn.click((e) => { }); }); +/** + * On document ready, collect the data for the survey + */ $(document).ready(function (){ let surveyId = $("#surveyId").text(); $.ajax({ From 8687382766f5ebd7e125c294c018a0454e17e52e Mon Sep 17 00:00:00 2001 From: Anthony Massaad Date: Fri, 1 Dec 2023 11:45:01 -0500 Subject: [PATCH 4/5] added disclaimer --- src/main/resources/templates/editSurvey.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/templates/editSurvey.html b/src/main/resources/templates/editSurvey.html index b24e298..a0e88c1 100644 --- a/src/main/resources/templates/editSurvey.html +++ b/src/main/resources/templates/editSurvey.html @@ -9,6 +9,7 @@
+

Note:Editing the survey will remove the existing responses from the previous survey!

Editing Survey#

From 95ad4581d43a6a4b6a495f47a69a5200fd3d4465 Mon Sep 17 00:00:00 2001 From: Anthony Massaad Date: Fri, 1 Dec 2023 11:56:20 -0500 Subject: [PATCH 5/5] removed protected conditions for getSurveyQuestion. it is now public --- .../opinionowl/controllers/APIController.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java b/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java index e8fbf1b..9fb7b1d 100644 --- a/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java +++ b/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java @@ -395,19 +395,10 @@ public int logoutUser(HttpServletResponse response, HttpServletRequest request) public String getSurveyQuestions(@PathVariable("id") String id, HttpServletRequest request) throws JSONException { System.out.println("getSurveyResults() API"); - String userid = CookieController.getUserIdFromCookie(request); - if (userid == null){ - System.out.println("You must be logged in first"); - return ""; - } - Optional s = surveyRepo.findById(Long.valueOf(id)); JSONObject resObject = new JSONObject(); if (s.isPresent()) { Survey survey = s.get(); - if (!survey.getUser().getId().equals(Long.valueOf(userid))){ - return ""; - } JSONObject questionObject = new JSONObject(); for (Question q : survey.getQuestions()) { JSONObject indQObject = new JSONObject(); @@ -423,8 +414,10 @@ public String getSurveyQuestions(@PathVariable("id") String id, HttpServletReque questionObject.put(q.getId().toString(), indQObject); } resObject.put("questions", questionObject); + } else { + System.out.println("No survey found of ID " + id); + return ""; } - System.out.println(resObject); return resObject.toString(); }