add mutations to questions and reviews
This commit is contained in:
605
app/graphql/__generated__/schema.graphql
generated
Normal file
605
app/graphql/__generated__/schema.graphql
generated
Normal file
@@ -0,0 +1,605 @@
|
|||||||
|
type Axis {
|
||||||
|
id: ID!
|
||||||
|
name: String!
|
||||||
|
subjects: [Subject!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Category {
|
||||||
|
id: ID!
|
||||||
|
name: String!
|
||||||
|
subjects: [Subject!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of CreateQuestion
|
||||||
|
"""
|
||||||
|
input CreateQuestionInput {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
question: QuestionCreateInput!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of CreateQuestion
|
||||||
|
"""
|
||||||
|
type CreateQuestionPayload {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Errors encountered during execution of the mutation.
|
||||||
|
"""
|
||||||
|
errors: [String!]!
|
||||||
|
question: Question
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of CreateReviewMessage
|
||||||
|
"""
|
||||||
|
input CreateReviewMessageInput {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
message: ReviewMessageInput!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of CreateReviewMessage
|
||||||
|
"""
|
||||||
|
type CreateReviewMessagePayload {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Errors encountered during execution of the mutation.
|
||||||
|
"""
|
||||||
|
errors: [String!]!
|
||||||
|
reviewMessage: ReviewMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
input DateRangeInput {
|
||||||
|
endAt: ISO8601Date!
|
||||||
|
startAt: ISO8601Date!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of DestroyQuestion
|
||||||
|
"""
|
||||||
|
input DestroyQuestionInput {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
questionId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of DestroyQuestion
|
||||||
|
"""
|
||||||
|
type DestroyQuestionPayload {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
deletedQuestionId: ID
|
||||||
|
|
||||||
|
"""
|
||||||
|
Errors encountered during execution of the mutation.
|
||||||
|
"""
|
||||||
|
errors: [String!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of FinishQuestion
|
||||||
|
"""
|
||||||
|
input FinishQuestionInput {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
questionId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of FinishQuestion
|
||||||
|
"""
|
||||||
|
type FinishQuestionPayload {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Errors encountered during execution of the mutation.
|
||||||
|
"""
|
||||||
|
errors: [String!]!
|
||||||
|
question: Question
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
An ISO 8601-encoded date
|
||||||
|
"""
|
||||||
|
scalar ISO8601Date
|
||||||
|
|
||||||
|
"""
|
||||||
|
An ISO 8601-encoded datetime
|
||||||
|
"""
|
||||||
|
scalar ISO8601DateTime
|
||||||
|
|
||||||
|
"""
|
||||||
|
Represents untyped JSON
|
||||||
|
"""
|
||||||
|
scalar JSON
|
||||||
|
|
||||||
|
type Mutation {
|
||||||
|
createQuestion(
|
||||||
|
"""
|
||||||
|
Parameters for CreateQuestion
|
||||||
|
"""
|
||||||
|
input: CreateQuestionInput!
|
||||||
|
): CreateQuestionPayload
|
||||||
|
createReviewMessage(
|
||||||
|
"""
|
||||||
|
Parameters for CreateReviewMessage
|
||||||
|
"""
|
||||||
|
input: CreateReviewMessageInput!
|
||||||
|
): CreateReviewMessagePayload
|
||||||
|
destroyQuestion(
|
||||||
|
"""
|
||||||
|
Parameters for DestroyQuestion
|
||||||
|
"""
|
||||||
|
input: DestroyQuestionInput!
|
||||||
|
): DestroyQuestionPayload
|
||||||
|
finishQuestion(
|
||||||
|
"""
|
||||||
|
Parameters for FinishQuestion
|
||||||
|
"""
|
||||||
|
input: FinishQuestionInput!
|
||||||
|
): FinishQuestionPayload
|
||||||
|
updateQuestion(
|
||||||
|
"""
|
||||||
|
Parameters for UpdateQuestion
|
||||||
|
"""
|
||||||
|
input: UpdateQuestionInput!
|
||||||
|
): UpdateQuestionPayload
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
An object with an ID.
|
||||||
|
"""
|
||||||
|
interface Node {
|
||||||
|
"""
|
||||||
|
ID of the object.
|
||||||
|
"""
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Information about pagination in a connection.
|
||||||
|
"""
|
||||||
|
type PageInfo {
|
||||||
|
"""
|
||||||
|
When paginating forwards, the cursor to continue.
|
||||||
|
"""
|
||||||
|
endCursor: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
When paginating forwards, are there more items?
|
||||||
|
"""
|
||||||
|
hasNextPage: Boolean!
|
||||||
|
|
||||||
|
"""
|
||||||
|
When paginating backwards, are there more items?
|
||||||
|
"""
|
||||||
|
hasPreviousPage: Boolean!
|
||||||
|
|
||||||
|
"""
|
||||||
|
When paginating backwards, the cursor to continue.
|
||||||
|
"""
|
||||||
|
startCursor: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
currentUser: User
|
||||||
|
|
||||||
|
"""
|
||||||
|
Fetches an object given its ID.
|
||||||
|
"""
|
||||||
|
node(
|
||||||
|
"""
|
||||||
|
ID of the object.
|
||||||
|
"""
|
||||||
|
id: ID!
|
||||||
|
): Node
|
||||||
|
|
||||||
|
"""
|
||||||
|
Fetches a list of objects given a list of IDs.
|
||||||
|
"""
|
||||||
|
nodes(
|
||||||
|
"""
|
||||||
|
IDs of the objects.
|
||||||
|
"""
|
||||||
|
ids: [ID!]!
|
||||||
|
): [Node]!
|
||||||
|
questions(
|
||||||
|
"""
|
||||||
|
Returns the elements in the list that come after the specified cursor.
|
||||||
|
"""
|
||||||
|
after: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the elements in the list that come before the specified cursor.
|
||||||
|
"""
|
||||||
|
before: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the first _n_ elements from the list.
|
||||||
|
"""
|
||||||
|
first: Int
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the last _n_ elements from the list.
|
||||||
|
"""
|
||||||
|
last: Int
|
||||||
|
where: QuestionWhereInput
|
||||||
|
): QuestionConnection!
|
||||||
|
reviewers(
|
||||||
|
"""
|
||||||
|
Returns the elements in the list that come after the specified cursor.
|
||||||
|
"""
|
||||||
|
after: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the elements in the list that come before the specified cursor.
|
||||||
|
"""
|
||||||
|
before: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the first _n_ elements from the list.
|
||||||
|
"""
|
||||||
|
first: Int
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the last _n_ elements from the list.
|
||||||
|
"""
|
||||||
|
last: Int
|
||||||
|
): UserConnection!
|
||||||
|
subjects(
|
||||||
|
"""
|
||||||
|
Returns the elements in the list that come after the specified cursor.
|
||||||
|
"""
|
||||||
|
after: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the elements in the list that come before the specified cursor.
|
||||||
|
"""
|
||||||
|
before: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the first _n_ elements from the list.
|
||||||
|
"""
|
||||||
|
first: Int
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the last _n_ elements from the list.
|
||||||
|
"""
|
||||||
|
last: Int
|
||||||
|
): SubjectConnection!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Question implements Node {
|
||||||
|
alternatives: JSON!
|
||||||
|
authorship: String
|
||||||
|
authorshipYear: String
|
||||||
|
bloomTaxonomy: QuestionBloomTaxonomy
|
||||||
|
body: String
|
||||||
|
checkType: QuestionCheckType
|
||||||
|
createdAt: ISO8601DateTime!
|
||||||
|
difficulty: QuestionDifficulty
|
||||||
|
explanation: String
|
||||||
|
id: ID!
|
||||||
|
instruction: String
|
||||||
|
intention: String
|
||||||
|
references: String
|
||||||
|
status: QuestionStatus!
|
||||||
|
subjectId: Int
|
||||||
|
support: String
|
||||||
|
updatedAt: ISO8601DateTime!
|
||||||
|
userId: Int!
|
||||||
|
}
|
||||||
|
|
||||||
|
input QuestionAlternativeInput {
|
||||||
|
correct: Boolean
|
||||||
|
text: String
|
||||||
|
}
|
||||||
|
|
||||||
|
enum QuestionBloomTaxonomy {
|
||||||
|
ANALYZE
|
||||||
|
APPLY
|
||||||
|
CREATE
|
||||||
|
EVALUATE
|
||||||
|
REMEMBER
|
||||||
|
UNDERSTAND
|
||||||
|
}
|
||||||
|
|
||||||
|
enum QuestionCheckType {
|
||||||
|
ASSERTION_AND_REASON
|
||||||
|
ASSOCIATION
|
||||||
|
CONSTANT_ALTERNATIVES
|
||||||
|
GAP
|
||||||
|
INCOMPLETE_AFFIRMATION
|
||||||
|
INTERPRETATION
|
||||||
|
MULTIPLE_ANSWER
|
||||||
|
NEGATIVE_FOCUS
|
||||||
|
ORDERING_OR_RANKING
|
||||||
|
UNIQUE_ANSWER
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
The connection type for Question.
|
||||||
|
"""
|
||||||
|
type QuestionConnection {
|
||||||
|
"""
|
||||||
|
A list of edges.
|
||||||
|
"""
|
||||||
|
edges: [QuestionEdge]
|
||||||
|
|
||||||
|
"""
|
||||||
|
A list of nodes.
|
||||||
|
"""
|
||||||
|
nodes: [Question]
|
||||||
|
|
||||||
|
"""
|
||||||
|
Information to aid in pagination.
|
||||||
|
"""
|
||||||
|
pageInfo: PageInfo!
|
||||||
|
}
|
||||||
|
|
||||||
|
input QuestionCreateInput {
|
||||||
|
alternatives: [QuestionAlternativeInput!]!
|
||||||
|
authorship: String!
|
||||||
|
authorshipYear: String!
|
||||||
|
bloomTaxonomy: QuestionBloomTaxonomy
|
||||||
|
body: String!
|
||||||
|
checkType: QuestionCheckType
|
||||||
|
difficulty: QuestionDifficulty
|
||||||
|
explanation: String!
|
||||||
|
instruction: String!
|
||||||
|
intention: String
|
||||||
|
references: String!
|
||||||
|
reviewerUserId: ID
|
||||||
|
status: QuestionStatus!
|
||||||
|
subjectId: ID
|
||||||
|
support: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
enum QuestionDifficulty {
|
||||||
|
EASY
|
||||||
|
HARD
|
||||||
|
MEDIUM
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
An edge in a connection.
|
||||||
|
"""
|
||||||
|
type QuestionEdge {
|
||||||
|
"""
|
||||||
|
A cursor for use in pagination.
|
||||||
|
"""
|
||||||
|
cursor: String!
|
||||||
|
|
||||||
|
"""
|
||||||
|
The item at the end of the edge.
|
||||||
|
"""
|
||||||
|
node: Question
|
||||||
|
}
|
||||||
|
|
||||||
|
enum QuestionStatus {
|
||||||
|
APPROVED
|
||||||
|
DRAFT
|
||||||
|
REGISTERED
|
||||||
|
WAITING_REVIEW
|
||||||
|
WITH_REQUESTED_CHANGES
|
||||||
|
}
|
||||||
|
|
||||||
|
input QuestionUpdateInput {
|
||||||
|
alternatives: [QuestionAlternativeInput!]!
|
||||||
|
authorship: String!
|
||||||
|
authorshipYear: String!
|
||||||
|
bloomTaxonomy: QuestionBloomTaxonomy
|
||||||
|
body: String!
|
||||||
|
checkType: QuestionCheckType
|
||||||
|
difficulty: QuestionDifficulty
|
||||||
|
explanation: String!
|
||||||
|
id: ID!
|
||||||
|
instruction: String!
|
||||||
|
intention: String
|
||||||
|
references: String!
|
||||||
|
reviewerUserId: ID
|
||||||
|
status: QuestionStatus!
|
||||||
|
subjectId: ID
|
||||||
|
support: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
input QuestionWhereInput {
|
||||||
|
authorshipYear: [String!]
|
||||||
|
bloomTaxonomy: [QuestionBloomTaxonomy!]
|
||||||
|
checkType: [QuestionCheckType!]
|
||||||
|
createDate: DateRangeInput
|
||||||
|
difficulty: [QuestionDifficulty!]
|
||||||
|
status: [QuestionStatus!]
|
||||||
|
subjectId: ID
|
||||||
|
unifesoAuthorship: Boolean
|
||||||
|
userId: ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReviewMessage {
|
||||||
|
createdAt: ISO8601DateTime!
|
||||||
|
feedbackType: ReviewMessageFeedbackType!
|
||||||
|
id: ID!
|
||||||
|
question: Question!
|
||||||
|
text: String!
|
||||||
|
updatedAt: ISO8601DateTime!
|
||||||
|
user: User!
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ReviewMessageFeedbackType {
|
||||||
|
ANSWER
|
||||||
|
APPROVE
|
||||||
|
REQUEST_CHANGES
|
||||||
|
}
|
||||||
|
|
||||||
|
input ReviewMessageInput {
|
||||||
|
feedbackType: ReviewMessageFeedbackType!
|
||||||
|
questionId: ID!
|
||||||
|
text: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Subject {
|
||||||
|
axis: Axis!
|
||||||
|
category: Category!
|
||||||
|
id: ID!
|
||||||
|
name: String!
|
||||||
|
questions(
|
||||||
|
"""
|
||||||
|
Returns the elements in the list that come after the specified cursor.
|
||||||
|
"""
|
||||||
|
after: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the elements in the list that come before the specified cursor.
|
||||||
|
"""
|
||||||
|
before: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the first _n_ elements from the list.
|
||||||
|
"""
|
||||||
|
first: Int
|
||||||
|
|
||||||
|
"""
|
||||||
|
Returns the last _n_ elements from the list.
|
||||||
|
"""
|
||||||
|
last: Int
|
||||||
|
where: QuestionWhereInput
|
||||||
|
): QuestionConnection!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
The connection type for Subject.
|
||||||
|
"""
|
||||||
|
type SubjectConnection {
|
||||||
|
"""
|
||||||
|
A list of edges.
|
||||||
|
"""
|
||||||
|
edges: [SubjectEdge]
|
||||||
|
|
||||||
|
"""
|
||||||
|
A list of nodes.
|
||||||
|
"""
|
||||||
|
nodes: [Subject]
|
||||||
|
|
||||||
|
"""
|
||||||
|
Information to aid in pagination.
|
||||||
|
"""
|
||||||
|
pageInfo: PageInfo!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
An edge in a connection.
|
||||||
|
"""
|
||||||
|
type SubjectEdge {
|
||||||
|
"""
|
||||||
|
A cursor for use in pagination.
|
||||||
|
"""
|
||||||
|
cursor: String!
|
||||||
|
|
||||||
|
"""
|
||||||
|
The item at the end of the edge.
|
||||||
|
"""
|
||||||
|
node: Subject
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of UpdateQuestion
|
||||||
|
"""
|
||||||
|
input UpdateQuestionInput {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
question: QuestionUpdateInput!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of UpdateQuestion
|
||||||
|
"""
|
||||||
|
type UpdateQuestionPayload {
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Errors encountered during execution of the mutation.
|
||||||
|
"""
|
||||||
|
errors: [String!]!
|
||||||
|
question: Question
|
||||||
|
}
|
||||||
|
|
||||||
|
type User {
|
||||||
|
email: String!
|
||||||
|
id: ID!
|
||||||
|
name: String!
|
||||||
|
roles: [UserRole!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
The connection type for User.
|
||||||
|
"""
|
||||||
|
type UserConnection {
|
||||||
|
"""
|
||||||
|
A list of edges.
|
||||||
|
"""
|
||||||
|
edges: [UserEdge]
|
||||||
|
|
||||||
|
"""
|
||||||
|
A list of nodes.
|
||||||
|
"""
|
||||||
|
nodes: [User]
|
||||||
|
|
||||||
|
"""
|
||||||
|
Information to aid in pagination.
|
||||||
|
"""
|
||||||
|
pageInfo: PageInfo!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
An edge in a connection.
|
||||||
|
"""
|
||||||
|
type UserEdge {
|
||||||
|
"""
|
||||||
|
A cursor for use in pagination.
|
||||||
|
"""
|
||||||
|
cursor: String!
|
||||||
|
|
||||||
|
"""
|
||||||
|
The item at the end of the edge.
|
||||||
|
"""
|
||||||
|
node: User
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UserRole {
|
||||||
|
ADMIN
|
||||||
|
CENTER_DIRECTOR
|
||||||
|
COORDINATOR
|
||||||
|
NDE
|
||||||
|
PRO_RECTOR
|
||||||
|
TEACHER
|
||||||
|
}
|
||||||
9
app/graphql/enums/review_message_feedback_type_enum.rb
Normal file
9
app/graphql/enums/review_message_feedback_type_enum.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Enums
|
||||||
|
class ReviewMessageFeedbackTypeEnum < Types::BaseEnum
|
||||||
|
graphql_name "ReviewMessageFeedbackType"
|
||||||
|
|
||||||
|
values_from_enumerize(ReviewMessage.feedback_type)
|
||||||
|
end
|
||||||
|
end
|
||||||
8
app/graphql/inputs/question_alternative_input.rb
Normal file
8
app/graphql/inputs/question_alternative_input.rb
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Inputs
|
||||||
|
class QuestionAlternativeInput < Types::BaseInputObject
|
||||||
|
argument :correct, Boolean, required: false
|
||||||
|
argument :text, String, required: false
|
||||||
|
end
|
||||||
|
end
|
||||||
21
app/graphql/inputs/question_create_input.rb
Normal file
21
app/graphql/inputs/question_create_input.rb
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Inputs
|
||||||
|
class QuestionCreateInput < Types::BaseInputObject
|
||||||
|
argument :instruction, String, required: true
|
||||||
|
argument :support, String, required: true
|
||||||
|
argument :body, String, required: true
|
||||||
|
argument :alternatives, [QuestionAlternativeInput], required: true
|
||||||
|
argument :explanation, String, required: true
|
||||||
|
argument :references, String, required: true
|
||||||
|
argument :authorship_year, String, required: true
|
||||||
|
argument :authorship, String, required: true
|
||||||
|
argument :intention, String, required: false
|
||||||
|
argument :status, Enums::QuestionStatusEnum, required: true
|
||||||
|
argument :check_type, Enums::QuestionCheckTypeEnum, required: false
|
||||||
|
argument :difficulty, Enums::QuestionDifficultyEnum, required: false
|
||||||
|
argument :bloom_taxonomy, Enums::QuestionBloomTaxonomyEnum, required: false
|
||||||
|
argument :subject_id, ID, required: false
|
||||||
|
argument :reviewer_user_id, ID, required: false
|
||||||
|
end
|
||||||
|
end
|
||||||
7
app/graphql/inputs/question_update_input.rb
Normal file
7
app/graphql/inputs/question_update_input.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Inputs
|
||||||
|
class QuestionUpdateInput < QuestionCreateInput
|
||||||
|
argument :id, ID, required: true
|
||||||
|
end
|
||||||
|
end
|
||||||
9
app/graphql/inputs/review_message_input.rb
Normal file
9
app/graphql/inputs/review_message_input.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Inputs
|
||||||
|
class ReviewMessageInput < Types::BaseInputObject
|
||||||
|
argument :feedback_type, Enums::ReviewMessageFeedbackTypeEnum, required: true
|
||||||
|
argument :text, String, required: true
|
||||||
|
argument :question_id, ID, required: true
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -4,5 +4,13 @@ module Mutations
|
|||||||
field_class Types::BaseField
|
field_class Types::BaseField
|
||||||
input_object_class Types::BaseInputObject
|
input_object_class Types::BaseInputObject
|
||||||
object_class Types::BaseObject
|
object_class Types::BaseObject
|
||||||
|
|
||||||
|
field :errors, [String],
|
||||||
|
null: false,
|
||||||
|
description: "Errors encountered during execution of the mutation."
|
||||||
|
|
||||||
|
def current_user
|
||||||
|
context[:current_user]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
35
app/graphql/mutations/create_question.rb
Normal file
35
app/graphql/mutations/create_question.rb
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Mutations
|
||||||
|
class CreateQuestion < BaseMutation
|
||||||
|
field :question, Types::QuestionType, null: true
|
||||||
|
|
||||||
|
argument :question, Inputs::QuestionCreateInput, required: true
|
||||||
|
|
||||||
|
def resolve(question:)
|
||||||
|
question = question.to_h
|
||||||
|
reviewer_user_id = question.delete(:reviewer_user_id)
|
||||||
|
|
||||||
|
record = Question.new(question)
|
||||||
|
record.user_id = context[:current_user].id
|
||||||
|
|
||||||
|
policy = QuestionPolicy.new(context[:current_user], record)
|
||||||
|
|
||||||
|
raise Pundit::NotAuthorizedError unless policy.create?
|
||||||
|
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
record.save!
|
||||||
|
|
||||||
|
if reviewer_user_id.present? && question[:status] != "draft"
|
||||||
|
record.review_requests.create!(user_id: reviewer_user_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
{ question: record, errors: [] }
|
||||||
|
rescue ActiveRecord::RecordInvalid
|
||||||
|
{ question: nil, errors: record.errors.full_messages }
|
||||||
|
end
|
||||||
|
rescue Pundit::NotAuthorizedError => e
|
||||||
|
{ question: nil, errors: [e.message] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
53
app/graphql/mutations/create_review_message.rb
Normal file
53
app/graphql/mutations/create_review_message.rb
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Mutations
|
||||||
|
class CreateReviewMessage < BaseMutation
|
||||||
|
field :review_message, Types::ReviewMessageType, null: true
|
||||||
|
|
||||||
|
argument :message, Inputs::ReviewMessageInput, required: true
|
||||||
|
|
||||||
|
def resolve(message:)
|
||||||
|
message = message.to_h
|
||||||
|
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
record = ReviewMessage.create!({
|
||||||
|
**message,
|
||||||
|
user_id: current_user.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
update_question_status(record.question, message[:feedback_type])
|
||||||
|
update_review_requests(record.question, message[:feedback_type])
|
||||||
|
|
||||||
|
{ review_message: record, errors: [] }
|
||||||
|
rescue ActiveRecord::RecordInvalid => e
|
||||||
|
{ review_message: nil, errors: e.record.errors.full_messages }
|
||||||
|
end
|
||||||
|
rescue Pundit::NotAuthorizedError => e
|
||||||
|
{ review_message: nil, errors: [e.message] }
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def update_question_status(question, feedback_type)
|
||||||
|
new_question_status = case feedback_type
|
||||||
|
when "request_changes"
|
||||||
|
"with_requested_changes"
|
||||||
|
when "approve"
|
||||||
|
"approved"
|
||||||
|
when "answer"
|
||||||
|
"waiting_review"
|
||||||
|
end
|
||||||
|
|
||||||
|
question.update!(status: new_question_status)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_review_requests(question, feedback_type)
|
||||||
|
return question.review_requests.update_all(answered: false) if feedback_type == "answer"
|
||||||
|
|
||||||
|
question
|
||||||
|
.review_requests
|
||||||
|
.where(user_id: current_user.id)
|
||||||
|
.update_all(answered: question.user_id != current_user.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
26
app/graphql/mutations/destroy_question.rb
Normal file
26
app/graphql/mutations/destroy_question.rb
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Mutations
|
||||||
|
class DestroyQuestion < BaseMutation
|
||||||
|
field :deleted_question_id, ID, null: true
|
||||||
|
|
||||||
|
argument :question_id, ID, required: true
|
||||||
|
|
||||||
|
def resolve(question_id:)
|
||||||
|
question = Question.find_by(id: question_id)
|
||||||
|
reviewer = question.reviewer
|
||||||
|
|
||||||
|
raise Pundit::NotAuthorizedError unless QuestionPolicy.new(context[:current_user], question).destroy?
|
||||||
|
|
||||||
|
return { errors: question.errors.full_messages } unless question.destroy!
|
||||||
|
|
||||||
|
ReviewerMailer.with(question_id: question_id, recipient: reviewer)
|
||||||
|
.question_deleted_notification
|
||||||
|
.deliver if reviewer
|
||||||
|
|
||||||
|
{ deleted_question_id: question_id, errors: [] }
|
||||||
|
rescue Pundit::NotAuthorizedError => e
|
||||||
|
{ errors: [e.message] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
26
app/graphql/mutations/finish_question.rb
Normal file
26
app/graphql/mutations/finish_question.rb
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Mutations
|
||||||
|
class FinishQuestion < BaseMutation
|
||||||
|
field :question, Types::QuestionType, null: true
|
||||||
|
|
||||||
|
argument :question_id, ID, required: true
|
||||||
|
|
||||||
|
def resolve(input)
|
||||||
|
user = context[:current_user]
|
||||||
|
|
||||||
|
question = ::Question.find(input[:question_id])
|
||||||
|
|
||||||
|
raise Pundit::NotAuthorizedError unless QuestionPolicy.new(user, question).finish?
|
||||||
|
|
||||||
|
if question.update(status: :registered)
|
||||||
|
{ question: question, errors: [] }
|
||||||
|
else
|
||||||
|
{ question: nil, errors: question.errors.full_messages }
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue Pundit::NotAuthorizedError => e
|
||||||
|
{ question: nil, errors: [e.message] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
37
app/graphql/mutations/update_question.rb
Normal file
37
app/graphql/mutations/update_question.rb
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Mutations
|
||||||
|
class UpdateQuestion < BaseMutation
|
||||||
|
field :question, Types::QuestionType, null: true
|
||||||
|
|
||||||
|
argument :question, Inputs::QuestionUpdateInput, required: true
|
||||||
|
|
||||||
|
def resolve(question:)
|
||||||
|
question = question.to_h
|
||||||
|
reviewer_user_id = question.delete(:reviewer_user_id)
|
||||||
|
|
||||||
|
record = Question.find(question[:id])
|
||||||
|
|
||||||
|
raise Pundit::NotAuthorizedError unless QuestionPolicy.new(context[:current_user], record).update?
|
||||||
|
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
record.update!(question)
|
||||||
|
|
||||||
|
if reviewer_user_id.present? && question[:status] != "draft"
|
||||||
|
review_request = record.review_requests.find_or_create_by!(
|
||||||
|
user_id: reviewer_user_id
|
||||||
|
)
|
||||||
|
|
||||||
|
review_request.update!(answered: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
{ question: record, errors: [] }
|
||||||
|
rescue ActiveRecord::RecordInvalid
|
||||||
|
{ question: nil, errors: question.errors.full_messages }
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue Pundit::NotAuthorizedError => e
|
||||||
|
{ question: nil, errors: [e.message] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
class ProgressTestSchema < GraphQL::Schema
|
class ProgressTestSchema < GraphQL::Schema
|
||||||
|
DEFINITION_DUMP_PATH = "app/graphql/__generated__/schema.graphql"
|
||||||
|
|
||||||
mutation(Types::MutationType)
|
mutation(Types::MutationType)
|
||||||
query(Types::QueryType)
|
query(Types::QueryType)
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
module Types
|
module Types
|
||||||
class MutationType < Types::BaseObject
|
class MutationType < Types::BaseObject
|
||||||
# TODO: remove me
|
field :create_question, mutation: Mutations::CreateQuestion
|
||||||
field :test_field, String, null: false,
|
field :update_question, mutation: Mutations::UpdateQuestion
|
||||||
description: "An example field added by the generator"
|
field :destroy_question, mutation: Mutations::DestroyQuestion
|
||||||
def test_field
|
field :finish_question, mutation: Mutations::FinishQuestion
|
||||||
"Hello World"
|
field :create_review_message, mutation: Mutations::CreateReviewMessage
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
14
app/graphql/types/review_message_type.rb
Normal file
14
app/graphql/types/review_message_type.rb
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Types
|
||||||
|
class ReviewMessageType < Types::BaseObject
|
||||||
|
graphql_name "ReviewMessage"
|
||||||
|
|
||||||
|
field :id, ID, null: false
|
||||||
|
field :user, UserType, null: false
|
||||||
|
field :question, QuestionType, null: false
|
||||||
|
field :text, String, null: false
|
||||||
|
field :feedback_type, Enums::ReviewMessageFeedbackTypeEnum, null: false
|
||||||
|
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
|
||||||
|
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
20
app/graphql/types/review_request_type.rb
Normal file
20
app/graphql/types/review_request_type.rb
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Types
|
||||||
|
class ReviewRequestType < Types::BaseObject
|
||||||
|
graphql_name "ReviewRequest"
|
||||||
|
|
||||||
|
field :id, ID, null: false
|
||||||
|
field :answered, Boolean, null: false
|
||||||
|
|
||||||
|
field :question, Types::QuestionType, null: false
|
||||||
|
def question
|
||||||
|
dataloader.with(Sources::ActiveRecord, Question).load(object.question_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
field :user, Types::UserType, null: false
|
||||||
|
def user
|
||||||
|
dataloader.with(Sources::ActiveRecord, User).load(object.user_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
11
lib/tasks/graphql.rake
Normal file
11
lib/tasks/graphql.rake
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace :graphql do
|
||||||
|
desc "Dump graphql schema to app/graphql/__generated__/schema.graphql"
|
||||||
|
task dump: :environment do
|
||||||
|
File.write(
|
||||||
|
Rails.root.join(ProgressTestSchema::DEFINITION_DUMP_PATH),
|
||||||
|
ProgressTestSchema.to_definition
|
||||||
|
)
|
||||||
|
|
||||||
|
puts("#{ProgressTestSchema::DEFINITION_DUMP_PATH} updated")
|
||||||
|
end
|
||||||
|
end
|
||||||
13
spec/graphql/progress_test_schema_spec.rb
Normal file
13
spec/graphql/progress_test_schema_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
describe ProgressTestSchema do
|
||||||
|
context "schema dump" do
|
||||||
|
it "is updated" do
|
||||||
|
File.open(described_class::DEFINITION_DUMP_PATH, "r") do |f|
|
||||||
|
expect(f.read).to(eq(described_class.to_definition))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user