From 0f4d404aa1036f79ae606eff5f5ef418393847e2 Mon Sep 17 00:00:00 2001 From: Adam Coffman Date: Fri, 26 Jul 2024 12:06:52 -0500 Subject: [PATCH 1/2] include full name in feature browse table --- .../features-table.component.html | 22 +++ .../features-table.component.ts | 3 + .../features-table/features-table.query.gql | 3 + .../src/app/generated/civic.apollo-helpers.ts | 20 +-- client/src/app/generated/civic.apollo.ts | 62 ++++++--- client/src/app/generated/server.model.graphql | 3 + client/src/app/generated/server.schema.json | 30 ++++ .../app/graphql/resolvers/browse_features.rb | 3 + .../browse_tables/browse_feature_type.rb | 1 + .../browse_tables/features_sort_columns.rb | 1 + ..._feature_browse_table_rows_to_version_6.rb | 8 ++ server/db/schema.rb | 128 ++++++++++-------- .../views/feature_browse_table_rows_v06.sql | 49 +++++++ 13 files changed, 252 insertions(+), 81 deletions(-) create mode 100644 server/db/migrate/20240726163525_update_feature_browse_table_rows_to_version_6.rb create mode 100644 server/db/views/feature_browse_table_rows_v06.sql diff --git a/client/src/app/components/features/features-table/features-table.component.html b/client/src/app/components/features/features-table/features-table.component.html index 6fd6fe6d1..46a029549 100644 --- a/client/src/app/components/features/features-table/features-table.component.html +++ b/client/src/app/components/features/features-table/features-table.component.html @@ -53,6 +53,13 @@ [nzSortFn]="true"> Name + + Full Name + @@ -130,6 +137,13 @@ filterChange$.next() "> + + + + + + {{ feature.fullName | titlecase }} + + therapyInput?: Maybe nameInput?: Maybe + fullNameInput?: Maybe aliasInput?: Maybe } @@ -89,6 +90,7 @@ export class CvcFeaturesTableComponent implements OnInit { diseaseInput: Maybe therapyInput: Maybe nameInput: Maybe + fullNameInput: Maybe aliasInput: Maybe typeInput: Maybe @@ -194,6 +196,7 @@ export class CvcFeaturesTableComponent implements OnInit { this.queryRef .refetch({ featureName: this.nameInput, + featureFullName: this.fullNameInput, featureAlias: this.aliasInput, diseaseName: this.diseaseInput, therapyName: this.therapyInput, diff --git a/client/src/app/components/features/features-table/features-table.query.gql b/client/src/app/components/features/features-table/features-table.query.gql index 8e0cf6175..3673cc2f8 100644 --- a/client/src/app/components/features/features-table/features-table.query.gql +++ b/client/src/app/components/features/features-table/features-table.query.gql @@ -1,5 +1,6 @@ query BrowseFeatures( $featureName: String + $featureFullName: String $therapyName: String $featureAlias: String $diseaseName: String @@ -12,6 +13,7 @@ query BrowseFeatures( ) { browseFeatures( featureName: $featureName + featureFullName: $featureFullName therapyName: $therapyName featureAlias: $featureAlias diseaseName: $diseaseName @@ -44,6 +46,7 @@ query BrowseFeatures( fragment BrowseFeaturesFields on BrowseFeature { id name + fullName link deprecated flagged diff --git a/client/src/app/generated/civic.apollo-helpers.ts b/client/src/app/generated/civic.apollo-helpers.ts index ee89027c4..30c9d2b61 100644 --- a/client/src/app/generated/civic.apollo-helpers.ts +++ b/client/src/app/generated/civic.apollo-helpers.ts @@ -194,7 +194,7 @@ export type BrowseDiseaseEdgeFieldPolicy = { cursor?: FieldPolicy | FieldReadFunction, node?: FieldPolicy | FieldReadFunction }; -export type BrowseFeatureKeySpecifier = ('assertionCount' | 'deprecated' | 'description' | 'diseases' | 'evidenceItemCount' | 'featureAliases' | 'featureInstanceId' | 'featureInstanceType' | 'flagged' | 'flags' | 'id' | 'link' | 'molecularProfileCount' | 'name' | 'therapies' | 'variantCount' | BrowseFeatureKeySpecifier)[]; +export type BrowseFeatureKeySpecifier = ('assertionCount' | 'deprecated' | 'description' | 'diseases' | 'evidenceItemCount' | 'featureAliases' | 'featureInstanceId' | 'featureInstanceType' | 'flagged' | 'flags' | 'fullName' | 'id' | 'link' | 'molecularProfileCount' | 'name' | 'therapies' | 'variantCount' | BrowseFeatureKeySpecifier)[]; export type BrowseFeatureFieldPolicy = { assertionCount?: FieldPolicy | FieldReadFunction, deprecated?: FieldPolicy | FieldReadFunction, @@ -206,6 +206,7 @@ export type BrowseFeatureFieldPolicy = { featureInstanceType?: FieldPolicy | FieldReadFunction, flagged?: FieldPolicy | FieldReadFunction, flags?: FieldPolicy | FieldReadFunction, + fullName?: FieldPolicy | FieldReadFunction, id?: FieldPolicy | FieldReadFunction, link?: FieldPolicy | FieldReadFunction, molecularProfileCount?: FieldPolicy | FieldReadFunction, @@ -373,33 +374,32 @@ export type BrowseTherapyEdgeFieldPolicy = { cursor?: FieldPolicy | FieldReadFunction, node?: FieldPolicy | FieldReadFunction }; -export type BrowseUserKeySpecifier = ('acceptedLicense' | 'areaOfExpertise' | 'bio' | 'countryId' | 'createdAt' | 'deleted' | 'deletedAt' | 'displayName' | 'email' | 'evidenceCount' | 'facebookProfile' | 'id' | 'lastSeenAt' | 'linkedinProfile' | 'mostRecentActivityTimestamp' | 'mostRecentOrganizationId' | 'name' | 'orcid' | 'organizations' | 'profileImagePath' | 'revisionCount' | 'role' | 'signupComplete' | 'twitterHandle' | 'updatedAt' | 'url' | 'username' | BrowseUserKeySpecifier)[]; +export type BrowseUserKeySpecifier = ('areaOfExpertise' | 'bio' | 'country' | 'displayName' | 'email' | 'events' | 'evidenceCount' | 'facebookProfile' | 'id' | 'linkedinProfile' | 'mostRecentActivityTimestamp' | 'mostRecentConflictOfInterestStatement' | 'mostRecentEvent' | 'mostRecentOrganizationId' | 'name' | 'notifications' | 'orcid' | 'organizations' | 'profileImagePath' | 'ranks' | 'revisionCount' | 'role' | 'statsHash' | 'twitterHandle' | 'url' | 'username' | BrowseUserKeySpecifier)[]; export type BrowseUserFieldPolicy = { - acceptedLicense?: FieldPolicy | FieldReadFunction, areaOfExpertise?: FieldPolicy | FieldReadFunction, bio?: FieldPolicy | FieldReadFunction, - countryId?: FieldPolicy | FieldReadFunction, - createdAt?: FieldPolicy | FieldReadFunction, - deleted?: FieldPolicy | FieldReadFunction, - deletedAt?: FieldPolicy | FieldReadFunction, + country?: FieldPolicy | FieldReadFunction, displayName?: FieldPolicy | FieldReadFunction, email?: FieldPolicy | FieldReadFunction, + events?: FieldPolicy | FieldReadFunction, evidenceCount?: FieldPolicy | FieldReadFunction, facebookProfile?: FieldPolicy | FieldReadFunction, id?: FieldPolicy | FieldReadFunction, - lastSeenAt?: FieldPolicy | FieldReadFunction, linkedinProfile?: FieldPolicy | FieldReadFunction, mostRecentActivityTimestamp?: FieldPolicy | FieldReadFunction, + mostRecentConflictOfInterestStatement?: FieldPolicy | FieldReadFunction, + mostRecentEvent?: FieldPolicy | FieldReadFunction, mostRecentOrganizationId?: FieldPolicy | FieldReadFunction, name?: FieldPolicy | FieldReadFunction, + notifications?: FieldPolicy | FieldReadFunction, orcid?: FieldPolicy | FieldReadFunction, organizations?: FieldPolicy | FieldReadFunction, profileImagePath?: FieldPolicy | FieldReadFunction, + ranks?: FieldPolicy | FieldReadFunction, revisionCount?: FieldPolicy | FieldReadFunction, role?: FieldPolicy | FieldReadFunction, - signupComplete?: FieldPolicy | FieldReadFunction, + statsHash?: FieldPolicy | FieldReadFunction, twitterHandle?: FieldPolicy | FieldReadFunction, - updatedAt?: FieldPolicy | FieldReadFunction, url?: FieldPolicy | FieldReadFunction, username?: FieldPolicy | FieldReadFunction }; diff --git a/client/src/app/generated/civic.apollo.ts b/client/src/app/generated/civic.apollo.ts index b3da83f60..5d7ee11d4 100644 --- a/client/src/app/generated/civic.apollo.ts +++ b/client/src/app/generated/civic.apollo.ts @@ -588,6 +588,7 @@ export type BrowseFeature = Flaggable & { flagged: Scalars['Boolean']; /** List and filter flags. */ flags: FlagConnection; + fullName?: Maybe; id: Scalars['Int']; link: Scalars['String']; molecularProfileCount: Scalars['Int']; @@ -853,33 +854,53 @@ export type BrowseTherapyEdge = { export type BrowseUser = { __typename: 'BrowseUser'; - acceptedLicense?: Maybe; - areaOfExpertise?: Maybe; + areaOfExpertise?: Maybe; bio?: Maybe; - countryId?: Maybe; - createdAt?: Maybe; - deleted?: Maybe; - deletedAt?: Maybe; + country?: Maybe; displayName: Scalars['String']; email?: Maybe; + events: EventConnection; evidenceCount: Scalars['Int']; facebookProfile?: Maybe; id: Scalars['Int']; - lastSeenAt?: Maybe; linkedinProfile?: Maybe; mostRecentActivityTimestamp?: Maybe; + mostRecentConflictOfInterestStatement?: Maybe; + mostRecentEvent?: Maybe; mostRecentOrganizationId?: Maybe; name?: Maybe; + /** Filterable list of notifications for the logged in user. */ + notifications?: Maybe; orcid?: Maybe; organizations: Array; profileImagePath?: Maybe; + ranks: Ranks; revisionCount: Scalars['Int']; - role: Scalars['String']; - signupComplete?: Maybe; + role: UserRole; + statsHash: Stats; twitterHandle?: Maybe; - updatedAt?: Maybe; url?: Maybe; - username?: Maybe; + username: Scalars['String']; +}; + + +export type BrowseUserEventsArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; +}; + + +export type BrowseUserNotificationsArgs = { + after?: InputMaybe; + before?: InputMaybe; + eventType?: InputMaybe; + first?: InputMaybe; + includeSeen?: InputMaybe; + last?: InputMaybe; + notificationType?: InputMaybe; + subscriptionId?: InputMaybe; }; @@ -2479,6 +2500,7 @@ export enum FeaturesSortColumns { DiseaseName = 'diseaseName', EvidenceItemCount = 'evidenceItemCount', FeatureAlias = 'featureAlias', + FeatureFullName = 'featureFullName', FeatureName = 'featureName', MolecularProfileCount = 'molecularProfileCount', TherapyName = 'therapyName', @@ -4467,6 +4489,7 @@ export type QueryBrowseFeaturesArgs = { before?: InputMaybe; diseaseName?: InputMaybe; featureAlias?: InputMaybe; + featureFullName?: InputMaybe; featureName?: InputMaybe; featureType?: InputMaybe; first?: InputMaybe; @@ -7224,6 +7247,7 @@ export type FeaturePopoverFragment = { __typename: 'Feature', id: number, name: export type BrowseFeaturesQueryVariables = Exact<{ featureName?: InputMaybe; + featureFullName?: InputMaybe; therapyName?: InputMaybe; featureAlias?: InputMaybe; diseaseName?: InputMaybe; @@ -7236,9 +7260,9 @@ export type BrowseFeaturesQueryVariables = Exact<{ }>; -export type BrowseFeaturesQuery = { __typename: 'Query', browseFeatures: { __typename: 'BrowseFeatureConnection', lastUpdated: any, totalCount: number, filteredCount: number, pageCount: number, edges: Array<{ __typename: 'BrowseFeatureEdge', cursor: string, node?: { __typename: 'BrowseFeature', id: number, name: string, link: string, deprecated: boolean, flagged: boolean, featureAliases?: Array | undefined, variantCount: number, evidenceItemCount: number, assertionCount: number, molecularProfileCount: number, featureInstanceType: FeatureInstanceTypes, diseases?: Array<{ __typename: 'Disease', name: string, id: number, link: string, deprecated: boolean }> | undefined, therapies?: Array<{ __typename: 'Therapy', name: string, id: number, link: string, deprecated: boolean }> | undefined } | undefined }>, pageInfo: { __typename: 'PageInfo', startCursor?: string | undefined, endCursor?: string | undefined, hasPreviousPage: boolean, hasNextPage: boolean } } }; +export type BrowseFeaturesQuery = { __typename: 'Query', browseFeatures: { __typename: 'BrowseFeatureConnection', lastUpdated: any, totalCount: number, filteredCount: number, pageCount: number, edges: Array<{ __typename: 'BrowseFeatureEdge', cursor: string, node?: { __typename: 'BrowseFeature', id: number, name: string, fullName?: string | undefined, link: string, deprecated: boolean, flagged: boolean, featureAliases?: Array | undefined, variantCount: number, evidenceItemCount: number, assertionCount: number, molecularProfileCount: number, featureInstanceType: FeatureInstanceTypes, diseases?: Array<{ __typename: 'Disease', name: string, id: number, link: string, deprecated: boolean }> | undefined, therapies?: Array<{ __typename: 'Therapy', name: string, id: number, link: string, deprecated: boolean }> | undefined } | undefined }>, pageInfo: { __typename: 'PageInfo', startCursor?: string | undefined, endCursor?: string | undefined, hasPreviousPage: boolean, hasNextPage: boolean } } }; -export type BrowseFeaturesFieldsFragment = { __typename: 'BrowseFeature', id: number, name: string, link: string, deprecated: boolean, flagged: boolean, featureAliases?: Array | undefined, variantCount: number, evidenceItemCount: number, assertionCount: number, molecularProfileCount: number, featureInstanceType: FeatureInstanceTypes, diseases?: Array<{ __typename: 'Disease', name: string, id: number, link: string, deprecated: boolean }> | undefined, therapies?: Array<{ __typename: 'Therapy', name: string, id: number, link: string, deprecated: boolean }> | undefined }; +export type BrowseFeaturesFieldsFragment = { __typename: 'BrowseFeature', id: number, name: string, fullName?: string | undefined, link: string, deprecated: boolean, flagged: boolean, featureAliases?: Array | undefined, variantCount: number, evidenceItemCount: number, assertionCount: number, molecularProfileCount: number, featureInstanceType: FeatureInstanceTypes, diseases?: Array<{ __typename: 'Disease', name: string, id: number, link: string, deprecated: boolean }> | undefined, therapies?: Array<{ __typename: 'Therapy', name: string, id: number, link: string, deprecated: boolean }> | undefined }; export type FlagListQueryVariables = Exact<{ flaggable?: InputMaybe; @@ -7654,9 +7678,9 @@ export type UsersBrowseQueryVariables = Exact<{ }>; -export type UsersBrowseQuery = { __typename: 'Query', users: { __typename: 'BrowseUserConnection', totalCount: number, pageInfo: { __typename: 'PageInfo', endCursor?: string | undefined, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | undefined }, edges: Array<{ __typename: 'BrowseUserEdge', cursor: string, node?: { __typename: 'BrowseUser', id: number, name?: string | undefined, displayName: string, username?: string | undefined, role: string, evidenceCount: number, revisionCount: number, profileImagePath?: string | undefined, mostRecentActivityTimestamp?: any | undefined, organizations: Array<{ __typename: 'Organization', id: number, name: string }> } | undefined }> } }; +export type UsersBrowseQuery = { __typename: 'Query', users: { __typename: 'BrowseUserConnection', totalCount: number, pageInfo: { __typename: 'PageInfo', endCursor?: string | undefined, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | undefined }, edges: Array<{ __typename: 'BrowseUserEdge', cursor: string, node?: { __typename: 'BrowseUser', id: number, name?: string | undefined, displayName: string, username: string, role: UserRole, evidenceCount: number, revisionCount: number, profileImagePath?: string | undefined, mostRecentActivityTimestamp?: any | undefined, organizations: Array<{ __typename: 'Organization', id: number, name: string }> } | undefined }> } }; -export type UserBrowseTableRowFieldsFragment = { __typename: 'BrowseUser', id: number, name?: string | undefined, displayName: string, username?: string | undefined, role: string, evidenceCount: number, revisionCount: number, profileImagePath?: string | undefined, mostRecentActivityTimestamp?: any | undefined, organizations: Array<{ __typename: 'Organization', id: number, name: string }> }; +export type UserBrowseTableRowFieldsFragment = { __typename: 'BrowseUser', id: number, name?: string | undefined, displayName: string, username: string, role: UserRole, evidenceCount: number, revisionCount: number, profileImagePath?: string | undefined, mostRecentActivityTimestamp?: any | undefined, organizations: Array<{ __typename: 'Organization', id: number, name: string }> }; export type VariantGroupPopoverQueryVariables = Exact<{ variantGroupId: Scalars['Int']; @@ -8652,9 +8676,9 @@ export type OrganizationMembersQueryVariables = Exact<{ }>; -export type OrganizationMembersQuery = { __typename: 'Query', users: { __typename: 'BrowseUserConnection', pageInfo: { __typename: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | undefined, endCursor?: string | undefined }, edges: Array<{ __typename: 'BrowseUserEdge', cursor: string, node?: { __typename: 'BrowseUser', id: number, name?: string | undefined, displayName: string, username?: string | undefined, profileImagePath?: string | undefined, role: string, url?: string | undefined, areaOfExpertise?: string | undefined, orcid?: string | undefined, twitterHandle?: string | undefined, facebookProfile?: string | undefined, linkedinProfile?: string | undefined, organizations: Array<{ __typename: 'Organization', id: number, name: string, url: string }> } | undefined }> } }; +export type OrganizationMembersQuery = { __typename: 'Query', users: { __typename: 'BrowseUserConnection', pageInfo: { __typename: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | undefined, endCursor?: string | undefined }, edges: Array<{ __typename: 'BrowseUserEdge', cursor: string, node?: { __typename: 'BrowseUser', id: number, name?: string | undefined, displayName: string, username: string, profileImagePath?: string | undefined, role: UserRole, url?: string | undefined, areaOfExpertise?: AreaOfExpertise | undefined, orcid?: string | undefined, twitterHandle?: string | undefined, facebookProfile?: string | undefined, linkedinProfile?: string | undefined, organizations: Array<{ __typename: 'Organization', id: number, name: string, url: string }> } | undefined }> } }; -export type OrganizationMembersFieldsFragment = { __typename: 'BrowseUser', id: number, name?: string | undefined, displayName: string, username?: string | undefined, profileImagePath?: string | undefined, role: string, url?: string | undefined, areaOfExpertise?: string | undefined, orcid?: string | undefined, twitterHandle?: string | undefined, facebookProfile?: string | undefined, linkedinProfile?: string | undefined, organizations: Array<{ __typename: 'Organization', id: number, name: string, url: string }> }; +export type OrganizationMembersFieldsFragment = { __typename: 'BrowseUser', id: number, name?: string | undefined, displayName: string, username: string, profileImagePath?: string | undefined, role: UserRole, url?: string | undefined, areaOfExpertise?: AreaOfExpertise | undefined, orcid?: string | undefined, twitterHandle?: string | undefined, facebookProfile?: string | undefined, linkedinProfile?: string | undefined, organizations: Array<{ __typename: 'Organization', id: number, name: string, url: string }> }; export type PhenotypeDetailQueryVariables = Exact<{ phenotypeId: Scalars['Int']; @@ -9457,6 +9481,7 @@ export const BrowseFeaturesFieldsFragmentDoc = gql` fragment BrowseFeaturesFields on BrowseFeature { id name + fullName link deprecated flagged @@ -12394,9 +12419,10 @@ export const FeaturePopoverDocument = gql` } } export const BrowseFeaturesDocument = gql` - query BrowseFeatures($featureName: String, $therapyName: String, $featureAlias: String, $diseaseName: String, $featureType: FeatureInstanceTypes, $sortBy: FeaturesSort, $first: Int, $last: Int, $before: String, $after: String) { + query BrowseFeatures($featureName: String, $featureFullName: String, $therapyName: String, $featureAlias: String, $diseaseName: String, $featureType: FeatureInstanceTypes, $sortBy: FeaturesSort, $first: Int, $last: Int, $before: String, $after: String) { browseFeatures( featureName: $featureName + featureFullName: $featureFullName therapyName: $therapyName featureAlias: $featureAlias diseaseName: $diseaseName diff --git a/client/src/app/generated/server.model.graphql b/client/src/app/generated/server.model.graphql index b2ac1ba3b..7efeff579 100644 --- a/client/src/app/generated/server.model.graphql +++ b/client/src/app/generated/server.model.graphql @@ -990,6 +990,7 @@ type BrowseFeature implements Flaggable { """ state: FlagState ): FlagConnection! + fullName: String id: Int! link: String! molecularProfileCount: Int! @@ -4185,6 +4186,7 @@ enum FeaturesSortColumns { diseaseName evidenceItemCount featureAlias + featureFullName featureName molecularProfileCount therapyName @@ -7296,6 +7298,7 @@ type Query { before: String diseaseName: String featureAlias: String + featureFullName: String featureName: String featureType: FeatureInstanceTypes diff --git a/client/src/app/generated/server.schema.json b/client/src/app/generated/server.schema.json index de75f5765..63c2d0a79 100644 --- a/client/src/app/generated/server.schema.json +++ b/client/src/app/generated/server.schema.json @@ -4565,6 +4565,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "fullName", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "id", "description": null, @@ -20225,6 +20237,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "featureFullName", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "therapyName", "description": null, @@ -34347,6 +34365,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "featureFullName", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "featureAlias", "description": null, diff --git a/server/app/graphql/resolvers/browse_features.rb b/server/app/graphql/resolvers/browse_features.rb index 036a4b9d9..6483e78e4 100644 --- a/server/app/graphql/resolvers/browse_features.rb +++ b/server/app/graphql/resolvers/browse_features.rb @@ -10,6 +10,7 @@ class Resolvers::BrowseFeatures < GraphQL::Schema::Resolver scope { MaterializedViews::FeatureBrowseTableRow.all } option(:feature_name, type: String) { |scope, value| scope.where("name ILIKE ?", "#{value}%") } + option(:feature_full_name, type: String) { |scope, value| scope.where("full_name ILIKE ?", "#{value}%") } option(:feature_alias, type: String) { |scope, value| scope.where(array_query_for_column('alias_names'), "#{value}%") } option(:disease_name, type: String) { |scope, value| scope.where(json_name_query_for_column('diseases'), "%#{value}%") } option(:therapy_name, type: String) { |scope, value| scope.where(json_name_query_for_column('therapies'), "%#{value}%") } @@ -25,6 +26,8 @@ class Resolvers::BrowseFeatures < GraphQL::Schema::Resolver case value.column when "featureName" scope.order "feature_browse_table_rows.name #{value.direction}" + when "featureFullName" + scope.order "feature_browse_table_rows.full_name #{value.direction}" when "therapyName" scope.order "drug_names #{value.direction}" when "geneAlias" diff --git a/server/app/graphql/types/browse_tables/browse_feature_type.rb b/server/app/graphql/types/browse_tables/browse_feature_type.rb index 7b475f31b..9fa5c7c82 100644 --- a/server/app/graphql/types/browse_tables/browse_feature_type.rb +++ b/server/app/graphql/types/browse_tables/browse_feature_type.rb @@ -5,6 +5,7 @@ class BrowseFeatureType < Types::BaseObject field :id, Int, null: false field :name, String, null: false + field :full_name, String, null: true field :link, String, null: false field :deprecated, Boolean, null: false field :description, String, null: false diff --git a/server/app/graphql/types/browse_tables/features_sort_columns.rb b/server/app/graphql/types/browse_tables/features_sort_columns.rb index 7c6d12247..b5901822a 100644 --- a/server/app/graphql/types/browse_tables/features_sort_columns.rb +++ b/server/app/graphql/types/browse_tables/features_sort_columns.rb @@ -1,6 +1,7 @@ module Types::BrowseTables class FeaturesSortColumns < Types::BaseEnum value "featureName" + value "featureFullName" value "therapyName" value "featureAlias" value "diseaseName" diff --git a/server/db/migrate/20240726163525_update_feature_browse_table_rows_to_version_6.rb b/server/db/migrate/20240726163525_update_feature_browse_table_rows_to_version_6.rb new file mode 100644 index 000000000..548466c2c --- /dev/null +++ b/server/db/migrate/20240726163525_update_feature_browse_table_rows_to_version_6.rb @@ -0,0 +1,8 @@ +class UpdateFeatureBrowseTableRowsToVersion6 < ActiveRecord::Migration[7.1] + def change + update_view :feature_browse_table_rows, + version: 6, + revert_to_version: 5, + materialized: true + end +end diff --git a/server/db/schema.rb b/server/db/schema.rb index 91dee13f6..80ac9eac9 100644 --- a/server/db/schema.rb +++ b/server/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_07_25_165912) do +ActiveRecord::Schema[7.1].define(version: 2024_07_26_163525) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -446,6 +446,29 @@ t.index ["therapy_id", "evidence_item_id"], name: "idx_therapy_eid_bridge_table" end + create_table "exon_coordinates", force: :cascade do |t| + t.text "chromosome", null: false + t.enum "strand", null: false, enum_type: "exon_offset_direction" + t.bigint "start", null: false + t.bigint "stop", null: false + t.integer "exon", null: false + t.text "ensembl_id", null: false + t.integer "exon_offset" + t.enum "exon_offset_direction", enum_type: "exon_offset_direction" + t.integer "ensembl_version", null: false + t.text "representative_transcript", null: false + t.integer "reference_build" + t.bigint "variant_id", null: false + t.text "coordinate_type", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["chromosome"], name: "index_exon_coordinates_on_chromosome" + t.index ["representative_transcript"], name: "index_exon_coordinates_on_representative_transcript" + t.index ["start"], name: "index_exon_coordinates_on_start" + t.index ["stop"], name: "index_exon_coordinates_on_stop" + t.index ["variant_id"], name: "index_exon_coordinates_on_variant_id" + end + create_table "factors", force: :cascade do |t| t.text "ncit_id" t.datetime "created_at", null: false @@ -889,8 +912,6 @@ t.bigint "stop" t.text "reference_bases" t.text "variant_bases" - t.integer "exon_boundary" - t.integer "exon_offset" t.integer "ensembl_version" t.text "representative_transcript" t.integer "reference_build" @@ -898,7 +919,6 @@ t.text "coordinate_type", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.enum "exon_offset_direction", enum_type: "exon_offset_direction" t.index ["chromosome"], name: "index_variant_coordinates_on_chromosome" t.index ["reference_build"], name: "index_variant_coordinates_on_reference_build" t.index ["representative_transcript"], name: "index_variant_coordinates_on_representative_transcript" @@ -1045,6 +1065,7 @@ add_foreign_key "evidence_items_phenotypes", "phenotypes" add_foreign_key "evidence_items_therapies", "evidence_items" add_foreign_key "evidence_items_therapies", "therapies" + add_foreign_key "exon_coordinates", "variants" add_foreign_key "feature_aliases_features", "feature_aliases" add_foreign_key "feature_aliases_features", "features" add_foreign_key "features_sources", "features" @@ -1300,55 +1321,6 @@ SQL add_index "molecular_profile_browse_table_rows", ["id"], name: "index_molecular_profile_browse_table_rows_on_id", unique: true - create_view "feature_browse_table_rows", materialized: true, sql_definition: <<-SQL - SELECT outer_features.id, - outer_features.name, - outer_features.flagged, - outer_features.deprecated, - outer_features.feature_instance_type, - outer_features.feature_instance_id, - array_agg(DISTINCT feature_aliases.name ORDER BY feature_aliases.name) AS alias_names, - json_agg(DISTINCT jsonb_build_object('name', diseases.name, 'id', diseases.id, 'deprecated', diseases.deprecated, 'total', disease_count.total)) FILTER (WHERE (diseases.name IS NOT NULL)) AS diseases, - json_agg(DISTINCT jsonb_build_object('name', therapies.name, 'id', therapies.id, 'deprecated', therapies.deprecated, 'total', therapy_count.total)) FILTER (WHERE (therapies.name IS NOT NULL)) AS therapies, - count(DISTINCT variants.id) AS variant_count, - count(DISTINCT evidence_items.id) AS evidence_item_count, - count(DISTINCT assertions.id) AS assertion_count, - count(DISTINCT molecular_profiles.id) AS molecular_profile_count - FROM ((((((((((((features outer_features - LEFT JOIN feature_aliases_features ON ((feature_aliases_features.feature_id = outer_features.id))) - LEFT JOIN feature_aliases ON ((feature_aliases.id = feature_aliases_features.feature_alias_id))) - JOIN variants ON ((variants.feature_id = outer_features.id))) - JOIN molecular_profiles_variants ON ((molecular_profiles_variants.variant_id = variants.id))) - JOIN molecular_profiles ON ((molecular_profiles.id = molecular_profiles_variants.molecular_profile_id))) - LEFT JOIN evidence_items ON ((evidence_items.molecular_profile_id = molecular_profiles.id))) - LEFT JOIN diseases ON ((diseases.id = evidence_items.disease_id))) - LEFT JOIN evidence_items_therapies ON ((evidence_items_therapies.evidence_item_id = evidence_items.id))) - LEFT JOIN therapies ON ((therapies.id = evidence_items_therapies.therapy_id))) - LEFT JOIN assertions ON ((assertions.molecular_profile_id = molecular_profiles.id))) - LEFT JOIN LATERAL ( SELECT therapies_1.id AS therapy_id, - count(DISTINCT evidence_items_1.id) AS total - FROM (((((evidence_items evidence_items_1 - LEFT JOIN molecular_profiles molecular_profiles_1 ON ((molecular_profiles_1.id = evidence_items_1.molecular_profile_id))) - LEFT JOIN molecular_profiles_variants molecular_profiles_variants_1 ON ((molecular_profiles_variants_1.molecular_profile_id = molecular_profiles_1.id))) - LEFT JOIN variants variants_1 ON ((variants_1.id = molecular_profiles_variants_1.variant_id))) - LEFT JOIN evidence_items_therapies evidence_items_therapies_1 ON ((evidence_items_therapies_1.evidence_item_id = evidence_items_1.id))) - LEFT JOIN therapies therapies_1 ON ((therapies_1.id = evidence_items_therapies_1.therapy_id))) - WHERE ((variants_1.feature_id = outer_features.id) AND (molecular_profiles_1.id IS NOT NULL)) - GROUP BY therapies_1.id) therapy_count ON ((therapies.id = therapy_count.therapy_id))) - LEFT JOIN LATERAL ( SELECT diseases_1.id AS disease_id, - count(DISTINCT evidence_items_1.id) AS total - FROM ((((evidence_items evidence_items_1 - LEFT JOIN molecular_profiles molecular_profiles_1 ON ((molecular_profiles_1.id = evidence_items_1.molecular_profile_id))) - LEFT JOIN molecular_profiles_variants molecular_profiles_variants_1 ON ((molecular_profiles_variants_1.molecular_profile_id = molecular_profiles_1.id))) - LEFT JOIN variants variants_1 ON ((variants_1.id = molecular_profiles_variants_1.variant_id))) - LEFT JOIN diseases diseases_1 ON ((diseases_1.id = evidence_items_1.disease_id))) - WHERE ((variants_1.feature_id = outer_features.id) AND (molecular_profiles_1.id IS NOT NULL)) - GROUP BY diseases_1.id) disease_count ON ((diseases.id = disease_count.disease_id))) - WHERE (((evidence_items.status)::text <> 'rejected'::text) OR ((evidence_items.status IS NULL) AND (molecular_profiles.deprecated = false) AND (variants.deprecated = false))) - GROUP BY outer_features.id, outer_features.name; - SQL - add_index "feature_browse_table_rows", ["id"], name: "index_feature_browse_table_rows_on_id", unique: true - create_view "variant_browse_table_rows", materialized: true, sql_definition: <<-SQL SELECT outer_variants.id, outer_variants.name, @@ -1454,4 +1426,54 @@ SQL add_index "user_browse_table_rows", ["id"], name: "index_user_browse_table_rows_on_id", unique: true + create_view "feature_browse_table_rows", materialized: true, sql_definition: <<-SQL + SELECT outer_features.id, + outer_features.name, + outer_features.flagged, + outer_features.deprecated, + outer_features.feature_instance_type, + outer_features.feature_instance_id, + outer_features.full_name, + array_agg(DISTINCT feature_aliases.name ORDER BY feature_aliases.name) AS alias_names, + json_agg(DISTINCT jsonb_build_object('name', diseases.name, 'id', diseases.id, 'deprecated', diseases.deprecated, 'total', disease_count.total)) FILTER (WHERE (diseases.name IS NOT NULL)) AS diseases, + json_agg(DISTINCT jsonb_build_object('name', therapies.name, 'id', therapies.id, 'deprecated', therapies.deprecated, 'total', therapy_count.total)) FILTER (WHERE (therapies.name IS NOT NULL)) AS therapies, + count(DISTINCT variants.id) AS variant_count, + count(DISTINCT evidence_items.id) AS evidence_item_count, + count(DISTINCT assertions.id) AS assertion_count, + count(DISTINCT molecular_profiles.id) AS molecular_profile_count + FROM ((((((((((((features outer_features + LEFT JOIN feature_aliases_features ON ((feature_aliases_features.feature_id = outer_features.id))) + LEFT JOIN feature_aliases ON ((feature_aliases.id = feature_aliases_features.feature_alias_id))) + JOIN variants ON ((variants.feature_id = outer_features.id))) + JOIN molecular_profiles_variants ON ((molecular_profiles_variants.variant_id = variants.id))) + JOIN molecular_profiles ON ((molecular_profiles.id = molecular_profiles_variants.molecular_profile_id))) + LEFT JOIN evidence_items ON ((evidence_items.molecular_profile_id = molecular_profiles.id))) + LEFT JOIN diseases ON ((diseases.id = evidence_items.disease_id))) + LEFT JOIN evidence_items_therapies ON ((evidence_items_therapies.evidence_item_id = evidence_items.id))) + LEFT JOIN therapies ON ((therapies.id = evidence_items_therapies.therapy_id))) + LEFT JOIN assertions ON ((assertions.molecular_profile_id = molecular_profiles.id))) + LEFT JOIN LATERAL ( SELECT therapies_1.id AS therapy_id, + count(DISTINCT evidence_items_1.id) AS total + FROM (((((evidence_items evidence_items_1 + LEFT JOIN molecular_profiles molecular_profiles_1 ON ((molecular_profiles_1.id = evidence_items_1.molecular_profile_id))) + LEFT JOIN molecular_profiles_variants molecular_profiles_variants_1 ON ((molecular_profiles_variants_1.molecular_profile_id = molecular_profiles_1.id))) + LEFT JOIN variants variants_1 ON ((variants_1.id = molecular_profiles_variants_1.variant_id))) + LEFT JOIN evidence_items_therapies evidence_items_therapies_1 ON ((evidence_items_therapies_1.evidence_item_id = evidence_items_1.id))) + LEFT JOIN therapies therapies_1 ON ((therapies_1.id = evidence_items_therapies_1.therapy_id))) + WHERE ((variants_1.feature_id = outer_features.id) AND (molecular_profiles_1.id IS NOT NULL)) + GROUP BY therapies_1.id) therapy_count ON ((therapies.id = therapy_count.therapy_id))) + LEFT JOIN LATERAL ( SELECT diseases_1.id AS disease_id, + count(DISTINCT evidence_items_1.id) AS total + FROM ((((evidence_items evidence_items_1 + LEFT JOIN molecular_profiles molecular_profiles_1 ON ((molecular_profiles_1.id = evidence_items_1.molecular_profile_id))) + LEFT JOIN molecular_profiles_variants molecular_profiles_variants_1 ON ((molecular_profiles_variants_1.molecular_profile_id = molecular_profiles_1.id))) + LEFT JOIN variants variants_1 ON ((variants_1.id = molecular_profiles_variants_1.variant_id))) + LEFT JOIN diseases diseases_1 ON ((diseases_1.id = evidence_items_1.disease_id))) + WHERE ((variants_1.feature_id = outer_features.id) AND (molecular_profiles_1.id IS NOT NULL)) + GROUP BY diseases_1.id) disease_count ON ((diseases.id = disease_count.disease_id))) + WHERE (((evidence_items.status)::text <> 'rejected'::text) OR ((evidence_items.status IS NULL) AND (molecular_profiles.deprecated = false) AND (variants.deprecated = false))) + GROUP BY outer_features.id, outer_features.name; + SQL + add_index "feature_browse_table_rows", ["id"], name: "index_feature_browse_table_rows_on_id", unique: true + end diff --git a/server/db/views/feature_browse_table_rows_v06.sql b/server/db/views/feature_browse_table_rows_v06.sql new file mode 100644 index 000000000..106b97155 --- /dev/null +++ b/server/db/views/feature_browse_table_rows_v06.sql @@ -0,0 +1,49 @@ +SELECT outer_features.id, + outer_features.name, + outer_features.flagged, + outer_features.deprecated, + outer_features.feature_instance_type, + outer_features.feature_instance_id, + outer_features.full_name, + array_agg(distinct(feature_aliases.name) order by feature_aliases.name) as alias_names, + json_agg(distinct jsonb_build_object('name', diseases.name, 'id', diseases.id, 'deprecated', diseases.deprecated, 'total', disease_count.total)) FILTER (WHERE diseases.name IS NOT NULL) as diseases, + json_agg(distinct jsonb_build_object('name', therapies.name, 'id', therapies.id, 'deprecated', therapies.deprecated, 'total', therapy_count.total)) FILTER (WHERE therapies.name IS NOT NULL) as therapies, + count(distinct(variants.id)) as variant_count, + count(distinct(evidence_items.id)) as evidence_item_count, + count(distinct(assertions.id)) as assertion_count, + count(distinct(molecular_profiles.id)) as molecular_profile_count +FROM features outer_features +LEFT OUTER JOIN feature_aliases_features ON feature_aliases_features.feature_id = outer_features.id +LEFT OUTER JOIN feature_aliases ON feature_aliases.id = feature_aliases_features.feature_alias_id +INNER JOIN variants ON variants.feature_id = outer_features.id +INNER JOIN molecular_profiles_variants ON molecular_profiles_variants.variant_id = variants.id +INNER JOIN molecular_profiles ON molecular_profiles.id = molecular_profiles_variants.molecular_profile_id +LEFT OUTER JOIN evidence_items ON evidence_items.molecular_profile_id = molecular_profiles.id +LEFT OUTER JOIN diseases ON diseases.id = evidence_items.disease_id +LEFT OUTER JOIN evidence_items_therapies ON evidence_items_therapies.evidence_item_id = evidence_items.id +LEFT OUTER JOIN therapies ON therapies.id = evidence_items_therapies.therapy_id +LEFT OUTER JOIN assertions on assertions.molecular_profile_id = molecular_profiles.id +LEFT JOIN LATERAL (SELECT therapies.id as therapy_id, COUNT(DISTINCT(evidence_items.id)) as total + FROM evidence_items + LEFT OUTER JOIN molecular_profiles ON molecular_profiles.id = evidence_items.molecular_profile_id + LEFT OUTER JOIN molecular_profiles_variants ON molecular_profiles_variants.molecular_profile_id = molecular_profiles.id + LEFT OUTER JOIN variants ON variants.id = molecular_profiles_variants.variant_id + LEFT OUTER JOIN evidence_items_therapies ON evidence_items_therapies.evidence_item_id = evidence_items.id + LEFT OUTER JOIN therapies ON therapies.id = evidence_items_therapies.therapy_id + WHERE variants.feature_id = outer_features.id AND molecular_profiles.id IS NOT NULL + GROUP BY therapies.id +) therapy_count on therapies.id = therapy_count.therapy_id + +LEFT JOIN LATERAL (SELECT diseases.id as disease_id, COUNT(DISTINCT(evidence_items.id)) as total + FROM evidence_items + LEFT OUTER JOIN molecular_profiles ON molecular_profiles.id = evidence_items.molecular_profile_id + LEFT OUTER JOIN molecular_profiles_variants ON molecular_profiles_variants.molecular_profile_id = molecular_profiles.id + LEFT OUTER JOIN variants ON variants.id = molecular_profiles_variants.variant_id + LEFT OUTER JOIN diseases ON diseases.id = evidence_items.disease_id + WHERE variants.feature_id = outer_features.id AND molecular_profiles.id IS NOT NULL + GROUP BY diseases.id +) disease_count on diseases.id = disease_count.disease_id +WHERE evidence_items.status != 'rejected' OR evidence_items.status IS NULL + AND molecular_profiles.deprecated = 'f' + AND variants.deprecated = 'f' +GROUP BY outer_features.id, outer_features.name; From e46e4e21d294ffa8f359b76d94398e22230ae5fe Mon Sep 17 00:00:00 2001 From: Adam Coffman Date: Fri, 26 Jul 2024 12:25:42 -0500 Subject: [PATCH 2/2] include full name in elasticsearch index for factors --- server/app/models/feature.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/app/models/feature.rb b/server/app/models/feature.rb index 4a026ac1f..30859da03 100644 --- a/server/app/models/feature.rb +++ b/server/app/models/feature.rb @@ -29,9 +29,14 @@ class Feature < ApplicationRecord # validates :name, uniqueness: { scope: :feature_instance_type } def search_data + aliases = feature_aliases.map(&:name) + if feature_instance.is_a?(Features::Factor) + aliases << self.full_name + end + { name: name, - aliases: feature_aliases.map(&:name), + aliases: aliases, feature_type: feature_instance_type.demodulize } end