Skip to content

Commit dd3fe37

Browse files
authored
Merge pull request #5 from Distributed-Noracle/develop
Develop
2 parents 2ec3b86 + 921fa30 commit dd3fe37

File tree

52 files changed

+12773
-188
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+12773
-188
lines changed

package-lock.json

Lines changed: 12136 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/graph-view/graph-view-page/graph-view-page.component.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
font-weight: bold;
99
}
1010

11+
.bw {
12+
background-color: white;
13+
}
14+
1115
.memberList {
1216
padding-top: 15px;
1317
right: 10px;

src/app/graph-view/graph-view-page/graph-view-page.component.html

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,24 @@
33
<mat-accordion displayMode="flat" multi="true">
44
<mat-expansion-panel expanded="true">
55
<mat-expansion-panel-header expandedHeight="30px" collapsedHeight="30px">
6-
Participants
6+
<span class="bw">Participants</span>
77
</mat-expansion-panel-header>
88
<ul>
9-
<li *ngFor="let m of spaceMembers">{{m}}</li>
9+
<li *ngFor="let m of spaceMembers"><span class="bw">{{m}}</span></li>
1010
</ul>
1111
</mat-expansion-panel>
1212

1313
<mat-expansion-panel>
1414
<mat-expansion-panel-header expandedHeight="30px" collapsedHeight="30px">
15-
Help
15+
<span class="bw">Help</span>
1616
</mat-expansion-panel-header>
1717
<ul>
18-
<li><md-icon style="font-weight: bold">chat_bubble_outline</md-icon> selected / <md-icon>chat_bubble_outline</md-icon> deselected</li>
19-
<li><md-icon style="color: green">chat_bubble_outline</md-icon> rated positively / <md-icon style="color: rgb(255, 0, 0)">chat_bubble_outline</md-icon> rated negatively</li>
20-
<li><span style="font-weight: bold">>>></span> follow-up question</li>
21-
<li><span style="font-weight: bold">――</span> related question</li>
22-
<li>―――――――――――――――――――――</li>
23-
<li>More questions? <a href="mailto:[email protected]">[email protected]</a></li>
18+
<li><span class="bw"><md-icon style="font-weight: bold">chat_bubble_outline</md-icon> selected / <md-icon>chat_bubble_outline</md-icon> deselected</span></li>
19+
<li><span class="bw"><md-icon style="color: green">chat_bubble_outline</md-icon> rated positively / <md-icon style="color: rgb(255, 0, 0)">chat_bubble_outline</md-icon> rated negatively</span></li>
20+
<li><span class="bw"><span style="font-weight: bold">>>></span> follow-up question</span></li>
21+
<li><span class="bw"><span style="font-weight: bold">――</span> related question</span></li>
22+
<li><span class="bw">―――――――――――――――――――――</span></li>
23+
<li><span class="bw">More questions? <a href="mailto:[email protected]">[email protected]</a></span></li>
2424
</ul>
2525
</mat-expansion-panel>
2626
</mat-accordion>

src/app/graph-view/graph-view-page/graph-view-page.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class GraphViewPageComponent implements OnInit, OnDestroy {
3131
this.height = (window.innerHeight
3232
- this.graphContainer.nativeElement.getBoundingClientRect().top
3333
- this.below.nativeElement.getBoundingClientRect().height) * 0.9;
34-
this.width = window.innerWidth * 0.9;
34+
this.width = window.innerWidth * 0.95;
3535
}
3636

3737
constructor(elementRef: ElementRef, private activatedRoute: ActivatedRoute,
@@ -98,8 +98,8 @@ export class GraphViewPageComponent implements OnInit, OnDestroy {
9898
return 'Add Question';
9999
case 'AddRelation':
100100
return 'Add Relation';
101-
case 'EditAndAssess':
102-
return 'Edit/Assess';
101+
case 'Inspect':
102+
return 'Vote/Edit';
103103
}
104104
}
105105
}

src/app/graph-view/graph-view.module.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ import {FlexLayoutModule} from '@angular/flex-layout';
1414
import {SharedModule} from '../shared/shared.module';
1515
import {RelationPickerDialogComponent} from './relation-picker-dialog/relation-picker-dialog.component';
1616
import {CreateQuestionDialogComponent} from './create-question-dialog/create-question-dialog.component';
17-
import {VoteDialogComponent} from './vote-dialog/vote-dialog.component';
17+
import {InspectDialogComponent} from './inspect-dialog/inspect-dialog.component';
18+
import {VoteDonutComponent, ItemDirective} from './vote-donut/vote-donut.component';
19+
import {InspectEdgeDialogComponent} from './inspect-edge-dialog/inspect-edge-dialog.component';
1820

1921
@NgModule({
2022
imports: [
@@ -34,8 +36,11 @@ import {VoteDialogComponent} from './vote-dialog/vote-dialog.component';
3436
],
3537
schemas: [CUSTOM_ELEMENTS_SCHEMA],
3638
declarations: [GraphViewComponent, GraphViewPageComponent, RelationPickerDialogComponent,
37-
CreateQuestionDialogComponent, VoteDialogComponent],
38-
bootstrap: [RelationPickerDialogComponent, CreateQuestionDialogComponent, VoteDialogComponent],
39+
CreateQuestionDialogComponent, InspectDialogComponent, VoteDonutComponent,
40+
ItemDirective,
41+
InspectEdgeDialogComponent],
42+
bootstrap: [RelationPickerDialogComponent, CreateQuestionDialogComponent,
43+
InspectDialogComponent, VoteDonutComponent, InspectEdgeDialogComponent],
3944
exports: [GraphViewPageComponent],
4045
providers: [D3Service, GraphViewService]
4146
})

src/app/graph-view/graph-view/graph-data-model/edge.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {SimulationLinkDatum} from 'd3-force';
22
import {GraphNode} from './graph-node';
33
import {Relation} from '../../../shared/rest-data-model/relation';
44
import {DrawUtil} from '../utils/draw-util';
5+
import { RelationType } from './relation-type.enum';
56

67
export class Edge implements SimulationLinkDatum<GraphNode> {
78

@@ -24,7 +25,7 @@ export class Edge implements SimulationLinkDatum<GraphNode> {
2425
}
2526

2627
draw(context: CanvasRenderingContext2D) {
27-
if (this.relation.directed) {
28+
if (this.relation.name === 'FollowUp') {
2829
this.drawDirected(context);
2930
} else {
3031
this.drawUndirected(context);

src/app/graph-view/graph-view/graph-data-model/graph-interaction-mode.enum.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ export enum GraphInteractionMode {
33
DragAndZoom,
44
AddQuestion,
55
AddRelation,
6-
EditAndAssess
6+
Inspect
77
}

src/app/graph-view/graph-view/graph-data-model/graph-node.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export class GraphNode implements SimulationNodeDatum {
1111
private bubbleScaleFactor = 1.25;
1212
public radius;
1313
public relationVotes: Map<string, RelationVote[]> = new Map<string, RelationVote[]>();
14+
public relations: Relation[];
1415

1516
/**
1617
* Node’s current x-position
@@ -24,8 +25,9 @@ export class GraphNode implements SimulationNodeDatum {
2425

2526
constructor(context: CanvasRenderingContext2D, public id: string,
2627
public question: Question, public questionAuthor: string, public questionVotes: QuestionVote[],
27-
public relations: Relation[], public relationAuthors: string[], relationVotes: RelationVote[][],
28+
relations: Relation[], public relationAuthors: string[], relationVotes: RelationVote[][],
2829
public isSelected = false, public isSeed = false) {
30+
this.relations = relations.slice(0);
2931
this.lines = this.wrapText((s) => context.measureText(s).width);
3032
for (let i = 0; i < relations.length; i++) {
3133
this.relationVotes.set(relations[i].relationId, relationVotes[i] !== undefined ? relationVotes[i] : []);
@@ -147,7 +149,7 @@ export class GraphNode implements SimulationNodeDatum {
147149
return false;
148150
}
149151
this.question = n.question;
150-
this.relations = n.relations;
152+
this.relations = n.relations.splice(0);
151153
this.lines = n.lines;
152154
this.radius = n.radius;
153155
this.textSize = n.textSize;
@@ -162,18 +164,17 @@ export class GraphNode implements SimulationNodeDatum {
162164
this.question.questionId === n.question.questionId &&
163165
this.question.timestampLastModified === n.question.timestampLastModified &&
164166
this.relations.length === n.relations.length &&
165-
this.relations.map(r => n.relations
166-
.findIndex(r2 => r2.relationId === r.relationId && r2.timestampLastModified === r.timestampLastModified) !== -1)
167-
.reduce((prev, cur) => prev && cur, true) &&
167+
JSON.stringify(this.relations) === JSON.stringify(n.relations) &&
168168
this.lines.map((l, i) => l === n.lines[i]).reduce((prev, cur) => prev && cur, true) &&
169169
this.radius === n.radius &&
170170
this.textSize === n.textSize &&
171171
this.bubbleScaleFactor === n.bubbleScaleFactor &&
172172
this.questionVotes.length === n.questionVotes.length &&
173+
this.questionVotes.map((v, i) => v.value === n.questionVotes[i].value).reduce((p, c) => p && c, true) &&
173174
this.relations.map(r =>
174175
this.relationVotes.get(r.relationId).length === n.relationVotes.get(r.relationId).length &&
175176
this.relationVotes.get(r.relationId).map((v, i) => v.value === n.relationVotes.get(r.relationId)[i].value &&
176-
v.voterAgentId === n.relationVotes.get(r.relationId)[i].voterAgentId).reduce((p, c) => p && c, true)
177+
v.voterAgentId === n.relationVotes.get(r.relationId)[i].voterAgentId).reduce((p, c) => p && c, true)
177178
).reduce((p, c) => p && c, true);
178179
}
179180
}

src/app/graph-view/graph-view/graph-data-model/network.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {GraphNode} from './graph-node';
22
import {Edge} from './edge';
3+
import { Relation } from '../../../shared/rest-data-model/relation';
34
/**
45
* Created by bgoeschlberger on 28.09.2017.
56
*/
@@ -39,7 +40,12 @@ export class Network {
3940
hasChanged = true;
4041
}
4142
nodeToAdd.relations.forEach((r, i) => {
42-
if (this.edges.findIndex((e) => e.id === r.relationId) === -1) {
43+
const index = this.edges.findIndex((e) => e.id === r.relationId);
44+
const needsUpdate = index !== -1 && (!this.edges[index].relation.equals || !this.edges[index].relation.equals(r));
45+
if (needsUpdate) {
46+
this.edges.splice(index, 1);
47+
}
48+
if (index === -1 || needsUpdate) {
4349
// edge not yet in network
4450
const node1 = this.nodes.find((n) => r.firstQuestionId === n.id);
4551
const node2 = this.nodes.find((n) => n.id === r.secondQuestionId);

src/app/graph-view/graph-view/graph-view.component.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {AddRelationBehavior} from './interaction-behaviors/add-relation-behavior
1515
import {Subscription} from 'rxjs/Subscription';
1616
import {MdDialog} from '@angular/material';
1717
import {AgentService} from '../../shared/agent/agent.service';
18+
import {QuestionVoteService} from '../../shared/question-vote/question-vote.service';
1819
import {EdgeInteractionBehavior} from './interaction-behaviors/edge-interaction-behavior';
1920
import {EditRelationBehavior} from './interaction-behaviors/edit-relation-behavior';
2021
import {UpdateData} from './graph-data-model/update-data';
@@ -46,7 +47,8 @@ export class GraphViewComponent implements OnInit, OnChanges, OnDestroy {
4647

4748

4849
constructor(private graphViewService: GraphViewService, private agentService: AgentService,
49-
private d3Service: D3Service, private dialog: MdDialog) {
50+
private questionVoteService: QuestionVoteService, private d3Service: D3Service,
51+
private dialog: MdDialog) {
5052
this.d3 = d3Service.getD3();
5153
this.transform = this.d3.zoomIdentity;
5254
}
@@ -82,8 +84,6 @@ export class GraphViewComponent implements OnInit, OnChanges, OnDestroy {
8284
this.network.getNodes().forEach((node) => {
8385
node.isSelected = (this.selectedQuestions.indexOf(node.id) !== -1);
8486
});
85-
// this.d3Sim.force('center', this.d3.forceCenter(this.width / 2, this.height / 2));
86-
// this.d3Sim.alpha(1).restart();
8787
this.updateInteractionMode();
8888
}
8989
}
@@ -129,21 +129,24 @@ export class GraphViewComponent implements OnInit, OnChanges, OnDestroy {
129129
// no change
130130
return;
131131
}
132+
132133
if (this.interactionMode === GraphInteractionMode.SelectAndNavigate) {
133134
// TODO: review: a new behavior every time? maybe use services?
134135
this.setSelectionBehaviors(new ChangeNodeSelectionBehavior(this.network, this.graphViewService), null);
135136
} else if (this.interactionMode === GraphInteractionMode.AddQuestion) {
136137
this.setSelectionBehaviors(new AddChildNodeBehavior(this.graphViewService, this.dialog), null);
137138
} else if (this.interactionMode === GraphInteractionMode.AddRelation) {
138139
this.setSelectionBehaviors(new AddRelationBehavior(this.graphViewService, this.dialog), null);
139-
} else if (this.interactionMode === GraphInteractionMode.EditAndAssess) {
140+
} else if (this.interactionMode === GraphInteractionMode.Inspect) {
140141
this.setSelectionBehaviors(
141142
new EditQuestionBehavior(this.graphViewService, this.agentService, this.dialog),
142143
new EditRelationBehavior(this.graphViewService, this.agentService, this.dialog)
143144
);
144145
} else {
145146
this.setDragAndZoomBehavior();
146147
}
148+
149+
this.activatedInteractionMode = this.interactionMode;
147150
}
148151

149152
private setDragAndZoomBehavior() {

src/app/graph-view/graph-view/graph-view.service.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -205,17 +205,22 @@ export class GraphViewService {
205205

206206
private fetchAll(spaceId: string) {
207207
// load all questions and all relations of the space
208-
const questionsAndRelationsPromise = Promise.all([this.questionService.getQuestionsOfSpace(spaceId).then((res) => {
209-
this.questions = res;
210-
const seedIndex = this.observedQuestionIds.indexOf('seed');
211-
if (seedIndex !== -1 && this.questions.length > 0) {
212-
this.observedQuestionIds.splice(seedIndex, 1);
213-
this.observedQuestionIds.push(this.questions[0].questionId);
214-
}
215-
return this.questions;
216-
}),
217-
this.relationService.getRelationsOfSpace(spaceId).then((res) =>
218-
this.relations = res)]);
208+
const questionsAndRelationsPromise = Promise.all([
209+
this.questionService.getQuestionsOfSpace(spaceId).then((res) => {
210+
this.questions = res;
211+
this.questions.forEach(q => this.questionVotes.set(q.questionId, q.votes));
212+
const seedIndex = this.observedQuestionIds.indexOf('seed');
213+
if (seedIndex !== -1 && this.questions.length > 0) {
214+
this.observedQuestionIds.splice(seedIndex, 1);
215+
this.observedQuestionIds.push(this.questions[0].questionId);
216+
}
217+
return this.questions;
218+
}),
219+
this.relationService.getRelationsOfSpace(spaceId).then((res) => {
220+
this.relations = res;
221+
this.relations.forEach(r => this.relationVotes.set(r.relationId, r.votes));
222+
})
223+
]);
219224

220225
// when all questions and relations are loaded
221226
questionsAndRelationsPromise.then(() => {
@@ -244,17 +249,13 @@ export class GraphViewService {
244249

245250
private loadRelationRelatedData(spaceId: string, r: Relation): Promise<any> {
246251
return Promise.all([
247-
this.relationVoteService.getRelationVotes(spaceId, r.relationId)
248-
.then((rv) => this.relationVotes.set(r.relationId, rv)),
249252
this.agentService.getAgentName(r.authorId)
250253
.then(ra => this.relationAuthors.set(r.relationId, ra))
251254
]);
252255
}
253256

254257
private loadQuestionRelatedData(spaceId: string, q: Question): Promise<any> {
255258
return Promise.all([
256-
this.questionVoteService.getQuestionVotes(spaceId, q.questionId)
257-
.then((qv) => this.questionVotes.set(q.questionId, qv)),
258259
this.agentService.getAgentName(q.authorId)
259260
.then(qa => this.questionAuthors.set(q.questionId, qa))
260261
]);

src/app/graph-view/graph-view/interaction-behaviors/edit-question-behavior.ts

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import {NodeInteractionBehavior} from './node-interaction-behavior';
22
import {GraphNode} from '../graph-data-model/graph-node';
33
import {GraphViewService} from '../graph-view.service';
44
import {MdDialog} from '@angular/material';
5-
import {CreateQuestionDialogComponent} from '../../create-question-dialog/create-question-dialog.component';
5+
import {InspectDialogComponent} from '../../inspect-dialog/inspect-dialog.component';
66
import {AgentService} from '../../../shared/agent/agent.service';
7-
import {VoteDialogComponent} from '../../vote-dialog/vote-dialog.component';
7+
import {QuestionVoteService} from '../../../shared/question-vote/question-vote.service'
8+
import {timestamp} from 'rxjs/operator/timestamp';
9+
import {VoteUtil} from '../utils/vote-util';
810

911
export class EditQuestionBehavior extends NodeInteractionBehavior {
1012

@@ -13,41 +15,33 @@ export class EditQuestionBehavior extends NodeInteractionBehavior {
1315
super();
1416
}
1517

16-
interactWith(node: GraphNode): Promise<any> {
17-
return this.agentService.getAgent().then((agent) => {
18-
if (agent.agentid === node.question.authorId) {
19-
const dialogRef = this.dialog.open(CreateQuestionDialogComponent, {
20-
width: '250px',
21-
data: {
22-
title: 'Edit Question',
23-
message: 'Edit question text and click Ok to save',
24-
text: node.question.text
25-
}
26-
});
27-
return dialogRef.afterClosed().toPromise().then(result => {
28-
if (result !== undefined) {
29-
return this.graphViewService.updateQuestion(node.id, result);
30-
}
31-
});
32-
} else {
33-
const myVote = node.questionVotes.find(vote => agent.agentid === vote.voterAgentId);
34-
const dialogRef = this.dialog.open(VoteDialogComponent, {
35-
width: '80%',
36-
data: {
37-
title: 'Assess Question',
38-
message: 'What is your opinion regarding this question:\n' + node.question.text,
39-
upvoteText: 'I like that question. It is particularly helpful for me.',
40-
neutralText: 'I am undecided whether this question is helpful for me.',
41-
downvoteText: 'This question did not help me.',
42-
vote: myVote !== undefined ? myVote.value : 0
43-
}
44-
});
45-
return dialogRef.afterClosed().toPromise().then(result => {
46-
if (result !== undefined) {
47-
this.graphViewService.updateQuestionVote(node.id, agent.agentid, result);
48-
}
49-
});
18+
async interactWith(node: GraphNode): Promise<any> {
19+
const agent = await this.agentService.getAgent();
20+
const authorName = await this.agentService.getAgentName(node.question.authorId);
21+
const questionVotes = node.questionVotes;
22+
const votes = VoteUtil.countVotes(questionVotes);
23+
24+
const isAuthor = agent.agentid === node.question.authorId;
25+
const myVote = questionVotes.find(vote => agent.agentid === vote.voterAgentId);
26+
27+
const data = {
28+
isAuthor: isAuthor,
29+
text: node.question.text,
30+
authorName: authorName,
31+
lastModified: new Date(node.question.timestampLastModified).toLocaleString(),
32+
inputHeading: `${authorName} (${node.question.timestampLastModified})`,
33+
votes: votes,
34+
vote: myVote ? myVote.value : undefined
35+
};
36+
37+
const dialogRef = this.dialog.open(InspectDialogComponent, {data: data});
38+
const result = await dialogRef.afterClosed().toPromise();
39+
if (result !== undefined) {
40+
if (isAuthor) {
41+
await this.graphViewService.updateQuestion(node.id, data.text);
42+
} else if (data.vote !== undefined) {
43+
await this.graphViewService.updateQuestionVote(node.id, agent.agentid, data.vote);
5044
}
51-
});
45+
}
5246
}
5347
}

0 commit comments

Comments
 (0)