Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edit Survey Feature #80

Merged
merged 5 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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