Skip to content

Commit

Permalink
Merge pull request #80 from bardia-p/milestone3/opinionOwl#18/EditSurvey
Browse files Browse the repository at this point in the history
Edit Survey Feature
  • Loading branch information
Anthony-Massaad authored Dec 1, 2023
2 parents 1f83245 + 95ad458 commit 8ffafc8
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 30 deletions.
122 changes: 122 additions & 0 deletions src/main/java/com/opinionowl/opinionowl/controllers/APIController.java
Original file line number Diff line number Diff line change
Expand Up @@ -364,4 +364,126 @@ public int logoutUser(HttpServletResponse response, HttpServletRequest request)
}
return 200;
}

/**
* <p>Handler for retrieving the survey questions based on its ID as a JSON</p>
* <strong>Example return json will full data of questions</strong>
* <pre>
* 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],
* }
* }
* </pre>
* @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<Survey> 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();
}

/**
* <p>Handle the update of a survey based on its ID</p>
* @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<String, Object> surveyData = objectMapper.readValue(jsonData, new TypeReference<HashMap<String, Object>>() {});
// Extract specific data from the parsed JSON
String title = (String) surveyData.get("title");
List<String> textQuestions = (List<String>) surveyData.get("textQuestions");
HashMap<String, List<String>> radioQuestions = (HashMap<String, List<String>>) surveyData.get("radioQuestions");
HashMap<String, List<Integer>> numericRanges = (HashMap<String, List<Integer>>) 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<Integer> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Survey> 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";
}

/**
* <p>Route to direct the client to view the survey responses.</p>
* <br />
Expand Down
11 changes: 8 additions & 3 deletions src/main/resources/static/css/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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%;
}

Expand All @@ -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;
}
Expand Down
64 changes: 41 additions & 23 deletions src/main/resources/static/scripts/createSurvey.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)}`;
Expand All @@ -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(`
<div id=${divId} class="radio-container flex">
<input id=${uniqueId} type="radio">
<label for=${uniqueId} contenteditable="true">sample</label>
<label for=${uniqueId} contenteditable="true">${prompt}</label>
<button class="btn" onclick="removingRadioChoice('${radioQuestionContainer}', '#${divId}')">-</button>
</div>
`);
Expand Down Expand Up @@ -60,39 +61,41 @@ 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 = `
<tr id=${rowId} class="text-questions">
<td>
<button class="btn" type="button" onclick="removeTableRow('#${rowId}')">-</button>
</td>
<td>
<label contenteditable="true">Question title</label>
<label contenteditable="true">${prompt}</label>
<input type="text" />
</td>
</tr>
`;
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 = `
<tr id='${rowId}' class="radio-questions">
Expand All @@ -101,41 +104,51 @@ addRadioChoice.click((e) => {
</td>
<td>
<div id=${radioQuestionContainer}>
<label contenteditable="true" class="title">Question title</label>
<label contenteditable="true" class="title">${prompt}</label>
</div>
<button class="btn add-more-radio-choices" type="button" onclick="addMoreRadioOptions('#${radioQuestionContainer}','${uniqueName}')">+</button>
<button class="btn add-more-radio-choices" type="button" onclick="addMoreRadioOptions('#${radioQuestionContainer}')">+</button>
</td>
</tr>
`;
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 = `
<tr id='${rowId}' class="numeric-questions">
<td>
<button class="btn" type="button" onclick="removeTableRow('#${rowId}')">-</button>
</td>
<td>
<label contenteditable="true" class="title">Question title</label>
<label contenteditable="true" class="title">${prompt}</label>
<div class="flex range-option">
<span contenteditable="true">0</span>
<span contenteditable="true">${ranges[0]}</span>
<input type="range" min="0" max="11" />
<span contenteditable="true">11</span>
<span contenteditable="true">${ranges[1]}</span>
</div>
</td>
</tr>
`;
survey.append(question);
incrementNumOfQuestions();
});
}

submitButton.click((e) => {
addNumericRange.click((e) => {
e.preventDefault();
addRangeQuestionRow();
});

const parseSurveyFormData = () => {
const dataDictionary = {};
dataDictionary["radioQuestions"] = {};
dataDictionary["numericRanges"] = {};
Expand Down Expand Up @@ -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({
Expand Down
Loading

0 comments on commit 8ffafc8

Please sign in to comment.