Skip to content
This repository was archived by the owner on Jan 22, 2026. It is now read-only.

Commit 9f778fb

Browse files
authored
Merge pull request #574 from Sage-Bionetworks/develop-prov-tidying
Tidy functionality and styling for provenance components
2 parents 194d407 + 6dfc057 commit 9f778fb

File tree

17 files changed

+596
-100
lines changed

17 files changed

+596
-100
lines changed

client/app/app.constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,9 @@ let config = {
3636
}),
3737
};
3838

39+
config.activityTypeFilters.push({
40+
'value': 'all',
41+
'title': 'All'
42+
})
43+
3944
export default merge(config, shared);

client/app/project/project-activity/project-activity.component.ts

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
import { Component, OnInit, ViewChild } from '@angular/core';
1+
import { Component, OnInit, ViewChild, ViewChildren, QueryList, AfterViewInit } from '@angular/core';
2+
import { combineLatest, BehaviorSubject, Observable } from 'rxjs';
3+
import { map, filter, switchMap } from 'rxjs/operators';
4+
import { flow, keyBy, mapValues, values } from 'lodash/fp';
25

36
import { Activity } from 'models/provenance/activity.model';
47
import { Project } from 'models/entities/project.model';
8+
import { Filter } from 'components/filters/filter.model';
9+
import { FiltersComponent } from 'components/filters/filters.component';
510
import { NotificationService } from 'components/notification/notification.service';
611
import { ProvenanceService } from 'components/provenance/provenance.service';
712
import { ProvenanceGraphComponent } from 'components/provenance/provenance-graph/provenance-graph.component';
@@ -15,38 +20,70 @@ import { ProjectDataService } from '../project-data.service';
1520
template: require('./project-activity.html'),
1621
styles: [require('./project-activity.scss')],
1722
})
18-
export class ProjectActivityComponent implements OnInit {
23+
export class ProjectActivityComponent implements OnInit, AfterViewInit {
1924
@ViewChild(ProvenanceGraphComponent, { static: false }) provenanceGraph: ProvenanceGraphComponent;
25+
@ViewChildren(FiltersComponent) filters: QueryList<FiltersComponent>;
26+
private activityTypeFilters: Filter[] = [];
2027

2128
private project: Project;
29+
private root: BehaviorSubject<Project> = new BehaviorSubject<Project>(undefined);
2230
private provenanceGraphData: any;
23-
private activityTypeFilters = config.activityTypeFilters;
2431
private showNewActivityForm = false;
2532

33+
private query: BehaviorSubject<any> = new BehaviorSubject<any>({});
34+
2635
static parameters = [ProvenanceService, ProjectDataService, NotificationService];
27-
constructor(private provenanceService: ProvenanceService,
36+
constructor(
37+
private provenanceService: ProvenanceService,
2838
private projectDataService: ProjectDataService,
29-
private notificationService: NotificationService) { }
39+
private notificationService: NotificationService
40+
) { }
3041

3142
ngOnInit() {
43+
this.activityTypeFilters = config.activityTypeFilters;
3244
this.projectDataService.project()
33-
.subscribe(project => {
34-
this.project = project;
35-
const selectedFilter = config.activityTypeFilters.find(filter => filter.active);
36-
const defaultQuery = { activityType: selectedFilter.value };
37-
this.onFilterChange(defaultQuery);
45+
.subscribe(project => {
46+
this.root.next(project);
47+
this.project = project;
3848
}, err => console.error(err));
3949
}
4050

41-
onFilterChange(query) {
42-
if (this.project) {
43-
this.provenanceService.getProvenanceGraph('created_at', 'desc', 10)
44-
.subscribe(activity => {
51+
ngAfterViewInit() {
52+
console.log('FILTER LENGTH', this.filters.length);
53+
console.log('this.filters', this.filters);
54+
55+
let selectedFilters = this.filters
56+
.map(f => f.getSelectedFilter());
57+
58+
combineLatest(
59+
combineLatest(...selectedFilters)
60+
.pipe(
61+
map(myFilters => flow([keyBy('group'), mapValues('value')])(myFilters))
62+
),
63+
this.root.pipe(filter(root => !!root))
64+
)
65+
.pipe(
66+
switchMap(([query, root]) => {
67+
console.log('ROOT', root);
68+
var filter_str = '*:*';
69+
if (query.activityType !== 'all') {
70+
filter_str = `class:${query.activityType}`;
71+
}
72+
return (
73+
this.provenanceService.getProvenanceGraphByReference(root._id, 'down', 'created_at', 'desc', 100, filter_str)
74+
);
75+
})
76+
)
77+
.subscribe(activity => {
78+
console.log('ACTIVITY', activity);
79+
if (activity) {
4580
this.provenanceGraphData = activity;
46-
}, err => {
47-
console.log(err);
48-
});
49-
}
81+
}
82+
}, err => console.error(err));
83+
}
84+
85+
get root$(): Observable<Project> {
86+
return this.root.asObservable();
5087
}
5188

5289
onNewActivity(activity: Activity): void {

client/app/project/project-activity/project-activity.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
<div class="project-activities-container">
33
<div class="activities-graph-container">
44
<div class="activities-graph-filters-container">
5-
<h3>{{ entityName }} Type</h3>
6-
<radio-button-filter [filters]="activityTypeFilters" [group]="filterGroup"></radio-button-filter>
5+
<h3>Activity Type</h3>
6+
<radio-button-filter [filters]="activityTypeFilters" group="activityType"></radio-button-filter>
77
</div>
88
<div class="activities-graph-content-container">
99
<div class="activities-graph-results" (resized)="onResized($event)">
10-
<provenance-graph class="provenance-graph" [graphData]="provenanceGraphData" [rootId]=null></provenance-graph>
10+
<provenance-graph class="provenance-graph" [graphData]="provenanceGraphData" [rootId]=project._id></provenance-graph>
1111
</div>
1212
</div>
1313
</div>

client/components/activity/activity.service.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { AuthService } from 'components/auth/auth.service';
33
import { Subscription, Observable } from 'rxjs';
44
import { User } from 'models/auth/user.model';
55
import { ProvenanceService } from 'components/provenance/provenance.service';
6+
import config from '../../app/app.constants';
67

78
@Injectable()
89
export class ActivityService {
@@ -21,6 +22,15 @@ export class ActivityService {
2122

2223
// TODO Add input and output types
2324
save({ generatedName, generatedTargetId, generatedClass, generatedSubClass, usedEntities = [] }): Observable<any> {
25+
let activityTypeMap = Object.values(config.activityTypes);
26+
let activityTypeMatch = activityTypeMap
27+
.filter(a => a.entitySubtype === generatedSubClass);
28+
if (!activityTypeMatch) {
29+
activityTypeMatch = activityTypeMap
30+
.filter(a => a.entityType === generatedClass)
31+
.filter(a => a.entitySubtype === '');
32+
}
33+
let activityClass = activityTypeMatch.pop().value;
2434
const activity = {
2535
agents: [
2636
{
@@ -30,7 +40,7 @@ export class ActivityService {
3040
},
3141
],
3242
description: '',
33-
class: 'Report generation', // TODO set from generatedSubClass
43+
class: activityClass, // TODO set from generatedSubClass
3444
generated: [
3545
{
3646
name: generatedName,

client/components/insight/insight-new/insight-new.component.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export class InsightNewComponent {
4242
this.attachmentTypes = [
4343
config.entityTypes.INSIGHT,
4444
config.entityTypes.RESOURCE,
45-
config.entityTypes.PROJECT,
45+
// config.entityTypes.PROJECT,
4646
config.entityTypes.DATA_CATALOG,
4747
config.entityTypes.TOOL,
4848
];
@@ -90,6 +90,14 @@ export class InsightNewComponent {
9090
switchMap((res: any) => {
9191
let insight = res.insight;
9292
let attachments = res.attachments;
93+
attachments.push({
94+
'attachment': {
95+
'entityId': this.project._id,
96+
'entityType': config.entityTypes.PROJECT.value,
97+
'parentEntityId': insight._id
98+
},
99+
'entity': this.project
100+
});
93101

94102
let usedEntities = attachments.map(att => ({
95103
name: att.entity.title,

client/components/provenance/provenance-graph/activity-node/activity-node.component.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ export class ActivityNodeComponent extends ProvenanceNodeComponent {
1111
private classIconMap = {
1212
'ToolSession': this.iconDictionary.gears,
1313
'Mention': this.iconDictionary.at,
14-
'Memoization': this.iconDictionary.stickyNote,
15-
'ReportGeneration': this.iconDictionary.edit,
14+
'MemoCreation': this.iconDictionary.stickyNote,
15+
'ReportCreation': this.iconDictionary.edit,
1616
'Starred': this.iconDictionary.star,
17+
'ResourceRegistration': this.iconDictionary.link,
1718
};
1819

1920
get icon() {

client/components/provenance/provenance-graph/provenance-node/provenance-node.component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,15 @@ export class ProvenanceNodeComponent implements OnInit {
7070
lightbulb: '&#xf0eb',
7171
cube: '&#xf1b2',
7272
comment: '&#xf075',
73+
suitcase: '&#xf0f2',
74+
link: '&#xf0c1'
7375
};
7476

7577
colorDictionary = {
7678
blue: '#679EC1',
7779
orange: '#EB8231',
7880
green: '#6DB56D',
81+
gray: '#3C4A63'
7982
};
8083

8184
get r() {

client/components/provenance/provenance-graph/reference-node/reference-node.component.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { get } from 'lodash';
99
})
1010
export class ReferenceNodeComponent extends ProvenanceNodeComponent {
1111
private classIconMap = {
12+
'Project': this.iconDictionary.suitcase,
1213
'Insight': this.iconDictionary.lightbulb,
1314
'Resource': this.iconDictionary.cube,
1415
'Tool': this.iconDictionary.gear,
@@ -32,7 +33,11 @@ export class ReferenceNodeComponent extends ProvenanceNodeComponent {
3233
}
3334

3435
get color() {
35-
return this.colorDictionary.green;
36+
if (this.node.nodeClass === 'Project') {
37+
return this.colorDictionary.gray;
38+
} else {
39+
return this.colorDictionary.green;
40+
}
3641
}
3742

3843
get subclassImage() {

client/components/provenance/provenance.service.ts

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,66 @@ export class ProvenanceService {
1616
return this.httpClient.post<any>(`/api/provenance/batch`, body);
1717
}
1818

19-
getProvenanceGraph(sortBy: string, order: string, limit: number): Observable<any> {
19+
getProvenanceGraph(
20+
sortBy: string,
21+
order: string,
22+
limit: number,
23+
filter: string = '*:*'
24+
): Observable<any> {
2025
let params = new HttpParams()
2126
.set('sortBy', sortBy)
2227
.set('order', order)
23-
.set('limit', String(limit));
28+
.set('limit', String(limit))
29+
.set('filter', filter);
2430
return this.httpClient.get<any>(`/api/provenance`, {params});
2531
}
2632

27-
getProvenanceGraphByAgent(agentId: string, sortBy: string, order: string, limit: number): Observable<any> {
33+
getProvenanceGraphByAgent(
34+
agentId: string,
35+
sortBy: string,
36+
order: string,
37+
limit: number,
38+
filter: string = '*:*'
39+
): Observable<any> {
2840
let params = new HttpParams()
2941
.set('sortBy', sortBy)
3042
.set('order', order)
31-
.set('limit', String(limit));
43+
.set('limit', String(limit))
44+
.set('filter', filter);
3245
return this.httpClient.get<any>(`/api/provenance/byAgent/${agentId}`, {params});
3346
}
3447

35-
getProvenanceGraphByReference(referenceId: string, direction: string, sortBy: string, order: string, limit: number): Observable<any> {
48+
getProvenanceGraphByReference(
49+
referenceId: string,
50+
direction: string,
51+
sortBy: string,
52+
order: string,
53+
limit: number,
54+
filter: string = '*:*'
55+
): Observable<any> {
3656
let params = new HttpParams()
3757
.set('direction', direction)
3858
.set('sortBy', sortBy)
3959
.set('order', order)
40-
.set('limit', String(limit));
60+
.set('limit', String(limit))
61+
.set('filter', filter);
4162
return this.httpClient.get<any>(`/api/provenance/byReference/${referenceId}`, {params});
4263
}
64+
65+
getProvenanceActivitiesByReference(
66+
referenceId: string,
67+
direction: string,
68+
sortBy: string,
69+
order: string,
70+
limit: number,
71+
filter: string = '*:*'
72+
): Observable<any> {
73+
let params = new HttpParams()
74+
.set('direction', direction)
75+
.set('sortBy', sortBy)
76+
.set('order', order)
77+
.set('limit', String(limit))
78+
.set('filter', filter);
79+
return this.httpClient.get<any>(`/api/provenance/byReference/${referenceId}/data`, {params});
80+
}
4381
}

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ services:
9595
- /tmp/neo4j/logs:/logs
9696

9797
phccp-prov:
98-
image: docker.synapse.org/syn18489221/prov-service:1.0.0-alpha.0
98+
image: docker.synapse.org/syn18489221/prov-service:1.0.0-alpha.1
9999
command: python3 -m synprov
100100
container_name: phccp-prov
101101
ports:

0 commit comments

Comments
 (0)