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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { NgModule } from "@angular/core";
import { Routes, RouterModule, PreloadAllModules } from "@angular/router";
import { AuthComponent } from "./auth/auth.component";
import { ErrorPageComponent } from "./error-page/error-page.component";
import { SearchComponent } from "./search/search.component";
import { AuthGuardService as AuthGuard } from "./auth/auth-guard.service";
import { PreloadAllModules, RouterModule, Routes } from "@angular/router";
import { NewUserComponent } from "./admin/users/new-kombit-user-page/new-user.component";
import { UserPageComponent } from "./admin/users/user-page/user-page.component";
import { AuthGuardService as AuthGuard } from "./auth/auth-guard.service";
import { AuthComponent } from "./auth/auth.component";
import { ErrorPageComponent } from "./error-page/error-page.component";

const routes: Routes = [
{
Expand Down Expand Up @@ -44,7 +43,6 @@ const routes: Routes = [
loadChildren: () => import("./device-model/device-model.module").then(m => m.DeviceModelModule),
canActivate: [AuthGuard],
},
{ path: "search", component: SearchComponent, canActivate: [AuthGuard] },
{ path: "not-found", component: ErrorPageComponent, data: { message: "not-found", code: 404 } },
{ path: "not-authorized", component: ErrorPageComponent },
{ path: "new-user", component: NewUserComponent, canActivate: [AuthGuard] },
Expand Down
50 changes: 26 additions & 24 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
import { BrowserModule, Title } from "@angular/platform-browser";
import { NgIf } from "@angular/common";
import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from "@angular/common/http";
import { NgModule } from "@angular/core";
import { TranslateModule, TranslateLoader } from "@ngx-translate/core";
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
import { HttpClient, HttpClientModule, HTTP_INTERCEPTORS } from "@angular/common/http";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { NavbarModule } from "./navbar/navbar.module";
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { ProfilesModule } from "./profiles/profiles.module";
import { AuthJwtInterceptor } from "@shared/helpers/auth-jwt.interceptor";
import { AuthModule } from "./auth/auth.module";
import { GatewayModule } from "./gateway/gateway.module";
import { SharedVariableModule } from "@shared/shared-variable/shared-variable.module";
import { SAVER, getSaver } from "@shared/providers/saver.provider";
import { ErrorPageComponent } from "./error-page/error-page.component";
import { SearchModule } from "./search/search.module";
import { JwtModule } from "@auth0/angular-jwt";
import { MonacoEditorModule } from "ngx-monaco-editor-v2";
import { MatInputModule } from "@angular/material/input";
import { MatPaginatorIntl } from "@angular/material/paginator";
import { MatPaginatorIntlDa } from "@shared/helpers/mat-paginator-intl-da";
import { MatTooltipModule } from "@angular/material/tooltip";
import { NewUserComponent } from "./admin/users/new-kombit-user-page/new-user.component";
import { BrowserModule, Title } from "@angular/platform-browser";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { JwtModule } from "@auth0/angular-jwt";
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
import { TranslateLoader, TranslateModule } from "@ngx-translate/core";
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
import { MatSelectSearchModule } from "@shared/components/mat-select-search/mat-select-search.module";
import { WelcomeDialogModule } from "@shared/components/welcome-dialog/welcome-dialog.module";
import { AuthJwtInterceptor } from "@shared/helpers/auth-jwt.interceptor";
import { MatPaginatorIntlDa } from "@shared/helpers/mat-paginator-intl-da";
import { NGMaterialModule } from "@shared/Modules/materiale.module";
import { MatSelectSearchModule } from "@shared/components/mat-select-search/mat-select-search.module";
import { UserPageComponent } from "./admin/users/user-page/user-page.component";
import { SharedModule } from "@shared/shared.module";
import { PipesModule } from "@shared/pipes/pipes.module";
import { SAVER, getSaver } from "@shared/providers/saver.provider";
import { SharedVariableModule } from "@shared/shared-variable/shared-variable.module";
import { SharedModule } from "@shared/shared.module";
import { CookieService } from "ngx-cookie-service";
import { MonacoEditorModule } from "ngx-monaco-editor-v2";
import { NewUserComponent } from "./admin/users/new-kombit-user-page/new-user.component";
import { UserPageComponent } from "./admin/users/user-page/user-page.component";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { AuthModule } from "./auth/auth.module";
import { ErrorPageComponent } from "./error-page/error-page.component";
import { GatewayModule } from "./gateway/gateway.module";
import { NavbarModule } from "./navbar/navbar.module";
import { ProfilesModule } from "./profiles/profiles.module";
import { SearchModule } from "./search/search.module";

export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, "./assets/i18n/", ".json");
Expand Down Expand Up @@ -60,6 +61,7 @@ export function tokenGetter() {
},
}),
NgbModule,
NgIf,
FormsModule,
ReactiveFormsModule,
BrowserAnimationsModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
import { AfterViewInit, Component, EventEmitter, OnDestroy, OnInit, Output } from "@angular/core";
import { AfterViewInit, ChangeDetectorRef, Component, EventEmitter, OnDestroy, OnInit, Output } from "@angular/core";
import { MatDialog } from "@angular/material/dialog";
import { Title } from "@angular/platform-browser";
import { ActivatedRoute, Router } from "@angular/router";
import { Gateway, GatewayResponseMany } from "@app/gateway/gateway.model";
import { Application } from "@applications/application.model";
import { ApplicationService } from "@applications/application.service";
import { IotDevicesApplicationMapResponse } from "@applications/iot-devices/iot-device.model";
import { TranslateService } from "@ngx-translate/core";
import { DeleteDialogService } from "@shared/components/delete-dialog/delete-dialog.service";
import { OrganizationAccessScope } from "@shared/enums/access-scopes";
import { BackButton } from "@shared/models/back-button.model";
import { ApplicationDialogModel } from "@shared/models/dialog.model";
import { DropdownButton } from "@shared/models/dropdown-button.model";
import { ChirpstackGatewayService } from "@shared/services/chirpstack-gateway.service";
import { MeService } from "@shared/services/me.service";
import { Subscription } from "rxjs";
import { OrganizationAccessScope } from "@shared/enums/access-scopes";
import { IotDevicesApplicationMapResponse } from "@applications/iot-devices/iot-device.model";
import { RestService } from "@shared/services/rest.service";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
import { SharedVariableService } from "@shared/shared-variable/shared-variable.service";
import { ChirpstackGatewayService } from "@shared/services/chirpstack-gateway.service";
import { Gateway, GatewayResponseMany } from "@app/gateway/gateway.model";
import { MatDialog } from "@angular/material/dialog";
import { Observable, Subscription } from "rxjs";
import { map } from "rxjs/operators";
import { ApplicationChangeOrganizationDialogComponent } from "../application-change-organization-dialog/application-change-organization-dialog.component";
import { ApplicationDialogModel } from "@shared/models/dialog.model";

@Component({
selector: "app-application",
Expand Down Expand Up @@ -72,11 +71,13 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy, AfterViewI
private restService: RestService,
private sharedVariableService: SharedVariableService,
private chirpstackGatewayService: ChirpstackGatewayService,
private changeOrganizationDialog: MatDialog
private changeOrganizationDialog: MatDialog,
private cdr: ChangeDetectorRef
) {}

ngOnInit(): void {
this.id = +this.route.snapshot.paramMap.get("id");

if (this.id) {
this.bindApplication(this.id);
this.dropdownButton = {
Expand Down Expand Up @@ -147,7 +148,7 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy, AfterViewI
useGeolocation: false,
markerInfo: {
name: dev.name,
active: false,
active: dev.type,
id: dev.id,
isDevice: true,
internalOrganizationId: this.sharedVariableService.getSelectedOrganisationId(),
Expand Down Expand Up @@ -214,6 +215,7 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy, AfterViewI
bindApplication(id: number): void {
this.applicationsSubscription = this.applicationService.getApplication(id).subscribe(application => {
this.application = application;
this.cdr.detectChanges();
});
}

Expand Down
6 changes: 4 additions & 2 deletions src/app/applications/application.model.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { PermissionResponse } from "@app/admin/permission/permission.model";
import { ControlledPropertyTypes } from "@app/device-model/Enums/controlled-propperty.enum";
import { Datatarget } from "@applications/datatarget/datatarget.model";
import { ApplicationDeviceTypeUnion } from "@shared/enums/device-type";
import { ControlledProperty } from "@shared/models/controlled-property.model";
import { Organisation } from "../admin/organisation/organisation.model";
import { ApplicationStatus } from "./enums/status.enum";
import { IotDevice } from "./iot-devices/iot-device.model";
import { ApplicationDeviceType } from "./models/application-device-type.model";
import { PermissionResponse } from "@app/admin/permission/permission.model";
import { Datatarget } from "@applications/datatarget/datatarget.model";

export type ApplicationWithStatus = Application & { statusCheck: "stable" | "alert" };

export class Application {
public id: number;
Expand Down
46 changes: 43 additions & 3 deletions src/app/applications/application.service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Injectable } from "@angular/core";
import { UserMinimalService } from "@app/admin/users/user-minimal.service";
import { Application, ApplicationData, UpdateApplicationOrganization } from "@applications/application.model";
import { RestService } from "../shared/services/rest.service";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
import { UserMinimalService } from "@app/admin/users/user-minimal.service";
import { RestService } from "../shared/services/rest.service";
import { ApplicationsFilterService } from "./applications-list/application-filter/applications-filter.service";
import { ApplicationStatus, ApplicationStatusCheck } from "./enums/status.enum";
import { IotDevice } from "./iot-devices/iot-device.model";

interface GetApplicationParameters {
limit: number;
Expand All @@ -12,6 +15,15 @@ interface GetApplicationParameters {
orderOn: string;
organizationId?: number;
permissionId?: number;
status?: ApplicationStatus;
statusCheck?: ApplicationStatusCheck;
owner?: string;
}

interface GetDevicesParameters {
status?: ApplicationStatus;
statusCheck?: ApplicationStatusCheck;
owner?: string;
}

@Injectable({
Expand All @@ -20,7 +32,11 @@ interface GetApplicationParameters {
export class ApplicationService {
public id: number;
public canEdit = false;
constructor(private restService: RestService, private userMinimalService: UserMinimalService) {}
constructor(
private restService: RestService,
private userMinimalService: UserMinimalService,
private filterService: ApplicationsFilterService
) {}

createApplication(body: any): Observable<ApplicationData> {
return this.restService.post("application", body, { observe: "response" });
Expand All @@ -41,6 +57,17 @@ export class ApplicationService {
})
);
}
getApplicationFilterOptions(id: number): Observable<string[]> {
return this.restService.get(`application/${id}/filter-information`);
}

getApplicationsWithError(id: number): Observable<{
total: number;
withError: number;
totalDevices: number;
}> {
return this.restService.get(`application/${id}/application-dashboard-data`);
}

getApplications(
limit: number,
Expand All @@ -55,6 +82,9 @@ export class ApplicationService {
offset,
sort,
orderOn,
statusCheck: this.filterService.statusCheck === "All" ? null : this.filterService.statusCheck,
status: this.filterService.status === "All" ? null : this.filterService.status,
owner: this.filterService.owner === "All" ? null : this.filterService.owner,
};
if (permissionId) {
body.permissionId = permissionId;
Expand All @@ -66,6 +96,16 @@ export class ApplicationService {
return this.restService.get("application", body);
}

getApplicationDevices(organizationId?: number): Observable<IotDevice[]> {
const body: GetDevicesParameters = {
statusCheck: this.filterService.statusCheck === "All" ? null : this.filterService.statusCheck,
status: this.filterService.status === "All" ? null : this.filterService.status,
owner: this.filterService.owner === "All" ? null : this.filterService.owner,
};

return this.restService.get(`application/${organizationId}/iot-devices-org`, body);
}

getApplicationsByOrganizationId(organizationId: number): Observable<ApplicationData> {
const body = {
organizationId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<div class="filter-container">
<div class="filter-selector-container">
<div class="filter-title">{{ "APPLICATION-FILTER.STATUS" | translate }}</div>
<mat-form-field appearance="outline">
<mat-select class="withoutArrow" [(value)]="state" placeholder="test" (selectionChange)="onStatusCheck($event)">
<mat-option *ngFor="let option of statusOptions" [value]="option.value">
{{ option.label | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</div>

<div class="filter-selector-container">
<div class="filter-title">{{ "APPLICATION-FILTER.STATE" | translate }}</div>
<mat-form-field appearance="outline">
<mat-select class="withoutArrow" [(value)]="status" (selectionChange)="onStatus($event)">
<mat-option *ngFor="let option of stateOptions" [value]="option.value">
{{ option.label | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</div>

<div class="filter-selector-container">
<div class="filter-title">{{ "APPLICATION-FILTER.OWNER" | translate }}</div>
<mat-form-field appearance="outline">
<mat-select class="withoutArrow" [(value)]="owner" (selectionChange)="onOwner($event)">
<mat-option [value]="owner">
{{ "APPLICATION-FILTER.ALL" | translate }}
</mat-option>
<mat-option *ngFor="let option of ownerOptions" [value]="option.value">
{{ option.label }}
</mat-option>
</mat-select>
</mat-form-field>
</div>

<div class="spacer"></div>
<button class="filter-button" mat-flat-button (click)="onButtonClick()">
<div class="filter-icon-container">
<img ngSrc="../../../../assets/images/sliders.svg" width="18" height="16" priority />
<div class="filter-label">
{{ "APPLICATION-FILTER.RESET-FILTER" | translate }}
</div>
</div>
</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
@import "../../../../assets/scss/setup/variables";

.filter-container {
display: flex;
flex-direction: row;
flex: 1;
min-height: 65px;
margin-bottom: 25px;
flex-wrap: wrap;
}

@media (max-width: 768px) {
.filter-container {
flex-direction: column;
}
}

.filter-selector-container {
width: 200px;
margin-right: 30px;
display: flex;
flex-direction: column;
margin-bottom: 30px;
}

.filter-title {
font-size: 14px;
}

.spacer {
display: flex;
flex: 1;
}

.filter-button {
margin-top: 26px;
height: 40px !important;
width: 170px !important;
min-width: 170px !important;
justify-content: center;
display: flex !important;
align-items: center;
border: 1px solid $color-link !important;
}

.filter-icon-container {
display: flex !important;
align-items: center;
justify-content: center;
gap: 10px;
width: 150px;
}

.filter-label {
font-size: 16px;
font-weight: 500;
}

:host .mat-mdc-select {
height: 24px;
display: flex;
align-items: center;
font-size: 16px !important;
color: $selector-font-color !important;
}

:host .mat-mdc-form-field {
height: 20px !important;
display: flex;
align-items: center;
}

:host .mat-mdc-text-field-wrapper {
background-color: $white !important;
height: 40px !important;
display: flex !important;
align-items: center !important;
font-size: 16px !important;
}

:host .mat-mdc-select-arrow {
display: none;
}
Loading
Loading