Revize cbb91c90
Přidáno uživatelem Jakub Hlaváč před téměř 4 roky(ů)
src/app/administration/administration.module.ts | ||
---|---|---|
1 |
import { NgModule } from '@angular/core'; |
|
2 |
import { CommonModule } from '@angular/common'; |
|
3 |
import { AdministrationComponent } from './components/administration.component'; |
|
4 |
import {NavBarModule} from '../shared/nav-bar/nav-bar.module'; |
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
@NgModule({ |
|
9 |
declarations: [AdministrationComponent], |
|
10 |
imports: [ |
|
11 |
CommonModule, |
|
12 |
NavBarModule |
|
13 |
] |
|
14 |
}) |
|
15 |
export class AdministrationModule { } |
src/app/administration/components/administration.component.html | ||
---|---|---|
1 |
<app-nav-bar></app-nav-bar> |
|
2 |
|
|
3 |
<p>administration works!</p> |
src/app/administration/components/administration.component.ts | ||
---|---|---|
1 |
import { Component, OnInit } from '@angular/core'; |
|
2 |
|
|
3 |
@Component({ |
|
4 |
selector: 'app-administration', |
|
5 |
templateUrl: './administration.component.html', |
|
6 |
styleUrls: ['./administration.component.scss'] |
|
7 |
}) |
|
8 |
export class AdministrationComponent implements OnInit { |
|
9 |
|
|
10 |
constructor() { } |
|
11 |
|
|
12 |
ngOnInit(): void { |
|
13 |
} |
|
14 |
|
|
15 |
} |
src/app/app-routing.module.ts | ||
---|---|---|
4 | 4 |
import {DashboardComponent} from './dashboard/components/dashboard.component'; |
5 | 5 |
import {AuthGuard} from './auth/guards/auth.guard'; |
6 | 6 |
import {RoleGuard} from './auth/guards/role.guard'; |
7 |
import {AdministrationComponent} from './administration/components/administration.component'; |
|
8 | 7 |
import {SensorComponent} from './sensor/components/sensor.component'; |
9 | 8 |
import {UnitComponent} from './unit/components/unit.component'; |
10 | 9 |
|
... | ... | |
35 | 34 |
expectedRole: ['1', '0'] |
36 | 35 |
} |
37 | 36 |
}, { |
38 |
canActivate: [AuthGuard, RoleGuard], |
|
39 |
path: 'administration', |
|
40 |
component: AdministrationComponent, |
|
41 |
pathMatch: 'full', |
|
42 |
data: { |
|
43 |
expectedRole: ['0'] |
|
44 |
} |
|
45 |
},{ |
|
46 | 37 |
path: 'login', |
47 | 38 |
component: LoginComponent, |
48 | 39 |
pathMatch: 'full', |
src/app/app.module.ts | ||
---|---|---|
9 | 9 |
import {AuthModule} from './auth/auth.module'; |
10 | 10 |
import {LoginModule} from './login/login.module'; |
11 | 11 |
import {DashboardModule} from './dashboard/dashboard.module'; |
12 |
import {AdministrationModule} from './administration/administration.module'; |
|
13 | 12 |
import {SensorModule} from './sensor/sensor.module'; |
14 | 13 |
import {FontAwesomeModule} from '@fortawesome/angular-fontawesome'; |
15 | 14 |
import {UnitModule} from './unit/unit.module'; |
... | ... | |
29 | 28 |
AuthModule, |
30 | 29 |
LoginModule, |
31 | 30 |
DashboardModule, |
32 |
AdministrationModule, |
|
33 | 31 |
SensorModule, |
34 | 32 |
FontAwesomeModule, |
35 | 33 |
UnitModule, |
src/app/auth/interceptors/auth.interceptor.ts | ||
---|---|---|
23 | 23 |
) { |
24 | 24 |
} |
25 | 25 |
|
26 |
/** |
|
27 |
* Intercept every request to backend |
|
28 |
* @param request request |
|
29 |
* @param next next |
|
30 |
*/ |
|
26 | 31 |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { |
27 |
|
|
32 |
// check if data in cookies |
|
28 | 33 |
if (!this.cookieService.get(GlobalVariable.SESSION_ID) && !request.url.includes('ControllerServlet')) { |
29 | 34 |
console.log('No sessionid!'); |
30 | 35 |
this.cookieService.deleteAll(); |
... | ... | |
32 | 37 |
return of(null); |
33 | 38 |
} |
34 | 39 |
|
35 |
console.log('Sending request!', request); |
|
40 |
console.log('Sending request!', request.url);
|
|
36 | 41 |
return next.handle(request) |
37 | 42 |
.pipe( |
38 | 43 |
catchError(err => { |
src/app/auth/models/user.ts | ||
---|---|---|
3 | 3 |
import {UserInfo} from '../../shared/api/endpoints/models/user-info'; |
4 | 4 |
import {UserCookie} from '../../shared/api/endpoints/models/user-cookie'; |
5 | 5 |
|
6 |
/** |
|
7 |
* User state model |
|
8 |
*/ |
|
6 | 9 |
export interface User { |
7 | 10 |
userInfo?: UserInfo; |
8 | 11 |
isLoggedIn?: boolean; |
src/app/auth/services/auth.service.ts | ||
---|---|---|
24 | 24 |
) { |
25 | 25 |
} |
26 | 26 |
|
27 |
/** |
|
28 |
* Set state from saved cookies |
|
29 |
*/ |
|
27 | 30 |
setFromCookie() { |
28 | 31 |
const user: User = { |
29 | 32 |
userCookie: { |
... | ... | |
37 | 40 |
this.userState.setUser(user); |
38 | 41 |
} |
39 | 42 |
|
43 |
/** |
|
44 |
* Get user from state |
|
45 |
*/ |
|
40 | 46 |
getUser() { |
41 | 47 |
console.log('Auth Service'); |
42 | 48 |
if (!this.userState.getUser() && this.cookieService.get(GlobalVariable.SESSION_ID)) { |
... | ... | |
46 | 52 |
return this.userState.getUser(); |
47 | 53 |
} |
48 | 54 |
|
55 |
/** |
|
56 |
* Get user from state as observable |
|
57 |
*/ |
|
49 | 58 |
getUserState(): Observable<User> { |
50 | 59 |
return this.userState.getUser$(); |
51 | 60 |
} |
52 | 61 |
|
62 |
/** |
|
63 |
* Login process with backend call |
|
64 |
* @param loginInput login form |
|
65 |
*/ |
|
53 | 66 |
doLogin(loginInput): Observable<boolean> { |
54 | 67 |
return this.loginService.login$Response(loginInput) |
55 | 68 |
.pipe( |
... | ... | |
61 | 74 |
); |
62 | 75 |
} |
63 | 76 |
|
77 |
/** |
|
78 |
* Set user state, cookie and localStorage from server response |
|
79 |
* @param userCookie server response |
|
80 |
* @param username form username |
|
81 |
*/ |
|
64 | 82 |
setUserFromResponse(userCookie: UserCookie, username): UserCookie { |
65 | 83 |
console.log('Setting user from login!'); |
66 | 84 |
this.userState.setUser({ |
... | ... | |
71 | 89 |
return userCookie; |
72 | 90 |
} |
73 | 91 |
|
92 |
/** |
|
93 |
* Logout user, clear user state and redirect to login |
|
94 |
*/ |
|
74 | 95 |
doLogout() { |
75 | 96 |
this.userState.setUser(null); |
76 | 97 |
this.cookieService.deleteAll(); |
... | ... | |
79 | 100 |
this.cookieService.deleteAll(); |
80 | 101 |
} |
81 | 102 |
|
103 |
/** |
|
104 |
* Set localstorage and cookies |
|
105 |
* @param userCookie user obejct |
|
106 |
* @param username username from login form |
|
107 |
*/ |
|
82 | 108 |
setSessionStorage(userCookie: UserCookie, username) { |
83 | 109 |
localStorage.setItem(GlobalVariable.USER_NAME, username) |
84 | 110 |
localStorage.setItem(GlobalVariable.RIGHTS, userCookie.rightsID.toString()); |
src/app/auth/states/user.state.ts | ||
---|---|---|
1 | 1 |
import {Injectable} from '@angular/core'; |
2 | 2 |
import {BehaviorSubject, Observable} from 'rxjs'; |
3 | 3 |
import {User} from '../models/user'; |
4 |
import {AuthService} from '../services/auth.service'; |
|
5 | 4 |
import {LoginService} from '../../shared/api/endpoints/services/login.service'; |
6 | 5 |
import {ToastService} from '../../shared/services/toast.service'; |
7 | 6 |
|
... | ... | |
28 | 27 |
return this.userState$.getValue(); |
29 | 28 |
} |
30 | 29 |
|
30 |
/** |
|
31 |
* Get user, if not exists fetch from server |
|
32 |
* @param refresh force refresh user status from backend |
|
33 |
*/ |
|
31 | 34 |
getUser$(refresh: boolean = false): Observable<User> { |
32 | 35 |
if (this.userState$.getValue()){ |
33 | 36 |
this.loginService.getUserInfo$Response().subscribe(res => { |
src/app/dashboard/components/dashboard.component.html | ||
---|---|---|
7 | 7 |
<div [className]="'row dashboard-unit'"> |
8 | 8 |
<div class="col-md-6"><h3>{{ unit.unit.description}}</h3></div> |
9 | 9 |
<div class="col-md-6 text-right"> |
10 |
<p-button label="Sensors graph" icon="pi pi-chart-line" [routerLink]="['/dashboard/unit', unit.unit.unitId]"></p-button> |
|
10 |
<p-button label="Sensors graph" icon="pi pi-chart-line" [routerLink]="['/dashboard/unit', unit.unit.unitId]" [queryParams]="{unitDescription: unit.unit.description}"></p-button>
|
|
11 | 11 |
<div class="dashboard-button-separator"></div> |
12 | 12 |
<p-button icon="pi pi-cog" styleClass="p-button-warning" (click)="showItems($event, unit.unit); menu.toggle($event)"></p-button> |
13 | 13 |
<p-menu #menu [popup]="true" [model]="items" [appendTo]="'body'" [baseZIndex]="50"></p-menu> |
src/app/dashboard/components/dashboard.component.ts | ||
---|---|---|
1 |
import { Component, OnInit } from '@angular/core';
|
|
1 |
import {Component, OnDestroy, OnInit} from '@angular/core';
|
|
2 | 2 |
import {Group} from '../../shared/api/endpoints/models/group'; |
3 | 3 |
import {Drivers} from '../../shared/api/endpoints/models/drivers'; |
4 | 4 |
import {GeneralInfo} from '../../shared/api/endpoints/models/general-info'; |
... | ... | |
16 | 16 |
import {AuthService} from '../../auth/services/auth.service'; |
17 | 17 |
import {User} from '../../auth/models/user'; |
18 | 18 |
import {SensorType} from '../../shared/api/endpoints/models/sensor-type'; |
19 |
import {Subscription} from 'rxjs'; |
|
19 | 20 |
|
20 | 21 |
@Component({ |
21 | 22 |
selector: 'app-dashboard', |
22 | 23 |
templateUrl: './dashboard.component.html', |
23 | 24 |
styleUrls: ['./dashboard.component.scss'] |
24 | 25 |
}) |
25 |
export class DashboardComponent implements OnInit { |
|
26 |
export class DashboardComponent implements OnInit, OnDestroy {
|
|
26 | 27 |
|
27 | 28 |
loggedUser: User; |
28 | 29 |
items: MenuItem[] = []; |
... | ... | |
35 | 36 |
showInsertPositionPopup = false; |
36 | 37 |
phenomenons: Phenomenon[]; |
37 | 38 |
sensorTypes: SensorType[]; |
39 |
subscription: Subscription[] = []; |
|
38 | 40 |
|
39 | 41 |
constructor( |
40 | 42 |
private dataService: DataService, |
... | ... | |
45 | 47 |
private toastService: ToastService, |
46 | 48 |
private authService: AuthService |
47 | 49 |
) { |
50 |
this.initData(); |
|
51 |
} |
|
52 |
|
|
53 |
ngOnInit(): void { |
|
54 |
} |
|
55 |
|
|
56 |
/** |
|
57 |
* Unsubscribe after leaving |
|
58 |
*/ |
|
59 |
ngOnDestroy(): void { |
|
60 |
this.subscription.forEach(subs => subs.unsubscribe()); |
|
61 |
} |
|
62 |
|
|
63 |
/** |
|
64 |
* Get necessary data from backend |
|
65 |
*/ |
|
66 |
initData() { |
|
48 | 67 |
this.sensorService.getPhenomenons().subscribe( |
49 | 68 |
response => this.phenomenons = response |
50 | 69 |
); |
51 | 70 |
this.sensorService.getSensorTypes().subscribe( |
52 | 71 |
response => this.sensorTypes = response |
53 | 72 |
); |
54 |
} |
|
55 |
|
|
56 |
ngOnInit(): void { |
|
57 | 73 |
this.setUser(); |
58 | 74 |
this.getUnits(); |
59 | 75 |
} |
60 | 76 |
|
77 |
/** |
|
78 |
* Get user from user state |
|
79 |
*/ |
|
61 | 80 |
setUser(){ |
62 | 81 |
this.authService.getUserState().subscribe(res => { |
63 | 82 |
if(res){ |
... | ... | |
66 | 85 |
}); |
67 | 86 |
} |
68 | 87 |
|
88 |
/** |
|
89 |
* Get all units and theirs sensors from backend |
|
90 |
*/ |
|
69 | 91 |
getUnits() { |
70 | 92 |
this.dataService.getData().subscribe(data => { |
71 | 93 |
this.units = data; |
... | ... | |
73 | 95 |
}, err => this.toastService.showError(err.error.message)); |
74 | 96 |
} |
75 | 97 |
|
98 |
/** |
|
99 |
* Show edit unit |
|
100 |
* @param $event click event |
|
101 |
* @param unit edited unit |
|
102 |
*/ |
|
76 | 103 |
editUnitPopup($event: MouseEvent, unit: Unit) { |
77 | 104 |
this.editedUnit = unit; |
78 | 105 |
this.showEditUnitPopup = true; |
79 | 106 |
} |
80 | 107 |
|
108 |
/** |
|
109 |
* Show insert unit |
|
110 |
* @param $event click event |
|
111 |
* @param unit unit for sensor insert |
|
112 |
*/ |
|
81 | 113 |
insertSensorPopup($event: any, unit: Unit) { |
82 | 114 |
this.showInsertSensorPopup = true; |
83 | 115 |
this.editedUnit = unit; |
84 | 116 |
} |
85 | 117 |
|
118 |
/** |
|
119 |
* Detele unit confirmation |
|
120 |
* @param $event click event |
|
121 |
* @param unit unit to delete |
|
122 |
*/ |
|
86 | 123 |
deleteUnit($event: any, unit: Unit) { |
87 | 124 |
this.confirmationService.confirm({ |
88 | 125 |
message: 'Do you want to delete this unit?', |
... | ... | |
98 | 135 |
}); |
99 | 136 |
} |
100 | 137 |
|
138 |
/** |
|
139 |
* Send delete unit request to backend |
|
140 |
* @param unit to delete |
|
141 |
*/ |
|
101 | 142 |
processUnitDeletion(unit: Unit) { |
102 | 143 |
this.managementService.deleteUnit$Response({body: { |
103 | 144 |
unit: { |
... | ... | |
114 | 155 |
).toPromise().then().catch(err => this.toastService.showError(err.error.message)); |
115 | 156 |
} |
116 | 157 |
|
158 |
/** |
|
159 |
* Show menu items to manipulate with unit |
|
160 |
* @param $event click event |
|
161 |
* @param unit unit we want edit |
|
162 |
*/ |
|
117 | 163 |
showItems($event: any, unit: Unit) { |
118 | 164 |
$event.stopPropagation(); |
119 | 165 |
this.items = [ |
... | ... | |
132 | 178 |
] |
133 | 179 |
} |
134 | 180 |
|
181 |
/** |
|
182 |
* Add created unit to memory so we do not need call backend |
|
183 |
* @param inserted unit |
|
184 |
*/ |
|
135 | 185 |
addUnit(inserted: any) { |
136 | 186 |
const sensors: Sensor[] = []; |
137 | 187 |
inserted.sensors.forEach(sens => { |
... | ... | |
153 | 203 |
}) |
154 | 204 |
} |
155 | 205 |
|
206 |
/** |
|
207 |
* Add created sensors to unit in memory so we do not need call backend |
|
208 |
* @param inserted sensors |
|
209 |
*/ |
|
156 | 210 |
addSensors(inserted: any) { |
157 | 211 |
inserted.sensors.forEach(sens => { |
158 | 212 |
this.units.find(un => un.unit.unitId === inserted.unit.unit_id).sensors.push({ |
... | ... | |
166 | 220 |
}); |
167 | 221 |
} |
168 | 222 |
|
223 |
/** |
|
224 |
* Delete sensor from memory |
|
225 |
* @param unitId sensor unit |
|
226 |
* @param sensor sensor to delete |
|
227 |
*/ |
|
169 | 228 |
deleteSensor(unitId: number, sensor: Sensor) { |
170 | 229 |
this.units.find(unit => unit.unit.unitId === unitId).sensors = |
171 | 230 |
this.units.find(unit => unit.unit.unitId === unitId).sensors.filter(testedSensor => testedSensor.sensorId !== sensor.sensorId); |
172 | 231 |
} |
173 | 232 |
|
174 |
private insertPosition($event: any, unit: Unit) { |
|
233 |
/** |
|
234 |
* Show insert position popup |
|
235 |
* @param $event click event |
|
236 |
* @param unit unit to insert position for |
|
237 |
*/ |
|
238 |
insertPosition($event: any, unit: Unit) { |
|
175 | 239 |
$event.stopPropagation(); |
176 | 240 |
this.showInsertPositionPopup = true; |
177 | 241 |
this.editedUnit = unit; |
src/app/dashboard/components/position-insert-popup/position-insert-popup.component.ts | ||
---|---|---|
44 | 44 |
this.insertForm.reset(); |
45 | 45 |
} |
46 | 46 |
|
47 |
/** |
|
48 |
* Send insert position request to backend adn handle response. |
|
49 |
*/ |
|
47 | 50 |
processInsertion() { |
48 | 51 |
if (this.insertForm.valid) { |
49 | 52 |
const lat = this.insertForm.controls.lat.value; |
... | ... | |
67 | 70 |
} |
68 | 71 |
} |
69 | 72 |
|
73 |
/** |
|
74 |
* Close popup |
|
75 |
*/ |
|
70 | 76 |
close() { |
71 | 77 |
this.isVisibleChange.emit(false); |
72 | 78 |
} |
src/app/dashboard/components/sensor-insert-popup/sensor-insert-popup.component.ts | ||
---|---|---|
49 | 49 |
}); |
50 | 50 |
} |
51 | 51 |
|
52 |
/** |
|
53 |
* Prepare form object for sensor |
|
54 |
*/ |
|
52 | 55 |
createSensor(): FormGroup { |
53 | 56 |
return this.formBuilder.group({ |
54 | 57 |
sensorId: ['', Validators.required], |
... | ... | |
58 | 61 |
}); |
59 | 62 |
} |
60 | 63 |
|
64 |
/** |
|
65 |
* Add sensor to form |
|
66 |
*/ |
|
61 | 67 |
addSensor(): void { |
62 | 68 |
this.items = this.insertForm.get('sensors') as FormArray; |
63 | 69 |
this.items.push(this.createSensor()); |
64 | 70 |
this.sensors++; |
65 | 71 |
} |
66 | 72 |
|
73 |
/** |
|
74 |
* Remove last sensor from form |
|
75 |
*/ |
|
67 | 76 |
removeSensor() { |
68 | 77 |
this.items = this.insertForm.get('sensors') as FormArray; |
69 | 78 |
this.items.removeAt(this.items.length - 1); |
70 | 79 |
this.sensors--; |
71 | 80 |
} |
72 | 81 |
|
82 |
/** |
|
83 |
* Clearing form |
|
84 |
*/ |
|
73 | 85 |
clearFormArray() { |
74 | 86 |
const frmArray = this.insertForm?.get('sensors') as FormArray; |
75 | 87 |
if (frmArray) { |
... | ... | |
79 | 91 |
this.insertForm.reset(); |
80 | 92 |
} |
81 | 93 |
|
94 |
/** |
|
95 |
* Send insert sensors request to backend. Iterate over all sensors in form. |
|
96 |
*/ |
|
82 | 97 |
processSensorInsertion() { |
83 | 98 |
if (this.insertForm.valid) { |
84 | 99 |
const unit: InsertUnit = { |
src/app/dashboard/components/sensor-popup/sensor-popup.component.ts | ||
---|---|---|
34 | 34 |
ngOnInit(): void { |
35 | 35 |
} |
36 | 36 |
|
37 |
/** |
|
38 |
* Close popup |
|
39 |
*/ |
|
37 | 40 |
close() { |
38 | 41 |
this.isVisibleChange.emit(false); |
39 | 42 |
} |
... | ... | |
52 | 55 |
}, 0); |
53 | 56 |
} |
54 | 57 |
|
58 |
/** |
|
59 |
* Send update sensor request to backend. Creates object from form input. Handle response. |
|
60 |
*/ |
|
55 | 61 |
processSensorEdition() { |
56 | 62 |
if (this.insertForm.valid) { |
57 | 63 |
this.managementService.updateSensor$Response({body: { |
... | ... | |
81 | 87 |
} |
82 | 88 |
} |
83 | 89 |
|
84 |
private changeSensor() { |
|
90 |
/** |
|
91 |
* Change sensor data to memory |
|
92 |
*/ |
|
93 |
changeSensor() { |
|
85 | 94 |
this.sensor.sensorType = this.insertForm.controls.sensorType.value; |
86 | 95 |
this.sensor.sensorName = this.insertForm.controls.sensorName.value; |
87 | 96 |
this.sensor.phenomenon.phenomenonId = this.insertForm.controls.phenomenon.value; |
src/app/dashboard/components/sensors/sensors.component.html | ||
---|---|---|
8 | 8 |
<button pButton type="button" label="View graph" [routerLink]="['/dashboard/unit', unit.unitId, 'sensor', sensor.sensorId]" [queryParams]="{unitName: unit.description}" title="Sensor" icon="pi pi-chart-line"></button> |
9 | 9 |
<ng-container *ngIf="loggedUser?.userInfo?.rightsId == 0 || loggedUser?.userInfo?.rightsId == 1"> |
10 | 10 |
<div class="dashboard-button-separator"></div> |
11 |
<button pButton type="button" label="Edit sensor" icon="pi pi-cog" (click)="editSensor($event, sensor)" [className]="'p-button-warning'"></button>
|
|
12 |
<button pButton type="button" label="Delete sensor" icon="pi pi-times" (click)="deleteSensor($event, sensor)" [className]="'p-button-danger'"></button>
|
|
11 |
<p-button icon="pi pi-cog" styleClass="p-button-warning" (click)="showItems($event, sensor); menu.toggle($event)"></p-button>
|
|
12 |
<p-menu #menu [popup]="true" [model]="items" [appendTo]="'body'" [baseZIndex]="50"></p-menu>
|
|
13 | 13 |
</ng-container> |
14 | 14 |
</div> |
15 | 15 |
</div> |
src/app/dashboard/components/sensors/sensors.component.ts | ||
---|---|---|
1 | 1 |
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; |
2 | 2 |
import {Sensor} from '../../../shared/api/endpoints/models/sensor'; |
3 |
import {ConfirmationService} from 'primeng/api'; |
|
3 |
import {ConfirmationService, MenuItem} from 'primeng/api';
|
|
4 | 4 |
import {ManagementService} from '../../../shared/api/endpoints/services/management.service'; |
5 | 5 |
import {map} from 'rxjs/operators'; |
6 | 6 |
import {HttpResponse} from '@angular/common/http'; |
... | ... | |
24 | 24 |
@Input() sensorTypes: SensorType[]; |
25 | 25 |
showSensorPopup = false; |
26 | 26 |
editedSensor: Sensor; |
27 |
items: MenuItem[] = []; |
|
28 |
|
|
27 | 29 |
constructor( |
28 | 30 |
private confirmationService: ConfirmationService, |
29 | 31 |
private managementService: ManagementService, |
... | ... | |
33 | 35 |
ngOnInit(): void { |
34 | 36 |
} |
35 | 37 |
|
38 |
/** |
|
39 |
* Show menu items to manipulate with sensor |
|
40 |
* @param $event click event |
|
41 |
* @param sensor sensor we want edit |
|
42 |
*/ |
|
43 |
showItems($event: any, sensor: Sensor) { |
|
44 |
$event.stopPropagation(); |
|
45 |
this.items = [ |
|
46 |
{label: 'Edit sensor', icon: 'pi pi-cog', command: () => { |
|
47 |
this.editSensor($event, sensor); |
|
48 |
}}, |
|
49 |
{label: 'Delete sensor', icon: 'pi pi-times', command: () => { |
|
50 |
this.deleteSensor($event, sensor); |
|
51 |
}} |
|
52 |
] |
|
53 |
} |
|
54 |
|
|
55 |
/** |
|
56 |
* Show edit sensor popup |
|
57 |
* @param $event click event |
|
58 |
* @param sensor sensor to edit |
|
59 |
*/ |
|
36 | 60 |
editSensor($event: MouseEvent, sensor: Sensor) { |
37 | 61 |
$event.stopPropagation(); |
38 | 62 |
this.editedSensor = sensor; |
39 | 63 |
this.showSensorPopup = true; |
40 | 64 |
} |
41 | 65 |
|
66 |
/** |
|
67 |
* Selete sensor confirmation |
|
68 |
* @param $event click event |
|
69 |
* @param sensor sensor to delete |
|
70 |
*/ |
|
42 | 71 |
deleteSensor($event: any, sensor: Sensor) { |
43 | 72 |
this.confirmationService.confirm({ |
44 | 73 |
message: 'Do you want to delete this sensor?', |
... | ... | |
54 | 83 |
}); |
55 | 84 |
} |
56 | 85 |
|
86 |
/** |
|
87 |
* Send deletion request to backend. Handle response. |
|
88 |
* @param sensor to delete |
|
89 |
*/ |
|
57 | 90 |
processSensorDeletion(sensor: Sensor) { |
58 | 91 |
this.managementService.deleteSensor$Response({body: { |
59 | 92 |
unit: { |
src/app/dashboard/components/unit-popup/unit-popup.component.ts | ||
---|---|---|
36 | 36 |
ngOnInit(): void { |
37 | 37 |
} |
38 | 38 |
|
39 |
|
|
39 |
/** |
|
40 |
* Send insert unit request to backend and handle it |
|
41 |
*/ |
|
40 | 42 |
saveUnit() { |
41 | 43 |
if (this.insertForm.controls.unitDescription.value && this.insertForm.controls.unitDescription.value !== this.unit.description) { |
42 | 44 |
this.unit.description = this.insertForm.controls.unitDescription.value; |
src/app/login/components/login.component.ts | ||
---|---|---|
1 |
import {Component, OnInit} from '@angular/core'; |
|
1 |
import {Component, OnDestroy, OnInit} from '@angular/core';
|
|
2 | 2 |
import {FormBuilder, FormGroup, Validators} from '@angular/forms'; |
3 | 3 |
import {switchMap} from 'rxjs/operators'; |
4 | 4 |
import {of, Subscription} from 'rxjs'; |
... | ... | |
10 | 10 |
templateUrl: './login.component.html', |
11 | 11 |
styleUrls: ['./login.component.scss'] |
12 | 12 |
}) |
13 |
export class LoginComponent implements OnInit { |
|
13 |
export class LoginComponent implements OnInit, OnDestroy {
|
|
14 | 14 |
|
15 | 15 |
loginForm: FormGroup; |
16 | 16 |
subscription: Subscription[] = []; |
... | ... | |
22 | 22 |
) { |
23 | 23 |
} |
24 | 24 |
|
25 |
/** |
|
26 |
* Unsubscribe after leaving |
|
27 |
*/ |
|
28 |
ngOnDestroy(): void { |
|
29 |
this.subscription.forEach(subs => subs.unsubscribe()); |
|
30 |
} |
|
31 |
|
|
25 | 32 |
ngOnInit(): void { |
26 | 33 |
this.loginForm = this.formBuilder.group({ |
27 | 34 |
username: ['', [Validators.required]], |
... | ... | |
30 | 37 |
this.userRedirect(); |
31 | 38 |
} |
32 | 39 |
|
40 |
/** |
|
41 |
* Process login |
|
42 |
*/ |
|
33 | 43 |
doLogin(): void { |
34 | 44 |
if (this.loginForm.valid) { |
35 | 45 |
this.subscription[2] = this.authService.doLogin({ |
... | ... | |
38 | 48 |
}) |
39 | 49 |
.pipe( |
40 | 50 |
switchMap(res => { |
41 |
console.log(res); |
|
42 | 51 |
if (res) { |
43 | 52 |
console.log('Login getUserState'); |
44 | 53 |
return this.authService.getUserState(); |
... | ... | |
48 | 57 |
}) |
49 | 58 |
).subscribe( |
50 | 59 |
res => { |
51 |
console.log(res); |
|
52 | 60 |
if (res) { |
53 | 61 |
this.subscription[2].unsubscribe(); |
54 | 62 |
this.router.navigate(['/dashboard']) |
... | ... | |
58 | 66 |
} |
59 | 67 |
} |
60 | 68 |
|
69 |
/** |
|
70 |
* If user already logged with valid sessionId redirect to dashboard |
|
71 |
*/ |
|
61 | 72 |
userRedirect(): void { |
62 | 73 |
console.log('Login redirect'); |
63 | 74 |
if (this.authService.getUser()){ |
64 |
console.log('Redirect to dashboard!'); |
|
65 | 75 |
this.router.navigate(['/dashboard']); |
66 | 76 |
} |
67 | 77 |
} |
src/app/sensor/components/sensor.component.html | ||
---|---|---|
3 | 3 |
<div class="container graph"> |
4 | 4 |
<div class="row-2"> |
5 | 5 |
<div class="col-xs-3"> |
6 |
<h5><span class="text-color-sensor-unit">Unit name: <a [routerLink]="['/dashboard/unit', unitId]">{{unitName}}</a></span></h5> |
|
6 |
<h5><span class="text-color-sensor-unit">Unit name: <a [routerLink]="['/dashboard/unit', unitId]">{{unitDescription}}</a></span></h5> |
|
7 |
</div> |
|
8 |
<div class="col-xs-3"> |
|
9 |
<h5><span class="text-color-sensor-unit">Sensor id: {{sensor?.sensorId}}</span></h5> |
|
7 | 10 |
</div> |
8 | 11 |
<div class="col-xs-3"> |
9 | 12 |
<h5><span class="text-color-sensor-unit">Sensor name: {{sensor?.sensorName}}</span></h5> |
... | ... | |
34 | 37 |
</div> |
35 | 38 |
</div> |
36 | 39 |
<div class="col-1"></div> |
37 |
<div *ngIf="showAggregation" class="col-xs-3">
|
|
40 |
<div class="col-xs-3"> |
|
38 | 41 |
<div class="input-group form-group"> |
39 |
<!--<div class="input-group-prepend"> |
|
40 |
<span class="input-group-text">Aggregation</span> |
|
41 |
</div>--> |
|
42 |
<p-listbox [options]="aggregationFunction" [(ngModel)]="selectedAggregationFunction" optionLabel="name" optionValue="code"></p-listbox> |
|
42 |
<p-listbox *ngIf="showAggregation" [options]="aggregationFunction" [(ngModel)]="selectedAggregationFunction" optionLabel="name" optionValue="code"></p-listbox> |
|
43 | 43 |
</div> |
44 | 44 |
</div> |
45 | 45 |
<div class="col-1"></div> |
src/app/sensor/components/sensor.component.ts | ||
---|---|---|
1 |
import {Component, OnInit} from '@angular/core'; |
|
1 |
import {Component, OnDestroy, OnInit} from '@angular/core';
|
|
2 | 2 |
import {ActivatedRoute} from '@angular/router'; |
3 | 3 |
import * as moment from 'moment-timezone'; |
4 | 4 |
import {AnalyticsService} from '../../shared/api/endpoints/services/analytics.service'; |
... | ... | |
10 | 10 |
import {ToastService} from '../../shared/services/toast.service'; |
11 | 11 |
import {Sensor} from '../../shared/api/endpoints/models/sensor'; |
12 | 12 |
import {SensorsService} from '../../shared/api/endpoints/services/sensors.service'; |
13 |
import {Subscription} from 'rxjs'; |
|
13 | 14 |
|
14 | 15 |
@Component({ |
15 | 16 |
selector: 'app-sensor', |
16 | 17 |
templateUrl: './sensor.component.html', |
17 | 18 |
styleUrls: ['./sensor.component.scss'] |
18 | 19 |
}) |
19 |
|
|
20 |
|
|
21 |
|
|
22 |
export class SensorComponent implements OnInit { |
|
20 |
export class SensorComponent implements OnInit, OnDestroy { |
|
23 | 21 |
|
24 | 22 |
sensorId: number; |
25 | 23 |
unitId: number; |
... | ... | |
32 | 30 |
selectedAggregationFunction = 'HOUR'; |
33 | 31 |
sensor: Sensor; |
34 | 32 |
dateChanged = false; |
35 |
unitName: string;
|
|
33 |
unitDescription: string;
|
|
36 | 34 |
today: Date = moment().toDate(); |
35 |
subscription: Subscription[] = []; |
|
37 | 36 |
|
38 | 37 |
constructor( |
39 | 38 |
private activatedRoute: ActivatedRoute, |
... | ... | |
58 | 57 |
getInitData() { |
59 | 58 |
this.route.queryParams.subscribe(params => { |
60 | 59 |
if(params.unitName) { |
61 |
this.unitName = params.unitName;
|
|
60 |
this.unitDescription = params.unitName;
|
|
62 | 61 |
} |
63 | 62 |
}); |
64 | 63 |
this.sensorId = parseInt(this.activatedRoute.snapshot.paramMap.get('sensorId'), 10); |
... | ... | |
71 | 70 |
]; |
72 | 71 |
} |
73 | 72 |
|
73 |
/** |
|
74 |
* Unsubscribe after leaving |
|
75 |
*/ |
|
76 |
ngOnDestroy(): void { |
|
77 |
this.subscription.forEach(subs => subs.unsubscribe()); |
|
78 |
} |
|
79 |
|
|
74 | 80 |
ngOnInit(): void { |
75 | 81 |
} |
76 | 82 |
|
src/app/shared/models/vegaModel.ts | ||
---|---|---|
1 |
/* tslint:disable */ |
|
2 |
/* eslint-disable */ |
|
3 |
export interface VegaModel { |
|
4 |
sensordId?: string, |
|
5 |
data?: [] |
|
6 |
} |
src/app/shared/nav-bar/components/nav-bar.component.ts | ||
---|---|---|
35 | 35 |
this.setUser(); |
36 | 36 |
} |
37 | 37 |
|
38 |
/** |
|
39 |
* Get user from state after logged |
|
40 |
*/ |
|
38 | 41 |
setUser(){ |
39 | 42 |
this.authService.getUserState().subscribe(res => { |
40 | 43 |
if(res){ |
... | ... | |
43 | 46 |
}); |
44 | 47 |
} |
45 | 48 |
|
49 |
/** |
|
50 |
* Show insert unit popup |
|
51 |
*/ |
|
46 | 52 |
insertUnitPopup() { |
47 | 53 |
this.sensorService.getPhenomenons().subscribe( |
48 | 54 |
response => this.phenomenons = response |
... | ... | |
54 | 60 |
this.authService.doLogout(); |
55 | 61 |
} |
56 | 62 |
|
63 |
/** |
|
64 |
* Unsubscribe after leaving |
|
65 |
*/ |
|
57 | 66 |
ngOnDestroy(): void { |
58 | 67 |
this.subscription.forEach(subs => subs.unsubscribe()); |
59 | 68 |
} |
60 | 69 |
|
70 |
/** |
|
71 |
* Show add user popup |
|
72 |
*/ |
|
61 | 73 |
addUser() { |
62 | 74 |
this.showAddUserPopup = true; |
63 | 75 |
} |
64 | 76 |
|
77 |
/** |
|
78 |
* Emit inserted unit to add it to units |
|
79 |
* @param inserted inserted unit |
|
80 |
*/ |
|
65 | 81 |
addUnit(inserted: any) { |
66 | 82 |
this.emitNewUnit.emit(inserted); |
67 | 83 |
} |
src/app/shared/nav-bar/components/unit-insert-popup/unit-insert-popup.component.ts | ||
---|---|---|
55 | 55 |
}); |
56 | 56 |
} |
57 | 57 |
|
58 |
/** |
|
59 |
* Create formBuilder for sensor |
|
60 |
*/ |
|
58 | 61 |
createSensor(): FormGroup { |
59 | 62 |
return this.formBuilder.group({ |
60 | 63 |
sensorId: ['', Validators.required], |
... | ... | |
64 | 67 |
}); |
65 | 68 |
} |
66 | 69 |
|
70 |
/** |
|
71 |
* Add sensor to form |
|
72 |
*/ |
|
67 | 73 |
addSensor(): void { |
68 | 74 |
this.items = this.insertForm.get('sensors') as FormArray; |
69 | 75 |
this.items.push(this.createSensor()); |
70 | 76 |
this.sensors++; |
71 | 77 |
} |
72 | 78 |
|
79 |
/** |
|
80 |
* Remove last sensor from form |
|
81 |
*/ |
|
73 | 82 |
removeSensor() { |
74 | 83 |
this.items = this.insertForm.get('sensors') as FormArray; |
75 | 84 |
this.items.removeAt(this.items.length - 1); |
76 | 85 |
this.sensors--; |
77 | 86 |
} |
78 | 87 |
|
88 |
/** |
|
89 |
* Clear form |
|
90 |
*/ |
|
79 | 91 |
clearFormArray() { |
80 | 92 |
const frmArray = this.insertForm?.get('sensors') as FormArray; |
81 | 93 |
if (frmArray) { |
... | ... | |
84 | 96 |
this.insertForm.reset(); |
85 | 97 |
} |
86 | 98 |
|
99 |
/** |
|
100 |
* Insert unit with sensor and position if form valid |
|
101 |
*/ |
|
87 | 102 |
processInsertion() { |
88 | 103 |
if (this.insertForm.valid) { |
89 | 104 |
const lat = this.insertForm.controls.lat.value; |
... | ... | |
95 | 110 |
const sensors: InsertSensor[] = []; |
96 | 111 |
const frmArray = this.insertForm?.get('sensors') as FormArray; |
97 | 112 |
|
113 |
// get sensors from form |
|
98 | 114 |
frmArray.controls.forEach(control => { |
99 | 115 |
const sensor: InsertSensor = { |
100 | 116 |
sensor_id: control.get('sensorId').value, |
... | ... | |
107 | 123 |
sensors.push(sensor); |
108 | 124 |
}); |
109 | 125 |
|
126 |
// insert unit |
|
110 | 127 |
this.managementService.insertUnit$Response({ body: { unit, sensors}}).pipe( |
111 | 128 |
map((response: HttpResponse<any>) => { |
112 | 129 |
if (response.status === 200) { |
130 |
// insert position |
|
113 | 131 |
this.sensorService.insertPosition$Response( {lat, lon, unit_id: this.insertForm.controls.unitId.value, date: moment().format('yyyy-MM-DD HH:mm:ssZZ')}).pipe( |
114 | 132 |
map((response2: HttpResponse<any>) => { |
115 | 133 |
if (response2.status === 200) { |
... | ... | |
119 | 137 |
this.close(); |
120 | 138 |
} else { |
121 | 139 |
this.toastService.showError('Unit insertion ' + response2.body.unitId + ' caused error! Wrong position!'); |
140 |
// if position not added delete unit |
|
122 | 141 |
this.managementService.deleteUnit({body: {unit}}).toPromise().then().catch( |
123 | 142 |
err => this.toastService.showError(err.error.message)); |
124 | 143 |
} |
125 | 144 |
}) |
126 | 145 |
).toPromise().then().catch(err => this.toastService.showError(err.error.message)); |
127 | 146 |
} else { |
147 |
this.toastService.showError('Unit insertion ' + response.body.unitId + ' caused error!'); |
|
128 | 148 |
} |
129 | 149 |
}) |
130 | 150 |
).toPromise().then().catch(err => this.toastService.showError(err.error.message)); |
src/app/shared/nav-bar/components/user-insert-popup/user-insert-popup.component.ts | ||
---|---|---|
1 |
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; |
|
1 |
import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';
|
|
2 | 2 |
import {map, tap} from 'rxjs/operators'; |
3 | 3 |
import {GroupService} from '../../../api/endpoints/services/group.service'; |
4 | 4 |
import {Group} from '../../../api/endpoints/models/group'; |
... | ... | |
7 | 7 |
import {FormBuilder, FormGroup, Validators} from '@angular/forms'; |
8 | 8 |
import {HttpResponse} from '@angular/common/http'; |
9 | 9 |
import {ToastService} from '../../../services/toast.service'; |
10 |
import {Subscription} from 'rxjs'; |
|
10 | 11 |
|
11 | 12 |
@Component({ |
12 | 13 |
selector: 'app-user-insert-popup', |
13 | 14 |
templateUrl: './user-insert-popup.component.html', |
14 | 15 |
styleUrls: ['./user-insert-popup.component.scss'] |
15 | 16 |
}) |
16 |
export class UserInsertPopupComponent implements OnInit { |
|
17 |
export class UserInsertPopupComponent implements OnInit, OnDestroy {
|
|
17 | 18 |
|
18 | 19 |
groups: Group[]; |
19 | 20 |
rights: Right[]; |
20 | 21 |
insertForm: FormGroup; |
22 |
subscription: Subscription[] = []; |
|
21 | 23 |
@Input() isVisible; |
22 | 24 |
@Output() isVisibleChange: EventEmitter<boolean> = new EventEmitter<boolean>(); |
23 | 25 |
|
... | ... | |
34 | 36 |
ngOnInit(): void { |
35 | 37 |
} |
36 | 38 |
|
39 |
/** |
|
40 |
* Unsubscribe after leaving |
|
41 |
*/ |
|
42 |
ngOnDestroy(): void { |
|
43 |
this.subscription.forEach(subs => subs.unsubscribe()); |
|
44 |
} |
|
45 |
|
|
37 | 46 |
getGroups() { |
38 | 47 |
this.groupService.getGroups({Operation: 'GetGroups'}).pipe( |
39 | 48 |
tap(data => this.groups = data) |
... | ... | |
46 | 55 |
).subscribe(); |
47 | 56 |
} |
48 | 57 |
|
58 |
/** |
|
59 |
* Close popup |
|
60 |
*/ |
|
49 | 61 |
close() { |
50 | 62 |
this.isVisibleChange.emit(false); |
51 | 63 |
} |
52 | 64 |
|
65 |
/** |
|
66 |
* If valid form send request with new user to server |
|
67 |
*/ |
|
53 | 68 |
saveUser() { |
54 | 69 |
if (this.insertForm.valid) { |
55 | 70 |
this.administrationService.createUser$Response({body: { |
src/app/shared/services/toast.service.ts | ||
---|---|---|
11 | 11 |
) { |
12 | 12 |
} |
13 | 13 |
|
14 |
/** |
|
15 |
* Error message |
|
16 |
* @param err error |
|
17 |
*/ |
|
14 | 18 |
showError(err: any) { |
15 | 19 |
this.messageService.add({key: 'mainToast', severity:'error', summary: 'Unsuccessful!', detail: err}); |
16 | 20 |
} |
17 | 21 |
|
22 |
/** |
|
23 |
* Show warning NoData message |
|
24 |
*/ |
|
18 | 25 |
showWarningNoData() { |
19 | 26 |
this.messageService.add({key: 'mainToast', severity:'warn', summary: 'No data!', detail: 'Can not display any data for given interval and aggregation!'}); |
20 | 27 |
} |
21 | 28 |
|
29 |
/** |
|
30 |
* Show success request message |
|
31 |
*/ |
|
22 | 32 |
showSuccess() { |
23 | 33 |
this.messageService.add({key: 'mainToast', severity:'success', summary: 'Success!', detail: 'Successful request!'}); |
24 | 34 |
} |
25 | 35 |
|
36 |
/** |
|
37 |
* Show message as success |
|
38 |
* @param message message string |
|
39 |
*/ |
|
26 | 40 |
showSuccessMessage(message: any) { |
27 | 41 |
this.messageService.add({key: 'mainToast', severity:'success', summary: 'Success!', detail: message}); |
28 | 42 |
} |
29 | 43 |
|
44 |
/** |
|
45 |
* Show operation rejected |
|
46 |
*/ |
|
30 | 47 |
operationRejected() { |
31 | 48 |
this.messageService.add({key: 'mainToast', severity:'warn', summary: 'Reject!', detail: 'Operation rejected!'}); |
32 | 49 |
} |
src/app/unit/components/unit.component.html | ||
---|---|---|
2 | 2 |
|
3 | 3 |
<div class="container"> |
4 | 4 |
<div class="row-2"> |
5 |
<h5><span class="text-color-sensor-unit">Unit ID: {{unitId}}</span></h5>
|
|
5 |
<h5><span class="text-color-sensor-unit">Unit description: {{unitDescription}}</span></h5>
|
|
6 | 6 |
</div> |
7 | 7 |
<div class="row"> |
8 | 8 |
<div class="col"> |
9 | 9 |
<div class="input-group form-group"> |
10 | 10 |
<div class="input-group-prepend"> |
11 |
<span class="input-group-text">From</span>
|
|
11 |
<span class="input-group-text text-color-date background-date-color"><i class="fa fa-calendar-alt" aria-hidden="false"></i>From</span>
|
|
12 | 12 |
</div> |
13 |
<p-calendar [style]="{'width':'100%'}" [inputStyle]="{'width':'100%'}" [(ngModel)]="from" [showTime]="true" (onSelect)="showGraph()" [maxDate]="today" showButtonBar="true"></p-calendar>
|
|
13 |
<p-calendar [style]="{'width':'100%'}" [inputStyle]="{'width':'100%'}" [(ngModel)]="from" [showTime]="true" (onSelect)="aggregationShow()" [maxDate]="today" showButtonBar="true"></p-calendar>
|
|
14 | 14 |
</div> |
15 | 15 |
</div> |
16 | 16 |
<div class="col"> |
17 | 17 |
<div class="input-group form-group"> |
18 | 18 |
<div class="input-group-prepend"> |
19 |
<span class="input-group-text">To</span>
|
|
19 |
<span class="input-group-text text-color-date background-date-color"><i class="fa fa-calendar-alt" aria-hidden="false"></i>To</span>
|
|
20 | 20 |
</div> |
21 |
<p-calendar [style]="{'width':'100%'}" [inputStyle]="{'width':'100%'}" [(ngModel)]="to" [showTime]="true" (onSelect)="showGraph()" [maxDate]="today" showButtonBar="true"></p-calendar>
|
|
21 |
<p-calendar [style]="{'width':'100%'}" [inputStyle]="{'width':'100%'}" [(ngModel)]="to" [showTime]="true" (onSelect)="aggregationShow()" [maxDate]="today" showButtonBar="true"></p-calendar>
|
|
22 | 22 |
</div> |
23 | 23 |
</div> |
24 |
<div *ngIf="showAggregation" class="col">
|
|
24 |
<div class="col"> |
|
25 | 25 |
<div class="input-group form-group"> |
26 |
<div class="input-group-prepend">
|
|
27 |
<span class="input-group-text">Aggregation</span>
|
|
26 |
<div class="input-group form-group">
|
|
27 |
<p-listbox *ngIf="showAggregation" [options]="aggregationFunction" [(ngModel)]="selectedAggregationFunction" optionLabel="name" optionValue="code"></p-listbox>
|
|
28 | 28 |
</div> |
29 |
<p-listbox [options]="aggregationFunction" [(ngModel)]="selectedAggregationFunction" optionLabel="name" optionValue="code" (onClick)="showGraph()" ></p-listbox> |
|
30 | 29 |
</div> |
31 | 30 |
</div> |
31 |
<div class="col-xs-3"> |
|
32 |
<p-button *ngIf="dateChanged" label="Get data" icon="pi pi-cog" styleClass="p-button-success" (click)="showGraph()"></p-button> |
|
33 |
</div> |
|
32 | 34 |
</div> |
33 | 35 |
|
34 | 36 |
<ng-container *ngFor="let group of sensorGroups"> |
35 | 37 |
<div class="row"> |
36 |
Group of sensors: |
|
38 |
Group of |
|
39 |
<ng-container *ngFor="let sensorType of sensorTypes"> |
|
40 |
<ng-container *ngIf="sensorType.sensorId.toString().slice(0, 5) === group"> |
|
41 |
{{sensorType.sensorType}} |
|
42 |
</ng-container> |
|
43 |
</ng-container> |
|
44 |
sensors: |
|
37 | 45 |
<ng-container *ngFor="let sensor of sensors"> |
38 | 46 |
<div *ngIf="sensor.sensorId.toString().slice(0, 5) === group" class="p-field-checkbox"> |
39 | 47 |
<p-checkbox name="{{group}}" [value]="sensor.sensorId.toString()" [(ngModel)]="selectedSensors" [inputId]="sensor.sensorId.toString()" (onChange)="addSensorToGraph(sensor.sensorId.toString(), $event)"></p-checkbox> |
src/app/unit/components/unit.component.ts | ||
---|---|---|
1 |
import {Component, OnInit} from '@angular/core'; |
|
1 |
import {Component, OnDestroy, OnInit} from '@angular/core';
|
|
2 | 2 |
import {ActivatedRoute} from '@angular/router'; |
3 | 3 |
import {AnalyticsService} from '../../shared/api/endpoints/services/analytics.service'; |
4 | 4 |
import {map, tap} from 'rxjs/operators'; |
... | ... | |
10 | 10 |
import {ToastService} from '../../shared/services/toast.service'; |
11 | 11 |
import {Sensor} from '../../shared/api/endpoints/models/sensor'; |
12 | 12 |
import {ObservationService} from '../../shared/api/endpoints/services/observation.service'; |
13 |
import {SensorType} from '../../shared/api/endpoints/models/sensor-type'; |
|
14 |
import {Subscription} from 'rxjs'; |
|
13 | 15 |
|
14 | 16 |
|
15 | 17 |
@Component({ |
... | ... | |
17 | 19 |
templateUrl: './unit.component.html', |
18 | 20 |
styleUrls: ['./unit.component.scss'] |
19 | 21 |
}) |
20 |
export class UnitComponent implements OnInit { |
|
22 |
export class UnitComponent implements OnInit, OnDestroy {
|
|
21 | 23 |
|
22 | 24 |
preselectedSensors: string; |
23 | 25 |
unitId: number; |
24 | 26 |
viewCount = 0; |
25 | 27 |
data = []; |
26 | 28 |
time = []; |
27 |
from: Date; |
|
28 |
to: Date; |
|
29 |
today: Date; |
|
29 |
from: Date = moment().hour(0).minutes(0).subtract(7, 'days').toDate();
|
|
30 |
to: Date = moment().toDate();
|
|
31 |
today: Date = moment().toDate();
|
|
30 | 32 |
analyticsData: any[] = []; |
31 | 33 |
observationsData: any[] = []; |
32 | 34 |
sensorGroups = []; |
... | ... | |
36 | 38 |
aggregationFunction: AggregationModel[]; |
37 | 39 |
selectedAggregationFunction = 'DAY'; |
38 | 40 |
useAnalyticsData = false; |
41 |
dateChanged = false; |
|
42 |
sensorTypes: SensorType[]; |
|
43 |
unitDescription: string; |
|
44 |
subscription: Subscription[] = []; |
|
39 | 45 |
|
40 | 46 |
constructor( |
41 | 47 |
private activatedRoute: ActivatedRoute, |
42 | 48 |
private analyticsService: AnalyticsService, |
43 | 49 |
private sensorService: SensorsService, |
44 | 50 |
private toastService: ToastService, |
45 |
private observationService: ObservationService |
|
51 |
private observationService: ObservationService, |
|
52 |
private route: ActivatedRoute, |
|
46 | 53 |
) { |
47 |
this.unitId = parseInt(this.activatedRoute.snapshot.paramMap.get('unitId'), 10); |
|
48 |
this.aggregationFunction = [ |
|
49 |
{name: 'Hour', code: 'HOUR'}, |
|
50 |
{name: 'Day', code: 'DAY'}, |
|
51 |
{name: 'Month', code: 'MONTH'}, |
|
52 |
{name: 'Year', code: 'YEAR'} |
|
53 |
]; |
|
54 |
this.today = moment().toDate(); |
|
54 |
this.getInitData(); |
|
55 |
// get unit sensors and prepare them for view |
|
55 | 56 |
this.sensorService.getUnitSensors({unit_id: this.unitId}).pipe( |
56 | 57 |
tap(sens => { |
57 | 58 |
this.sensors = sens; |
... | ... | |
61 | 62 |
if (this.sensors && this.sensors.length > 0) { |
62 | 63 |
this.sensors.forEach(sensor => { |
63 | 64 |
const sensorType = sensor.sensorId.toString().slice(0, 5); |
64 |
if (!this.sensorGroups.some(group => group === sensorType)) { |
|
65 |
if (!this.sensorGroups.some(group => group === sensorType)) { // create sensor groups only for unit sensors
|
|
65 | 66 |
this.sensorGroups.push(sensorType); |
66 | 67 |
setTimeout(() => { |
67 |
// GraphLoader.getAnalyticsGraph(null, null, null, '#vega_container_' + sensor.sensorId.toString().slice(0, 5)); |
|
68 |
GraphLoader.getGraph(null, null, null, '#vega_container_' + sensor.sensorId.toString().slice(0, 5),null ); |
|
68 |
GraphLoader.getGraph(null, null, null, '#vega_container_' + sensor.sensorId.toString().slice(0, 5),null); |
|
69 | 69 |
}, 0); |
70 | 70 |
} |
71 | 71 |
}); |
... | ... | |
74 | 74 |
).toPromise().then(); |
75 | 75 |
} |
76 | 76 |
|
77 |
ngOnInit(): void { |
|
77 |
/** |
|
78 |
* Unsubscribe after leaving |
|
79 |
*/ |
|
80 |
ngOnDestroy(): void { |
|
81 |
this.subscription.forEach(subs => subs.unsubscribe()); |
|
78 | 82 |
} |
79 | 83 |
|
80 |
showGraph(changedDate: boolean = true, changedSensor: string = null) { |
|
81 |
const range: Date[] = [moment().subtract(7, 'days').toDate(), moment().toDate()]; |
|
84 |
/** |
|
85 |
* Sets up default data |
|
86 |
*/ |
|
87 |
getInitData() { |
|
88 |
this.route.queryParams.subscribe(params => { |
|
89 |
if(params.unitDescription) { |
|
90 |
this.unitDescription = params.unitDescription; |
|
91 |
} |
|
92 |
}); |
|
93 |
this.sensorService.getSensorTypes().toPromise().then(types => this.sensorTypes = types); |
|
94 |
this.unitId = parseInt(this.activatedRoute.snapshot.paramMap.get('unitId'), 10); |
|
95 |
this.aggregationFunction = [ |
|
96 |
{name: 'Hour', code: 'HOUR'}, |
|
97 |
{name: 'Day', code: 'DAY'}, |
|
98 |
{name: 'Month', code: 'MONTH'}, |
|
99 |
{name: 'Year', code: 'YEAR'} |
|
100 |
]; |
|
101 |
} |
|
82 | 102 |
|
83 |
if (this.from && !this.to || !this.from && this.to) { |
|
84 |
return; |
|
85 |
} |
|
103 |
ngOnInit(): void { |
|
104 |
} |
|
86 | 105 |
|
87 |
if (this.from && this.to) { |
|
88 |
range[0] = this.from; |
|
89 |
range[1] = this.to; |
|
90 |
} |
|
106 |
/** |
|
107 |
* Shows aggregation select box and get data button |
|
108 |
*/ |
|
109 |
aggregationShow() { |
|
110 |
this.dateChanged = true; |
|
111 |
this.showAggregation = moment(this.to).diff(moment(this.from), 'days') > 7; |
|
112 |
} |
|
91 | 113 |
|
92 |
if (moment(range[1]).diff(moment(range[0]), 'days') > 7) { |
|
114 |
/** |
|
115 |
* Gets data based on selected time range |
|
116 |
*/ |
|
117 |
showGraph(changedDate: boolean = true, changedSensor: string = null) { |
|
118 |
if (moment(this.to).diff(moment(this.from), 'days') > 7) { |
|
93 | 119 |
this.useAnalyticsData = true; |
94 | 120 |
this.showAggregation = true; |
121 |
const range: Date[] = [this.from, this.to]; |
|
95 | 122 |
this.getAnalytics(range, changedDate, changedSensor); |
96 | 123 |
} else { |
97 | 124 |
this.useAnalyticsData = false; |
98 | 125 |
this.showAggregation = false; |
126 |
const range: Date[] = [this.from, this.to]; |
|
99 | 127 |
this.getObservations(range, changedDate, changedSensor); |
100 | 128 |
} |
101 | 129 |
} |
102 | 130 |
|
103 |
getAnalytics(range: Date[], changedDate: boolean, changedSensor: string) { |
|
104 |
const groupId = changedSensor.toString().slice(0, 5); |
|
105 |
if (changedDate) { |
|
131 |
/** |
|
132 |
* Gets data from analytics endpoint |
|
133 |
* @param range from and to interval |
|
134 |
* @param changedDate determines if dates changed so we need refresh all data |
|
135 |
* @param changedSensorId if selecting sensor only fetch data for this server |
|
136 |
*/ |
|
137 |
getAnalytics(range: Date[], changedDate: boolean, changedSensorId: string) { |
|
138 |
if (changedDate) { // if changed date we need new data for all sensors |
|
106 | 139 |
this.selectedSensors.forEach(selectSens => { |
107 |
this.analyticsService.getAnalytics$Response({unit_id: this.unitId, sensor_id: parseInt(selectSens, 10), |
|
108 |
from: moment(range[0]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3), |
|
109 |
to: moment(range[1]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3), interval: this.selectedAggregationFunction}).pipe( |
|
110 |
map((response: HttpResponse<any>) => { |
|
111 |
if (response.status === 200) { |
|
112 |
return response.body; |
|
113 |
} else if (response.status === 204) { |
|
114 |
// GraphLoader.getAnalyticsGraph(null, null, null, '#vega_container_' + selectSens.toString().slice(0, 5)); |
|
115 |
GraphLoader.getGraph(null, null, null, '#vega_container_' + selectSens.toString().slice(0, 5),null ); |
|
116 |
this.toastService.showWarningNoData(); |
|
117 |
return response.body; |
|
118 |
} else { |
|
119 |
return false; |
|
120 |
} |
|
121 |
}) |
|
122 |
).subscribe(data => { |
|
123 |
if (data) { |
|
124 |
this.analyticsData.push({sensorId: selectSens, data: data[selectSens].data, interval: data[selectSens].interval}); |
|
125 |
const objectKeys = Object.keys(data); |
|
126 |
for(const key of objectKeys ) { |
|
127 |
if (data[key].data) { |
|
128 |
const view = '#vega_container_' + key.slice(0, 5); |
|
129 |
if (this.selectedSensors.some(sens => sens.toString() === key)) { |
|
130 |
// GraphLoader.getAnalyticsGraph(key, data[key].data, data[key].interval, view); |
|
131 |
// GraphLoader.getGraph(this.selectedSensors, this.filteredAnalyticsData(groupId), view, true); |
|
132 |
} else { |
|
133 |
GraphLoader.getGraph(null, null, null, view, null); |
|
134 |
} |
|
135 |
} |
|
136 |
} |
|
137 |
} |
|
138 |
}, err => this.toastService.showError(err.error.message)); |
|
140 |
this.analyticsEndpointRequest(selectSens, range); |
|
139 | 141 |
}); |
140 |
} else { |
|
141 |
this.analyticsService.getAnalytics$Response({unit_id: this.unitId, sensor_id: parseInt(changedSensor, 10), |
|
142 |
from: moment(range[0]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3), |
|
143 |
to: moment(range[1]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3), interval: this.selectedAggregationFunction}).pipe( |
|
144 |
map((response: HttpResponse<any>) => { |
|
145 |
if (response.status === 200) { |
|
146 |
return response.body; |
|
147 |
} else if (response.status === 204) { |
|
148 |
this.toastService.showWarningNoData(); |
|
149 |
return response.body; |
|
142 |
} else { // add data for selected sensor |
|
143 |
this.analyticsEndpointRequest(changedSensorId, range); |
|
144 |
} |
|
145 |
} |
|
146 |
|
|
147 |
/** |
|
148 |
* Endpoint request to get analytics data for sensor |
|
149 |
* @param sensorId sensor id to get data |
|
150 |
* @param range from and to interval |
|
151 |
*/ |
|
152 |
analyticsEndpointRequest(sensorId: string, range: Date[]) { |
|
153 |
this.analyticsService.getAnalytics$Response({unit_id: this.unitId, sensor_id: parseInt(sensorId, 10), |
|
154 |
from: moment(range[0]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3), |
|
155 |
to: moment(range[1]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3), interval: this.selectedAggregationFunction}).pipe( |
|
156 |
map((response: HttpResponse<any>) => { |
|
157 |
if (response.status === 200) { |
|
158 |
return response.body; |
|
159 |
} else if (response.status === 204) { |
|
160 |
this.toastService.showWarningNoData(); |
|
161 |
return response.body; |
|
162 |
} else { |
|
163 |
return false; |
|
164 |
} |
|
165 |
}) |
|
166 |
).subscribe(data => { |
|
167 |
if (data) { |
|
168 |
this.analyticsData.push({sensorId, data: data[sensorId].data, interval: data[sensorId].interval}); |
|
169 |
if (data[sensorId].data) { |
|
170 |
const groupId = sensorId.slice(0, 5); |
|
171 |
const view = '#vega_container_' + groupId; |
|
172 |
if (this.selectedSensors.some(sens => sens.toString() === sensorId)) { |
|
173 |
// GraphLoader.getAnalyticsGraph(key, data[key].data, data[key].interval, view); |
|
174 |
GraphLoader.getGraph(this.selectedSensors, this.analyticsData, this.filteredSensorsInfos(groupId), view, true); |
|
150 | 175 |
} else { |
151 |
return false; |
|
152 |
} |
|
153 |
}) |
|
154 |
).subscribe(data => { |
|
155 |
if (data) { |
|
156 |
this.analyticsData.push({sensorId: changedSensor, data: data[changedSensor].data, interval: data[changedSensor].interval}); |
|
157 |
const objectKeys = Object.keys(data); |
|
158 |
for(const key of objectKeys ) { |
|
159 |
if (data[key].data) { |
|
160 |
const view = '#vega_container_' + key.slice(0, 5); |
|
161 |
if (this.selectedSensors.some(sens => sens.toString() === key)) { |
|
162 |
// GraphLoader.getAnalyticsGraph(key, data[key].data, data[key].interval, view); |
|
163 |
GraphLoader.getGraph(this.selectedSensors, this.analyticsData, this.filteredSensorsInfos(groupId), view, true); |
|
164 |
} else { |
|
165 |
// GraphLoader.getAnalyticsGraph(null, null, null, view); |
|
166 |
GraphLoader.getGraph(null, null, null, view, null); |
|
167 |
} |
|
168 |
} |
|
176 |
// GraphLoader.getAnalyticsGraph(null, null, null, view); |
|
177 |
GraphLoader.getGraph(null, null, null, view, null); |
|
169 | 178 |
} |
170 | 179 |
} |
171 |
}, err => this.toastService.showError(err.error.message));
|
|
172 |
} |
|
180 |
} |
|
181 |
}, err => this.toastService.showError(err.error.message));
|
|
173 | 182 |
} |
174 | 183 |
|
175 | 184 |
/** |
... | ... | |
205 | 214 |
if (this.observationsData.some(sens => sens.sensorId.toString() === sensorId)) { // if already data for selected sensor in memory |
206 | 215 |
GraphLoader.getGraph(this.filteredSelectedSensors(groupId), this.filteredObservationData(groupId), |
207 | 216 |
this.filteredSensorsInfos(groupId), sensorGroupElement, false); |
208 |
// GraphLoader.getMultilineGraph(this.selectedSensors, this.filteredObservationData(groupId), sensorGroupElement) |
|
209 | 217 |
} else { // get data from server for added sensor and show graph for selected sensors |
210 | 218 |
this.showGraph(false, sensorId); |
211 | 219 |
} |
212 | 220 |
} else { // remove sensor from graph |
213 |
// GraphLoader.getMultilineGraph(this.selectedSensors, this.filteredObservationData(groupId), sensorGroupElement) |
|
214 |
GraphLoader.getGraph(this.filteredSelectedSensors(groupId), this.filteredObservationData(groupId), |
|
221 |
GraphLoader.getGraph(this.filteredSelectedSensors(groupId), this.filteredObservationData(groupId), |
|
215 | 222 |
this.filteredSensorsInfos(groupId), sensorGroupElement, false); |
216 |
|
|
217 | 223 |
} |
218 | 224 |
} |
219 | 225 |
} |
... | ... | |
236 | 242 |
sen.sensorId.toString().slice(0, 5) === sensorGroupId); |
237 | 243 |
} |
238 | 244 |
|
239 |
|
|
245 |
/** |
|
246 |
* Filter only selected sensors for group of sensors |
|
247 |
* @param sensorGroupId group of sensors |
|
248 |
*/ |
|
240 | 249 |
filteredSelectedSensors(sensorGroupId: string): any { |
241 |
return this.selectedSensors.filter(sen => sen.toString().slice(0, 5) === sensorGroupId );
|
|
250 |
return this.selectedSensors.filter(sen => sen.toString().slice(0, 5) === sensorGroupId); |
|
242 | 251 |
} |
243 | 252 |
|
253 |
/** |
|
254 |
* Get sensors only for group |
|
255 |
* @param sensorGroupId group id |
|
256 |
*/ |
|
244 | 257 |
filteredSensorsInfos(sensorGroupId: string): any { |
245 | 258 |
return this.sensors.filter(sen => this.selectedSensors.includes(sen.sensorId.toString()) && |
246 | 259 |
sen.sensorId.toString().slice(0, 5) === sensorGroupId); |
247 | 260 |
} |
248 | 261 |
|
249 |
private getObservations(range: Date[], changedDate: boolean, changedSensorId: string) { |
|
250 |
const groupId = changedSensorId.toString().slice(0, 5); |
|
262 |
/** |
|
263 |
* Gets data from observation endpoint |
|
264 |
* @param range from and to interval |
|
265 |
* @param changedDate determines if dates changed so we need refresh all data |
|
266 |
* @param changedSensorId if selecting sensor only fetch data for this server |
|
267 |
*/ |
|
268 |
getObservations(range: Date[], changedDate: boolean, changedSensorId: string) { |
|
251 | 269 |
if (changedDate) { // if changed date we need new data for all sensors |
252 | 270 |
this.observationsData = []; // empty observation data |
253 | 271 |
this.selectedSensors.forEach(selectSens => { |
254 |
this.observationService.getObservation$Response({ |
|
255 |
unit_id: this.unitId, |
|
256 |
sensor_id: parseInt(selectSens, 10), |
|
257 |
from: moment(range[0]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3), |
|
258 |
to: moment(range[1]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3) |
|
259 |
}).pipe( |
|
260 |
map((response: HttpResponse<any>) => { |
|
261 |
if (response.status === 200) { |
|
262 |
return response.body; |
|
263 |
} else if (response.status === 204) { |
|
264 |
this.toastService.showWarningNoData(); |
|
265 |
return response.body; |
|
266 |
} else { |
|
267 |
return false; |
|
268 |
} |
|
269 |
}), |
|
270 |
tap((observations) => { |
|
271 |
if (observations) { |
|
272 |
this.observationsData.push({sensorId: selectSens, sensor: |
|
273 |
this.sensors.find(sens => sens.sensorId.toString() === selectSens.toString()), data: observations}); |
|
274 |
} |
|
275 |
}), |
|
276 |
tap(() => { |
|
277 |
if (this.observationsData && this.observationsData.length > 1) { |
|
278 |
const view = '#vega_container_' + selectSens.toString().slice(0, 5); |
|
279 |
setTimeout(() => { |
|
280 |
console.log(this.selectedSensors); |
Také k dispozici: Unified diff
Re #8915 - Zapracování požadavků ze schůzky
+ sensor edit under edit button in menu+ sensor group names
+ adding information to unit and sensor
+ commenting
+ code refactor