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
44 changes: 44 additions & 0 deletions modules/ui/src/app/mocks/profile.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import { Profile } from '../model/profile';
import { FormControlType, ProfileFormat } from '../model/profile';

export const PROFILE_MOCK: Profile = {
name: 'Profile name',
Expand All @@ -25,3 +26,46 @@ export const PROFILE_MOCK_2: Profile = {
name: 'Second profile name',
sections: [],
};

export const PROFILE_FORM: ProfileFormat[] = [
{
question: 'Email',
type: FormControlType.EMAIL_MULTIPLE,
validation: {
required: true,
},
},
{
question: 'What type of device do you need reviewed?',
type: FormControlType.TEXTAREA,
validation: {
required: true,
},
description: 'This tells us about the device',
},
{
question:
'Has this device already been through a criticality assessment with testrun?',
type: FormControlType.SELECT,
options: [],
validation: {
max: '128',
required: true,
},
},
{
question: 'What features does the device have?',
description:
'This tells us about the data your device will collectThis tells us about the data your device will collect',
type: FormControlType.SELECT_MULTIPLE,
options: ['Wi-fi', 'Bluetooth', 'ZigBee / Z-Wave / Thread / Matter'],
validation: {
required: true,
},
},
{
question: 'Comments',
type: FormControlType.TEXT,
description: 'Please enter any comments here',
},
];
32 changes: 32 additions & 0 deletions modules/ui/src/app/model/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,35 @@ export interface Profile {
name: string;
sections: ProfileSection[];
}

export interface ProfileRequestBody {
name: string;
questions: Question[];
}

export interface Question {
question?: string;
answer?: string | number[];
}

export enum FormControlType {
SELECT = 'select',
TEXTAREA = 'text-long',
EMAIL_MULTIPLE = 'email-multiple',
SELECT_MULTIPLE = 'select-multiple',
TEXT = 'text',
}

export interface Validation {
required?: boolean;
max?: string;
}

export interface ProfileFormat {
question: string;
type: FormControlType;
description?: string;
options?: string[];
default?: string;
validation?: Validation;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@
-->
<form [formGroup]="profileForm" class="profile-form">
<div class="field-container">
<!-- TODO move profile name to json (in scope of validation) -->
<p class="field-label">Profile name *</p>
<mat-form-field appearance="outline" class="name-field">
<mat-form-field
appearance="outline"
floatLabel="always"
class="name-field profile-form-field">
<mat-label>Specify risk assessment profile name</mat-label>
<input class="form-name" formControlName="name" matInput />
<mat-error
Expand All @@ -38,6 +42,22 @@
>
</mat-error>
</mat-form-field>

<ng-container *ngFor="let control of profileFormat; index as i">
<ng-container
*ngTemplateOutlet="
formField;
context: {
label: control.question,
type: control.type,
formControlName: i,
formGroup: profileForm,
required: control.validation?.required,
options: control.options,
description: control.description
}
"></ng-container>
</ng-container>
</div>
</form>
<div class="form-actions">
Expand All @@ -52,3 +72,185 @@
Discard
</button>
</div>

<ng-template
#formField
let-type="type"
let-label="label"
let-required="required"
let-description="description"
let-options="options"
let-formControlName="formControlName">
<label class="field-label" for="{{ formControlName }}-group"
>{{ label }} <span *ngIf="required">*</span></label
>
<ng-container [ngSwitch]="type">
<ng-container *ngSwitchCase="FormControlType.TEXT">
<ng-container
*ngTemplateOutlet="
text;
context: {
formControlName: formControlName,
description: description
}
"></ng-container>
</ng-container>

<ng-container *ngSwitchCase="FormControlType.TEXTAREA">
<ng-container
*ngTemplateOutlet="
textarea;
context: {
formControlName: formControlName,
description: description
}
"></ng-container>
</ng-container>

<ng-container *ngSwitchCase="FormControlType.EMAIL_MULTIPLE">
<ng-container
*ngTemplateOutlet="
emailMultiple;
context: {
formControlName: formControlName,
description: description
}
"></ng-container>
</ng-container>

<ng-container *ngSwitchCase="FormControlType.SELECT">
<ng-container
*ngTemplateOutlet="
select;
context: {
formControlName: formControlName,
options: options,
description: description,
label: label
}
"></ng-container>
</ng-container>

<ng-container *ngSwitchCase="FormControlType.SELECT_MULTIPLE">
<ng-container
*ngTemplateOutlet="
selectMultiple;
context: {
formControlName: formControlName,
options: options,
description: description
}
"></ng-container>
</ng-container>

<ng-container *ngSwitchDefault>
<ng-container
*ngTemplateOutlet="
text;
context: {
formControlName: formControlName,
description: description
}
"></ng-container>
</ng-container>
</ng-container>
</ng-template>

<ng-template
#text
let-formControlName="formControlName"
let-description="description">
<mat-form-field
appearance="outline"
floatLabel="always"
class="profile-form-field"
[formGroup]="profileForm">
<input
matInput
id="{{ formControlName }}-group"
[formControlName]="formControlName" />
<mat-hint *ngIf="description">{{ description }}</mat-hint>
</mat-form-field>
</ng-template>

<ng-template
#textarea
let-formControlName="formControlName"
let-description="description">
<mat-form-field
appearance="outline"
floatLabel="always"
class="profile-form-field"
[formGroup]="profileForm">
<input
matInput
id="{{ formControlName }}-group"
[formControlName]="formControlName" />
<mat-hint *ngIf="description">{{ description }}</mat-hint>
</mat-form-field>
</ng-template>

<ng-template
#emailMultiple
let-formControlName="formControlName"
let-description="description">
<mat-form-field
appearance="outline"
floatLabel="always"
class="profile-form-field"
[formGroup]="profileForm">
<input
matInput
id="{{ formControlName }}-group"
[formControlName]="formControlName" />
<mat-hint *ngIf="description">{{ description }}</mat-hint>
</mat-form-field>
</ng-template>

<ng-template
#selectMultiple
let-formControlName="formControlName"
let-options="options"
let-description="description">
<section
class="field-select-multiple profile-form-field"
[formGroup]="getFormGroup(formControlName)">
<p
*ngFor="let option of options; let i = index"
class="field-select-checkbox">
<mat-checkbox [formControlName]="i">
{{ option }}
</mat-checkbox>
</p>
<mat-hint *ngIf="description" class="field-hint">{{
description
}}</mat-hint>
</section>
</ng-template>

<ng-template
#select
let-formControlName="formControlName"
let-label="label"
let-options="options"
let-description="description">
<mat-form-field
appearance="outline"
floatLabel="always"
class="profile-form-field"
[formGroup]="profileForm">
<mat-select
aria-label="{{ label }}"
id="{{ formControlName }}-group"
[formControlName]="formControlName">
<mat-option
*ngFor="let option of options; let i = index"
[value]="option">
{{ option }}
</mat-option>
</mat-select>
<mat-hint *ngIf="description" class="field-hint">{{
description
}}</mat-hint>
</mat-form-field>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@use '@angular/material' as mat;
@import 'src/theming/colors';
@import 'src/theming/variables';

Expand All @@ -21,27 +22,56 @@
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 16px;
padding: 8px 16px 8px 24px;
}
.field-label {
margin: 0;
color: $grey-800;
font-size: 18px;
line-height: 24px;
padding-top: 24px;
padding-bottom: 16px;
&:first-child {
padding-top: 0;
}
}
mat-form-field {
width: 100%;
}
.field-hint {
font-family: $font-secondary;
font-size: 12px;
font-weight: 400;
line-height: 16px;
text-align: left;
padding-top: 8px;
}
}

.form-actions {
display: flex;
gap: 16px;
padding: 0 24px;
padding: 8px 24px 24px 24px;
}

.save-draft-button,
.discard-button {
color: $primary;
}

.field-select-multiple {
.field-select-checkbox {
&:has(::ng-deep .mat-mdc-checkbox-checked) {
background: mat.get-color-from-palette($color-primary, 50);
}
::ng-deep .mdc-checkbox__ripple {
display: none;
}
&:first-of-type {
margin-top: 0;
}
&:last-of-type {
margin-bottom: 8px;
}
}
}
Loading