org.projectlombok
lombok
diff --git a/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java b/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java
new file mode 100644
index 0000000..cb41639
--- /dev/null
+++ b/src/main/java/com/opinionowl/opinionowl/controllers/APIController.java
@@ -0,0 +1,116 @@
+package com.opinionowl.opinionowl.controllers;
+import com.fasterxml.jackson.databind.ObjectMapper; // You might need to import this class
+
+import com.opinionowl.opinionowl.models.*;
+import com.opinionowl.opinionowl.repos.SurveyRepository;
+import com.opinionowl.opinionowl.repos.UserRepository;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.NoArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.fasterxml.jackson.core.type.TypeReference;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Version 1 of the API layer for Opinion Owl
+ */
+@RestController
+@RequestMapping("/api/v1")
+@NoArgsConstructor
+public class APIController {
+
+ @Autowired
+ SurveyRepository surveyRepo;
+
+
+ @Autowired
+ private UserRepository userRepository;
+
+
+ /**
+ * Api call to handle the survey answers by a user.
+ *
+ * Api route: api/v1/postSurveyResponses
+ * @param response HttpServletResponse server side response
+ * @throws IOException
+ */
+ @PostMapping("/postSurveyResponses")
+ public void postSurveyResponses(HttpServletResponse response) throws IOException {
+ // handle save of survey data
+ // redirect to home
+ response.sendRedirect("/");
+ }
+
+ /**
+ * API Call to post a generated survey by the user. A survey generated JSON is required from the client
+ *
+ * Example of a JSON:
+ *
+ * json = {
+ * title: "title",
+ * textQuestions: ["question 1", "question 2"],
+ * radioQuestions: {
+ * "question 1": ["radio 1", "radio 2"],
+ * "question 2": ["radio 1", "radio 2", "radio 3"]
+ * },
+ * numericRanges: {
+ * "question 1": [1, 11],
+ * "question 2": [1, 5]
+ * }
+ * }
+ *
+ * @param request HttpServletRequest request from the client
+ * @return 200 if api was a success
+ * @throws IOException
+ */
+ @PostMapping("/createSurvey")
+ public int createSurvey(HttpServletRequest request) throws IOException {
+ System.out.println("createSurvey() API");
+ // read the json sent by the client
+ BufferedReader reader = request.getReader();
+ // create a string format of the json from the reader
+ StringBuilder jsonBuilder = new StringBuilder();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ jsonBuilder.append(line);
+ }
+ String jsonData = jsonBuilder.toString();
+ System.out.println("JSONDATA: " + jsonData);
+ // Parse the JSON data using Jackson ObjectMapper
+
+ //create the objects as java objects
+ 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 user = new AppUser("username", "password");
+ userRepository.save(user);
+ Survey survey = new Survey(user, title);
+ user.addSurvey(survey);
+ // add all the question types to the survey
+ for (String questionTitle : textQuestions) {
+ survey.addQuestion(new LongAnswerQuestion(survey, questionTitle, 50));
+ }
+
+ for (String questionTitle : radioQuestions.keySet()) {
+ String[] radioQuestionsArr = new String[radioQuestions.get(questionTitle).size()];
+ survey.addQuestion(new RadioChoiceQuestion(survey, questionTitle, radioQuestions.get(questionTitle).toArray(radioQuestionsArr)));
+ }
+
+ for (String questionTitle : numericRanges.keySet()) {
+ List ranges = numericRanges.get(questionTitle);
+ survey.addQuestion(new RangeQuestion(survey, questionTitle, ranges.get(0), ranges.get(1), 1));
+ }
+ surveyRepo.save(survey);
+ System.out.println("survey generated\n\n" + survey);
+ return 200;
+ }
+}
diff --git a/src/main/java/com/opinionowl/opinionowl/controllers/PageController.java b/src/main/java/com/opinionowl/opinionowl/controllers/PageController.java
new file mode 100644
index 0000000..dec9210
--- /dev/null
+++ b/src/main/java/com/opinionowl/opinionowl/controllers/PageController.java
@@ -0,0 +1,103 @@
+package com.opinionowl.opinionowl.controllers;
+
+import com.opinionowl.opinionowl.models.*;
+import com.opinionowl.opinionowl.repos.SurveyRepository;
+import lombok.NoArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Route controller for Opinion Owl pages
+ */
+@Controller
+@NoArgsConstructor
+public class PageController {
+
+ @Autowired
+ SurveyRepository surveyRepo;
+
+ /**
+ * Home route that gets all the surveys in the database, sends it to the model and directs the user to the home page
+ * @param model Model, the client Model
+ * @return String, the html template
+ */
+ @GetMapping("/")
+ public String getHomePage(Model model) {
+ List surveys = surveyRepo.findAll();
+ model.addAttribute("surveys", surveys);
+ return "index";
+ }
+
+ /**
+ * Route for the create survey page
+ * @param model Model, the client Model
+ * @return String ,the html template
+ */
+ @GetMapping("/createSurvey")
+ public String getCreateSurveyPage(Model model) {
+ return "createSurvey";
+ }
+
+ /**
+ * Route to direct the client to the answer survey page, given a survey id to pass the Survey object to the Model
+ *
+ * Example call: /answerSurvey?surveyId=1
+ * @param surveyId Long, the ID associated with a survey
+ * @param model Model, the client Model
+ * @return String, the html template
+ */
+ @GetMapping("/answerSurvey")
+ public String getAnswerSurveyPage(@RequestParam(value = "surveyId") Long surveyId, Model model) {
+ // find the survey by id
+ 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();
+ System.out.println("Survey found:");
+ System.out.println(survey);
+ // cast the order of the questions to the associtate subclass they belong to
+ // Cast in hashmaps as
+ List q = survey.getQuestions();
+ HashMap longAnswerQuestions = new HashMap<>();
+ HashMap radioChoiceQuestions = new HashMap<>();
+ HashMap rangeQuestionQuestions = new HashMap<>();
+ int numQuestions = q.size();
+ String title = survey.getTitle();
+ for (int i = 0; i {
// Essentially performs SELECT * FROM survey
List findAll();
+
+ Survey findById(long Id);
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 8b13789..0e621e4 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1 +1,2 @@
-
+spring.thymeleaf.prefix=classpath:/templates/
+spring.thymeleaf.suffix=.html
\ No newline at end of file
diff --git a/src/main/resources/static/images/owl.png b/src/main/resources/static/images/owl.png
new file mode 100644
index 0000000..b2135ad
Binary files /dev/null and b/src/main/resources/static/images/owl.png differ
diff --git a/src/main/resources/static/scripts/createSurvey.js b/src/main/resources/static/scripts/createSurvey.js
new file mode 100644
index 0000000..c78af67
--- /dev/null
+++ b/src/main/resources/static/scripts/createSurvey.js
@@ -0,0 +1,167 @@
+let counter = 0;
+let numOfQuestions = 0;
+
+const formTitle = $(".form-title");
+const survey = $("#survey");
+const addTextQuestion = $("#add-text");
+const addRadioChoice = $("#add-radio-choice");
+const addNumericRange = $("#add-numeric-range");
+const submitButton = $("#create-survey");
+submitButton.attr("disabled", true);
+const generateUniqueID = () => {
+ counter++;
+ return `unique-${counter}-${Math.floor(Math.random() * 1000)}`;
+};
+
+/**
+ *
+ * @param {string} radioQuestionContainer
+ * @param {string} uniqueName
+ */
+const addMoreRadioOptions = (radioQuestionContainer, uniqueName) => {
+ const uniqueId = generateUniqueID();
+ $(radioQuestionContainer).append(`
+
+
+ sample
+ `);
+};
+
+/**
+ *
+ * @param {string} tableRowId
+ */
+const removeTableRow = (tableRowId) => {
+ $(tableRowId).remove();
+ decrementNumOfQuestion();
+};
+
+const incrementNumOfQuestions = () => {
+ numOfQuestions++;
+ submitButton.removeAttr('disabled');
+};
+
+const decrementNumOfQuestion = () => {
+ numOfQuestions--;
+ if (numOfQuestions === 0){
+ submitButton.attr("disabled", true);
+ }
+};
+
+addTextQuestion.click((e) => {
+ e.preventDefault();
+ const rowId = generateUniqueID();
+ const question = `
+
+
+ -
+
+
+ Question title
+
+
+
+
+ `;
+ survey.append(question);
+ incrementNumOfQuestions();
+});
+
+addRadioChoice.click((e) => {
+ e.preventDefault();
+ const rowId = generateUniqueID();
+ const radioQuestionContainer = generateUniqueID();
+ const uniqueName = generateUniqueID();
+ const question = `
+
+
+ -
+
+
+
+ Question title
+
+
+ sample
+
+ +
+
+
+ `;
+ survey.append(question);
+ incrementNumOfQuestions();
+});
+
+addNumericRange.click((e) => {
+ e.preventDefault();
+ const rowId = generateUniqueID();
+ const question = `
+
+
+ -
+
+
+ Question title
+
+ 0
+
+ 11
+
+
+ `;
+ survey.append(question);
+ incrementNumOfQuestions();
+});
+
+submitButton.click((e) => {
+ e.preventDefault();
+ const dataDictionary = {};
+ dataDictionary["radioQuestions"] = {};
+ dataDictionary["numericRanges"] = {};
+ dataDictionary["title"] = formTitle.text();
+ // Iterate over table rows with the class 'text-questions'
+ const textQuestions = []
+ $('.text-questions label').each(function () {
+ textQuestions.push($(this).text())
+ }).get();
+ dataDictionary["textQuestions"] = textQuestions;
+
+ $('.radio-questions').each(function() {
+ const title = $(this).find('.title').text();
+ const radioQuestions = [];
+ const radioQuestionContainer = $(this).find('div');
+ $(radioQuestionContainer).find('label:not(.title)').each(function () {
+ radioQuestions.push($(this).text());
+ });
+ dataDictionary["radioQuestions"][title] = radioQuestions;
+ });
+
+ $('.numeric-questions').each(function() {
+ const title = $(this).find(".title").text();
+ const ranges = [];
+ $(this).find("span").each(function() {
+ ranges.push(parseInt($(this).text()));
+ })
+ dataDictionary["numericRanges"][title] = ranges;
+ });
+
+ console.log(dataDictionary);
+
+ // send post using ajax
+ const dataJson = JSON.stringify(dataDictionary);
+ $.ajax({
+ type: $("#survey-container").attr("method"),
+ url: '/api/v1/createSurvey',
+ data: dataJson,
+ contentType: 'application/json',
+ success: function(res) {
+ // success handling
+ console.log('Survey created successfully');
+ if (res === 200) window.location.href = "/";
+ },
+ error: function(xhr, status, error) {
+ // error handling
+ console.error('Error creating survey:', error);
+ }
+ });
+});
\ No newline at end of file
diff --git a/src/main/resources/templates/answerSurvey.html b/src/main/resources/templates/answerSurvey.html
new file mode 100644
index 0000000..98e9004
--- /dev/null
+++ b/src/main/resources/templates/answerSurvey.html
@@ -0,0 +1,37 @@
+
+
+
+ OpinionOwl | Answer Survey
+
+
+
+
+
+ Survey# :
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/createSurvey.html b/src/main/resources/templates/createSurvey.html
new file mode 100644
index 0000000..ff98185
--- /dev/null
+++ b/src/main/resources/templates/createSurvey.html
@@ -0,0 +1,29 @@
+
+
+
+ OpinionOwl | Create Survey
+
+
+
+
+
+ Create a Survey
+
+ Add Text Question
+ Add Multiple Choice Question
+ Add Numeric Range Select Question
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/fragments/footer.html b/src/main/resources/templates/fragments/footer.html
new file mode 100644
index 0000000..28d587d
--- /dev/null
+++ b/src/main/resources/templates/fragments/footer.html
@@ -0,0 +1 @@
+
diff --git a/src/main/resources/templates/fragments/header.html b/src/main/resources/templates/fragments/header.html
new file mode 100644
index 0000000..abcdf23
--- /dev/null
+++ b/src/main/resources/templates/fragments/header.html
@@ -0,0 +1,6 @@
+
+
+
+
Opinion Owl
+
+
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html
new file mode 100644
index 0000000..8eef2f2
--- /dev/null
+++ b/src/main/resources/templates/index.html
@@ -0,0 +1,33 @@
+
+
+
+ OpinionOwl
+
+
+
+
+
+ Welcome To OpinionOwl
+
+ The ultimate platform for both survey creators and respondents. If you're
+ a survey creator - a fellow owl companion, our user-friendly interface
+ will allow you to craft surveys with any topic your choosing. If you are a
+ survey respondents - either an owl companion or an unknown owl, you are
+ free to share your thoughts and opinions on the topics created by other
+ owl companions.
+
+ Create a survey
+
+
+
+
diff --git a/src/main/resources/templates/viewResponse.html b/src/main/resources/templates/viewResponse.html
new file mode 100644
index 0000000..e26f3ad
--- /dev/null
+++ b/src/main/resources/templates/viewResponse.html
@@ -0,0 +1,11 @@
+
+
+
+ OpinionOwl | Responses
+
+
+
+
+View Response
+
+
\ No newline at end of file