add body to submission draft in graphql

we need to add a 'body' field to the submission draft type
in graphql to allow us to store text entry drafts going forward.

Test Plan:
* run the db migration to add body to submission draft:
** bundle exec rake db:migrate:up VERSION=20190801215707

* create an assignment as a teacher
* add a student to that assignment
* run the following in the /graphiql endpoint to locate the
  submissions for that assignment

  ```query MyQuery {
  assignment(id: "1") {
    submissionsConnection(filter: {states: [unsubmitted, submitted, graded, pending_review]}) {
      nodes {
        _id
        submissionDraft {
          body
        }
      }
    }
  }
}```

** you should see a submission with a null submission draft

* in the rails console, you will need to add a submission
  draft with a body to that submission
** sub = Submission.find(1) // or whatever your submission ID is
** draft = SubmissionDraft.create!(submission: sub,
   submission_attempt = sub.attempt + 1)
** draft.body = 'some text'
** draft.save!
** sub.submission_drafts = [draft]
** sub.save!

* run the query in graphql again, and you should see something
  like:

```
{
  "data": {
    "assignment": {
      "submissionsConnection": {
        "nodes": [
          {
            "_id": "31",
            "submissionDraft": {
              "body": "some text"
            }
          }
        ]
      }
    }
  }
}
```

fixes COMMS-2263

Change-Id: I62877ac43727f02191c84a98e2609bd8f9987733
Reviewed-on: https://gerrit.instructure.com/203674
Reviewed-by: Steven Burnett <sburnett@instructure.com>
Reviewed-by: Landon Gilbert-Bland <lbland@instructure.com>
Reviewed-by: Cameron Matheson <cameron@instructure.com>
Tested-by: Jenkins
QA-Review: Matthew Lemon <mlemon@instructure.com>
Product-Review: Ryan Norton <rnorton@instructure.com>
This commit is contained in:
Ryan Norton 2019-08-02 12:20:36 -06:00
parent 7e41826748
commit d790a76222
8 changed files with 93 additions and 18 deletions

View File

@ -0,0 +1,28 @@
#
# Copyright (C) 2019 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
class Loaders::ApiContentAttachmentLoader < GraphQL::Batch::Loader
def initialize(context)
@context = context
end
def perform(htmls)
as = Api.api_bulk_load_user_content_attachments(htmls, @context)
htmls.each { |html| fulfill(html, as) }
end
end

View File

@ -264,17 +264,6 @@ module Types
)
end
class AttachmentPreloader < GraphQL::Batch::Loader
def initialize(context)
@context = context
end
def perform(htmls)
as = Api.api_bulk_load_user_content_attachments(htmls, @context)
htmls.each { |html| fulfill(html, as) }
end
end
field :description, String, null: true
def description
return nil if assignment.description.blank?
@ -282,8 +271,7 @@ module Types
load_locked_for do |lock_info|
# some (but not all) locked assignments allow viewing the description
next nil if lock_info && !assignment.include_description?(current_user, lock_info)
AttachmentPreloader.for(assignment.context).load(assignment.description).then do |preloaded_attachments|
Loaders::ApiContentAttachmentLoader.for(assignment.context).load(assignment.description).then do |preloaded_attachments|
GraphQLHelpers::UserContent.process(assignment.description,
request: context[:request],
context: assignment.context,

View File

@ -22,11 +22,31 @@ module Types
field :_id, ID, 'legacy canvas id', null: false, method: :id
field :submission_attempt, Integer, null: false
field :attachments, [Types::FileType], null: true
def attachments
load_association(:attachments)
end
field :body, String, null: true
def body
load_association(:submission).then do |submission|
Loaders::AssociationLoader.for(Submission, :assignment).load(submission).then do |assignment|
Loaders::AssociationLoader.for(Assignment, :context).load(assignment).then do
Loaders::ApiContentAttachmentLoader.for(assignment.context).load(object.body).then do |preloaded_attachments|
GraphQLHelpers::UserContent.process(
object.body,
context: assignment.context,
in_app: context[:in_app],
request: context[:request],
preloaded_attachments: preloaded_attachments,
user: current_user
)
end
end
end
end
end
field :submission_attempt, Integer, null: false
end
end

View File

@ -26,18 +26,21 @@ export const SubmissionDraft = {
attachments {
...SubmissionDraftFile
}
body
}
${SubmissionDraftFile.fragment}
`,
shape: shape({
_id: string,
attachments: arrayOf(SubmissionDraftFile.shape)
attachments: arrayOf(SubmissionDraftFile.shape),
body: string
})
}
export const SubmissionDraftDefaultMocks = {
SubmissionDraft: () => ({
attachments: () => []
attachments: () => [],
body: null
})
}

View File

@ -24,6 +24,7 @@ class SubmissionDraft < ActiveRecord::Base
validates :submission, presence: true
validates :submission_attempt, numericality: { only_integer: true }
validates :submission, uniqueness: { scope: :submission_attempt }
validates :body, length: {maximum: maximum_text_length, allow_nil: true, allow_blank: true}
validate :submission_attempt_matches_submission
def submission_attempt_matches_submission

View File

@ -0,0 +1,25 @@
#
# Copyright (C) 2019 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
class AddBodyToSubmissionDraft < ActiveRecord::Migration[5.1]
tag :predeploy
def change
add_column :submission_drafts, :body, :text
end
end

View File

@ -2535,6 +2535,7 @@ type SubmissionDraft {
"""
_id: ID!
attachments: [File!]
body: String
submissionAttempt: Int!
}

View File

@ -29,7 +29,7 @@ RSpec.describe Types::SubmissionDraftType do
end
def resolve_submission_draft
result = CanvasSchema.execute(<<~GQL, context: {current_user: @teacher})
result = CanvasSchema.execute(<<~GQL, context: {current_user: @teacher, request: ActionDispatch::TestRequest.create})
query {
assignment(id: "#{@assignment.id}") {
submissionsConnection(filter: {states: [unsubmitted, graded, pending_review, submitted]}) {
@ -40,6 +40,7 @@ RSpec.describe Types::SubmissionDraftType do
_id
displayName
}
body
submissionAttempt
}
}
@ -70,4 +71,12 @@ RSpec.describe Types::SubmissionDraftType do
submission_draft = resolve_submission_draft
expect(submission_draft['attachments'].first['displayName']).to eq(attachment.display_name)
end
it 'returns the draft body' do
@submission_draft.body = 'some text'
@submission_draft.save!
submission_draft = resolve_submission_draft
expect(submission_draft['body']).to eq('some text')
end
end