diff --git a/client/src/app/components/shared/tab-navigation/tab-navigation.component.html b/client/src/app/components/shared/tab-navigation/tab-navigation.component.html
index 9cb4fbf60..f6e6d40f5 100644
--- a/client/src/app/components/shared/tab-navigation/tab-navigation.component.html
+++ b/client/src/app/components/shared/tab-navigation/tab-navigation.component.html
@@ -20,12 +20,12 @@
[nzType]="tab.iconName">
{{ tab.tabLabel }}
0"
nzStandalone
[nzCount]="tab.badgeCount"
- nzTitle="There are {{ tab.badgeCount }} outstanding revisions."
- [nzStyle]="{
- transform: 'scale(0.75, 0.75) translate(0, -2px)'
- }">
+ nzTitle="{{ tab.badgeCount }} {{ tab.tabLabel }}(s)."
+ [nzStyle]="{ transform: 'scale(0.75, 0.75) translate(0, -2px)', backgroundColor: tab.badgeColor || '#ff4d4f'}">
+
diff --git a/client/src/app/components/shared/tab-navigation/tab-navigation.component.ts b/client/src/app/components/shared/tab-navigation/tab-navigation.component.ts
index c384f8454..e8fac5917 100644
--- a/client/src/app/components/shared/tab-navigation/tab-navigation.component.ts
+++ b/client/src/app/components/shared/tab-navigation/tab-navigation.component.ts
@@ -7,6 +7,7 @@ export interface RouteableTab {
tabLabel: string
iconName: string
badgeCount?: number
+ badgeColor?: string
}
@Component({
diff --git a/client/src/app/generated/civic.apollo.ts b/client/src/app/generated/civic.apollo.ts
index 0e76c872a..ee06a5d52 100644
--- a/client/src/app/generated/civic.apollo.ts
+++ b/client/src/app/generated/civic.apollo.ts
@@ -6781,9 +6781,9 @@ export type SourceDetailQueryVariables = Exact<{
}>;
-export type SourceDetailQuery = { __typename: 'Query', source?: { __typename: 'Source', id: number, citation?: string | undefined, sourceUrl?: string | undefined, displayType: string, citationId: string } | undefined };
+export type SourceDetailQuery = { __typename: 'Query', source?: { __typename: 'Source', id: number, citation?: string | undefined, sourceUrl?: string | undefined, displayType: string, citationId: string, comments: { __typename: 'CommentConnection', totalCount: number } } | undefined };
-export type SourceDetailFieldsFragment = { __typename: 'Source', id: number, citation?: string | undefined, sourceUrl?: string | undefined, displayType: string, citationId: string };
+export type SourceDetailFieldsFragment = { __typename: 'Source', id: number, citation?: string | undefined, sourceUrl?: string | undefined, displayType: string, citationId: string, comments: { __typename: 'CommentConnection', totalCount: number } };
export type SourceSummaryQueryVariables = Exact<{
sourceId: Scalars['Int'];
@@ -9208,6 +9208,9 @@ export const SourceDetailFieldsFragmentDoc = gql`
sourceUrl
displayType
citationId
+ comments {
+ totalCount
+ }
}
`;
export const SourceSummaryFieldsFragmentDoc = gql`
diff --git a/client/src/app/views/assertions/assertions-detail/assertions-detail.view.ts b/client/src/app/views/assertions/assertions-detail/assertions-detail.view.ts
index 53dccf6e6..c384b160b 100644
--- a/client/src/app/views/assertions/assertions-detail/assertions-detail.view.ts
+++ b/client/src/app/views/assertions/assertions-detail/assertions-detail.view.ts
@@ -27,7 +27,6 @@ export class AssertionsDetailView implements OnDestroy {
assertion$?: Observable>
loading$?: Observable
- commentsTotal$?: Observable
flagsTotal$?: Observable
viewer$: Observable
@@ -85,21 +84,23 @@ export class AssertionsDetailView implements OnDestroy {
this.assertion$ = observable.pipe(pluck('data', 'assertion'))
- this.commentsTotal$ = this.assertion$.pipe(
- pluck('comments', 'totalCount')
- )
-
this.flagsTotal$ = this.assertion$.pipe(pluck('flags', 'totalCount'))
this.assertion$
- .pipe(pluck('revisions', 'totalCount'), takeUntil(this.destroy$))
+ .pipe(takeUntil(this.destroy$))
.subscribe({
- next: (count) => {
+ next: (assertionResp) => {
this.tabs$.next(
this.defaultTabs.map((tab) => {
if (tab.tabLabel === 'Revisions') {
return {
- badgeCount: count as number,
+ badgeCount: assertionResp?.revisions.totalCount,
+ ...tab,
+ }
+ } else if (tab.tabLabel === 'Comments') {
+ return {
+ badgeCount: assertionResp?.comments.totalCount,
+ badgeColor: '#cccccc',
...tab,
}
} else {
diff --git a/client/src/app/views/evidence/evidence-detail/evidence-detail.view.ts b/client/src/app/views/evidence/evidence-detail/evidence-detail.view.ts
index b1cc8eb03..a34cebbdc 100644
--- a/client/src/app/views/evidence/evidence-detail/evidence-detail.view.ts
+++ b/client/src/app/views/evidence/evidence-detail/evidence-detail.view.ts
@@ -27,7 +27,6 @@ export class EvidenceDetailView implements OnDestroy {
evidence$?: Observable>
loading$?: Observable
- commentsTotal$?: Observable
flagsTotal$?: Observable
viewer$: Observable
@@ -85,19 +84,23 @@ export class EvidenceDetailView implements OnDestroy {
this.evidence$ = observable.pipe(pluck('data', 'evidenceItem'))
- this.commentsTotal$ = this.evidence$.pipe(pluck('comments', 'totalCount'))
-
this.flagsTotal$ = this.evidence$.pipe(pluck('flags', 'totalCount'))
this.evidence$
- .pipe(pluck('revisions', 'totalCount'), takeUntil(this.destroy$))
+ .pipe(takeUntil(this.destroy$))
.subscribe({
- next: (count) => {
+ next: (evidenceResponse) => {
this.tabs$.next(
this.defaultTabs.map((tab) => {
if (tab.tabLabel === 'Revisions') {
return {
- badgeCount: count as number,
+ badgeCount: evidenceResponse?.revisions.totalCount,
+ ...tab,
+ }
+ } else if (tab.tabLabel === 'Comments') {
+ return {
+ badgeCount: evidenceResponse?.comments.totalCount,
+ badgeColor: '#cccccc',
...tab,
}
} else {
diff --git a/client/src/app/views/genes/genes-detail/genes-detail.view.ts b/client/src/app/views/genes/genes-detail/genes-detail.view.ts
index 5c7e9294e..0086b97bb 100644
--- a/client/src/app/views/genes/genes-detail/genes-detail.view.ts
+++ b/client/src/app/views/genes/genes-detail/genes-detail.view.ts
@@ -22,7 +22,6 @@ export class GenesDetailView implements OnDestroy {
loading$?: Observable
gene$?: Observable>
viewer$: Observable
- commentsTotal$?: Observable
flagsTotal$?: Observable
routeSub: Subscription
subscribable?: SubscribableInput
@@ -72,19 +71,23 @@ export class GenesDetailView implements OnDestroy {
this.gene$ = observable.pipe(pluck('data', 'gene'))
- this.commentsTotal$ = this.gene$.pipe(pluck('comments', 'totalCount'))
-
this.flagsTotal$ = this.gene$.pipe(pluck('flags', 'totalCount'))
this.gene$
- .pipe(pluck('revisions', 'totalCount'), takeUntil(this.destroy$))
+ .pipe(takeUntil(this.destroy$))
.subscribe({
- next: (count) => {
+ next: (geneResp) => {
this.tabs$.next(
this.defaultTabs.map((tab) => {
if (tab.tabLabel === 'Revisions') {
return {
- badgeCount: count as number,
+ badgeCount: geneResp?.revisions.totalCount,
+ ...tab,
+ }
+ } else if (tab.tabLabel === 'Comments') {
+ return {
+ badgeCount: geneResp?.comments.totalCount,
+ badgeColor: '#cccccc',
...tab,
}
} else {
diff --git a/client/src/app/views/molecular-profiles/molecular-profiles-detail/molecular-profiles-detail.view.ts b/client/src/app/views/molecular-profiles/molecular-profiles-detail/molecular-profiles-detail.view.ts
index eb279d222..4c272f1e9 100644
--- a/client/src/app/views/molecular-profiles/molecular-profiles-detail/molecular-profiles-detail.view.ts
+++ b/client/src/app/views/molecular-profiles/molecular-profiles-detail/molecular-profiles-detail.view.ts
@@ -29,7 +29,6 @@ export class MolecularProfilesDetailView implements OnDestroy {
molecularProfile$?: Observable>
loading$?: Observable
- commentsTotal$?: Observable
flagsTotal$?: Observable
viewer$: Observable
@@ -85,23 +84,25 @@ export class MolecularProfilesDetailView implements OnDestroy {
pluck('data', 'molecularProfile')
)
- this.commentsTotal$ = this.molecularProfile$.pipe(
- pluck('comments', 'totalCount')
- )
-
this.flagsTotal$ = this.molecularProfile$.pipe(
pluck('flags', 'totalCount')
)
this.molecularProfile$
- .pipe(pluck('revisions', 'totalCount'), takeUntil(this.destroy$))
+ .pipe(takeUntil(this.destroy$))
.subscribe({
- next: (count) => {
+ next: (mpResp) => {
this.tabs$.next(
this.defaultTabs.map((tab) => {
if (tab.tabLabel === 'Revisions') {
return {
- badgeCount: count as number,
+ badgeCount: mpResp?.revisions.totalCount,
+ ...tab,
+ }
+ } else if (tab.tabLabel === 'Comments') {
+ return {
+ badgeCount: mpResp?.comments.totalCount,
+ badgeColor: '#cccccc',
...tab,
}
} else {
diff --git a/client/src/app/views/sources/sources-detail/sources-detail.query.gql b/client/src/app/views/sources/sources-detail/sources-detail.query.gql
index aecbdf90e..f6091a7ab 100644
--- a/client/src/app/views/sources/sources-detail/sources-detail.query.gql
+++ b/client/src/app/views/sources/sources-detail/sources-detail.query.gql
@@ -10,4 +10,7 @@ fragment SourceDetailFields on Source {
sourceUrl
displayType
citationId
+ comments {
+ totalCount
+ }
}
diff --git a/client/src/app/views/sources/sources-detail/sources-detail.view.html b/client/src/app/views/sources/sources-detail/sources-detail.view.html
index 14e5bd921..30cbf2bbd 100644
--- a/client/src/app/views/sources/sources-detail/sources-detail.view.html
+++ b/client/src/app/views/sources/sources-detail/sources-detail.view.html
@@ -35,7 +35,7 @@
-
+
diff --git a/client/src/app/views/sources/sources-detail/sources-detail.view.ts b/client/src/app/views/sources/sources-detail/sources-detail.view.ts
index 5cd9d53d3..403bbb20c 100644
--- a/client/src/app/views/sources/sources-detail/sources-detail.view.ts
+++ b/client/src/app/views/sources/sources-detail/sources-detail.view.ts
@@ -10,8 +10,8 @@ import {
SourceDetailQueryVariables,
} from '@app/generated/civic.apollo'
import { QueryRef } from 'apollo-angular'
-import { Observable, Subscription } from 'rxjs'
-import { startWith } from 'rxjs/operators'
+import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs'
+import { startWith, takeUntil } from 'rxjs/operators'
import { pluck } from 'rxjs-etc/operators'
@Component({
@@ -25,17 +25,32 @@ export class SourcesDetailView implements OnDestroy {
sourceId?: number
queryRef?: QueryRef
+ destroy$ = new Subject()
loading$?: Observable
source$?: Observable>
- tabs: RouteableTab[]
+ tabs$: BehaviorSubject
+ defaultTabs: RouteableTab[] = [
+ {
+ routeName: 'summary',
+ iconName: 'pic-left',
+ tabLabel: 'Summary',
+ },
+ {
+ routeName: 'comments',
+ iconName: 'civic-comment',
+ tabLabel: 'Comments',
+ },
+ ]
constructor(
private viewerService: ViewerService,
private route: ActivatedRoute,
private gql: SourceDetailGQL
) {
+ this.tabs$ = new BehaviorSubject(this.defaultTabs)
+
this.viewer$ = this.viewerService.viewer$
this.routeSub = this.route.params.subscribe((params) => {
@@ -49,22 +64,29 @@ export class SourcesDetailView implements OnDestroy {
this.loading$ = observable.pipe(pluck('loading'), startWith(true))
this.source$ = observable.pipe(pluck('data', 'source'))
+ this.source$.pipe(takeUntil(this.destroy$)).subscribe({
+ next: (sourceResp) => {
+ this.tabs$.next(
+ this.defaultTabs.map((tab) => {
+ if (tab.tabLabel === 'Comments') {
+ return {
+ badgeCount: sourceResp?.comments.totalCount,
+ badgeColor: '#cccccc',
+ ...tab,
+ }
+ } else {
+ return tab
+ }
+ })
+ )
+ },
+ })
})
-
- this.tabs = [
- {
- routeName: 'summary',
- iconName: 'pic-left',
- tabLabel: 'Summary',
- },
- {
- routeName: 'comments',
- iconName: 'civic-comment',
- tabLabel: 'Comments',
- },
- ]
}
+
ngOnDestroy() {
this.routeSub.unsubscribe()
+ this.destroy$.next()
+ this.destroy$.unsubscribe()
}
}
diff --git a/client/src/app/views/variant-groups/variant-groups-detail/variant-groups-detail.view.ts b/client/src/app/views/variant-groups/variant-groups-detail/variant-groups-detail.view.ts
index d55dbd602..290ce6bbd 100644
--- a/client/src/app/views/variant-groups/variant-groups-detail/variant-groups-detail.view.ts
+++ b/client/src/app/views/variant-groups/variant-groups-detail/variant-groups-detail.view.ts
@@ -22,7 +22,6 @@ export class VariantGroupsDetailView implements OnInit, OnDestroy {
loading$?: Observable
variantGroup$?: Observable>
viewer$: Observable
- commentsTotal$?: Observable
revisionsTotal$?: Observable
flagsTotal$?: Observable
routeSub: Subscription
@@ -70,21 +69,23 @@ export class VariantGroupsDetailView implements OnInit, OnDestroy {
this.variantGroup$ = observable.pipe(pluck('data', 'variantGroup'))
- this.commentsTotal$ = this.variantGroup$.pipe(
- pluck('comments', 'totalCount')
- )
-
this.flagsTotal$ = this.variantGroup$.pipe(pluck('flags', 'totalCount'))
this.variantGroup$
- .pipe(pluck('revisions', 'totalCount'), takeUntil(this.destroy$))
+ .pipe(takeUntil(this.destroy$))
.subscribe({
- next: (count) => {
+ next: (vgResp) => {
this.tabs$.next(
this.defaultTabs.map((tab) => {
if (tab.tabLabel === 'Revisions') {
return {
- badgeCount: count as number,
+ badgeCount: vgResp?.revisions.totalCount,
+ ...tab,
+ }
+ } else if (tab.tabLabel === 'Comments') {
+ return {
+ badgeCount: vgResp?.comments.totalCount,
+ badgeColor: '#cccccc',
...tab,
}
} else {
diff --git a/client/src/app/views/variants/variants-detail/variants-detail.view.ts b/client/src/app/views/variants/variants-detail/variants-detail.view.ts
index d48742137..a0158556d 100644
--- a/client/src/app/views/variants/variants-detail/variants-detail.view.ts
+++ b/client/src/app/views/variants/variants-detail/variants-detail.view.ts
@@ -26,7 +26,6 @@ export class VariantsDetailView implements OnDestroy {
variant$?: Observable>
loading$?: Observable
- commentsTotal$?: Observable
flagsTotal$?: Observable
viewer$: Observable
@@ -80,19 +79,23 @@ export class VariantsDetailView implements OnDestroy {
this.variant$ = observable.pipe(pluck('data', 'variant'))
- this.commentsTotal$ = this.variant$.pipe(pluck('comments', 'totalCount'))
-
this.flagsTotal$ = this.variant$.pipe(pluck('flags', 'totalCount'))
this.variant$
- .pipe(pluck('revisions', 'totalCount'), takeUntil(this.destroy$))
+ .pipe(takeUntil(this.destroy$))
.subscribe({
- next: (count) => {
+ next: (variantResp) => {
this.tabs$.next(
this.defaultTabs.map((tab) => {
if (tab.tabLabel === 'Revisions') {
return {
- badgeCount: count as number,
+ badgeCount: variantResp?.revisions.totalCount,
+ ...tab,
+ }
+ } else if (tab.tabLabel === 'Comments') {
+ return {
+ badgeCount: variantResp?.comments.totalCount,
+ badgeColor: '#cccccc',
...tab,
}
} else {
diff --git a/server/app/models/source.rb b/server/app/models/source.rb
index 818aea871..2d579ffa6 100644
--- a/server/app/models/source.rb
+++ b/server/app/models/source.rb
@@ -2,6 +2,7 @@ class Source < ActiveRecord::Base
include ModeratedField
include Subscribable
include WithTimepointCounts
+ include Commentable
has_many :evidence_items
has_and_belongs_to_many :genes