From 2f4cb2b7a79df72053a9732b210134fcd1366acf Mon Sep 17 00:00:00 2001 From: Adam Coffman Date: Wed, 21 Aug 2024 15:25:23 -0500 Subject: [PATCH 1/5] use table aliases in order to allow filtering on _id and _name at the same time for therapies and diseases --- server/app/graphql/resolvers/top_level_assertions.rb | 7 +++++-- server/app/graphql/resolvers/top_level_evidence_items.rb | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/server/app/graphql/resolvers/top_level_assertions.rb b/server/app/graphql/resolvers/top_level_assertions.rb index 28b2a92ed..41e22480d 100644 --- a/server/app/graphql/resolvers/top_level_assertions.rb +++ b/server/app/graphql/resolvers/top_level_assertions.rb @@ -40,10 +40,13 @@ def generate_select(field = nil) scope.joins(:submission_event).where('events.originating_user_id = ?', value) end option(:disease_name, type: GraphQL::Types::String, description: 'Substring filtering on disease name.') do |scope, value| - scope.joins(:disease).where('diseases.name ILIKE ?', "%#{value}%") + scope.joins('INNER JOIN diseases AS disease_names ON assertions.disease_id = disease_names.id ') + .where('disease_names.name ILIKE ?', "%#{value}%") end option(:therapy_name, type: GraphQL::Types::String, description: 'Substring filtering on therapy name.') do |scope, value| - scope.joins(:therapies).where('therapies.name ILIKE ?', "%#{value}%") + scope.joins("INNER JOIN assertions_therapies AS at_names on at_names.assertion_id = assertions.id") + .joins("INNER JOIN therapies AS therapy_names ON therapy_names.id = at_names.therapy_id") + .where('therapy_names.name ILIKE ?', "%#{value}%") end option(:molecular_profile_name, type: GraphQL::Types::String, description: 'Substring filtering on molecular profile name') do |scope, value| results = Searchkick.search( diff --git a/server/app/graphql/resolvers/top_level_evidence_items.rb b/server/app/graphql/resolvers/top_level_evidence_items.rb index ed0bc1083..0c6f49c0d 100644 --- a/server/app/graphql/resolvers/top_level_evidence_items.rb +++ b/server/app/graphql/resolvers/top_level_evidence_items.rb @@ -41,10 +41,13 @@ def generate_select(field = nil) scope.joins(:submission_event).where('events.originating_user_id = ?', value) end option(:disease_name, type: GraphQL::Types::String, description: 'Substring filtering on disease name.') do |scope, value| - scope.joins(:disease).where('diseases.name ILIKE ?', "%#{value}%") + scope.joins('INNER JOIN diseases AS disease_names ON evidence_items.disease_id = disease_names.id ') + .where('disease_names.name ILIKE ?', "%#{value}%") end option(:therapy_name, type: GraphQL::Types::String, description: 'Substring filtering on therapy name.') do |scope, value| - scope.joins(:therapies).where('therapies.name ILIKE ?', "%#{value}%") + scope.joins("INNER JOIN evidence_items_therapies AS eit_names on eit_names.evidence_item_id = evidence_items.id") + .joins("INNER JOIN therapies AS therapy_names ON therapy_names.id = eit_names.therapy_id") + .where('therapy_names.name ILIKE ?', "%#{value}%") end option(:description, type: GraphQL::Types::String, description: 'Substring filtering on evidence item description.') do |scope, value| scope.where("evidence_items.description ILIKE ?", "%#{value}%") From 4d2fe6a55052f0414e3cef2a4e865a765a7bd8bd Mon Sep 17 00:00:00 2001 From: Adam Coffman Date: Wed, 21 Aug 2024 16:17:54 -0500 Subject: [PATCH 2/5] port therapy browse to use materialized view, add aliases to therapy and disease browse --- .../graphql/resolvers/top_level_therapies.rb | 10 +- .../browse_tables/browse_disease_type.rb | 5 + .../browse_tables/browse_therapy_type.rb | 9 ++ server/app/jobs/refresh_materialized_views.rb | 2 + ..._disease_browse_table_rows_to_version_8.rb | 8 ++ ...202933_create_therapy_browse_table_rows.rb | 5 + server/db/schema.rb | 106 +++++++++++------- .../views/disease_browse_table_rows_v08.sql | 24 ++++ .../views/therapy_browse_table_rows_v01.sql | 19 ++++ 9 files changed, 140 insertions(+), 48 deletions(-) create mode 100644 server/db/migrate/20240821202632_update_disease_browse_table_rows_to_version_8.rb create mode 100644 server/db/migrate/20240821202933_create_therapy_browse_table_rows.rb create mode 100644 server/db/views/disease_browse_table_rows_v08.sql create mode 100644 server/db/views/therapy_browse_table_rows_v01.sql diff --git a/server/app/graphql/resolvers/top_level_therapies.rb b/server/app/graphql/resolvers/top_level_therapies.rb index adc4324a5..b3368c21f 100644 --- a/server/app/graphql/resolvers/top_level_therapies.rb +++ b/server/app/graphql/resolvers/top_level_therapies.rb @@ -8,15 +8,7 @@ class Resolvers::TopLevelTherapies < GraphQL::Schema::Resolver description 'List and filter Therapies from the NCI Thesaurus.' - scope do - Therapy.select('therapies.id, therapies.name, therapies.deprecated, max(therapies.ncit_id) as ncit_id, count(distinct(assertions.id)) as assertion_count, count(distinct(evidence_items.id)) as evidence_count') - .left_outer_joins(:assertions, :evidence_items) - .where("evidence_items.status != 'rejected' OR assertions.status != 'rejected'") - .where(deprecated: false) - .group('therapies.id, therapies.name, therapies.deprecated') - .having('COUNT(evidence_items.id) > 0 OR COUNT(assertions.id) > 0') - .order('evidence_count DESC', :id) - end + scope { MaterializedViews::TherapyBrowseTableRow.all } option(:ncit_id, type: String, description: 'Limit to therapies with a specific NCIT ID') do |scope, value| if value.upcase.starts_with?('C') diff --git a/server/app/graphql/types/browse_tables/browse_disease_type.rb b/server/app/graphql/types/browse_tables/browse_disease_type.rb index 4d8cdb15d..ebe935790 100644 --- a/server/app/graphql/types/browse_tables/browse_disease_type.rb +++ b/server/app/graphql/types/browse_tables/browse_disease_type.rb @@ -17,6 +17,7 @@ class BrowseDiseaseType < Types::BaseObject field :feature_count, Int, null: false field :link, String, null: false field :deprecated, Boolean, null: false + field :disease_aliases, [String], null: true def features Array(object.features) @@ -24,6 +25,10 @@ def features .map { |f| { name: f['name'], id: f['id'], link: "/features/#{f['id']}" } } end + def disease_aliases + object.alias_names.compact + end + def link Rails.application.routes.url_helpers.url_for("/diseases/#{object.id}") end diff --git a/server/app/graphql/types/browse_tables/browse_therapy_type.rb b/server/app/graphql/types/browse_tables/browse_therapy_type.rb index f3f448bdd..a3898c7a1 100644 --- a/server/app/graphql/types/browse_tables/browse_therapy_type.rb +++ b/server/app/graphql/types/browse_tables/browse_therapy_type.rb @@ -10,9 +10,18 @@ class BrowseTherapyType < Types::BaseObject field :therapy_url, String, null: true field :link, String, null: false field :deprecated, Boolean, null: false + field :therapy_aliases, [String], null: true def therapy_url Therapy.url_for(ncit_id: object.ncit_id) end + + def therapy_aliases + object.alias_names.compact + end + + def link + Rails.application.routes.url_helpers.url_for("/therapies/#{object.id}") + end end end diff --git a/server/app/jobs/refresh_materialized_views.rb b/server/app/jobs/refresh_materialized_views.rb index eedef17e3..fbb80449a 100644 --- a/server/app/jobs/refresh_materialized_views.rb +++ b/server/app/jobs/refresh_materialized_views.rb @@ -5,6 +5,7 @@ def perform(kwargs) to_refresh = if views == 'all' [ MaterializedViews::DiseaseBrowseTableRow, + MaterializedViews::TherapyBrowseTableRow, MaterializedViews::FeatureBrowseTableRow, MaterializedViews::SourceBrowseTableRow, MaterializedViews::VariantBrowseTableRow, @@ -20,6 +21,7 @@ def perform(kwargs) elsif views == 'except_features' [ MaterializedViews::DiseaseBrowseTableRow, + MaterializedViews::TherapyBrowseTableRow, MaterializedViews::SourceBrowseTableRow, MaterializedViews::VariantBrowseTableRow, MaterializedViews::VariantGroupBrowseTableRow, diff --git a/server/db/migrate/20240821202632_update_disease_browse_table_rows_to_version_8.rb b/server/db/migrate/20240821202632_update_disease_browse_table_rows_to_version_8.rb new file mode 100644 index 000000000..f66b24150 --- /dev/null +++ b/server/db/migrate/20240821202632_update_disease_browse_table_rows_to_version_8.rb @@ -0,0 +1,8 @@ +class UpdateDiseaseBrowseTableRowsToVersion8 < ActiveRecord::Migration[7.1] + def change + update_view :disease_browse_table_rows, + version: 8, + revert_to_version: 7, + materialized: true + end +end diff --git a/server/db/migrate/20240821202933_create_therapy_browse_table_rows.rb b/server/db/migrate/20240821202933_create_therapy_browse_table_rows.rb new file mode 100644 index 000000000..761469a52 --- /dev/null +++ b/server/db/migrate/20240821202933_create_therapy_browse_table_rows.rb @@ -0,0 +1,5 @@ +class CreateTherapyBrowseTableRows < ActiveRecord::Migration[7.1] + def change + create_view :therapy_browse_table_rows, materialized: true + end +end diff --git a/server/db/schema.rb b/server/db/schema.rb index 80ac9eac9..ac509a02f 100644 --- a/server/db/schema.rb +++ b/server/db/schema.rb @@ -10,14 +10,16 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_07_26_163525) do +ActiveRecord::Schema[7.1].define(version: 2024_08_21_202933) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" # Custom types defined in this database. # Note that some types may not work with other database engines. Be careful if changing database. + create_enum "exon_coordinate_record_state", ["stub", "exons_provided", "fully_curated"] create_enum "exon_offset_direction", ["positive", "negative"] create_enum "fusion_partner_status", ["known", "unknown", "multiple"] + create_enum "variant_coordinate_record_state", ["stub", "fully_curated"] create_table "acmg_codes", id: :serial, force: :cascade do |t| t.text "code" @@ -447,21 +449,22 @@ 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.text "chromosome" + t.enum "strand", enum_type: "exon_offset_direction" + t.bigint "start" + t.bigint "stop" + t.integer "exon" + t.text "ensembl_id" 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 "ensembl_version" + t.text "representative_transcript" 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.enum "record_state", default: "stub", null: false, enum_type: "exon_coordinate_record_state" 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" @@ -729,14 +732,15 @@ end create_table "solid_errors", force: :cascade do |t| - t.string "exception_class", null: false - t.string "message", null: false - t.string "severity", null: false - t.string "source" + t.text "exception_class", null: false + t.text "message", null: false + t.text "severity", null: false + t.text "source" t.datetime "resolved_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.index ["exception_class", "message", "severity", "source"], name: "solid_error_uniqueness_index", unique: true + t.string "fingerprint", limit: 64 + t.index ["fingerprint"], name: "index_solid_errors_on_fingerprint", unique: true t.index ["resolved_at"], name: "index_solid_errors_on_resolved_at" end @@ -915,10 +919,11 @@ t.integer "ensembl_version" t.text "representative_transcript" t.integer "reference_build" - t.bigint "variant_id" + 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.enum "record_state", default: "stub", null: false, enum_type: "variant_coordinate_record_state" 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" @@ -1255,30 +1260,6 @@ SQL add_index "source_browse_table_rows", ["id"], name: "index_source_browse_table_rows_on_id", unique: true - create_view "disease_browse_table_rows", materialized: true, sql_definition: <<-SQL - SELECT diseases.id, - diseases.name, - diseases.display_name, - diseases.doid, - diseases.deprecated, - json_agg(DISTINCT jsonb_build_object('name', features.name, 'id', features.id)) FILTER (WHERE (features.name IS NOT NULL)) AS features, - count(DISTINCT evidence_items.id) AS evidence_item_count, - count(DISTINCT variants.id) AS variant_count, - count(DISTINCT assertions.id) AS assertion_count, - count(DISTINCT features.id) AS feature_count - FROM (((((((diseases - JOIN evidence_items ON ((diseases.id = evidence_items.disease_id))) - LEFT JOIN assertions_evidence_items ON ((assertions_evidence_items.evidence_item_id = evidence_items.id))) - LEFT JOIN assertions ON ((assertions_evidence_items.assertion_id = assertions.id))) - JOIN molecular_profiles ON ((molecular_profiles.id = evidence_items.molecular_profile_id))) - JOIN molecular_profiles_variants ON ((molecular_profiles_variants.molecular_profile_id = molecular_profiles.id))) - JOIN variants ON ((variants.id = molecular_profiles_variants.variant_id))) - JOIN features ON ((features.id = variants.feature_id))) - WHERE (((evidence_items.status)::text <> 'rejected'::text) AND (diseases.deprecated = false)) - GROUP BY diseases.id, diseases.name, diseases.doid; - SQL - add_index "disease_browse_table_rows", ["id"], name: "index_disease_browse_table_rows_on_id", unique: true - create_view "molecular_profile_browse_table_rows", materialized: true, sql_definition: <<-SQL SELECT outer_mps.id, outer_mps.name, @@ -1476,4 +1457,51 @@ SQL add_index "feature_browse_table_rows", ["id"], name: "index_feature_browse_table_rows_on_id", unique: true + create_view "disease_browse_table_rows", materialized: true, sql_definition: <<-SQL + SELECT diseases.id, + diseases.name, + diseases.display_name, + diseases.doid, + diseases.deprecated, + array_agg(DISTINCT disease_aliases.name ORDER BY disease_aliases.name) AS alias_names, + json_agg(DISTINCT jsonb_build_object('name', features.name, 'id', features.id)) FILTER (WHERE (features.name IS NOT NULL)) AS features, + count(DISTINCT evidence_items.id) AS evidence_item_count, + count(DISTINCT variants.id) AS variant_count, + count(DISTINCT assertions.id) AS assertion_count, + count(DISTINCT features.id) AS feature_count + FROM (((((((((diseases + JOIN evidence_items ON ((diseases.id = evidence_items.disease_id))) + LEFT JOIN assertions_evidence_items ON ((assertions_evidence_items.evidence_item_id = evidence_items.id))) + LEFT JOIN assertions ON ((assertions_evidence_items.assertion_id = assertions.id))) + LEFT JOIN disease_aliases_diseases ON ((disease_aliases_diseases.disease_id = diseases.id))) + LEFT JOIN disease_aliases ON ((disease_aliases.id = disease_aliases_diseases.disease_alias_id))) + JOIN molecular_profiles ON ((molecular_profiles.id = evidence_items.molecular_profile_id))) + JOIN molecular_profiles_variants ON ((molecular_profiles_variants.molecular_profile_id = molecular_profiles.id))) + JOIN variants ON ((variants.id = molecular_profiles_variants.variant_id))) + JOIN features ON ((features.id = variants.feature_id))) + WHERE (((evidence_items.status)::text <> 'rejected'::text) AND (diseases.deprecated = false)) + GROUP BY diseases.id, diseases.name, diseases.doid; + SQL + add_index "disease_browse_table_rows", ["id"], name: "index_disease_browse_table_rows_on_id", unique: true + + create_view "therapy_browse_table_rows", materialized: true, sql_definition: <<-SQL + SELECT therapies.id, + therapies.name, + therapies.deprecated, + therapies.ncit_id, + count(DISTINCT assertions.id) AS assertion_count, + count(DISTINCT evidence_items.id) AS evidence_count, + array_agg(DISTINCT therapy_aliases.name ORDER BY therapy_aliases.name) AS alias_names + FROM ((((((therapies + JOIN evidence_items_therapies ON ((evidence_items_therapies.therapy_id = therapies.id))) + JOIN evidence_items ON ((evidence_items_therapies.evidence_item_id = evidence_items.id))) + LEFT JOIN assertions_evidence_items ON ((assertions_evidence_items.evidence_item_id = evidence_items.id))) + LEFT JOIN assertions ON ((assertions_evidence_items.assertion_id = assertions.id))) + LEFT JOIN therapies_therapy_aliases ON ((therapies_therapy_aliases.therapy_id = therapies.id))) + LEFT JOIN therapy_aliases ON ((therapy_aliases.id = therapies_therapy_aliases.therapy_alias_id))) + WHERE ((((evidence_items.status)::text <> 'rejected'::text) OR (assertions.status <> 'rejected'::text)) AND (therapies.deprecated = false)) + GROUP BY therapies.id, therapies.name, therapies.deprecated, therapies.ncit_id + HAVING ((count(evidence_items.id) > 0) OR (count(assertions.id) > 0)) + ORDER BY (count(DISTINCT evidence_items.id)) DESC, therapies.id; + SQL end diff --git a/server/db/views/disease_browse_table_rows_v08.sql b/server/db/views/disease_browse_table_rows_v08.sql new file mode 100644 index 000000000..2aef96910 --- /dev/null +++ b/server/db/views/disease_browse_table_rows_v08.sql @@ -0,0 +1,24 @@ +SELECT diseases.id, + diseases.name, + diseases.display_name, + diseases.doid, + diseases.deprecated, + array_agg(distinct(disease_aliases.name) order by disease_aliases.name) as alias_names, + json_agg(distinct jsonb_build_object('name', features.name, 'id', features.id)) FILTER (WHERE features.name IS NOT NULL) as features, + COUNT(DISTINCT(evidence_items.id)) as evidence_item_count, + COUNT(DISTINCT(variants.id)) as variant_count, + COUNT(DISTINCT(assertions.id)) as assertion_count, + COUNT(DISTINCT(features.id)) as feature_count +FROM diseases +INNER JOIN evidence_items on diseases.id = evidence_items.disease_id +LEFT OUTER JOIN assertions_evidence_items on assertions_evidence_items.evidence_item_id = evidence_items.id +LEFT OUTER JOIN assertions on assertions_evidence_items.assertion_id = assertions.id +LEFT OUTER JOIN disease_aliases_diseases ON disease_aliases_diseases.disease_id = diseases.id +LEFT OUTER JOIN disease_aliases ON disease_aliases.id = disease_aliases_diseases.disease_alias_id +INNER JOIN molecular_profiles on molecular_profiles.id = evidence_items.molecular_profile_id +INNER JOIN molecular_profiles_variants on molecular_profiles_variants.molecular_profile_id = molecular_profiles.id +INNER JOIN variants on variants.id = molecular_profiles_variants.variant_id +INNER JOIN features on features.id = variants.feature_id +WHERE evidence_items.status != 'rejected' +AND diseases.deprecated = false +GROUP BY diseases.id, diseases.name, diseases.doid diff --git a/server/db/views/therapy_browse_table_rows_v01.sql b/server/db/views/therapy_browse_table_rows_v01.sql new file mode 100644 index 000000000..31c3f6847 --- /dev/null +++ b/server/db/views/therapy_browse_table_rows_v01.sql @@ -0,0 +1,19 @@ +SELECT therapies.id, + therapies.name, + therapies.deprecated, + therapies.ncit_id, + COUNT(DISTINCT(assertions.id)) as assertion_count, + COUNT(DISTINCT(evidence_items.id)) as evidence_count, + array_agg(distinct(therapy_aliases.name) order by therapy_aliases.name) as alias_names +FROM therapies +INNER JOIN evidence_items_therapies ON evidence_items_therapies.therapy_id = therapies.id +INNER JOIN evidence_items on evidence_items_therapies.evidence_item_id = evidence_items.id +LEFT OUTER JOIN assertions_evidence_items on assertions_evidence_items.evidence_item_id = evidence_items.id +LEFT OUTER JOIN assertions on assertions_evidence_items.assertion_id = assertions.id +LEFT OUTER JOIN therapies_therapy_aliases ON therapies_therapy_aliases.therapy_id = therapies.id +LEFT OUTER JOIN therapy_aliases ON therapy_aliases.id = therapies_therapy_aliases.therapy_alias_id +WHERE (evidence_items.status != 'rejected' OR assertions.status != 'rejected') +AND deprecated = false +GROUP BY therapies.id, therapies.name, therapies.deprecated, therapies.ncit_id +HAVING (COUNT(evidence_items.id) > 0 OR COUNT(assertions.id) > 0) +ORDER BY evidence_count DESC, therapies.id ASC From 87a15b894994b1f2093299274aa6f3c2f0500573 Mon Sep 17 00:00:00 2001 From: Adam Coffman Date: Wed, 21 Aug 2024 16:18:20 -0500 Subject: [PATCH 3/5] add alias filtering to therapy and disease browse, extract duplicate search helpers --- .../app/graphql/resolvers/browse_diseases.rb | 15 +++++---- .../app/graphql/resolvers/browse_features.rb | 21 ++++-------- .../resolvers/browse_molecular_profiles.rb | 33 ++++++++----------- .../app/graphql/resolvers/browse_variants.rb | 31 +++++++---------- .../resolvers/shared/search_helpers.rb | 17 ++++++++++ .../graphql/resolvers/top_level_therapies.rb | 5 +++ .../therapy_browse_table_row.rb | 2 ++ 7 files changed, 64 insertions(+), 60 deletions(-) create mode 100644 server/app/graphql/resolvers/shared/search_helpers.rb create mode 100644 server/app/models/materialized_views/therapy_browse_table_row.rb diff --git a/server/app/graphql/resolvers/browse_diseases.rb b/server/app/graphql/resolvers/browse_diseases.rb index 3456b757f..cf709c8e1 100644 --- a/server/app/graphql/resolvers/browse_diseases.rb +++ b/server/app/graphql/resolvers/browse_diseases.rb @@ -2,8 +2,8 @@ require 'search_object/plugin/graphql' class Resolvers::BrowseDiseases < GraphQL::Schema::Resolver - # include SearchObject for GraphQL include SearchObject.module(:graphql) + include Resolvers::Shared::SearchHelpers type Types::BrowseTables::BrowseDiseaseType.connection_type, null: false @@ -25,7 +25,13 @@ class Resolvers::BrowseDiseases < GraphQL::Schema::Resolver end end - option(:feature_name, type: String) { |scope, value| scope.where(json_name_query_for_column('features'), "%#{value}%") } + option(:feature_name, type: String) do |scope, value| + scope.where(json_name_query_for_column(scope.table_name, 'features'), "%#{value}%") + end + + option(:disease_alias, type: String) do |scope, value| + scope.where(array_query_for_column('alias_names'), "%#{value}%") + end option(:sort_by, type: Types::BrowseTables::DiseasesSortType) do |scope, value| case value.column @@ -43,10 +49,5 @@ class Resolvers::BrowseDiseases < GraphQL::Schema::Resolver scope.order("feature_count #{value.direction}") end end - - def json_name_query_for_column(col) - raise 'Must supply a column name' if col.nil? - "disease_browse_table_rows.id IN (select d.id FROM disease_browse_table_rows d, json_array_elements(d.#{col}) dr where dr->>'name' ILIKE ?)" - end end diff --git a/server/app/graphql/resolvers/browse_features.rb b/server/app/graphql/resolvers/browse_features.rb index 6483e78e4..331a0a2da 100644 --- a/server/app/graphql/resolvers/browse_features.rb +++ b/server/app/graphql/resolvers/browse_features.rb @@ -2,8 +2,8 @@ require 'search_object/plugin/graphql' class Resolvers::BrowseFeatures < GraphQL::Schema::Resolver - # include SearchObject for GraphQL include SearchObject.module(:graphql) + include Resolvers::Shared::SearchHelpers type Types::BrowseTables::BrowseFeatureType.connection_type, null: false @@ -12,8 +12,12 @@ class Resolvers::BrowseFeatures < GraphQL::Schema::Resolver 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}%") } + option(:disease_name, type: String) do |scope, value| + scope.where(json_name_query_for_column(scope.table_name, 'diseases'), "%#{value}%") + end + option(:therapy_name, type: String) do |scope, value| + scope.where(json_name_query_for_column(scope.table_name, 'therapies'), "%#{value}%") + end option(:feature_type, type: Types::FeatureInstanceTypes) do |scope, value| if value scope.where(feature_instance_type: value) @@ -44,15 +48,4 @@ class Resolvers::BrowseFeatures < GraphQL::Schema::Resolver scope.order "molecular_profile_count #{value.direction}" end end - - private - def array_query_for_column(col) - raise 'Must supply a column name' if col.nil? - "EXISTS (SELECT * FROM (SELECT unnest(#{col})) x(name) where name ILIKE ?)" - end - - def json_name_query_for_column(col) - raise 'Must supply a column name' if col.nil? - "feature_browse_table_rows.id IN (select fb.id FROM feature_browse_table_rows fb, json_array_elements(fb.#{col}) d where d->>'name' ILIKE ?)" - end end diff --git a/server/app/graphql/resolvers/browse_molecular_profiles.rb b/server/app/graphql/resolvers/browse_molecular_profiles.rb index d9da15c2c..46ce324b1 100644 --- a/server/app/graphql/resolvers/browse_molecular_profiles.rb +++ b/server/app/graphql/resolvers/browse_molecular_profiles.rb @@ -2,9 +2,8 @@ require 'search_object/plugin/graphql' class Resolvers::BrowseMolecularProfiles < GraphQL::Schema::Resolver - # include SearchObject for GraphQL include SearchObject.module(:graphql) - + include Resolvers::Shared::SearchHelpers type Types::BrowseTables::BrowseMolecularProfileType.connection_type, null: false @@ -27,16 +26,22 @@ class Resolvers::BrowseMolecularProfiles < GraphQL::Schema::Resolver scope.where(id: ids) end - option(:variant_name, type: String) do |scope, value| - scope.where(json_name_query_for_column('variants'), "#{value}%") - .or(scope.where(json_name_query_for_column('features'), "#{value}")) + option(:variant_name, type: String) do |scope, value| + scope.where(json_name_query_for_column(scope.table_name, 'variants'), "#{value}%") + .or(scope.where(json_name_query_for_column(scope.table_name, 'features'), "#{value}")) end - option(:feature_name, type: String) { |scope, value| scope.where(json_name_query_for_column('features'), "#{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}%") } + option(:feature_name, type: String) do |scope, value| + scope.where(json_name_query_for_column(scope.table_name, 'features'), "#{value}%") + end + option(:disease_name, type: String) do |scope, value| + scope.where(json_name_query_for_column(scope.table_name, 'diseases'), "%#{value}%") + end + option(:therapy_name, type: String) do |scope, value| + scope.where(json_name_query_for_column(scope.table_name, 'therapies'), "%#{value}%") + end option(:molecular_profile_alias, type: String) { |scope, value| scope.where(array_query_for_column('alias_names'), "%#{value}%") } - option(:variant_id, type: Int) do |scope, value| + option(:variant_id, type: Int) do |scope, value| scope.where(id: MolecularProfile.joins(:variants).where(variants: { id: value }).select('molecular_profiles.id')) end @@ -52,14 +57,4 @@ class Resolvers::BrowseMolecularProfiles < GraphQL::Schema::Resolver scope.reorder "variant_count #{value.direction}" end end - - def json_name_query_for_column(col) - raise 'Must supply a column name' if col.nil? - "molecular_profile_browse_table_rows.id IN (select mp.id FROM molecular_profile_browse_table_rows mp, json_array_elements(mp.#{col}) d where d->>'name' ILIKE ?)" - end - - def array_query_for_column(col) - raise 'Must supply a column name' if col.nil? - "EXISTS (SELECT * FROM (SELECT unnest(#{col})) x(name) where name ILIKE ?)" - end end diff --git a/server/app/graphql/resolvers/browse_variants.rb b/server/app/graphql/resolvers/browse_variants.rb index 08c4f481c..4333199ca 100644 --- a/server/app/graphql/resolvers/browse_variants.rb +++ b/server/app/graphql/resolvers/browse_variants.rb @@ -2,8 +2,8 @@ require 'search_object/plugin/graphql' class Resolvers::BrowseVariants < GraphQL::Schema::Resolver - # include SearchObject for GraphQL include SearchObject.module(:graphql) + include Resolvers::Shared::SearchHelpers type Types::BrowseTables::BrowseVariantType.connection_type, null: false @@ -12,10 +12,17 @@ class Resolvers::BrowseVariants < GraphQL::Schema::Resolver option(:variant_name, type: String) { |scope, value| scope.where("name ILIKE ?", "%#{value}%") } option(:feature_name, type: String) { |scope, value| scope.where("feature_name ILIKE ?", "#{value}%") } option(:variant_type_id, type: Int) { |scope, value| scope.where(int_array_query_for_column('variant_type_ids'), 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}%") } + + option(:disease_name, type: String) do |scope, value| + scope.where(json_name_query_for_column(scope.table_name, 'diseases'), "%#{value}%") + end + + option(:therapy_name, type: String) do |scope, value| + scope.where(json_name_query_for_column(scope.table_name, 'therapies'), "%#{value}%") + end + option(:variant_alias, type: String) { |scope, value| scope.where(array_query_for_column('alias_names'), "%#{value}%") } - option(:variant_group_id, type: Int) do |scope, value| + option(:variant_group_id, type: Int) do |scope, value| scope.where(id: Variant.joins(:variant_groups).where('variant_groups.id = ?', value).distinct) end option(:variant_type_name, type: String) { |scope, value| scope.where(json_name_query_for_column('variant_types'), "%#{value}%") } @@ -47,20 +54,4 @@ class Resolvers::BrowseVariants < GraphQL::Schema::Resolver scope.reorder "disease_names #{value.direction}" end end - - private - def array_query_for_column(col) - raise 'Must supply a column name' if col.nil? - "EXISTS (SELECT * FROM (SELECT unnest(#{col})) x(name) where name ILIKE ?)" - end - - def int_array_query_for_column(col) - raise 'Must supply a column name' if col.nil? - "EXISTS (SELECT * FROM (SELECT unnest(#{col})) x(id) where id = ?)" - end - - def json_name_query_for_column(col) - raise 'Must supply a column name' if col.nil? - "variant_browse_table_rows.id IN (select vb.id FROM variant_browse_table_rows vb, json_array_elements(vb.#{col}) d where d->>'name' ILIKE ?)" - end end diff --git a/server/app/graphql/resolvers/shared/search_helpers.rb b/server/app/graphql/resolvers/shared/search_helpers.rb new file mode 100644 index 000000000..d53b582de --- /dev/null +++ b/server/app/graphql/resolvers/shared/search_helpers.rb @@ -0,0 +1,17 @@ +module Resolvers::Shared::SearchHelpers + def json_name_query_for_column(table_name, col) + raise 'Must supply a table_name' if table_name.nil? + raise 'Must supply a column name' if col.nil? + "#{table_name}.id IN (select d.id FROM #{table_name} d, json_array_elements(d.#{col}) dr where dr->>'name' ILIKE ?)" + end + + def array_query_for_column(col) + raise 'Must supply a column name' if col.nil? + "EXISTS (SELECT * FROM (SELECT unnest(#{col})) x(name) where name ILIKE ?)" + end + + def int_array_query_for_column(col) + raise 'Must supply a column name' if col.nil? + "EXISTS (SELECT * FROM (SELECT unnest(#{col})) x(id) where id = ?)" + end +end diff --git a/server/app/graphql/resolvers/top_level_therapies.rb b/server/app/graphql/resolvers/top_level_therapies.rb index b3368c21f..a3c218d48 100644 --- a/server/app/graphql/resolvers/top_level_therapies.rb +++ b/server/app/graphql/resolvers/top_level_therapies.rb @@ -3,6 +3,7 @@ class Resolvers::TopLevelTherapies < GraphQL::Schema::Resolver include SearchObject.module(:graphql) + include Resolvers::Shared::SearchHelpers type Types::BrowseTables::BrowseTherapyType.connection_type, null: false @@ -18,6 +19,10 @@ class Resolvers::TopLevelTherapies < GraphQL::Schema::Resolver end end + option(:therapy_alias, type: String) do |scope, value| + scope.where(array_query_for_column('alias_names'), "%#{value}%") + end + option(:id, type: Int, description: "Filter on a therapy's internal CIViC id") do |scope, value| scope.where(id: id) end diff --git a/server/app/models/materialized_views/therapy_browse_table_row.rb b/server/app/models/materialized_views/therapy_browse_table_row.rb new file mode 100644 index 000000000..683d7898e --- /dev/null +++ b/server/app/models/materialized_views/therapy_browse_table_row.rb @@ -0,0 +1,2 @@ +class MaterializedViews::TherapyBrowseTableRow < MaterializedViews::MaterializedView +end From 5fdabc809ef71b04339e33b0852c5c488d1cf39f Mon Sep 17 00:00:00 2001 From: Adam Coffman Date: Wed, 21 Aug 2024 16:49:23 -0500 Subject: [PATCH 4/5] add aliases to therapy browse table --- .../therapies-table.component.html | 16 ++++- .../therapies-table.component.ts | 14 +++- .../therapies-table/therapies-table.module.ts | 2 + .../therapies-table/therapies-table.query.gql | 3 + .../src/app/generated/civic.apollo-helpers.ts | 6 +- client/src/app/generated/civic.apollo.ts | 13 +++- client/src/app/generated/server.model.graphql | 4 ++ client/src/app/generated/server.schema.json | 64 +++++++++++++++++++ .../browse_tables/browse_therapy_type.rb | 3 +- 9 files changed, 115 insertions(+), 10 deletions(-) diff --git a/client/src/app/components/therapies/therapies-table/therapies-table.component.html b/client/src/app/components/therapies/therapies-table/therapies-table.component.html index ca6aef0b1..7fc791ff2 100644 --- a/client/src/app/components/therapies/therapies-table/therapies-table.component.html +++ b/client/src/app/components/therapies/therapies-table/therapies-table.component.html @@ -54,11 +54,12 @@ Name NCIt Code + Aliases + + + @@ -123,6 +131,12 @@ -- + + + diff --git a/client/src/app/components/therapies/therapies-table/therapies-table.component.ts b/client/src/app/components/therapies/therapies-table/therapies-table.component.ts index a5749064f..f0fadfe55 100644 --- a/client/src/app/components/therapies/therapies-table/therapies-table.component.ts +++ b/client/src/app/components/therapies/therapies-table/therapies-table.component.ts @@ -33,7 +33,6 @@ import { filter, map, skip, - take, takeWhile, withLatestFrom, } from 'rxjs/operators' @@ -42,6 +41,7 @@ import { pluck } from 'rxjs-etc/operators' export interface TherapyTableUserFilters { ncitIdFilter?: Maybe nameFilter?: Maybe + therapyAliasFilter?: Maybe } @UntilDestroy() @@ -87,10 +87,14 @@ export class CvcTherapiesTableComponent implements OnInit { // filters ncitIdFilter: Maybe nameFilter: Maybe + therapyAliasFilter: Maybe sortColumns = TherapySortColumns - constructor(private gql: TherapiesBrowseGQL, private cdr: ChangeDetectorRef) { + constructor( + private gql: TherapiesBrowseGQL, + private cdr: ChangeDetectorRef + ) { this.noMoreRows$ = new BehaviorSubject(false) this.scrollEvent$ = new BehaviorSubject('stop') this.sortChange$ = new Subject() @@ -186,13 +190,17 @@ export class CvcTherapiesTableComponent implements OnInit { .refetch({ name: this.nameFilter, ncitId: this.ncitIdFilter, + therapyAlias: this.therapyAliasFilter, }) .then(() => this.scrollIndex$.next(0)) this.cdr.detectChanges() } - trackByIndex(_: number, data: Maybe): Maybe { + trackByIndex( + _: number, + data: Maybe + ): Maybe { return data?.id } } diff --git a/client/src/app/components/therapies/therapies-table/therapies-table.module.ts b/client/src/app/components/therapies/therapies-table/therapies-table.module.ts index 292e3abc2..38d7d1f0a 100644 --- a/client/src/app/components/therapies/therapies-table/therapies-table.module.ts +++ b/client/src/app/components/therapies/therapies-table/therapies-table.module.ts @@ -18,6 +18,7 @@ import { CvcTableCountsModule } from '@app/components/shared/table-counts/table- import { CvcNoMoreRowsModule } from '@app/components/shared/no-more-rows/no-more-rows.module' import { CvcPipesModule } from '@app/core/pipes/pipes.module' import { CvcTherapyTagModule } from '../cvc-therapy-tag/cvc-therapy-tag.module' +import { CvcPlainTagOverflowModule } from '@app/components/shared/plain-tag-overflow/plain-tag-overflow.module' @NgModule({ declarations: [CvcTherapiesTableComponent], @@ -44,6 +45,7 @@ import { CvcTherapyTagModule } from '../cvc-therapy-tag/cvc-therapy-tag.module' CvcNoMoreRowsModule, CvcTableCountsModule, CvcTableScrollModule, + CvcPlainTagOverflowModule, ], exports: [CvcTherapiesTableComponent], }) diff --git a/client/src/app/components/therapies/therapies-table/therapies-table.query.gql b/client/src/app/components/therapies/therapies-table/therapies-table.query.gql index 3cd1eb57a..f8bc7a0a2 100644 --- a/client/src/app/components/therapies/therapies-table/therapies-table.query.gql +++ b/client/src/app/components/therapies/therapies-table/therapies-table.query.gql @@ -5,6 +5,7 @@ query TherapiesBrowse( $after: String $name: String $ncitId: String + $therapyAlias: String, $sortBy: TherapySort ) { therapies( @@ -14,6 +15,7 @@ query TherapiesBrowse( after: $after name: $name ncitId: $ncitId + therapyAlias: $therapyAlias sortBy: $sortBy ) { totalCount @@ -42,4 +44,5 @@ fragment TherapyBrowseTableRowFields on BrowseTherapy { evidenceCount link deprecated + therapyAliases } diff --git a/client/src/app/generated/civic.apollo-helpers.ts b/client/src/app/generated/civic.apollo-helpers.ts index 30c9d2b61..ac056a32d 100644 --- a/client/src/app/generated/civic.apollo-helpers.ts +++ b/client/src/app/generated/civic.apollo-helpers.ts @@ -164,10 +164,11 @@ export type BrowseClinicalTrialEdgeFieldPolicy = { cursor?: FieldPolicy | FieldReadFunction, node?: FieldPolicy | FieldReadFunction }; -export type BrowseDiseaseKeySpecifier = ('assertionCount' | 'deprecated' | 'diseaseUrl' | 'displayName' | 'doid' | 'evidenceItemCount' | 'featureCount' | 'features' | 'id' | 'link' | 'name' | 'variantCount' | BrowseDiseaseKeySpecifier)[]; +export type BrowseDiseaseKeySpecifier = ('assertionCount' | 'deprecated' | 'diseaseAliases' | 'diseaseUrl' | 'displayName' | 'doid' | 'evidenceItemCount' | 'featureCount' | 'features' | 'id' | 'link' | 'name' | 'variantCount' | BrowseDiseaseKeySpecifier)[]; export type BrowseDiseaseFieldPolicy = { assertionCount?: FieldPolicy | FieldReadFunction, deprecated?: FieldPolicy | FieldReadFunction, + diseaseAliases?: FieldPolicy | FieldReadFunction, diseaseUrl?: FieldPolicy | FieldReadFunction, displayName?: FieldPolicy | FieldReadFunction, doid?: FieldPolicy | FieldReadFunction, @@ -348,7 +349,7 @@ export type BrowseSourceEdgeFieldPolicy = { cursor?: FieldPolicy | FieldReadFunction, node?: FieldPolicy | FieldReadFunction }; -export type BrowseTherapyKeySpecifier = ('assertionCount' | 'deprecated' | 'evidenceCount' | 'id' | 'link' | 'name' | 'ncitId' | 'therapyUrl' | BrowseTherapyKeySpecifier)[]; +export type BrowseTherapyKeySpecifier = ('assertionCount' | 'deprecated' | 'evidenceCount' | 'id' | 'link' | 'name' | 'ncitId' | 'therapyAliases' | 'therapyUrl' | BrowseTherapyKeySpecifier)[]; export type BrowseTherapyFieldPolicy = { assertionCount?: FieldPolicy | FieldReadFunction, deprecated?: FieldPolicy | FieldReadFunction, @@ -357,6 +358,7 @@ export type BrowseTherapyFieldPolicy = { link?: FieldPolicy | FieldReadFunction, name?: FieldPolicy | FieldReadFunction, ncitId?: FieldPolicy | FieldReadFunction, + therapyAliases?: FieldPolicy | FieldReadFunction, therapyUrl?: FieldPolicy | FieldReadFunction }; export type BrowseTherapyConnectionKeySpecifier = ('edges' | 'filteredCount' | 'lastUpdated' | 'nodes' | 'pageCount' | 'pageInfo' | 'totalCount' | BrowseTherapyConnectionKeySpecifier)[]; diff --git a/client/src/app/generated/civic.apollo.ts b/client/src/app/generated/civic.apollo.ts index 0bb152fea..14854aae5 100644 --- a/client/src/app/generated/civic.apollo.ts +++ b/client/src/app/generated/civic.apollo.ts @@ -537,6 +537,7 @@ export type BrowseDisease = { __typename: 'BrowseDisease'; assertionCount: Scalars['Int']['output']; deprecated: Scalars['Boolean']['output']; + diseaseAliases?: Maybe>; diseaseUrl?: Maybe; displayName: Scalars['String']['output']; doid?: Maybe; @@ -823,6 +824,7 @@ export type BrowseTherapy = { link: Scalars['String']['output']; name: Scalars['String']['output']; ncitId?: Maybe; + therapyAliases?: Maybe>; therapyUrl?: Maybe; }; @@ -4478,6 +4480,7 @@ export type QueryAssertionsArgs = { export type QueryBrowseDiseasesArgs = { after?: InputMaybe; before?: InputMaybe; + diseaseAlias?: InputMaybe; doid?: InputMaybe; featureName?: InputMaybe; first?: InputMaybe; @@ -4942,6 +4945,7 @@ export type QueryTherapiesArgs = { name?: InputMaybe; ncitId?: InputMaybe; sortBy?: InputMaybe; + therapyAlias?: InputMaybe; }; @@ -7607,13 +7611,14 @@ export type TherapiesBrowseQueryVariables = Exact<{ after?: InputMaybe; name?: InputMaybe; ncitId?: InputMaybe; + therapyAlias?: InputMaybe; sortBy?: InputMaybe; }>; -export type TherapiesBrowseQuery = { __typename: 'Query', therapies: { __typename: 'BrowseTherapyConnection', totalCount: number, filteredCount: number, pageInfo: { __typename: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | undefined, endCursor?: string | undefined }, edges: Array<{ __typename: 'BrowseTherapyEdge', cursor: string, node?: { __typename: 'BrowseTherapy', id: number, name: string, ncitId?: string | undefined, therapyUrl?: string | undefined, assertionCount: number, evidenceCount: number, link: string, deprecated: boolean } | undefined }> } }; +export type TherapiesBrowseQuery = { __typename: 'Query', therapies: { __typename: 'BrowseTherapyConnection', totalCount: number, filteredCount: number, pageInfo: { __typename: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | undefined, endCursor?: string | undefined }, edges: Array<{ __typename: 'BrowseTherapyEdge', cursor: string, node?: { __typename: 'BrowseTherapy', id: number, name: string, ncitId?: string | undefined, therapyUrl?: string | undefined, assertionCount: number, evidenceCount: number, link: string, deprecated: boolean, therapyAliases?: Array | undefined } | undefined }> } }; -export type TherapyBrowseTableRowFieldsFragment = { __typename: 'BrowseTherapy', id: number, name: string, ncitId?: string | undefined, therapyUrl?: string | undefined, assertionCount: number, evidenceCount: number, link: string, deprecated: boolean }; +export type TherapyBrowseTableRowFieldsFragment = { __typename: 'BrowseTherapy', id: number, name: string, ncitId?: string | undefined, therapyUrl?: string | undefined, assertionCount: number, evidenceCount: number, link: string, deprecated: boolean, therapyAliases?: Array | undefined }; export type LeaderboardUserFieldsFragment = { __typename: 'LeaderboardUser', id: number, name?: string | undefined, displayName: string, actionCount: number, role: UserRole, rank: number, profileImagePath?: string | undefined }; @@ -10059,6 +10064,7 @@ export const TherapyBrowseTableRowFieldsFragmentDoc = gql` evidenceCount link deprecated + therapyAliases } `; export const LeaderboardUserFieldsFragmentDoc = gql` @@ -13342,7 +13348,7 @@ export const TherapyPopoverDocument = gql` } } export const TherapiesBrowseDocument = gql` - query TherapiesBrowse($first: Int, $last: Int, $before: String, $after: String, $name: String, $ncitId: String, $sortBy: TherapySort) { + query TherapiesBrowse($first: Int, $last: Int, $before: String, $after: String, $name: String, $ncitId: String, $therapyAlias: String, $sortBy: TherapySort) { therapies( first: $first last: $last @@ -13350,6 +13356,7 @@ export const TherapiesBrowseDocument = gql` after: $after name: $name ncitId: $ncitId + therapyAlias: $therapyAlias sortBy: $sortBy ) { totalCount diff --git a/client/src/app/generated/server.model.graphql b/client/src/app/generated/server.model.graphql index 8ba2abfd1..3c8cde4ec 100644 --- a/client/src/app/generated/server.model.graphql +++ b/client/src/app/generated/server.model.graphql @@ -868,6 +868,7 @@ type BrowseClinicalTrialEdge { type BrowseDisease { assertionCount: Int! deprecated: Boolean! + diseaseAliases: [String!] diseaseUrl: String displayName: String! doid: String @@ -1341,6 +1342,7 @@ type BrowseTherapy { link: String! name: String! ncitId: String + therapyAliases: [String!] therapyUrl: String } @@ -7272,6 +7274,7 @@ type Query { Returns the elements in the list that come before the specified cursor. """ before: String + diseaseAlias: String doid: String featureName: String @@ -8301,6 +8304,7 @@ type Query { Sort order for the therapies. Defaults to the highest evidence item count. """ sortBy: TherapySort + therapyAlias: String ): BrowseTherapyConnection! """ diff --git a/client/src/app/generated/server.schema.json b/client/src/app/generated/server.schema.json index f37995794..d220cd5ac 100644 --- a/client/src/app/generated/server.schema.json +++ b/client/src/app/generated/server.schema.json @@ -3951,6 +3951,26 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "diseaseAliases", + "description": null, + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "diseaseUrl", "description": null, @@ -6512,6 +6532,26 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "therapyAliases", + "description": null, + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "therapyUrl", "description": null, @@ -34300,6 +34340,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "diseaseAlias", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "sortBy", "description": null, @@ -38372,6 +38424,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "therapyAlias", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "id", "description": "Filter on a therapy's internal CIViC id", diff --git a/server/app/graphql/types/browse_tables/browse_therapy_type.rb b/server/app/graphql/types/browse_tables/browse_therapy_type.rb index a3898c7a1..8809a7ef6 100644 --- a/server/app/graphql/types/browse_tables/browse_therapy_type.rb +++ b/server/app/graphql/types/browse_tables/browse_therapy_type.rb @@ -17,7 +17,8 @@ def therapy_url end def therapy_aliases - object.alias_names.compact + #order by size to reduce the chance of the long chemical formulas appearing the table + object.alias_names&.compact&.sort_by(&:size) end def link From 0297aa19b36b365927d2b8e652e8d9b1430a9b8a Mon Sep 17 00:00:00 2001 From: Adam Coffman Date: Wed, 21 Aug 2024 16:57:37 -0500 Subject: [PATCH 5/5] add aliases to disease browse --- .../diseases-table.component.html | 20 ++++++++++++++++--- .../diseases-table.component.ts | 14 ++++++++++--- .../diseases-table/diseases-table.module.ts | 2 ++ .../diseases-table/diseases-table.query.gql | 3 +++ client/src/app/generated/civic.apollo.ts | 9 ++++++--- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/client/src/app/components/diseases/diseases-table/diseases-table.component.html b/client/src/app/components/diseases/diseases-table/diseases-table.component.html index 6747b1254..4a09bbedc 100644 --- a/client/src/app/components/diseases/diseases-table/diseases-table.component.html +++ b/client/src/app/components/diseases/diseases-table/diseases-table.component.html @@ -46,20 +46,21 @@ Name DOID - Features + Aliases + Features + + + -- + + + featureNameInput?: Maybe doidInput?: Maybe + diseaseAliasInput?: Maybe } @UntilDestroy() @@ -85,10 +85,14 @@ export class CvcDiseasesTableComponent implements OnInit { nameInput: Maybe featureNameInput: Maybe doidInput: Maybe + diseaseAliasInput: Maybe sortColumns: typeof DiseasesSortColumns = DiseasesSortColumns - constructor(private gql: BrowseDiseasesGQL, private cdr: ChangeDetectorRef) { + constructor( + private gql: BrowseDiseasesGQL, + private cdr: ChangeDetectorRef + ) { this.noMoreRows$ = new BehaviorSubject(false) this.scrollEvent$ = new BehaviorSubject('stop') this.sortChange$ = new Subject() @@ -185,13 +189,17 @@ export class CvcDiseasesTableComponent implements OnInit { name: this.nameInput, featureName: this.featureNameInput, doid: this.doidInput, + diseaseAlias: this.diseaseAliasInput, }) .then(() => this.scrollIndex$.next(0)) this.cdr.detectChanges() } - trackByIndex(_: number, data: Maybe): Maybe { + trackByIndex( + _: number, + data: Maybe + ): Maybe { return data?.id } } diff --git a/client/src/app/components/diseases/diseases-table/diseases-table.module.ts b/client/src/app/components/diseases/diseases-table/diseases-table.module.ts index 795e86c46..a24268013 100644 --- a/client/src/app/components/diseases/diseases-table/diseases-table.module.ts +++ b/client/src/app/components/diseases/diseases-table/diseases-table.module.ts @@ -19,6 +19,7 @@ import { NzToolTipModule } from 'ng-zorro-antd/tooltip' import { NzTypographyModule } from 'ng-zorro-antd/typography' import { CvcDiseaseTagModule } from '../cvc-disease-tag/cvc-disease-tag.module' import { CvcDiseasesTableComponent } from './diseases-table.component' +import { CvcPlainTagOverflowModule } from '@app/components/shared/plain-tag-overflow/plain-tag-overflow.module' @NgModule({ declarations: [CvcDiseasesTableComponent], @@ -46,6 +47,7 @@ import { CvcDiseasesTableComponent } from './diseases-table.component' CvcTableCountsModule, CvcTableScrollModule, CvcTagOverflowModule, + CvcPlainTagOverflowModule, ], exports: [CvcDiseasesTableComponent], }) diff --git a/client/src/app/components/diseases/diseases-table/diseases-table.query.gql b/client/src/app/components/diseases/diseases-table/diseases-table.query.gql index 3e94e6d47..dccd4e5b4 100644 --- a/client/src/app/components/diseases/diseases-table/diseases-table.query.gql +++ b/client/src/app/components/diseases/diseases-table/diseases-table.query.gql @@ -6,6 +6,7 @@ query BrowseDiseases( $sortBy: DiseasesSort $name: String $doid: String + $diseaseAlias: String $featureName: String ) { browseDiseases( @@ -16,6 +17,7 @@ query BrowseDiseases( sortBy: $sortBy name: $name doid: $doid + diseaseAlias: $diseaseAlias featureName: $featureName ) { pageInfo { @@ -53,4 +55,5 @@ fragment BrowseDiseaseRowFields on BrowseDisease { featureCount link deprecated + diseaseAliases } diff --git a/client/src/app/generated/civic.apollo.ts b/client/src/app/generated/civic.apollo.ts index 14854aae5..33f801d1d 100644 --- a/client/src/app/generated/civic.apollo.ts +++ b/client/src/app/generated/civic.apollo.ts @@ -7155,13 +7155,14 @@ export type BrowseDiseasesQueryVariables = Exact<{ sortBy?: InputMaybe; name?: InputMaybe; doid?: InputMaybe; + diseaseAlias?: InputMaybe; featureName?: InputMaybe; }>; -export type BrowseDiseasesQuery = { __typename: 'Query', browseDiseases: { __typename: 'BrowseDiseaseConnection', lastUpdated: any, totalCount: number, filteredCount: number, pageCount: number, pageInfo: { __typename: 'PageInfo', endCursor?: string | undefined, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | undefined }, edges: Array<{ __typename: 'BrowseDiseaseEdge', cursor: string, node?: { __typename: 'BrowseDisease', id: number, name: string, doid?: string | undefined, diseaseUrl?: string | undefined, assertionCount: number, evidenceItemCount: number, variantCount: number, featureCount: number, link: string, deprecated: boolean, features: Array<{ __typename: 'LinkableFeature', id: number, name: string, link: string }> } | undefined }> } }; +export type BrowseDiseasesQuery = { __typename: 'Query', browseDiseases: { __typename: 'BrowseDiseaseConnection', lastUpdated: any, totalCount: number, filteredCount: number, pageCount: number, pageInfo: { __typename: 'PageInfo', endCursor?: string | undefined, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | undefined }, edges: Array<{ __typename: 'BrowseDiseaseEdge', cursor: string, node?: { __typename: 'BrowseDisease', id: number, name: string, doid?: string | undefined, diseaseUrl?: string | undefined, assertionCount: number, evidenceItemCount: number, variantCount: number, featureCount: number, link: string, deprecated: boolean, diseaseAliases?: Array | undefined, features: Array<{ __typename: 'LinkableFeature', id: number, name: string, link: string }> } | undefined }> } }; -export type BrowseDiseaseRowFieldsFragment = { __typename: 'BrowseDisease', id: number, name: string, doid?: string | undefined, diseaseUrl?: string | undefined, assertionCount: number, evidenceItemCount: number, variantCount: number, featureCount: number, link: string, deprecated: boolean, features: Array<{ __typename: 'LinkableFeature', id: number, name: string, link: string }> }; +export type BrowseDiseaseRowFieldsFragment = { __typename: 'BrowseDisease', id: number, name: string, doid?: string | undefined, diseaseUrl?: string | undefined, assertionCount: number, evidenceItemCount: number, variantCount: number, featureCount: number, link: string, deprecated: boolean, diseaseAliases?: Array | undefined, features: Array<{ __typename: 'LinkableFeature', id: number, name: string, link: string }> }; export type EventFeedCountQueryVariables = Exact<{ subject?: InputMaybe; @@ -9259,6 +9260,7 @@ export const BrowseDiseaseRowFieldsFragmentDoc = gql` featureCount link deprecated + diseaseAliases } `; export const EventFeedNodeFragmentDoc = gql` @@ -12235,7 +12237,7 @@ export const DiseasePopoverDocument = gql` } } export const BrowseDiseasesDocument = gql` - query BrowseDiseases($first: Int, $last: Int, $before: String, $after: String, $sortBy: DiseasesSort, $name: String, $doid: String, $featureName: String) { + query BrowseDiseases($first: Int, $last: Int, $before: String, $after: String, $sortBy: DiseasesSort, $name: String, $doid: String, $diseaseAlias: String, $featureName: String) { browseDiseases( first: $first last: $last @@ -12244,6 +12246,7 @@ export const BrowseDiseasesDocument = gql` sortBy: $sortBy name: $name doid: $doid + diseaseAlias: $diseaseAlias featureName: $featureName ) { pageInfo {