Skip to content
This repository was archived by the owner on May 14, 2025. It is now read-only.

Commit ad3c7c9

Browse files
committed
Angular boostrap tooltips for JointJS shapes
- Tooltips for nodes - Tooltips for JointJS shapes - Tooltips for JointJS shapes - Fixes #438
1 parent e0aaf66 commit ad3c7c9

25 files changed

+629
-24
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<svg:g class="rotatable" [tooltip]="markerTooltip" placement="right"
2+
containerClass="{{kind + '-marker-tooltip'}}" container="body">
3+
<svg:g class="scalable">
4+
<svg:image/>
5+
</svg:g>
6+
</svg:g>
7+
8+
<template #markerTooltip>
9+
<div>
10+
<li *ngFor="let msg of getMessages()">{{msg}}</li>
11+
</div>
12+
</template>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.error-marker-tooltip .tooltip-inner {
2+
background-color: red;
3+
max-width: 400px;
4+
}
5+
.tooltip.error-marker-tooltip .tooltip-arrow {
6+
border-right-color: red;
7+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Shapes } from 'spring-flo';
2+
import { dia } from 'jointjs';
3+
import { RenderService } from '../render.service';
4+
import { MockMetamodelService } from '../mocks/mock-metamodel.service';
5+
import { DecorationComponent } from './decoration.component';
6+
import { Constants } from 'spring-flo';
7+
8+
import * as _joint from 'jointjs';
9+
const joint: any = _joint;
10+
11+
function createMockView(cell: dia.Element): any {
12+
return {
13+
model: cell,
14+
};
15+
}
16+
17+
describe('DecorationComponent Tests.', () => {
18+
19+
const MOCK_METAMODEL_SERVICE = new MockMetamodelService();
20+
const RENDER_SERVICE = new RenderService(MOCK_METAMODEL_SERVICE);
21+
22+
let graph: dia.Graph;
23+
let component: DecorationComponent;
24+
let parentNode: dia.Element;
25+
26+
beforeEach(() => {
27+
graph = new joint.dia.Graph();
28+
component = new DecorationComponent();
29+
parentNode = Shapes.Factory.createNode({
30+
metadata: MOCK_METAMODEL_SERVICE.data.get('source').get('http'),
31+
renderer: RENDER_SERVICE,
32+
graph: graph
33+
});
34+
});
35+
36+
it('No decoration view', () => {
37+
expect(component.kind).toEqual('');
38+
expect(component.getMessages()).toEqual([]);
39+
});
40+
41+
it('Error Marker', () => {
42+
const errorMarker = Shapes.Factory.createDecoration({
43+
kind: Constants.ERROR_DECORATION_KIND,
44+
messages: [
45+
'm1', 'm2', 'm3'
46+
],
47+
parent: parentNode,
48+
renderer: RENDER_SERVICE,
49+
graph: graph
50+
});
51+
component.view = createMockView(errorMarker);
52+
expect(component.kind).toEqual(Constants.ERROR_DECORATION_KIND);
53+
expect(component.getMessages()).toEqual(['m1', 'm2', 'm3']);
54+
});
55+
56+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Component, ViewEncapsulation } from '@angular/core';
2+
import { dia } from 'jointjs';
3+
import { BaseShapeComponent } from '../support/shape-component';
4+
5+
/**
6+
* Component for displaying application properties and capturing their values.
7+
*
8+
* @author Alex Boyko
9+
* @author Andy Clement
10+
*/
11+
@Component({
12+
selector: 'app-flo-decoration',
13+
templateUrl: 'decoration.component.html',
14+
styleUrls: [ 'decoration.component.scss' ],
15+
encapsulation: ViewEncapsulation.None
16+
})
17+
export class DecorationComponent extends BaseShapeComponent {
18+
19+
getMessages(): Array<string> {
20+
return this.view && Array.isArray(this.view.model.attr('messages')) ? this.view.model.attr('messages') : [];
21+
}
22+
23+
get kind(): string {
24+
return this.view ? this.view.model.attr('./kind') : '';
25+
}
26+
27+
}
28+

ui/src/app/streams/flo/editor.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { ApplicationType } from '../../shared/model/application-type';
2020
import { Flo, Constants } from 'spring-flo';
2121
import { dia } from 'jointjs';
2222
import { PropertiesDialogComponent } from './properties/properties-dialog.component';
23-
import { Utils } from './utils';
23+
import { Utils } from './support/utils';
2424
import * as _joint from 'jointjs';
2525
const joint: any = _joint;
2626

ui/src/app/streams/flo/flo.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,3 +406,7 @@ $spring-grey: $gray;
406406
background-color: transparent;
407407
}
408408

409+
.tooltip {
410+
position: absolute;
411+
}
412+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<svg:g class="rotatable" [tooltip]="tooltipText" [placement]="placement" container="body">
2+
<svg:g class="scalable">
3+
<svg:image/>
4+
</svg:g>
5+
</svg:g>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { Shapes } from 'spring-flo';
2+
import { dia } from 'jointjs';
3+
import { RenderService } from '../render.service';
4+
import { MockMetamodelService } from '../mocks/mock-metamodel.service';
5+
import { HandleComponent } from './handle.component';
6+
import { Constants } from 'spring-flo';
7+
8+
import * as _joint from 'jointjs';
9+
const joint: any = _joint;
10+
11+
function createMockView(cell: dia.Element): any {
12+
return {
13+
model: cell,
14+
};
15+
}
16+
17+
describe('HandleComponent Tests.', () => {
18+
19+
const MOCK_METAMODEL_SERVICE = new MockMetamodelService();
20+
const RENDER_SERVICE = new RenderService(MOCK_METAMODEL_SERVICE);
21+
22+
let graph: dia.Graph;
23+
let component: HandleComponent;
24+
let parentNode: dia.Element;
25+
26+
beforeEach(() => {
27+
graph = new joint.dia.Graph();
28+
component = new HandleComponent();
29+
parentNode = Shapes.Factory.createNode({
30+
metadata: MOCK_METAMODEL_SERVICE.data.get('source').get('http'),
31+
renderer: RENDER_SERVICE,
32+
graph: graph
33+
});
34+
});
35+
36+
it('No handle view', () => {
37+
expect(component.placement).toEqual('top');
38+
expect(component.tooltipText).toBeUndefined();
39+
});
40+
41+
it('Remove Handle', () => {
42+
const removeHandle = Shapes.Factory.createHandle({
43+
kind: Constants.REMOVE_HANDLE_TYPE,
44+
parent: parentNode,
45+
renderer: RENDER_SERVICE,
46+
graph: graph
47+
});
48+
component.view = createMockView(removeHandle);
49+
expect(component.placement).toEqual('bottom');
50+
expect(component.tooltipText).toEqual('Remove Element');
51+
});
52+
53+
it('Edit Properties Handle', () => {
54+
const propertiesHandle = Shapes.Factory.createHandle({
55+
kind: Constants.PROPERTIES_HANDLE_TYPE,
56+
parent: parentNode,
57+
renderer: RENDER_SERVICE,
58+
graph: graph
59+
});
60+
component.view = createMockView(propertiesHandle);
61+
expect(component.placement).toEqual('bottom');
62+
expect(component.tooltipText).toEqual('Edit Properties');
63+
});
64+
65+
it('Random Handle', () => {
66+
const randomHandle = Shapes.Factory.createHandle({
67+
kind: 'random',
68+
parent: parentNode,
69+
renderer: RENDER_SERVICE,
70+
graph: graph
71+
});
72+
component.view = createMockView(randomHandle);
73+
expect(component.placement).toEqual('top');
74+
expect(component.tooltipText).toBeUndefined();
75+
});
76+
77+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Component, ViewEncapsulation } from '@angular/core';
2+
import { Constants } from 'spring-flo';
3+
import { BaseShapeComponent } from '../support/shape-component';
4+
5+
/**
6+
* Component for displaying application properties and capturing their values.
7+
*
8+
* @author Alex Boyko
9+
* @author Andy Clement
10+
*/
11+
@Component({
12+
selector: 'app-flo-handle',
13+
templateUrl: 'handle.component.html',
14+
encapsulation: ViewEncapsulation.None
15+
})
16+
export class HandleComponent extends BaseShapeComponent {
17+
18+
get tooltipText(): string {
19+
if (this.view) {
20+
switch (this.view.model.attr('./kind')) {
21+
case Constants.REMOVE_HANDLE_TYPE:
22+
return 'Remove Element';
23+
case Constants.PROPERTIES_HANDLE_TYPE:
24+
return 'Edit Properties';
25+
}
26+
}
27+
}
28+
29+
get placement(): string {
30+
if (this.view) {
31+
switch (this.view.model.attr('./kind')) {
32+
case Constants.REMOVE_HANDLE_TYPE:
33+
return 'bottom';
34+
case Constants.PROPERTIES_HANDLE_TYPE:
35+
return 'bottom';
36+
}
37+
}
38+
return 'top';
39+
}
40+
41+
}
42+

ui/src/app/streams/flo/metamodel.service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { ApplicationType } from '../../shared/model/application-type';
2121
import { DetailedAppRegistration, ConfigurationMetadataProperty } from '../../shared/model/detailed-app-registration.model';
2222
import { convertGraphToText } from './graph-to-text';
2323
import { convertTextToGraph } from './text-to-graph';
24-
import { OTHER_GROUP_TYPE } from './shapes';
24+
import { OTHER_GROUP_TYPE } from './support/shapes';
2525
import { Observable} from 'rxjs/Observable';
2626

2727
/**
@@ -59,7 +59,7 @@ class StreamAppMetadata implements Flo.ElementMetadata {
5959
const propertyMetadata: Flo.PropertyMetadata = {
6060
id: o.id,
6161
name: o.name,
62-
description: o.description,
62+
description: o.description || o.shortDescription,
6363
defaultValue: o.defaultValue,
6464
type: o.type
6565
};
@@ -95,7 +95,7 @@ class StreamAppMetadata implements Flo.ElementMetadata {
9595
}
9696

9797
description(): Promise<string> {
98-
return Promise.resolve(this._name);
98+
return Promise.resolve('');
9999
}
100100

101101
get(property: string): Promise<Flo.PropertyMetadata> {

0 commit comments

Comments
 (0)