Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ $border-radius: 12px;
padding: 0;
grid-column-gap: 8px;
grid-row-gap: 4px;
font-family: 'Open Sans', sans-serif;
font-family: $font-primary;
grid-template-areas:
'manufacturer manufacturer'
'name address';
Expand All @@ -59,7 +59,7 @@ $border-radius: 12px;
grid-template-columns: 1fr $icon-width;
grid-column-gap: 1px;
padding: 0;
font-family: 'Open Sans', sans-serif;
font-family: $font-primary;
grid-template-areas: 'edit start';

&.device-item-outdated {
Expand All @@ -76,7 +76,7 @@ $border-radius: 12px;
padding: 0 6px 0 0;
grid-column-gap: 8px;
grid-row-gap: 4px;
font-family: 'Open Sans', sans-serif;
font-family: $font-primary;
grid-template-areas:
'manufacturer status'
'name address';
Expand Down
2 changes: 1 addition & 1 deletion modules/ui/src/app/mocks/device.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const MOCK_TEST_MODULES = [
{
displayName: 'Udmi',
name: 'udmi',
enabled: false,
enabled: true,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ <h2 class="device-qualification-form-header-title">{{ data.title }}</h2>
[selectedIndex]="selectedIndex"
[title]="data.title + ' modal window'"
(selectionChange)="onStepChange($event)">
{{ selectedIndex }}
<cdk-step [editable]="true" formGroupName="0" [stepControl]="getStep(0)">
<section
class="device-qualification-form-page device-qualification-form-step-content">
Expand Down Expand Up @@ -148,13 +147,18 @@ <h2 class="device-qualification-form-header-title">{{ data.title }}</h2>
</mat-radio-group>
<app-device-tests
class="device-qualification-form-test-modules-container"
[class.device-qualification-form-test-modules-error]="
[class.device-qualification-form-test-modules-container-error]="
test_modules.touched && test_modules.errors?.['required']
"
[deviceForm]="getStep(0)"
[deviceTestModules]="data.device?.test_modules"
[testModules]="testModules">
</app-device-tests>
<mat-error
*ngIf="test_modules.touched && test_modules.errors?.['required']"
class="device-qualification-form-test-modules-error">
At least one test has to be selected to save a Device.
</mat-error>
</section>
</cdk-step>

Expand Down Expand Up @@ -185,10 +189,14 @@ <h3 class="device-qualification-form-step-title" *ngIf="step.title">
<section class="device-qualification-form-page">
<h3 class="device-qualification-form-step-title">Summary</h3>
<p class="device-qualification-form-step-description">
<ng-container *ngIf="formValid && !deviceHasNoChanges">
<ng-container
*ngIf="
formValid && !deviceHasNoChanges(data.initialDevice, device)
">
The device has been configured. Please check the setup.
</ng-container>
<ng-container *ngIf="formValid && deviceHasNoChanges">
<ng-container
*ngIf="formValid && deviceHasNoChanges(data.initialDevice, device)">
No changes were made to the device configuration.
</ng-container>
<ng-container *ngIf="!formValid"
Expand All @@ -212,6 +220,22 @@ <h3 class="device-qualification-form-step-title">Summary</h3>
</p>
</div>
</section>
<section
*ngIf="formValid && !deviceHasNoChanges(data.initialDevice, device)"
class="device-qualification-form-instructions">
<span
>Select Save to create your new device. You will then be able to
carry on your device testing journey:</span
>
<ul>
<li>
Run Testrun against your device until you achieve a compliant
result
</li>
<li>Export the Testrun report and output files</li>
<li>Send the testing results to the lab for validation</li>
</ul>
</section>

<section
*ngIf="!formValid"
Expand Down Expand Up @@ -274,7 +298,9 @@ <h3 class="device-qualification-form-summary-info-title">
mat-flat-button
color="primary"
class="save-button"
[disabled]="formPristine || !formValid"
[disabled]="
deviceHasNoChanges(data.initialDevice, device) || !formValid
"
(click)="submit()">
Save
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,13 +273,15 @@ $form-height: 993px;

.device-qualification-form-instructions {
margin-top: auto;
padding-top: 8px;
color: $grey-800;
text-align: center;
font-family: $font-secondary;
font-size: 16px;

width: 510px;
ul {
text-align: left;
padding-left: 26px;
}
li {
line-height: 24px;
Expand All @@ -295,10 +297,16 @@ $form-height: 993px;
padding-bottom: 14px;
}

.device-qualification-form-test-modules-error ::ng-deep .device-tests-title {
.device-qualification-form-test-modules-container-error
::ng-deep
.device-tests-title {
color: $red-800;
}

.device-qualification-form-test-modules-error {
padding: 0 24px;
}

@container qualification-form (height < 870px) {
.device-qualification-form-page {
overflow: scroll;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ describe('DeviceQualificationFromComponent', () => {

it('should close dialog on "cancel" click', () => {
fixture.detectChanges();
component.manufacturer.setValue('test');
(
component.deviceQualificationForm.get('steps') as FormArray
).controls.forEach(control => control.markAsDirty());
Expand All @@ -178,15 +179,15 @@ describe('DeviceQualificationFromComponent', () => {
index: 0,
device: {
status: DeviceStatus.VALID,
manufacturer: '',
manufacturer: 'test',
model: '',
mac_addr: '',
test_pack: 'Device qualification',
type: '',
technology: '',
test_modules: {
udmi: {
enabled: false,
enabled: true,
},
connection: {
enabled: true,
Expand Down Expand Up @@ -228,12 +229,19 @@ describe('DeviceQualificationFromComponent', () => {

it('should have error when no modules selected', () => {
component.test_modules.setValue([false, false]);
component.test_modules.markAsTouched();
fixture.detectChanges();

const modules = compiled.querySelectorAll(
const modules = compiled.querySelector(
'.device-qualification-form-test-modules-container-error'
);
const error = compiled.querySelector(
'.device-qualification-form-test-modules-error'
);

expect(modules).toBeTruthy();
expect(error?.innerHTML.trim()).toEqual(
'At least one test has to be selected to save a Device.'
);
});
});

Expand Down Expand Up @@ -559,6 +567,13 @@ describe('DeviceQualificationFromComponent', () => {
expect(item).toBeTruthy();
});

it('should have instructions', () => {
const instructions = compiled.querySelector(
'.device-qualification-form-instructions'
);
expect(instructions).toBeTruthy();
});

it('should save device', () => {
const saveSpy = spyOn(component.devicesStore, 'saveDevice');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,15 @@ import { QualificationIconComponent } from '../../../../components/qualification
import { PilotIconComponent } from '../../../../components/pilot-icon/pilot-icon.component';
import { Question } from '../../../../model/profile';
import { FormControlType } from '../../../../model/question';
import { FocusManagerService } from '../../../../services/focus-manager.service';

const MAC_ADDRESS_PATTERN =
'^[\\s]*[a-fA-F0-9]{2}(?:[:][a-fA-F0-9]{2}){5}[\\s]*$';

interface DialogData {
title?: string;
device?: Device;
initialDevice?: Device;
devices: Device[];
testModules: TestModule[];
index: number;
Expand Down Expand Up @@ -173,12 +175,8 @@ export class DeviceQualificationFromComponent
).controls.every(control => (control as FormGroup).valid);
}

get deviceHasNoChanges() {
const obj1 = this.data.device;
const obj2 = this.device;
return (
(obj1 && obj2 && this.compareObjects(obj1, obj2)) || this.formPristine
);
deviceHasNoChanges(device1: Device | undefined, device2: Device | undefined) {
return device1 && device2 && this.compareDevices(device1, device2);
}

constructor(
Expand All @@ -188,7 +186,8 @@ export class DeviceQualificationFromComponent
public dialogRef: MatDialogRef<DeviceQualificationFromComponent>,
@Inject(MAT_DIALOG_DATA) public data: DialogData,
public devicesStore: DevicesStore,
private element: ElementRef
private element: ElementRef,
private focusService: FocusManagerService
) {
this.device = data.device;
}
Expand Down Expand Up @@ -221,7 +220,10 @@ export class DeviceQualificationFromComponent
this.fillDeviceForm(this.format, this.data.device!);
}
if (this.data.index) {
this.selectedIndex = this.data.index;
// previous steps should be marked as interacted
for (let i = 0; i <= this.data.index; i++) {
this.goToStep(i);
}
}
this.dialogRef
.keydownEvents()
Expand Down Expand Up @@ -256,11 +258,11 @@ export class DeviceQualificationFromComponent
}

closeForm(): void {
const obj1 = this.data.device;
const obj2 = this.createDeviceFromForm();
const device1 = this.data.initialDevice;
const device2 = this.createDeviceFromForm();
if (
(obj1 && obj2 && this.compareObjects(obj1, obj2)) ||
this.formPristine
(device1 && device2 && this.compareDevices(device1, device2)) ||
(!device1 && this.deviceIsEmpty(device2))
) {
this.dialogRef.close();
} else {
Expand All @@ -279,6 +281,7 @@ export class DeviceQualificationFromComponent
}

onStepChange(event: StepperSelectionEvent) {
this.focusService.focusFirstElementInContainer();
if (event.previouslySelectedStep.completed) {
this.device = this.createDeviceFromForm();
}
Expand Down Expand Up @@ -460,32 +463,89 @@ export class DeviceQualificationFromComponent
return new FormGroup({});
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
private compareObjects(object1: any, object2: any) {
const keys1 = Object.keys(object1);
const keys2 = Object.keys(object2);

if (keys1.length !== keys2.length) {
private compareDevices(device1: Device, device2: Device) {
if (device1.manufacturer !== device2.manufacturer) {
return false;
}
if (device1.model !== device2.model) {
return false;
}
if (device1.mac_addr !== device2.mac_addr) {
return false;
}
if (device1.type !== device2.type) {
return false;
}
if (device1.technology !== device2.technology) {
return false;
}
if (device1.test_pack !== device2.test_pack) {
return false;
}
const keys1 = Object.keys(device1.test_modules!);

for (const key of keys1) {
const val1 = object1[key];
const val2 = object2[key];
const areObjects = this.isObject(val1) && this.isObject(val2);
if (
(areObjects && !this.compareObjects(val1, val2)) ||
(!areObjects && val1 !== val2)
) {
const val1 = device1.test_modules![key];
const val2 = device2.test_modules![key];
if (val1.enabled !== val2.enabled) {
return false;
}
}

if (device1.additional_info) {
for (const question of device1.additional_info) {
if (
question.answer !==
device2.additional_info?.find(
question2 => question2.question === question.question
)?.answer
) {
return false;
}
}
} else {
return false;
}
return true;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
private isObject(object: any) {
return object != null && typeof object === 'object';
private deviceIsEmpty(device: Device) {
if (device.manufacturer !== '') {
return false;
}
if (device.model !== '') {
return false;
}
if (device.mac_addr !== '') {
return false;
}
if (device.type !== '') {
return false;
}
if (device.technology !== '') {
return false;
}
if (device.test_pack !== TestingType.Qualification) {
return false;
}
const keys1 = Object.keys(device.test_modules!);

for (const key of keys1) {
const val1 = device.test_modules![key];
if (!val1.enabled) {
return false;
}
}

if (device.additional_info) {
for (const question of device.additional_info) {
if (question.answer !== '') {
return false;
}
}
} else {
return false;
}
return true;
}
}
Loading