Skip to content

Commit 2e3367b

Browse files
committed
Merge branch 'feature/445-add-basic-sender-pipe'
2 parents 3abf0b9 + 1e6b460 commit 2e3367b

24 files changed

+1100
-215
lines changed

frank-flow/src/frontend/README.md

Lines changed: 0 additions & 31 deletions
This file was deleted.

frank-flow/src/frontend/src/app/flow/flow.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { FormsModule } from '@angular/forms';
1111
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
1212
import { NgxPanZoomModule } from 'ngx-panzoom';
1313
import { ActionsComponent } from './actions/actions.component';
14+
import { NestedElementComponent } from './options/nested-element/nested-element.component';
1415

1516
@NgModule({
1617
declarations: [
@@ -19,6 +20,7 @@ import { ActionsComponent } from './actions/actions.component';
1920
NodeComponent,
2021
OptionsComponent,
2122
ActionsComponent,
23+
NestedElementComponent,
2224
],
2325
exports: [FlowComponent],
2426
imports: [
Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,31 @@
11
<div class="node">
22
<div class="node__icon">
3-
<fa-icon [icon]="cloud"></fa-icon>
3+
<fa-icon [icon]="puzzlePiece"></fa-icon>
44
</div>
55
<div [title]="node.getType()" class="node__type">
66
{{ node.getType() }}
77
</div>
88
<div [title]="node.getName()" class="node__name">
99
{{ node.getName() }}
1010
</div>
11-
<div class="node__badges"></div>
11+
<div class="node__badges">
12+
<div
13+
[title]="senders[0]?.name"
14+
*ngIf="senders.length === 1; else senderCount"
15+
class="node__sender"
16+
>
17+
<fa-icon size="xs" [icon]="paperPlane"></fa-icon> {{ senders[0]?.name }}
18+
</div>
19+
<ng-template #senderCount>
20+
<div
21+
[title]="senders.length + ' senders'"
22+
*ngIf="senders.length > 1"
23+
class="node__sender"
24+
>
25+
<fa-icon size="sm" [icon]="paperPlane"></fa-icon>
26+
{{ senders.length }} senders
27+
<!-- TODO: Pipe only can have one sender, this should be implemented for the parallelSender-->
28+
</div>
29+
</ng-template>
30+
</div>
1231
</div>

frank-flow/src/frontend/src/app/flow/node/node.component.scss

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
grid-row-start: 3;
3333
grid-column-start: 1;
3434
}
35+
36+
&__badges {
37+
grid-row-start: 4;
38+
grid-column-start: 1;
39+
}
3540
}
3641
}
3742

@@ -53,6 +58,11 @@
5358
grid-row-start: 3;
5459
grid-column-start: 1;
5560
}
61+
62+
&__badges {
63+
grid-row-start: 4;
64+
grid-column-start: 1;
65+
}
5666
}
5767
}
5868

@@ -82,7 +92,7 @@
8292

8393
&.color--success {
8494
color: var(--success);
85-
background: var(--success-lighter-4);
95+
background: var(--success-lighter-7);
8696
border: 1px solid var(--success-darker-1);
8797

8898
&.jtk-drag {
@@ -134,6 +144,27 @@
134144
overflow: hidden;
135145
text-overflow: ellipsis;
136146
}
147+
148+
&__badges {
149+
grid-column-start: 2;
150+
grid-row-start: 3;
151+
width: 100%;
152+
overflow: hidden;
153+
}
154+
155+
&__sender {
156+
display: inline-block;
157+
max-width: 100%;
158+
font-size: 11px;
159+
color: var(--success);
160+
background: var(--success-lighter-7);
161+
border: 1px solid var(--success-darker-1);
162+
border-radius: 5px;
163+
white-space: nowrap;
164+
overflow: hidden;
165+
text-overflow: ellipsis;
166+
padding: 2px;
167+
}
137168
}
138169

139170
&:hover {

frank-flow/src/frontend/src/app/flow/node/node.component.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
} from 'jsplumb';
1717
import { NgxSmartModalService } from 'ngx-smart-modal';
1818
import { FlowStructureService } from 'src/app/shared/services/flow-structure.service';
19-
import { faCloudDownloadAlt } from '@fortawesome/free-solid-svg-icons';
19+
import { faPuzzlePiece, faPaperPlane } from '@fortawesome/free-solid-svg-icons';
2020
import { SettingsService } from 'src/app/header/settings/settings.service';
2121
import { Settings } from 'src/app/header/settings/settings.model';
2222
import { ForwardStyle } from 'src/app/header/settings/options/forward-style';
@@ -42,8 +42,12 @@ export class NodeComponent implements AfterViewInit {
4242
public get isActive() {
4343
return this.flowStructureService.selectedNode?.uid === this.node?.getId();
4444
}
45+
public get senders() {
46+
return this.node.getSenders() ?? [];
47+
}
4548

46-
public readonly cloud = faCloudDownloadAlt;
49+
public readonly puzzlePiece = faPuzzlePiece;
50+
public readonly paperPlane = faPaperPlane;
4751

4852
private defaultSettings = new DefaultSettings();
4953
private readonly bezierConnectionSpecification: ConnectorSpec = [

frank-flow/src/frontend/src/app/flow/node/nodes/node.model.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ComponentFactoryResolver, ViewContainerRef } from '@angular/core';
22
import { jsPlumbInstance } from 'jsplumb';
33
import { FlowNodeAttributes } from 'src/app/shared/models/flow-node-attributes.model';
4+
import { FlowStructureNode } from 'src/app/shared/models/flow-structure-node.model';
45
import { NodeComponent } from '../node.component';
56

67
export class Node {
@@ -11,6 +12,7 @@ export class Node {
1112
private top?: number | undefined;
1213
private left?: number | undefined;
1314
private attributes?: FlowNodeAttributes | undefined;
15+
private senders?: FlowStructureNode[];
1416

1517
constructor(options: {
1618
id: string;
@@ -19,13 +21,15 @@ export class Node {
1921
top?: number;
2022
left?: number;
2123
attributes?: FlowNodeAttributes;
24+
senders?: FlowStructureNode[];
2225
}) {
2326
this.id = options.id;
2427
this.name = options.name;
2528
this.type = options.type;
2629
this.top = options.top;
2730
this.left = options.left;
2831
this.attributes = options.attributes;
32+
this.senders = options.senders;
2933
}
3034

3135
getId(): string {
@@ -52,6 +56,10 @@ export class Node {
5256
return this.attributes;
5357
}
5458

59+
getSenders(): FlowStructureNode[] | undefined {
60+
return this.senders;
61+
}
62+
5563
setTop(top: number): void {
5664
this.top = top;
5765
}
@@ -60,6 +68,11 @@ export class Node {
6068
this.left = left;
6169
}
6270

71+
setName(name: string) {
72+
this.id = this.id.replace(this.name, name);
73+
this.name = name;
74+
}
75+
6376
generateNode(
6477
rootViewContainer: ViewContainerRef,
6578
factoryResolver: ComponentFactoryResolver,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { FlowNodeAttributes } from 'src/app/shared/models/flow-node-attributes.model';
2+
import { Node } from './node.model';
3+
import { FlowStructureNode } from '../../../shared/models/flow-structure-node.model';
4+
5+
export default class Sender extends Node {
6+
constructor(options: {
7+
id: string;
8+
name: string;
9+
type: string;
10+
top?: number;
11+
left?: number;
12+
attributes?: FlowNodeAttributes;
13+
senders?: FlowStructureNode[];
14+
}) {
15+
super(options);
16+
this.classes = 'color--success';
17+
}
18+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<h3>Info about {{ structureNode?.type }}: {{ structureNode?.name }}</h3>
2+
<div class="content-section">
3+
<p [innerHTML]="frankDocElement?.description" class="description"></p>
4+
<a
5+
href="{{ frankDocElementsURI }}/{{ frankDocElement?.name }}"
6+
target="_blank"
7+
>
8+
Read more about {{ frankDocElement?.name }}...
9+
</a>
10+
</div>
11+
<h3>Attributes</h3>
12+
<div class="content-section">
13+
<ng-container
14+
*ngFor="
15+
let attribute of attributes | keyvalue;
16+
trackBy: customTrackBy;
17+
index as i
18+
"
19+
>
20+
<div *ngIf="!disabledAttributes.includes(attribute.key)" class="input-row">
21+
<label>{{ attribute.key }}:</label>
22+
<div
23+
class="input-row--input-with-button"
24+
*ngIf="!nonRemovableAttributes.includes(attribute.key); else inputOnly"
25+
>
26+
<input
27+
(ngModelChange)="changeAttribute(attribute.key, $event)"
28+
[ngModel]="attributes[attribute.key].value"
29+
type="text"
30+
/>
31+
<app-button (click)="deleteAttribute(attribute.key)">
32+
<fa-icon [icon]="['fas', 'trash']" title="Delete attribute"></fa-icon>
33+
</app-button>
34+
</div>
35+
<ng-template #inputOnly>
36+
<input
37+
(ngModelChange)="changeAttribute(attribute.key, $event)"
38+
[ngModel]="attributes[attribute.key].value"
39+
type="text"
40+
/>
41+
</ng-template>
42+
</div>
43+
</ng-container>
44+
</div>
45+
<div class="content-section">
46+
<div *ngIf="availableAttributes.length > 0" class="input-row">
47+
<label for="selectAttribute">Add a new attribute:</label>
48+
<select [(ngModel)]="selectedAttribute" id="selectAttribute" required>
49+
<option [ngValue]="undefined" disabled hidden selected>
50+
Choose an attribute...
51+
</option>
52+
<option
53+
*ngFor="let availableAttribute of availableAttributes"
54+
[hidden]="
55+
attributeIsUsed(availableAttribute?.name) ||
56+
availableAttribute?.deprecated
57+
"
58+
[ngValue]="availableAttribute"
59+
>
60+
{{ availableAttribute?.name }}
61+
</option>
62+
</select>
63+
</div>
64+
<div *ngIf="selectedAttribute" class="input-row">
65+
<label for="newAttribute">New attribute value:</label>
66+
<input
67+
(keyup.enter)="addAttribute()"
68+
[(ngModel)]="newAttributeValue"
69+
[placeholder]="selectedAttribute?.default ?? ''"
70+
id="newAttribute"
71+
type="text"
72+
/>
73+
</div>
74+
<div *ngIf="selectedAttribute && selectedAttribute?.description" class="row">
75+
<label>Description of attribute</label>
76+
<p [innerHTML]="selectedAttribute?.description"></p>
77+
</div>
78+
<div *ngIf="newAttributeValue" class="row">
79+
<app-button (click)="addAttribute()" [block]="true"
80+
>Add {{ selectedAttribute?.name }}</app-button
81+
>
82+
</div>
83+
</div>
84+
<h3>Other options</h3>
85+
<div class="content-section">
86+
<div class="input-row">
87+
<label>Permanently delete this {{ structureNode?.type }}</label>
88+
<app-button (click)="deleteNode()" [block]="true"
89+
>Delete {{ structureNode?.name }}</app-button
90+
>
91+
</div>
92+
</div>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
a {
2+
color: var(--border-color);
3+
text-decoration: none;
4+
5+
&:hover {
6+
color: var(--text-color);
7+
}
8+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { NestedElementComponent } from './nested-element.component';
4+
5+
describe('NestedElementComponent', () => {
6+
let component: NestedElementComponent;
7+
let fixture: ComponentFixture<NestedElementComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
declarations: [NestedElementComponent],
12+
}).compileComponents();
13+
});
14+
15+
beforeEach(() => {
16+
fixture = TestBed.createComponent(NestedElementComponent);
17+
component = fixture.componentInstance;
18+
fixture.detectChanges();
19+
});
20+
21+
it('should create', () => {
22+
expect(component).toBeTruthy();
23+
});
24+
});

0 commit comments

Comments
 (0)