diff --git a/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java b/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java index f2eb4f1..9fb7b1d 100644 --- a/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java +++ b/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java @@ -364,4 +364,126 @@ 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"); + + Optional s = surveyRepo.findById(Long.valueOf(id)); + JSONObject resObject = new JSONObject(); + if (s.isPresent()) { + Survey survey = s.get(); + 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); + } else { + System.out.println("No survey found of ID " + id); + return ""; + } + 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()"); + + 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..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%; } @@ -492,7 +497,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..efbc658 --- /dev/null +++ b/src/main/resources/static/scripts/editSurvey.js @@ -0,0 +1,78 @@ +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']; + 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']); + } + }); +} + +/** + * Handle the survey update button functionality + */ +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); + } + }); +}); + +/** + * On document ready, collect the data for the survey + */ +$(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..a0e88c1 --- /dev/null +++ b/src/main/resources/templates/editSurvey.html @@ -0,0 +1,33 @@ + + + + OpinionOwl | Edit Survey + + + + + +
+
+

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

+

Editing Survey#

+
+ + + +
+ +
+
+

+ +
+ +
+
+
+
+ + + + diff --git a/src/main/resources/templates/manageSurvey.html b/src/main/resources/templates/manageSurvey.html index 56f06d1..bd353af 100644 --- a/src/main/resources/templates/manageSurvey.html +++ b/src/main/resources/templates/manageSurvey.html @@ -15,10 +15,10 @@

Manage Surveys

Survey #:

Number of Questions:

- + View Results
- - + Edit Survey +