diff --git a/client/src/app/components/activities/activity-feed/feed-filters/feed-filters.component.html b/client/src/app/components/activities/activity-feed/feed-filters/feed-filters.component.html index e3b7a06a1..c9c0bab4e 100644 --- a/client/src/app/components/activities/activity-feed/feed-filters/feed-filters.component.html +++ b/client/src/app/components/activities/activity-feed/feed-filters/feed-filters.component.html @@ -114,39 +114,10 @@ filterTitle; context: { $implicit: 'Participating User', value: userId() } "> - - - - - - - - {{ selected.nzLabel }} - - + } @@ -160,43 +131,14 @@ value: organizationId(), } "> - - - - - - - - {{ selected.nzLabel }} - - + } Sort Direction - diff --git a/client/src/app/components/activities/activity-feed/feed-filters/feed-filters.component.ts b/client/src/app/components/activities/activity-feed/feed-filters/feed-filters.component.ts index 50ca82ed9..4a52b14ed 100644 --- a/client/src/app/components/activities/activity-feed/feed-filters/feed-filters.component.ts +++ b/client/src/app/components/activities/activity-feed/feed-filters/feed-filters.component.ts @@ -27,6 +27,9 @@ import { DateSortColumns, Maybe, SortDirection, + UserFilterSearchGQL, + UserFilterSearchQuery, + UserFilterSearchQueryVariables, } from '@app/generated/civic.apollo' import { CommonModule, KeyValuePipe } from '@angular/common' import { FormsModule } from '@angular/forms' @@ -40,12 +43,19 @@ import { disableDates } from '../activity-feed.functions' import { toObservable, toSignal } from '@angular/core/rxjs-interop' import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy' import { tag } from 'rxjs-spy/operators' -import { distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators' -import { timer, filter, of } from 'rxjs' -import { isNonNullObject } from '@apollo/client/utilities' +import { + distinctUntilChanged, + map, + skip, + startWith, + switchMap, +} from 'rxjs/operators' +import { timer, filter, of, Subject, from } from 'rxjs' import { isNonNulled } from 'rxjs-etc' import { NzButtonModule } from 'ng-zorro-antd/button' import { NzAlertModule } from 'ng-zorro-antd/alert' +import { CvcUserFilterSelect } from './user-filter-select/user-filter-select.component' +import { CvcOrgFilterSelect } from './org-filter-select/org-filter-select.component' export const defaultFilters = {} @@ -65,6 +75,8 @@ export const defaultFilters = {} NzSelectModule, NzDatePickerModule, CvcPipesModule, + CvcUserFilterSelect, + CvcOrgFilterSelect, ], templateUrl: './feed-filters.component.html', styleUrls: ['./feed-filters.component.less'], @@ -118,7 +130,17 @@ export class CvcActivityFeedFilterSelects implements OnInit { sortByDirection: this.sortByDirection(), }) }) - + /** + * Observable that emits the count of new activities since the last refresh. + * + * Behavior: + * - Only activates if cvcCheckInterval > 0, else emits 0 + * - Polls the API at the specified interval (cvcCheckInterval in seconds) + * - Uses the current filter settings but only looks for activities after the last refresh + * - Emits 0 initially and then the count of new activities + * - Only emits when the count changes (uses distinctUntilChanged) + * - Resets to 0 when filters change via cvcRefreshChanges + */ const newActivities$ = toObservable(this.cvcRefreshChanges).pipe( filter(isNonNulled), switchMap((refetchEvent) => { @@ -151,6 +173,7 @@ export class CvcActivityFeedFilterSelects implements OnInit { ) this.newActivities = toSignal(newActivities$, { initialValue: 0 }) } + ngOnInit(): void { this.eventType = signal(this.cvcFilters().activityType) this.subjectType = signal(this.cvcFilters().subjectType) diff --git a/client/src/app/components/activities/activity-feed/feed-filters/org-filter-select/org-filter-select.component.html b/client/src/app/components/activities/activity-feed/feed-filters/org-filter-select/org-filter-select.component.html new file mode 100644 index 000000000..1b88c434c --- /dev/null +++ b/client/src/app/components/activities/activity-feed/feed-filters/org-filter-select/org-filter-select.component.html @@ -0,0 +1,42 @@ + + + + + + + + + + {{ selected.nzLabel }} + + + + No organizationsfound matching "{{ onSearch() }}" + diff --git a/client/src/app/components/activities/activity-feed/feed-filters/org-filter-select/org-filter-select.component.less b/client/src/app/components/activities/activity-feed/feed-filters/org-filter-select/org-filter-select.component.less new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/app/components/activities/activity-feed/feed-filters/org-filter-select/org-filter-select.component.ts b/client/src/app/components/activities/activity-feed/feed-filters/org-filter-select/org-filter-select.component.ts new file mode 100644 index 000000000..c69067b12 --- /dev/null +++ b/client/src/app/components/activities/activity-feed/feed-filters/org-filter-select/org-filter-select.component.ts @@ -0,0 +1,70 @@ +import { Component, input, model, Signal } from '@angular/core' +import { ActivityFeedFilterOptions } from '../../activity-feed.types' +import { CvcPipesModule } from '@app/core/pipes/pipes.module' +import { CommonModule } from '@angular/common' +import { NzSelectModule } from 'ng-zorro-antd/select' +import { NzIconModule } from 'ng-zorro-antd/icon' +import { FormsModule } from '@angular/forms' +import { + BrowseOrganization, + Organization, + OrgFilterSearchGQL, + OrgFilterSearchQuery, + OrgFilterSearchQueryVariables, +} from '@app/generated/civic.apollo' +import { from, map, Subject, switchMap } from 'rxjs' +import { QueryRef } from 'apollo-angular' +import { tag } from 'rxjs-spy/operators' +import { toSignal } from '@angular/core/rxjs-interop' + +@Component({ + selector: 'cvc-org-filter-select', + standalone: true, + imports: [ + CommonModule, + FormsModule, + NzIconModule, + NzSelectModule, + CvcPipesModule, + ], + templateUrl: './org-filter-select.component.html', + styleUrl: './org-filter-select.component.less', +}) +export class CvcOrgFilterSelect { + cvcParticipatingOrganizations = + input.required() + cvcOrganizationId = model.required() + + onSearch$: Subject + onSearch: Signal + queryRef!: QueryRef + filteredOrganizations: Signal + + constructor(private gql: OrgFilterSearchGQL) { + this.onSearch$ = new Subject() + const filteredOrganizations$ = this.onSearch$.pipe( + tag(`filteredOrganizations$`), + switchMap((nameStr) => { + const query = { name: nameStr, first: 25 } + if (this.queryRef) { + const refetch = this.queryRef.refetch({ name: nameStr }) + return from(refetch) + } else { + this.queryRef = this.gql.watch({ name: nameStr }) + return this.queryRef.valueChanges + } + }), + map( + (result) => + result.data?.organizations.edges.map( + (e) => e.node! as BrowseOrganization + ) ?? [] + ), + tag(`${this.constructor.name} filteredOrganizations$ after`) + ) + this.filteredOrganizations = toSignal(filteredOrganizations$, { + initialValue: [], + }) + this.onSearch = toSignal(this.onSearch$, { initialValue: '' }) + } +} diff --git a/client/src/app/components/activities/activity-feed/feed-filters/org-filter-select/org-filter-select.query.gql b/client/src/app/components/activities/activity-feed/feed-filters/org-filter-select/org-filter-select.query.gql new file mode 100644 index 000000000..6aa74b8dc --- /dev/null +++ b/client/src/app/components/activities/activity-feed/feed-filters/org-filter-select/org-filter-select.query.gql @@ -0,0 +1,16 @@ +query OrgFilterSearch($name: String) { + organizations(name: $name) { + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + edges { + node { + id + name + } + } + } +} diff --git a/client/src/app/components/activities/activity-feed/feed-filters/user-filter-select/user-filter-select.component.html b/client/src/app/components/activities/activity-feed/feed-filters/user-filter-select/user-filter-select.component.html new file mode 100644 index 000000000..e2bde4797 --- /dev/null +++ b/client/src/app/components/activities/activity-feed/feed-filters/user-filter-select/user-filter-select.component.html @@ -0,0 +1,43 @@ + + + + + + + + + + {{ selected.nzLabel }} + + + + No users found matching "{{ onSearch() }}" + diff --git a/client/src/app/components/activities/activity-feed/feed-filters/user-filter-select/user-filter-select.component.less b/client/src/app/components/activities/activity-feed/feed-filters/user-filter-select/user-filter-select.component.less new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/app/components/activities/activity-feed/feed-filters/user-filter-select/user-filter-select.component.ts b/client/src/app/components/activities/activity-feed/feed-filters/user-filter-select/user-filter-select.component.ts new file mode 100644 index 000000000..81142cdf4 --- /dev/null +++ b/client/src/app/components/activities/activity-feed/feed-filters/user-filter-select/user-filter-select.component.ts @@ -0,0 +1,78 @@ +import { + Component, + input, + model, + output, + Signal, + WritableSignal, +} from '@angular/core' +import { ActivityFeedFilterOptions } from '../../activity-feed.types' +import { NzSelectModule } from 'ng-zorro-antd/select' +import { FormsModule } from '@angular/forms' +import { CvcPipesModule } from '@app/core/pipes/pipes.module' +import { NzIconModule } from 'ng-zorro-antd/icon' +import { CommonModule } from '@angular/common' +import { from, map, skip, startWith, Subject, switchMap } from 'rxjs' +import { + BrowseUser, + User, + UserFilterSearchGQL, + UserFilterSearchQuery, + UserFilterSearchQueryVariables, +} from '@app/generated/civic.apollo' +import { QueryRef } from 'apollo-angular' +import { tag } from 'rxjs-spy/operators' +import { toSignal } from '@angular/core/rxjs-interop' + +@Component({ + selector: 'cvc-user-filter-select', + standalone: true, + imports: [ + CommonModule, + FormsModule, + NzIconModule, + NzSelectModule, + CvcPipesModule, + ], + templateUrl: './user-filter-select.component.html', + styleUrl: './user-filter-select.component.less', +}) +export class CvcUserFilterSelect { + cvcUniqueParticipants = + input.required() + cvcUserId = model.required() + + onSearch$: Subject + onSearch: Signal + queryRef!: QueryRef + filteredUsers: Signal + + constructor(private gql: UserFilterSearchGQL) { + this.onSearch$ = new Subject() + const filteredUser$ = this.onSearch$.pipe( + tag(`filteredUser$`), + // skip(1), + // filter(isNonNulled), + switchMap((nameStr) => { + const query = { + name: nameStr, + first: 25, + } + if (this.queryRef) { + const refetch = this.queryRef.refetch({ name: nameStr }) + return from(refetch) + } else { + this.queryRef = this.gql.watch({ name: nameStr }) + return this.queryRef.valueChanges + } + }), + map( + (result) => + result.data?.users.edges.map((e) => e.node! as BrowseUser) ?? [] + ), + tag(`${this.constructor.name} filteredUser$ after`) + ) + this.filteredUsers = toSignal(filteredUser$, { initialValue: [] }) + this.onSearch = toSignal(this.onSearch$, { initialValue: '' }) + } +} diff --git a/client/src/app/components/activities/activity-feed/feed-filters/user-filter-select/user-filter-select.query.gql b/client/src/app/components/activities/activity-feed/feed-filters/user-filter-select/user-filter-select.query.gql new file mode 100644 index 000000000..3b6f7bdba --- /dev/null +++ b/client/src/app/components/activities/activity-feed/feed-filters/user-filter-select/user-filter-select.query.gql @@ -0,0 +1,19 @@ +query UserFilterSearch($name: String) { + users(name: $name) { + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + edges { + node { + id + displayName + name + username + role + } + } + } +} diff --git a/client/src/app/components/genes/my-gene-info/my-gene-info.component.html b/client/src/app/components/genes/my-gene-info/my-gene-info.component.html index 29fdf53e7..b4000728f 100644 --- a/client/src/app/components/genes/my-gene-info/my-gene-info.component.html +++ b/client/src/app/components/genes/my-gene-info/my-gene-info.component.html @@ -25,7 +25,23 @@ {{ info.symbol }} (ID: {{ info._id }}) - {{ info.uniprot['Swiss-Prot'] }} + @if ( + info.uniprot['Swiss-Prot'] && info.uniprot['Swiss-Prot'].trim() + ) { + + {{ info.uniprot['Swiss-Prot'] }} + + } @else { + N/A + } - @@ -52,12 +68,20 @@ {{ info.alias.join(', ') }} -

+

{{ info.interproList.join(', ') }}

-

+

{{ info.pathwayList.join(', ') }}

diff --git a/client/src/app/components/genes/my-gene-info/my-gene-info.module.ts b/client/src/app/components/genes/my-gene-info/my-gene-info.module.ts index 1e9fb2e78..754f9d29e 100644 --- a/client/src/app/components/genes/my-gene-info/my-gene-info.module.ts +++ b/client/src/app/components/genes/my-gene-info/my-gene-info.module.ts @@ -7,6 +7,7 @@ import { NzGridModule } from 'ng-zorro-antd/grid' import { NzTableModule } from 'ng-zorro-antd/table' import { NzTypographyModule } from 'ng-zorro-antd/typography' import { NzDescriptionsModule } from 'ng-zorro-antd/descriptions' +import { CvcLinkTagModule } from '@app/components/shared/link-tag/link-tag.module' @NgModule({ declarations: [CvcMyGeneInfoComponent], @@ -19,6 +20,7 @@ import { NzDescriptionsModule } from 'ng-zorro-antd/descriptions' NzTableModule, NzTypographyModule, NzDescriptionsModule, + CvcLinkTagModule, ], exports: [CvcMyGeneInfoComponent], }) diff --git a/client/src/app/components/molecular-profiles/molecular-profiles-menu/molecular-profiles-menu.component.ts b/client/src/app/components/molecular-profiles/molecular-profiles-menu/molecular-profiles-menu.component.ts index 6517b5ac2..33276afdf 100644 --- a/client/src/app/components/molecular-profiles/molecular-profiles-menu/molecular-profiles-menu.component.ts +++ b/client/src/app/components/molecular-profiles/molecular-profiles-menu/molecular-profiles-menu.component.ts @@ -7,7 +7,7 @@ import { MolecularProfileConnection, MolecularProfileMenuQueryVariables, MolecularProfileMenuGQL, - MolecularProfileDisplayFilter, + AssociatedEvidenceStatusFilter, } from '@app/generated/civic.apollo' import { map, debounceTime, filter, startWith } from 'rxjs/operators' import { Observable, Subject } from 'rxjs' @@ -32,8 +32,8 @@ export class CvcMolecularProfilesMenuComponent implements OnInit { loading$?: Observable; mpNameFilter: Maybe - statusFilter: MolecularProfileDisplayFilter = - MolecularProfileDisplayFilter.All + statusFilter: AssociatedEvidenceStatusFilter = + AssociatedEvidenceStatusFilter.All private debouncedQuery = new Subject() private result$!: Observable> @@ -91,7 +91,7 @@ export class CvcMolecularProfilesMenuComponent implements OnInit { this.debouncedQuery.next() } - onMolecularProfileStatusFilterChanged(filter: MolecularProfileDisplayFilter) { + onMolecularProfileStatusFilterChanged(filter: AssociatedEvidenceStatusFilter) { this.queryRef$.refetch({ first: this.pageSize, evidenceStatusFilter: filter diff --git a/client/src/app/components/molecular-profiles/molecular-profiles-menu/molecular-profiles-menu.gql b/client/src/app/components/molecular-profiles/molecular-profiles-menu/molecular-profiles-menu.gql index 9d4075285..4722120af 100644 --- a/client/src/app/components/molecular-profiles/molecular-profiles-menu/molecular-profiles-menu.gql +++ b/client/src/app/components/molecular-profiles/molecular-profiles-menu/molecular-profiles-menu.gql @@ -6,7 +6,7 @@ query MolecularProfileMenu( $last: Int $before: String $after: String - $evidenceStatusFilter: MolecularProfileDisplayFilter + $evidenceStatusFilter: AssociatedEvidenceStatusFilter ) { molecularProfiles( geneId: $geneId diff --git a/client/src/app/generated/civic.apollo.ts b/client/src/app/generated/civic.apollo.ts index 3db9875b9..255fe12d6 100644 --- a/client/src/app/generated/civic.apollo.ts +++ b/client/src/app/generated/civic.apollo.ts @@ -129,6 +129,7 @@ export enum ActivitySubjectInput { Assertion = 'ASSERTION', Comment = 'COMMENT', EvidenceItem = 'EVIDENCE_ITEM', + ExonCoordinate = 'EXON_COORDINATE', Feature = 'FEATURE', Flag = 'FLAG', MolecularProfile = 'MOLECULAR_PROFILE', @@ -137,6 +138,7 @@ export enum ActivitySubjectInput { Source = 'SOURCE', SourceSuggestion = 'SOURCE_SUGGESTION', Variant = 'VARIANT', + VariantCoordinate = 'VARIANT_COORDINATE', VariantGroup = 'VARIANT_GROUP' } @@ -488,6 +490,17 @@ export enum AssertionType { Prognostic = 'PROGNOSTIC' } +export enum AssociatedEvidenceStatusFilter { + /** Apply no status filter to an entity in order to display all entities regardless of attached evidence status. */ + All = 'ALL', + /** Apply filter to an entity to display only those which have at least one accepted associated evidence item. */ + WithAccepted = 'WITH_ACCEPTED', + /** Apply filter to an entity to display only those which have at least one accepted or submitted associated evidence item. */ + WithAcceptedOrSubmitted = 'WITH_ACCEPTED_OR_SUBMITTED', + /** Apply filter to an entity to display only those which have at least one submitted associated evidence item. */ + WithSubmitted = 'WITH_SUBMITTED' +} + export enum BooleanOperator { And = 'AND', Or = 'OR' @@ -3963,17 +3976,6 @@ export enum MolecularProfileDeprecationReasonMutationInput { Other = 'OTHER' } -export enum MolecularProfileDisplayFilter { - /** Display all molecular profiles regardless of attached evidence status. */ - All = 'ALL', - /** Display only molecular profiles which have at least one accepted evidence item. */ - WithAccepted = 'WITH_ACCEPTED', - /** Display only molecular profiles which have evidence in either an accepted or submitted state. */ - WithAcceptedOrSubmitted = 'WITH_ACCEPTED_OR_SUBMITTED', - /** Display molecular profiles which have at least one submitted evidence item. */ - WithSubmitted = 'WITH_SUBMITTED' -} - /** An edge in a connection. */ export type MolecularProfileEdge = { __typename: 'MolecularProfileEdge'; @@ -5251,6 +5253,7 @@ export type QueryEvidenceItemsArgs = { evidenceType?: InputMaybe; first?: InputMaybe; id?: InputMaybe; + ids?: InputMaybe>; last?: InputMaybe; molecularProfileId?: InputMaybe; molecularProfileName?: InputMaybe; @@ -5277,6 +5280,7 @@ export type QueryFactorArgs = { export type QueryFactorsArgs = { after?: InputMaybe; before?: InputMaybe; + evidenceStatusFilter?: InputMaybe; first?: InputMaybe; last?: InputMaybe; name?: InputMaybe>; @@ -5321,8 +5325,7 @@ export type QueryFusionArgs = { export type QueryFusionsArgs = { after?: InputMaybe; before?: InputMaybe; - entrezIds?: InputMaybe>; - entrezSymbols?: InputMaybe>; + evidenceStatusFilter?: InputMaybe; first?: InputMaybe; genePartnerId?: InputMaybe; last?: InputMaybe; @@ -5340,6 +5343,7 @@ export type QueryGenesArgs = { before?: InputMaybe; entrezIds?: InputMaybe>; entrezSymbols?: InputMaybe>; + evidenceStatusFilter?: InputMaybe; first?: InputMaybe; last?: InputMaybe; }; @@ -5354,7 +5358,7 @@ export type QueryMolecularProfilesArgs = { after?: InputMaybe; alleleRegistryId?: InputMaybe; before?: InputMaybe; - evidenceStatusFilter?: InputMaybe; + evidenceStatusFilter?: InputMaybe; featureId?: InputMaybe; first?: InputMaybe; geneId?: InputMaybe; @@ -7850,6 +7854,20 @@ export type ActivityFeedUpdatesQueryVariables = Exact<{ export type ActivityFeedUpdatesQuery = { __typename: 'Query', activities: { __typename: 'ActivityInterfaceConnection', pageCount: number, totalCount: number, unfilteredCount: number, pageInfo: { __typename: 'PageInfo', startCursor?: string | undefined, endCursor?: string | undefined, hasNextPage: boolean, hasPreviousPage: boolean } } }; +export type OrgFilterSearchQueryVariables = Exact<{ + name?: InputMaybe; +}>; + + +export type OrgFilterSearchQuery = { __typename: 'Query', organizations: { __typename: 'BrowseOrganizationConnection', pageInfo: { __typename: 'PageInfo', endCursor?: string | undefined, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | undefined }, edges: Array<{ __typename: 'BrowseOrganizationEdge', node?: { __typename: 'BrowseOrganization', id: number, name: string } | undefined }> } }; + +export type UserFilterSearchQueryVariables = Exact<{ + name?: InputMaybe; +}>; + + +export type UserFilterSearchQuery = { __typename: 'Query', users: { __typename: 'BrowseUserConnection', pageInfo: { __typename: 'PageInfo', endCursor?: string | undefined, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | undefined }, edges: Array<{ __typename: 'BrowseUserEdge', node?: { __typename: 'BrowseUser', id: number, displayName: string, name?: string | undefined, username: string, role: UserRole } | undefined }> } }; + export type AcceptRevisionsActivityDetailFragment = { __typename: 'AcceptRevisionsActivity', id: number, verbiage: string, createdAt: any, parsedNote: Array<{ __typename: 'CommentTagSegment', entityId: number, displayName: string, tagType: TaggableEntity, link: string, revisionSetId?: number | undefined, feature?: { __typename: 'LinkableFeature', id: number, name: string, link: string, deprecated: boolean, flagged: boolean } | undefined } | { __typename: 'CommentTagSegmentFlagged', entityId: number, displayName: string, tagType: TaggableEntity, flagged: boolean, link: string, revisionSetId?: number | undefined, feature?: { __typename: 'LinkableFeature', id: number, name: string, link: string, deprecated: boolean, flagged: boolean } | undefined } | { __typename: 'CommentTagSegmentFlaggedAndDeprecated', entityId: number, displayName: string, tagType: TaggableEntity, flagged: boolean, deprecated: boolean, link: string, revisionSetId?: number | undefined, feature?: { __typename: 'LinkableFeature', id: number, name: string, link: string, deprecated: boolean, flagged: boolean } | undefined } | { __typename: 'CommentTagSegmentFlaggedAndWithStatus', entityId: number, displayName: string, tagType: TaggableEntity, status: EvidenceStatus, flagged: boolean, link: string, revisionSetId?: number | undefined, feature?: { __typename: 'LinkableFeature', id: number, name: string, link: string, deprecated: boolean, flagged: boolean } | undefined } | { __typename: 'CommentTextSegment', text: string } | { __typename: 'User', id: number, username: string, displayName: string, name?: string | undefined, role: UserRole, profileImagePath?: string | undefined, organizations: Array<{ __typename: 'Organization', id: number, name: string, profileImagePath?: string | undefined }> }>, revisions: Array<{ __typename: 'Revision', id: number, name: string, status: RevisionStatus, currentValue?: any | undefined, suggestedValue?: any | undefined, fieldName: string, link: string, linkoutData: { __typename: 'LinkoutData', name: string, diffValue: { __typename: 'ObjectFieldDiff', currentObjects: Array<{ __typename: 'ModeratedObjectField', id: number, displayName?: string | undefined, displayType?: string | undefined, entityType: string, link?: string | undefined, deleted: boolean, deprecated?: boolean | undefined, flagged?: boolean | undefined, feature?: { __typename: 'LinkableFeature', link: string, id: number, name: string, deprecated: boolean, flagged: boolean } | undefined }>, addedObjects: Array<{ __typename: 'ModeratedObjectField', id: number, displayName?: string | undefined, displayType?: string | undefined, entityType: string, link?: string | undefined, deleted: boolean, deprecated?: boolean | undefined, flagged?: boolean | undefined, feature?: { __typename: 'LinkableFeature', link: string, id: number, name: string, deprecated: boolean, flagged: boolean } | undefined }>, removedObjects: Array<{ __typename: 'ModeratedObjectField', id: number, displayName?: string | undefined, displayType?: string | undefined, entityType: string, link?: string | undefined, deleted: boolean, deprecated?: boolean | undefined, flagged?: boolean | undefined, feature?: { __typename: 'LinkableFeature', link: string, id: number, name: string, deprecated: boolean, flagged: boolean } | undefined }>, keptObjects: Array<{ __typename: 'ModeratedObjectField', id: number, displayName?: string | undefined, displayType?: string | undefined, entityType: string, link?: string | undefined, deleted: boolean, deprecated?: boolean | undefined, flagged?: boolean | undefined, feature?: { __typename: 'LinkableFeature', link: string, id: number, name: string, deprecated: boolean, flagged: boolean } | undefined }>, suggestedObjects: Array<{ __typename: 'ModeratedObjectField', id: number, displayName?: string | undefined, displayType?: string | undefined, entityType: string, link?: string | undefined, deleted: boolean, deprecated?: boolean | undefined, flagged?: boolean | undefined, feature?: { __typename: 'LinkableFeature', link: string, id: number, name: string, deprecated: boolean, flagged: boolean } | undefined }> } | { __typename: 'ScalarFieldDiff', left: string, right: string } } }>, supersededRevisions: Array<{ __typename: 'Revision', id: number, link: string, name: string, fieldName: string, createdAt: any, creationActivity?: { __typename: 'SuggestRevisionSetActivity', user: { __typename: 'User', displayName: string, profileImagePath?: string | undefined, id: number, role: UserRole } } | undefined }>, organization?: { __typename: 'Organization', id: number, name: string } | undefined, user: { __typename: 'User', id: number, displayName: string, role: UserRole }, subject: { __typename: 'Assertion', id: number, name: string, link: string } | { __typename: 'Comment', deleted: boolean, deletedAt?: any | undefined, id: number, name: string, link: string, commentable: { __typename: 'Assertion', id: number, name: string, link: string } | { __typename: 'EvidenceItem', id: number, name: string, link: string } | { __typename: 'Factor', id: number, name: string, link: string } | { __typename: 'FactorVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'Feature', id: number, name: string, link: string } | { __typename: 'Flag', id: number, name: string, link: string } | { __typename: 'Fusion', id: number, name: string, link: string } | { __typename: 'FusionVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'Gene', id: number, name: string, link: string } | { __typename: 'GeneVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'MolecularProfile', id: number, name: string, link: string } | { __typename: 'Revision', id: number, name: string, link: string } | { __typename: 'Source', id: number, name: string, link: string } | { __typename: 'SourcePopover', id: number, name: string, link: string } | { __typename: 'Variant', id: number, name: string, link: string } | { __typename: 'VariantGroup', id: number, name: string, link: string } } | { __typename: 'EvidenceItem', id: number, name: string, link: string } | { __typename: 'ExonCoordinate', id: number, name: string, link: string } | { __typename: 'Factor', id: number, name: string, link: string } | { __typename: 'FactorVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'Feature', id: number, name: string, link: string } | { __typename: 'Flag', id: number, name: string, link: string } | { __typename: 'Fusion', id: number, name: string, link: string } | { __typename: 'FusionVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'Gene', id: number, name: string, link: string } | { __typename: 'GeneVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'MolecularProfile', id: number, name: string, link: string } | { __typename: 'Revision', id: number, name: string, link: string } | { __typename: 'RevisionSet', id: number, name: string, link: string } | { __typename: 'Source', id: number, name: string, link: string } | { __typename: 'SourcePopover', id: number, name: string, link: string } | { __typename: 'SourceSuggestion', id: number, name: string, link: string } | { __typename: 'Variant', id: number, name: string, link: string } | { __typename: 'VariantCoordinate', id: number, name: string, link: string } | { __typename: 'VariantGroup', id: number, name: string, link: string }, events: Array<{ __typename: 'Event', id: number, createdAt: any, action: EventAction, originatingObject?: { __typename: 'Assertion', id: number, name: string, link: string } | { __typename: 'Comment', id: number, name: string, link: string } | { __typename: 'EvidenceItem', id: number, name: string, link: string } | { __typename: 'Factor', id: number, name: string, link: string } | { __typename: 'FactorVariant', id: number, name: string, link: string } | { __typename: 'Feature', id: number, name: string, link: string } | { __typename: 'Flag', id: number, name: string, link: string } | { __typename: 'Fusion', id: number, name: string, link: string } | { __typename: 'FusionVariant', id: number, name: string, link: string } | { __typename: 'Gene', id: number, name: string, link: string } | { __typename: 'GeneVariant', id: number, name: string, link: string } | { __typename: 'MolecularProfile', id: number, name: string, link: string } | { __typename: 'Revision', id: number, name: string, link: string } | { __typename: 'SourceSuggestion', id: number, name: string, link: string } | { __typename: 'Variant', id: number, name: string, link: string } | undefined, originatingUser: { __typename: 'User', id: number, displayName: string } }> }; export type CommentActivityDetailFragment = { __typename: 'CommentActivity', id: number, verbiage: string, createdAt: any, comment: { __typename: 'Comment', id: number, name: string, link: string, deleted: boolean, deletedAt?: any | undefined, title?: string | undefined, comment: string, createdAt: any, commentable: { __typename: 'Assertion', id: number, name: string, link: string } | { __typename: 'EvidenceItem', id: number, name: string, link: string } | { __typename: 'Factor', id: number, name: string, link: string } | { __typename: 'FactorVariant', id: number, name: string, link: string } | { __typename: 'Feature', id: number, name: string, link: string } | { __typename: 'Flag', id: number, name: string, link: string } | { __typename: 'Fusion', id: number, name: string, link: string } | { __typename: 'FusionVariant', id: number, name: string, link: string } | { __typename: 'Gene', id: number, name: string, link: string } | { __typename: 'GeneVariant', id: number, name: string, link: string } | { __typename: 'MolecularProfile', id: number, name: string, link: string } | { __typename: 'Revision', id: number, name: string, link: string } | { __typename: 'Source', id: number, name: string, link: string } | { __typename: 'SourcePopover', id: number, name: string, link: string } | { __typename: 'Variant', id: number, name: string, link: string } | { __typename: 'VariantGroup', id: number, name: string, link: string }, commenter: { __typename: 'User', id: number, username: string, displayName: string, name?: string | undefined, role: UserRole, profileImagePath?: string | undefined, organizations: Array<{ __typename: 'Organization', id: number, name: string, profileImagePath?: string | undefined }> }, parsedComment: Array<{ __typename: 'CommentTagSegment', entityId: number, displayName: string, tagType: TaggableEntity, link: string, revisionSetId?: number | undefined, feature?: { __typename: 'LinkableFeature', id: number, name: string, link: string, deprecated: boolean, flagged: boolean } | undefined } | { __typename: 'CommentTagSegmentFlagged', entityId: number, displayName: string, tagType: TaggableEntity, flagged: boolean, link: string, revisionSetId?: number | undefined, feature?: { __typename: 'LinkableFeature', id: number, name: string, link: string, deprecated: boolean, flagged: boolean } | undefined } | { __typename: 'CommentTagSegmentFlaggedAndDeprecated', entityId: number, displayName: string, tagType: TaggableEntity, flagged: boolean, deprecated: boolean, link: string, revisionSetId?: number | undefined, feature?: { __typename: 'LinkableFeature', id: number, name: string, link: string, deprecated: boolean, flagged: boolean } | undefined } | { __typename: 'CommentTagSegmentFlaggedAndWithStatus', entityId: number, displayName: string, tagType: TaggableEntity, status: EvidenceStatus, flagged: boolean, link: string, revisionSetId?: number | undefined, feature?: { __typename: 'LinkableFeature', id: number, name: string, link: string, deprecated: boolean, flagged: boolean } | undefined } | { __typename: 'CommentTextSegment', text: string } | { __typename: 'User', id: number, username: string, displayName: string, name?: string | undefined, role: UserRole, profileImagePath?: string | undefined, organizations: Array<{ __typename: 'Organization', id: number, name: string, profileImagePath?: string | undefined }> }> }, organization?: { __typename: 'Organization', id: number, name: string } | undefined, user: { __typename: 'User', id: number, displayName: string, role: UserRole }, subject: { __typename: 'Assertion', id: number, name: string, link: string } | { __typename: 'Comment', deleted: boolean, deletedAt?: any | undefined, id: number, name: string, link: string, commentable: { __typename: 'Assertion', id: number, name: string, link: string } | { __typename: 'EvidenceItem', id: number, name: string, link: string } | { __typename: 'Factor', id: number, name: string, link: string } | { __typename: 'FactorVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'Feature', id: number, name: string, link: string } | { __typename: 'Flag', id: number, name: string, link: string } | { __typename: 'Fusion', id: number, name: string, link: string } | { __typename: 'FusionVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'Gene', id: number, name: string, link: string } | { __typename: 'GeneVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'MolecularProfile', id: number, name: string, link: string } | { __typename: 'Revision', id: number, name: string, link: string } | { __typename: 'Source', id: number, name: string, link: string } | { __typename: 'SourcePopover', id: number, name: string, link: string } | { __typename: 'Variant', id: number, name: string, link: string } | { __typename: 'VariantGroup', id: number, name: string, link: string } } | { __typename: 'EvidenceItem', id: number, name: string, link: string } | { __typename: 'ExonCoordinate', id: number, name: string, link: string } | { __typename: 'Factor', id: number, name: string, link: string } | { __typename: 'FactorVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'Feature', id: number, name: string, link: string } | { __typename: 'Flag', id: number, name: string, link: string } | { __typename: 'Fusion', id: number, name: string, link: string } | { __typename: 'FusionVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'Gene', id: number, name: string, link: string } | { __typename: 'GeneVariant', id: number, name: string, link: string, feature: { __typename: 'Feature', id: number, name: string, link: string } } | { __typename: 'MolecularProfile', id: number, name: string, link: string } | { __typename: 'Revision', id: number, name: string, link: string } | { __typename: 'RevisionSet', id: number, name: string, link: string } | { __typename: 'Source', id: number, name: string, link: string } | { __typename: 'SourcePopover', id: number, name: string, link: string } | { __typename: 'SourceSuggestion', id: number, name: string, link: string } | { __typename: 'Variant', id: number, name: string, link: string } | { __typename: 'VariantCoordinate', id: number, name: string, link: string } | { __typename: 'VariantGroup', id: number, name: string, link: string }, events: Array<{ __typename: 'Event', id: number, createdAt: any, action: EventAction, originatingObject?: { __typename: 'Assertion', id: number, name: string, link: string } | { __typename: 'Comment', id: number, name: string, link: string } | { __typename: 'EvidenceItem', id: number, name: string, link: string } | { __typename: 'Factor', id: number, name: string, link: string } | { __typename: 'FactorVariant', id: number, name: string, link: string } | { __typename: 'Feature', id: number, name: string, link: string } | { __typename: 'Flag', id: number, name: string, link: string } | { __typename: 'Fusion', id: number, name: string, link: string } | { __typename: 'FusionVariant', id: number, name: string, link: string } | { __typename: 'Gene', id: number, name: string, link: string } | { __typename: 'GeneVariant', id: number, name: string, link: string } | { __typename: 'MolecularProfile', id: number, name: string, link: string } | { __typename: 'Revision', id: number, name: string, link: string } | { __typename: 'SourceSuggestion', id: number, name: string, link: string } | { __typename: 'Variant', id: number, name: string, link: string } | undefined, originatingUser: { __typename: 'User', id: number, displayName: string } }> }; @@ -8270,7 +8288,7 @@ export type MolecularProfileMenuQueryVariables = Exact<{ last?: InputMaybe; before?: InputMaybe; after?: InputMaybe; - evidenceStatusFilter?: InputMaybe; + evidenceStatusFilter?: InputMaybe; }>; @@ -13702,6 +13720,67 @@ export const ActivityFeedUpdatesDocument = gql` export class ActivityFeedUpdatesGQL extends Apollo.Query { document = ActivityFeedUpdatesDocument; + constructor(apollo: Apollo.Apollo) { + super(apollo); + } + } +export const OrgFilterSearchDocument = gql` + query OrgFilterSearch($name: String) { + organizations(name: $name) { + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + edges { + node { + id + name + } + } + } +} + `; + + @Injectable({ + providedIn: 'root' + }) + export class OrgFilterSearchGQL extends Apollo.Query { + document = OrgFilterSearchDocument; + + constructor(apollo: Apollo.Apollo) { + super(apollo); + } + } +export const UserFilterSearchDocument = gql` + query UserFilterSearch($name: String) { + users(name: $name) { + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + edges { + node { + id + displayName + name + username + role + } + } + } +} + `; + + @Injectable({ + providedIn: 'root' + }) + export class UserFilterSearchGQL extends Apollo.Query { + document = UserFilterSearchDocument; + constructor(apollo: Apollo.Apollo) { super(apollo); } @@ -14394,7 +14473,7 @@ export const BrowseMolecularProfilesDocument = gql` } } export const MolecularProfileMenuDocument = gql` - query MolecularProfileMenu($geneId: Int, $featureId: Int, $mpName: String, $first: Int, $last: Int, $before: String, $after: String, $evidenceStatusFilter: MolecularProfileDisplayFilter) { + query MolecularProfileMenu($geneId: Int, $featureId: Int, $mpName: String, $first: Int, $last: Int, $before: String, $after: String, $evidenceStatusFilter: AssociatedEvidenceStatusFilter) { molecularProfiles( geneId: $geneId featureId: $featureId diff --git a/client/src/app/generated/server.model.graphql b/client/src/app/generated/server.model.graphql index 5f6103bf0..18840fbe5 100644 --- a/client/src/app/generated/server.model.graphql +++ b/client/src/app/generated/server.model.graphql @@ -794,6 +794,28 @@ enum AssertionType { PROGNOSTIC } +enum AssociatedEvidenceStatusFilter { + """ + Apply no status filter to an entity in order to display all entities regardless of attached evidence status. + """ + ALL + + """ + Apply filter to an entity to display only those which have at least one accepted associated evidence item. + """ + WITH_ACCEPTED + + """ + Apply filter to an entity to display only those which have at least one accepted or submitted associated evidence item. + """ + WITH_ACCEPTED_OR_SUBMITTED + + """ + Apply filter to an entity to display only those which have at least one submitted associated evidence item. + """ + WITH_SUBMITTED +} + enum BooleanOperator { AND OR @@ -6976,28 +6998,6 @@ enum MolecularProfileDeprecationReasonMutationInput { OTHER } -enum MolecularProfileDisplayFilter { - """ - Display all molecular profiles regardless of attached evidence status. - """ - ALL - - """ - Display only molecular profiles which have at least one accepted evidence item. - """ - WITH_ACCEPTED - - """ - Display only molecular profiles which have evidence in either an accepted or submitted state. - """ - WITH_ACCEPTED_OR_SUBMITTED - - """ - Display molecular profiles which have at least one submitted evidence item. - """ - WITH_SUBMITTED -} - """ An edge in a connection. """ @@ -8944,6 +8944,11 @@ type Query { """ before: String + """ + Limit factors by the status of attached evidence. + """ + evidenceStatusFilter: AssociatedEvidenceStatusFilter + """ Returns the first _n_ elements from the list. """ @@ -9046,14 +9051,9 @@ type Query { before: String """ - List of Entrez Gene IDs to return results for + Limit fusions by the status of attached evidence. """ - entrezIds: [Int!] - - """ - List of Entrez Gene symbols to return results for - """ - entrezSymbols: [String!] + evidenceStatusFilter: AssociatedEvidenceStatusFilter """ Returns the first _n_ elements from the list. @@ -9100,6 +9100,11 @@ type Query { """ entrezSymbols: [String!] + """ + Limit genes by the status of attached evidence. + """ + evidenceStatusFilter: AssociatedEvidenceStatusFilter + """ Returns the first _n_ elements from the list. """ @@ -9138,7 +9143,7 @@ type Query { """ Limit molecular profiles by the status of attached evidence. """ - evidenceStatusFilter: MolecularProfileDisplayFilter + evidenceStatusFilter: AssociatedEvidenceStatusFilter """ Filter molecular profiles to the CIViC ID of the feature(s) involved. diff --git a/client/src/app/generated/server.schema.json b/client/src/app/generated/server.schema.json index 7b899f155..be7d148b1 100644 --- a/client/src/app/generated/server.schema.json +++ b/client/src/app/generated/server.schema.json @@ -3594,6 +3594,41 @@ ], "possibleTypes": null }, + { + "kind": "ENUM", + "name": "AssociatedEvidenceStatusFilter", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "WITH_ACCEPTED", + "description": "Apply filter to an entity to display only those which have at least one accepted associated evidence item.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WITH_ACCEPTED_OR_SUBMITTED", + "description": "Apply filter to an entity to display only those which have at least one accepted or submitted associated evidence item.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WITH_SUBMITTED", + "description": "Apply filter to an entity to display only those which have at least one submitted associated evidence item.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "ALL", + "description": "Apply no status filter to an entity in order to display all entities regardless of attached evidence status.", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "SCALAR", "name": "Boolean", @@ -32541,41 +32576,6 @@ ], "possibleTypes": null }, - { - "kind": "ENUM", - "name": "MolecularProfileDisplayFilter", - "description": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "WITH_ACCEPTED", - "description": "Display only molecular profiles which have at least one accepted evidence item.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "WITH_ACCEPTED_OR_SUBMITTED", - "description": "Display only molecular profiles which have evidence in either an accepted or submitted state.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "WITH_SUBMITTED", - "description": "Display molecular profiles which have at least one submitted evidence item.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ALL", - "description": "Display all molecular profiles regardless of attached evidence status.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, { "kind": "OBJECT", "name": "MolecularProfileEdge", @@ -41062,6 +41062,18 @@ "name": "factors", "description": "List and filter factors.", "args": [ + { + "name": "evidenceStatusFilter", + "description": "Limit factors by the status of attached evidence.", + "type": { + "kind": "ENUM", + "name": "AssociatedEvidenceStatusFilter", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "ncitIt", "description": "List of NCIt Codes to return Factors for", @@ -41425,11 +41437,11 @@ "description": "List and filter fusions.", "args": [ { - "name": "genePartnerId", - "description": "CIViC ID of one of the Gene partners", + "name": "evidenceStatusFilter", + "description": "Limit fusions by the status of attached evidence.", "type": { - "kind": "SCALAR", - "name": "Int", + "kind": "ENUM", + "name": "AssociatedEvidenceStatusFilter", "ofType": null }, "defaultValue": null, @@ -41437,40 +41449,12 @@ "deprecationReason": null }, { - "name": "entrezSymbols", - "description": "List of Entrez Gene symbols to return results for", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - "defaultValue": null, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "entrezIds", - "description": "List of Entrez Gene IDs to return results for", + "name": "genePartnerId", + "description": "CIViC ID of one of the Gene partners", "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } + "kind": "SCALAR", + "name": "Int", + "ofType": null }, "defaultValue": null, "isDeprecated": false, @@ -41578,6 +41562,18 @@ "name": "genes", "description": "List and filter genes.", "args": [ + { + "name": "evidenceStatusFilter", + "description": "Limit genes by the status of attached evidence.", + "type": { + "kind": "ENUM", + "name": "AssociatedEvidenceStatusFilter", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "entrezSymbols", "description": "List of Entrez Gene symbols to return results for", @@ -41717,7 +41713,7 @@ "description": "Limit molecular profiles by the status of attached evidence.", "type": { "kind": "ENUM", - "name": "MolecularProfileDisplayFilter", + "name": "AssociatedEvidenceStatusFilter", "ofType": null }, "defaultValue": null, diff --git a/client/src/app/views/curation/curation-activity/curation-timeline/curation-timeline.page.html b/client/src/app/views/curation/curation-activity/curation-timeline/curation-timeline.page.html index dbee5ffd7..e0c6e4e43 100644 --- a/client/src/app/views/curation/curation-activity/curation-timeline/curation-timeline.page.html +++ b/client/src/app/views/curation/curation-activity/curation-timeline/curation-timeline.page.html @@ -1 +1 @@ - + diff --git a/client/src/app/views/variants/variants-revise/variants-revise.module.ts b/client/src/app/views/variants/variants-revise/variants-revise.module.ts index 3007e529a..39aa1665d 100644 --- a/client/src/app/views/variants/variants-revise/variants-revise.module.ts +++ b/client/src/app/views/variants/variants-revise/variants-revise.module.ts @@ -10,6 +10,7 @@ import { CvcLoginPromptModule } from '@app/components/shared/login-prompt/login- import { LetDirective, PushPipe } from '@ngrx/component' import { NzGridModule } from 'ng-zorro-antd/grid' import { CvcPipesModule } from '@app/core/pipes/pipes.module' +import { NzTypographyModule } from 'ng-zorro-antd/typography' @NgModule({ declarations: [VariantsReviseView], @@ -18,6 +19,7 @@ import { CvcPipesModule } from '@app/core/pipes/pipes.module' VariantsReviseRoutingModule, NzPageHeaderModule, NzIconModule, + NzTypographyModule, CvcPipesModule, CvcSectionNavigationModule, CvcLoginPromptModule, diff --git a/client/src/app/views/variants/variants-revise/variants-revise.view.html b/client/src/app/views/variants/variants-revise/variants-revise.view.html index 9368a4d0c..99182285c 100644 --- a/client/src/app/views/variants/variants-revise/variants-revise.view.html +++ b/client/src/app/views/variants/variants-revise/variants-revise.view.html @@ -11,6 +11,7 @@ nzTheme="twotone" [nzTwotoneColor]="'Variant' | entityColor" nzType="civic-variant"> + {{ variant.feature.name }} {{ variant.name }} diff --git a/server/app/graphql/resolvers/top_level_factors.rb b/server/app/graphql/resolvers/top_level_factors.rb index 670156507..e5fc53636 100644 --- a/server/app/graphql/resolvers/top_level_factors.rb +++ b/server/app/graphql/resolvers/top_level_factors.rb @@ -8,10 +8,27 @@ class Resolvers::TopLevelFactors < GraphQL::Schema::Resolver description 'List and filter factors.' scope do - Features::Factor - .eager_load(:feature) - .joins(feature: {variants: [molecular_profiles: [:evidence_items]]}) - .order('features.name ASC').where("evidence_items.status != 'rejected'").distinct + Features::Factor.joins(feature: { variants: [:molecular_profiles]}) + .where("variants.deprecated = 'f'") + .order('features.name ASC') + .select("factors.*, features.name") + .distinct + end + + option(:evidence_status_filter, default_value: 'WITH_ACCEPTED_OR_SUBMITTED', type: Types::AssociatedEvidenceStatusFilterType , description: 'Limit factors by the status of attached evidence.') do |scope, value| + case value + when 'WITH_ACCEPTED' + scope.joins(feature: { variants: { molecular_profiles: [:evidence_items_by_status] } }) + .where('evidence_items_by_statuses.accepted_count >= 1') + when 'WITH_ACCEPTED_OR_SUBMITTED' + scope.joins(feature: { variants: { molecular_profiles: [:evidence_items_by_status] } }) + .where('evidence_items_by_statuses.accepted_count >= 1 OR evidence_items_by_statuses.submitted_count >= 1') + when 'WITH_SUBMITTED' + scope.joins(feature: { variants: { molecular_profiles: [:evidence_items_by_status] } }) + .where('evidence_items_by_statuses.submitted_count >= 1') + when 'ALL' + scope + end end option(:ncit_it, type: [GraphQL::Types::String], description: 'List of NCIt Codes to return Factors for') do |scope, value| diff --git a/server/app/graphql/resolvers/top_level_fusions.rb b/server/app/graphql/resolvers/top_level_fusions.rb index 407a745a3..f6fce847e 100644 --- a/server/app/graphql/resolvers/top_level_fusions.rb +++ b/server/app/graphql/resolvers/top_level_fusions.rb @@ -10,20 +10,30 @@ class Resolvers::TopLevelFusions < GraphQL::Schema::Resolver @@cols = Features::Fusion.column_names.map { |col| "fusions.#{col}" }.join(",") scope do - Features::Fusion.joins(feature: { variants: [:molecular_profiles ]}) + Features::Fusion.joins(feature: { variants: [:molecular_profiles]}) .where("variants.deprecated = 'f'") + .order('features.name ASC') + .select("fusions.*, features.name") .distinct end - option(:gene_partner_id, type: Int, description: 'CIViC ID of one of the Gene partners') do |scope, value| - scope.where('fusions.five_prime_gene_id = ? OR fusions.three_prime_gene_id = ?', value, value) - end - - option(:entrez_symbols, type: [GraphQL::Types::String], description: 'List of Entrez Gene symbols to return results for') do |scope, value| - scope.where('genes.name IN (?)', value.map(&:upcase)) + option(:evidence_status_filter, default_value: 'WITH_ACCEPTED_OR_SUBMITTED', type: Types::AssociatedEvidenceStatusFilterType , description: 'Limit fusions by the status of attached evidence.') do |scope, value| + case value + when 'WITH_ACCEPTED' + scope.joins(feature: { variants: { molecular_profiles: [:evidence_items_by_status] } }) + .where('evidence_items_by_statuses.accepted_count >= 1') + when 'WITH_ACCEPTED_OR_SUBMITTED' + scope.joins(feature: { variants: { molecular_profiles: [:evidence_items_by_status] } }) + .where('evidence_items_by_statuses.accepted_count >= 1 OR evidence_items_by_statuses.submitted_count >= 1') + when 'WITH_SUBMITTED' + scope.joins(feature: { variants: { molecular_profiles: [:evidence_items_by_status] } }) + .where('evidence_items_by_statuses.submitted_count >= 1') + when 'ALL' + scope + end end - option(:entrez_ids, type: [GraphQL::Types::Int], description: 'List of Entrez Gene IDs to return results for') do |scope, value| - scope.where('genes.entrez_id IN (?)', value) + option(:gene_partner_id, type: Int, description: 'CIViC ID of one of the Gene partners') do |scope, value| + scope.where('fusions.five_prime_gene_id = ? OR fusions.three_prime_gene_id = ?', value, value) end end diff --git a/server/app/graphql/resolvers/top_level_genes.rb b/server/app/graphql/resolvers/top_level_genes.rb index 6a202b4bf..38ba9ffc1 100644 --- a/server/app/graphql/resolvers/top_level_genes.rb +++ b/server/app/graphql/resolvers/top_level_genes.rb @@ -8,13 +8,29 @@ class Resolvers::TopLevelGenes < GraphQL::Schema::Resolver description 'List and filter genes.' scope do - Features::Gene.joins(feature: { variants: [molecular_profiles: [:evidence_items]]}) + Features::Gene.joins(feature: { variants: [:molecular_profiles]}) + .where("variants.deprecated = 'f'") .order('features.name ASC') - .where("evidence_items.status != 'rejected'") .select("genes.*, features.name") .distinct end + option(:evidence_status_filter, default_value: 'WITH_ACCEPTED_OR_SUBMITTED', type: Types::AssociatedEvidenceStatusFilterType , description: 'Limit genes by the status of attached evidence.') do |scope, value| + case value + when 'WITH_ACCEPTED' + scope.joins(feature: { variants: { molecular_profiles: [:evidence_items_by_status] } }) + .where('evidence_items_by_statuses.accepted_count >= 1') + when 'WITH_ACCEPTED_OR_SUBMITTED' + scope.joins(feature: { variants: { molecular_profiles: [:evidence_items_by_status] } }) + .where('evidence_items_by_statuses.accepted_count >= 1 OR evidence_items_by_statuses.submitted_count >= 1') + when 'WITH_SUBMITTED' + scope.joins(feature: { variants: { molecular_profiles: [:evidence_items_by_status] } }) + .where('evidence_items_by_statuses.submitted_count >= 1') + when 'ALL' + scope + end + end + option(:entrez_symbols, type: [GraphQL::Types::String], description: 'List of Entrez Gene symbols to return results for') do |scope, value| scope.where('features.name IN (?)', value.map(&:upcase)) end diff --git a/server/app/graphql/resolvers/top_level_molecular_profiles.rb b/server/app/graphql/resolvers/top_level_molecular_profiles.rb index 315e064c3..6fbab8f30 100644 --- a/server/app/graphql/resolvers/top_level_molecular_profiles.rb +++ b/server/app/graphql/resolvers/top_level_molecular_profiles.rb @@ -9,7 +9,7 @@ class Resolvers::TopLevelMolecularProfiles < GraphQL::Schema::Resolver scope { MolecularProfile.where(deprecated: false).order('molecular_profiles.evidence_score DESC').distinct } - option(:evidence_status_filter, default_value: 'WITH_ACCEPTED_OR_SUBMITTED', type: Types::MolecularProfileDisplayFilterType , description: 'Limit molecular profiles by the status of attached evidence.') do |scope, value| + option(:evidence_status_filter, default_value: 'WITH_ACCEPTED_OR_SUBMITTED', type: Types::AssociatedEvidenceStatusFilterType , description: 'Limit molecular profiles by the status of attached evidence.') do |scope, value| case value when 'WITH_ACCEPTED' scope.joins(:evidence_items_by_status) diff --git a/server/app/graphql/types/activities/activity_subject_input_type.rb b/server/app/graphql/types/activities/activity_subject_input_type.rb index b1533c335..f27a56dab 100644 --- a/server/app/graphql/types/activities/activity_subject_input_type.rb +++ b/server/app/graphql/types/activities/activity_subject_input_type.rb @@ -12,7 +12,5 @@ class ActivitySubjectInputType < Types::BaseEnum value 'FLAG', value: 'Flag' value 'REVISION_SET', value: 'RevisionSet' value 'COMMENT', value: 'Comment' - value 'EXON_COORDINATE', value: 'ExonCoordinate' - value 'GENE_COORDINATE', value: 'GeneCoordinate' end end diff --git a/server/app/graphql/types/associated_evidence_status_filter_type.rb b/server/app/graphql/types/associated_evidence_status_filter_type.rb new file mode 100644 index 000000000..c3261ba48 --- /dev/null +++ b/server/app/graphql/types/associated_evidence_status_filter_type.rb @@ -0,0 +1,12 @@ +module Types + class AssociatedEvidenceStatusFilterType < Types::BaseEnum + value 'WITH_ACCEPTED', + description: 'Apply filter to an entity to display only those which have at least one accepted associated evidence item.' + value 'WITH_ACCEPTED_OR_SUBMITTED', + description: 'Apply filter to an entity to display only those which have at least one accepted or submitted associated evidence item.' + value 'WITH_SUBMITTED', + description: 'Apply filter to an entity to display only those which have at least one submitted associated evidence item.' + value 'ALL', + description: 'Apply no status filter to an entity in order to display all entities regardless of attached evidence status.' + end +end diff --git a/server/app/graphql/types/entities/user_type.rb b/server/app/graphql/types/entities/user_type.rb index fd49eff07..9e1c8b0be 100644 --- a/server/app/graphql/types/entities/user_type.rb +++ b/server/app/graphql/types/entities/user_type.rb @@ -21,6 +21,7 @@ class UserType < Types::BaseObject field :most_recent_activity_timestamp, GraphQL::Types::ISO8601DateTime, null: true field :most_recent_organization_id, Int, null: true field :ranks, Types::Entities::RanksType, null: false + field :email, String, null: true profile_image_sizes = [256, 128, 64, 32, 18, 12] field :profile_image_path, String, null: true do @@ -33,12 +34,6 @@ class UserType < Types::BaseObject } end - field :email, String, null: true do - def authorized?(object, args, context) - object.id == context[:current_user]&.id - end - end - field :notifications, Types::Entities::NotificationType.connection_type, null: true do description 'Filterable list of notifications for the logged in user.' type_desc = 'Filter the response to include only notifications of a certain type (ex: mentions).' @@ -55,6 +50,15 @@ def authorized?(object, args, context) end end + def email + #You can only fetch your own email + if object.id == context[:current_user]&.id + object.email + else + nil + end + end + def organizations Loaders::AssociationLoader.for(User, :organizations).load(object) end diff --git a/server/app/graphql/types/molecular_profile_display_filter_type.rb b/server/app/graphql/types/molecular_profile_display_filter_type.rb deleted file mode 100644 index 1fde9f7fd..000000000 --- a/server/app/graphql/types/molecular_profile_display_filter_type.rb +++ /dev/null @@ -1,12 +0,0 @@ -module Types - class MolecularProfileDisplayFilterType < Types::BaseEnum - value 'WITH_ACCEPTED', - description: 'Display only molecular profiles which have at least one accepted evidence item.' - value 'WITH_ACCEPTED_OR_SUBMITTED', - description: 'Display only molecular profiles which have evidence in either an accepted or submitted state.' - value 'WITH_SUBMITTED', - description: 'Display molecular profiles which have at least one submitted evidence item.' - value 'ALL', - description: 'Display all molecular profiles regardless of attached evidence status.' - end -end diff --git a/server/app/models/activities/accept_revisions.rb b/server/app/models/activities/accept_revisions.rb index 737e75ecb..f70be8e2c 100644 --- a/server/app/models/activities/accept_revisions.rb +++ b/server/app/models/activities/accept_revisions.rb @@ -10,8 +10,12 @@ def initialize(accepting_user:, revisions:, organization_id: nil, note:) private def create_activity + #Set the subject of this activity to the subject of the revision's creation activity + #In the case of gene/exon coordinates, the revision's subject will be the coordinate Object + #which we do not want. The creation activity's subject will be the Variant. + activity_subject = revisions.first&.creation_activity&.subject @activity = AcceptRevisionsActivity.create!( - subject: revisions.first.subject, + subject: activity_subject, user: accepting_user, organization: organization, note: note diff --git a/server/yarn.lock b/server/yarn.lock index ca73469fa..dbcbca99d 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -2428,9 +2428,9 @@ http-parser-js@>=0.5.1: integrity sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA== http-proxy-middleware@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" - integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + version "2.0.7" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz#915f236d92ae98ef48278a95dedf17e991936ec6" + integrity sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA== dependencies: "@types/http-proxy" "^1.17.8" http-proxy "^1.18.1"