Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional metadata fields when managing an application #72

Merged
merged 5 commits into from
Mar 17, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@angular/forms": "~9.1.11",
"@angular/localize": "^9.1.11",
"@angular/material": "^9.2.4",
"@angular/material-moment-adapter": "^9.2.4",
"@angular/platform-browser": "~9.1.11",
"@angular/platform-browser-dynamic": "~9.1.11",
"@angular/router": "~9.1.11",
Expand Down
2 changes: 1 addition & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function tokenGetter() {
@NgModule({
declarations: [
AppComponent,
ErrorPageComponent
ErrorPageComponent,
],
imports: [
SharedVariableModule.forRoot(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,23 @@
<div *ngIf="errorMessage" class="error-messages p-3 my-3">
{{errorMessage | translate}}
</div>
<h3>Detaljer</h3>
<h3>{{ 'APPLICATION.DETAILS' | translate }}</h3>
<app-general-details [data]="application"></app-general-details>
<p *ngIf="application.description">
<strong>{{ 'APPLICATION.DESCRIPTION' | translate }}</strong></p>
<pre><p>{{application.description}}</p></pre>
<app-metadata-details [status]="application.status" [startDate]="application.startDate"
[endDate]="application.endDate"
[category]="application.category"
[owner]="application.owner"
[contactPerson]="application.contactPerson"
[contactEmail]="application.contactEmail"
[contactPhone]="application.contactPhone"
[personalData]="application.personalData"
[hardware]="application.hardware"
[controlledProperties]="application.controlledProperties"
[deviceTypes]="application.deviceTypes"
></app-metadata-details>
</div>
</div>
</div>
Expand Down Expand Up @@ -81,4 +93,4 @@ <h3>Detaljer</h3>
</mat-tab>
</mat-tab-group>
</div>
</div>
</div>
29 changes: 29 additions & 0 deletions src/app/applications/application.model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { ControlledPropertyTypes } from '@app/device-model/Enums/controlled-propperty.enum';
import { ApplicationDeviceTypeUnion } from '@shared/enums/device-type';
import { ControlledProperty } from '@shared/models/controlled-property.model';
import { Organisation } from '../admin/organisation/organisation.model';
import { ApplicationStatus } from './enums/status.enum';
import { IotDevice } from './iot-devices/iot-device.model';
import { ApplicationDeviceType } from './models/application-device-type.model';

export class Application {
public id: number;
Expand All @@ -13,12 +18,36 @@ export class Application {
public updatedBy: number;
public createdByName: string;
public updatedByName: string;
public status?: ApplicationStatus;
public startDate?: Date;
public endDate?: Date;
public category?: string;
public owner?: string;
public contactPerson?: string;
public contactEmail?: string;
public contactPhone?: string;
public personalData?: boolean;
public hardware?: string;
public controlledProperties?: ControlledProperty[];
public deviceTypes?: ApplicationDeviceType[];
}

export class ApplicationRequest {
public name: string;
public description: string;
public organizationId: number;
public status?: ApplicationStatus;
public startDate?: Date;
public endDate?: Date;
public category?: string;
public owner?: string;
public contactPerson?: string;
public contactEmail?: string;
public contactPhone?: string;
public personalData?: boolean;
public hardware?: string;
public controlledProperties?: ControlledPropertyTypes[];
public deviceTypes?: ApplicationDeviceTypeUnion[];
}

export interface ApplicationData {
Expand Down
4 changes: 2 additions & 2 deletions src/app/applications/bulk-import/bulkMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class BulkMapping {
switch (data.type.toUpperCase()) {
case DeviceType.LORAWAN:
return this.lorawanMapper(data, applicationId);
case DeviceType.GENERICHTTP:
case DeviceType.GENERIC_HTTP:
return this.baseMapper(data, applicationId);
default:
break;
Expand Down Expand Up @@ -53,7 +53,7 @@ export class BulkMapping {
location: undefined,
commentOnLocation: data.commentOnLocation,
comment: data.comment,
type: DeviceType.GENERICHTTP,
type: DeviceType.GENERIC_HTTP,
receivedMessagesMetadata: undefined,
metadata: undefined,
apiKey: undefined,
Expand Down
11 changes: 11 additions & 0 deletions src/app/applications/enums/status.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { recordToEntries } from '@shared/helpers/record.helper';

export enum ApplicationStatus {
'NONE' = 'NONE',
'IN-OPERATION' = 'IN-OPERATION',
'PROJECT' = 'PROJECT',
'PROTOTYPE' = 'PROTOTYPE',
'OTHER' = 'OTHER',
}

export const ApplicationStatusEntries = recordToEntries(ApplicationStatus);
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export class IotDeviceEditComponent implements OnInit, OnDestroy {
getDeviceModels() {
this.deviceModelService.getMultiple(
1000,
0,
0,
"id",
"ASC",
this.shareVariable.getSelectedOrganisationId()
Expand Down Expand Up @@ -197,7 +197,7 @@ export class IotDeviceEditComponent implements OnInit, OnDestroy {
this.iotDevice.deviceModelId = null
}
switch (this.iotDevice.type) {
case DeviceType.GENERICHTTP: {
case DeviceType.GENERIC_HTTP: {
this.iotDevice.lorawanSettings = undefined;
this.iotDevice.sigfoxSettings = undefined;
break;
Expand Down
2 changes: 1 addition & 1 deletion src/app/applications/iot-devices/iot-device.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class IotDevice {
location: JsonLocation;
commentOnLocation: string;
comment: string;
type: DeviceType = DeviceType.GENERICHTTP;
type: DeviceType = DeviceType.GENERIC_HTTP;
receivedMessagesMetadata: ReceivedMessageMetadata[];
metadata?: JSON;
apiKey?: string;
Expand Down
7 changes: 7 additions & 0 deletions src/app/applications/models/application-device-type.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Application } from '@applications/application.model';
import { ApplicationDeviceTypeUnion } from '@shared/enums/device-type';

export class ApplicationDeviceType {
public applications: Application[];
public type: ApplicationDeviceTypeUnion;
}
2 changes: 1 addition & 1 deletion src/app/device-model/Enums/controlled-propperty.enum.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export enum ControlledPropperty {
export enum ControlledPropertyTypes {
AIRPOLLUTION = "airPollution",
ATMOSPHERICPRESSURE = "atmosphericPressure",
CDOM = "cdom",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { BackButton } from '@shared/models/back-button.model';
import { ScrollToTopService } from '@shared/services/scroll-to-top.service';
import { DeviceModelService } from '../device-model.service';
import { DeviceModel } from '../device.model';
import { ControlledPropperty } from '../Enums/controlled-propperty.enum';
import { ControlledPropertyTypes } from '../Enums/controlled-propperty.enum';
import { DeviceCategory } from '../Enums/device-category.enum';
import { DeviceFunction } from '../Enums/device-function.enum';
import { EnergyLimitationClass } from '../Enums/energy-limitation-class.model';
Expand Down Expand Up @@ -58,7 +58,7 @@ export class DeviceModelEditComponent implements OnInit {
}

mapEnumsToArray() {
this.controlledPropperties = Object.values(ControlledPropperty);
this.controlledPropperties = Object.values(ControlledPropertyTypes);
this.categories = Object.values(DeviceCategory);
this.deviceFunctions = Object.values(DeviceFunction);
this.supportedProtocol = Object.values(SupportedProtocol);
Expand Down
14 changes: 12 additions & 2 deletions src/app/shared/Modules/materiale.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CdkStepperModule } from '@angular/cdk/stepper';
import { CdkTableModule } from '@angular/cdk/table';
import { CdkTreeModule } from '@angular/cdk/tree';
import { NgModule } from '@angular/core';
import { MomentDateAdapter } from '@angular/material-moment-adapter';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatBadgeModule } from '@angular/material/badge';
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
Expand All @@ -14,7 +15,7 @@ import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatNativeDateModule, MatRippleModule } from '@angular/material/core';
import { DateAdapter, MatNativeDateModule, MatRippleModule, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDialogModule } from '@angular/material/dialog';
import { MatDividerModule } from '@angular/material/divider';
Expand All @@ -40,6 +41,7 @@ import { MatTabsModule } from '@angular/material/tabs';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatTreeModule } from '@angular/material/tree';
import { DayMonthYearPickerFormat } from '@shared/constants/date.constants';

@NgModule({
exports: [
Expand Down Expand Up @@ -85,7 +87,15 @@ import { MatTreeModule } from '@angular/material/tree';
MatTreeModule,
PortalModule,
ScrollingModule,
]
],
providers: [
{
provide: DateAdapter,
useClass: MomentDateAdapter,
deps: [MAT_DATE_LOCALE],
},
{ provide: MAT_DATE_FORMATS, useValue: DayMonthYearPickerFormat },
],
})
export class NGMaterialModule { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,144 @@
</div>
<div class="row">
<div class="form-group mt-3">
<label class="form-label" for="name">{{'QUESTION.GIVE-APPLICATION-NAME' | translate}}</label>*
<label class="form-label" for="name">{{'GEN.NAME' | translate}}*</label>

<input type="text" class="form-control" id="name" name="name"
[placeholder]="'QUESTION.APPLICATION-NAME-PLACEHOLDER' | translate" maxlength="50" required
[placeholder]="'QUESTION.APPLICATION.NAME-PLACEHOLDER' | translate" maxlength="50" required
[(ngModel)]="application.name"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('name'), 'is-valid' : formFailedSubmit && !errorFields.includes('name')}">
</div>

<div class="form-group mt-3">
<label class="form-label" for="description">{{'QUESTION.GIVE-APPLICATION-DESCRIPTION' | translate}}</label>
<label class="form-label" for="description">{{'GEN.DESCRIPTION' | translate}}</label>
<textarea id="description" name="description"
[placeholder]="'QUESTION.APPLICATION-DESCRIPTION-PLACEHOLDER' | translate" [maxLength]="1024" [rows]="6"
[placeholder]="'QUESTION.APPLICATION.DESCRIPTION-PLACEHOLDER' | translate" [maxLength]="1024" [rows]="6"
class="form-control" [(ngModel)]="application.description"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('description'), 'is-valid' : formFailedSubmit && !errorFields.includes('description')}"></textarea>
</div>

<div class="form-group mt-3">
<label class="form-label" for="application.status">{{'APPLICATION.METADATA-FIELD.STATUS' | translate}}</label>
<mat-select class="form-control" name="application.statusOptions" [(ngModel)]="application.status"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('application.status'), 'is-valid' : formFailedSubmit && !errorFields.includes('application.status')}">
<mat-option *ngFor="let statusOption of statuses" [value]="statusOption.value">
{{statusOption.label}}
</mat-option>
</mat-select>
</div>

<div class="form-group mt-3">
AramAlsabti marked this conversation as resolved.
Show resolved Hide resolved
<label class="form-label" for="application.startDate">{{'APPLICATION.METADATA-FIELD.START-DATE' |
translate}}</label>
<mat-form-field appearance="fill">
<mat-label>{{'QUESTION.APPLICATION.START-DATE-PLACEHOLDER' | translate}}</mat-label>
<input matInput [min]="today" [max]="serializedEndDate.value" [matDatepicker]="startDatePicker"
[formControl]="serializedStartDate"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('application.startDate'), 'is-valid' : formFailedSubmit && !errorFields.includes('application.startDate')}">
<mat-datepicker-toggle matSuffix [for]="startDatePicker"></mat-datepicker-toggle>
<mat-datepicker panelClass="datepicker-table-fix" #startDatePicker></mat-datepicker>
</mat-form-field>
</div>

<div class="form-group mt-3">
<label class="form-label" for="application.endDate">{{'APPLICATION.METADATA-FIELD.END-DATE' | translate}}</label>
<mat-form-field appearance="fill">
<mat-label>{{'QUESTION.APPLICATION.END-DATE-PLACEHOLDER' | translate}}</mat-label>
<input matInput [min]="serializedStartDate.value" [matDatepicker]="endDatePicker"
[formControl]="serializedEndDate"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('application.endDate'), 'is-valid' : formFailedSubmit && !errorFields.includes('application.endDate')}">
<mat-datepicker-toggle matSuffix [for]="endDatePicker"></mat-datepicker-toggle>
<mat-datepicker panelClass="datepicker-table-fix" #endDatePicker></mat-datepicker>
</mat-form-field>
</div>

<div class="form-group mt-3">
<label class="form-label" for="application.category">{{'APPLICATION.METADATA-FIELD.CATEGORY' | translate}}</label>
<input type="text" class="form-control" id="category" name="category"
[placeholder]="'QUESTION.APPLICATION.CATEGORY-PLACEHOLDER' | translate" maxlength="100"
[(ngModel)]="application.category"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('application.category'), 'is-valid' : formFailedSubmit && !errorFields.includes('application.category')}">
</div>

<div class="form-group mt-3">
<label class="form-label" for="application.owner">{{'APPLICATION.METADATA-FIELD.OWNER' | translate}}</label>
<input type="text" class="form-control" id="owner" name="owner"
[placeholder]="'QUESTION.APPLICATION.OWNER-PLACEHOLDER' | translate" maxlength="100"
[(ngModel)]="application.owner"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('application.owner'), 'is-valid' : formFailedSubmit && !errorFields.includes('application.owner')}">
</div>

<div class="form-group mt-3">
<label class="form-label" for="application.contactPerson">{{'APPLICATION.METADATA-FIELD.CONTACT-PERSON' |
translate}}</label>
<input type="text" class="form-control" id="contactPerson" name="contactPerson"
[placeholder]="'QUESTION.APPLICATION.CONTACT-PERSON-PLACEHOLDER' | translate" maxlength="100"
[(ngModel)]="application.contactPerson"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('application.contactPerson'), 'is-valid' : formFailedSubmit && !errorFields.includes('application.contactPerson')}">
</div>

<div class="form-group mt-3">
<label class="form-label" for="application.contactEmail">{{'APPLICATION.METADATA-FIELD.CONTACT-EMAIL' |
translate}}</label>
<input type="email" class="form-control" id="contactEmail" name="contactEmail"
[placeholder]="'QUESTION.APPLICATION.CONTACT-EMAIL-PLACEHOLDER' | translate" maxlength="50" [email]="true"
[(ngModel)]="application.contactEmail"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('application.contactEmail'), 'is-valid' : formFailedSubmit && !errorFields.includes('application.contactEmail')}">
</div>

<div class="form-group mt-3">
<label class="form-label" for="application.contactPhone">{{'APPLICATION.METADATA-FIELD.CONTACT-PHONE' |
translate}}</label>
<input type="text" class="form-control" id="contactPhone" name="contactPhone" [formControl]="phoneCtrl"
[placeholder]="'QUESTION.APPLICATION.CONTACT-PHONE-PLACEHOLDER' | translate" maxlength="12"
[ngClass]="{'is-invalid' : application.contactPhone && phoneCtrl.invalid, 'is-valid' : !phoneCtrl.invalid}">
</div>

<div class="form-group mt-3">
<mat-checkbox id="application.personalData" name="application.personalData"
[(ngModel)]="application.personalData">
<mat-label for="application.personalData" class="form-check-label text--bold margin-top-25px"
style="white-space: initial">{{'QUESTION.APPLICATION.PERSONAL-DATA-PLACEHOLDER' | translate}}</mat-label>
</mat-checkbox>
</div>

<div class="form-group mt-3">
<label class="form-label" for="application.hardware">{{'APPLICATION.METADATA-FIELD.HARDWARE' | translate}}</label>
<textarea id="application.hardware" name="application.hardware"
[placeholder]="'QUESTION.APPLICATION.HARDWARE-PLACEHOLDER' | translate" [maxLength]="1024" [rows]="6"
class="form-control" [(ngModel)]="application.hardware"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('application.hardware'), 'is-valid' : formFailedSubmit && !errorFields.includes('application.hardware')}"></textarea>
</div>

<div class="form-group mt-3">
<label class="form-label" for="application.controlledProperty">{{'APPLICATION.METADATA-FIELD.CONTROLLED-PROPERTY'
|
translate}}</label>
<mat-select class="form-control" name="application.controlledProperty" multiple="true"
[(ngModel)]="application.controlledProperties"
[placeholder]="'QUESTION.APPLICATION.CONTROLLED-PROPERTY-PLACEHOLDER' | translate"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('application.controlledProperty'), 'is-valid' : formFailedSubmit && !errorFields.includes('application.controlledProperty')}">
<mat-option *ngFor="let ctrlProperty of controlledProperties" [value]="ctrlProperty">
{{ctrlProperty}}
</mat-option>
</mat-select>
</div>

<div class="form-group mt-3">
<label class="form-label" for="application.deviceType">{{'APPLICATION.METADATA-FIELD.DEVICE-TYPE' |
translate}}</label>
<mat-select class="form-control" name="application.deviceType" multiple="true"
[(ngModel)]="application.deviceTypes" [placeholder]="'QUESTION.APPLICATION.DEVICE-TYPE-PLACEHOLDER' | translate"
[ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('application.deviceType'), 'is-valid' : formFailedSubmit && !errorFields.includes('application.deviceType')}">
<mat-option *ngFor="let deviceType of deviceTypes" [value]="deviceType.value">
{{deviceType.label}}
</mat-option>
</mat-select>
</div>
</div>

<div class="form-group mt-5">
<button (click)="routeBack()" class="btn btn-secondary" type="button">{{ 'GEN.CANCEL' | translate}}</button>
<button class="btn btn-primary ml-2" type="submit">{{ submitButton }}</button>
</div>
</form>
</form>
Loading