integrasi list monitoring

This commit is contained in:
Fuzi_fauzia 2024-06-04 11:37:57 +07:00
parent 6061f4e58e
commit 0f1c3d6c33
13 changed files with 18959 additions and 19165 deletions

37548
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -85,6 +85,7 @@
"rxjs": "^7.5.5", "rxjs": "^7.5.5",
"sass": "^1.57.1", "sass": "^1.57.1",
"save": "^2.9.0", "save": "^2.9.0",
"sweetalert2": "^11.11.0",
"tree-ngx": "^4.3.0", "tree-ngx": "^4.3.0",
"tslib": "^2.4.1", "tslib": "^2.4.1",
"util": "^0.12.5", "util": "^0.12.5",

View File

@ -11,7 +11,7 @@
class="text-bold-800 grey darken-2" class="text-bold-800 grey darken-2"
href="https://allbestsistem.com/" href="https://allbestsistem.com/"
target="_blank" target="_blank"
>Allbest Solusi Sistem >Allbest Solusi Sistem (V@2024-06-04.01)
</a></span </a></span
> >
</p> </p>

View File

@ -11,8 +11,8 @@
<li class="nav-item"><a [routerLink]="['/monitoring']" class="navbar-brand"><img class="brand-logo" alt="modern admin logo" <li class="nav-item"><a [routerLink]="['/monitoring']" class="navbar-brand"><img class="brand-logo" alt="modern admin logo"
src="../../../../assets/images/logo/logo.png"> src="../../../../assets/images/logo/logo.png">
<!-- <h3 class="brand-text">{{_themeSettingsConfig.brand.brand_name}}</h3> --> <!-- <h3 class="brand-text">{{_themeSettingsConfig.brand.brand_name}}</h3> -->
<!-- <h3 class="brand-text">{{_themeSettingsConfig.brand.brand_name}} - (V@2024.05.22.01)</h3> --> <!-- <h3 class="brand-text">{{_themeSettingsConfig.brand.brand_name}}</h3> -->
<h3 class="brand-text" style="color: aliceblue;">Hemat - (V@2024.06.03.01)</h3> <h3 class="brand-text" style="color: aliceblue;">Hemat</h3>
</a></li> </a></li>
<li class="nav-item d-md-none"><a class="nav-link open-navbar-container" data-toggle="collapse" <li class="nav-item d-md-none"><a class="nav-link open-navbar-container" data-toggle="collapse"

View File

@ -1,229 +1,37 @@
<div class="app-content content"> <div class="app-content content bg-maintenance-image">
<div class="content-wrapper"> <div class="content-wrapper">
<div class="content-header row mb-1">
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
</div>
<div class="content-body"> <div class="content-body">
<section id="configuration"> <section class="flexbox-container">
<div class="row"> <div class="col-12 d-flex align-items-center justify-content-center">
<div <div class="col-md-4 col-10 box-shadow-2 p-0">
class="col-12" <div class="card border-grey border-lighten-3 px-1 py-1 box-shadow-3 m-0">
*blockUI="'zeroConfiguration'; message: 'Loading'"
>
<m-card>
<ng-container mCardHeaderTitle>
Cost Management Table
</ng-container>
<ng-container mCardBody>
<div class="row mb-2">
<div class="col-md-6">
<input
type="text"
class="form-control"
placeholder="Search..."
[(ngModel)]="searchTerm"
(input)="filterRows()"
(touchstart)="onTouchStart($event)"
/>
</div>
<div class="col-md-6 text-right">
<button
class="btn btn-secondary"
[routerLink]="['/cost-management/add-row']"
>
<i class="feather ft-plus"></i>&nbsp; Add new data
</button>
</div>
</div>
<div class="card-dashboard">
<ngx-datatable
class="bootstrap table-bordered"
[limit]="10"
[rows]="filteredRows"
[columnMode]="'force'"
[headerHeight]="50"
[footerHeight]="50"
[rowHeight]="50"
fxFlex="auto"
[scrollbarH]="true"
>
<ngx-datatable-column
name="#"
[flexGrow]="1"
[minWidth]="10"
>
<ng-template
ngx-datatable-cell-template
let-rowIndex="rowIndex"
>
{{ rowIndex + 1 }}
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column
name="Name"
[flexGrow]="1"
[minWidth]="90"
>
<ng-template ngx-datatable-header-template>
<span>Estimasi Cost Name</span>
</ng-template>
<ng-template
let-value="value"
ngx-datatable-cell-template
>
{{ value }}
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column
name="Position"
[flexGrow]="1"
[minWidth]="90"
>
<ng-template ngx-datatable-header-template>
<span>Category</span>
</ng-template>
<ng-template
ngx-datatable-cell-template
let-value="value"
>
{{ value }}
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column
name="Office"
[flexGrow]="1"
[minWidth]="90"
>
<ng-template ngx-datatable-header-template>
<span>Location</span>
</ng-template>
<ng-template
ngx-datatable-cell-template
let-value="value"
>
{{ value }}
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column
name="Age"
[flexGrow]="1"
[minWidth]="40"
>
<ng-template ngx-datatable-header-template>
<span>Location Room</span>
</ng-template>
<ng-template
ngx-datatable-cell-template
let-value="value"
>
{{ value }}
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column
name="Startdate"
[flexGrow]="1"
[minWidth]="90"
>
<ng-template ngx-datatable-header-template>
<span>Duration Use</span>
</ng-template>
<ng-template
ngx-datatable-cell-template
let-value="value"
>
{{ value }}
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column
name="Salary"
[flexGrow]="1"
[minWidth]="90"
>
<ng-template ngx-datatable-header-template>
<span>Status</span>
</ng-template>
<ng-template
ngx-datatable-cell-template
let-value="value"
>
{{ value }}
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column
name="Actions"
[flexGrow]="1"
[minWidth]="150"
>
<ng-template
ngx-datatable-cell-template
let-rowIndex="rowIndex"
let-row="row"
>
<button
class="btn btn-sm btn-info mr-1"
(click)="viewRow(row)"
>
<i class="ficon feather ft-eye"></i>
</button>
<button
class="btn btn-sm btn-warning mr-1"
(click)="editRow(row)"
>
<i class="ficon feather ft-edit"></i>
</button>
<button
class="btn btn-sm btn-danger"
(click)="deleteRow(row)"
>
<i class="ficon feather ft-trash-2"></i>
</button>
</ng-template>
</ngx-datatable-column>
</ngx-datatable>
</div>
</ng-container>
</m-card>
</div>
</div>
</section>
<section id="configuration">
<div class="row">
<div class="col-lg-6 col-12">
<div class="card pull-up">
<div class="card-content">
<div class="card-body"> <div class="card-body">
<div class="media d-flex"> <span class="card-title text-center">
<div class="media-body text-left"> <img src="../../../../assets/images/logo/logo-dark-lg.png" class="img-fluid mx-auto d-block pt-2"
<h6 class="text-muted">Total Use </h6> width="250" alt="logo">
<h3>3,568</h3> </span>
</div>
<div class="align-self-center">
<i class="feather ft-zap danger font-large-2 float-right"></i>
</div>
</div>
</div> </div>
<div class="card-body text-center">
<h3>Coming Soon</h3>
<p>We're sorry for the inconvenience.
<br> Please check back later.</p>
<div class="mt-2"><i class="la la-cog spinner font-large-2"></i></div>
</div>
<hr>
<!-- <p class="socialIcon card-text text-center pt-2 pb-2">
<a [routerLink]="" class="btn btn-social-icon mr-1 mb-1 btn-outline-facebook"><span
class="la la-facebook"></span></a>
<a [routerLink]="" class="btn btn-social-icon mr-1 mb-1 btn-outline-twitter"><span
class="la la-twitter"></span></a>
<a [routerLink]="" class="btn btn-social-icon mr-1 mb-1 btn-outline-linkedin"><span
class="la la-linkedin font-medium-4"></span></a>
<a [routerLink]="" class="btn btn-social-icon mr-1 mb-1 btn-outline-github"><span
class="la la-github font-medium-4"></span></a>
</p> -->
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-6 col-12"> </section>
<div class="card pull-up">
<div class="card-content">
<div class="card-body">
<div class="media d-flex">
<div class="media-body text-left">
<h6 class="text-muted">Estimation Cost</h6>
<h3>Rp 1.000.000.000.000</h3>
</div>
<div class="align-self-center">
<i class="feather ft-trending-up success font-large-2 float-right"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div> </div>
</div> </div>
</div> </div>

View File

@ -62,47 +62,14 @@
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="buildingId">Room *</label> <label for="statusId">Status *</label>
<div class="input-group"> <div class="input-group">
<select <select
id="buildingId" id="statusId"
class="form-control" class="form-control"
formControlName="buildingId" formControlName="statusId"
[ngClass]="{ [ngClass]="{
'is-invalid': submitted && f.buildingId.errors 'is-invalid': submitted && f.statusId.errors
}"
>
<option
*ngFor="let data of dataRoomList"
[value]="data.id"
>
{{ data.name }}
</option>
</select>
</div>
<small
class="form-text text-muted danger"
*ngIf="submitted && f.buildingId.errors"
class="invalid-feedback"
>
<div *ngIf="f.buildingId.errors.required">
Room is required
</div>
</small>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="buildingId">Status *</label>
<div class="input-group">
<select
id="buildingId"
class="form-control"
formControlName="buildingId"
[ngClass]="{
'is-invalid': submitted && f.buildingId.errors
}" }"
> >
<option <option
@ -115,11 +82,90 @@
</div> </div>
<small <small
class="form-text text-muted danger" class="form-text text-muted danger"
*ngIf="submitted && f.buildingId.errors" *ngIf="submitted && f.statusId.errors"
class="invalid-feedback" class="invalid-feedback"
> >
<div *ngIf="f.buildingId.errors.required"> <div *ngIf="f.statusId.errors.required">
Building is required Status is required
</div>
</small>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group" *ngIf="mode === 'add'">
<div class="" formArrayName="userArray">
<div
class=""
*ngFor="
let userForm of userFormGroup.controls;
let i = index
"
>
<div [formGroupName]="i" class="">
<div class="input-group mb-1">
<select
id="roomId"
class="form-control"
formControlName="roomId"
[ngClass]="{
'is-invalid':
submitted && f.roomId.errors
}"
>
<option
*ngFor="let list of dataRoomList"
[value]="list.id"
>
{{ list.name }}
</option>
</select>
<button
class="btn btn-danger"
type="button"
(click)="removePhone(i)"
>
<i class="feather ft-x"></i>
</button>
</div>
</div>
</div>
</div>
<button
type="button"
class="btn btn-primary"
(click)="addPhone()"
>
<i class="feather ft-plus"></i> Add Room
</button>
</div>
<div class="form-group" *ngIf="mode !== 'add'">
<label for="roomId">Room *</label>
<div class="input-group">
<select
id="roomId"
class="form-control"
formControlName="roomId"
[ngClass]="{
'is-invalid': submitted && f.roomId.errors
}"
>
<option
*ngFor="let data of dataRoomList"
[value]="data.id"
>
{{ data.name }}
</option>
</select>
</div>
<small
class="form-text text-muted danger"
*ngIf="submitted && f.roomId.errors"
class="invalid-feedback"
>
<div *ngIf="f.roomId.errors.required">
Status is required
</div> </div>
</small> </small>
</div> </div>
@ -134,7 +180,7 @@
> >
<i class="feather ft-x"></i> Cancel <i class="feather ft-x"></i> Cancel
</button> </button>
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary" *ngIf="mode !== 'view'" (click)="save()">
<i class="la la-check"></i> Save <i class="la la-check"></i> Save
</button> </button>
</div> </div>

View File

@ -1,5 +1,5 @@
import { Component, ViewChild } from '@angular/core'; import { Component, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms'; import { FormArray, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { BlockUI, NgBlockUI } from 'ng-block-ui'; import { BlockUI, NgBlockUI } from 'ng-block-ui';
import { BuildingService } from '../../service/monitoring-api.service'; import { BuildingService } from '../../service/monitoring-api.service';
@ -10,7 +10,7 @@ import { BuildingService } from '../../service/monitoring-api.service';
styleUrls: ['./add-edit-list.component.css'] styleUrls: ['./add-edit-list.component.css']
}) })
export class AddEditListComponent { export class AddEditListComponent {
@ViewChild("f", { read: true }) userProfileForm: NgForm; // @ViewChild("f", { read: true }) userProfileForm: NgForm;
model: any = {}; model: any = {};
mode: string; mode: string;
@ -20,9 +20,16 @@ export class AddEditListComponent {
dataBuildingList: any; dataBuildingList: any;
dataRoomList: any; dataRoomList: any;
dataMasterStatus: any dataMasterStatus: any;
roombuildingId: any;
dataRoomBuilding: any;
// userProfileForm: FormGroup;
public userList: FormArray;
@BlockUI("projectInfo") blockUIProjectInfo: NgBlockUI; @BlockUI("projectInfo") blockUIProjectInfo: NgBlockUI;
get userFormGroup() {
return this.projectInfo.get('userArray') as FormArray;
}
constructor( constructor(
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
@ -35,6 +42,13 @@ export class AddEditListComponent {
this.route.data.subscribe((data) => { this.route.data.subscribe((data) => {
this.mode = data.mode; this.mode = data.mode;
}); });
this.route.params.subscribe(params => {
const id = params['id'];
this.roombuildingId = id;
if (id) {
this.loadRoomBuilding(id);
}
});
this.setBreadcrumb(); this.setBreadcrumb();
this.dataListBuilding(); this.dataListBuilding();
this.dataListRoom(); this.dataListRoom();
@ -42,9 +56,25 @@ export class AddEditListComponent {
this.projectInfo = this.formBuilder.group({ this.projectInfo = this.formBuilder.group({
buildingId: ["", Validators.required], buildingId: ["", Validators.required],
roomId: ["", Validators.required], roomId: [""],
statusId: ["", Validators.required], statusId: ["", Validators.required],
userArray: this.formBuilder.array([this.createRoom()]),
}); });
this.userList = this.projectInfo.get('userArray') as FormArray;
}
createRoom(): FormGroup {
return this.formBuilder.group({
roomId: ['', Validators.required]
});
}
addPhone() {
this.userList.push(this.createRoom());
}
removePhone(index) {
this.userList.removeAt(index);
} }
setBreadcrumb() { setBreadcrumb() {
@ -105,6 +135,31 @@ export class AddEditListComponent {
} }
} }
loadRoomBuilding(deviceId: string) {
this.monitoringApiService.getRoomBuildingById(deviceId).subscribe(data => {
this.dataRoomBuilding = data;
this.formGetDevice(data)
});
}
formGetDevice(data){
this.projectInfo.patchValue({
buildingId: data.data.buildingId,
roomId: data.data.roomId,
statusId: data.data.statusId,
});
if (this.mode === 'view') {
this.formDisable();
}
}
formDisable(){
this.projectInfo.get('buildingId').disable()
this.projectInfo.get('roomId').disable()
this.projectInfo.get('statusId').disable()
}
isEditMode() { isEditMode() {
return this.mode === "edit"; return this.mode === "edit";
} }
@ -138,10 +193,10 @@ export class AddEditListComponent {
dataListBuilding() { dataListBuilding() {
this.monitoringApiService.getBuildingList().subscribe(data => { this.monitoringApiService.getBuildingList().subscribe(data => {
this.dataBuildingList = data.data this.dataBuildingList = data.data.filter(item => item.statusId === 2)
}); });
} }
dataListRoom() { dataListRoom() {
this.monitoringApiService.getListRoomData().subscribe(data => { this.monitoringApiService.getListRoomData().subscribe(data => {
this.dataRoomList = data.data this.dataRoomList = data.data
@ -157,7 +212,27 @@ export class AddEditListComponent {
}); });
} }
addData() {} save() {
if (this.mode === 'add') {
if (this.projectInfo.invalid) {
return;
}
const formData = this.projectInfo.value;
const transformedData = {
buildingId: formData.buildingId,
roomId: formData.userArray.map(room => room.roomId),
statusId: formData.statusId
};
this.monitoringApiService.postBatchBuilding(transformedData).subscribe((res) => {
this.router.navigate(["/list-monitoring"]);
});
} else {
delete this.projectInfo.value.userArray;
this.monitoringApiService.puttBuildingRoom(this.projectInfo.value, this.roombuildingId).subscribe(data => {
this.router.navigate(["/list-monitoring"]);
});
}
}
cancel() { cancel() {
this.router.navigate(["/list-monitoring"]); this.router.navigate(["/list-monitoring"]);

View File

@ -188,3 +188,32 @@
display: -webkit-box; display: -webkit-box;
} }
/* Custom styles for Swal buttons */
.btn-confirm {
background-color: #28a745 !important;
color: white !important;
border: none !important;
padding: 10px 20px !important;
border-radius: 5px !important;
font-size: 16px !important;
}
.btn-cancel {
background-color: #dc3545 !important;
color: white !important;
border: none !important;
padding: 10px 20px !important;
border-radius: 5px !important;
font-size: 16px !important;
}
.btn-confirm:hover {
background-color: #218838 !important;
}
.btn-cancel:hover {
background-color: #c82333 !important;
}

View File

@ -2,6 +2,7 @@ import { Component } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { TableApiService } from 'src/app/_services/table-api.service'; import { TableApiService } from 'src/app/_services/table-api.service';
import { BuildingService } from '../service/monitoring-api.service'; import { BuildingService } from '../service/monitoring-api.service';
import Swal from 'sweetalert2';
@Component({ @Component({
selector: 'app-list-monitoring', selector: 'app-list-monitoring',
@ -40,11 +41,8 @@ export class ListMonitoringComponent {
fetchData() { fetchData() {
this.monitoringApiService.getBuildingRoomList().subscribe((res) => { this.monitoringApiService.getBuildingRoomList().subscribe((res) => {
console.log(res);
this.data = res; this.data = res;
this.filteredRows = this.data.results.data; this.filteredRows = this.data.results.data;
console.log(this.filteredRows);
}); });
} }
@ -68,17 +66,45 @@ export class ListMonitoringComponent {
} }
viewRow(row) { viewRow(row) {
console.log("View row:", row); this.router.navigate(["/list-monitoring/view", row.id]);
this.router.navigate(["/list-monitoring/view", row.name]);
} }
editRow(row) { editRow(row) {
console.log("Edit row:", row); this.router.navigate(["/list-monitoring/edit", row.id]);
this.router.navigate(["/list-monitoring/edit", row.name]);
} }
deleteRow(row) { deleteRow(row) {
console.log("Delete row:", row); Swal.fire({
title: 'Are you sure?',
text: 'Do you want to delete?',
icon: 'question',
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'No',
customClass: {
confirmButton: 'btn-confirm',
cancelButton: 'btn-cancel'
}
}).then((result) => {
if (result.isConfirmed) {
Swal.fire({
title: 'Loading...',
text: 'Please wait',
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
}
});
setTimeout(() => {
this.monitoringApiService.deleteRoomBuilding(row.id).subscribe(data => {
Swal.fire('Confirmed!', 'You clicked Yes.', 'success');
this.fetchData();
});
}, 2000);
} else if (result.isDismissed) {
Swal.fire('Cancelled', 'You clicked No.', 'error');
}
});
} }
onTouchStart(event: Event) { onTouchStart(event: Event) {

View File

@ -82,8 +82,6 @@ export class AddNewBuildingRoomComponent implements OnInit {
} }
save(){ save(){
console.log(this.userProfileForm);
console.log(this.userProfileForm.valid);
this.submitted = true; this.submitted = true;
if (this.userProfileForm.invalid) { if (this.userProfileForm.invalid) {
@ -97,8 +95,6 @@ export class AddNewBuildingRoomComponent implements OnInit {
statusId: formData.statusId statusId: formData.statusId
}; };
console.log(transformedData);
this.monitoringApiService.postBatchBuilding(transformedData).subscribe((res) => { this.monitoringApiService.postBatchBuilding(transformedData).subscribe((res) => {
console.log(res); console.log(res);
}); });

View File

@ -222,6 +222,15 @@ export class BuildingService {
return this.http.get<any>(url, { headers }); return this.http.get<any>(url, { headers });
} }
puttBuildingRoom(data: any, id: any): Observable<any> {
const url = `https://kapi.absys.ninja/hemat/room-building/${id}`;
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
});
return this.http.put<any>(url, data, { headers });
}
putDevice(data: any, id: any): Observable<any> { putDevice(data: any, id: any): Observable<any> {
const url = `https://kapi.absys.ninja/hemat/devices/${id}`; const url = `https://kapi.absys.ninja/hemat/devices/${id}`;
const headers = new HttpHeaders({ const headers = new HttpHeaders({
@ -230,4 +239,22 @@ export class BuildingService {
}); });
return this.http.put<any>(url, data, { headers }); return this.http.put<any>(url, data, { headers });
} }
getRoomBuildingById(roomBuildingId: any): Observable<any> {
const url = `https://kapi.absys.ninja/hemat/room-building/${roomBuildingId}`;
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
});
return this.http.get<any>(url, { headers });
}
deleteRoomBuilding(id: any): Observable<any> {
const url = `https://kapi.absys.ninja/hemat/room-building/${id}`;
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
});
return this.http.delete<any>(url, { headers });
}
} }

View File

@ -12,7 +12,7 @@
</span> </span>
</div> </div>
<div class="card-body text-center"> <div class="card-body text-center">
<h3>This page is under maintenance</h3> <h3>Coming Soon</h3>
<p>We're sorry for the inconvenience. <p>We're sorry for the inconvenience.
<br> Please check back later.</p> <br> Please check back later.</p>
<div class="mt-2"><i class="la la-cog spinner font-large-2"></i></div> <div class="mt-2"><i class="la la-cog spinner font-large-2"></i></div>

View File

@ -133,7 +133,7 @@
<p <p
class="card-subtitle line-on-side text-muted text-center font-small-3 mx-2 my-1" class="card-subtitle line-on-side text-muted text-center font-small-3 mx-2 my-1"
> >
<span>New to Modern ? (v@2024.06.03.01)</span> <span>New to Modern ? (v@2024.06.04.01)</span>
</p> </p>
<div class="card-body"> <div class="card-body">
<a <a