diff --git a/client/src/app/generated/civic.apollo-helpers.ts b/client/src/app/generated/civic.apollo-helpers.ts index 925b87874..57fdf6be7 100644 --- a/client/src/app/generated/civic.apollo-helpers.ts +++ b/client/src/app/generated/civic.apollo-helpers.ts @@ -46,7 +46,7 @@ export type AdvancedSearchResultFieldPolicy = { resultIds?: FieldPolicy | FieldReadFunction, searchEndpoint?: FieldPolicy | FieldReadFunction }; -export type AssertionKeySpecifier = ('acceptanceEvent' | 'acmgCodes' | 'ampLevel' | 'assertionDirection' | 'assertionType' | 'clingenCodes' | 'clinicalSignificance' | 'comments' | 'description' | 'disease' | 'drugInteractionType' | 'drugs' | 'events' | 'evidenceItems' | 'evidenceItemsCount' | 'fdaCompanionTest' | 'fdaCompanionTestLastUpdated' | 'flagged' | 'flags' | 'id' | 'lastAcceptedRevisionEvent' | 'lastCommentEvent' | 'lastSubmittedRevisionEvent' | 'link' | 'molecularProfile' | 'name' | 'nccnGuideline' | 'nccnGuidelineVersion' | 'phenotypes' | 'regulatoryApproval' | 'regulatoryApprovalLastUpdated' | 'rejectionEvent' | 'revisions' | 'status' | 'submissionEvent' | 'summary' | 'variantOrigin' | AssertionKeySpecifier)[]; +export type AssertionKeySpecifier = ('acceptanceEvent' | 'acmgCodes' | 'ampLevel' | 'assertionDirection' | 'assertionType' | 'clingenCodes' | 'clinicalSignificance' | 'comments' | 'description' | 'disease' | 'drugInteractionType' | 'drugs' | 'events' | 'evidenceItems' | 'evidenceItemsCount' | 'fdaCompanionTest' | 'fdaCompanionTestLastUpdated' | 'flagged' | 'flags' | 'id' | 'lastAcceptedRevisionEvent' | 'lastCommentEvent' | 'lastSubmittedRevisionEvent' | 'link' | 'molecularProfile' | 'name' | 'nccnGuideline' | 'nccnGuidelineVersion' | 'phenotypes' | 'regulatoryApproval' | 'regulatoryApprovalLastUpdated' | 'rejectionEvent' | 'revisions' | 'status' | 'submissionEvent' | 'summary' | 'valid' | 'validationErrors' | 'variantOrigin' | AssertionKeySpecifier)[]; export type AssertionFieldPolicy = { acceptanceEvent?: FieldPolicy | FieldReadFunction, acmgCodes?: FieldPolicy | FieldReadFunction, @@ -84,6 +84,8 @@ export type AssertionFieldPolicy = { status?: FieldPolicy | FieldReadFunction, submissionEvent?: FieldPolicy | FieldReadFunction, summary?: FieldPolicy | FieldReadFunction, + valid?: FieldPolicy | FieldReadFunction, + validationErrors?: FieldPolicy | FieldReadFunction, variantOrigin?: FieldPolicy | FieldReadFunction }; export type AssertionConnectionKeySpecifier = ('edges' | 'nodes' | 'pageCount' | 'pageInfo' | 'totalCount' | AssertionConnectionKeySpecifier)[]; @@ -603,7 +605,7 @@ export type EventSubjectWithCountFieldPolicy = { occuranceCount?: FieldPolicy | FieldReadFunction, subject?: FieldPolicy | FieldReadFunction }; -export type EvidenceItemKeySpecifier = ('acceptanceEvent' | 'assertions' | 'clinicalSignificance' | 'comments' | 'description' | 'disease' | 'drugInteractionType' | 'drugs' | 'events' | 'evidenceDirection' | 'evidenceLevel' | 'evidenceRating' | 'evidenceType' | 'flagged' | 'flags' | 'id' | 'lastAcceptedRevisionEvent' | 'lastCommentEvent' | 'lastSubmittedRevisionEvent' | 'link' | 'molecularProfile' | 'name' | 'phenotypes' | 'rejectionEvent' | 'revisions' | 'source' | 'status' | 'submissionEvent' | 'variant' | 'variantHgvs' | 'variantOrigin' | EvidenceItemKeySpecifier)[]; +export type EvidenceItemKeySpecifier = ('acceptanceEvent' | 'assertions' | 'clinicalSignificance' | 'comments' | 'description' | 'disease' | 'drugInteractionType' | 'drugs' | 'events' | 'evidenceDirection' | 'evidenceLevel' | 'evidenceRating' | 'evidenceType' | 'flagged' | 'flags' | 'id' | 'lastAcceptedRevisionEvent' | 'lastCommentEvent' | 'lastSubmittedRevisionEvent' | 'link' | 'molecularProfile' | 'name' | 'phenotypes' | 'rejectionEvent' | 'revisions' | 'source' | 'status' | 'submissionEvent' | 'valid' | 'validationErrors' | 'variant' | 'variantHgvs' | 'variantOrigin' | EvidenceItemKeySpecifier)[]; export type EvidenceItemFieldPolicy = { acceptanceEvent?: FieldPolicy | FieldReadFunction, assertions?: FieldPolicy | FieldReadFunction, @@ -633,6 +635,8 @@ export type EvidenceItemFieldPolicy = { source?: FieldPolicy | FieldReadFunction, status?: FieldPolicy | FieldReadFunction, submissionEvent?: FieldPolicy | FieldReadFunction, + valid?: FieldPolicy | FieldReadFunction, + validationErrors?: FieldPolicy | FieldReadFunction, variant?: FieldPolicy | FieldReadFunction, variantHgvs?: FieldPolicy | FieldReadFunction, variantOrigin?: FieldPolicy | FieldReadFunction diff --git a/client/src/app/generated/civic.apollo.ts b/client/src/app/generated/civic.apollo.ts index 3a65dea30..2895861b4 100644 --- a/client/src/app/generated/civic.apollo.ts +++ b/client/src/app/generated/civic.apollo.ts @@ -234,6 +234,8 @@ export type Assertion = Commentable & EventOriginObject & EventSubject & Flaggab status: EvidenceStatus; submissionEvent: Event; summary: Scalars['String']; + valid: Scalars['Boolean']; + validationErrors: Array; variantOrigin: VariantOrigin; }; @@ -1448,6 +1450,8 @@ export type EvidenceItem = Commentable & EventOriginObject & EventSubject & Flag source: Source; status: EvidenceStatus; submissionEvent: Event; + valid: Scalars['Boolean']; + validationErrors: Array; variant: Variant; variantHgvs: Scalars['String']; variantOrigin: VariantOrigin; @@ -6103,9 +6107,9 @@ export type AssertionDetailQueryVariables = Exact<{ }>; -export type AssertionDetailQuery = { __typename: 'Query', assertion?: { __typename: 'Assertion', id: number, name: string, status: EvidenceStatus, submissionEvent: { __typename: 'Event', originatingUser: { __typename: 'User', id: number } }, molecularProfile: { __typename: 'MolecularProfile', id: number, name: string, link: string }, flags: { __typename: 'FlagConnection', totalCount: number }, revisions: { __typename: 'RevisionConnection', totalCount: number }, comments: { __typename: 'CommentConnection', totalCount: number } } | undefined }; +export type AssertionDetailQuery = { __typename: 'Query', assertion?: { __typename: 'Assertion', id: number, name: string, status: EvidenceStatus, valid: boolean, validationErrors: Array<{ __typename: 'FieldValidationError', fieldName: string, error: string }>, submissionEvent: { __typename: 'Event', originatingUser: { __typename: 'User', id: number } }, molecularProfile: { __typename: 'MolecularProfile', id: number, name: string, link: string }, flags: { __typename: 'FlagConnection', totalCount: number }, revisions: { __typename: 'RevisionConnection', totalCount: number }, comments: { __typename: 'CommentConnection', totalCount: number } } | undefined }; -export type AssertionDetailFieldsFragment = { __typename: 'Assertion', id: number, name: string, status: EvidenceStatus, submissionEvent: { __typename: 'Event', originatingUser: { __typename: 'User', id: number } }, molecularProfile: { __typename: 'MolecularProfile', id: number, name: string, link: string }, flags: { __typename: 'FlagConnection', totalCount: number }, revisions: { __typename: 'RevisionConnection', totalCount: number }, comments: { __typename: 'CommentConnection', totalCount: number } }; +export type AssertionDetailFieldsFragment = { __typename: 'Assertion', id: number, name: string, status: EvidenceStatus, valid: boolean, validationErrors: Array<{ __typename: 'FieldValidationError', fieldName: string, error: string }>, submissionEvent: { __typename: 'Event', originatingUser: { __typename: 'User', id: number } }, molecularProfile: { __typename: 'MolecularProfile', id: number, name: string, link: string }, flags: { __typename: 'FlagConnection', totalCount: number }, revisions: { __typename: 'RevisionConnection', totalCount: number }, comments: { __typename: 'CommentConnection', totalCount: number } }; export type AssertionSummaryQueryVariables = Exact<{ assertionId: Scalars['Int']; @@ -6167,9 +6171,9 @@ export type EvidenceDetailQueryVariables = Exact<{ }>; -export type EvidenceDetailQuery = { __typename: 'Query', evidenceItem?: { __typename: 'EvidenceItem', id: number, name: string, status: EvidenceStatus, submissionEvent: { __typename: 'Event', originatingUser: { __typename: 'User', id: number } }, molecularProfile: { __typename: 'MolecularProfile', id: number, name: string, link: string }, assertions: Array<{ __typename: 'Assertion', id: number, name: string, link: string }>, flags: { __typename: 'FlagConnection', totalCount: number }, revisions: { __typename: 'RevisionConnection', totalCount: number }, comments: { __typename: 'CommentConnection', totalCount: number } } | undefined }; +export type EvidenceDetailQuery = { __typename: 'Query', evidenceItem?: { __typename: 'EvidenceItem', id: number, name: string, status: EvidenceStatus, valid: boolean, validationErrors: Array<{ __typename: 'FieldValidationError', fieldName: string, error: string }>, submissionEvent: { __typename: 'Event', originatingUser: { __typename: 'User', id: number } }, molecularProfile: { __typename: 'MolecularProfile', id: number, name: string, link: string }, assertions: Array<{ __typename: 'Assertion', id: number, name: string, link: string }>, flags: { __typename: 'FlagConnection', totalCount: number }, revisions: { __typename: 'RevisionConnection', totalCount: number }, comments: { __typename: 'CommentConnection', totalCount: number } } | undefined }; -export type EvidenceDetailFieldsFragment = { __typename: 'EvidenceItem', id: number, name: string, status: EvidenceStatus, submissionEvent: { __typename: 'Event', originatingUser: { __typename: 'User', id: number } }, molecularProfile: { __typename: 'MolecularProfile', id: number, name: string, link: string }, assertions: Array<{ __typename: 'Assertion', id: number, name: string, link: string }>, flags: { __typename: 'FlagConnection', totalCount: number }, revisions: { __typename: 'RevisionConnection', totalCount: number }, comments: { __typename: 'CommentConnection', totalCount: number } }; +export type EvidenceDetailFieldsFragment = { __typename: 'EvidenceItem', id: number, name: string, status: EvidenceStatus, valid: boolean, validationErrors: Array<{ __typename: 'FieldValidationError', fieldName: string, error: string }>, submissionEvent: { __typename: 'Event', originatingUser: { __typename: 'User', id: number } }, molecularProfile: { __typename: 'MolecularProfile', id: number, name: string, link: string }, assertions: Array<{ __typename: 'Assertion', id: number, name: string, link: string }>, flags: { __typename: 'FlagConnection', totalCount: number }, revisions: { __typename: 'RevisionConnection', totalCount: number }, comments: { __typename: 'CommentConnection', totalCount: number } }; export type EvidenceSummaryQueryVariables = Exact<{ evidenceId: Scalars['Int']; @@ -7803,6 +7807,11 @@ export const AssertionDetailFieldsFragmentDoc = gql` id name status + valid + validationErrors { + fieldName + error + } submissionEvent { originatingUser { id @@ -7943,6 +7952,11 @@ export const EvidenceDetailFieldsFragmentDoc = gql` id name status + valid + validationErrors { + fieldName + error + } submissionEvent { originatingUser { id diff --git a/client/src/app/generated/server.model.graphql b/client/src/app/generated/server.model.graphql index 57c1cab30..eb7cf1c9c 100644 --- a/client/src/app/generated/server.model.graphql +++ b/client/src/app/generated/server.model.graphql @@ -498,6 +498,8 @@ type Assertion implements Commentable & EventOriginObject & EventSubject & Flagg status: EvidenceStatus! submissionEvent: Event! summary: String! + valid: Boolean! + validationErrors: [FieldValidationError!]! variantOrigin: VariantOrigin! } @@ -2384,6 +2386,8 @@ type EvidenceItem implements Commentable & EventOriginObject & EventSubject & Fl source: Source! status: EvidenceStatus! submissionEvent: Event! + valid: Boolean! + validationErrors: [FieldValidationError!]! variant: Variant! variantHgvs: String! variantOrigin: VariantOrigin! diff --git a/client/src/app/generated/server.schema.json b/client/src/app/generated/server.schema.json index 5c9d837cd..f1ec58a6c 100644 --- a/client/src/app/generated/server.schema.json +++ b/client/src/app/generated/server.schema.json @@ -1886,6 +1886,46 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "valid", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "validationErrors", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "FieldValidationError", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "variantOrigin", "description": null, @@ -11443,6 +11483,46 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "valid", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "validationErrors", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "FieldValidationError", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "variant", "description": null, diff --git a/client/src/app/views/assertions/assertions-detail/assertions-detail.query.gql b/client/src/app/views/assertions/assertions-detail/assertions-detail.query.gql index 9819707c4..fa4424df2 100644 --- a/client/src/app/views/assertions/assertions-detail/assertions-detail.query.gql +++ b/client/src/app/views/assertions/assertions-detail/assertions-detail.query.gql @@ -7,26 +7,31 @@ query AssertionDetail( } fragment AssertionDetailFields on Assertion { - id - name - status - submissionEvent { - originatingUser { - id - } - } - molecularProfile { + id + name + status + valid + validationErrors { + fieldName + error + } + submissionEvent { + originatingUser { id - name - link - } - flags(state: OPEN) { - totalCount - } - revisions(status: NEW) { - totalCount - } - comments { - totalCount } + } + molecularProfile { + id + name + link + } + flags(state: OPEN) { + totalCount + } + revisions(status: NEW) { + totalCount + } + comments { + totalCount + } } \ No newline at end of file diff --git a/client/src/app/views/assertions/assertions-detail/assertions-detail.view.html b/client/src/app/views/assertions/assertions-detail/assertions-detail.view.html index 3a74b127f..46ec778c8 100644 --- a/client/src/app/views/assertions/assertions-detail/assertions-detail.view.html +++ b/client/src/app/views/assertions/assertions-detail/assertions-detail.view.html @@ -105,6 +105,18 @@ nzMessage="This Assertion has been rejected." nzType="error"> + + + + This Assertion is in an invalid state. +
+ + Field: {{error.fieldName}}. Error: {{error.error}}
+
+
diff --git a/client/src/app/views/evidence/evidence-detail/evidence-detail.query.gql b/client/src/app/views/evidence/evidence-detail/evidence-detail.query.gql index 902b70d20..3ce3b566c 100644 --- a/client/src/app/views/evidence/evidence-detail/evidence-detail.query.gql +++ b/client/src/app/views/evidence/evidence-detail/evidence-detail.query.gql @@ -8,6 +8,11 @@ fragment EvidenceDetailFields on EvidenceItem { id name status + valid + validationErrors { + fieldName + error + } submissionEvent { originatingUser { id diff --git a/client/src/app/views/evidence/evidence-detail/evidence-detail.view.html b/client/src/app/views/evidence/evidence-detail/evidence-detail.view.html index c0ea2f5d8..80dfa04c4 100644 --- a/client/src/app/views/evidence/evidence-detail/evidence-detail.view.html +++ b/client/src/app/views/evidence/evidence-detail/evidence-detail.view.html @@ -100,6 +100,18 @@ nzMessage="This Evidence Item has been rejected." nzType="error"> + + + + This Evidence Item is in an invalid state. +
+ + Field: {{error.fieldName}}. Error: {{error.error}}
+
+
diff --git a/server/app/graphql/types/entities/assertion_type.rb b/server/app/graphql/types/entities/assertion_type.rb index fc2385f21..455cc4ea3 100644 --- a/server/app/graphql/types/entities/assertion_type.rb +++ b/server/app/graphql/types/entities/assertion_type.rb @@ -8,6 +8,8 @@ class AssertionType < Types::BaseObject implements Types::Interfaces::EventOriginObject field :id, Int, null: false + field :valid, Boolean, null: false + field :validation_errors, [Types::FieldValidationErrorType], null: false field :name, String, null: false field :molecular_profile, Types::Entities::MolecularProfileType, null: false field :clinical_significance, Types::AssertionClinicalSignificanceType, null: false @@ -36,6 +38,27 @@ class AssertionType < Types::BaseObject field :evidence_items, [Types::Entities::EvidenceItemType], null: false field :evidence_items_count, Integer, null: false + def valid + object.valid? + end + + def validation_errors + if !object.valid? + object.errors.map do |attribute, message| + attribute = attribute.to_s + if attribute.ends_with?("_ids") + formatted_attribute = attribute.singularize.humanize.pluralize + else + formatted_attribute = attribute.humanize + end + { 'field_name': formatted_attribute, 'error': message } + end + else + [] + end + end + + def disease Loaders::RecordLoader.for(Disease).load(object.disease_id) end diff --git a/server/app/graphql/types/entities/evidence_item_type.rb b/server/app/graphql/types/entities/evidence_item_type.rb index e060634e6..b29809b0f 100644 --- a/server/app/graphql/types/entities/evidence_item_type.rb +++ b/server/app/graphql/types/entities/evidence_item_type.rb @@ -8,6 +8,8 @@ class EvidenceItemType < Types::BaseObject implements Types::Interfaces::EventOriginObject field :id, Int, null: false + field :valid, Boolean, null: false + field :validation_errors, [Types::FieldValidationErrorType], null: false field :name, String, null: false field :molecular_profile, Types::Entities::MolecularProfileType, null: false field :clinical_significance, Types::EvidenceClinicalSignificanceType, null: false @@ -31,6 +33,26 @@ class EvidenceItemType < Types::BaseObject field :rejection_event, Types::Entities::EventType, null: true field :assertions, [Types::Entities::AssertionType], null: false + def valid + object.valid? + end + + def validation_errors + if !object.valid? + object.errors.map do |attribute, message| + attribute = attribute.to_s + if attribute.ends_with?("_ids") + formatted_attribute = attribute.singularize.humanize.pluralize + else + formatted_attribute = attribute.humanize + end + { 'field_name': formatted_attribute, 'error': message } + end + else + [] + end + end + def disease Loaders::RecordLoader.for(Disease).load(object.disease_id) end