diff --git a/.vscode/launch.json b/.vscode/launch.json index 0c95de90..5eb02650 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,13 +1,19 @@ { - "version": "0.2.0", - "configurations": [ - { - "type": "firefox", - "request": "launch", - "reAttach": true, - "name": "Launch localhost", - "url": "http://localhost:4200", - "webRoot": "${workspaceFolder}" - } - ] + "version": "0.2.0", + "configurations": [{ + "type": "firefox", + "request": "launch", + "reAttach": true, + "name": "Launch localhost with Firefox", + "url": "http://localhost:4200", + "webRoot": "${workspaceFolder}" + }, + { + "name": "Launch localhost with Chrome", + "type": "chrome", + "request": "launch", + "url": "http://localhost:4200", + "webRoot": "${workspaceFolder}" + }, + ] } diff --git a/package-lock.json b/package-lock.json index 477d9281..e2f180f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2062,6 +2062,68 @@ } } }, + "@ngrx/effects": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-10.0.0.tgz", + "integrity": "sha512-HHcQQ6mj1Cd0rQgnX5Wp3f7G8PKhh+Rk+jofsOsE6aHQPuuNhmnDwSA1U4PT4sXNv6JmFi5GjUqBz+tuw83oFQ==", + "requires": { + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", + "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" + } + } + }, + "@ngrx/router-store": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/router-store/-/router-store-10.0.0.tgz", + "integrity": "sha512-naK+IlgTQNEWWlKndQIBS/EQZ2h3pRF4owF+4kVpn+OI5Il7+Nugf0spj+0IFGd21Z7YvBe9C54SQPOPP4HARg==", + "requires": { + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", + "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" + } + } + }, + "@ngrx/store": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-10.0.0.tgz", + "integrity": "sha512-+mhTGJXjc+55KI1pWV5SSuP+JBAr35U1AbnBYJqqXuwJVXnJ8+n6gAr06qpPN+YMf+zRQDFwAIrqyFOfMqeJHg==", + "requires": { + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", + "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" + } + } + }, + "@ngrx/store-devtools": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-10.0.0.tgz", + "integrity": "sha512-+7SSPW9H+IdGX04QYmfgqYOeFM++PLD6CxGRUkIIc+6jFovanMS6CVKw6V+WeerPwoZaRn43cMIDj9FChMQ4oA==", + "dev": true, + "requires": { + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", + "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==", + "dev": true + } + } + }, "@ngtools/webpack": { "version": "9.1.9", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-9.1.9.tgz", @@ -4456,6 +4518,12 @@ "regexp.prototype.flags": "^1.2.0" } }, + "deep-freeze-strict": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-freeze-strict/-/deep-freeze-strict-1.1.1.tgz", + "integrity": "sha1-d9BYPKJKab5LvZrC+uQV1VUj5bA=", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -8468,6 +8536,15 @@ "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, + "ngrx-store-freeze": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/ngrx-store-freeze/-/ngrx-store-freeze-0.2.4.tgz", + "integrity": "sha512-90awpbbMa/x2H81eWWYniyli3LJ1PZU/FaztL10d9Rp/4kw2+97pqyLjdxSPxcOv9St//m9kfuWZ7gyoVDjgcg==", + "dev": true, + "requires": { + "deep-freeze-strict": "^1.1.1" + } + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -12766,6 +12843,12 @@ } } }, + "tslint-angular": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tslint-angular/-/tslint-angular-3.0.3.tgz", + "integrity": "sha512-5xD1gLE89lBExfSbMslDw/ZfOZM0t0CJsoJa4svsgF7tlwVS3IpXjzNcNRN0RZqDBj+cdTlbeel6GpZ3PqpPiw==", + "dev": true + }, "tslint-config-prettier": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", diff --git a/package.json b/package.json index 2e325947..cbd385f5 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,9 @@ "@fortawesome/free-solid-svg-icons": "^5.13.0", "@ng-bootstrap/ng-bootstrap": "^6.1.0", "@ng-bootstrap/schematics": "^2.0.0-alpha.1", + "@ngrx/effects": "^10.0.0", + "@ngrx/router-store": "^10.0.0", + "@ngrx/store": "^10.0.0", "@ngx-translate/core": "^13.0.0", "@ngx-translate/http-loader": "^6.0.0", "all": "0.0.0", @@ -43,6 +46,7 @@ "@angular-devkit/build-angular": "^0.901.9", "@angular/cli": "~9.1.9", "@angular/compiler-cli": "~9.1.11", + "@ngrx/store-devtools": "^10.0.0", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "@types/node": "^12.11.1", @@ -55,9 +59,11 @@ "karma-coverage-istanbul-reporter": "~2.1.0", "karma-jasmine": "~3.0.1", "karma-jasmine-html-reporter": "^1.4.2", + "ngrx-store-freeze": "^0.2.4", "prettier": "^2.0.5", "protractor": "~7.0.0", "ts-node": "~8.3.0", + "tslint-angular": "^3.0.3", "tslint-config-prettier": "^1.18.0", "typescript": "~3.8.3" } diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index bc2eeffb..80c2c39e 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,78 +1,86 @@ -import { NgModule, Component } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; -import { DashboardComponent } from './views/dashboard/dashboard/dashboard.component'; -import { MineApplikationerComponent } from './views/mine-applikationer/mine-applikationer/mine-applikationer.component'; -import { EditApplicationComponent } from './views/mine-applikationer/edit-application/edit-application.component'; -import { ListApplicationsComponent } from './views/mine-applikationer/list-applications/list-applications.component'; -import { ApplicationComponent } from './views/mine-applikationer/application/application.component'; -import { IoTDeviceComponent } from './views/alle-iot-enheder/iot-device/iot-device.component'; -import { EditIotDeviceComponent } from './views/alle-iot-enheder/edit-iot-device/edit-iot-device.component'; -import { MineLoraGatewaysComponent } from './views/administration-gateway/mine-lora-gateways/mine-lora-gateways.component'; -import { ListLoraGatewayComponent } from './views/administration-gateway/list-lora-gateway/list-lora-gateway.component'; -import { EditGatewayComponent } from './views/administration-gateway/edit-gateway/edit-gateway.component'; -import { GatewayComponent } from './views/administration-gateway/gateway/gateway.component'; -import { DatatargetListComponent } from './views/datatarget/datatarget-list/datatarget-list.component'; -import { DatatargetEditComponent } from './views/datatarget/datatarget-edit/datatarget-edit.component'; -import { DatatargetComponent } from './views/datatarget/datatarget/datatarget.component'; - -const routes: Routes = [ - { path: 'home', component: DashboardComponent }, - { path: 'mine-applikationer', component: MineApplikationerComponent, - children: [ - { path: '', component: ListApplicationsComponent }, - { path: 'application/:id', - children: [ - { path: '', component: ApplicationComponent }, - { path: 'edit-iot-device', component: EditIotDeviceComponent,}, - { path: 'edit-iot-device/:deviceId', component: EditIotDeviceComponent,}, - { path: 'iot-device/:deviceId', component: IoTDeviceComponent, }, - { path: '', component: ApplicationComponent, - - }, - { - path: 'edit-iot-device', - component: EditIotDeviceComponent, - }, - { - path: 'edit-iot-device/:deviceId', - component: EditIotDeviceComponent, - }, - { - path: 'iot-device/:deviceId', - component: IoTDeviceComponent, - }, - { - path: 'datatarget-list/:name', - children: [ - { path: '', component: DatatargetListComponent}, - { path: 'datatarget-edit', component: DatatargetEditComponent}, - { path: 'datatarget-edit/:datatargetId', component: DatatargetEditComponent}, - { path: 'datatarget/:datatargetId', component: DatatargetComponent} - ] - - } - ], - }, - { path: 'edit-application', component: EditApplicationComponent,}, - { path: 'edit-application/:id', component: EditApplicationComponent,}, - ], - }, - { path: 'mine-lora-gateways', component: MineLoraGatewaysComponent, - children: [ - { path: '', component: ListLoraGatewayComponent}, - { path: 'edit-gateway/:id', component: EditGatewayComponent}, - { path: 'edit-gateway', component: EditGatewayComponent}, - { path: 'gateway/:id', component: GatewayComponent} - ], - - }, - { path: 'datatarget', component: DatatargetListComponent }, - { path: '', redirectTo: '/home', pathMatch: 'full' }, - { path: '**', redirectTo: '/home', pathMatch: 'full' }, -]; - -@NgModule({ - imports: [RouterModule.forRoot(routes)], - exports: [RouterModule], -}) -export class AppRoutingModule {} +import { NgModule, Component } from '@angular/core'; +import { Routes, RouterModule, PreloadAllModules } from '@angular/router'; +import { DashboardComponent } from './views/dashboard/dashboard/dashboard.component'; +import { EditApplicationComponent } from './my-applications/edit-application/edit-application.component'; +import { ListApplicationsComponent } from './my-applications/list-applications/list-applications.component'; +import { ApplicationComponent } from './my-applications/application/application.component'; +import { IoTDeviceComponent } from './views/alle-iot-enheder/iot-device/iot-device.component'; +import { EditIotDeviceComponent } from './views/alle-iot-enheder/edit-iot-device/edit-iot-device.component'; +import { MineLoraGatewaysComponent } from './views/administration-gateway/mine-lora-gateways/mine-lora-gateways.component'; +import { ListLoraGatewayComponent } from './views/administration-gateway/list-lora-gateway/list-lora-gateway.component'; +import { EditGatewayComponent } from './views/administration-gateway/edit-gateway/edit-gateway.component'; +import { GatewayComponent } from './views/administration-gateway/gateway/gateway.component'; +import { DatatargetListComponent } from './views/datatarget/datatarget-list/datatarget-list.component'; +import { DatatargetEditComponent } from './views/datatarget/datatarget-edit/datatarget-edit.component'; +import { DatatargetComponent } from './views/datatarget/datatarget/datatarget.component'; +import { ProfilesComponent } from './profiles/profiles.component'; +import { AlleIotEnhederComponent } from './views/alle-iot-enheder/alle-iot-enheder/alle-iot-enheder.component'; +import { MyApplicationsComponent } from './my-applications/my-applications.component'; + +const routes: Routes = [ + { path: 'home', component: DashboardComponent }, + { + path: 'my-applications', component: MyApplicationsComponent, + children: [ + { path: '', component: ListApplicationsComponent }, + { + path: 'application/:id', + children: [ + { path: '', component: ApplicationComponent }, + { path: 'edit-iot-device', component: EditIotDeviceComponent, }, + { path: 'edit-iot-device/:deviceId', component: EditIotDeviceComponent, }, + { path: 'iot-device/:deviceId', component: IoTDeviceComponent, }, + { + path: '', component: ApplicationComponent, + + }, + { + path: 'edit-iot-device', + component: EditIotDeviceComponent, + }, + { + path: 'edit-iot-device/:deviceId', + component: EditIotDeviceComponent, + }, + { + path: 'iot-device/:deviceId', + component: IoTDeviceComponent, + }, + { + path: 'datatarget-list/:name', + children: [ + { path: '', component: DatatargetListComponent }, + { path: 'datatarget-edit', component: DatatargetEditComponent }, + { path: 'datatarget-edit/:datatargetId', component: DatatargetEditComponent }, + { path: 'datatarget/:datatargetId', component: DatatargetComponent } + ] + + } + ], + }, + { path: 'edit-application', component: EditApplicationComponent, }, + { path: 'edit-application/:id', component: EditApplicationComponent, }, + ], + }, + { + path: 'mine-lora-gateways', component: MineLoraGatewaysComponent, + children: [ + { path: '', component: ListLoraGatewayComponent }, + { path: 'edit-gateway/:id', component: EditGatewayComponent }, + { path: 'edit-gateway', component: EditGatewayComponent }, + { path: 'gateway/:id', component: GatewayComponent } + ], + + }, + { path: 'datatarget', component: DatatargetListComponent }, + { path: 'iot-devices', component: AlleIotEnhederComponent }, + { path: 'profiles', loadChildren: () => import('./profiles/profiles.module').then(m => m.ProfilesModule) }, + { path: '', redirectTo: '/home', pathMatch: 'full' }, + { path: '**', redirectTo: '/home', pathMatch: 'full' }, +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })], + exports: [RouterModule], +}) +export class AppRoutingModule { } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 396a279d..646c18f8 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,53 +1,69 @@ -import { BrowserModule } from '@angular/platform-browser'; -import { NgModule } from '@angular/core'; -import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; -import { TranslateHttpLoader } from '@ngx-translate/http-loader'; -import { HttpClient, HttpClientModule } from '@angular/common/http'; - -import { AppRoutingModule } from './app-routing.module'; - -import { AppComponent } from './app.component'; - -import { DashboardModule } from './views/dashboard/dashboard.module'; -import { MineApplikationerModule } from './views/mine-applikationer/mine-applikationer.module'; -import { AlleIotEnhederModule } from './views/alle-iot-enheder/alle-iot-enheder.module'; -import { NavbarModule } from './shared/navbar/navbar.module'; -import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; -import { ReactiveFormsModule } from '@angular/forms'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { AdministrationGatewayModule } from './views/administration-gateway/administration-gateway.module'; -import { DatatargetModule } from './views/datatarget/datatarget.module'; - -export function HttpLoaderFactory(http: HttpClient) { - return new TranslateHttpLoader(http, './assets/i18n/', '.json'); -} - -@NgModule({ - declarations: [AppComponent], - imports: [ - BrowserModule, - HttpClientModule, - AppRoutingModule, - DashboardModule, - MineApplikationerModule, - AlleIotEnhederModule, - DatatargetModule, - NavbarModule, - TranslateModule.forRoot({ - defaultLanguage: 'da', - loader: { - provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient], - }, - }), - NgbModule, - ReactiveFormsModule, - BrowserAnimationsModule, - AdministrationGatewayModule - ], - providers: [], - bootstrap: [AppComponent], - exports: [TranslateModule], -}) -export class AppModule {} +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; +import { TranslateHttpLoader } from '@ngx-translate/http-loader'; +import { HttpClient, HttpClientModule } from '@angular/common/http'; +import { StoreModule } from '@ngrx/store'; +import { EffectsModule } from '@ngrx/effects'; +import { StoreDevtoolsModule } from '@ngrx/store-devtools'; +import { StoreRouterConnectingModule } from '@ngrx/router-store'; + +import { AppRoutingModule } from './app-routing.module'; + +import { AppComponent } from './app.component'; +import { appReducer, metaReducers } from './store/app.reducer'; +import { ServiceProfileEffects } from './profiles/service-profiles/store/service-profile.effects'; +import { environment } from '../environments/environment'; + +import { DashboardModule } from './views/dashboard/dashboard.module'; +import { MineApplikationerModule } from './my-applications/my-applications.module'; +import { AlleIotEnhederModule } from './views/alle-iot-enheder/alle-iot-enheder.module'; +import { NavbarModule } from './navbar/navbar.module'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { ReactiveFormsModule } from '@angular/forms'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { AdministrationGatewayModule } from './views/administration-gateway/administration-gateway.module'; +import { DatatargetModule } from './views/datatarget/datatarget.module'; +import { LoggingService } from './logging.service'; +import { ProfilesModule } from './profiles/profiles.module'; + +export function HttpLoaderFactory(http: HttpClient) { + return new TranslateHttpLoader(http, './assets/i18n/', '.json'); +} + +@NgModule({ + declarations: [AppComponent], + imports: [ + BrowserModule, + BrowserAnimationsModule, + HttpClientModule, + AppRoutingModule, + DashboardModule, + MineApplikationerModule, + AlleIotEnhederModule, + DatatargetModule, + NavbarModule, + ProfilesModule, + TranslateModule, + StoreModule.forRoot(appReducer, { metaReducers }), + !environment.production ? StoreDevtoolsModule.instrument() : [], + EffectsModule.forRoot([ServiceProfileEffects]), + StoreRouterConnectingModule.forRoot({ stateKey: 'router' }), + TranslateModule.forRoot({ + defaultLanguage: 'da', + loader: { + provide: TranslateLoader, + useFactory: HttpLoaderFactory, + deps: [HttpClient], + }, + }), + NgbModule, + ReactiveFormsModule, + BrowserAnimationsModule, + AdministrationGatewayModule + ], + providers: [LoggingService], + bootstrap: [AppComponent], + exports: [TranslateModule], +}) +export class AppModule { } diff --git a/src/app/logging.service.ts b/src/app/logging.service.ts new file mode 100644 index 00000000..0aec60c6 --- /dev/null +++ b/src/app/logging.service.ts @@ -0,0 +1,12 @@ +import { Injectable } from '@angular/core'; + +// @Injectable({ providedIn: 'root' }) +export class LoggingService { + lastlog: string; + + printLog(message: string) { + console.log(message); + console.log(this.lastlog); + this.lastlog = message; + } +} diff --git a/src/app/views/mine-applikationer/application/application.component.html b/src/app/my-applications/application/application.component.html similarity index 98% rename from src/app/views/mine-applikationer/application/application.component.html rename to src/app/my-applications/application/application.component.html index 522e3a3f..e44e02ba 100644 --- a/src/app/views/mine-applikationer/application/application.component.html +++ b/src/app/my-applications/application/application.component.html @@ -24,4 +24,4 @@

{{ 'APPLICATION.DESCRIPTION' | translate }}

- + \ No newline at end of file diff --git a/src/app/views/mine-applikationer/application/application.component.scss b/src/app/my-applications/application/application.component.scss similarity index 100% rename from src/app/views/mine-applikationer/application/application.component.scss rename to src/app/my-applications/application/application.component.scss diff --git a/src/app/views/mine-applikationer/application/application.component.spec.ts b/src/app/my-applications/application/application.component.spec.ts similarity index 100% rename from src/app/views/mine-applikationer/application/application.component.spec.ts rename to src/app/my-applications/application/application.component.spec.ts diff --git a/src/app/views/mine-applikationer/application/application.component.ts b/src/app/my-applications/application/application.component.ts similarity index 93% rename from src/app/views/mine-applikationer/application/application.component.ts rename to src/app/my-applications/application/application.component.ts index 69b344e9..d68530b4 100644 --- a/src/app/views/mine-applikationer/application/application.component.ts +++ b/src/app/my-applications/application/application.component.ts @@ -8,7 +8,7 @@ import { Application } from 'src/app/models/application'; import { Sort } from 'src/app/models/sort'; import { QuickActionButton } from 'src/app/models/quick-action-button'; import { IotDevice } from 'src/app/models/iot-device'; -import { ApplicationService } from '../../../shared/_services/application.service'; +import { ApplicationService } from '../../shared/services/application.service'; import { BackButton } from 'src/app/models/back-button'; @Component({ @@ -19,7 +19,7 @@ import { BackButton } from 'src/app/models/back-button'; export class ApplicationComponent implements OnInit { public applicationsSubscription: Subscription; public application: Application; - public backButton: BackButton = {label: '', routerLink: '/mine-applikationer'}; + public backButton: BackButton = { label: '', routerLink: '/my-applications' }; private id: number; public pageLimit: number = 10; public selectedSortId: number = 6; @@ -111,7 +111,7 @@ export class ApplicationComponent implements OnInit { private applicationService: ApplicationService, private route: ActivatedRoute, public translate: TranslateService - ) {} + ) { } ngOnInit(): void { this.id = +this.route.snapshot.paramMap.get('id'); @@ -119,9 +119,9 @@ export class ApplicationComponent implements OnInit { this.bindApplication(this.id); } this.translate.get(['NAV.MY-APPLICATIONS']) - .subscribe(translations => { - this.backButton.label = translations['NAV.MY-APPLICATIONS']; - }); + .subscribe(translations => { + this.backButton.label = translations['NAV.MY-APPLICATIONS']; + }); } bindApplication(id: number): void { diff --git a/src/app/my-applications/applications-table/applications-table-row/applications-table-row.component.html b/src/app/my-applications/applications-table/applications-table-row/applications-table-row.component.html new file mode 100644 index 00000000..7c4ff1ab --- /dev/null +++ b/src/app/my-applications/applications-table/applications-table-row/applications-table-row.component.html @@ -0,0 +1,24 @@ + + {{application.name}} + + + {{application.iotDevices.length}} + + + 0 + + + {{application.updatedAt | date:'dd/MM yyyy'}} + + \ No newline at end of file diff --git a/src/app/views/mine-applikationer/applications-table-row/applications-table-row.component.scss b/src/app/my-applications/applications-table/applications-table-row/applications-table-row.component.scss similarity index 100% rename from src/app/views/mine-applikationer/applications-table-row/applications-table-row.component.scss rename to src/app/my-applications/applications-table/applications-table-row/applications-table-row.component.scss diff --git a/src/app/views/mine-applikationer/applications-table-row/applications-table-row.component.spec.ts b/src/app/my-applications/applications-table/applications-table-row/applications-table-row.component.spec.ts similarity index 100% rename from src/app/views/mine-applikationer/applications-table-row/applications-table-row.component.spec.ts rename to src/app/my-applications/applications-table/applications-table-row/applications-table-row.component.spec.ts diff --git a/src/app/views/mine-applikationer/applications-table-row/applications-table-row.component.ts b/src/app/my-applications/applications-table/applications-table-row/applications-table-row.component.ts similarity index 100% rename from src/app/views/mine-applikationer/applications-table-row/applications-table-row.component.ts rename to src/app/my-applications/applications-table/applications-table-row/applications-table-row.component.ts diff --git a/src/app/views/mine-applikationer/applications-table/applications-table.component.html b/src/app/my-applications/applications-table/applications-table.component.html similarity index 100% rename from src/app/views/mine-applikationer/applications-table/applications-table.component.html rename to src/app/my-applications/applications-table/applications-table.component.html diff --git a/src/app/views/mine-applikationer/applications-table/applications-table.component.scss b/src/app/my-applications/applications-table/applications-table.component.scss similarity index 100% rename from src/app/views/mine-applikationer/applications-table/applications-table.component.scss rename to src/app/my-applications/applications-table/applications-table.component.scss diff --git a/src/app/views/mine-applikationer/applications-table/applications-table.component.spec.ts b/src/app/my-applications/applications-table/applications-table.component.spec.ts similarity index 100% rename from src/app/views/mine-applikationer/applications-table/applications-table.component.spec.ts rename to src/app/my-applications/applications-table/applications-table.component.spec.ts diff --git a/src/app/views/mine-applikationer/applications-table/applications-table.component.ts b/src/app/my-applications/applications-table/applications-table.component.ts similarity index 96% rename from src/app/views/mine-applikationer/applications-table/applications-table.component.ts rename to src/app/my-applications/applications-table/applications-table.component.ts index 2c1376a1..f6c52bcd 100644 --- a/src/app/views/mine-applikationer/applications-table/applications-table.component.ts +++ b/src/app/my-applications/applications-table/applications-table.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit, OnDestroy, Input, OnChanges } from '@angular/core'; import { Subscription, Observable } from 'rxjs'; import { TranslateService } from '@ngx-translate/core'; -import { ApplicationService } from 'src/app/shared/_services/application.service'; +import { ApplicationService } from 'src/app/shared/services/application.service'; import { Application } from 'src/app/models/application'; import { Sort } from 'src/app/models/sort'; diff --git a/src/app/views/mine-applikationer/create-application/create-application.component.html b/src/app/my-applications/create-application/create-application.component.html similarity index 100% rename from src/app/views/mine-applikationer/create-application/create-application.component.html rename to src/app/my-applications/create-application/create-application.component.html diff --git a/src/app/views/mine-applikationer/edit-application/edit-application.component.html b/src/app/my-applications/edit-application/edit-application.component.html similarity index 100% rename from src/app/views/mine-applikationer/edit-application/edit-application.component.html rename to src/app/my-applications/edit-application/edit-application.component.html diff --git a/src/app/views/mine-applikationer/edit-application/edit-application.component.scss b/src/app/my-applications/edit-application/edit-application.component.scss similarity index 100% rename from src/app/views/mine-applikationer/edit-application/edit-application.component.scss rename to src/app/my-applications/edit-application/edit-application.component.scss diff --git a/src/app/views/mine-applikationer/edit-application/edit-application.component.spec.ts b/src/app/my-applications/edit-application/edit-application.component.spec.ts similarity index 100% rename from src/app/views/mine-applikationer/edit-application/edit-application.component.spec.ts rename to src/app/my-applications/edit-application/edit-application.component.spec.ts diff --git a/src/app/views/mine-applikationer/edit-application/edit-application.component.ts b/src/app/my-applications/edit-application/edit-application.component.ts similarity index 68% rename from src/app/views/mine-applikationer/edit-application/edit-application.component.ts rename to src/app/my-applications/edit-application/edit-application.component.ts index 08442d3b..9906fcc4 100644 --- a/src/app/views/mine-applikationer/edit-application/edit-application.component.ts +++ b/src/app/my-applications/edit-application/edit-application.component.ts @@ -8,7 +8,7 @@ import { BackButton } from 'src/app/models/back-button'; styleUrls: ['./edit-application.component.scss'] }) export class EditApplicationComponent implements OnInit { - public backButton: BackButton = {label: '', routerLink: '/mine-applikationer'}; + public backButton: BackButton = { label: '', routerLink: '/my-applications' }; public multiPage: boolean = false; public title: string = ''; public sectionTitle: string = ''; @@ -16,16 +16,16 @@ export class EditApplicationComponent implements OnInit { constructor( public translate: TranslateService - ) { + ) { translate.use('da'); } - + ngOnInit(): void { this.translate.get(['NAV.MY-APPLICATIONS', 'FORM.EDIT-NEW-APPLICATION', 'APPLICATION.SAVE']) - .subscribe(translations => { - this.backButton.label = translations['NAV.MY-APPLICATIONS']; - this.title = translations['FORM.EDIT-NEW-APPLICATION']; - this.submitButton = translations['APPLICATION.SAVE']; - }); + .subscribe(translations => { + this.backButton.label = translations['NAV.MY-APPLICATIONS']; + this.title = translations['FORM.EDIT-NEW-APPLICATION']; + this.submitButton = translations['APPLICATION.SAVE']; + }); } } diff --git a/src/app/views/mine-applikationer/list-applications/list-applications.component.html b/src/app/my-applications/list-applications/list-applications.component.html similarity index 100% rename from src/app/views/mine-applikationer/list-applications/list-applications.component.html rename to src/app/my-applications/list-applications/list-applications.component.html diff --git a/src/app/views/mine-applikationer/list-applications/list-applications.component.scss b/src/app/my-applications/list-applications/list-applications.component.scss similarity index 100% rename from src/app/views/mine-applikationer/list-applications/list-applications.component.scss rename to src/app/my-applications/list-applications/list-applications.component.scss diff --git a/src/app/views/mine-applikationer/list-applications/list-applications.component.spec.ts b/src/app/my-applications/list-applications/list-applications.component.spec.ts similarity index 100% rename from src/app/views/mine-applikationer/list-applications/list-applications.component.spec.ts rename to src/app/my-applications/list-applications/list-applications.component.spec.ts diff --git a/src/app/views/mine-applikationer/list-applications/list-applications.component.ts b/src/app/my-applications/list-applications/list-applications.component.ts similarity index 100% rename from src/app/views/mine-applikationer/list-applications/list-applications.component.ts rename to src/app/my-applications/list-applications/list-applications.component.ts diff --git a/src/app/views/mine-applikationer/mine-applikationer/mine-applikationer.component.html b/src/app/my-applications/my-applications.component.html similarity index 100% rename from src/app/views/mine-applikationer/mine-applikationer/mine-applikationer.component.html rename to src/app/my-applications/my-applications.component.html diff --git a/src/app/views/mine-applikationer/mine-applikationer/mine-applikationer.component.scss b/src/app/my-applications/my-applications.component.scss similarity index 100% rename from src/app/views/mine-applikationer/mine-applikationer/mine-applikationer.component.scss rename to src/app/my-applications/my-applications.component.scss diff --git a/src/app/my-applications/my-applications.component.spec.ts b/src/app/my-applications/my-applications.component.spec.ts new file mode 100644 index 00000000..6e72d739 --- /dev/null +++ b/src/app/my-applications/my-applications.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyApplicationsComponent } from './my-applications.component'; + +describe('MyApplicationsComponent', () => { + let component: MyApplicationsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [MyApplicationsComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MyApplicationsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/my-applications/my-applications.component.ts b/src/app/my-applications/my-applications.component.ts new file mode 100644 index 00000000..bad8c479 --- /dev/null +++ b/src/app/my-applications/my-applications.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-my-applications', + templateUrl: './my-applications.component.html', + styleUrls: ['./my-applications.component.scss'] +}) +export class MyApplicationsComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/views/mine-applikationer/mine-applikationer.module.ts b/src/app/my-applications/my-applications.module.ts similarity index 70% rename from src/app/views/mine-applikationer/mine-applikationer.module.ts rename to src/app/my-applications/my-applications.module.ts index 20609581..5b3ca245 100644 --- a/src/app/views/mine-applikationer/mine-applikationer.module.ts +++ b/src/app/my-applications/my-applications.module.ts @@ -4,20 +4,20 @@ import { RouterModule } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; -import { TopBarModule } from 'src/app/shared/top-bar/top-bar.module'; -import { FormModule } from 'src/app/shared/form/form.module'; +import { TopBarModule } from '../shared/top-bar/top-bar.module'; +import { FormModule } from '../shared/form/form.module'; -import { MineApplikationerComponent } from './mine-applikationer/mine-applikationer.component'; +import { MyApplicationsComponent } from './my-applications.component'; import { ApplicationComponent } from './application/application.component'; import { ApplicationsTableComponent } from './applications-table/applications-table.component'; -import { ApplicationsTableRowComponent } from './applications-table-row/applications-table-row.component'; +import { ApplicationsTableRowComponent } from './applications-table/applications-table-row/applications-table-row.component'; import { EditApplicationComponent } from './edit-application/edit-application.component'; import { ListApplicationsComponent } from './list-applications/list-applications.component'; -import { AlleIotEnhederModule } from '../alle-iot-enheder/alle-iot-enheder.module'; +import { AlleIotEnhederModule } from '../views/alle-iot-enheder/alle-iot-enheder.module'; @NgModule({ declarations: [ - MineApplikationerComponent, + MyApplicationsComponent, ApplicationComponent, ApplicationsTableComponent, ApplicationsTableRowComponent, @@ -25,7 +25,7 @@ import { AlleIotEnhederModule } from '../alle-iot-enheder/alle-iot-enheder.modul ListApplicationsComponent, ], exports: [ - MineApplikationerComponent, + MyApplicationsComponent, ApplicationComponent, ApplicationsTableComponent, ApplicationsTableRowComponent, @@ -39,4 +39,4 @@ import { AlleIotEnhederModule } from '../alle-iot-enheder/alle-iot-enheder.modul AlleIotEnhederModule ] }) -export class MineApplikationerModule {} +export class MineApplikationerModule { } diff --git a/src/app/shared/navbar/navbar.component.html b/src/app/navbar/navbar.component.html similarity index 93% rename from src/app/shared/navbar/navbar.component.html rename to src/app/navbar/navbar.component.html index 30861922..84b2946c 100644 --- a/src/app/shared/navbar/navbar.component.html +++ b/src/app/navbar/navbar.component.html @@ -1,31 +1,46 @@ - + \ No newline at end of file diff --git a/src/app/shared/navbar/navbar.component.scss b/src/app/navbar/navbar.component.scss similarity index 100% rename from src/app/shared/navbar/navbar.component.scss rename to src/app/navbar/navbar.component.scss diff --git a/src/app/shared/navbar/navbar.component.spec.ts b/src/app/navbar/navbar.component.spec.ts similarity index 100% rename from src/app/shared/navbar/navbar.component.spec.ts rename to src/app/navbar/navbar.component.spec.ts diff --git a/src/app/shared/navbar/navbar.component.ts b/src/app/navbar/navbar.component.ts similarity index 100% rename from src/app/shared/navbar/navbar.component.ts rename to src/app/navbar/navbar.component.ts diff --git a/src/app/shared/navbar/navbar.module.ts b/src/app/navbar/navbar.module.ts similarity index 84% rename from src/app/shared/navbar/navbar.module.ts rename to src/app/navbar/navbar.module.ts index 562cb250..fa5bd43b 100644 --- a/src/app/shared/navbar/navbar.module.ts +++ b/src/app/navbar/navbar.module.ts @@ -5,10 +5,10 @@ import { CommonModule } from '@angular/common'; import { NavbarComponent } from './navbar.component'; // Modules -import { SharedModule } from '../shared.module'; +import { SharedModule } from '../shared/shared.module'; // Services -import { RestService } from '../_services/rest.service'; +import { RestService } from '../shared/services/rest.service'; import { RouterModule } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; diff --git a/src/app/profiles/profiles-list/profiles-list.component.html b/src/app/profiles/profiles-list/profiles-list.component.html new file mode 100644 index 00000000..d77f261e --- /dev/null +++ b/src/app/profiles/profiles-list/profiles-list.component.html @@ -0,0 +1,6 @@ +
+ +
+
+ +
\ No newline at end of file diff --git a/src/app/profiles/profiles-list/profiles-list.component.scss b/src/app/profiles/profiles-list/profiles-list.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/profiles/profiles-list/profiles-list.component.ts b/src/app/profiles/profiles-list/profiles-list.component.ts new file mode 100644 index 00000000..3a25b661 --- /dev/null +++ b/src/app/profiles/profiles-list/profiles-list.component.ts @@ -0,0 +1,22 @@ +import { Component, OnInit } from '@angular/core'; +import { Router, ActivatedRoute } from '@angular/router'; + +@Component({ + selector: 'app-profiles-list', + templateUrl: './profiles-list.component.html', + styleUrls: ['./profiles-list.component.scss'] +}) +export class ProfilesListComponent implements OnInit { + + constructor( + private router: Router, + private route: ActivatedRoute, + ) { } + + ngOnInit(): void { + } + + onNewServiceProfile() { + this.router.navigate(['new-profile'], { relativeTo: this.route }); + } +} diff --git a/src/app/profiles/profiles-routing.module.ts b/src/app/profiles/profiles-routing.module.ts new file mode 100644 index 00000000..2fd0e98d --- /dev/null +++ b/src/app/profiles/profiles-routing.module.ts @@ -0,0 +1,35 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { ServiceProfilesEditComponent } from './service-profiles/service-profiles-edit/service-profiles-edit.component'; +import { ServiceProfilesDetailComponent } from './service-profiles/service-profiles-detail/service-profiles-detail.component'; +import { ServiceProfileResolverService } from './service-profiles/service-profile-resolver.service'; +import { ProfilesComponent } from './profiles.component'; +import { ProfilesListComponent } from './profiles-list/profiles-list.component'; + + +const routes: Routes = [ + { + path: '', + component: ProfilesComponent, + children: [ + { path: '', component: ProfilesListComponent }, + { path: 'new', component: ServiceProfilesEditComponent }, + { + path: ':id', + component: ServiceProfilesDetailComponent, + resolve: [ServiceProfileResolverService] + }, + { + path: ':id/edit-profile', + component: ServiceProfilesEditComponent, + resolve: [ServiceProfileResolverService] + } + ] + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class ProfilesRoutingModule { } diff --git a/src/app/profiles/profiles.component.html b/src/app/profiles/profiles.component.html new file mode 100644 index 00000000..9742badc --- /dev/null +++ b/src/app/profiles/profiles.component.html @@ -0,0 +1,3 @@ +
+ +
\ No newline at end of file diff --git a/src/app/profiles/profiles.component.ts b/src/app/profiles/profiles.component.ts new file mode 100644 index 00000000..b24894a1 --- /dev/null +++ b/src/app/profiles/profiles.component.ts @@ -0,0 +1,29 @@ +import { Component, OnInit } from '@angular/core'; +import { LoggingService } from '../logging.service'; +import { ServiceProfile } from './service-profiles/service-profile.model'; +import * as ServiceProfilesAction from './service-profiles/store/service-profile.actions'; +import { Store } from '@ngrx/store'; +import * as fromApp from '../store/app.reducer'; + +@Component({ + selector: 'app-profiles', + templateUrl: './profiles.component.html' +}) +export class ProfilesComponent implements OnInit { + + constructor( + private store: Store, + private loggingService: LoggingService, + ) { } + + ngOnInit(): void { + this.loggingService.printLog('Profiles tapped'); + this.onFetchData(); + } + + onFetchData() { + // this.dataStorageService.fetchRecipes().subscribe(); + this.store.dispatch(new ServiceProfilesAction.FetchServiceProfiles()); + } + +} diff --git a/src/app/profiles/profiles.module.ts b/src/app/profiles/profiles.module.ts new file mode 100644 index 00000000..389b6a1f --- /dev/null +++ b/src/app/profiles/profiles.module.ts @@ -0,0 +1,37 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { ProfilesComponent } from './profiles.component'; +import { ProfilesRoutingModule } from './profiles-routing.module'; +import { LoggingService } from '../logging.service'; +import { RouterModule } from '@angular/router'; +import { ServiceProfilesModule } from './service-profiles/service-profiles.module'; +import { ProfilesListComponent } from './profiles-list/profiles-list.component'; +import { SharedModule } from '../shared/shared.module'; +import { TopBarModule } from '../shared/top-bar/top-bar.module'; +import { FormModule } from '../shared/form/form.module'; +import { TranslateModule } from '@ngx-translate/core'; + + + +@NgModule({ + declarations: [ + ProfilesComponent, + ProfilesListComponent, + ], + exports: [], + imports: [ + ServiceProfilesModule, + ProfilesRoutingModule, + RouterModule, + TopBarModule, + SharedModule, + FormModule, + TranslateModule + + ], + providers: [ + LoggingService, + ] +}) +export class ProfilesModule { } diff --git a/src/app/profiles/service-profiles/service-profile-resolver.service.ts b/src/app/profiles/service-profiles/service-profile-resolver.service.ts new file mode 100644 index 00000000..d69f0f90 --- /dev/null +++ b/src/app/profiles/service-profiles/service-profile-resolver.service.ts @@ -0,0 +1,40 @@ + + +import { ServiceProfile } from './service-profile.model'; +import * as fromApp from '../../store/app.reducer'; +import * as ServiceProfileActions from './store/service-profile.actions'; +import { LoggingService } from 'src/app/logging.service'; +import { Injectable } from '@angular/core'; +import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { Store } from '@ngrx/store'; +import { Actions, ofType } from '@ngrx/effects'; +import { take, map, switchMap } from 'rxjs/operators'; +import { of } from 'rxjs'; + +@Injectable({ providedIn: 'root' }) +export class ServiceProfileResolverService implements Resolve { + constructor( + private store: Store, + private actions$: Actions, + ) { } + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + return this.store.select('serviceProfiles').pipe( + take(1), + map(serviceProfileState => { + return serviceProfileState.serviceProfiles; + }), + switchMap(serviceProfiles => { + if (serviceProfiles.length === 0) { + this.store.dispatch(new ServiceProfileActions.FetchServiceProfiles()); + return this.actions$.pipe( + ofType(ServiceProfileActions.SET_SERVICEPROFILES), + take(1) + ); + } else { + return of(serviceProfiles); + } + }) + ); + } +} diff --git a/src/app/profiles/service-profiles/service-profile.model.ts b/src/app/profiles/service-profiles/service-profile.model.ts new file mode 100644 index 00000000..8db1b008 --- /dev/null +++ b/src/app/profiles/service-profiles/service-profile.model.ts @@ -0,0 +1,79 @@ +export class ServiceProfile { + public id: string; + public name: string; + public networkServerID: string; + public addGWMetaData: boolean; + public channelMask: string; + public devStatusReqFreq: number; + public dlBucketSize: number; + public dlRate: number; + public dlRatePolicy: string; + public drMax: number; + public drMin: number; + public hrAllowed: boolean; + public minGWDiversity: number; + public nwkGeoLoc: boolean; + public organizationID: string; + public prAllowed: boolean; + public raAllowed: boolean; + public reportDevStatusBattery: boolean; + public reportDevStatusMargin: boolean; + public targetPER: number; + public ulBucketSize: number; + public ulRate: number; + public ulRatePolicy: string; + + constructor( + id: string, + name: string, + networkServerID: string, + addGWMetaData: boolean, + channelMask: string, + devStatusReqFreq: number, + dlBucketSize: number, + dlRate: number, + dlRatePolicy: string, + drMax: number, + drMin: number, + hrAllowed: boolean, + minGWDiversity: number, + nwkGeoLoc: boolean, + organizationID: string, + prAllowed: boolean, + raAllowed: boolean, + reportDevStatusBattery: boolean, + reportDevStatusMargin: boolean, + targetPER: number, + ulBucketSize: number, + ulRate: number, + ulRatePolicy: string) { + this.id = id; + this.name = name; + this.networkServerID = networkServerID; + this.addGWMetaData = addGWMetaData; + this.channelMask = channelMask; + this.devStatusReqFreq = devStatusReqFreq; + this.dlBucketSize = dlBucketSize; + this.dlRate = dlRate; + this.dlRatePolicy = dlRatePolicy; + this.drMax = drMax; + this.drMin = drMin; + this.hrAllowed = hrAllowed; + this.minGWDiversity = minGWDiversity; + this.nwkGeoLoc = nwkGeoLoc; + this.organizationID = organizationID; + this.prAllowed = prAllowed; + this.raAllowed = raAllowed; + this.reportDevStatusBattery = reportDevStatusBattery; + this.reportDevStatusMargin = reportDevStatusMargin; + this.targetPER = targetPER; + this.ulBucketSize = ulBucketSize; + this.ulRate = ulRate; + this.ulRatePolicy = ulRatePolicy; + } +} + +export interface ServiceProfileData { + result: ServiceProfile[]; + totalCount?: string; +} diff --git a/src/app/profiles/service-profiles/service-profiles-detail/service-profiles-detail.component.html b/src/app/profiles/service-profiles/service-profiles-detail/service-profiles-detail.component.html new file mode 100644 index 00000000..1a38a536 --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles-detail/service-profiles-detail.component.html @@ -0,0 +1,71 @@ +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+

{{'PROFILES.SERVICE_PROFILE.NAME' | translate}}

+
+
+

{{serviceProfile.name}}

+
+
+
+
+

{{'PROFILES.SERVICE_PROFILE.REPORTBATTERYSTATUS' | translate}}

+
+
+

{{serviceProfile.reportDevStatusBattery}}

+
+
+
+
+

{{'PROFILES.SERVICE_PROFILE.ADDGWMETADATA' | translate}}

+
+
+

{{ serviceProfile.addGWMetaData }}

+
+
+
+
+

{{'PROFILES.SERVICE_PROFILE.DRRATEMIN' | translate}}

+
+
+

{{ serviceProfile.drMin }}

+
+
+
+
+

{{'PROFILES.SERVICE_PROFILE.DRRATEMAX' | translate}}

+
+
+

{{ serviceProfile.drMax}}

+
+
+
+
+

{{'PROFILES.SERVICE_PROFILE.REPORT_END_DEVICE' | translate}}

+
+
+

{{ serviceProfile.targetPER }}

+
+
+
\ No newline at end of file diff --git a/src/app/profiles/service-profiles/service-profiles-detail/service-profiles-detail.component.ts b/src/app/profiles/service-profiles/service-profiles-detail/service-profiles-detail.component.ts new file mode 100644 index 00000000..126b05b6 --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles-detail/service-profiles-detail.component.ts @@ -0,0 +1,63 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Store } from '@ngrx/store'; +import { map, switchMap } from 'rxjs/operators'; + +import { ServiceProfile } from '../service-profile.model'; +import * as fromApp from '../../../store/app.reducer'; +import * as ServiceProfilesActions from '../store/service-profile.actions'; +import { BackButton } from 'src/app/models/back-button'; +import { TranslateService } from '@ngx-translate/core'; + + +@Component({ + selector: 'app-service-profiles-detail', + templateUrl: './service-profiles-detail.component.html', + +}) +export class ServiceProfilesDetailComponent implements OnInit { + public backButton: BackButton = { label: 'Go back', routerLink: '/profiles' }; + public title: ''; + serviceProfile: ServiceProfile; + id: number; + + constructor( + private route: ActivatedRoute, + private router: Router, + private store: Store, + private translate: TranslateService + ) { translate.use('da'); } + + ngOnInit() { + this.route.params + .pipe( + map(params => { + return +params['id']; + }), + switchMap(id => { + this.id = id; + return this.store.select('serviceProfiles'); + }), + map(serviceProfilesState => { + return serviceProfilesState.serviceProfiles.find((serviceProfile, index) => { + return index === this.id; + }); + }) + ) + .subscribe(serviceProfile => { + this.serviceProfile = serviceProfile; + }); + + } + + + onEditServiceProfile() { + this.router.navigate(['edit'], { relativeTo: this.route }); + } + + onDeleteServiceProfile() { + this.store.dispatch(new ServiceProfilesActions.DeleteServiceProfile(this.id)); + this.router.navigate(['/serviceProfiles']); + } + +} diff --git a/src/app/profiles/service-profiles/service-profiles-edit/service-profiles-edit.component.html b/src/app/profiles/service-profiles/service-profiles-edit/service-profiles-edit.component.html new file mode 100644 index 00000000..3b4501cd --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles-edit/service-profiles-edit.component.html @@ -0,0 +1,79 @@ +
+
+ + +
+ +
+
+
+ + +
+
+
+ +
+
+
+ + + + {{GWvalue}} + + +
+
+
+ +
+
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
\ No newline at end of file diff --git a/src/app/profiles/service-profiles/service-profiles-edit/service-profiles-edit.component.scss b/src/app/profiles/service-profiles/service-profiles-edit/service-profiles-edit.component.scss new file mode 100644 index 00000000..414bc59c --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles-edit/service-profiles-edit.component.scss @@ -0,0 +1,3 @@ +.form-group { + margin-top: 25px; +} diff --git a/src/app/profiles/service-profiles/service-profiles-edit/service-profiles-edit.component.ts b/src/app/profiles/service-profiles/service-profiles-edit/service-profiles-edit.component.ts new file mode 100644 index 00000000..5ae94722 --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles-edit/service-profiles-edit.component.ts @@ -0,0 +1,115 @@ +import { Component, OnInit } from '@angular/core'; +import { FormGroup, FormControl, Validators } from '@angular/forms'; +import { Subscription } from 'rxjs'; +import { ActivatedRoute, Router, Params } from '@angular/router'; +import { Store } from '@ngrx/store'; +import { map } from 'rxjs/operators'; +import * as fromApp from '../../../store/app.reducer'; +import * as ServiceProfilesActions from '../store/service-profile.actions'; +import { BackButton } from 'src/app/models/back-button'; +import { TranslateService } from '@ngx-translate/core'; + +@Component({ + selector: 'app-service-profiles-edit', + templateUrl: './service-profiles-edit.component.html', + styleUrls: ['./service-profiles-edit.component.scss'] + +}) +export class ServiceProfilesEditComponent implements OnInit { + public backButton: BackButton = { label: '', routerLink: '/profiles' }; + public title: 'Service Profile'; + id: number; + editMode = false; + serviceProfileForm: FormGroup; + GWvalues: string[] = ['true', 'false']; + + private storeSub: Subscription; + + constructor( + private route: ActivatedRoute, + private router: Router, + private store: Store, + private translate: TranslateService + ) { } + + ngOnInit() { + this.route.params.subscribe((params: Params) => { + this.id = +params['id']; + this.editMode = params['id'] != null; + this.initForm(); + }); + this.translate.get(['PROFILES.SERVICE_PROFILE.GOBACK', 'PROFILES.SERVICE_PROFILE.ADDSERVICEPROFILE',]) + .subscribe(translations => { + this.backButton.label = translations['PROFILES.SERVICE_PROFILE.GOBACK']; + this.title = translations['PROFILES.SERVICE_PROFILE.ADDSERVICEPROFILE']; + + }); + } + + onSubmit() { + if (this.editMode) { + this.store.dispatch( + new ServiceProfilesActions.UpdateServiceProfile({ + index: this.id, + updateServiceProfile: this.serviceProfileForm.value + }) + ); + } else { + this.store.dispatch(new ServiceProfilesActions.AddServiceProfile(this.serviceProfileForm.value)); + } + this.onCancel(); + } + + + onCancel() { + this.router.navigate(['../'], { relativeTo: this.route }); + } + + ngDestroy() { + if (this.storeSub) { + this.storeSub.unsubscribe(); + } + } + + private initForm() { + let serviceProfileName = 'Navngiv din profil'; + let serviceProfileGWData = false; + let serviceProfileBatteryStatus = true; + let serviceProfileMinDateRate = 2000; + let serviceProfileMaxDateRate = 2000; + let serviceProfileReportEndDevice = 2000; + + if (this.editMode) { + this.storeSub = this.store + .select('serviceProfiles') + .pipe( + map(serviceProfileState => { + return serviceProfileState.serviceProfiles.find((serviceProfile, index) => { + return index === this.id; + }); + }) + ) + .subscribe(serviceProfile => { + serviceProfileName = serviceProfile.name; + serviceProfileGWData = serviceProfile.addGWMetaData; + serviceProfileBatteryStatus = serviceProfile.reportDevStatusBattery; + serviceProfileMinDateRate = serviceProfile.drMin; + serviceProfileMaxDateRate = serviceProfile.drMax; + serviceProfileReportEndDevice = serviceProfile.targetPER; + + }); + } + + this.serviceProfileForm = new FormGroup({ + name: new FormControl(serviceProfileName, Validators.required), + addGWMetaData: new FormControl(serviceProfileGWData, Validators.required), + reportDevStatusBattery: new FormControl(serviceProfileBatteryStatus, Validators.required), + drMin: new FormControl(serviceProfileMinDateRate, Validators.required), + drMax: new FormControl(serviceProfileMaxDateRate, Validators.required), + targetPER: new FormControl(serviceProfileReportEndDevice, Validators.required) + + + }); + } + +} diff --git a/src/app/profiles/service-profiles/service-profiles-list/service-profile-item/service-profile-item.component.html b/src/app/profiles/service-profiles/service-profiles-list/service-profile-item/service-profile-item.component.html new file mode 100644 index 00000000..800e9cf6 --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles-list/service-profile-item/service-profile-item.component.html @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/src/app/profiles/service-profiles/service-profiles-list/service-profile-item/service-profile-item.component.scss b/src/app/profiles/service-profiles/service-profiles-list/service-profile-item/service-profile-item.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/views/mine-applikationer/mine-applikationer/mine-applikationer.component.spec.ts b/src/app/profiles/service-profiles/service-profiles-list/service-profile-item/service-profile-item.component.spec.ts similarity index 50% rename from src/app/views/mine-applikationer/mine-applikationer/mine-applikationer.component.spec.ts rename to src/app/profiles/service-profiles/service-profiles-list/service-profile-item/service-profile-item.component.spec.ts index 06b76a9d..429848f3 100644 --- a/src/app/views/mine-applikationer/mine-applikationer/mine-applikationer.component.spec.ts +++ b/src/app/profiles/service-profiles/service-profiles-list/service-profile-item/service-profile-item.component.spec.ts @@ -1,20 +1,20 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { MineApplikationerComponent } from './mine-applikationer.component'; +import { ServiceProfileItemComponent } from './service-profile-item.component'; -describe('MineApplikationerComponent', () => { - let component: MineApplikationerComponent; - let fixture: ComponentFixture; +describe('ServiceProfileItemComponent', () => { + let component: ServiceProfileItemComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ MineApplikationerComponent ] + declarations: [ ServiceProfileItemComponent ] }) .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(MineApplikationerComponent); + fixture = TestBed.createComponent(ServiceProfileItemComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/profiles/service-profiles/service-profiles-list/service-profile-item/service-profile-item.component.ts b/src/app/profiles/service-profiles/service-profiles-list/service-profile-item/service-profile-item.component.ts new file mode 100644 index 00000000..2f228460 --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles-list/service-profile-item/service-profile-item.component.ts @@ -0,0 +1,38 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { ServiceProfile } from '../../service-profile.model'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Store } from '@ngrx/store'; +import * as ServiceProfilesActions from '../../store/service-profile.actions'; +import * as fromApp from '../../../../store/app.reducer'; + + +@Component({ + selector: 'app-service-profile-item', + templateUrl: './service-profile-item.component.html', + styleUrls: ['./service-profile-item.component.scss'] +}) +export class ServiceProfileItemComponent implements OnInit { + @Input() serviceProfile: ServiceProfile; + @Input() index: number; + id: number; + + constructor( + private route: ActivatedRoute, + private router: Router, + private store: Store + ) { } + + ngOnInit(): void { + } + + onEditServiceProfile() { + //this.router.navigate(['edit-profile'], { relativeTo: this.route }); + this.router.navigate([this.index, 'edit-profile'], { relativeTo: this.route }); + } + + onDeleteServiceProfile() { + this.store.dispatch(new ServiceProfilesActions.DeleteServiceProfile(this.index)); + this.router.navigate(['/profiles']); + } + +} diff --git a/src/app/profiles/service-profiles/service-profiles-list/service-profiles-list.component.html b/src/app/profiles/service-profiles/service-profiles-list/service-profiles-list.component.html new file mode 100644 index 00000000..757c5f06 --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles-list/service-profiles-list.component.html @@ -0,0 +1,15 @@ +
+
+

Service Profiles

+
+
+ +
+
+
+
+
+ +
+
\ No newline at end of file diff --git a/src/app/profiles/service-profiles/service-profiles-list/service-profiles-list.component.scss b/src/app/profiles/service-profiles/service-profiles-list/service-profiles-list.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/profiles/service-profiles/service-profiles-list/service-profiles-list.component.ts b/src/app/profiles/service-profiles/service-profiles-list/service-profiles-list.component.ts new file mode 100644 index 00000000..cb79016a --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles-list/service-profiles-list.component.ts @@ -0,0 +1,47 @@ +import { Component, OnInit, OnChanges, OnDestroy, Input } from '@angular/core'; +import { Subscription } from 'rxjs'; + +import { ServiceProfile } from '../service-profile.model'; +import { map } from 'rxjs/operators'; +import { Store } from '@ngrx/store'; +import * as fromApp from '../../../store/app.reducer'; +import { Router, ActivatedRoute } from '@angular/router'; + + + + +@Component({ + selector: 'app-service-profiles-list', + templateUrl: './service-profiles-list.component.html', + styleUrls: ['./service-profiles-list.component.scss'] +}) +export class ServiceProfilesListComponent implements OnInit, OnDestroy { + serviceProfiles: ServiceProfile[]; + subscription: Subscription; + public pageLimit: 10; + public pageOffset: 0; + + constructor( + private router: Router, + private route: ActivatedRoute, + private store: Store + ) { } + + ngOnInit() { + this.subscription = this.store + .select('serviceProfiles') + .pipe(map(serviceProfileState => serviceProfileState.serviceProfiles)) + .subscribe((serviceProfiles: ServiceProfile[]) => { + this.serviceProfiles = serviceProfiles; + }); + } + + onNewServiceProfile() { + this.router.navigate(['new'], { relativeTo: this.route }); + } + + ngOnDestroy() { + this.subscription.unsubscribe(); + } + +} diff --git a/src/app/profiles/service-profiles/service-profiles.component.html b/src/app/profiles/service-profiles/service-profiles.component.html new file mode 100644 index 00000000..19c10e03 --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles.component.html @@ -0,0 +1,2 @@ +

Service profiles virker +

\ No newline at end of file diff --git a/src/app/profiles/service-profiles/service-profiles.component.ts b/src/app/profiles/service-profiles/service-profiles.component.ts new file mode 100644 index 00000000..9f7e7b01 --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles.component.ts @@ -0,0 +1,14 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-service-profiles', + templateUrl: './service-profiles.component.html', +}) +export class ServiceProfilesComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/profiles/service-profiles/service-profiles.module.ts b/src/app/profiles/service-profiles/service-profiles.module.ts new file mode 100644 index 00000000..e0a4e9f3 --- /dev/null +++ b/src/app/profiles/service-profiles/service-profiles.module.ts @@ -0,0 +1,43 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ServiceProfilesEditComponent } from './service-profiles-edit/service-profiles-edit.component'; +import { ServiceProfilesComponent } from './service-profiles.component'; +import { ServiceProfilesListComponent } from './service-profiles-list/service-profiles-list.component'; +import { ServiceProfileItemComponent } from './service-profiles-list/service-profile-item/service-profile-item.component'; +import { ServiceProfilesDetailComponent } from './service-profiles-detail/service-profiles-detail.component'; +import { ReactiveFormsModule } from '@angular/forms'; +import { StoreModule } from '@ngrx/store'; +import * as fromServiceProfiles from './../service-profiles/store/service-profile.reducer'; +import { RouterModule } from '@angular/router'; +import { FormModule } from 'src/app/shared/form/form.module'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { DirectivesModule } from 'src/app/shared/directives/directives.module'; +import { TranslateModule } from '@ngx-translate/core'; +import { MaterialModule } from 'src/app/shared/Modules/material.module'; + + + + +@NgModule({ + declarations: [ + ServiceProfilesListComponent, + ServiceProfileItemComponent, + ServiceProfilesComponent, + ServiceProfilesDetailComponent, + ServiceProfilesEditComponent, + ], + exports: [ + ServiceProfilesListComponent + ], + imports: [ + DirectivesModule, + CommonModule, + RouterModule, + ReactiveFormsModule, + FormModule, + TranslateModule, + MaterialModule, + StoreModule.forFeature('serviceProfiles', fromServiceProfiles.serviceProfileReducer), + ] +}) +export class ServiceProfilesModule { } diff --git a/src/app/profiles/service-profiles/store/service-profile.actions.ts b/src/app/profiles/service-profiles/store/service-profile.actions.ts new file mode 100644 index 00000000..c118f6ed --- /dev/null +++ b/src/app/profiles/service-profiles/store/service-profile.actions.ts @@ -0,0 +1,50 @@ +import { Action } from '@ngrx/store'; +import { ServiceProfile } from '../service-profile.model'; + + +export const SET_SERVICEPROFILES = '[Service Profile] Set Service Profiles'; +export const FETCH_SERVICEPROFILES = '[Service Profile] Fetch Service Profiles'; +export const ADD_SERVICEPROFILE = '[Service Profile] Add Service Profile'; +export const UPDATE_SERVICEPROFILE = '[Service Profile] Update Service Profile'; +export const DELETE_SERVICEPROFILE = '[Service Profile] Delete Service Profile'; +export const STORE_SERVICEPROFILES = '[Service Profile] Store Service Profiles'; + +export class SetServiceProfiles implements Action { + readonly type = SET_SERVICEPROFILES; + + constructor(public payload: ServiceProfile[]) { } +} + +export class FetchServiceProfiles implements Action { + readonly type = FETCH_SERVICEPROFILES; +} + +export class AddServiceProfile implements Action { + readonly type = ADD_SERVICEPROFILE; + + constructor(public payload: ServiceProfile) { } +} + +export class UpdateServiceProfile implements Action { + readonly type = UPDATE_SERVICEPROFILE; + + constructor(public payload: { index: number; updateServiceProfile: ServiceProfile }) { } +} + +export class DeleteServiceProfile implements Action { + readonly type = DELETE_SERVICEPROFILE; + + constructor(public payload: number) { } +} + +export class StoreServiceProfiles implements Action { + readonly type = STORE_SERVICEPROFILES; +} + +export type ServiceProfileActions = + | SetServiceProfiles + | FetchServiceProfiles + | AddServiceProfile + | UpdateServiceProfile + | DeleteServiceProfile + | StoreServiceProfiles; diff --git a/src/app/profiles/service-profiles/store/service-profile.effects.ts b/src/app/profiles/service-profiles/store/service-profile.effects.ts new file mode 100644 index 00000000..e9893987 --- /dev/null +++ b/src/app/profiles/service-profiles/store/service-profile.effects.ts @@ -0,0 +1,69 @@ +import { Injectable } from '@angular/core'; +import { Actions, Effect, ofType } from '@ngrx/effects'; +import { Store } from '@ngrx/store'; +import { HttpClient } from '@angular/common/http'; +import { switchMap, map, withLatestFrom } from 'rxjs/operators'; + +import * as ServiceProfileActions from './service-profile.actions'; +import { ServiceProfile, ServiceProfileData } from '../service-profile.model'; +import * as fromApp from '../../../store/app.reducer'; + +import { environment } from 'src/environments/environment'; +import { RestService } from 'src/app/shared/services/rest.service'; +import { Observable } from 'rxjs'; +import { of } from 'rxjs'; +import { catchError } from 'rxjs/operators'; + + + +@Injectable() +export class ServiceProfileEffects { + + @Effect() + fetchServiceProfiles = this.actions$.pipe( + ofType(ServiceProfileActions.FETCH_SERVICEPROFILES), + switchMap((): Observable => { + const body = { + limit: 10, + offset: 0, + }; + const result = this.restService.get( + 'chirpstack/service-profiles', body); + console.log(result); + return result; + }), + map(serviceProfiles => { + return serviceProfiles.result.map(serviceProfile => { + return { + ...serviceProfile, + }; + }); + }), + map(serviceProfiles => { + return new ServiceProfileActions.SetServiceProfiles(serviceProfiles); + }), + catchError(() => of({ type: ' Loaded Error' })) + ); + + @Effect({ dispatch: false }) + storeServiceProfiles = this.actions$.pipe( + ofType(ServiceProfileActions.STORE_SERVICEPROFILES), + withLatestFrom(this.store.select('serviceProfiles')), + switchMap(([actionData, serviceProfileState]): Observable => { + const result = this.restService.post( + 'chirpstack/service-profiles', + serviceProfileState.serviceProfiles, + { observe: 'response' } + ); + console.log(result) + return result + }) + ); + + constructor( + private restService: RestService, + private actions$: Actions, + private http: HttpClient, + private store: Store + ) { } +} diff --git a/src/app/profiles/service-profiles/store/service-profile.reducer.ts b/src/app/profiles/service-profiles/store/service-profile.reducer.ts new file mode 100644 index 00000000..27f4384b --- /dev/null +++ b/src/app/profiles/service-profiles/store/service-profile.reducer.ts @@ -0,0 +1,74 @@ +import { ServiceProfile } from '../service-profile.model'; +import * as ServiceProfileActions from './service-profile.actions'; + +export interface State { + serviceProfiles: ServiceProfile[]; +} + +const initialState: State = { + serviceProfiles: [{ + id: 'ID', + name: 'Vandmåler', + networkServerID: 'networkserverID', + addGWMetaData: true, + channelMask: 'channelmask', + devStatusReqFreq: 789, + dlBucketSize: 123, + dlRate: 456, + dlRatePolicy: 'dlRatePolicy', + drMax: 789, + drMin: 132, + hrAllowed: true, + minGWDiversity: 123, + nwkGeoLoc: true, + organizationID: 'organizationID', + prAllowed: true, + raAllowed: true, + reportDevStatusBattery: true, + reportDevStatusMargin: true, + targetPER: 123, + ulBucketSize: 456, + ulRate: 789, + ulRatePolicy: 'ulRatePolicy' + }], +}; + +export function serviceProfileReducer( + state = initialState, + action: ServiceProfileActions.ServiceProfileActions +) { + switch (action.type) { + case ServiceProfileActions.SET_SERVICEPROFILES: + return { + ...state, + serviceProfiles: [...action.payload], + }; + case ServiceProfileActions.ADD_SERVICEPROFILE: + return { + ...state, + serviceProfiles: [...state.serviceProfiles, action.payload] + }; + case ServiceProfileActions.UPDATE_SERVICEPROFILE: + const updatedRecipe = { + ...state.serviceProfiles[action.payload.index], + ...action.payload.updateServiceProfile + }; + + const updatedServiceProfiles = [...state.serviceProfiles]; + updatedServiceProfiles[action.payload.index] = updatedRecipe; + + return { + ...state, + serviceProfiles: updatedServiceProfiles + }; + case ServiceProfileActions.DELETE_SERVICEPROFILE: + return { + ...state, + serviceProfiles: state.serviceProfiles.filter((serviceProfile, index) => { + return index !== action.payload; + }) + }; + default: + return state; + } +} diff --git a/src/app/shared/Modules/material.module.ts b/src/app/shared/Modules/material.module.ts new file mode 100644 index 00000000..00e1b2a9 --- /dev/null +++ b/src/app/shared/Modules/material.module.ts @@ -0,0 +1,95 @@ +import { A11yModule } from '@angular/cdk/a11y'; +import { DragDropModule } from '@angular/cdk/drag-drop'; +import { PortalModule } from '@angular/cdk/portal'; +import { ScrollingModule } from '@angular/cdk/scrolling'; +import { CdkStepperModule } from '@angular/cdk/stepper'; +import { CdkTableModule } from '@angular/cdk/table'; +import { CdkTreeModule } from '@angular/cdk/tree'; +import { NgModule } from '@angular/core'; +import { MatAutocompleteModule } from '@angular/material/autocomplete'; +import { MatBadgeModule } from '@angular/material/badge'; +import { MatBottomSheetModule } from '@angular/material/bottom-sheet'; +import { MatButtonModule } from '@angular/material/button'; +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 { MatDatepickerModule } from '@angular/material/datepicker'; +import { MatDialogModule } from '@angular/material/dialog'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatExpansionModule } from '@angular/material/expansion'; +import { MatGridListModule } from '@angular/material/grid-list'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatListModule } from '@angular/material/list'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatRadioModule } from '@angular/material/radio'; +import { MatSelectModule } from '@angular/material/select'; +import { MatSidenavModule } from '@angular/material/sidenav'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { MatSliderModule } from '@angular/material/slider'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { MatSortModule } from '@angular/material/sort'; +import { MatStepperModule } from '@angular/material/stepper'; +import { MatTableModule } from '@angular/material/table'; +import { MatTabsModule } from '@angular/material/tabs'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatTreeModule } from '@angular/material/tree'; + +@NgModule({ + exports: [ + A11yModule, + CdkStepperModule, + CdkTableModule, + CdkTreeModule, + DragDropModule, + MatAutocompleteModule, + MatBadgeModule, + MatBottomSheetModule, + MatButtonModule, + MatButtonToggleModule, + MatCardModule, + MatCheckboxModule, + MatChipsModule, + MatStepperModule, + MatDatepickerModule, + MatDialogModule, + MatDividerModule, + MatExpansionModule, + MatGridListModule, + MatIconModule, + MatInputModule, + MatListModule, + MatMenuModule, + MatNativeDateModule, + MatPaginatorModule, + MatProgressBarModule, + MatProgressSpinnerModule, + MatRadioModule, + MatRippleModule, + MatSelectModule, + MatSidenavModule, + MatSliderModule, + MatSlideToggleModule, + MatSnackBarModule, + MatSortModule, + MatTableModule, + MatTabsModule, + MatToolbarModule, + MatTooltipModule, + MatTreeModule, + PortalModule, + ScrollingModule, + ] +}) +export class MaterialModule { } + + +/** Copyright 2019 Google Inc. All Rights Reserved. + Use of this source code is governed by an MIT-style license that + can be found in the LICENSE file at http://angular.io/license */ diff --git a/src/app/shared/alert/alert.component.ts b/src/app/shared/alert/alert.component.ts index 1a4a2072..d6b0dca1 100644 --- a/src/app/shared/alert/alert.component.ts +++ b/src/app/shared/alert/alert.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { AlertService } from '../_services/alert.service'; +import { AlertService } from '../services/alert.service'; @Component({ selector: 'app-alert', @@ -8,7 +8,7 @@ import { AlertService } from '../_services/alert.service'; }) export class AlertComponent implements OnInit { - constructor(public alertService: AlertService) {} + constructor(public alertService: AlertService) { } ngOnInit() { } diff --git a/src/app/shared/directives/directives.module.ts b/src/app/shared/directives/directives.module.ts new file mode 100644 index 00000000..e612d487 --- /dev/null +++ b/src/app/shared/directives/directives.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { DropdownDirective } from './dropdown.directive'; +import { PlaceholderDirective } from './placeholder.directive'; + + + +@NgModule({ + declarations: [ + DropdownDirective, + PlaceholderDirective], + imports: [ + CommonModule + ], + exports: [ + DropdownDirective, + PlaceholderDirective + ] +}) +export class DirectivesModule { } diff --git a/src/app/shared/directives/dropdown.directive.ts b/src/app/shared/directives/dropdown.directive.ts new file mode 100644 index 00000000..90529ef1 --- /dev/null +++ b/src/app/shared/directives/dropdown.directive.ts @@ -0,0 +1,12 @@ +import { Directive, HostListener, HostBinding } from '@angular/core'; + +@Directive({ + selector: '[appDropdown]' +}) +export class DropdownDirective { + @HostBinding('class.open') isOpen = false; + + @HostListener('click') toggleOpen() { + this.isOpen = !this.isOpen; + } +} diff --git a/src/app/shared/directives/placeholder.directive.ts b/src/app/shared/directives/placeholder.directive.ts new file mode 100644 index 00000000..1cde7668 --- /dev/null +++ b/src/app/shared/directives/placeholder.directive.ts @@ -0,0 +1,8 @@ +import { Directive, ViewContainerRef } from '@angular/core'; + +@Directive({ + selector: '[appPlaceholder]' +}) +export class PlaceholderDirective { + constructor(public viewContainerRef: ViewContainerRef) { } +} diff --git a/src/app/shared/form/form-body-application/form-body-application.component.ts b/src/app/shared/form/form-body-application/form-body-application.component.ts index 9d961d44..0d954c04 100644 --- a/src/app/shared/form/form-body-application/form-body-application.component.ts +++ b/src/app/shared/form/form-body-application/form-body-application.component.ts @@ -1,140 +1,140 @@ -import { Component, OnInit, Input, OnDestroy, ErrorHandler } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { Subscription } from 'rxjs'; - -import { TranslateService } from '@ngx-translate/core'; - -import { RestService } from '../../_services/rest.service'; - -import { Application } from 'src/app/models/application'; -import { ApplicationService } from '../../_services/application.service'; -import { HttpErrorResponse, HttpDownloadProgressEvent } from '@angular/common/http'; - -export class User { - public name: string; - public email: string; - public password: string; - public hobbies: string; - } - -@Component({ - selector: 'app-form-body-application', - templateUrl: './form-body-application.component.html', - styleUrls: ['./form-body-application.component.scss'] -}) -export class FormBodyApplicationComponent implements OnInit, OnDestroy { - @Input() submitButton: string; - public payLoad = ''; - public applicationsSubscription: Subscription; - public errorMessage: string; - public errorMessages: any; - public errorFields: string[]; - public formFailedSubmit: boolean = false; - private id: number; - - application = new Application(); - model = new User(); - - constructor( - private restService: RestService, - private applicationService: ApplicationService, - private route: ActivatedRoute, - public translate: TranslateService, - private router: Router - ) {} - - ngOnInit(): void { - this.translate.use('da'); - this.id = +this.route.snapshot.paramMap.get('id'); - if (this.id) { - this.getApplication(this.id); - } - } - - getApplication(id: number): void { - this.applicationsSubscription = this.restService - .get('application', {}, id) - .subscribe((application: Application) => { - this.application = application; - }); - } - - onSubmit(): void { - if (this.id) { - this.updateApplication(this.id); - } else { - this.postApplication(); - } - } - - updateApplication(id: number): void { - this.applicationService - .updateApplication(this.application, id) - .subscribe( - (response) => { - console.log(response); - this.router.navigateByUrl('/mine-applikationer'); - }, - (error: HttpErrorResponse) => { - this.handleError(error) - } - ); - } - - postApplication(): void { - this.applicationService - .createApplication(this.application) - .subscribe( - (response) => { - console.log(response); - this.router.navigateByUrl('/mine-applikationer'); - }, - (error: HttpErrorResponse) => { - this.handleError(error) - } - ); - } - - private handleError(error: HttpErrorResponse) { - this.errorFields = []; - this.errorMessages = []; - - // Temp fix till we standardise backend error handling - if(error.error?.message[0]?.property) { - this.externalError(error) - } else { - this.backendError(error) - } - - this.formFailedSubmit = true; - } - - externalError(error: HttpErrorResponse) { - error.error.message.forEach((err) => { - this.errorFields.push(err.property); - this.errorMessages = this.errorMessages.concat( - Object.values(err.constraints) - ); - }); - this.formFailedSubmit = true; - } - - backendError(error: HttpErrorResponse) { - this.translate.get([error.error.message]) - .subscribe(translations => { - this.errorMessages.push(translations[error.error.message]); - }); - this.errorFields.push('name') - } - - routeBack(): void { - this.router.navigateByUrl('/mine-applikationer'); - } - - ngOnDestroy() { - // prevent memory leak by unsubscribing - if (this.applicationsSubscription) { - this.applicationsSubscription.unsubscribe(); - } - } -} +import { Component, OnInit, Input, OnDestroy, ErrorHandler } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Subscription } from 'rxjs'; + +import { TranslateService } from '@ngx-translate/core'; + +import { RestService } from '../../services/rest.service'; + +import { Application } from 'src/app/models/application'; +import { ApplicationService } from '../../services/application.service'; +import { HttpErrorResponse, HttpDownloadProgressEvent } from '@angular/common/http'; + +export class User { + public name: string; + public email: string; + public password: string; + public hobbies: string; +} + +@Component({ + selector: 'app-form-body-application', + templateUrl: './form-body-application.component.html', + styleUrls: ['./form-body-application.component.scss'] +}) +export class FormBodyApplicationComponent implements OnInit, OnDestroy { + @Input() submitButton: string; + public payLoad = ''; + public applicationsSubscription: Subscription; + public errorMessage: string; + public errorMessages: any; + public errorFields: string[]; + public formFailedSubmit: boolean = false; + private id: number; + + application = new Application(); + model = new User(); + + constructor( + private restService: RestService, + private applicationService: ApplicationService, + private route: ActivatedRoute, + public translate: TranslateService, + private router: Router + ) { } + + ngOnInit(): void { + this.translate.use('da'); + this.id = +this.route.snapshot.paramMap.get('id'); + if (this.id) { + this.getApplication(this.id); + } + } + + getApplication(id: number): void { + this.applicationsSubscription = this.restService + .get('application', {}, id) + .subscribe((application: Application) => { + this.application = application; + }); + } + + onSubmit(): void { + if (this.id) { + this.updateApplication(this.id); + } else { + this.postApplication(); + } + } + + updateApplication(id: number): void { + this.applicationService + .updateApplication(this.application, id) + .subscribe( + (response) => { + console.log(response); + this.router.navigateByUrl('/my-applications'); + }, + (error: HttpErrorResponse) => { + this.handleError(error) + } + ); + } + + postApplication(): void { + this.applicationService + .createApplication(this.application) + .subscribe( + (response) => { + console.log(response); + this.router.navigateByUrl('/my-applications'); + }, + (error: HttpErrorResponse) => { + this.handleError(error) + } + ); + } + + private handleError(error: HttpErrorResponse) { + this.errorFields = []; + this.errorMessages = []; + + // Temp fix till we standardise backend error handling + if(error.error?.message[0]?.property) { + this.externalError(error) + } else { + this.backendError(error) + } + + this.formFailedSubmit = true; + } + + externalError(error: HttpErrorResponse) { + error.error.message.forEach((err) => { + this.errorFields.push(err.property); + this.errorMessages = this.errorMessages.concat( + Object.values(err.constraints) + ); + }); + this.formFailedSubmit = true; + } + + backendError(error: HttpErrorResponse) { + this.translate.get([error.error.message]) + .subscribe(translations => { + this.errorMessages.push(translations[error.error.message]); + }); + this.errorFields.push('name') + } + + routeBack(): void { + this.router.navigateByUrl('/my-applications'); + } + + ngOnDestroy() { + // prevent memory leak by unsubscribing + if (this.applicationsSubscription) { + this.applicationsSubscription.unsubscribe(); + } + } +} diff --git a/src/app/shared/form/form-body-datatarget/form-body-datatarget.component.ts b/src/app/shared/form/form-body-datatarget/form-body-datatarget.component.ts index e16e1c7b..7949be67 100644 --- a/src/app/shared/form/form-body-datatarget/form-body-datatarget.component.ts +++ b/src/app/shared/form/form-body-datatarget/form-body-datatarget.component.ts @@ -4,7 +4,7 @@ import { Subscription } from 'rxjs'; import { FormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; -import { DatatargetService } from '../../_services/datatarget.service'; +import { DatatargetService } from '../../services/datatarget.service'; import { Location } from '@angular/common'; import { DatatargetResponse } from 'src/app/models/datatarget-response'; import { HttpErrorResponse } from '@angular/common/http'; @@ -28,10 +28,10 @@ export class FormBodyDatatargetComponent implements OnInit { private applicationId: number; constructor( - private route: ActivatedRoute, - public translate: TranslateService, - private datatargetService: DatatargetService, - private location: Location + private route: ActivatedRoute, + public translate: TranslateService, + private datatargetService: DatatargetService, + private location: Location ) { } ngOnInit(): void { @@ -45,9 +45,9 @@ export class FormBodyDatatargetComponent implements OnInit { onSubmit(): void { if (this.id) { - this.updateDatatarget(); + this.updateDatatarget(); } else { - this.createDatatarget(); + this.createDatatarget(); } } @@ -56,8 +56,8 @@ export class FormBodyDatatargetComponent implements OnInit { this.datatargetService.update(this.datatarget) .subscribe( (datatargetResponse: DatatargetResponse) => { - this.datatarget = this.mapToDatatarget(datatargetResponse) - this.routeBack() + this.datatarget = this.mapToDatatarget(datatargetResponse) + this.routeBack() }, (error: HttpErrorResponse) => { this.handleError(error) @@ -73,21 +73,21 @@ export class FormBodyDatatargetComponent implements OnInit { .subscribe((datatargetData: DatatargetData) => { this.routeBack() }, - (error: HttpErrorResponse) => { - this.handleError(error) - this.formFailedSubmit = true; - }) - + (error: HttpErrorResponse) => { + this.handleError(error) + this.formFailedSubmit = true; + }) + } handleError(error: HttpErrorResponse) { this.errorFields = []; this.errorMessages = []; error.error.message.forEach((err) => { - this.errorFields.push(err.property); - this.errorMessages = this.errorMessages.concat( - Object.values(err.constraints) - ); + this.errorFields.push(err.property); + this.errorMessages = this.errorMessages.concat( + Object.values(err.constraints) + ); }); } @@ -99,13 +99,13 @@ export class FormBodyDatatargetComponent implements OnInit { console.log(event.target.value); console.log(event.target.maxLength); if (event.target.value.length > event.target.maxLength) - event.target.value = event.target.value.slice( - 0, - event.target.maxLength - ); -} + event.target.value = event.target.value.slice( + 0, + event.target.maxLength + ); + } - getDatatarget(id: number){ + getDatatarget(id: number) { this.datatargetSubscription = this.datatargetService .get(id) .subscribe((datatargetResponse: DatatargetResponse) => { @@ -115,13 +115,14 @@ export class FormBodyDatatargetComponent implements OnInit { private mapToDatatarget(data: DatatargetResponse): Datatarget { const dt: Datatarget = { - id: data.id, + id: data.id, name: data.name, timeout: data.timeout, type: data.type, url: data.url, authorizationHeader: null, - applicationId: data.application.id} + applicationId: data.application.id + } return dt } diff --git a/src/app/shared/form/form-body-iot-devices/form-body-iot-devices.component.ts b/src/app/shared/form/form-body-iot-devices/form-body-iot-devices.component.ts index 94a0f84f..40984b05 100644 --- a/src/app/shared/form/form-body-iot-devices/form-body-iot-devices.component.ts +++ b/src/app/shared/form/form-body-iot-devices/form-body-iot-devices.component.ts @@ -1,152 +1,152 @@ -import { Component, OnInit, Input, OnDestroy } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { Router, ActivatedRoute } from '@angular/router'; - -import { TranslateService } from '@ngx-translate/core'; - -import { Application } from 'src/app/models/application'; -import { IotDevice } from 'src/app/models/iot-device'; -import { Subscription } from 'rxjs'; -import { IoTDeviceService } from '../../_services/iot-device.service'; -import { HttpErrorResponse } from '@angular/common/http'; -import { ApplicationService } from '../../_services/application.service'; -import { Location } from '@angular/common'; - -@Component({ - selector: 'app-form-body-iot-devices', - templateUrl: './form-body-iot-devices.component.html', - styleUrls: ['./form-body-iot-devices.component.scss'], -}) -export class FormBodyIotDevicesComponent implements OnInit, OnDestroy { - @Input() submitButton: string; - @Input() application: Application; - public form: FormGroup; - public payLoad = ''; - public deviceSubscription: Subscription; - public errorMessages: any; - public errorFields: string[]; - public formFailedSubmit: boolean = false; - public applications: Application[]; - private id: number; - public disableChoseApplication: boolean = true; - - private applicationsSubscription: Subscription; - - iotDevice = new IotDevice(); - - constructor( - private route: ActivatedRoute, - public translate: TranslateService, - private router: Router, - private applicationService: ApplicationService, - private iotDeviceService: IoTDeviceService, - private location: Location - ) {} - - ngOnInit(): void { - this.translate.use('da'); - this.iotDevice.applicationId = +this.route.snapshot.paramMap.get('id'); - this.id = +this.route.snapshot.paramMap.get('deviceId'); - - if (this.iotDevice.applicationId && this.id) { - this.getDevice(this.id); - this.disableChoseApplication = false; - } - - this.getApplications(); - } - - getApplications(): void { - this.applicationsSubscription = this.applicationService - .getApplications(0, 0, 'ASC', 'name') - .subscribe((applications) => { - this.applications = applications.data; - }); - } - - getDevice(id: number): void { - this.deviceSubscription = this.iotDeviceService - .getIoTDevice(id) - .subscribe((device: IotDevice) => { - this.iotDevice = device; - if (this.iotDevice?.application?.id) { - this.iotDevice.applicationId = device.application?.id - } - if (device.location) { - this.iotDevice.longitude = device.location.coordinates[0]; - this.iotDevice.latitude = device.location.coordinates[1]; - } - }); - } - - onSubmit(): void { - if (this.id) { - this.updateIoTDevice(this.id); - } else { - this.postIoTDevice(); - } - } - - postIoTDevice() { - this.iotDeviceService.createIoTDevice(this.iotDevice).subscribe( - () => { - this.router.navigate([ - 'mine-applikationer/application', - this.iotDevice.applicationId, - ]); - }, - (error: HttpErrorResponse) => { - this.handleError(error) - this.formFailedSubmit = true; - } - ); - } - - updateIoTDevice(id: number) { - this.iotDevice.applicationId = Number(this.iotDevice.applicationId) - this.iotDeviceService.updateIoTDevice(this.iotDevice, id).subscribe( - () => { - this.routeBack() - }, - (error: HttpErrorResponse) => { - this.handleError(error) - this.formFailedSubmit = true; - } - ); - } - - routeBack(): void { - this.location.back() - } - - handleError(error: HttpErrorResponse) { - this.errorFields = []; - this.errorMessages = []; - error.error.message.forEach((err) => { - this.errorFields.push(err.property); - this.errorMessages = this.errorMessages.concat( - Object.values(err.constraints) - ); - }); - } - - onCoordinateKey(event: any) { - console.log(event.target.value); - console.log(event.target.maxLength); - if (event.target.value.length > event.target.maxLength) - event.target.value = event.target.value.slice( - 0, - event.target.maxLength - ); - } - - ngOnDestroy() { - // prevent memory leak by unsubscribing - if (this.applicationsSubscription) { - this.applicationsSubscription.unsubscribe(); - } - if (this.deviceSubscription) { - this.deviceSubscription.unsubscribe(); - } - } -} +import { Component, OnInit, Input, OnDestroy } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { Router, ActivatedRoute } from '@angular/router'; + +import { TranslateService } from '@ngx-translate/core'; + +import { Application } from 'src/app/models/application'; +import { IotDevice } from 'src/app/models/iot-device'; +import { Subscription } from 'rxjs'; +import { IoTDeviceService } from '../../services/iot-device.service'; +import { HttpErrorResponse } from '@angular/common/http'; +import { Location } from '@angular/common'; +import { ApplicationService } from '../../services/application.service'; + +@Component({ + selector: 'app-form-body-iot-devices', + templateUrl: './form-body-iot-devices.component.html', + styleUrls: ['./form-body-iot-devices.component.scss'], +}) +export class FormBodyIotDevicesComponent implements OnInit, OnDestroy { + @Input() submitButton: string; + @Input() application: Application; + public form: FormGroup; + public payLoad = ''; + public deviceSubscription: Subscription; + public errorMessages: any; + public errorFields: string[]; + public formFailedSubmit: boolean = false; + public applications: Application[]; + private id: number; + public disableChoseApplication: boolean = true; + + private applicationsSubscription: Subscription; + + iotDevice = new IotDevice(); + + constructor( + private route: ActivatedRoute, + public translate: TranslateService, + private router: Router, + private applicationService: ApplicationService, + private iotDeviceService: IoTDeviceService, + private location: Location + ) { } + + ngOnInit(): void { + this.translate.use('da'); + this.iotDevice.applicationId = +this.route.snapshot.paramMap.get('id'); + this.id = +this.route.snapshot.paramMap.get('deviceId'); + + if (this.iotDevice.applicationId && this.id) { + this.getDevice(this.id); + this.disableChoseApplication = false; + } + + this.getApplications(); + } + + getApplications(): void { + this.applicationsSubscription = this.applicationService + .getApplications(0, 0, 'ASC', 'name') + .subscribe((applications) => { + this.applications = applications.data; + }); + } + + getDevice(id: number): void { + this.deviceSubscription = this.iotDeviceService + .getIoTDevice(id) + .subscribe((device: IotDevice) => { + this.iotDevice = device; + if (this.iotDevice?.application?.id) { + this.iotDevice.applicationId = device.application?.id + } + if (device.location) { + this.iotDevice.longitude = device.location.coordinates[0]; + this.iotDevice.latitude = device.location.coordinates[1]; + } + }); + } + + onSubmit(): void { + if (this.id) { + this.updateIoTDevice(this.id); + } else { + this.postIoTDevice(); + } + } + + postIoTDevice() { + this.iotDeviceService.createIoTDevice(this.iotDevice).subscribe( + () => { + this.router.navigate([ + 'my-applications/application', + this.iotDevice.applicationId, + ]); + }, + (error: HttpErrorResponse) => { + this.handleError(error) + this.formFailedSubmit = true; + } + ); + } + + updateIoTDevice(id: number) { + this.iotDevice.applicationId = Number(this.iotDevice.applicationId) + this.iotDeviceService.updateIoTDevice(this.iotDevice, id).subscribe( + () => { + this.routeBack() + }, + (error: HttpErrorResponse) => { + this.handleError(error) + this.formFailedSubmit = true; + } + ); + } + + routeBack(): void { + this.location.back() + } + + handleError(error: HttpErrorResponse) { + this.errorFields = []; + this.errorMessages = []; + error.error.message.forEach((err) => { + this.errorFields.push(err.property); + this.errorMessages = this.errorMessages.concat( + Object.values(err.constraints) + ); + }); + } + + onCoordinateKey(event: any) { + console.log(event.target.value); + console.log(event.target.maxLength); + if (event.target.value.length > event.target.maxLength) + event.target.value = event.target.value.slice( + 0, + event.target.maxLength + ); + } + + ngOnDestroy() { + // prevent memory leak by unsubscribing + if (this.applicationsSubscription) { + this.applicationsSubscription.unsubscribe(); + } + if (this.deviceSubscription) { + this.deviceSubscription.unsubscribe(); + } + } +} diff --git a/src/app/shared/form/form-body-lora-gateway/form-body-lora-gateway.component.ts b/src/app/shared/form/form-body-lora-gateway/form-body-lora-gateway.component.ts index df73bae8..d036ee2a 100644 --- a/src/app/shared/form/form-body-lora-gateway/form-body-lora-gateway.component.ts +++ b/src/app/shared/form/form-body-lora-gateway/form-body-lora-gateway.component.ts @@ -6,7 +6,7 @@ import { TranslateService } from '@ngx-translate/core'; import { Gateway, GatewayResponse } from '../../../../app/models/gateway' import { Subscription } from 'rxjs'; import { HttpErrorResponse } from '@angular/common/http'; -import { ChirpstackGatewayService } from '../../_services/chirpstack-gateway.service'; +import { ChirpstackGatewayService } from '../../services/chirpstack-gateway.service'; @Component({ selector: 'app-form-body-lora-gateway', @@ -38,17 +38,17 @@ export class FormBodyLoraGatewayComponent implements OnInit { this.translate.use('da'); this.id = this.route.snapshot.paramMap.get('id'); if (this.id) { - this.getGateway(this.id); + this.getGateway(this.id); } } getGateway(id: string): void { this.gatewaySubscription = this.loraGatewayService - .get(id) - .subscribe((result: GatewayResponse) => { - result.gateway.tagsString = JSON.stringify(result.gateway.tags) - this.gateway = result.gateway - }); + .get(id) + .subscribe((result: GatewayResponse) => { + result.gateway.tagsString = JSON.stringify(result.gateway.tags) + this.gateway = result.gateway + }); } createGateway(): void { @@ -69,7 +69,7 @@ export class FormBodyLoraGatewayComponent implements OnInit { .put(this.gateway, this.id) .subscribe( (response) => { - this.routeBack() + this.routeBack() }, (error) => { this.showError(error) @@ -78,9 +78,9 @@ export class FormBodyLoraGatewayComponent implements OnInit { onSubmit(): void { if (this.id) { - this.updateGateway(); + this.updateGateway(); } else { - this.createGateway(); + this.createGateway(); } } @@ -89,20 +89,20 @@ export class FormBodyLoraGatewayComponent implements OnInit { } ngOnDestroy() { - if (this.gatewaySubscription) { - this.gatewaySubscription.unsubscribe(); - } + if (this.gatewaySubscription) { + this.gatewaySubscription.unsubscribe(); + } } onCoordinateKey(event: any) { console.log(event.target.value); console.log(event.target.maxLength); if (event.target.value.length > event.target.maxLength) - event.target.value = event.target.value.slice( - 0, - event.target.maxLength - ); -} + event.target.value = event.target.value.slice( + 0, + event.target.maxLength + ); + } private showError(error: HttpErrorResponse) { this.errorFields = []; @@ -111,9 +111,9 @@ export class FormBodyLoraGatewayComponent implements OnInit { error.error.message[0].children.forEach((err) => { this.errorFields.push(err.property); this.errorMessages = this.errorMessages.concat( - Object.values(err.constraints) + Object.values(err.constraints) ); - }); + }); } else { this.errorMessage = error.message } diff --git a/src/app/shared/_services/alert.service.spec.ts b/src/app/shared/services/alert.service.spec.ts similarity index 100% rename from src/app/shared/_services/alert.service.spec.ts rename to src/app/shared/services/alert.service.spec.ts diff --git a/src/app/shared/_services/alert.service.ts b/src/app/shared/services/alert.service.ts similarity index 100% rename from src/app/shared/_services/alert.service.ts rename to src/app/shared/services/alert.service.ts diff --git a/src/app/shared/_services/application.service.spec.ts b/src/app/shared/services/application.service.spec.ts similarity index 100% rename from src/app/shared/_services/application.service.spec.ts rename to src/app/shared/services/application.service.spec.ts diff --git a/src/app/shared/_services/application.service.ts b/src/app/shared/services/application.service.ts similarity index 100% rename from src/app/shared/_services/application.service.ts rename to src/app/shared/services/application.service.ts diff --git a/src/app/shared/_services/chirpstack-gateway.service.ts b/src/app/shared/services/chirpstack-gateway.service.ts similarity index 100% rename from src/app/shared/_services/chirpstack-gateway.service.ts rename to src/app/shared/services/chirpstack-gateway.service.ts diff --git a/src/app/shared/_services/chripstack-gateway.service.spec.ts b/src/app/shared/services/chripstack-gateway.service.spec.ts similarity index 100% rename from src/app/shared/_services/chripstack-gateway.service.spec.ts rename to src/app/shared/services/chripstack-gateway.service.spec.ts diff --git a/src/app/shared/_services/datatarget.service.spec.ts b/src/app/shared/services/datatarget.service.spec.ts similarity index 100% rename from src/app/shared/_services/datatarget.service.spec.ts rename to src/app/shared/services/datatarget.service.spec.ts diff --git a/src/app/shared/_services/datatarget.service.ts b/src/app/shared/services/datatarget.service.ts similarity index 100% rename from src/app/shared/_services/datatarget.service.ts rename to src/app/shared/services/datatarget.service.ts diff --git a/src/app/shared/_services/iot-device.service.spec.ts b/src/app/shared/services/iot-device.service.spec.ts similarity index 100% rename from src/app/shared/_services/iot-device.service.spec.ts rename to src/app/shared/services/iot-device.service.spec.ts diff --git a/src/app/shared/_services/iot-device.service.ts b/src/app/shared/services/iot-device.service.ts similarity index 90% rename from src/app/shared/_services/iot-device.service.ts rename to src/app/shared/services/iot-device.service.ts index 04b1472e..62ae62d1 100644 --- a/src/app/shared/_services/iot-device.service.ts +++ b/src/app/shared/services/iot-device.service.ts @@ -7,14 +7,14 @@ import { IotDevice, IotDeviceData } from '../../models/iot-device'; providedIn: 'root', }) export class IoTDeviceService { - constructor(private restService: RestService) {} + constructor(private restService: RestService) { } createIoTDevice(body: IotDevice): Observable { return this.restService.post('iot-device', body); } updateIoTDevice(body: IotDevice, id: number): Observable { - return this.restService.replace('iot-device', body, id, {observe: 'response'}); + return this.restService.replace('iot-device', body, id, { observe: 'response' }); } getIoTDevice(id: number): Observable { diff --git a/src/app/shared/_services/rest.service.spec.ts b/src/app/shared/services/rest.service.spec.ts similarity index 100% rename from src/app/shared/_services/rest.service.spec.ts rename to src/app/shared/services/rest.service.spec.ts diff --git a/src/app/shared/_services/rest.service.ts b/src/app/shared/services/rest.service.ts similarity index 98% rename from src/app/shared/_services/rest.service.ts rename to src/app/shared/services/rest.service.ts index 4b44af66..6c05449e 100644 --- a/src/app/shared/_services/rest.service.ts +++ b/src/app/shared/services/rest.service.ts @@ -18,7 +18,7 @@ interface IHttpOptions { withCredentials?: boolean; } -@Injectable() +@Injectable({ providedIn: 'root' }) export class RestService { constructor( private http: HttpClient, @@ -133,7 +133,7 @@ export class RestService { catchError(this.handleError('delete', [])) ); } - + public replace( url: string, object: any, @@ -228,7 +228,7 @@ export class RestService { }; } - /** Use the AlertService to notify of the request*/ + // Use the AlertService to notify of the request private log(alert: Alert) { this.alertService.add(alert); } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 807a2a58..b52d25b6 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -7,6 +7,8 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { AlertComponent } from './alert/alert.component'; import { SearchBarComponent } from './search-bar/search-bar.component'; import { TranslateModule } from '@ngx-translate/core'; +import { LoggingService } from '../logging.service'; +import { DirectivesModule } from './directives/directives.module'; @NgModule({ declarations: [ @@ -14,15 +16,13 @@ import { TranslateModule } from '@ngx-translate/core'; SearchBarComponent, ], imports: [ + DirectivesModule, CommonModule, - HttpClientModule, - BrowserAnimationsModule, ], exports: [ AlertComponent, - BrowserAnimationsModule, - HttpClientModule, - TranslateModule - ] + TranslateModule, + ], + providers: [LoggingService] }) export class SharedModule { } diff --git a/src/app/shared/top-bar/top-bar.component.html b/src/app/shared/top-bar/top-bar.component.html index 23e761ef..da384565 100644 --- a/src/app/shared/top-bar/top-bar.component.html +++ b/src/app/shared/top-bar/top-bar.component.html @@ -5,7 +5,7 @@

{{title}}

-

{{title}}

+

{{title}}

@@ -19,8 +19,8 @@

{{title}}

{{ 'GEN.PER-PAGE' | translate }} --> -
@@ -29,4 +29,4 @@

{{title}}

type="button" [attr.aria-label]="ctaLabel">{{ctaLabel}} - + \ No newline at end of file diff --git a/src/app/shared/top-bar/top-bar.component.ts b/src/app/shared/top-bar/top-bar.component.ts index fd10ba92..a72127ca 100644 --- a/src/app/shared/top-bar/top-bar.component.ts +++ b/src/app/shared/top-bar/top-bar.component.ts @@ -1,43 +1,45 @@ -import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; - -import { Sort } from 'src/app/models/sort'; -import { Location } from '@angular/common'; - -@Component({ - selector: 'app-top-bar', - templateUrl: './top-bar.component.html', - styleUrls: ['./top-bar.component.scss'], -}) -export class TopBarComponent implements OnInit { - @Input() title: string; - @Input() ctaLabel: string; - @Input() ctaRouterLink: string; - @Input() sort: Sort[]; - @Input() pageLimit: number; - @Input() selectedSortId: number; - @Input() component: boolean = false; - @Input() backButtonTitle: string; - @Output() selectedSortChange = new EventEmitter(); - @Output() updatePageLimit = new EventEmitter(); - - constructor(public translate: TranslateService, - private location: Location) { - translate.use('da'); - } - - ngOnInit(): void {} - - changeSort(id: number) { - this.selectedSortChange.emit(id); - } - - routeBack(): void { - this.location.back() - } - - // pageLimitUpdate(value) { - // console.log('page limit', value); - // this.updatePageLimit.emit(value); - // } -} +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; + +import { Sort } from 'src/app/models/sort'; +import { Location } from '@angular/common'; + +@Component({ + selector: 'app-top-bar', + templateUrl: './top-bar.component.html', + styleUrls: ['./top-bar.component.scss'], +}) +export class TopBarComponent implements OnInit { + @Input() title: string; + @Input() ctaLabel: string; + @Input() ctaRouterLink: string; + @Input() sort: Sort[]; + @Input() pageLimit: number; + @Input() selectedSortId: number; + @Input() component: false; + @Input() showSelectedSort = true; + @Input() backButtonTitle: string; + @Output() selectedSortChange = new EventEmitter(); + @Output() updatePageLimit = new EventEmitter(); + + constructor(public translate: TranslateService, + private location: Location) { + translate.use('da'); + } + + + ngOnInit(): void { } + + changeSort(id: number) { + this.selectedSortChange.emit(id); + } + + routeBack(): void { + this.location.back() + } + + // pageLimitUpdate(value) { + // console.log('page limit', value); + // this.updatePageLimit.emit(value); + // } +} diff --git a/src/app/store/app.reducer.ts b/src/app/store/app.reducer.ts new file mode 100644 index 00000000..d803cdd7 --- /dev/null +++ b/src/app/store/app.reducer.ts @@ -0,0 +1,19 @@ +import { storeFreeze } from 'ngrx-store-freeze'; +import { ActionReducerMap, MetaReducer } from '@ngrx/store'; +import { routerReducer, RouterReducerState } from '@ngrx/router-store'; + +import * as fromServiceProfiles from '../profiles/service-profiles/store/service-profile.reducer'; +import { environment } from 'src/environments/environment'; + +export interface AppState { + serviceProfiles: fromServiceProfiles.State; + router: RouterReducerState; +} + +export const appReducer: ActionReducerMap = { + serviceProfiles: fromServiceProfiles.serviceProfileReducer, + router: routerReducer, +}; + +export const metaReducers: MetaReducer[] = + !environment.production ? [storeFreeze] : []; diff --git a/src/app/views/administration-gateway/admin-lora-table/admin-lora-table.component.ts b/src/app/views/administration-gateway/admin-lora-table/admin-lora-table.component.ts index e6e91130..ef206609 100644 --- a/src/app/views/administration-gateway/admin-lora-table/admin-lora-table.component.ts +++ b/src/app/views/administration-gateway/admin-lora-table/admin-lora-table.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, OnChanges, OnDestroy, Input } from '@angular/core'; import { Sort } from 'src/app/models/sort'; import { Subscribable, Subscription, Observable } from 'rxjs'; -import { ChirpstackGatewayService } from 'src/app/shared/_services/chirpstack-gateway.service'; +import { ChirpstackGatewayService } from 'src/app/shared/services/chirpstack-gateway.service'; import { TranslateService } from '@ngx-translate/core'; import { Gateway, GatewayResponse } from 'src/app/models/gateway'; @@ -11,7 +11,7 @@ import { Gateway, GatewayResponse } from 'src/app/models/gateway'; styleUrls: ['./admin-lora-table.component.scss'] }) export class AdminLoraTableComponent implements OnInit, OnChanges, OnDestroy { - + @Input() pageLimit: number; @Input() selectedSortObject: Sort; public gateways: Observable; @@ -19,12 +19,12 @@ export class AdminLoraTableComponent implements OnInit, OnChanges, OnDestroy { public pageTotal: number; private gatewaySubscription: Subscription; - + constructor( private chirpstackGatewayService: ChirpstackGatewayService, - public translate: TranslateService) { - this.translate.use('da') - } + public translate: TranslateService) { + this.translate.use('da') + } ngOnInit(): void { } @@ -36,19 +36,19 @@ export class AdminLoraTableComponent implements OnInit, OnChanges, OnDestroy { } getLoraGateways(): void { - this.gatewaySubscription = this.chirpstackGatewayService.getMultiple( - { - limit: this.pageLimit, - offset: this.pageOffset * this.pageLimit, - sort: this.selectedSortObject.dir, - orderOn: this.selectedSortObject.col - }) - .subscribe( - (gateways) => { - this.gateways = gateways.result - if (this.pageLimit) { - console.log(gateways.result); - this.pageTotal = Math.ceil(gateways.count / this.pageLimit); + this.gatewaySubscription = this.chirpstackGatewayService.getMultiple( + { + limit: this.pageLimit, + offset: this.pageOffset * this.pageLimit, + sort: this.selectedSortObject.dir, + orderOn: this.selectedSortObject.col + }) + .subscribe( + (gateways) => { + this.gateways = gateways.result + if (this.pageLimit) { + console.log(gateways.result); + this.pageTotal = Math.ceil(gateways.count / this.pageLimit); } } ) @@ -58,26 +58,26 @@ export class AdminLoraTableComponent implements OnInit, OnChanges, OnDestroy { console.log('delete') this.chirpstackGatewayService.delete(id).subscribe((response) => { if (response.ok && response.body.success === true) { - this.getLoraGateways(); + this.getLoraGateways(); } - }); + }); } prevPage() { - if (this.pageOffset) this.pageOffset--; - this.getLoraGateways(); + if (this.pageOffset) this.pageOffset--; + this.getLoraGateways(); } nextPage() { - if (this.pageOffset < this.pageTotal) this.pageOffset++; - this.getLoraGateways(); + if (this.pageOffset < this.pageTotal) this.pageOffset++; + this.getLoraGateways(); } ngOnDestroy() { // prevent memory leak by unsubscribing if (this.gatewaySubscription) { - this.gatewaySubscription.unsubscribe(); + this.gatewaySubscription.unsubscribe(); } -} + } } diff --git a/src/app/views/administration-gateway/gateway/gateway.component.ts b/src/app/views/administration-gateway/gateway/gateway.component.ts index 817fc6ff..a8d7034a 100644 --- a/src/app/views/administration-gateway/gateway/gateway.component.ts +++ b/src/app/views/administration-gateway/gateway/gateway.component.ts @@ -2,142 +2,142 @@ import { Component, OnInit } from '@angular/core'; import { Gateway } from 'src/app/models/gateway'; import { Subscription } from 'rxjs'; import { Sort } from 'src/app/models/sort'; -import { ChirpstackGatewayService } from 'src/app/shared/_services/chirpstack-gateway.service'; +import { ChirpstackGatewayService } from 'src/app/shared/services/chirpstack-gateway.service'; import { ActivatedRoute } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { BackButton } from 'src/app/models/back-button'; import { QuickActionButton } from 'src/app/models/quick-action-button'; @Component({ - selector: 'app-gateway', - templateUrl: './gateway.component.html', - styleUrls: ['./gateway.component.scss'] + selector: 'app-gateway', + templateUrl: './gateway.component.html', + styleUrls: ['./gateway.component.scss'] }) export class GatewayComponent implements OnInit { - public gatewaySubscription: Subscription; - public gateway: Gateway; - public backButton: BackButton = {label: '', routerLink: '/mine-lora-gateways'}; - private id: string; - public pageLimit: number = 10; - public pageOffset: number = 0; - public pageTotal: number; - public selectedSortId: number = 6; - public selectedSortObject: Sort = { - id: 6, - dir: 'DESC', - col: 'createdAt', - label: 'SORT.CREATED-DESCENDING', - }; - public sort: Sort[] = [ - { - id: 1, - dir: 'ASC', - col: 'name', - label: 'SORT.NAME-ASCENDING', - }, - { - id: 2, - dir: 'DESC', - col: 'name', - label: 'SORT.NAME-DESCENDING', - }, - { - id: 3, - dir: 'ASC', - col: 'updatedAt', - label: 'SORT.UPDATED-ASCENDING', - }, - { - id: 4, - dir: 'DESC', - col: 'updatedAt', - label: 'SORT.UPDATED-DESCENDING', - }, - { - id: 5, - dir: 'ASC', - col: 'createdAt', - label: 'SORT.CREATED-ASCENDING', - }, - { + public gatewaySubscription: Subscription; + public gateway: Gateway; + public backButton: BackButton = { label: '', routerLink: '/mine-lora-gateways' }; + private id: string; + public pageLimit: number = 10; + public pageOffset: number = 0; + public pageTotal: number; + public selectedSortId: number = 6; + public selectedSortObject: Sort = { id: 6, dir: 'DESC', col: 'createdAt', label: 'SORT.CREATED-DESCENDING', - }, - { - id: 7, - dir: 'ASC', - col: 'createdAt', - label: 'SORT.APPLICATION-ASCENDING', - }, - { - id: 8, - dir: 'DESC', - col: 'createdAt', - label: 'SORT.APPLICATION-DESCENDING', - }, - { - id: 9, - dir: 'ASC', - col: 'createdAt', - label: 'SORT.BATTERY-ASCENDING', - }, - { - id: 10, - dir: 'DESC', - col: 'createdAt', - label: 'SORT.BATTERY-DESCENDING', - }, - ]; - public buttons: QuickActionButton[] = [ - { - label: 'GEN.EDIT', - type: 'edit', - }, -]; + }; + public sort: Sort[] = [ + { + id: 1, + dir: 'ASC', + col: 'name', + label: 'SORT.NAME-ASCENDING', + }, + { + id: 2, + dir: 'DESC', + col: 'name', + label: 'SORT.NAME-DESCENDING', + }, + { + id: 3, + dir: 'ASC', + col: 'updatedAt', + label: 'SORT.UPDATED-ASCENDING', + }, + { + id: 4, + dir: 'DESC', + col: 'updatedAt', + label: 'SORT.UPDATED-DESCENDING', + }, + { + id: 5, + dir: 'ASC', + col: 'createdAt', + label: 'SORT.CREATED-ASCENDING', + }, + { + id: 6, + dir: 'DESC', + col: 'createdAt', + label: 'SORT.CREATED-DESCENDING', + }, + { + id: 7, + dir: 'ASC', + col: 'createdAt', + label: 'SORT.APPLICATION-ASCENDING', + }, + { + id: 8, + dir: 'DESC', + col: 'createdAt', + label: 'SORT.APPLICATION-DESCENDING', + }, + { + id: 9, + dir: 'ASC', + col: 'createdAt', + label: 'SORT.BATTERY-ASCENDING', + }, + { + id: 10, + dir: 'DESC', + col: 'createdAt', + label: 'SORT.BATTERY-DESCENDING', + }, + ]; + public buttons: QuickActionButton[] = [ + { + label: 'GEN.EDIT', + type: 'edit', + }, + ]; - constructor( - private gatewayService: ChirpstackGatewayService, - private route: ActivatedRoute, - public translate: TranslateService - ) { } + constructor( + private gatewayService: ChirpstackGatewayService, + private route: ActivatedRoute, + public translate: TranslateService + ) { } - ngOnInit(): void { - this.id = this.route.snapshot.paramMap.get('id'); + ngOnInit(): void { + this.id = this.route.snapshot.paramMap.get('id'); if (this.id) { this.bindGateway(this.id); } - this.translate.get(['NAV.MY-LORA-GATEWAYS']) - .subscribe(translations => { - this.backButton.label = translations['NAV.MY-LORA-GATEWAYS']; - }); - } + this.translate.get(['NAV.MY-LORA-GATEWAYS']) + .subscribe(translations => { + this.backButton.label = translations['NAV.MY-LORA-GATEWAYS']; + }); + } - bindGateway(id: string): void { - this.gatewayService.get(id).subscribe((result: any) => { - result.gateway.tagsString = JSON.stringify(result.gateway.tags) - this.gateway = result.gateway; - console.log('gateway', this.gateway); - }); - } - updatePageLimit(limit: any) { - console.log(limit); - } + bindGateway(id: string): void { + this.gatewayService.get(id).subscribe((result: any) => { + result.gateway.tagsString = JSON.stringify(result.gateway.tags) + this.gateway = result.gateway; + console.log('gateway', this.gateway); + }); + } + updatePageLimit(limit: any) { + console.log(limit); + } - changeSort(sortId: number) { - for (let i = 0; i < this.sort.length; i++) { - const elem = this.sort[i]; - if (elem.id == sortId) { - this.selectedSortObject = elem; - } - } - } + changeSort(sortId: number) { + for (let i = 0; i < this.sort.length; i++) { + const elem = this.sort[i]; + if (elem.id == sortId) { + this.selectedSortObject = elem; + } + } + } - ngOnDestroy() { - if (this.gatewaySubscription) { - this.gatewaySubscription.unsubscribe(); - } - } + ngOnDestroy() { + if (this.gatewaySubscription) { + this.gatewaySubscription.unsubscribe(); + } + } } diff --git a/src/app/views/alle-iot-enheder/alle-iot-enheder.component.spec.ts b/src/app/views/alle-iot-enheder/alle-iot-enheder.component.spec.ts deleted file mode 100644 index f0ac48f0..00000000 --- a/src/app/views/alle-iot-enheder/alle-iot-enheder.component.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AlleIotEnhederComponent } from './alle-iot-enheder/alle-iot-enheder.component'; - -describe('AlleIotEnhederComponent', () => { - let component: AlleIotEnhederComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ AlleIotEnhederComponent ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(AlleIotEnhederComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/views/alle-iot-enheder/edit-iot-device/edit-iot-device.component.ts b/src/app/views/alle-iot-enheder/edit-iot-device/edit-iot-device.component.ts index 70550cbd..ffebe445 100644 --- a/src/app/views/alle-iot-enheder/edit-iot-device/edit-iot-device.component.ts +++ b/src/app/views/alle-iot-enheder/edit-iot-device/edit-iot-device.component.ts @@ -3,7 +3,7 @@ import { Application } from 'src/app/models/application'; import { BackButton } from 'src/app/models/back-button'; import { TranslateService } from '@ngx-translate/core'; import { ActivatedRoute } from '@angular/router'; -import { ApplicationService } from 'src/app/shared/_services/application.service'; +import { ApplicationService } from 'src/app/shared/services/application.service'; @Component({ selector: 'app-edit-iot-device', diff --git a/src/app/views/alle-iot-enheder/iot-device/iot-device.component.ts b/src/app/views/alle-iot-enheder/iot-device/iot-device.component.ts index 9eca4931..3d0e9b0e 100644 --- a/src/app/views/alle-iot-enheder/iot-device/iot-device.component.ts +++ b/src/app/views/alle-iot-enheder/iot-device/iot-device.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, OnDestroy } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Subscription } from 'rxjs'; -import { IoTDeviceService } from 'src/app/shared/_services/iot-device.service'; +import { IoTDeviceService } from 'src/app/shared/services/iot-device.service'; import { TranslateService } from '@ngx-translate/core'; import { Application } from 'src/app/models/application'; import { IotDevice } from '../../../models/iot-device'; @@ -15,12 +15,12 @@ import { BackButton } from 'src/app/models/back-button'; }) export class IoTDeviceComponent implements OnInit, OnDestroy { public deviceId: number; - public backButton: BackButton = {label: '', routerLink: '/mine-applikationer'}; + public backButton: BackButton = { label: '', routerLink: '/my-applications' }; public application: Application; public latitude: number; public longitude: number; public iotDeviceSubscription: Subscription; - + // TODO: Få aktivt miljø? public baseUrl = environment.baseUrl; public genericHttpDeviceUrl: string; @@ -31,7 +31,7 @@ export class IoTDeviceComponent implements OnInit, OnDestroy { private route: ActivatedRoute, private iotDeviceService: IoTDeviceService, private translate: TranslateService - ) {} + ) { } ngOnInit(): void { this.deviceId = +this.route.snapshot.paramMap.get('deviceId'); @@ -41,9 +41,9 @@ export class IoTDeviceComponent implements OnInit, OnDestroy { } this.translate.get(['NAV.MY-APPLICATIONS']) - .subscribe(translations => { - this.backButton.label = translations['NAV.MY-APPLICATIONS']; - }); + .subscribe(translations => { + this.backButton.label = translations['NAV.MY-APPLICATIONS']; + }); } bindIoTDeviceAndApplication(deviceId: number) { diff --git a/src/app/views/alle-iot-enheder/iot-devices-table-row/iot-devices-table-row.component.ts b/src/app/views/alle-iot-enheder/iot-devices-table-row/iot-devices-table-row.component.ts index 4418852c..60eb7c48 100644 --- a/src/app/views/alle-iot-enheder/iot-devices-table-row/iot-devices-table-row.component.ts +++ b/src/app/views/alle-iot-enheder/iot-devices-table-row/iot-devices-table-row.component.ts @@ -2,9 +2,9 @@ import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import { IotDevice } from 'src/app/models/iot-device'; import { TranslateService } from '@ngx-translate/core'; import { Router } from '@angular/router'; -import * as moment from 'moment'; +import * as moment from 'moment'; import 'moment/locale/da'; -import { IoTDeviceService } from '../../../shared/_services/iot-device.service'; +import { IoTDeviceService } from '../../../shared/services/iot-device.service'; @Component({ selector: 'tr[app-iot-devices-table-row]', @@ -20,24 +20,24 @@ export class IotDevicesTableRowComponent implements OnInit { public iotDeviceService: IoTDeviceService, public translate: TranslateService, private router: Router - ) { - translate.use('da'); - moment.locale('da') + ) { + translate.use('da'); + moment.locale('da') } - ngOnInit(): void {} + ngOnInit(): void { } clickDelete() { const id = this.device.id; this.iotDeviceService.deleteIoTDevice(id).subscribe((response) => { - if (response.ok && response.body.affected > 0) { - this.deleteDevice.emit(id); - } + if (response.ok && response.body.affected > 0) { + this.deleteDevice.emit(id); + } }); } navigateToEditPage() { - this.router.navigate(['edit-iot-device', this.device.id]); + this.router.navigate(['edit-iot-device', this.device.id]); } lastActive() { diff --git a/src/app/views/alle-iot-enheder/iot-devices-table/iot-devices-table.component.ts b/src/app/views/alle-iot-enheder/iot-devices-table/iot-devices-table.component.ts index 12d57aea..9e531570 100644 --- a/src/app/views/alle-iot-enheder/iot-devices-table/iot-devices-table.component.ts +++ b/src/app/views/alle-iot-enheder/iot-devices-table/iot-devices-table.component.ts @@ -3,7 +3,7 @@ import { Subscription, Observable } from 'rxjs'; import { TranslateService } from '@ngx-translate/core'; -import { RestService } from 'src/app/shared/_services/rest.service'; +import { RestService } from 'src/app/shared/services/rest.service'; import { IotDevice } from 'src/app/models/iot-device'; import { Sort } from 'src/app/models/sort'; @@ -30,7 +30,7 @@ export class IotDevicesTableComponent implements OnInit, OnChanges, OnDestroy { translate.use('da'); } - ngOnInit(): void {} + ngOnInit(): void { } ngOnChanges() { this.getDevices(); @@ -43,7 +43,7 @@ export class IotDevicesTableComponent implements OnInit, OnChanges, OnDestroy { this.iotDevices = application.iotDevices; }); } - + deleteDevice(id: number): void { this.getDevices(); } diff --git a/src/app/views/datatarget/datatarget-table/datatarget-table.component.ts b/src/app/views/datatarget/datatarget-table/datatarget-table.component.ts index 1eead117..7a4733fc 100644 --- a/src/app/views/datatarget/datatarget-table/datatarget-table.component.ts +++ b/src/app/views/datatarget/datatarget-table/datatarget-table.component.ts @@ -2,85 +2,85 @@ import { Component, OnInit, Input, OnChanges, OnDestroy } from '@angular/core'; import { Datatarget, DatatargetData } from 'src/app/models/datatarget'; import { Sort } from 'src/app/models/sort'; import { Subscription } from 'rxjs'; -import { DatatargetService } from 'src/app/shared/_services/datatarget.service'; +import { DatatargetService } from 'src/app/shared/services/datatarget.service'; import { TranslateService } from '@ngx-translate/core'; import { ActivatedRoute } from '@angular/router'; @Component({ - selector: 'app-datatarget-table', - templateUrl: './datatarget-table.component.html', - styleUrls: ['./datatarget-table.component.scss'] + selector: 'app-datatarget-table', + templateUrl: './datatarget-table.component.html', + styleUrls: ['./datatarget-table.component.scss'] }) export class DatatargetTableComponent implements OnInit, OnChanges, OnDestroy { - - @Input() pageLimit: number; - @Input() selectedSortObject: Sort; - public pageOffset: number = 0; - public pageTotal: number; - public applicationId: number; - datatargets: Datatarget[] - private datatargetSubscription: Subscription; + @Input() pageLimit: number; + @Input() selectedSortObject: Sort; + public pageOffset: number = 0; + public pageTotal: number; + public applicationId: number; - constructor( - private route: ActivatedRoute, - private datatargetService: DatatargetService, - public translate: TranslateService) { + datatargets: Datatarget[] + private datatargetSubscription: Subscription; + + constructor( + private route: ActivatedRoute, + private datatargetService: DatatargetService, + public translate: TranslateService) { translate.use('da'); } - ngOnInit(): void { - this.applicationId = +Number(this.route.parent.parent.snapshot.paramMap.get('id')); - console.log(this.applicationId) - this.getDatatarget(); - } + ngOnInit(): void { + this.applicationId = +Number(this.route.parent.parent.snapshot.paramMap.get('id')); + console.log(this.applicationId) + this.getDatatarget(); + } + + ngOnChanges() { + this.getDatatarget(); + } + + getDatatarget(): void { + const appId: number = this.applicationId; + if (appId) { + this.datatargetSubscription = this.datatargetService + .getByApplicationId( + this.pageLimit, + this.pageOffset * this.pageLimit, + appId + ) + .subscribe((datatargets: DatatargetData) => { + this.datatargets = datatargets.data + if (this.pageLimit) { + this.pageTotal = Math.ceil(datatargets.count / this.pageLimit); + } + }); + } - ngOnChanges() { - this.getDatatarget(); - } + } - getDatatarget(): void { - const appId: number = this.applicationId; - if (appId) { - this.datatargetSubscription = this.datatargetService - .getByApplicationId( - this.pageLimit, - this.pageOffset * this.pageLimit, - appId - ) - .subscribe((datatargets: DatatargetData) => { - this.datatargets = datatargets.data - if (this.pageLimit) { - this.pageTotal = Math.ceil(datatargets.count / this.pageLimit); + deleteDatatarget(id: number) { + this.datatargetService.delete(id).subscribe((response) => { + if (response.ok && response.body.affected > 0) { + this.getDatatarget(); } }); } - - } - - deleteDatatarget(id: number) { - this.datatargetService.delete(id).subscribe((response) => { - if (response.ok && response.body.affected > 0) { - this.getDatatarget(); - } - }); - } - prevPage() { - if (this.pageOffset) this.pageOffset--; - this.getDatatarget(); - } + prevPage() { + if (this.pageOffset) this.pageOffset--; + this.getDatatarget(); + } - nextPage() { - if (this.pageOffset < this.pageTotal) this.pageOffset++; - this.getDatatarget(); - } + nextPage() { + if (this.pageOffset < this.pageTotal) this.pageOffset++; + this.getDatatarget(); + } - ngOnDestroy() { - // prevent memory leak by unsubscribing - if (this.datatargetSubscription) { - this.datatargetSubscription.unsubscribe(); - } - } + ngOnDestroy() { + // prevent memory leak by unsubscribing + if (this.datatargetSubscription) { + this.datatargetSubscription.unsubscribe(); + } + } } diff --git a/src/app/views/datatarget/datatarget/datatarget.component.ts b/src/app/views/datatarget/datatarget/datatarget.component.ts index 88d5a32d..25ca3964 100644 --- a/src/app/views/datatarget/datatarget/datatarget.component.ts +++ b/src/app/views/datatarget/datatarget/datatarget.component.ts @@ -5,123 +5,123 @@ import { Subscription } from 'rxjs'; import { BackButton } from 'src/app/models/back-button'; import { ActivatedRoute } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; -import { DatatargetService } from 'src/app/shared/_services/datatarget.service'; +import { DatatargetService } from 'src/app/shared/services/datatarget.service'; import { DatatargetResponse } from 'src/app/models/datatarget-response'; @Component({ - selector: 'app-datatarget', - templateUrl: './datatarget.component.html', - styleUrls: ['./datatarget.component.scss'] + selector: 'app-datatarget', + templateUrl: './datatarget.component.html', + styleUrls: ['./datatarget.component.scss'] }) export class DatatargetComponent implements OnInit { - public datatargetSubscription: Subscription; - public datatarget: DatatargetResponse; - public backButton: BackButton = {label: '', routerLink: '/datatarget-list'}; - public pageLimit: number = 10; - public selectedSortId: number = 6; - public selectedSortObject: Sort = { - id: 6, - dir: 'DESC', - col: 'createdAt', - label: 'SORT.CREATED-DESCENDING', - }; - public sort: Sort[] = [ - { - id: 1, - dir: 'ASC', - col: 'name', - label: 'SORT.NAME-ASCENDING', - }, - { - id: 2, - dir: 'DESC', - col: 'name', - label: 'SORT.NAME-DESCENDING', - }, - { - id: 3, - dir: 'ASC', - col: 'updatedAt', - label: 'SORT.UPDATED-ASCENDING', - }, - { - id: 4, - dir: 'DESC', - col: 'updatedAt', - label: 'SORT.UPDATED-DESCENDING', - }, - { - id: 5, - dir: 'ASC', - col: 'createdAt', - label: 'SORT.CREATED-ASCENDING', - }, - { - id: 6, - dir: 'DESC', - col: 'createdAt', - label: 'SORT.CREATED-DESCENDING', - }, - { - id: 7, - dir: 'ASC', - col: 'createdAt', - label: 'SORT.APPLICATION-ASCENDING', - }, - { - id: 8, - dir: 'DESC', - col: 'createdAt', - label: 'SORT.APPLICATION-DESCENDING', - }, - { - id: 9, - dir: 'ASC', - col: 'createdAt', - label: 'SORT.BATTERY-ASCENDING', - }, - { - id: 10, - dir: 'DESC', - col: 'createdAt', - label: 'SORT.BATTERY-DESCENDING', - }, - ]; - public buttons: QuickActionButton[] = [ - { - label: 'APPLICATION.DELETE', - type: 'delete', - }, - { - label: 'GEN.EDIT', - type: 'edit', - }, - ]; - public pageOffset: number = 0; - public pageTotal: number; + public datatargetSubscription: Subscription; + public datatarget: DatatargetResponse; + public backButton: BackButton = { label: '', routerLink: '/datatarget-list' }; + public pageLimit: number = 10; + public selectedSortId: number = 6; + public selectedSortObject: Sort = { + id: 6, + dir: 'DESC', + col: 'createdAt', + label: 'SORT.CREATED-DESCENDING', + }; + public sort: Sort[] = [ + { + id: 1, + dir: 'ASC', + col: 'name', + label: 'SORT.NAME-ASCENDING', + }, + { + id: 2, + dir: 'DESC', + col: 'name', + label: 'SORT.NAME-DESCENDING', + }, + { + id: 3, + dir: 'ASC', + col: 'updatedAt', + label: 'SORT.UPDATED-ASCENDING', + }, + { + id: 4, + dir: 'DESC', + col: 'updatedAt', + label: 'SORT.UPDATED-DESCENDING', + }, + { + id: 5, + dir: 'ASC', + col: 'createdAt', + label: 'SORT.CREATED-ASCENDING', + }, + { + id: 6, + dir: 'DESC', + col: 'createdAt', + label: 'SORT.CREATED-DESCENDING', + }, + { + id: 7, + dir: 'ASC', + col: 'createdAt', + label: 'SORT.APPLICATION-ASCENDING', + }, + { + id: 8, + dir: 'DESC', + col: 'createdAt', + label: 'SORT.APPLICATION-DESCENDING', + }, + { + id: 9, + dir: 'ASC', + col: 'createdAt', + label: 'SORT.BATTERY-ASCENDING', + }, + { + id: 10, + dir: 'DESC', + col: 'createdAt', + label: 'SORT.BATTERY-DESCENDING', + }, + ]; + public buttons: QuickActionButton[] = [ + { + label: 'APPLICATION.DELETE', + type: 'delete', + }, + { + label: 'GEN.EDIT', + type: 'edit', + }, + ]; + public pageOffset: number = 0; + public pageTotal: number; - constructor( - private route: ActivatedRoute, - private datatargetService: DatatargetService, - public translate: TranslateService) { } + constructor( + private route: ActivatedRoute, + private datatargetService: DatatargetService, + public translate: TranslateService) { } - ngOnInit(): void { - var id:number = +this.route.snapshot.paramMap.get('datatargetId'); - if (id) { - this.getDatatarget(id); + ngOnInit(): void { + var id: number = +this.route.snapshot.paramMap.get('datatargetId'); + if (id) { + this.getDatatarget(id); + } + this.translate.get(['NAV.MY-DATATARGET']) + .subscribe(translations => { + this.backButton.label = translations['NAV.MY-DATATARGET']; + }); } - this.translate.get(['NAV.MY-DATATARGET']) - .subscribe(translations => { - this.backButton.label = translations['NAV.MY-DATATARGET']; - }); - } - getDatatarget(id: number) { - this.datatargetService.get(id) - .subscribe((datatargetResponse: DatatargetResponse) => { - this.datatarget = datatargetResponse; - }); - } + getDatatarget(id: number) { + this.datatargetService.get(id) + .subscribe((datatargetResponse: DatatargetResponse) => { + this.datatarget = datatargetResponse; + }); + } } diff --git a/src/app/views/mine-applikationer/applications-table-row/applications-table-row.component.html b/src/app/views/mine-applikationer/applications-table-row/applications-table-row.component.html deleted file mode 100644 index 82e07d26..00000000 --- a/src/app/views/mine-applikationer/applications-table-row/applications-table-row.component.html +++ /dev/null @@ -1,49 +0,0 @@ - - {{ application.name }} - - - {{ application.iotDevices.length }} - - - 0 - - - {{ application.updatedAt | date: 'dd/MM yyyy' }} - - diff --git a/src/app/views/mine-applikationer/mine-applikationer/mine-applikationer.component.ts b/src/app/views/mine-applikationer/mine-applikationer/mine-applikationer.component.ts deleted file mode 100644 index 97b775ef..00000000 --- a/src/app/views/mine-applikationer/mine-applikationer/mine-applikationer.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-mine-applikationer', - templateUrl: './mine-applikationer.component.html', - styleUrls: ['./mine-applikationer.component.scss'] -}) -export class MineApplikationerComponent implements OnInit { - - constructor() { } - - ngOnInit(): void { - } - -} diff --git a/src/assets/i18n/da.json b/src/assets/i18n/da.json index 7948942f..f5960251 100644 --- a/src/assets/i18n/da.json +++ b/src/assets/i18n/da.json @@ -1,189 +1,208 @@ -{ - "GEN": { - "CANCEL": "Annuller", - "SHOW": "Vis", - "PER-PAGE": "Per side", - "BACK": "Tilbage", - "EDIT": "Redigér", - "APPLICATION": "Applikation", - "HTTP": "Generisk HTTP" - }, - "NAV": { - "DASHBOARD": "Dashboard", - "MY-APPLICATIONS": "Mine applikationer", - "ALL-IOT-DEVICES": "Alle IoT enheder", - "MY-LORA-GATEWAYS": "Mine LoRaWan Gateways", - "DATATARGET": "Datatarget", - "MY-DATATARGET": "Tilbage", - "DATATARGET-APPLIKATION": "for applikation:" - }, - "APPLICATION": { - "CREATE": "Opret applikation", - "SAVE": "Gem applikation", - "DELETE": "Slet applikation", - "NAME": "Applikationens navn", - "DESCRIPTION": "Applikationens beskrivelse", - "ATTACHED-IOT": "Tilknyttede IoT enheder" - }, - "GATEWAY": { - "DESCRIPTION":"LoRaWAN Gateway beskrivelse", - "LONGITUDE": "Længdegrad", - "LATITUDE":"Breddegrad", - "ALTITUDE":"Højde", - "SAVE": "Gem gateway", - "ID": "Gateway ID", - "LOCATION": "Placering", - "TAGS": "Tags", - "NAME": "Gatewayens navn" - }, - "IOT-DEVICE": { - "CREATE": "Gem IoT enhed", - "SAVE": "Gem IoT enhed", - "DELETE": "Slet IoT enhed", - "RESTART": "Genstart IoT enhed" - }, - "DATATARGET": { - "SAVE": "Gem datatarget", - "DESCRIPTION": "Beskrivelse" - }, - "APPLICATION-TABLE": { - "NAME": "NAVN", - "IOT-DEVICES": "IOT ENHEDER", - "UPDATED": "SENEST OPDATERET" - }, - "IOT-TABLE": { - "APPLICATION": "APPLIKATION", - "NETWORK-TECHNOLOGY": "NETVÆRKSTEKNOLOGI", - "ALARM": "ALARM", - "BATTERY": "BATTERI", - "ACTIVE": "AKTIV", - "DATA": "DATA(24 TIMER)" - }, - "LORA-GATEWAY-TABLE": { - "NAME": "Navn", - "GATEWAYID": "Gateway ID", - "LOCATION": "Placering" - }, - "LORA-GATEWAY-TABLE-ROW": { - "DELETE": "Slet Gateway", - "EDIT": "Redigér", - "SHOW-OPTIONS": "Vis muligheder" - }, - "LORA-GATEWAY": { - "CREATE":"Opret LoRaWan Gateway" - }, - "DATATARGET-TABLE": { - "NAME": "Navn", - "TYPE": "Type" - }, - "IOT-DEVICE-TYPES": { - "GENERIC_HTTP": "Generisk HTTP" - }, - "ACTIVITY": { - "NEVER": "Aldrig set" - }, - "TABLE": { - "PAGINATION": "Navigér tabel" - }, - "APPLICATION-TABLE-ROW": { - "DELETE": "Slet", - "EDIT": "Redigér", - "SHOW-OPTIONS": "Vis muligheder" - }, - "IOTDEVICE-TABLE-ROW": { - "DELETE": "Slet", - "EDIT": "Redigér", - "SHOW-OPTIONS": "Vis muligheder" - }, - "DATATARGET-TABLE-ROW": { - "DELETE":"Slet datatarget", - "EDIT": "Redigér" - }, - "FORM": { - "CREATE-NEW-APPLICATION": "Opret ny applikation", - "CREATE-NEW-LORA-GATEWAY": "Opret ny LoRaWan Gateway", - "CREATE-NEW-DATATARGET": "Opret nyt datatarget", - "CREATE-NEW-IOT-DEVICE": "Tilføj en IoT enhed", - "EDIT-NEW-GATEWAY": "Redigér LoRaWAN Gateway", - "EDIT-NEW-APPLICATION": "Redigér applikation", - "TRANSMISSION_PROTOCOL_TEXT": "Vælg transmissionsprotokol", - "TRANSMISSION_PROTOCOL_DESCRIPTION": "Transmissions protokollen angiver måden IoT-enheden forbinder til OS2IoT", - "ALERT-NO-DELETE-DEVICES": "Du kan ikke slette denne applikation da den indeholder IOT enhed(er)" - }, - "QUESTION": { - "GIVE-APPLICATION-NAME": "Navngiv applikation", - "APPLICATION-NAME-PLACEHOLDER": "Applikationens navn", - "GIVE-APPLICATION-DESCRIPTION": "Applikationens beskrivelse", - "APPLICATION-DESCRIPTION-PLACEHOLDER": "Kort beskrivelse af applikationen", - "TRANSMISSION-PROTOCOL": "Vælg transmissionsprotokol", - "ESTABLISH-CONNECTION-TO-DEVICE": "Opret forbindelse til din enhed", - "ADD-MORE-INFO-ABOUT-DEVICE": "Tilføj yderlige informationer om din enhed", - "DATATARGET": "Datatarget - Hvor vil du sende data hen?", - "REVIEW-AND-SUBMIT": "Gennemgå og godkend indstillinger for din IoT enhed", - "DEVICE-NAME-PLACEHOLDER": "Enhedsnavn", - "GIVE-DEVICE-NAME": "Navngiv enhed", - "EXTRA-COMMENT-PLACEHOLDER": "Anden relevant information", - "LOCATION-DESCRIPTION": "Beskrivelse af placering", - "LOCATION-DESCRIPTION-PLACEHOLDER": "F.eks. køleskab på 3. sal", - "CHOOSE-APPLICATION": "Vælg applikation", - "GIVE-DATATARGET-NAME": "Navngiv datatarget", - "GIVE-DATATARGET-NAME-PLACEHOLDER": "Datatarget's navn", - "GIVE-DATATARGET-TIMEOUT": "Timeout", - "GIVE-DATATARGET-URL": "Angiv datatargets URL", - "GIVE-DATATARGET-URL-PLACEHOLDER": "https://datatarget.dk/data" - }, - "QUESTION-LORA-GATEWAY": { - "NAME": "Navngiv LoRaWAN Gateway", - "NAME-PLACEHOLDER": "LoRaWAN Gateways' navn", - "DESCRIPTION":"LoRaWAN Gateway beskrivelse", - "DESCRIPTION-PLACEHOLDER":"beskrivelse af LoRaWAN Gateway", - "GATEWAYID": "Gateway ID", - "GATEWAYID-PLACEHOLDER": "0000-0000-0000-0000", - "METADATA": "Gateway Tags", - "METADATA-PLACEHOLDER": "Angiv JSON her", - "ALTITUDE": "Højde", - "ALTITUDE-PLACEHOLDER": "00", - "LONGITUDE":"Længdegrad", - "LONGITUDE-PLACEHOLDER": "00", - "LATITUDE": "Breddegrad", - "LATITUDE-PLACEHOLDER": "00" - }, - "SORT": { - "SORT": "Sortér", - "UPDATED-ASCENDING": "Senest opdateret: stigende", - "UPDATED-DESCENDING": "Senest opdateret: faldende", - "CREATED-ASCENDING": "Oprettet: stigende", - "CREATED-DESCENDING": "Oprettet: faldende", - "NAME-ASCENDING": "Navn: stigende", - "NAME-DESCENDING": "Navn: faldende", - "APPLICATION-ASCENDING": "Applikation: stigende", - "APPLICATION-DESCENDING": "Applikation: faldende", - "BATTERY-ASCENDING": "Batteri: stigende", - "BATTERY-DESCENDING": "Batteri: faldende" - }, - "IOTDEVICE": { - "HEADING": { - "PROTOCOL": "Transmission Protokol", - "BASIC": "Basis info", - "OPTIONAL": "Yderligere info" - }, - "NAME": "Navn", - "TYPE": "Enhedstype", - "APPLICATION": "Applikation", - "LOCATION": "Placering", - "LONGITUDE": "Længdegrad", - "LATITUDE": "Breddegrad", - "COMMENTONLOCATION": "Kommentar om placering", - "COMMENT": "Kommentar", - "NOCOMMENT": "Ingen kommentar er angivet.", - "NOLOCATION": "Ingen placering er angivet", - "NOCOMMENTONLOCATION": "Ingen kommentar om placeringen er angivet", - "GENERIC_HTTP": { - "APIKEY": "API kald", - "INSTRUCTIONS": "Du kalder denne url:" - } - }, - "MESSAGE": { - "NAME-INVALID-OR-ALREADY-IN-USE": "En applikation med det navn findes allerede" - } -} \ No newline at end of file +{ + "GEN": { + "CANCEL": "Annuller", + "SHOW": "Vis", + "PER-PAGE": "Per side", + "BACK": "Tilbage", + "EDIT": "Redigér", + "APPLICATION": "Applikation", + "HTTP": "Generisk HTTP" + }, + "NAV": { + "DASHBOARD": "Dashboard", + "MY-APPLICATIONS": "Mine applikationer", + "ALL-IOT-DEVICES": "Alle IoT enheder", + "MY-LORA-GATEWAYS": "Mine LoRaWan Gateways", + "DATATARGET": "Datatarget", + "MY-DATATARGET": "Tilbage", + "DATATARGET-APPLIKATION": "for applikation:", + "PROFILES": "Profiler" + }, + "APPLICATION": { + "CREATE": "Opret applikation", + "SAVE": "Gem applikation", + "DELETE": "Slet applikation", + "NAME": "Applikationens navn", + "DESCRIPTION": "Applikationens beskrivelse", + "ATTACHED-IOT": "Tilknyttede IoT enheder" + }, + "GATEWAY": { + "DESCRIPTION": "LoRaWAN Gateway beskrivelse", + "LONGITUDE": "Længdegrad", + "LATITUDE": "Breddegrad", + "ALTITUDE": "Højde", + "SAVE": "Gem gateway", + "ID": "Gateway ID", + "LOCATION": "Placering", + "TAGS": "Tags", + "NAME": "Gatewayens navn" + }, + "IOT-DEVICE": { + "CREATE": "Gem IoT enhed", + "SAVE": "Gem IoT enhed", + "DELETE": "Slet IoT enhed", + "RESTART": "Genstart IoT enhed" + }, + "DATATARGET": { + "SAVE": "Gem datatarget", + "DESCRIPTION": "Beskrivelse" + }, + "APPLICATION-TABLE": { + "NAME": "NAVN", + "IOT-DEVICES": "IOT ENHEDER", + "UPDATED": "SENEST OPDATERET" + }, + "IOT-TABLE": { + "APPLICATION": "APPLIKATION", + "NETWORK-TECHNOLOGY": "NETVÆRKSTEKNOLOGI", + "ALARM": "ALARM", + "BATTERY": "BATTERI", + "ACTIVE": "AKTIV", + "DATA": "DATA(24 TIMER)" + }, + "LORA-GATEWAY-TABLE": { + "NAME": "Navn", + "GATEWAYID": "Gateway ID", + "LOCATION": "Placering" + }, + "LORA-GATEWAY-TABLE-ROW": { + "DELETE": "Slet Gateway", + "EDIT": "Redigér", + "SHOW-OPTIONS": "Vis muligheder" + }, + "LORA-GATEWAY": { + "CREATE": "Opret LoRaWan Gateway" + }, + "DATATARGET-TABLE": { + "NAME": "Navn", + "TYPE": "Type" + }, + "IOT-DEVICE-TYPES": { + "GENERIC_HTTP": "Generisk HTTP" + }, + "ACTIVITY": { + "NEVER": "Aldrig set" + }, + "TABLE": { + "PAGINATION": "Navigér tabel" + }, + "APPLICATION-TABLE-ROW": { + "DELETE": "Slet", + "EDIT": "Redigér", + "SHOW-OPTIONS": "Vis muligheder" + }, + "IOTDEVICE-TABLE-ROW": { + "DELETE": "Slet", + "EDIT": "Redigér", + "SHOW-OPTIONS": "Vis muligheder" + }, + "DATATARGET-TABLE-ROW": { + "DELETE": "Slet datatarget", + "EDIT": "Redigér" + }, + "FORM": { + "CREATE-NEW-APPLICATION": "Opret ny applikation", + "CREATE-NEW-LORA-GATEWAY": "Opret ny LoRaWan Gateway", + "CREATE-NEW-DATATARGET": "Opret nyt datatarget", + "CREATE-NEW-IOT-DEVICE": "Tilføj en IoT enhed", + "EDIT-NEW-GATEWAY": "Redigér LoRaWAN Gateway", + "EDIT-NEW-APPLICATION": "Redigér applikation", + "TRANSMISSION_PROTOCOL_TEXT": "Vælg transmissionsprotokol", + "TRANSMISSION_PROTOCOL_DESCRIPTION": "Transmissions protokollen angiver måden IoT-enheden forbinder til OS2IoT", + "ALERT-NO-DELETE-DEVICES": "Du kan ikke slette denne applikation da den indeholder IOT enhed(er)" + }, + "QUESTION": { + "GIVE-APPLICATION-NAME": "Navngiv applikation", + "APPLICATION-NAME-PLACEHOLDER": "Applikationens navn", + "GIVE-APPLICATION-DESCRIPTION": "Applikationens beskrivelse", + "APPLICATION-DESCRIPTION-PLACEHOLDER": "Kort beskrivelse af applikationen", + "TRANSMISSION-PROTOCOL": "Vælg transmissionsprotokol", + "ESTABLISH-CONNECTION-TO-DEVICE": "Opret forbindelse til din enhed", + "ADD-MORE-INFO-ABOUT-DEVICE": "Tilføj yderlige informationer om din enhed", + "DATATARGET": "Datatarget - Hvor vil du sende data hen?", + "REVIEW-AND-SUBMIT": "Gennemgå og godkend indstillinger for din IoT enhed", + "DEVICE-NAME-PLACEHOLDER": "Enhedsnavn", + "GIVE-DEVICE-NAME": "Navngiv enhed", + "EXTRA-COMMENT-PLACEHOLDER": "Anden relevant information", + "LOCATION-DESCRIPTION": "Beskrivelse af placering", + "LOCATION-DESCRIPTION-PLACEHOLDER": "F.eks. køleskab på 3. sal", + "CHOOSE-APPLICATION": "Vælg applikation", + "GIVE-DATATARGET-NAME": "Navngiv datatarget", + "GIVE-DATATARGET-NAME-PLACEHOLDER": "Datatarget's navn", + "GIVE-DATATARGET-TIMEOUT": "Timeout", + "GIVE-DATATARGET-URL": "Angiv datatargets URL", + "GIVE-DATATARGET-URL-PLACEHOLDER": "https://datatarget.dk/data" + }, + "QUESTION-LORA-GATEWAY": { + "NAME": "Navngiv LoRaWAN Gateway", + "NAME-PLACEHOLDER": "LoRaWAN Gateways' navn", + "DESCRIPTION": "LoRaWAN Gateway beskrivelse", + "DESCRIPTION-PLACEHOLDER": "beskrivelse af LoRaWAN Gateway", + "GATEWAYID": "Gateway ID", + "GATEWAYID-PLACEHOLDER": "0000-0000-0000-0000", + "METADATA": "Gateway Tags", + "METADATA-PLACEHOLDER": "Angiv JSON her", + "ALTITUDE": "Højde", + "ALTITUDE-PLACEHOLDER": "00", + "LONGITUDE": "Længdegrad", + "LONGITUDE-PLACEHOLDER": "00", + "LATITUDE": "Breddegrad", + "LATITUDE-PLACEHOLDER": "00" + }, + "SORT": { + "SORT": "Sortér", + "UPDATED-ASCENDING": "Senest opdateret: stigende", + "UPDATED-DESCENDING": "Senest opdateret: faldende", + "CREATED-ASCENDING": "Oprettet: stigende", + "CREATED-DESCENDING": "Oprettet: faldende", + "NAME-ASCENDING": "Navn: stigende", + "NAME-DESCENDING": "Navn: faldende", + "APPLICATION-ASCENDING": "Applikation: stigende", + "APPLICATION-DESCENDING": "Applikation: faldende", + "BATTERY-ASCENDING": "Batteri: stigende", + "BATTERY-DESCENDING": "Batteri: faldende" + }, + "IOTDEVICE": { + "HEADING": { + "PROTOCOL": "Transmission Protokol", + "BASIC": "Basis info", + "OPTIONAL": "Yderligere info" + }, + "NAME": "Navn", + "TYPE": "Enhedstype", + "APPLICATION": "Applikation", + "LOCATION": "Placering", + "LONGITUDE": "Længdegrad", + "LATITUDE": "Breddegrad", + "COMMENTONLOCATION": "Kommentar om placering", + "COMMENT": "Kommentar", + "NOCOMMENT": "Ingen kommentar er angivet.", + "NOLOCATION": "Ingen placering er angivet", + "NOCOMMENTONLOCATION": "Ingen kommentar om placeringen er angivet", + "GENERIC_HTTP": { + "APIKEY": "API kald", + "INSTRUCTIONS": "Du kalder denne url:" + } + }, + "MESSAGE": { + "NAME-INVALID-OR-ALREADY-IN-USE": "En applikation med det navn findes allerede" + }, + "PROFILES": { + "NAME": "Profiler", + "SERVICE_PROFILE": { + "DROPDOWN": "HÃ¥ndter service profil", + "EDIT": "Editer service profil", + "DELETE": "Slet service profil", + "NAME": "Navn", + "REPORTBATTERYSTATUS": "Report battery status", + "ADDGWMETADATA": "Tilføjet GW meta data", + "DRRATEMIN": "Min date rate", + "DRRATEMAX": "Max date rate", + "REPORT_END_DEVICE": "Report end-device margin", + "SAVE": "Gem", + "CANCEL": "Annuller", + "GOBACK": "GÃ¥ tilbage", + "ADDSERVICEPROFILE": "Tilføj eller editer service profil" + } + } +} diff --git a/src/assets/scss/_tables.scss b/src/assets/scss/_tables.scss index 65f5883c..f9e88f6f 100644 --- a/src/assets/scss/_tables.scss +++ b/src/assets/scss/_tables.scss @@ -1,97 +1,98 @@ .table { - background-color: $white; - // -webkit-border-radius: .25rem; - // -moz-border-radius: .25rem; - // border-radius: .25rem; - box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.14), - 0px 1px 13px rgba(0, 0, 0, 0.03), 0px 0px 1px rgba(0, 0, 0, 0.22); - -webkit-box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.14), - 0px 1px 13px rgba(0, 0, 0, 0.03), 0px 0px 1px rgba(0, 0, 0, 0.22); - -moz-box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.14), - 0px 1px 13px rgba(0, 0, 0, 0.03), 0px 0px 1px rgba(0, 0, 0, 0.22); - // border: $grey-border solid 1px; + background-color: $white; + // -webkit-border-radius: .25rem; + // -moz-border-radius: .25rem; + // border-radius: .25rem; + box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.14), + 0px 1px 13px rgba(0, 0, 0, 0.03), 0px 0px 1px rgba(0, 0, 0, 0.22); + -webkit-box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.14), + 0px 1px 13px rgba(0, 0, 0, 0.03), 0px 0px 1px rgba(0, 0, 0, 0.22); + -moz-box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.14), + 0px 1px 13px rgba(0, 0, 0, 0.03), 0px 0px 1px rgba(0, 0, 0, 0.22); + // border: $grey-border solid 1px; + * { * { - * { - border-bottom-width: 0 !important; - } + border-bottom-width: 0 !important; } + } - th, - td { - padding: 0.5rem 1rem; - } + th, + td { + padding: 0.5rem 1rem; + } - thead { - font-family: roboto-light; - font-weight: 300; - font-size: 15px; - line-height: 24px; - color: $grey-tablehead; - background-color: $grey-dark; - } + thead { + font-family: roboto-light; + font-weight: 300; + font-size: 15px; + line-height: 24px; + color: $grey-tablehead; + background-color: $grey-dark; + } - tbody { - color: $black; - font-family: roboto; + tbody { + color: $black; + font-family: roboto; - tr { - border-top: $grey-border solid 1px; - line-height: 40px; - color: $black; + tr { + border-top: $grey-border solid 1px; + line-height: 40px; + color: $black; - &:hover { - background-color: $grey-highlight; - } - } + &:hover { + background-color: $grey-highlight; + } } + } } .dropdown { - right: 3rem; - top: 10px; + right: 3rem; + top: 10px; - .applicationRow__edit { - width: 10px; - height: 20px; - background-image: radial-gradient(circle, $black 2px, transparent 1px); - background-size: 100% 33.33%; - padding: 2px 10px; + .applicationRow__edit { + width: 10px; + height: 20px; + background-image: radial-gradient(circle, $black 2px, transparent 1px); + background-size: 100% 33.33%; + padding: 2px 10px; - &:after { - display: none; - } + &:after { + display: none; } + } - .dropdown-menu { - min-width: 90px !important; - left: -35px !important; + .dropdown-menu { + min-width: 90px !important; + left: -35px !important; - li { - a { - font-family: roboto-bold; - color: $black; - font-size: 12px; - line-height: 14px; - } + li { + a { + font-family: roboto-bold; + color: $black; + font-size: 12px; + line-height: 14px; + } - &:hover, - &:active { - color: $black; - text-decoration: none; - background-color: #0d6efd; - } - } + &:hover, + &:active { + color: $black; + text-decoration: none; + background-color: #0d6efd; + } } + } } .pagination { - .page-item { - .page-link { - color: $black; - &:focus { - box-shadow: 0 0 0 0.2rem $grey-outline; - } - } + .page-item { + .page-link { + color: $black; + + &:focus { + box-shadow: 0 0 0 0.2rem $grey-outline; + } } + } } diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 37be9ad9..3049be24 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -4,7 +4,7 @@ export const environment = { production: false, - baseUrl: 'http://localhost:3000/api/v1/' + baseUrl: 'http://[::1]:3000/api/v1/' }; /* diff --git a/src/styles.scss b/src/styles.scss index f60b7aca..addae3cb 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,4 +1,3 @@ - // Custom Theming for Angular Material // For more information: https://material.angular.io/guide/theming @import '~@angular/material/theming'; @@ -31,18 +30,18 @@ $OS2IoT-frontend-theme: mat-light-theme($OS2IoT-frontend-primary, $OS2IoT-fronte // Fonts @font-face { - font-family: 'roboto-light'; - src: url('./assets/fonts/Roboto-Light.ttf') format('truetype'); + font-family: 'roboto-light'; + src: url('./assets/fonts/Roboto-Light.ttf') format('truetype'); } @font-face { - font-family: 'roboto'; - src: url('./assets/fonts/Roboto-Regular.ttf') format('truetype'); + font-family: 'roboto'; + src: url('./assets/fonts/Roboto-Regular.ttf') format('truetype'); } @font-face { - font-family: 'roboto-bold'; - src: url('./assets/fonts/Roboto-Bold.ttf') format('truetype'); + font-family: 'roboto-bold'; + src: url('./assets/fonts/Roboto-Bold.ttf') format('truetype'); } @@ -56,5 +55,12 @@ $OS2IoT-frontend-theme: mat-light-theme($OS2IoT-frontend-primary, $OS2IoT-fronte @import 'assets/scss/forms'; -html, body { height: 100%; } -body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } +html, +body { + height: 100%; +} + +body { + margin: 0; + font-family: Roboto, "Helvetica Neue", sans-serif; +} diff --git a/tsconfig.json b/tsconfig.json index 253b3354..437e0730 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,20 +1,41 @@ { - "compileOnSave": false, - "compilerOptions": { - "baseUrl": "./", - "outDir": "./dist/out-tsc", - "sourceMap": true, - "declaration": false, - "downlevelIteration": true, - "experimentalDecorators": true, - "module": "esnext", - "moduleResolution": "node", - "importHelpers": true, - "target": "es2015", - "lib": ["es2018", "dom"] + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "module": "esnext", + "moduleResolution": "node", + "importHelpers": true, + "target": "es2015", + "lib": ["es2018", "dom"], + "typeRoots": ["node_modules/@types"], + "paths": { + "@app/*": [ + "app/*" + ], + "@shared/*": [ + "app/shared/*" + ], + "@store/*": [ + "app/store/*" + ], + "@environments/*": [ + "environments/*" + ], + "@Material": [ + "app/shared/modules/material.module" + ], + "@Shared-Bootstrap": [ + "app/shared/modules/shared-bootstrap.module" + ] }, - "angularCompilerOptions": { - "fullTemplateTypeCheck": true, - "strictInjectionParameters": true - } + }, + "angularCompilerOptions": { + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true + } } diff --git a/tslint.json b/tslint.json index 0a5244e8..4f4dff57 100644 --- a/tslint.json +++ b/tslint.json @@ -10,23 +10,30 @@ }, "array-type": false, "arrow-return-shorthand": true, + "callable-types": true, + "class-name": true, + "comment-format": [true, "check-space"], + "component-class-suffix": true, + "component-selector": [true, "element", "app", "kebab-case"], "curly": true, "deprecation": { "severity": "warning" }, - "component-class-suffix": true, "contextual-lifecycle": true, "directive-class-suffix": true, "directive-selector": [true, "attribute", "app", "camelCase"], - "component-selector": [true, "element", "app", "kebab-case"], "eofline": true, + "forin": true, + "interface-over-type-literal": true, "import-blacklist": [true, "rxjs/Rx"], "import-spacing": true, "indent": { "options": ["spaces"] }, + "label-position": true, "max-classes-per-file": false, - "max-line-length": [true, 140], + "max-line-length": [true, 200], + "member-access": false, "member-ordering": [ true, { @@ -50,6 +57,51 @@ "semicolon": { "options": ["always"] }, + "no-conflicting-lifecycle": true, + "no-host-metadata-property": true, + "no-input-rename": true, + "no-inputs-metadata-property": true, + "no-output-native": true, + "no-output-on-prefix": true, + "no-output-rename": true, + "no-outputs-metadata-property": true, + "no-arg": true, + "no-bitwise": true, + "no-construct": true, + "no-debugger": true, + "no-duplicate-super": true, + "no-empty-interface": true, + "no-eval": true, + "no-misused-new": true, + "no-shadowed-variable": [ + false, + { + "class": true, + "enum": true, + "function": true, + "interface": false, + "namespace": true, + "typeAlias": false, + "typeParameter": false + } + ], + "no-string-literal": false, + "no-string-throw": true, + "no-trailing-whitespace": true, + "no-unnecessary-initializer": true, + "no-unused-expression": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "prefer-const": true, + "radix": true, "space-before-function-paren": { "options": { "anonymous": "never", @@ -59,6 +111,9 @@ "named": "never" } }, + "template-banana-in-box": true, + "template-no-negated-async": true, + "triple-equals": [true, "allow-null-check"], "typedef-whitespace": { "options": [ { @@ -67,16 +122,12 @@ "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" - }, - { - "call-signature": "onespace", - "index-signature": "onespace", - "parameter": "onespace", - "property-declaration": "onespace", - "variable-declaration": "onespace" } ] }, + "unified-signatures": true, + "use-lifecycle-interface": true, + "use-pipe-transform-interface": true, "variable-name": { "options": ["ban-keywords", "check-format", "allow-pascal-case"] }, @@ -87,21 +138,10 @@ "check-operator", "check-separator", "check-type", - "check-typecast" + "check-typecast", + "check-module" ] - }, - "no-conflicting-lifecycle": true, - "no-host-metadata-property": true, - "no-input-rename": true, - "no-inputs-metadata-property": true, - "no-output-native": true, - "no-output-on-prefix": true, - "no-output-rename": true, - "no-outputs-metadata-property": true, - "template-banana-in-box": true, - "template-no-negated-async": true, - "use-lifecycle-interface": true, - "use-pipe-transform-interface": true + } }, "rulesDirectory": ["codelyzer"] }