diff --git a/app/graphql/types/rubric_assessment_type.rb b/app/graphql/types/rubric_assessment_type.rb index e8f499bc788..38bd03c6d74 100644 --- a/app/graphql/types/rubric_assessment_type.rb +++ b/app/graphql/types/rubric_assessment_type.rb @@ -32,6 +32,11 @@ module Types implements Interfaces::LegacyIDInterface + field :artifact_attempt, Integer, null: false + def artifact_attempt + object.artifact_attempt || 0 + end + field :assessment_type, AssessmentType, null: false field :score, Float, null: true diff --git a/spec/graphql/types/rubric_assessment_type_spec.rb b/spec/graphql/types/rubric_assessment_type_spec.rb index 0eb3024da8b..849b867caa3 100644 --- a/spec/graphql/types/rubric_assessment_type_spec.rb +++ b/spec/graphql/types/rubric_assessment_type_spec.rb @@ -100,4 +100,22 @@ describe Types::RubricAssessmentType do ).to eq [rubric_association.id.to_s] end end + + describe "artifact_attempt" do + it "returns the value when artifact_attempt is non-nil" do + submission.update!(attempt: 2) + rubric_assessment.reload + rubric_assessment.update!(artifact_attempt: 2) + expect( + submission_type.resolve('rubricAssessmentsConnection { nodes { artifactAttempt } }') + ).to eq [2] + end + + it "returns zero when artifact_attempt is nil" do + rubric_assessment.update!(artifact_attempt: nil) + expect( + submission_type.resolve('rubricAssessmentsConnection { nodes { artifactAttempt } }') + ).to eq [0] + end + end end diff --git a/ui/shared/apollo/index.js b/ui/shared/apollo/index.js index d21bd288d94..0db406e4a3c 100644 --- a/ui/shared/apollo/index.js +++ b/ui/shared/apollo/index.js @@ -70,13 +70,24 @@ function createCache() { return new InMemoryCache({ addTypename: true, dataIdFromObject: object => { + let cacheKey + if (object.id) { - return object.id + cacheKey = object.id } else if (object._id && object.__typename) { - return object.__typename + object._id + cacheKey = object.__typename + object._id } else { return null } + + // Multiple distinct RubricAssessments (and likely other versionable + // objects) may be represented by the same ID and type. Add the + // artifactAttempt field to the cache key to assessments for different + // attempts don't collide. + if (object.__typename === 'RubricAssessment' && object.artifactAttempt != null) { + cacheKey = `${cacheKey}:${object.artifactAttempt}` + } + return cacheKey }, fragmentMatcher: new IntrospectionFragmentMatcher({ introspectionQueryResultData diff --git a/ui/shared/assignments/graphql/student/RubricAssessment.js b/ui/shared/assignments/graphql/student/RubricAssessment.js index 5bc9a67e6c1..96e71606cd6 100644 --- a/ui/shared/assignments/graphql/student/RubricAssessment.js +++ b/ui/shared/assignments/graphql/student/RubricAssessment.js @@ -25,6 +25,7 @@ export const RubricAssessment = { fragment: gql` fragment RubricAssessment on RubricAssessment { _id + artifactAttempt assessment_type: assessmentType assessor { _id @@ -47,6 +48,7 @@ export const RubricAssessment = { shape: shape({ _id: string.isRequired, + artifactAttempt: number, assessment_type: string, assessor: shape({ _id: string.isRequired, @@ -61,6 +63,7 @@ export const RubricAssessment = { export const DefaultMocks = { RubricAssessment: () => ({ _id: '1', + artifactAttempt: '1', assessmentType: 'grading', assessmentRatings: [{}], score: '10'