Skip to content

Commit a39544c

Browse files
authored
Updates to the Application screen (#7)
Improving the usablity and information given on the application screen. But also changed the default ip to be 192.168.56.1 to support future testing.
1 parent d7a9770 commit a39544c

23 files changed

+1992
-3811
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# External Control URCap
22

3-
This URCap allows you to send script code to the robot, and is primarily meant for connecting the robot to the Universal ROS/ROS2 driver, Isaac Sim driver, and the Universal Robots Client Library.
3+
This URCap allows you to inject script code to the robot, and is primarily meant for connecting the robot to the Universal ROS/ROS 2 driver and the Universal Robots Client Library.
44

55

66
## Build and Deploy Sample

external-control-frontend/.eslintrc.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
],
1414
"rules": {
1515
"@typescript-eslint/no-unused-vars": "off",
16+
"@typescript-eslint/no-explicit-any": "off",
1617
"@angular-eslint/component-selector": [
1718
"error",
1819
{

external-control-frontend/package-lock.json

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

external-control-frontend/package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"prebuild": "npm run generatepath",
88
"build": "ng build --configuration=production",
99
"lint": "ng lint",
10+
"test": "ng test",
1011
"generatepath": "generate-manifest-constants ../manifest.yaml"
1112
},
1213
"private": true,
@@ -40,11 +41,11 @@
4041
"@types/jasmine": "~5.1.0",
4142
"@typescript-eslint/eslint-plugin": "6.19.0",
4243
"@typescript-eslint/parser": "6.19.0",
43-
"@universal-robots/contribution-api": "32.1.7",
44-
"@universal-robots/urcap-utils": "1.0.5",
45-
"@universal-robots/utilities-units": "5.6.1",
46-
"@universal-robots/designtokens": "0.10.0",
47-
"@universal-robots/ui-models": "0.18.4",
44+
"@universal-robots/contribution-api": "38.1.2",
45+
"@universal-robots/urcap-utils": "1.1.0",
46+
"@universal-robots/utilities-units": "5.7.1",
47+
"@universal-robots/designtokens": "0.11.0",
48+
"@universal-robots/ui-models": "0.23.0",
4849
"eslint": "8.48.0",
4950
"jasmine-core": "~5.1.0",
5051
"karma": "~6.4.0",

external-control-frontend/src/app/components/external-control-application/external-control-application.behavior.worker.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import {
88
import { ExternalControlApplicationNode } from './external-control-application.node';
99

1010
// factory is required
11-
const createApplicationNode = (): OptionalPromise<ExternalControlApplicationNode> => ({
11+
export const createApplicationNode = (): OptionalPromise<ExternalControlApplicationNode> => ({
1212
type: 'universal-robots-external-control-external-control-application', // type is required
1313
version: '1.0.0', // version is required
1414
port: 50002,
15-
robotIP: 'servicegateway'
15+
robotIP: '192.168.56.1' //the hostname of the internal daemon docker is "servicegateway"
1616
});
1717

1818
// generatePreamble is optional
@@ -23,13 +23,13 @@ const generatePreambleScriptCode = (node: ExternalControlApplicationNode): Optio
2323

2424
// upgradeNode is optional
2525
const upgradeApplicationNode
26-
= (loadedNode: ApplicationNode, defaultNode: ExternalControlApplicationNode): ExternalControlApplicationNode =>
27-
defaultNode;
26+
= (loadedNode: ApplicationNode, defaultNode: ExternalControlApplicationNode): ExternalControlApplicationNode =>
27+
defaultNode;
2828

2929
// downgradeNode is optional
3030
const downgradeApplicationNode
31-
= (loadedNode: ApplicationNode, defaultNode: ExternalControlApplicationNode): ExternalControlApplicationNode =>
32-
defaultNode;
31+
= (loadedNode: ApplicationNode, defaultNode: ExternalControlApplicationNode): ExternalControlApplicationNode =>
32+
defaultNode;
3333

3434
const behaviors: ApplicationBehaviors = {
3535
factory: createApplicationNode,
Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,33 @@
11
<div *ngIf="applicationNode" class="main-section">
2+
<h1 class="header" [textContent]="baseTranslationKey + '.title' | translate"></h1>
3+
<p class="info-text" [textContent]="baseTranslationKey + '.description.line1' | translate"></p>
4+
<p class="info-text" [textContent]="baseTranslationKey + '.description.line2' | translate"></p>
5+
6+
<h2 class="sub-header" [textContent]="baseTranslationKey + '.settings.header' | translate"></h2>
7+
<p class="info-text" [textContent]="baseTranslationKey + '.settings.description' | translate"></p>
28
<div class="flex-container">
3-
<div>
9+
<div class="input-ip">
410
<ur-dialog-input [type]="'text'" [label]="'presenter.robotIP-input-description' | translate"
5-
[value]="applicationNode.robotIP" (valueChanged)="saveNode()" #robotIP></ur-dialog-input>
11+
[value]="applicationNode.robotIP" (valueChanged)="writeParam(port.value, robotIP.value)"
12+
#robotIP></ur-dialog-input>
613
</div>
7-
<div>
8-
<ur-label [label]="'&nbsp;'" [required]="false" [size]="'large'"></ur-label>
9-
</div>
10-
<div>
11-
<ur-label [label]="'&nbsp;'" [required]="false" [size]="'large'"></ur-label>
12-
</div>
13-
<div>
14+
<div class="input-port">
1415
<ur-dialog-input [type]="'number'" [label]="'presenter.port-input-description' | translate"
15-
[value]="applicationNode.port" (valueChanged)="saveNode()" #port></ur-dialog-input>
16-
</div>
17-
<div>
18-
<ur-label [label]="'&nbsp;'" [required]="false" [size]="'large'"></ur-label>
19-
</div>
20-
<div>
21-
<ur-label [label]="'&nbsp;&nbsp;'" [required]="false" [size]="'large'"></ur-label>
16+
[value]="applicationNode.port" (valueChanged)="writeParam(port.value, robotIP.value)"
17+
#port></ur-dialog-input>
2218
</div>
23-
<ur-button (handleClick)="writeParam(port.value, robotIP.value)" [type]="'cta'" class="button">
24-
{{'presenter.confirm-button' | translate}}
25-
</ur-button>
2619
</div>
20+
21+
<h2 class="sub-header" [textContent]="baseTranslationKey + '.important.header' | translate"></h2>
22+
<p class="info-text pre-line" [textContent]="baseTranslationKey + '.important.line1' | translate"></p>
23+
<p class="info-text pre-line" [textContent]="baseTranslationKey + '.important.line2' | translate"></p>
24+
<div class="vertical-spacer"></div>
25+
<p class="info-text" [textContent]="baseTranslationKey + '.serviceHowToEnable.text' | translate"></p>
26+
<span class="highlight">
27+
{{ baseTranslationKey + '.serviceHowToEnable.settings' | translate }}
28+
<span class="arrow"></span>
29+
{{ baseTranslationKey + '.serviceHowToEnable.security' | translate }}
30+
<span class="arrow"></span>
31+
{{ baseTranslationKey + '.serviceHowToEnable.services' | translate }}
32+
</span>
2733
</div>

external-control-frontend/src/app/components/external-control-application/external-control-application.component.scss

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,51 @@
66
}
77
}
88

9+
.main-section {
10+
margin-left: 50px;
11+
}
12+
913
.flex-container {
1014
display: flex;
11-
align-content: flex-start;
12-
padding: 0.5rem 0.5rem 1rem;
15+
flex-wrap: wrap;
16+
gap: 10px;
17+
}
18+
19+
.input-ip,
20+
.input-port {
21+
min-width: 200px;
22+
}
23+
24+
.header {
25+
font-size: 24px;
26+
margin-bottom: 20px;
27+
}
28+
29+
.sub-header {
30+
font-size: 18px;
31+
margin-top: 40px;
32+
margin-bottom: 10px;
33+
}
34+
35+
.pre-line {
36+
white-space: pre-line;
37+
}
38+
39+
.vertical-spacer {
40+
height: 1px;
41+
}
42+
43+
.arrow {
44+
font-size: 20px;
45+
vertical-align: bottom;
46+
margin: 0 5px;
47+
}
48+
49+
.highlight {
50+
background-color: #ffffff;
51+
padding: 5px;
52+
border-radius: 5px;
53+
font-weight: bold;
54+
color: #333;
55+
margin-left: 30px;
1356
}
Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,89 @@
1+
/**
2+
* Contains unit tests for the ExternalControlApplicationComponent.
3+
* It ensures that the component is created correctly and its functionalities
4+
* work as expected.
5+
*/
6+
import {provideHttpClient, withInterceptorsFromDi} from '@angular/common/http';
7+
import {provideHttpClientTesting} from '@angular/common/http/testing';
18
import {ComponentFixture, TestBed} from '@angular/core/testing';
2-
import {ExternalControlApplicationComponent} from "./external-control-application.component";
3-
import {TranslateLoader, TranslateModule} from "@ngx-translate/core";
4-
import {Observable, of} from "rxjs";
9+
import {TranslateLoader, TranslateModule, TranslateService} from '@ngx-translate/core';
10+
import {Observable, of} from 'rxjs';
11+
import {ExternalControlApplicationComponent} from './external-control-application.component';
12+
import { RobotSettings } from '@universal-robots/contribution-api';
513

614
describe('ExternalControlApplicationComponent', () => {
715
let fixture: ComponentFixture<ExternalControlApplicationComponent>;
816
let component: ExternalControlApplicationComponent;
17+
let translateService: TranslateService;
918

1019
beforeEach(() => {
11-
TestBed.configureTestingModule({
12-
declarations: [ExternalControlApplicationComponent],
13-
imports: [TranslateModule.forRoot({
14-
loader: {
15-
provide: TranslateLoader, useValue: {
16-
getTranslation(): Observable<Record<string, string>> {
17-
return of({});
20+
TestBed
21+
.configureTestingModule({
22+
declarations: [ExternalControlApplicationComponent],
23+
imports: [TranslateModule.forRoot({
24+
loader: {
25+
provide: TranslateLoader,
26+
useValue: {
27+
getTranslation(): Observable<Record<string, string>> {
28+
return of({});
29+
}
30+
}
1831
}
19-
}
20-
}
21-
})],
22-
}).compileComponents();
32+
})],
33+
providers: [
34+
provideHttpClient(withInterceptorsFromDi()),
35+
provideHttpClientTesting()
36+
],
37+
})
38+
.compileComponents();
2339

2440
fixture = TestBed.createComponent(ExternalControlApplicationComponent);
2541
component = fixture.componentInstance;
42+
translateService = TestBed.inject(TranslateService);
2643
});
2744

45+
/**
46+
* Test to ensure the component is created successfully.
47+
*/
2848
it('should create the component', () => {
2949
expect(component).toBeTruthy();
3050
});
51+
52+
/**
53+
* Test to ensure the component initializes with default values.
54+
*/
55+
it('should initialize with default values', () => {
56+
expect(component.baseTranslationKey)
57+
.toBe(
58+
'application.nodes.universal-robots-external-control-external-control-application');
59+
expect(component.messageEmitter$.value).toBe('');
60+
});
61+
62+
/**
63+
* Test to ensure the ngOnChanges method updates the translation language EN.
64+
*/
65+
it('should update translation language on robotSettings change', () => {
66+
component.robotSettings = { language: 'en', units: null } as RobotSettings;
67+
component.ngOnChanges({ robotSettings: { currentValue: component.robotSettings } } as any);
68+
expect(component.currentLanguage).toBe('en');
69+
});
70+
71+
/**
72+
* Test to ensure the ngOnChanges method updates the translation language DA.
73+
*/
74+
it('should update translation language on robotSettings change', () => {
75+
component.robotSettings = { language: 'da', units: null } as RobotSettings;
76+
component.ngOnChanges({ robotSettings: { currentValue: component.robotSettings } } as any);
77+
expect(component.currentLanguage).toBe('da');
78+
});
79+
80+
/**
81+
* Test to ensure the ngOnChanges method sets the default language if the
82+
* language is not supported.
83+
*/
84+
it('should set default language to "en" if the language is not supported', () => {
85+
component.robotSettings = { language: 'qq', units: null } as RobotSettings;
86+
component.ngOnChanges({ robotSettings: { currentValue: component.robotSettings } } as any);
87+
expect(component.currentLanguage).toBe('en');
88+
});
3189
});

0 commit comments

Comments
 (0)