-
Notifications
You must be signed in to change notification settings - Fork 27
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
Enabling User to have multiple questions #80
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.example.restservice.config; | ||
|
||
import com.fasterxml.jackson.databind.DeserializationFeature; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
public class JacksonConfiguration { | ||
@Bean | ||
public ObjectMapper objectMapper() { | ||
ObjectMapper mapper = new ObjectMapper(); | ||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); | ||
|
||
return mapper; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package com.example.restservice.dao; | ||
|
||
import com.fasterxml.jackson.annotation.JsonInclude; | ||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
@Getter | ||
@Setter | ||
@NoArgsConstructor | ||
public class CustomQuestions { | ||
|
||
@JsonProperty("questions") | ||
List<Question> questions; | ||
|
||
@JsonInclude(JsonInclude.Include.NON_NULL) | ||
public static class Question { | ||
@JsonProperty("questionId") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wondering if we're using our own custom representation of the questions object. Then we'll need to write our own parsing library to generate the forms on UI. |
||
private String questionId; | ||
@JsonProperty("type") | ||
private String type; | ||
@JsonProperty("label") | ||
private String label; | ||
@JsonProperty("repeatable") | ||
private Boolean repeatable; | ||
@JsonProperty("subQuestions") | ||
private List<SubQuestion> subQuestions; | ||
|
||
public Question() { | ||
if(this.questionId == null) { | ||
this.questionId = UUID.randomUUID().toString(); | ||
} | ||
} | ||
|
||
@JsonInclude(JsonInclude.Include.NON_NULL) | ||
public static class Option { | ||
@JsonProperty("text") | ||
private String text; | ||
} | ||
|
||
@JsonInclude(JsonInclude.Include.NON_NULL) | ||
public static class SubQuestion { | ||
@JsonProperty("questionId") | ||
private String questionId; | ||
@JsonProperty("label") | ||
private String label; | ||
@JsonProperty("type") | ||
private String type; | ||
@JsonProperty("options") | ||
private List<Option> options; | ||
|
||
public SubQuestion() { | ||
if(this.questionId == null) { | ||
this.questionId = UUID.randomUUID().toString(); | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,14 @@ | ||
package com.example.restservice.dao; | ||
|
||
import java.util.Date; | ||
import java.util.List; | ||
import javax.persistence.CascadeType; | ||
import javax.persistence.Column; | ||
import javax.persistence.Entity; | ||
import javax.persistence.GeneratedValue; | ||
import javax.persistence.Id; | ||
import javax.persistence.OneToMany; | ||
import javax.persistence.Table; | ||
import javax.persistence.Temporal; | ||
import javax.persistence.TemporalType; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
import org.hibernate.annotations.GenericGenerator; | ||
|
||
import javax.persistence.*; | ||
import java.util.Date; | ||
import java.util.List; | ||
|
||
@Entity | ||
@Table(name = "queue") | ||
@Getter | ||
|
@@ -40,6 +33,9 @@ public class Queue { | |
@Temporal(TemporalType.TIMESTAMP) | ||
Date queueCreationTimestamp; | ||
|
||
@Column(length = 100000) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can use Text type here maybe. It is just a proposal |
||
private String customQuestions; | ||
|
||
public Queue(String queueName, String ownerId) { | ||
this.queueName = queueName; | ||
this.ownerId = ownerId; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,25 +7,32 @@ | |
import com.example.restservice.controller.model.queue.MyQueuesResponse; | ||
import com.example.restservice.controller.model.queue.QueueDetailsResponse; | ||
import com.example.restservice.controller.model.queue.QueueStatusResponse; | ||
import com.example.restservice.dao.CustomQuestions; | ||
import com.example.restservice.dao.Queue; | ||
import com.example.restservice.dao.QueueRepository; | ||
import com.example.restservice.dao.Token; | ||
import com.example.restservice.exceptions.SQAccessDeniedException; | ||
import com.example.restservice.exceptions.SQInternalServerException; | ||
import com.example.restservice.exceptions.SQInvalidRequestException; | ||
import java.util.Comparator; | ||
import java.util.function.BooleanSupplier; | ||
import java.util.stream.Collectors; | ||
import javax.transaction.Transactional; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.dao.DataIntegrityViolationException; | ||
import org.springframework.stereotype.Service; | ||
import springfox.documentation.spring.web.json.Json; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class QueueService { | ||
|
||
private final QueueRepository queueRepository; | ||
private final LoggedInUserInfo loggedInUserInfo; | ||
private final ObjectMapper mapper; | ||
|
||
@Transactional | ||
public CreateQueueResponse createQueue(CreateQueueRequest createQueueRequest) { | ||
|
@@ -68,14 +75,25 @@ public QueueStatusResponse getQueueStatus(String queueId) { | |
.findById(queueId) | ||
.map( | ||
queue -> | ||
new QueueStatusResponse( | ||
queueId, | ||
queue.getQueueName(), | ||
queue.getTokens().stream() | ||
.filter(user -> user.getStatus().equals(TokenStatus.WAITING)) | ||
.count(), | ||
Long.valueOf(queue.getTokens().size()), | ||
queue.getQueueCreationTimestamp())) | ||
{ | ||
try { | ||
CustomQuestions customQuestions = queue.getCustomQuestions() != null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You have duplicate code starting with line +122 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also you can do flatMap and create a method with the following body. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also why do we store json? We can handle this using table relationship and we can avoid this complicated logic. Plus it adds a lot of computational overhead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. If you want to redo this as a table, with just textual questions and answers, we can do that. But we should think first about how we would display the user input along with each token in the admin page. Maybe some collapsable expansion panel would do the job. That's the reason why I have been delaying this feature for a long time, till all the easy features are done and I get some real customers. |
||
? mapper.readValue(queue.getCustomQuestions(), CustomQuestions.class) | ||
: null; | ||
return new QueueStatusResponse( | ||
queueId, | ||
queue.getQueueName(), | ||
queue.getTokens().stream() | ||
.filter(user -> user.getStatus().equals(TokenStatus.WAITING)) | ||
.count(), | ||
Long.valueOf(queue.getTokens().size()), | ||
queue.getQueueCreationTimestamp(), | ||
customQuestions); | ||
} catch (JsonProcessingException e) { | ||
e.printStackTrace(); | ||
} | ||
return null; | ||
}) | ||
.orElseThrow(SQInvalidRequestException::queueNotFoundException); | ||
} | ||
|
||
|
@@ -99,14 +117,46 @@ public QueueStatusResponse getQueueStatusByName(String queueName) { | |
.findByQueueName(queueName) | ||
.map( | ||
queue -> | ||
new QueueStatusResponse( | ||
queue.getQueueId(), | ||
queue.getQueueName(), | ||
queue.getTokens().stream() | ||
.filter(user -> user.getStatus().equals(TokenStatus.WAITING)) | ||
.count(), | ||
Long.valueOf(queue.getTokens().size()), | ||
queue.getQueueCreationTimestamp())) | ||
{ | ||
try { | ||
CustomQuestions customQuestions = queue.getCustomQuestions() != null | ||
? mapper.readValue(queue.getCustomQuestions(), CustomQuestions.class) | ||
: null; | ||
return new QueueStatusResponse( | ||
queue.getQueueId(), | ||
queue.getQueueName(), | ||
queue.getTokens().stream() | ||
.filter(user -> user.getStatus().equals(TokenStatus.WAITING)) | ||
.count(), | ||
Long.valueOf(queue.getTokens().size()), | ||
queue.getQueueCreationTimestamp(), | ||
customQuestions); | ||
} catch (JsonProcessingException e) { | ||
e.printStackTrace(); | ||
} | ||
return null; | ||
}) | ||
.orElseThrow(SQInvalidRequestException::queueNotFoundException); | ||
} | ||
|
||
@Transactional | ||
public CustomQuestions createCustomQuestions(String queueId, String customQuestions) throws JsonProcessingException { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can remove the throws part |
||
CustomQuestions customQuestionsObject = mapper.readValue(customQuestions, CustomQuestions.class); | ||
var queue = queueRepository | ||
.findById(queueId) | ||
.map( | ||
queue1 -> { | ||
if (!queue1.getOwnerId().equals(loggedInUserInfo.getUserId())) { | ||
throw new SQAccessDeniedException("You do not have access to this queue"); | ||
} | ||
try { | ||
queue1.setCustomQuestions(mapper.writeValueAsString(customQuestionsObject)); | ||
} catch (JsonProcessingException e) { | ||
e.printStackTrace(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is better to be logged using a logger, for future debugging. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also I think you should throw an 500 internal error here |
||
} | ||
return queueRepository.save(queue1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line should be moved in try block, and return null instead. |
||
}) | ||
.orElseThrow(SQInvalidRequestException::queueNotFoundException); | ||
return customQuestionsObject; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove throws parts