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
|
||||
input_object_class Types::BaseInputObject
|
||||
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
|
||||
|
||||
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
|
||||
DEFINITION_DUMP_PATH = "app/graphql/__generated__/schema.graphql"
|
||||
|
||||
mutation(Types::MutationType)
|
||||
query(Types::QueryType)
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
module Types
|
||||
class MutationType < Types::BaseObject
|
||||
# TODO: remove me
|
||||
field :test_field, String, null: false,
|
||||
description: "An example field added by the generator"
|
||||
def test_field
|
||||
"Hello World"
|
||||
end
|
||||
field :create_question, mutation: Mutations::CreateQuestion
|
||||
field :update_question, mutation: Mutations::UpdateQuestion
|
||||
field :destroy_question, mutation: Mutations::DestroyQuestion
|
||||
field :finish_question, mutation: Mutations::FinishQuestion
|
||||
field :create_review_message, mutation: Mutations::CreateReviewMessage
|
||||
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
|
||||
Reference in New Issue
Block a user