Compare commits
82 Commits
06a7c9b249
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| b00896d407 | |||
| 7c443080d6 | |||
| 98159a1584 | |||
| 5c5ca65f53 | |||
| ecef25f30d | |||
| 45e280c007 | |||
| ca5f0c8c0c | |||
| b1ee612602 | |||
| 9654cf92e8 | |||
| a2d166ac1a | |||
| a9a7e6edd3 | |||
| b5e0962079 | |||
| 633effdb9b | |||
| 7a28e52e89 | |||
| c54fdd0f55 | |||
| 04972e33b1 | |||
| f81dc7bf66 | |||
| 2b1f6c0cfe | |||
| 9529da581a | |||
| b195055651 | |||
| 2a4135c966 | |||
| cd1f56e07b | |||
| 9377bebcb4 | |||
| 57bcbcccde | |||
| d753a3a634 | |||
| a9d135f8ef | |||
| 0aac2ff194 | |||
| 379bdb24da | |||
| 21b75ca610 | |||
| b5cf71d008 | |||
| cd777f11ad | |||
| f4036b1a06 | |||
| 4fdaa8c1bd | |||
| 5410d966d0 | |||
|
|
bfb828c15c | ||
| 124f3eef4c | |||
| 9b4ac3b992 | |||
| d70edcebd8 | |||
| a458f2ce3c | |||
| db9a9e415a | |||
| a9f3da867f | |||
| 03c7e54bc8 | |||
| df1cd2339e | |||
| 2a6cf6410d | |||
| 3b3757e2a7 | |||
| 95fa99799c | |||
| 8cc1a2b9fb | |||
| 9d8e31e7fe | |||
| c04cafa384 | |||
| e3be28b4b6 | |||
| da4100993b | |||
| 0c1dd29554 | |||
| f86dfb7829 | |||
| 9a29e2e4e0 | |||
| 721d4e9af9 | |||
| 153b47eaaa | |||
| c337a8941c | |||
| bd1cd42ed6 | |||
| 7bc1fa5fe9 | |||
| 768c9ee6ca | |||
| efb6ae0060 | |||
| d22eaa50e1 | |||
| 60d14b2fce | |||
| 6b91c937ab | |||
| fa12fcec50 | |||
| 9570b77e32 | |||
| dd1deb0812 | |||
| 751c36209e | |||
| 4c2d40986e | |||
| 5782af4c75 | |||
| 5b3c9bcba4 | |||
| 45f3c9b86b | |||
| 9a0d0d919e | |||
| 13e5ee01d2 | |||
| a9034c1a32 | |||
| 28067d1704 | |||
| 4ae3b51530 | |||
| dc4be31103 | |||
| 0b37bcd8ee | |||
| a79493d329 | |||
| 52481cbc4b | |||
| d43a26513e |
1
package-lock.json
generated
1
package-lock.json
generated
@@ -57,6 +57,7 @@
|
||||
"jspdf": "^2.5.1",
|
||||
"jspdf-autotable": "^3.5.28",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"ng-chartist": "^4.1.0",
|
||||
"ng-multiselect-dropdown": "^0.3.9",
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"jspdf": "^2.5.1",
|
||||
"jspdf-autotable": "^3.5.28",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"ng-chartist": "^4.1.0",
|
||||
"ng-multiselect-dropdown": "^0.3.9",
|
||||
|
||||
@@ -9,23 +9,23 @@
|
||||
class="btn btn-icon btn-pure secondary mr-1"
|
||||
routerLink="{{ breadcrumb.linkBack }}"
|
||||
>
|
||||
<i class="feather ft-chevron-left" style="color: #ffffff"></i>
|
||||
<i class="feather ft-chevron-left" style="color: #242222"></i>
|
||||
</button>
|
||||
<h3 class="content-header-title mb-0 d-inline-block" style="color: #ffffff">
|
||||
<h3 class="content-header-title mb-0 d-inline-block" style="color: #242222">
|
||||
{{ breadcrumb.mainlabel }}
|
||||
</h3>
|
||||
<div class="row breadcrumbs-top d-inline-block">
|
||||
<div class="breadcrumb-wrapper col-12">
|
||||
<ol class="breadcrumb">
|
||||
<ng-container *ngFor="let link of breadcrumb.links; let last = last">
|
||||
<li class="breadcrumb-item" style="color: #ffffff">
|
||||
<li class="breadcrumb-item" style="color: #242222">
|
||||
<ng-container *ngIf="link.isLink; else notLink">
|
||||
<a routerLink="{{ link.link }}" style="color: #ffffff">{{ link.name }}</a>
|
||||
<a routerLink="{{ link.link }}" style="color: #242222">{{ link.name }}</a>
|
||||
</ng-container>
|
||||
<ng-template #notLink>
|
||||
<span style="color: #ffffff">{{ link.name }}</span>
|
||||
<span style="color: #242222">{{ link.name }}</span>
|
||||
</ng-template>
|
||||
<span *ngIf="!last" class="breadcrumb-arrow" style="color: #ffffff; margin: 0 5px;">
|
||||
<span *ngIf="!last" class="breadcrumb-arrow" style="color: #242222; margin: 0 5px;">
|
||||
<i class="feather ft-chevron-right"></i>
|
||||
</span>
|
||||
</li>
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
id="footer"
|
||||
class="footer footer-static footer-light navbar-border navbar-shadow"
|
||||
*ngIf="showFooter"
|
||||
style="background-color: #000000 !important; border: none !important;"
|
||||
style="border: none !important;"
|
||||
>
|
||||
<p class="clearfix blue-grey lighten-2 text-sm-center mb-0 px-2" style="background-color: #000000 !important;">
|
||||
<span class="float-md-ceter d-block d-md-inline-block" style="background-color: #000000 !important;"
|
||||
<p class="clearfix blue-grey lighten-2 text-sm-center mb-0 px-2">
|
||||
<span class="float-md-ceter d-block d-md-inline-block"
|
||||
>Copyright © 2024
|
||||
<a
|
||||
[routerLink]=""
|
||||
class="text-bold-800 grey darken-2"
|
||||
href="https://allbestsistem.com/"
|
||||
target="_blank"
|
||||
style="background-color: #000000 !important;"
|
||||
>Smart Building Management Systems (V@2024-07-11.01)
|
||||
style="background-color: #ffffff !important;"
|
||||
>Smart Building Management Systems (V@2024-08-28.1)
|
||||
</a></span
|
||||
>
|
||||
</p>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<nav
|
||||
class="header-navbar navbar-expand-md navbar navbar-with-menu navbar-without-dd-arrow fixed-top navbar-shadow"
|
||||
[ngClass]="selectedHeaderNavBarClass"
|
||||
style="background-color: #000000 !important"
|
||||
>
|
||||
<div class="navbar-wrapper">
|
||||
<div
|
||||
@@ -10,7 +9,7 @@
|
||||
[ngClass]="selectedNavBarHeaderClass"
|
||||
(mouseenter)="mouseEnter($event)"
|
||||
(mouseleave)="mouseLeave($event)"
|
||||
style="background-color: #252525 !important"
|
||||
style="background-color: #fbfbfb !important"
|
||||
>
|
||||
<ul class="nav navbar-nav flex-row">
|
||||
<!-- Remove position relative in responsive -->
|
||||
@@ -24,9 +23,9 @@
|
||||
</li>
|
||||
<li class="nav-item mr-auto">
|
||||
<a
|
||||
[routerLink]="['/dashboard/sales']"
|
||||
[routerLink]="['/monitoring']"
|
||||
class="navbar-brand"
|
||||
routerLink="/dashboard/sales"
|
||||
routerLink="/monitoring"
|
||||
>
|
||||
<img
|
||||
class="brand-logo"
|
||||
@@ -43,7 +42,7 @@
|
||||
text-overflow: ellipsis;
|
||||
"
|
||||
>
|
||||
<h3 class="brand-text" style="color: #ffffff; margin: 0">
|
||||
<h3 class="brand-text" style="color: #242222; margin: 0">
|
||||
Smart Building
|
||||
</h3>
|
||||
</div>
|
||||
@@ -54,6 +53,7 @@
|
||||
[routerLink]=""
|
||||
class="nav-link modern-nav-toggle pr-0"
|
||||
data-toggle="collapse"
|
||||
|
||||
(click)="toggleFixMenu($event)"
|
||||
>
|
||||
<i
|
||||
@@ -119,7 +119,7 @@
|
||||
<span class="badge badge-pill badge-danger badge-up badge-glow">5</span>
|
||||
</a> -->
|
||||
<a class="nav-link nav-link-label">
|
||||
<i class="ficon la la-bell" style="color: #bef264"></i>
|
||||
<i class="ficon la la-bell" style="color: #242424"></i>
|
||||
<!-- <span class="badge badge-pill badge-danger badge-up badge-glow">5</span> -->
|
||||
</a>
|
||||
<ul class="dropdown-menu-media dropdown-menu-right" ngbDropdownMenu>
|
||||
@@ -321,7 +321,7 @@
|
||||
<span
|
||||
*ngIf="currentUser.displayName"
|
||||
class="mr-1 user-name text-bold-700"
|
||||
style="color: #ffffff"
|
||||
style="color: #242222"
|
||||
>{{ currentUser.displayName }}</span
|
||||
>
|
||||
<span
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<div (mouseenter)="mouseEnter($event)" (mouseleave)="mouseLeave($event)" id="main-menu"
|
||||
class="main-menu menu-fixed menu-dark menu-accordion menu-shadow" data-scroll-to-active="true" style="background-color: #252525 !important;">
|
||||
class="main-menu menu-fixed menu-dark menu-accordion menu-shadow" data-scroll-to-active="true" style="background-color: #fbfbfb !important; box-shadow: none !important; border-right: 3px solid #f4f4f4;">
|
||||
<div id="main-menu-content" class="main-menu-content ps-container ps-theme-light" fxFlex="auto"
|
||||
[perfectScrollbar]="config" >
|
||||
<ul class="navigation navigation-main" id="main-menu-navigation" data-menu="menu-navigation" style="background-color: #252525 !important;">
|
||||
<ul class="navigation navigation-main" id="main-menu-navigation" data-menu="menu-navigation" style="background-color: #fbfbfb !important;">
|
||||
<!-- Menu -->
|
||||
{{child?child.title:''}}
|
||||
<li *ngFor="let child of _menuSettingsConfig.vertical_menu.items" class="" [ngClass]="{
|
||||
@@ -17,16 +17,16 @@
|
||||
<!-- Section -->
|
||||
<span class="menu-title" *ngIf="child.section">{{child.section}}</span>
|
||||
<i class="la" *ngIf="child.section" [ngClass]="child.icon" data-toggle="tooltip" data-placement="right"
|
||||
data-original-title="Support"></i>
|
||||
data-original-title="Support" style="color: #242222;"></i>
|
||||
|
||||
<!-- Root Menu -->
|
||||
<a *ngIf="child.title && !child.submenu && !child.excludeInVertical && !child.isExternalLink && !child.issupportExternalLink && !child.isStarterkitExternalLink"
|
||||
routerLink="{{child.page !== 'null'?child.page:router.url}}" (click)="toggleMenu($event, child)"
|
||||
style="background-color: #252525 !important;">
|
||||
<i class="la" [ngClass]="child.icon"></i>
|
||||
<span class="menu-title" data-i18n="">{{child.title}}</span>
|
||||
style="background-color: #fbfbfb !important;">
|
||||
<i class="la" [ngClass]="child.icon" style="color: #242222;"></i>
|
||||
<span class="menu-title" data-i18n="" style="color: #242222;">{{child.title}}</span>
|
||||
<span *ngIf="child.badge" class="badge badge-pill float-right"
|
||||
[ngClass]="{'badge-info mr-2': child.badge.type==='badge-info' , 'badge-danger':child.badge.type==='badge-danger'}">
|
||||
[ngClass]="{'badge-info mr-2': child.badge.type==='badge-info' , 'badge-danger':child.badge.type==='badge-danger'}" style="color: #242222;">
|
||||
{{child.badge.value}}
|
||||
</span>
|
||||
</a>
|
||||
@@ -53,15 +53,15 @@
|
||||
|
||||
<!-- Submenu -->
|
||||
<a *ngIf="child.title && child.submenu && !child.excludeInVertical"
|
||||
routerLink="{{child.page !== 'null'?child.page:router.url}}" (click)="toggleMenu($event, child)" style="background-color: #252525 !important;">
|
||||
<i class="la" [ngClass]="child.icon"></i>
|
||||
<span class="menu-title" data-i18n="">{{child.title}}</span>
|
||||
routerLink="{{child.page !== 'null'?child.page:router.url}}" (click)="toggleMenu($event, child)" style="background-color: #fbfbfb !important;">
|
||||
<i class="la" [ngClass]="child.icon" style="color: #242222;"></i>
|
||||
<span class="menu-title" data-i18n="" style="color: #242222;">{{child.title}}</span>
|
||||
<span *ngIf="child.badge" class="badge badge-pill float-right"
|
||||
[ngClass]="{'badge-info mr-2': child.badge.type==='badge-info' , 'badge-danger':child.badge.type==='badge-danger'}">
|
||||
[ngClass]="{'badge-info mr-2': child.badge.type==='badge-info' , 'badge-danger':child.badge.type==='badge-danger'}" style="color: #242222;">
|
||||
{{child.badge.value}}
|
||||
</span>
|
||||
</a>
|
||||
<ul *ngIf="child.submenu" class="menu-content" [@popOverState]="child.isOpen" style="background-color: #252525 !important;">
|
||||
<ul *ngIf="child.submenu" class="menu-content" [@popOverState]="child.isOpen" style="background-color: #fbfbfb !important;">
|
||||
<!-- Submenu of Submenu -->
|
||||
<li *ngFor="let subchild of child.submenu.items" class="isShown"
|
||||
[ngClass]="{'has-sub':(subchild.submenu),'active': subchild.isSelected && !subchild.submenu, 'open': subchild.isOpen && subchild.submenu}">
|
||||
@@ -69,7 +69,7 @@
|
||||
(click)="toggleMenu($event, subchild, true)"
|
||||
routerLink="{{subchild.page !== 'null'?subchild.page:router.url}}"
|
||||
[ngClass]="{'active': subchild.isSelected}"
|
||||
style="background-color: #252525 !important;">{{subchild.title}}</a>
|
||||
style="background-color: #fbfbfb !important; color: #242222;">{{subchild.title}}</a>
|
||||
<a class="menu-item" *ngIf="subchild.submenu && !subchild.excludeInVertical" (click)="toggleMenu($event, subchild, true)"
|
||||
routerLink="{{subchild.page !== 'null'?subchild.page:router.url}}">{{subchild.title}}</a>
|
||||
<ul *ngIf="subchild.submenu && !subchild.excludeInVertical" class="menu-content">
|
||||
|
||||
@@ -1018,10 +1018,7 @@ export const MenuSettingsConfig: MenuConfig = {
|
||||
page: "null",
|
||||
submenu: {
|
||||
items: [
|
||||
// {
|
||||
// title: "Monitoring List",
|
||||
// page: "/list-monitoring",
|
||||
// },
|
||||
|
||||
{
|
||||
title: "Master Category",
|
||||
page: "/master/master-category",
|
||||
@@ -1062,6 +1059,10 @@ export const MenuSettingsConfig: MenuConfig = {
|
||||
title: "Master Building",
|
||||
page: "/master/master-building",
|
||||
},
|
||||
{
|
||||
title: "Master Monitoring List",
|
||||
page: "/list-monitoring",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -208,4 +208,73 @@ export class TableexcelService {
|
||||
});
|
||||
this.saveAsExcelFile(excelBuffer, excelFileName);
|
||||
}
|
||||
|
||||
public exportAsExcelFileMonitoringDetail(
|
||||
json: any[],
|
||||
excelFileName: string,
|
||||
columns: string[],
|
||||
mode: any
|
||||
): void {
|
||||
const filteredJson = json.map((item) => {
|
||||
const filteredItem = {};
|
||||
columns.forEach((column) => {
|
||||
filteredItem[column] = item[column];
|
||||
});
|
||||
return filteredItem;
|
||||
});
|
||||
|
||||
const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(filteredJson);
|
||||
let columnWidths = [];
|
||||
if (mode === "building") {
|
||||
columnWidths = [
|
||||
{ wch: 30 },
|
||||
{ wch: 40 },
|
||||
{ wch: 30 },
|
||||
{ wch: 30 },
|
||||
{ wch: 30 },
|
||||
{ wch: 30 },
|
||||
];
|
||||
} else if (mode === "floor") {
|
||||
columnWidths = [
|
||||
{ wch: 40 },
|
||||
{ wch: 30 },
|
||||
{ wch: 30 },
|
||||
{ wch: 30 },
|
||||
{ wch: 30 },
|
||||
];
|
||||
} else if (mode === "room") {
|
||||
columnWidths = [{ wch: 30 }, { wch: 30 }, { wch: 30 }, { wch: 30 }];
|
||||
}
|
||||
|
||||
worksheet["!cols"] = columnWidths;
|
||||
|
||||
let header = [];
|
||||
if (mode === "building") {
|
||||
header = [
|
||||
"Floor",
|
||||
"Room",
|
||||
"Device",
|
||||
"Duration",
|
||||
"Price Kwh",
|
||||
"Estimation Cost",
|
||||
];
|
||||
} else if (mode === "floor") {
|
||||
header = ["Room", "Device", "Duration", "Price Kwh", "Estimation Cost"];
|
||||
} else if (mode === "room") {
|
||||
header = ["Device", "Duration", "Price Kwh", "Estimation Cost"];
|
||||
}
|
||||
|
||||
XLSX.utils.sheet_add_aoa(worksheet, [header]);
|
||||
|
||||
const workbook: XLSX.WorkBook = {
|
||||
Sheets: { data: worksheet },
|
||||
SheetNames: ["data"],
|
||||
};
|
||||
|
||||
const excelBuffer: any = XLSX.write(workbook, {
|
||||
bookType: "xlsx",
|
||||
type: "array",
|
||||
});
|
||||
this.saveAsExcelFile(excelBuffer, excelFileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
/* color: #ffffff !important; */
|
||||
/* background-color: #252525 !important; */
|
||||
}
|
||||
|
||||
@@ -31,6 +31,5 @@ export class SelectIconComponent {
|
||||
} else {
|
||||
this.iconSelected.emit(undefined);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,19 +364,21 @@ input[type="month"]::-webkit-calendar-picker-indicator {
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -404,21 +406,38 @@ input[type="month"]::-webkit-calendar-picker-indicator {
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.modal-open .content {
|
||||
filter: blur(5px);
|
||||
transition: filter 0.3s ease-in-out;
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,21 +7,20 @@
|
||||
<section>
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6 col-md-6 col-lg-6">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #DDE1E6 !important">
|
||||
<div
|
||||
class="card-header"
|
||||
style="background-color: #252525 !important"
|
||||
style="background-color: #DDE1E6 !important"
|
||||
>
|
||||
<h4
|
||||
class="card-title text-center"
|
||||
style="color: #ffffff !important"
|
||||
class="card-title text-center text-custom-label"
|
||||
>
|
||||
Comparison of Previous Month Costs
|
||||
</h4>
|
||||
<hr
|
||||
style="
|
||||
border-top: 4px solid #ffffff;
|
||||
border-color: #ffffff !important;
|
||||
border-top: 4px solid #242222;
|
||||
border-color: #242222 !important;
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
@@ -36,21 +35,20 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 col-md-6 col-lg-6">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #DDE1E6 !important">
|
||||
<div
|
||||
class="card-header"
|
||||
style="background-color: #252525 !important"
|
||||
style="background-color: #DDE1E6 !important"
|
||||
>
|
||||
<h4
|
||||
class="card-title text-center"
|
||||
style="color: #ffffff !important"
|
||||
class="card-title text-center text-custom-label"
|
||||
>
|
||||
Comparison of Actual Costs and Estimated Costs
|
||||
</h4>
|
||||
<hr
|
||||
style="
|
||||
border-top: 4px solid #ffffff;
|
||||
border-color: #ffffff !important;
|
||||
border-top: 4px solid #242222;
|
||||
border-color: #242222 !important;
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
@@ -67,7 +65,7 @@
|
||||
</div>
|
||||
</section>
|
||||
<section id="configuration">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
@@ -115,8 +113,9 @@
|
||||
class="btn btn-outline-success"
|
||||
(click)="doFilter()"
|
||||
style="
|
||||
background-color: #252525 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #37A647 !important;
|
||||
border-color: #37A647 !important;
|
||||
color: #ffffff;
|
||||
"
|
||||
[disabled]="spinnerFilterActive"
|
||||
>
|
||||
@@ -148,13 +147,13 @@
|
||||
/>
|
||||
<div
|
||||
class="input-group-append"
|
||||
style="background-color: #252525 !important"
|
||||
style="background-color: #FBFBFB !important"
|
||||
>
|
||||
<span
|
||||
class="input-group-text"
|
||||
style="
|
||||
background-color: #252525 !important;
|
||||
color: #ffffff;
|
||||
background-color: #FBFBFB !important;
|
||||
color: #242222;
|
||||
height: 40px !important;
|
||||
"
|
||||
>Kwh</span
|
||||
@@ -177,13 +176,13 @@
|
||||
/>
|
||||
<div
|
||||
class="input-group-append"
|
||||
style="background-color: #252525 !important"
|
||||
style="background-color: #FBFBFB !important"
|
||||
>
|
||||
<span
|
||||
class="input-group-text"
|
||||
style="
|
||||
background-color: #252525 !important;
|
||||
color: #ffffff;
|
||||
background-color: #FBFBFB !important;
|
||||
color: #242222;
|
||||
height: 40px !important;
|
||||
"
|
||||
>IDR</span
|
||||
@@ -199,9 +198,9 @@
|
||||
class="btn btn-secondary mr-2"
|
||||
style="
|
||||
width: 100%;
|
||||
background-color: #bef264 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #000000 !important;
|
||||
background-color: #37A647 !important;
|
||||
border-color: #37A647 !important;
|
||||
color: #ffffff !important;
|
||||
"
|
||||
(click)="export()"
|
||||
[disabled]="spinnerExportActive"
|
||||
@@ -218,9 +217,9 @@
|
||||
class="btn btn-secondary mr-2"
|
||||
style="
|
||||
width: 100%;
|
||||
background-color: #bef264 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #000000 !important;
|
||||
background-color: #37A647 !important;
|
||||
border-color: #37A647 !important;
|
||||
color: #ffffff !important;
|
||||
"
|
||||
(click)="syncData()"
|
||||
[disabled]="spinnerActive"
|
||||
@@ -236,9 +235,9 @@
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
width: 100%;
|
||||
background-color: #bef264 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #000000 !important;
|
||||
background-color: #37A647 !important;
|
||||
border-color: #37A647 !important;
|
||||
color: #ffffff !important;
|
||||
"
|
||||
(click)="addFieldValue()"
|
||||
>
|
||||
@@ -252,7 +251,7 @@
|
||||
<div class="card-dashboard">
|
||||
<ngx-datatable
|
||||
class="bootstrap table-bordered"
|
||||
[limit]="5"
|
||||
[limit]="10"
|
||||
[rows]="data_cost"
|
||||
[columnMode]="'force'"
|
||||
[headerHeight]="50"
|
||||
@@ -270,7 +269,7 @@
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
>
|
||||
<p style="color: #ffffff !important">
|
||||
<p class="style-custom-label">
|
||||
{{ rowIndex + 1 }}
|
||||
</p>
|
||||
</ng-template>
|
||||
@@ -281,10 +280,10 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Building</span>
|
||||
<span class="style-custom-label">Building</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -293,10 +292,10 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Category</span>
|
||||
<span class="style-custom-label">Category</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -305,10 +304,10 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Room</span>
|
||||
<span class="style-custom-label">Room</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -317,12 +316,12 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important"
|
||||
<span class="style-custom-label"
|
||||
>Estimation Cost</span
|
||||
>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">
|
||||
<p class="style-custom-label">
|
||||
{{
|
||||
value.toLocaleString("id-ID", {
|
||||
style: "currency",
|
||||
@@ -338,10 +337,10 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Total Kwh</span>
|
||||
<span class="style-custom-label">Total Kwh</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
kWh
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
@@ -351,10 +350,10 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Tanggal</span>
|
||||
<span class="style-custom-label">Tanggal</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">
|
||||
<p class="style-custom-label">
|
||||
{{ value | date : "MM/yyyy" }}
|
||||
</p>
|
||||
</ng-template>
|
||||
@@ -365,10 +364,10 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Status</span>
|
||||
<span class="style-custom-label">Status</span>
|
||||
</ng-template>
|
||||
<ng-template ngx-datatable-cell-template let-value="value">
|
||||
<p style="color: #ffffff !important">
|
||||
<p class="style-custom-label">
|
||||
{{ value === 2 ? "Aktif" : "Tidak Aktif" }}
|
||||
</p>
|
||||
</ng-template>
|
||||
@@ -379,7 +378,7 @@
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Actions</span>
|
||||
<span class="style-custom-label">Actions</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
@@ -389,14 +388,14 @@
|
||||
<button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
border-color: #37A647 !important;
|
||||
"
|
||||
(click)="viewRow(row)"
|
||||
>
|
||||
<i
|
||||
class="ficon ri-export-line"
|
||||
style="color: #bef264 !important"
|
||||
style="color: #37A647 !important"
|
||||
></i>
|
||||
</button>
|
||||
</ng-template>
|
||||
|
||||
@@ -54,7 +54,8 @@ export class CostManagementComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Cost Management",
|
||||
links: [
|
||||
@@ -91,7 +92,9 @@ export class CostManagementComponent implements OnInit {
|
||||
.subscribe((response) => {
|
||||
this.data = response.results.data;
|
||||
this.filteredRows = this.data;
|
||||
this.kwhTerm = response.results.kwh;
|
||||
let kwhData = parseFloat(response.results.kwh);
|
||||
this.kwhTerm = kwhData.toFixed(1);
|
||||
|
||||
this.costTerm = response.results.cost;
|
||||
|
||||
this.data_cost = this.filteredRows.map((item) => ({
|
||||
@@ -99,7 +102,7 @@ export class CostManagementComponent implements OnInit {
|
||||
roomName: item.room_name,
|
||||
categoryName: item.category_name,
|
||||
estimationCost: item.estimation_cost,
|
||||
totalUse: item.total_use,
|
||||
totalUse: item.total_use.toFixed(1),
|
||||
endDate: this.convertToUTC7(item.end_date),
|
||||
// endDate: item.end_date,
|
||||
statusId: item.status_id,
|
||||
@@ -132,7 +135,9 @@ export class CostManagementComponent implements OnInit {
|
||||
|
||||
dataListBuilding() {
|
||||
this.monitoringApiService.getBuildingList().subscribe((data) => {
|
||||
this.dataBuildingList = data.data.filter((item) => item.statusId === 2);
|
||||
this.dataBuildingList = data.data.filter(
|
||||
(item) => item.statusName.toLowerCase() === "aktif"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -140,88 +145,90 @@ export class CostManagementComponent implements OnInit {
|
||||
this.costService.getCompPrevMonthCost(buildingId).subscribe((data) => {
|
||||
this.dataCompPrev = data.data;
|
||||
this.chartOption = {
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow",
|
||||
},
|
||||
formatter: function (params) {
|
||||
var tar = params[1];
|
||||
return tar.name + "<br/>" + tar.seriesName + " : " + tar.value;
|
||||
},
|
||||
},
|
||||
|
||||
grid: {
|
||||
left: "25%",
|
||||
right: "25%",
|
||||
top: "20%",
|
||||
bottom: "20%",
|
||||
},
|
||||
|
||||
// Add tooltip
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
enterable: false,
|
||||
formatter: function (params) {
|
||||
return `${params[0].name}<br/>${
|
||||
params[0].seriesName
|
||||
}: Rp. ${params[0].value.toLocaleString()}`;
|
||||
color: ["#37A647"],
|
||||
xAxis: {
|
||||
type: "category",
|
||||
splitLine: { show: false },
|
||||
data: [this.dataCompPrev[0].name, this.dataCompPrev[1].name],
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: "#37A647",
|
||||
width: 7,
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
|
||||
// Add legend
|
||||
legend: false,
|
||||
|
||||
// Add custom colors
|
||||
color: ["#BEF264"],
|
||||
|
||||
// Horizontal axis
|
||||
xAxis: [
|
||||
{
|
||||
type: "category",
|
||||
data: [this.dataCompPrev[0].name, this.dataCompPrev[1].name],
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: "#BEF264",
|
||||
width: 4,
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
],
|
||||
|
||||
// Vertical axis
|
||||
yAxis: [
|
||||
{
|
||||
type: "value",
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
],
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
|
||||
// Add series
|
||||
series: [
|
||||
// {
|
||||
// name: "Placeholder",
|
||||
// type: "bar",
|
||||
// stack: "Total",
|
||||
// itemStyle: {
|
||||
// borderColor: "transparent",
|
||||
// color: "transparent",
|
||||
// },
|
||||
// emphasis: {
|
||||
// itemStyle: {
|
||||
// borderColor: "transparent",
|
||||
// color: "transparent",
|
||||
// },
|
||||
// },
|
||||
// data: [1000, 1000],
|
||||
// },
|
||||
{
|
||||
name: "Cost",
|
||||
type: "bar",
|
||||
data: [this.dataCompPrev[0].rupiah, this.dataCompPrev[1].rupiah],
|
||||
stack: "Total",
|
||||
label: {
|
||||
show: true,
|
||||
position: "top",
|
||||
color: "#ffffff",
|
||||
color: "#242222",
|
||||
formatter: function (params) {
|
||||
return `Rp. ${params.value.toLocaleString()}`;
|
||||
},
|
||||
},
|
||||
barWidth: "50%",
|
||||
// barWidth: "50%",
|
||||
data: [this.dataCompPrev[0].rupiah, this.dataCompPrev[1].rupiah],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -232,88 +239,90 @@ export class CostManagementComponent implements OnInit {
|
||||
this.costService.getCompActEstCost(buildingId).subscribe((data) => {
|
||||
this.dataCompAct = data.data[0];
|
||||
this.chartOption2 = {
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow",
|
||||
},
|
||||
formatter: function (params) {
|
||||
var tar = params[1];
|
||||
return tar.name + "<br/>" + tar.seriesName + " : " + tar.value;
|
||||
},
|
||||
},
|
||||
|
||||
grid: {
|
||||
left: "25%",
|
||||
right: "25%",
|
||||
top: "20%",
|
||||
bottom: "20%",
|
||||
},
|
||||
|
||||
// Add tooltip
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
enterable: false,
|
||||
formatter: function (params) {
|
||||
return `${params[0].name}<br/>${
|
||||
params[0].seriesName
|
||||
}: Rp. ${params[0].value.toLocaleString()}`;
|
||||
color: ["#37A647"],
|
||||
xAxis: {
|
||||
type: "category",
|
||||
splitLine: { show: false },
|
||||
data: ["Estimation Cost", "Actual Cost"],
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: "#37A647",
|
||||
width: 7,
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
|
||||
// Add legend
|
||||
legend: false,
|
||||
|
||||
// Add custom colors
|
||||
color: ["#BEF264"],
|
||||
|
||||
// Horizontal axis
|
||||
xAxis: [
|
||||
{
|
||||
type: "category",
|
||||
data: ["Estimation Cost", "Actual Cost"],
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: "#BEF264",
|
||||
width: 4,
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
],
|
||||
|
||||
// Vertical axis
|
||||
yAxis: [
|
||||
{
|
||||
type: "value",
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
],
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
|
||||
// Add series
|
||||
series: [
|
||||
// {
|
||||
// name: "Placeholder",
|
||||
// type: "bar",
|
||||
// stack: "Total",
|
||||
// itemStyle: {
|
||||
// borderColor: "transparent",
|
||||
// color: "transparent",
|
||||
// },
|
||||
// emphasis: {
|
||||
// itemStyle: {
|
||||
// borderColor: "transparent",
|
||||
// color: "transparent",
|
||||
// },
|
||||
// },
|
||||
// data: [2500, 2500],
|
||||
// },
|
||||
{
|
||||
name: "Cost",
|
||||
type: "bar",
|
||||
data: [this.dataCompAct.est_cost, this.dataCompAct.real_cost],
|
||||
stack: "Total",
|
||||
label: {
|
||||
show: true,
|
||||
position: "top",
|
||||
color: "#ffffff",
|
||||
color: "#242222",
|
||||
formatter: function (params) {
|
||||
return `Rp. ${params.value.toLocaleString()}`;
|
||||
},
|
||||
},
|
||||
barWidth: "50%", // Adjust bar width
|
||||
// barWidth: "50%",
|
||||
data: [this.dataCompAct.est_cost, this.dataCompAct.real_cost],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
<div class="modal-body" style="background-color: #252525 !important">
|
||||
<h4 style="color: #ffffff">Input the actual cost of your expenses</h4>
|
||||
<p style="color: #ffffff">Building : {{ buildingName }}</p>
|
||||
<p style="color: #ffffff">Periode : {{ formattedDate }}</p>
|
||||
<div class="modal-body" style="background-color: #FBFBFB !important">
|
||||
<h4 style="color: #242222">Input the actual cost of your expenses</h4>
|
||||
<p style="color: #242222">Building : {{ buildingName }}</p>
|
||||
<p style="color: #242222">Periode : {{ formattedDate }}</p>
|
||||
<form [formGroup]="myForm">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div
|
||||
class="input-group-prepend"
|
||||
style="background-color: #252525 !important"
|
||||
style="background-color: #FBFBFB !important"
|
||||
>
|
||||
<span
|
||||
class="input-group-text"
|
||||
id="basic-addon1"
|
||||
style="
|
||||
background-color: #252525 !important;
|
||||
color: #ffffff;
|
||||
background-color: #FBFBFB !important;
|
||||
color: #242222;
|
||||
height: calc(1.5em + 0.75rem + 2px) !important;
|
||||
"
|
||||
>Rp</span
|
||||
@@ -34,15 +34,15 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer justify-content-between" style="background-color: #252525 !important; border-style: none !important;">
|
||||
<div class="modal-footer justify-content-between" style="background-color: #FBFBFB !important; border-style: none !important;">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
class="btn"
|
||||
style="
|
||||
color: #c3f164;
|
||||
color: #242222;
|
||||
width: 25%;
|
||||
background-color: #252525 !important;
|
||||
border-color: #c3f164 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
border-color: #FBFBFB !important;
|
||||
border-radius: 10px;
|
||||
"
|
||||
(click)="activeModal.dismiss('Cross click')"
|
||||
@@ -51,12 +51,12 @@
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
class="btn"
|
||||
style="
|
||||
color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
width: 25%;
|
||||
background-color: #c3f164 !important;
|
||||
border-color: #c3f164 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
border-radius: 10px;
|
||||
"
|
||||
(click)="addRow()"
|
||||
|
||||
@@ -30,7 +30,8 @@ export class ModalAddActualComponent {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
const currentDate = new Date();
|
||||
this.dateCurrent = currentDate.toISOString().slice(0, 7);
|
||||
this.dateFormat();
|
||||
|
||||
@@ -367,13 +367,15 @@ input[type="month"]::-webkit-calendar-picker-indicator {
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -401,17 +403,40 @@ input[type="month"]::-webkit-calendar-picker-indicator {
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
::ng-deep .modal-backdrop.show {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<div class="modal-body" style="background-color: #5b5b5b !important">
|
||||
<h4 style="color: #ffffff; margin-bottom: 20px !important">
|
||||
<div class="modal-body" style="background-color: #FBFBFB !important">
|
||||
<h4 style="color: #242222; margin-bottom: 20px !important">
|
||||
Comparison of Water and Electricity Costs > {{ dataRow.building }}
|
||||
</h4>
|
||||
<p style="color: #ffffff">Room : {{ dataRow?.roomName }}</p>
|
||||
<p style="color: #ffffff">Category : {{ dataRow?.categoryName }}</p>
|
||||
<p style="color: #242222">Room : {{ dataRow?.roomName }}</p>
|
||||
<p style="color: #242222">Category : {{ dataRow?.categoryName }}</p>
|
||||
|
||||
<div class="card-dashboard">
|
||||
<ngx-datatable
|
||||
@@ -19,43 +19,43 @@
|
||||
>
|
||||
<ngx-datatable-column name="#" [flexGrow]="0.5" [minWidth]="30">
|
||||
<ng-template ngx-datatable-cell-template let-rowIndex="rowIndex">
|
||||
<p style="color: #ffffff !important">
|
||||
<p style="color: #242222 !important">
|
||||
{{ rowIndex + 1 }}
|
||||
</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="periode" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Tanggal</span>
|
||||
<span style="color: #242222 !important">Tanggal</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">
|
||||
<p style="color: #242222 !important">
|
||||
{{ value | date : "dd/MM/yyyy" }}
|
||||
</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="deviceName" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Device</span>
|
||||
<span style="color: #242222 !important">Device</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p style="color: #242222 !important">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="roomName" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Room</span>
|
||||
<span style="color: #242222 !important">Room</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p style="color: #242222 !important">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="categoryName" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Category</span>
|
||||
<span style="color: #242222 !important">Category</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p style="color: #242222 !important">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -64,10 +64,10 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Estimation Cost</span>
|
||||
<span style="color: #242222 !important">Estimation Cost</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">
|
||||
<p style="color: #242222 !important">
|
||||
{{
|
||||
value.toLocaleString("id-ID", {
|
||||
style: "currency",
|
||||
@@ -79,34 +79,34 @@
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="totalKwh" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Total Kwh</span>
|
||||
<span style="color: #242222 !important">Total Kwh</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p style="color: #242222 !important">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="watt" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Watt</span>
|
||||
<span style="color: #242222 !important">Watt</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p style="color: #242222 !important">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="duration" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Duration</span>
|
||||
<span style="color: #242222 !important">Duration</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p style="color: #242222 !important">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="priceKwh" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Price Kwh</span>
|
||||
<span style="color: #242222 !important">Price Kwh</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #ffffff !important">
|
||||
<p style="color: #242222 !important">
|
||||
{{
|
||||
value.toLocaleString("id-ID", {
|
||||
style: "currency",
|
||||
@@ -121,16 +121,16 @@
|
||||
</div>
|
||||
<div
|
||||
class="modal-footer justify-content-between"
|
||||
style="background-color: #252525 !important; border-style: none !important"
|
||||
style="background-color: #FBFBFB !important; border-style: none !important"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
class="btn"
|
||||
style="
|
||||
color: #c3f164;
|
||||
color: #242222;
|
||||
width: 25%;
|
||||
background-color: #252525 !important;
|
||||
border-color: #c3f164 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
border-color: #242222 !important;
|
||||
border-radius: 10px;
|
||||
"
|
||||
(click)="activeModal.dismiss('Cross click')"
|
||||
@@ -139,12 +139,12 @@
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
class="btn"
|
||||
style="
|
||||
color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
width: 25%;
|
||||
background-color: #c3f164 !important;
|
||||
border-color: #c3f164 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
border-radius: 10px;
|
||||
"
|
||||
[disabled]="spinnerExportActive"
|
||||
|
||||
@@ -30,7 +30,8 @@ export class ModalExportComponent {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
const dateRow = this.convertToUTC7(this.dataRow.endDate)
|
||||
this.formattedEndDate = dateRow.slice(0, 7);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #fbfbfb !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,13 +7,13 @@
|
||||
<section id="basic-form-layouts">
|
||||
<div class="row">
|
||||
<div class="col-12" *blockUI="'projectInfo'; message: 'Loading'">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #fbfbfb !important">
|
||||
<div class="card-content">
|
||||
<div
|
||||
class="card-header"
|
||||
style="background-color: #252525 !important"
|
||||
style="background-color: #fbfbfb !important"
|
||||
>
|
||||
<h2 style="color: #ffffff">
|
||||
<h2 style="color: #242222">
|
||||
{{
|
||||
isEditMode()
|
||||
? "Edit Device"
|
||||
@@ -29,14 +29,14 @@
|
||||
(ngSubmit)="onProjectInfoSubmit()"
|
||||
>
|
||||
<div class="form-body">
|
||||
<h4 class="form-section" style="color: #ffffff">
|
||||
<i class="feather ft-user" style="color: #ffffff"></i>
|
||||
<h4 class="form-section" style="color: #242222">
|
||||
<i class="feather ft-user" style="color: #242222"></i>
|
||||
General Information
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="name" style="color: #ffffff"
|
||||
<label for="name" style="color: #242222"
|
||||
>Device Name *</label
|
||||
>
|
||||
<input
|
||||
@@ -63,13 +63,13 @@
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="categoryId" style="color: #ffffff"
|
||||
<label for="categoryId" style="color: #242222"
|
||||
>Category *</label
|
||||
>
|
||||
<div class="input-group">
|
||||
<select
|
||||
id="categoryId"
|
||||
class="form-control"
|
||||
class="form-control custom-select"
|
||||
formControlName="categoryId"
|
||||
[ngClass]="{
|
||||
'is-invalid': submitted && f.categoryId.errors
|
||||
@@ -83,26 +83,28 @@
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<small
|
||||
class="form-text text-muted danger"
|
||||
*ngIf="submitted && f.categoryId.errors"
|
||||
class="invalid-feedback"
|
||||
<div
|
||||
*ngIf="
|
||||
projectInfo.get('categoryId').invalid &&
|
||||
projectInfo.get('categoryId').touched
|
||||
"
|
||||
class="text-danger"
|
||||
>
|
||||
<div *ngIf="f.categoryId.errors.required">
|
||||
Category is required
|
||||
</div>
|
||||
</small>
|
||||
<small class="text-danger"
|
||||
>Category is required.</small
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="voltageId" style="color: #ffffff"
|
||||
<label for="voltageId" style="color: #242222"
|
||||
>Voltage *</label
|
||||
>
|
||||
<div class="input-group">
|
||||
<select
|
||||
id="voltageId"
|
||||
class="form-control"
|
||||
class="form-control custom-select"
|
||||
formControlName="voltageId"
|
||||
[ngClass]="{
|
||||
'is-invalid': submitted && f.voltageId.errors
|
||||
@@ -116,25 +118,27 @@
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<small
|
||||
class="form-text text-muted danger"
|
||||
*ngIf="submitted && f.voltageId.errors"
|
||||
class="invalid-feedback"
|
||||
<div
|
||||
*ngIf="
|
||||
projectInfo.get('voltageId').invalid &&
|
||||
projectInfo.get('voltageId').touched
|
||||
"
|
||||
class="text-danger"
|
||||
>
|
||||
<div *ngIf="f.voltageId.errors.required">
|
||||
Voltage is required
|
||||
</div>
|
||||
</small>
|
||||
<small class="text-danger"
|
||||
>Voltage is required.</small
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="typeId" style="color: #ffffff"
|
||||
<label for="typeId" style="color: #242222"
|
||||
>Type *</label
|
||||
>
|
||||
<select
|
||||
id="typeId"
|
||||
class="form-control"
|
||||
class="form-control custom-select"
|
||||
formControlName="typeId"
|
||||
[ngClass]="{
|
||||
'is-invalid': submitted && f.typeId.errors
|
||||
@@ -160,12 +164,12 @@
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="durationId" style="color: #ffffff"
|
||||
<label for="durationId" style="color: #242222"
|
||||
>Duration Use *</label
|
||||
>
|
||||
<select
|
||||
id="durationId"
|
||||
class="form-control"
|
||||
class="form-control custom-select"
|
||||
formControlName="durationId"
|
||||
[ngClass]="{
|
||||
'is-invalid': submitted && f.durationId.errors
|
||||
@@ -191,12 +195,12 @@
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="roomBuildingId" style="color: #ffffff"
|
||||
<label for="roomBuildingId" style="color: #242222"
|
||||
>Location Room *</label
|
||||
>
|
||||
<select
|
||||
id="roomBuildingId"
|
||||
class="form-control"
|
||||
class="form-control custom-select"
|
||||
formControlName="roomBuildingId"
|
||||
[ngClass]="{
|
||||
'is-invalid':
|
||||
@@ -223,7 +227,7 @@
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="watt" style="color: #ffffff"
|
||||
<label for="watt" style="color: #242222"
|
||||
>Watt *</label
|
||||
>
|
||||
<input
|
||||
@@ -237,15 +241,15 @@
|
||||
'is-invalid': submitted && f.watt.errors
|
||||
}"
|
||||
/>
|
||||
<small
|
||||
class="form-text text-muted danger"
|
||||
*ngIf="submitted && f.watt.errors"
|
||||
class="invalid-feedback"
|
||||
<div
|
||||
*ngIf="
|
||||
projectInfo.get('watt').invalid &&
|
||||
projectInfo.get('watt').touched
|
||||
"
|
||||
class="text-danger"
|
||||
>
|
||||
<div *ngIf="f.watt.errors.required">
|
||||
watt is required
|
||||
</div>
|
||||
</small>
|
||||
<small class="text-danger">Please enter a valid Watt.</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -255,21 +259,22 @@
|
||||
type="button"
|
||||
class="btn btn-warning mr-1"
|
||||
style="
|
||||
color: #c3f164 !important;
|
||||
background-color: #000000 !important;
|
||||
border-color: #c3f164 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #fbfbfb !important;
|
||||
border-color: #fbfbfb !important;
|
||||
"
|
||||
(click)="cancel()"
|
||||
>
|
||||
<i class="feather ft-x"></i>
|
||||
<i *ngIf="mode === 'edit'" class="feather ft-x"></i>
|
||||
<i *ngIf="mode === 'view'" class="la la-arrow-left"></i>
|
||||
{{ mode === "edit" ? "Cancel" : "Back" }}
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
background-color: #c3f164 !important;
|
||||
color: #ffffff !important;
|
||||
background-color: #37a647 !important;
|
||||
"
|
||||
(click)="saveEdit()"
|
||||
*ngIf="mode === 'edit'"
|
||||
|
||||
@@ -4,13 +4,14 @@ import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { BlockUI, NgBlockUI } from "ng-block-ui";
|
||||
import { BuildingService } from "../../service/monitoring-api.service";
|
||||
import { LoginService } from "../../service/login.service";
|
||||
import Swal from "sweetalert2";
|
||||
|
||||
@Component({
|
||||
selector: "app-add-edit-device",
|
||||
templateUrl: "./add-edit-device.component.html",
|
||||
styleUrls: ["./add-edit-device.component.css"],
|
||||
})
|
||||
export class AddEditDeviceComponent implements OnInit{
|
||||
export class AddEditDeviceComponent implements OnInit {
|
||||
@ViewChild("f", { read: true }) userProfileForm: NgForm;
|
||||
dataMasterCategori: any;
|
||||
dataMasterVoltage: any;
|
||||
@@ -41,9 +42,10 @@ export class AddEditDeviceComponent implements OnInit{
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.route.params.subscribe(params => {
|
||||
const id = params['id'];
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.route.params.subscribe((params) => {
|
||||
const id = params["id"];
|
||||
this.deviceId = id;
|
||||
if (id) {
|
||||
this.loadDevice(id);
|
||||
@@ -51,7 +53,7 @@ export class AddEditDeviceComponent implements OnInit{
|
||||
this.dataListRoomBuilding();
|
||||
}
|
||||
});
|
||||
this.setBreadcrumb()
|
||||
this.setBreadcrumb();
|
||||
this.route.data.subscribe((data) => {
|
||||
this.mode = data.mode;
|
||||
});
|
||||
@@ -63,57 +65,79 @@ export class AddEditDeviceComponent implements OnInit{
|
||||
typeId: ["", Validators.required],
|
||||
durationId: ["", Validators.required],
|
||||
roomBuildingId: ["", Validators.required],
|
||||
watt: ["", Validators.required],
|
||||
watt: ["", [Validators.required, Validators.maxLength(15), Validators.pattern(/^[0-9]{1,7}$/)]],
|
||||
});
|
||||
}
|
||||
|
||||
loadDevice(deviceId: string) {
|
||||
this.monitoringApiService.getDeviceById(deviceId).subscribe(data => {
|
||||
this.monitoringApiService.getDeviceById(deviceId).subscribe((data) => {
|
||||
this.dataDevice = data;
|
||||
this.formGetDevice(data)
|
||||
console.log(this.dataDevice);
|
||||
|
||||
this.formGetDevice(data);
|
||||
});
|
||||
}
|
||||
|
||||
dataListMaster() {
|
||||
this.monitoringApiService.getMasterListData().subscribe(data => {
|
||||
this.monitoringApiService.getMasterListData().subscribe((data) => {
|
||||
const dataCategory = data.data.find(
|
||||
(item) => item.name === "master_category"
|
||||
).headerDetailParam;
|
||||
this.dataMasterCategori = dataCategory.filter(item => item.statusName.toLowerCase() === "aktif")
|
||||
this.dataMasterCategori = dataCategory.filter(
|
||||
(item) =>
|
||||
item.statusName.toLowerCase() === "aktif" ||
|
||||
item.status.toLowerCase() === "71"
|
||||
);
|
||||
|
||||
const dataVoltage = data.data.find(
|
||||
const dataVoltage = data.data.find(
|
||||
(item) => item.name === "master_voltage"
|
||||
).headerDetailParam;
|
||||
this.dataMasterVoltage = dataVoltage.filter(item => item.statusName.toLowerCase() === "aktif")
|
||||
this.dataMasterVoltage = dataVoltage.filter(
|
||||
(item) =>
|
||||
item.statusName.toLowerCase() === "aktif" ||
|
||||
item.status.toLowerCase() === "71"
|
||||
);
|
||||
|
||||
const dataType = data.data.find(
|
||||
(item) => item.name === "master_type"
|
||||
).headerDetailParam;
|
||||
this.dataMasterType = dataType.filter(item => item.statusName.toLowerCase() === "aktif")
|
||||
this.dataMasterType = dataType.filter(
|
||||
(item) =>
|
||||
item.statusName.toLowerCase() === "aktif" ||
|
||||
item.status.toLowerCase() === "71"
|
||||
);
|
||||
|
||||
const dataDuration = data.data.find(
|
||||
(item) => item.name === "master_duration"
|
||||
).headerDetailParam;
|
||||
this.dataMasterDuration = dataDuration.filter(item => item.statusName.toLowerCase() === "aktif")
|
||||
this.dataMasterDuration = dataDuration.filter(
|
||||
(item) =>
|
||||
item.statusName.toLowerCase() === "aktif" ||
|
||||
item.status.toLowerCase() === "71"
|
||||
);
|
||||
|
||||
const dataStatus = data.data.find(
|
||||
(item) => item.name === "master_status"
|
||||
).headerDetailParam;
|
||||
this.dataMasterStatus = dataStatus.filter(item => item.statusName.toLowerCase() === "aktif")
|
||||
this.dataMasterStatus = dataStatus.filter(
|
||||
(item) =>
|
||||
item.statusName.toLowerCase() === "aktif" ||
|
||||
item.status.toLowerCase() === "71"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
dataListRoomBuilding() {
|
||||
this.monitoringApiService.getBuildingRoomList().subscribe(data => {
|
||||
const newArray = data.results.data.map(item => ({
|
||||
this.monitoringApiService.getBuildingRoomList().subscribe((data) => {
|
||||
const newArray = data.results.data.map((item) => ({
|
||||
id: item.id,
|
||||
name: `${item.buildingEntity.name} (${item.roomEntity.name})`
|
||||
name: `${item.buildingEntity.name} (${item.roomEntity.name})`,
|
||||
}));
|
||||
this.dataBuildingRoomList = newArray
|
||||
this.dataBuildingRoomList = newArray;
|
||||
});
|
||||
}
|
||||
|
||||
formGetDevice(data){
|
||||
formGetDevice(data) {
|
||||
this.projectInfo.patchValue({
|
||||
name: data.data.name,
|
||||
categoryId: data.data.categoryId,
|
||||
@@ -121,21 +145,24 @@ export class AddEditDeviceComponent implements OnInit{
|
||||
typeId: data.data.typeId,
|
||||
durationId: data.data.durationId,
|
||||
roomBuildingId: data.data.roomBuildingId,
|
||||
watt: data.data.watt
|
||||
watt: data.data.watt,
|
||||
});
|
||||
if (this.mode === 'view') {
|
||||
if (this.mode === "view") {
|
||||
this.formDisable();
|
||||
}
|
||||
if (this.projectInfo.get("roomBuildingId").value) {
|
||||
this.projectInfo.get("roomBuildingId").disable();
|
||||
}
|
||||
}
|
||||
|
||||
formDisable(){
|
||||
this.projectInfo.get('name').disable()
|
||||
this.projectInfo.get('categoryId').disable()
|
||||
this.projectInfo.get('voltageId').disable()
|
||||
this.projectInfo.get('typeId').disable()
|
||||
this.projectInfo.get('durationId').disable()
|
||||
this.projectInfo.get('roomBuildingId').disable()
|
||||
this.projectInfo.get('watt').disable()
|
||||
formDisable() {
|
||||
this.projectInfo.get("name").disable();
|
||||
this.projectInfo.get("categoryId").disable();
|
||||
this.projectInfo.get("voltageId").disable();
|
||||
this.projectInfo.get("typeId").disable();
|
||||
this.projectInfo.get("durationId").disable();
|
||||
this.projectInfo.get("roomBuildingId").disable();
|
||||
this.projectInfo.get("watt").disable();
|
||||
}
|
||||
|
||||
setBreadcrumb() {
|
||||
@@ -225,11 +252,53 @@ export class AddEditDeviceComponent implements OnInit{
|
||||
if (event.keyCode !== 8 && !pattern.test(inputChar)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
saveEdit() {
|
||||
this.monitoringApiService.putDevice(this.projectInfo.value, this.deviceId).subscribe(data => {
|
||||
this.router.navigate(["/device"]);
|
||||
if (this.projectInfo.valid) {
|
||||
if (this.dataDevice.data.roomBuildingId) {
|
||||
this.monitoringApiService
|
||||
.putDevice(this.projectInfo.value, this.deviceId)
|
||||
.subscribe((data) => {
|
||||
this.router.navigate(["/device"]);
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: "Apakah kamu yakin?",
|
||||
text: "Data lokasi device tidak dapat diubah!",
|
||||
icon: "warning",
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: "#37a647",
|
||||
cancelButtonColor: "#d33",
|
||||
confirmButtonText: "Yes, save it!",
|
||||
allowOutsideClick: false,
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
this.monitoringApiService
|
||||
.putDevice(this.projectInfo.value, this.deviceId)
|
||||
.subscribe((data) => {
|
||||
this.router.navigate(["/device"]);
|
||||
});
|
||||
Swal.fire({
|
||||
title: "Saved!",
|
||||
text: "Data berhasil disimpan.",
|
||||
icon: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.markFormGroupTouched(this.projectInfo)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
markFormGroupTouched(formGroup: FormGroup) {
|
||||
(Object as any).values(formGroup.controls).forEach((control) => {
|
||||
control.markAsTouched();
|
||||
if (control.controls) {
|
||||
this.markFormGroupTouched(control);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
::ng-deep .modal-backdrop.show {
|
||||
z-index: auto !important;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<div class="modal-header" style="background-color: #fbfbfb !important">
|
||||
<h4 class="modal-title" style="color: #242222">{{ labelModal }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
aria-label="Close"
|
||||
(click)="activeModal.dismiss('Cross click')"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body" style="background-color: #fbfbfb !important">
|
||||
<form [formGroup]="myForm">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="name" style="color: #242222">Name:</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="name"
|
||||
formControlName="name"
|
||||
maxlength="50"
|
||||
/>
|
||||
<div
|
||||
*ngIf="myForm.get('name').touched && myForm.get('name').invalid"
|
||||
class="text-danger"
|
||||
>
|
||||
Name is required.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="timeset" style="color: #242222">Time</label>
|
||||
<input
|
||||
type="time"
|
||||
class="form-control"
|
||||
formControlName="timeset"
|
||||
id="timeset"
|
||||
/>
|
||||
<div
|
||||
*ngIf="myForm.get('timeset').touched && myForm.get('timeset').invalid"
|
||||
class="text-danger"
|
||||
>
|
||||
Time On is required.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="switch" style="color: #242222">Switch:</label>
|
||||
<select
|
||||
id="switch"
|
||||
class="form-control custom-select"
|
||||
formControlName="switch"
|
||||
>
|
||||
<option *ngFor="let data of dataSwitch" [value]="data.value">
|
||||
{{ data.label }}
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
*ngIf="myForm.get('switch').touched && myForm.get('switch').invalid"
|
||||
class="text-danger"
|
||||
>
|
||||
Switch is required.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Checkbox for Days of the Week -->
|
||||
<div class="form-group col-md-12">
|
||||
<label style="color: #242222">Select Days:</label>
|
||||
<div *ngFor="let day of daysOfWeek">
|
||||
<div class="form-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-check-input"
|
||||
[formControlName]="day.value"
|
||||
(change)="onDayChange(day.value, $event.target.checked)"
|
||||
/>
|
||||
<label class="form-check-label" style="color: #242222">{{
|
||||
day.label
|
||||
}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="myForm.hasError('noDaySelected') && myForm.touched" class="text-danger">
|
||||
Please select at least one day.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Checkbox for Repeat -->
|
||||
<div class="form-group col-md-12">
|
||||
<label style="color: #242222">Repeat:</label>
|
||||
<div class="form-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-check-input"
|
||||
formControlName="recurring"
|
||||
/>
|
||||
<label class="form-check-label" style="color: #242222">Yes</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="form-group col-md-12">
|
||||
<label for="active" style="color: #242222">Active:</label>
|
||||
<select
|
||||
id="active"
|
||||
class="form-control custom-select"
|
||||
formControlName="active"
|
||||
>
|
||||
<option *ngFor="let data of dataActive" [value]="data.value">
|
||||
{{ data.label }}
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
*ngIf="myForm.get('active').touched && myForm.get('active').invalid"
|
||||
class="text-danger"
|
||||
>
|
||||
Active is required.
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer" style="background-color: #fbfbfb !important">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #242222 !important;
|
||||
background-color: #fbfbfb !important;
|
||||
border-color: #fbfbfb !important;
|
||||
"
|
||||
(click)="activeModal.dismiss('Cross click')"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
style="color: #ffffff !important; background-color: #37a647 !important"
|
||||
class="btn btn-primary"
|
||||
(click)="save()"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ControlSchedulerComponent } from './control-scheduler.component';
|
||||
|
||||
describe('ControlSchedulerComponent', () => {
|
||||
let component: ControlSchedulerComponent;
|
||||
let fixture: ComponentFixture<ControlSchedulerComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ControlSchedulerComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ControlSchedulerComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,175 @@
|
||||
import { Component, Input } from "@angular/core";
|
||||
import {
|
||||
FormBuilder,
|
||||
FormControl,
|
||||
FormGroup,
|
||||
Validators,
|
||||
} from "@angular/forms";
|
||||
import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { DeviceService } from "../../service/device.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-control-scheduler",
|
||||
templateUrl: "./control-scheduler.component.html",
|
||||
styleUrls: ["./control-scheduler.component.css"],
|
||||
})
|
||||
export class ControlSchedulerComponent {
|
||||
@Input() deviceId: any;
|
||||
@Input() data: any;
|
||||
@Input() mode: any;
|
||||
labelModal: string = "";
|
||||
myForm: FormGroup;
|
||||
dataSwitch = [
|
||||
{
|
||||
label: "On",
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: "Off",
|
||||
value: false,
|
||||
},
|
||||
];
|
||||
|
||||
dataActive = [
|
||||
{
|
||||
label: "Active",
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: "Non Active",
|
||||
value: false,
|
||||
},
|
||||
];
|
||||
|
||||
daysOfWeek = [
|
||||
{ label: "Monday", value: "monday" },
|
||||
{ label: "Tuesday", value: "tuesday" },
|
||||
{ label: "Wednesday", value: "wednesday" },
|
||||
{ label: "Thursday", value: "thursday" },
|
||||
{ label: "Friday", value: "friday" },
|
||||
{ label: "Saturday", value: "saturday" },
|
||||
{ label: "Sunday", value: "sunday" },
|
||||
];
|
||||
|
||||
selectedDays: string[] = [];
|
||||
|
||||
constructor(
|
||||
public activeModal: NgbActiveModal,
|
||||
private fb: FormBuilder,
|
||||
private deviceService: DeviceService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.createForm();
|
||||
if (this.mode === "add") {
|
||||
this.labelModal = "Add Scheduler";
|
||||
} else if (this.mode === "edit") {
|
||||
this.editForm();
|
||||
this.labelModal = "Edit Scheduler";
|
||||
}
|
||||
}
|
||||
|
||||
createForm() {
|
||||
const controls = {
|
||||
name: ["", Validators.required],
|
||||
timeset: ["", Validators.required],
|
||||
active: [true],
|
||||
switch: [false],
|
||||
recurring: [true], // Default value for repeat checkbox
|
||||
device_id: this.deviceId,
|
||||
};
|
||||
|
||||
// Initialize checkboxes for each day of the week
|
||||
this.daysOfWeek.forEach((day) => {
|
||||
controls[day.value] = [false]; // Each day starts as unchecked
|
||||
});
|
||||
|
||||
this.myForm = this.fb.group(controls);
|
||||
this.myForm.setValidators(this.atLeastOneDaySelectedValidator());
|
||||
}
|
||||
|
||||
editForm() {
|
||||
this.selectedDays = this.data.days || [];
|
||||
this.myForm.patchValue({
|
||||
name: this.data.name,
|
||||
timeset: this.data.timeset,
|
||||
recurring: this.data.recurring,
|
||||
active: this.data.active,
|
||||
switch: this.data.switch,
|
||||
});
|
||||
|
||||
// Patch the form with the selected days
|
||||
this.selectedDays.forEach((day) => {
|
||||
this.myForm.patchValue({
|
||||
[day]: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
atLeastOneDaySelectedValidator() {
|
||||
return (formGroup: FormGroup) => {
|
||||
const selectedDays = this.daysOfWeek.some(
|
||||
(day) => formGroup.get(day.value)?.value
|
||||
);
|
||||
return selectedDays ? null : { noDaySelected: true };
|
||||
};
|
||||
}
|
||||
|
||||
onDayChange(day: string, isChecked: boolean) {
|
||||
if (isChecked) {
|
||||
this.selectedDays.push(day);
|
||||
} else {
|
||||
this.selectedDays = this.selectedDays.filter((d) => d !== day);
|
||||
}
|
||||
}
|
||||
|
||||
save() {
|
||||
if (this.myForm.valid) {
|
||||
const formValues = this.myForm.value;
|
||||
|
||||
// Collect selected days' labels
|
||||
const selectedDays = this.daysOfWeek
|
||||
.filter((day) => formValues[day.value])
|
||||
.map((day) => day.value);
|
||||
|
||||
// Construct the final output
|
||||
let result = {};
|
||||
|
||||
if (this.mode === "add") {
|
||||
result = {
|
||||
name: formValues.name,
|
||||
device_id: formValues.device_id,
|
||||
timeset: formValues.timeset,
|
||||
recurring: formValues.recurring,
|
||||
active: formValues.active,
|
||||
switch: formValues.switch,
|
||||
days: selectedDays,
|
||||
};
|
||||
} else {
|
||||
result = {
|
||||
id: this.data.id,
|
||||
name: formValues.name,
|
||||
device_id: formValues.device_id,
|
||||
timeset: formValues.timeset,
|
||||
recurring: formValues.recurring,
|
||||
active: formValues.active,
|
||||
switch: formValues.switch,
|
||||
days: selectedDays,
|
||||
};
|
||||
}
|
||||
|
||||
this.activeModal.close(result);
|
||||
} else {
|
||||
this.markFormGroupTouched(this.myForm);
|
||||
}
|
||||
}
|
||||
|
||||
markFormGroupTouched(formGroup: FormGroup) {
|
||||
(Object as any).values(formGroup.controls).forEach((control) => {
|
||||
control.markAsTouched();
|
||||
if (control.controls) {
|
||||
this.markFormGroupTouched(control);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,54 @@
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important; /* Menambahkan border-radius */
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
|
||||
.background-round {
|
||||
background-color: #252525 !important;
|
||||
padding: 8px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #BEF264;
|
||||
border-color: #BEF264 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.text-custom-name{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.text-custom-category{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.menu-popup {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 30px;
|
||||
background-color: white;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.menu-popup ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.menu-popup ul li {
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menu-popup ul li:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important;">
|
||||
<div class="app-content content" style="background-color: #fbfbfb !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,7 +7,13 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div
|
||||
class="card"
|
||||
style="
|
||||
background-color: #fbfbfb !important;
|
||||
box-shadow: none !important;
|
||||
"
|
||||
>
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
@@ -21,7 +27,7 @@
|
||||
bindValue="id"
|
||||
placeholder="Select Building"
|
||||
[(ngModel)]="buildingSelected"
|
||||
style="width: 100% !important;"
|
||||
style="width: 100% !important"
|
||||
>
|
||||
</ng-select>
|
||||
</div>
|
||||
@@ -58,12 +64,13 @@
|
||||
<div class="d-flex">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-success ml-2"
|
||||
class="btn ml-2"
|
||||
(click)="doFilter()"
|
||||
style="
|
||||
background-color: #252525 !important;
|
||||
background-color: #37a647 !important;
|
||||
border-color: #ffffff !important;
|
||||
border-radius: 12px;
|
||||
color: #ffffff;
|
||||
"
|
||||
[disabled]="spinnerFilterActive"
|
||||
>
|
||||
@@ -83,9 +90,9 @@
|
||||
class="btn btn-outline-success ml-2"
|
||||
(click)="doCancelFilter()"
|
||||
style="
|
||||
background-color: #252525 !important;
|
||||
border-color: #ffffff !important;
|
||||
color: #ffffff;
|
||||
background-color: #fbfbfb !important;
|
||||
border-color: #6b6b6b !important;
|
||||
color: #6b6b6b;
|
||||
border-radius: 12px;
|
||||
"
|
||||
>
|
||||
@@ -103,10 +110,18 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12" *ngIf="filteredRows?.length === 0">
|
||||
<div class="card" style="background-color: #252525; min-height: 200px;">
|
||||
<div
|
||||
class="card"
|
||||
style="
|
||||
background-color: #fbfbfb !important;
|
||||
box-shadow: none !important;
|
||||
"
|
||||
>
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<p class="text-center" style="color: #ffffff;">No data available</p>
|
||||
<p class="text-center" style="color: #242222">
|
||||
No data available
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -114,7 +129,7 @@
|
||||
<div class="col-lg-4 col-12" *ngFor="let item of filteredDeviceRows">
|
||||
<div
|
||||
class="card"
|
||||
style="background-color: #252525; position: relative"
|
||||
style="background-color: #dde1e6; position: relative"
|
||||
>
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
@@ -122,7 +137,7 @@
|
||||
<div class="align-self-center">
|
||||
<div
|
||||
style="
|
||||
background-color: #414F2B;
|
||||
background-color: #37a647;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
@@ -131,29 +146,51 @@
|
||||
justify-content: center;
|
||||
"
|
||||
>
|
||||
<i class="{{item.category_icon}} font-large-1 blue-grey d-block"
|
||||
style="color: #bef264 !important"
|
||||
<i
|
||||
class="{{
|
||||
item.category_icon
|
||||
}} font-large-1 blue-grey d-block"
|
||||
style="color: #ffffff !important"
|
||||
></i>
|
||||
</div>
|
||||
<div style="margin-top: 10px">
|
||||
<span
|
||||
class="text-muted"
|
||||
style="color: #ffffff !important"
|
||||
>{{ item.name }}</span
|
||||
>
|
||||
<span class="text-custom-name">{{ item.name }}</span>
|
||||
<br />
|
||||
<span
|
||||
class="text-muted"
|
||||
>{{item.category_name}}</span
|
||||
>
|
||||
<span class="text-custom-category">{{
|
||||
item.category_name
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui-switch-container" style="position: absolute; bottom: 10px; right: 10px;">
|
||||
|
||||
<div style="position: absolute; top: 10px; right: 10px">
|
||||
<button
|
||||
(click)="toggleMenu(item.id)"
|
||||
class="btn"
|
||||
style="
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
padding: 0;
|
||||
"
|
||||
>
|
||||
⋮
|
||||
</button>
|
||||
<div *ngIf="item.menuOpen" class="menu-popup">
|
||||
<ul>
|
||||
<li (click)="schedulerItem(item)">scheduler</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ui-switch-container"
|
||||
style="position: absolute; bottom: 10px; right: 10px"
|
||||
>
|
||||
<ui-switch
|
||||
style="border-color: #bef264 !important"
|
||||
class="switchery"
|
||||
switchColor="black"
|
||||
color="rgb(190, 242, 100)"
|
||||
color="rgb(55, 166, 71)"
|
||||
size="small"
|
||||
[checked]="item.status_id === 2"
|
||||
(change)="switchChanged($event, item)"
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { Component, HostListener } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
import { BuildingService } from "../../service/monitoring-api.service";
|
||||
import { DeviceService } from "../../service/device.service";
|
||||
import { ToastrService } from "ngx-toastr";
|
||||
import { LoginService } from "../../service/login.service";
|
||||
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { ControlSchedulerComponent } from "../control-scheduler/control-scheduler.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-device-control",
|
||||
@@ -34,11 +36,13 @@ export class DeviceControlComponent {
|
||||
private deviceService: DeviceService,
|
||||
private monitoringApiService: BuildingService,
|
||||
private toastr: ToastrService,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private modalService: NgbModal,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Device",
|
||||
links: [
|
||||
@@ -77,7 +81,7 @@ export class DeviceControlComponent {
|
||||
filterDevices(devices: any[]): any[] {
|
||||
return devices.filter((device) =>
|
||||
device.mapping.some(
|
||||
(map) => map.name.startsWith("switch") && map.type === "Boolean"
|
||||
(map) => map.code.startsWith("switch") && map.type === "Boolean"
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -99,7 +103,7 @@ export class DeviceControlComponent {
|
||||
|
||||
dataListBuilding() {
|
||||
this.monitoringApiService.getBuildingList().subscribe((data) => {
|
||||
this.dataBuildingList = data.data.filter((item) => item.statusId === 2);
|
||||
this.dataBuildingList = data.data.filter((item) => item.statusName.toLowerCase() === "aktif");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -150,8 +154,8 @@ export class DeviceControlComponent {
|
||||
|
||||
switchChanged(ev, data) {
|
||||
const requestData = {
|
||||
device_id: data.device_id,
|
||||
switch: data.mapping[0].switch,
|
||||
id: data.id,
|
||||
code: data.mapping[0].code,
|
||||
value: ev,
|
||||
command_type: "on_off",
|
||||
};
|
||||
@@ -160,7 +164,50 @@ export class DeviceControlComponent {
|
||||
});
|
||||
}
|
||||
|
||||
addFieldValue() {}
|
||||
toggleMenu(itemId) {
|
||||
this.filteredDeviceRows.forEach(item => {
|
||||
if (item.id === itemId) {
|
||||
item.menuOpen = !item.menuOpen;
|
||||
} else {
|
||||
item.menuOpen = false; // Close other menus
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addDevice(): void {}
|
||||
schedulerItem(row) {
|
||||
console.log(row);
|
||||
|
||||
this.router.navigate(["/device/scheduler", row.id]);
|
||||
}
|
||||
|
||||
// schedulerItem(item) {
|
||||
// const modalRef = this.modalService.open(ControlSchedulerComponent, {
|
||||
// size: "md",
|
||||
// backdrop: "static",
|
||||
// keyboard: false,
|
||||
// centered: true
|
||||
// });
|
||||
|
||||
// modalRef.componentInstance.device = item;
|
||||
// modalRef.result.then(
|
||||
// (result) => {
|
||||
// if (result) {
|
||||
// console.log(result);
|
||||
// }
|
||||
// },
|
||||
// (reason) => {
|
||||
// console.log(`Dismissed: ${reason}`);
|
||||
// }
|
||||
// );
|
||||
// // Handle edit action
|
||||
// }
|
||||
|
||||
@HostListener('document:click', ['$event'])
|
||||
clickout(event) {
|
||||
if (!event.target.closest('.menu-popup') && !event.target.closest('.btn')) {
|
||||
this.filteredDeviceRows.forEach(item => {
|
||||
item.menuOpen = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,19 +271,21 @@
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -311,20 +313,38 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #ffffff !important;
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,22 +7,22 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-lg-4 col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #DDE1E6 !important; box-shadow: none !important;">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h6 class="text-muted" style="color: #ffffff !important">
|
||||
<h6 class="text-custom-label">
|
||||
Total Device
|
||||
</h6>
|
||||
<h3 style="color: #ffffff !important">
|
||||
<h3 class="text-custom-data">
|
||||
{{ summaryTotal?.length }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="align-self-center">
|
||||
<div
|
||||
style="
|
||||
background-color: #414f2b;
|
||||
background-color: #37A647;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
@@ -33,7 +33,7 @@
|
||||
>
|
||||
<i
|
||||
class="ri-device-line primary font-large-1 float-right"
|
||||
style="color: #bef264 !important"
|
||||
style="color: #ffffff !important"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -43,20 +43,20 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #DDE1E6 !important; box-shadow: none !important;">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h6 class="text-light" style="color: #ffffff !important">
|
||||
<h6 class="text-custom-label">
|
||||
Total Device Active
|
||||
</h6>
|
||||
<h3 style="color: #ffffff !important">{{ totalOn }}</h3>
|
||||
<h3 class="text-custom-data">{{ totalOn }}</h3>
|
||||
</div>
|
||||
<div class="align-self-center">
|
||||
<div
|
||||
style="
|
||||
background-color: #414f2b;
|
||||
background-color: #37A647;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
@@ -67,7 +67,7 @@
|
||||
>
|
||||
<i
|
||||
class="feather ft-wifi primary font-large-1 float-right"
|
||||
style="color: #bef264 !important"
|
||||
style="color: #ffffff !important"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -77,20 +77,20 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #DDE1E6 !important; box-shadow: none !important;">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h6 class="text-muted" style="color: #ffffff !important">
|
||||
<h6 class="text-custom-label">
|
||||
Total Device Non-Active
|
||||
</h6>
|
||||
<h3 style="color: #ffffff !important">{{ totalOff }}</h3>
|
||||
<h3 class="text-custom-data">{{ totalOff }}</h3>
|
||||
</div>
|
||||
<div class="align-self-center">
|
||||
<div
|
||||
style="
|
||||
background-color: #414f2b;
|
||||
background-color: #37A647;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
@@ -101,7 +101,7 @@
|
||||
>
|
||||
<i
|
||||
class="feather ft-wifi-off primary font-large-1 float-right"
|
||||
style="color: #bef264 !important"
|
||||
style="color: #ffffff !important"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -116,7 +116,7 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important; box-shadow: none;">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
@@ -169,12 +169,13 @@
|
||||
<div class="d-flex">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-success ml-2"
|
||||
class="btn ml-2"
|
||||
(click)="doFilter()"
|
||||
style="
|
||||
background-color: #252525 !important;
|
||||
border-color: #ffffff !important;
|
||||
background-color: #37A647 !important;
|
||||
border-color: #37A647 !important;
|
||||
border-radius: 12px;
|
||||
color: #ffffff;
|
||||
"
|
||||
[disabled]="spinnerFilterActive || newDeviceActive"
|
||||
>
|
||||
@@ -191,12 +192,12 @@
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-success ml-2"
|
||||
class="btn ml-2"
|
||||
(click)="doCancelFilter()"
|
||||
style="
|
||||
background-color: #252525 !important;
|
||||
border-color: #ffffff !important;
|
||||
color: #ffffff;
|
||||
background-color: #FBFBFB !important;
|
||||
border-color: #242222 !important;
|
||||
color: #242222;
|
||||
border-radius: 12px;
|
||||
"
|
||||
>
|
||||
@@ -213,9 +214,9 @@
|
||||
[disabled]="spinnerActive"
|
||||
(click)="addDevice()"
|
||||
style="
|
||||
background-color: #bef264 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #000000 !important;
|
||||
background-color: #37A647 !important;
|
||||
border-color: #37A647 !important;
|
||||
color: #ffffff !important;
|
||||
"
|
||||
>
|
||||
<i
|
||||
@@ -233,9 +234,9 @@
|
||||
[disabled]="spinnerExportActive"
|
||||
(click)="exportDevice()"
|
||||
style="
|
||||
background-color: #bef264 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #000000 !important;
|
||||
background-color: #37A647 !important;
|
||||
border-color: #37A647 !important;
|
||||
color: #ffffff !important;
|
||||
"
|
||||
>
|
||||
<i
|
||||
@@ -257,9 +258,9 @@
|
||||
[disabled]="spinnerNewDeviceActive"
|
||||
(click)="newDevice()"
|
||||
style="
|
||||
background-color: #bef264 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #000000 !important;
|
||||
background-color: #37A647 !important;
|
||||
border-color: #37A647 !important;
|
||||
color: #ffffff !important;
|
||||
"
|
||||
>
|
||||
<i
|
||||
@@ -279,9 +280,9 @@
|
||||
[disabled]="spinnerNewDeviceActive"
|
||||
(click)="allDevice()"
|
||||
style="
|
||||
background-color: #bef264 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #000000 !important;
|
||||
background-color: #37A647 !important;
|
||||
border-color: #37A647 !important;
|
||||
color: #ffffff !important;
|
||||
"
|
||||
>
|
||||
<i
|
||||
@@ -328,7 +329,7 @@
|
||||
[minWidth]="20"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Image</span>
|
||||
<span class="style-custom-label">Image</span>
|
||||
</ng-template>
|
||||
<ng-template ngx-datatable-cell-template let-row="row">
|
||||
<span class="avatar avatar-sm rounded-circle">
|
||||
@@ -342,7 +343,7 @@
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important"
|
||||
<span class="style-custom-label"
|
||||
>Device Name</span
|
||||
>
|
||||
</ng-template>
|
||||
@@ -350,7 +351,7 @@
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -359,7 +360,7 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important"
|
||||
<span class="style-custom-label"
|
||||
>Building</span
|
||||
>
|
||||
</ng-template>
|
||||
@@ -367,7 +368,7 @@
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -376,7 +377,7 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important"
|
||||
<span class="style-custom-label"
|
||||
>Category</span
|
||||
>
|
||||
</ng-template>
|
||||
@@ -384,7 +385,7 @@
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff !important">
|
||||
<p class="style-custom-label">
|
||||
{{ value }}
|
||||
</p>
|
||||
</ng-template>
|
||||
@@ -395,13 +396,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Watt</span>
|
||||
<span class="style-custom-label">Watt</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff !important">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -410,13 +411,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Type</span>
|
||||
<span class="style-custom-label">Type</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff !important">
|
||||
<p class="style-custom-label">
|
||||
{{ value }}
|
||||
</p>
|
||||
</ng-template>
|
||||
@@ -427,13 +428,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Voltage</span>
|
||||
<span class="style-custom-label">Voltage</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff !important">
|
||||
<p class="style-custom-label">
|
||||
{{ value }}
|
||||
</p>
|
||||
</ng-template>
|
||||
@@ -461,7 +462,7 @@
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff !important">Actions</span>
|
||||
<span class="style-custom-label">Actions</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
@@ -471,27 +472,27 @@
|
||||
<button
|
||||
class="btn btn-sm btn-info mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
border-color: #37A647 !important;
|
||||
"
|
||||
(click)="viewRow(row)"
|
||||
>
|
||||
<i
|
||||
class="ficon feather ft-eye"
|
||||
style="color: #bef264 !important"
|
||||
style="color: #37A647 !important"
|
||||
></i>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
border-color: #37A647 !important;
|
||||
"
|
||||
(click)="editRow(row)"
|
||||
>
|
||||
<i
|
||||
class="ficon feather ft-edit"
|
||||
style="color: #bef264 !important"
|
||||
style="color: #37A647 !important"
|
||||
></i>
|
||||
</button>
|
||||
<!-- <button
|
||||
|
||||
@@ -53,7 +53,8 @@ export class DeviceComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Device",
|
||||
links: [
|
||||
@@ -169,7 +170,7 @@ export class DeviceComponent implements OnInit {
|
||||
|
||||
dataListBuilding() {
|
||||
this.monitoringApiService.getBuildingList().subscribe((data) => {
|
||||
this.dataBuildingList = data.data.filter((item) => item.statusId === 2);
|
||||
this.dataBuildingList = data.data.filter((item) => item.statusName.toLowerCase() === "aktif");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ import { AddEditDeviceComponent } from './add-edit-device/add-edit-device.compon
|
||||
import { ModalAddEditComponent } from './modal-add-edit/modal-add-edit.component';
|
||||
import { DeviceControlComponent } from './device-control/device-control.component';
|
||||
import { UiSwitchModule } from 'ngx-ui-switch';
|
||||
import { ControlSchedulerComponent } from './control-scheduler/control-scheduler.component';
|
||||
import { SchedulerListComponent } from './scheduler-list/scheduler-list.component';
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +26,9 @@ import { UiSwitchModule } from 'ngx-ui-switch';
|
||||
DeviceComponent,
|
||||
AddEditDeviceComponent,
|
||||
ModalAddEditComponent,
|
||||
DeviceControlComponent
|
||||
DeviceControlComponent,
|
||||
ControlSchedulerComponent,
|
||||
SchedulerListComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
@@ -63,8 +67,15 @@ import { UiSwitchModule } from 'ngx-ui-switch';
|
||||
path: 'view/:id',
|
||||
component: AddEditDeviceComponent,
|
||||
data: { mode: 'view' }
|
||||
},
|
||||
{
|
||||
path: 'scheduler/:id',
|
||||
component: SchedulerListComponent,
|
||||
data: { mode: 'scheduler' }
|
||||
}
|
||||
])
|
||||
]),
|
||||
|
||||
|
||||
]
|
||||
})
|
||||
export class DeviceModule { }
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
.app-content {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 15px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
padding: 1.5rem;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
background-color: #f7f8fa;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.list-group-item:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.list-group-item h5 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.list-group-item .btn-outline-secondary,
|
||||
.list-group-item .btn-outline-danger {
|
||||
border-radius: 20px;
|
||||
padding: 0.25rem 0.75rem;
|
||||
}
|
||||
|
||||
.btn-light {
|
||||
background-color: #e8eaf6;
|
||||
color: #3f51b5;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
padding: 0.5rem 1.25rem;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn-light:hover {
|
||||
background-color: #d1d9ff;
|
||||
color: #303f9f;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<div class="app-content content" style="background-color: #fbfbfb !important">
|
||||
<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">
|
||||
<section id="basic-form-layouts">
|
||||
<div class="row">
|
||||
<div class="col-6" *blockUI="'projectInfo'; message: 'Loading'">
|
||||
<div class="card" style="background-color: #fbfbfb !important">
|
||||
<div class="card-content">
|
||||
<div
|
||||
class="card-header d-flex justify-content-between align-items-center"
|
||||
style="background-color: #fbfbfb !important"
|
||||
>
|
||||
<h4 class="form-section m-0" style="color: #242222">
|
||||
<i class="feather ft-calendar" style="color: #242222"></i>
|
||||
{{ deviceName ? deviceName : '' }}
|
||||
</h4>
|
||||
|
||||
<button
|
||||
class="btn"
|
||||
style="
|
||||
background-color: #37a647 !important;
|
||||
border-color: #37a647 !important;
|
||||
color: #ffffff !important;
|
||||
"
|
||||
(click)="addSchedulerItem()"
|
||||
>
|
||||
<span style="font-weight: 600">Add Schedule</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div *ngIf="schedules.length > 0; else noSchedules">
|
||||
<ul class="list-group">
|
||||
<li
|
||||
class="list-group-item d-flex justify-content-between align-items-center mb-3"
|
||||
*ngFor="let schedule of listScheduler"
|
||||
>
|
||||
<!-- Tambahkan checkbox di sini -->
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="mr-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
[(ngModel)]="schedule.selected"
|
||||
(change)="checkSelected()"
|
||||
/>
|
||||
</div>
|
||||
<div (click)="editSchedule(schedule)">
|
||||
<h5 style="color: #242222">
|
||||
{{ schedule.name }} ({{
|
||||
schedule.switch ? "On" : "Off"
|
||||
}})
|
||||
</h5>
|
||||
<h2 class="mb-0" style="color: #242222">
|
||||
{{ schedule.timeset }}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<ui-switch
|
||||
style="border-color: #bef264 !important"
|
||||
class="switchery"
|
||||
switchColor="white"
|
||||
color="rgb(55, 166, 71)"
|
||||
size="small"
|
||||
[checked]="schedule.active"
|
||||
(change)="switchChanged($event, schedule)"
|
||||
></ui-switch>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Tambahkan tombol delete di sini -->
|
||||
<div class="d-flex justify-content-center">
|
||||
<button
|
||||
*ngIf="hasSelected"
|
||||
class="btn btn-danger mt-2"
|
||||
(click)="deleteSelectedSchedules()"
|
||||
style="
|
||||
background-color: transparent !important;
|
||||
border-color: #37a647 !important;
|
||||
"
|
||||
>
|
||||
<i
|
||||
class="ficon la la-trash"
|
||||
style="color: #37a647 !important"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #noSchedules>
|
||||
<div class="alert alert-info text-center">
|
||||
<strong>No schedules available.</strong> Click the
|
||||
"Add Schedule" button to create one.
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SchedulerListComponent } from './scheduler-list.component';
|
||||
|
||||
describe('SchedulerListComponent', () => {
|
||||
let component: SchedulerListComponent;
|
||||
let fixture: ComponentFixture<SchedulerListComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ SchedulerListComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(SchedulerListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,192 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { ControlSchedulerComponent } from "../control-scheduler/control-scheduler.component";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { DeviceService } from "../../service/device.service";
|
||||
import Swal from "sweetalert2";
|
||||
@Component({
|
||||
selector: "app-scheduler-list",
|
||||
templateUrl: "./scheduler-list.component.html",
|
||||
styleUrls: ["./scheduler-list.component.css"],
|
||||
})
|
||||
export class SchedulerListComponent {
|
||||
public breadcrumb: any;
|
||||
listScheduler: any;
|
||||
deviceId: any;
|
||||
deviceName: any;
|
||||
hasSelected: boolean = false;
|
||||
schedules = [
|
||||
{
|
||||
id: 1,
|
||||
title: "Lampu Depan ON",
|
||||
time: "08:55",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Lampu Depan OFF",
|
||||
time: "09:50",
|
||||
},
|
||||
];
|
||||
|
||||
constructor(
|
||||
private modalService: NgbModal,
|
||||
private route: ActivatedRoute,
|
||||
private deviceService: DeviceService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.route.params.subscribe((params) => {
|
||||
const id = params["id"];
|
||||
this.deviceId = id;
|
||||
if (id) {
|
||||
this.dataListScheduler(id);
|
||||
this.dataDevice(id);
|
||||
}
|
||||
});
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Scheduler List",
|
||||
linkBack: "/device/control-device",
|
||||
isLinkBack: true,
|
||||
links: [
|
||||
{
|
||||
name: "Home",
|
||||
isLink: false,
|
||||
link: "/dashboard/sales",
|
||||
},
|
||||
{
|
||||
name: "Control Device",
|
||||
isLink: false,
|
||||
},
|
||||
{
|
||||
name: "Scheduler List",
|
||||
isLink: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
dataListScheduler(id) {
|
||||
this.deviceService.getDeviceScheduler(id).subscribe((data) => {
|
||||
this.listScheduler = data.results;
|
||||
console.log(this.listScheduler);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
dataDevice(id) {
|
||||
this.deviceService.getDeviceByid(id).subscribe((data) => {
|
||||
this.deviceName = data.data.name
|
||||
});
|
||||
}
|
||||
|
||||
switchChanged(e, item) {
|
||||
const data = {
|
||||
id: item.id,
|
||||
active: e,
|
||||
};
|
||||
this.deviceService.putDeviceSchedulerActive(data, item.id).subscribe((res) => {
|
||||
this.dataListScheduler(this.deviceId);
|
||||
});
|
||||
}
|
||||
|
||||
addSchedulerItem() {
|
||||
const modalRef = this.modalService.open(ControlSchedulerComponent, {
|
||||
size: "md",
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
centered: true,
|
||||
});
|
||||
|
||||
modalRef.componentInstance.deviceId = this.deviceId;
|
||||
modalRef.componentInstance.mode = "add";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
if (result) {
|
||||
this.deviceService.postDeviceScheduler(result).subscribe((res) => {
|
||||
this.dataListScheduler(this.deviceId);
|
||||
});
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
}
|
||||
);
|
||||
// Handle edit action
|
||||
}
|
||||
|
||||
editSchedule(data) {
|
||||
const modalRef = this.modalService.open(ControlSchedulerComponent, {
|
||||
size: "md",
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
centered: true,
|
||||
});
|
||||
|
||||
modalRef.componentInstance.deviceId = this.deviceId;
|
||||
modalRef.componentInstance.data = data;
|
||||
modalRef.componentInstance.mode = "edit";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
if (result) {
|
||||
this.deviceService
|
||||
.putDeviceScheduler(result, data.id)
|
||||
.subscribe((res) => {
|
||||
this.dataListScheduler(this.deviceId);
|
||||
});
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
checkSelected() {
|
||||
this.hasSelected = this.listScheduler.some((schedule) => schedule.selected);
|
||||
}
|
||||
|
||||
deleteSelectedSchedules() {
|
||||
const selectedSchedules = this.listScheduler.filter(
|
||||
(schedule) => schedule.selected
|
||||
);
|
||||
|
||||
if (selectedSchedules.length > 0) {
|
||||
Swal.fire({
|
||||
title: "Apakah kamu yakin ingin menghapus jadwal yang dipilih?",
|
||||
text: "Tindakan ini tidak dapat dibatalkan.",
|
||||
icon: "warning",
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: "#37a647",
|
||||
cancelButtonColor: "#d33",
|
||||
confirmButtonText: "Ya, hapus!",
|
||||
cancelButtonText: "Batal",
|
||||
allowOutsideClick: false,
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
selectedSchedules.forEach((schedule) => {
|
||||
this.deleteSchedule(schedule.id);
|
||||
});
|
||||
|
||||
Swal.fire({
|
||||
title: "Terhapus!",
|
||||
text: "Jadwal yang dipilih berhasil dihapus.",
|
||||
icon: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: "Tidak ada jadwal yang dipilih!",
|
||||
text: "Pilih setidaknya satu jadwal untuk dihapus.",
|
||||
icon: "info",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
deleteSchedule(id) {
|
||||
this.deviceService.deleteDeviceScheduler(id).subscribe(() => {
|
||||
this.dataListScheduler(this.deviceId);
|
||||
this.hasSelected = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #fbfbfb !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,13 +7,13 @@
|
||||
<section id="basic-form-layouts">
|
||||
<div class="row">
|
||||
<div class="col-12" *blockUI="'projectInfo'; message: 'Loading'">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #fbfbfb !important">
|
||||
<div class="card-content">
|
||||
<div
|
||||
class="card-header"
|
||||
style="background-color: #252525 !important"
|
||||
style="background-color: #fbfbfb !important"
|
||||
>
|
||||
<h2 style="color: #ffffff">
|
||||
<h2 style="color: #242222">
|
||||
{{
|
||||
isEditMode()
|
||||
? "Edit List Monitoring"
|
||||
@@ -29,14 +29,14 @@
|
||||
(ngSubmit)="onProjectInfoSubmit()"
|
||||
>
|
||||
<div class="form-body">
|
||||
<h4 class="form-section" style="color: #ffffff">
|
||||
<i class="feather ft-user" style="color: #ffffff"></i>
|
||||
<!-- <h4 class="form-section" style="color: #242222">
|
||||
<i class="feather ft-user" style="color: #242222"></i>
|
||||
General Information
|
||||
</h4>
|
||||
</h4> -->
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="buildingId" style="color: #ffffff"
|
||||
<label for="buildingId" style="color: #242222"
|
||||
>Building *</label
|
||||
>
|
||||
<div class="input-group">
|
||||
@@ -55,49 +55,59 @@
|
||||
{{ data.name }}
|
||||
</option>
|
||||
</select>
|
||||
<button
|
||||
class="btn btn-danger ml-2"
|
||||
type="button"
|
||||
style="
|
||||
color: #ffffff !important;
|
||||
border-color: #37a647 !important;
|
||||
background-color: #37a647 !important;
|
||||
"
|
||||
(click)="modalAddBuilding()"
|
||||
>
|
||||
<i class="feather ft-plus"> New Building</i>
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="projectInfo.get('buildingId').touched && projectInfo.get('buildingId').invalid" class="text-danger">
|
||||
Building is required.
|
||||
</div>
|
||||
<small
|
||||
class="form-text text-muted danger"
|
||||
*ngIf="submitted && f.buildingId.errors"
|
||||
class="invalid-feedback"
|
||||
>
|
||||
<div *ngIf="f.buildingId.errors.required">
|
||||
Building is required
|
||||
</div>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="statusId" style="color: #ffffff"
|
||||
>Status *</label
|
||||
<label for="floorId" style="color: #242222"
|
||||
>Floor *</label
|
||||
>
|
||||
<div class="input-group">
|
||||
<select
|
||||
id="statusId"
|
||||
id="floorId"
|
||||
class="form-control"
|
||||
formControlName="statusId"
|
||||
formControlName="floorId"
|
||||
[ngClass]="{
|
||||
'is-invalid': submitted && f.statusId.errors
|
||||
'is-invalid': submitted && f.floorId.errors
|
||||
}"
|
||||
>
|
||||
<option
|
||||
*ngFor="let data of dataMasterStatus"
|
||||
*ngFor="let data of dataFloorList"
|
||||
[value]="data.id"
|
||||
>
|
||||
{{ data.name }}
|
||||
</option>
|
||||
</select>
|
||||
<button
|
||||
class="btn btn-danger ml-2"
|
||||
type="button"
|
||||
style="
|
||||
color: #ffffff !important;
|
||||
border-color: #37a647 !important;
|
||||
background-color: #37a647 !important;
|
||||
"
|
||||
(click)="modalAddFloor()"
|
||||
>
|
||||
<i class="feather ft-plus"> New Floor</i>
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="projectInfo.get('floorId').touched && projectInfo.get('floorId').invalid" class="text-danger">
|
||||
Floor is required.
|
||||
</div>
|
||||
<small
|
||||
class="form-text text-muted danger"
|
||||
*ngIf="submitted && f.statusId.errors"
|
||||
class="invalid-feedback"
|
||||
>
|
||||
<div *ngIf="f.statusId.errors.required">
|
||||
Status is required
|
||||
</div>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -115,16 +125,17 @@
|
||||
<div [formGroupName]="i" class="">
|
||||
<div class="input-group mb-1">
|
||||
<select
|
||||
id="roomId"
|
||||
id="roomId{{i}}"
|
||||
class="form-control"
|
||||
formControlName="roomId"
|
||||
(change)="validateDouble($event, i)"
|
||||
[ngClass]="{
|
||||
'is-invalid':
|
||||
submitted && f.roomId.errors
|
||||
}"
|
||||
>
|
||||
<option
|
||||
*ngFor="let list of dataRoomList"
|
||||
*ngFor="let list of dataRoomList; trackBy: trackByFn"
|
||||
[value]="list.id"
|
||||
>
|
||||
{{ list.name }}
|
||||
@@ -134,9 +145,9 @@
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #a64f37 !important;
|
||||
background-color: #a64f37 !important;
|
||||
"
|
||||
(click)="removePhone(i)"
|
||||
>
|
||||
@@ -149,15 +160,28 @@
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
[disabled]="disableButton"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #37a647 !important;
|
||||
background-color: #37a647 !important;
|
||||
"
|
||||
(click)="addPhone()"
|
||||
>
|
||||
<i class="feather ft-plus"></i> Add Room
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary ml-2"
|
||||
style="
|
||||
color: #ffffff !important;
|
||||
border-color: #37a647 !important;
|
||||
background-color: #37a647 !important;
|
||||
"
|
||||
(click)="modalAddNewRoom()"
|
||||
>
|
||||
New Room
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-group" *ngIf="mode !== 'add'">
|
||||
<label for="roomId">Room *</label>
|
||||
@@ -188,6 +212,32 @@
|
||||
</div>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="statusId" style="color: #242222"
|
||||
>Status *</label
|
||||
>
|
||||
<div class="input-group">
|
||||
<select
|
||||
id="statusId"
|
||||
class="form-control"
|
||||
formControlName="statusId"
|
||||
[ngClass]="{
|
||||
'is-invalid': submitted && f.statusId.errors
|
||||
}"
|
||||
>
|
||||
<option
|
||||
*ngFor="let data of dataMasterStatus"
|
||||
[value]="data.id"
|
||||
>
|
||||
{{ data.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div *ngIf="projectInfo.get('statusId').touched && projectInfo.get('statusId').invalid" class="text-danger">
|
||||
Status is required.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -196,9 +246,9 @@
|
||||
type="button"
|
||||
class="btn btn-warning mr-1"
|
||||
style="
|
||||
color: #bef264 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #000000 !important;
|
||||
color: #242222 !important;
|
||||
border-color: #242222 !important;
|
||||
background-color: #fbfbfb !important;
|
||||
"
|
||||
(click)="cancel()"
|
||||
>
|
||||
@@ -207,12 +257,12 @@
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
[disabled]="disableButtonSave"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #37a647 !important;
|
||||
background-color: #37a647 !important;
|
||||
"
|
||||
*ngIf="mode !== 'view'"
|
||||
(click)="save()"
|
||||
>
|
||||
<i class="la la-check"></i> Save
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
import { Component, ViewChild } from '@angular/core';
|
||||
import { FormArray, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { BlockUI, NgBlockUI } from 'ng-block-ui';
|
||||
import { BuildingService } from '../../service/monitoring-api.service';
|
||||
import { LoginService } from '../../service/login.service';
|
||||
import { Component, ViewChild } from "@angular/core";
|
||||
import {
|
||||
FormArray,
|
||||
FormBuilder,
|
||||
FormGroup,
|
||||
NgForm,
|
||||
Validators,
|
||||
} from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { BlockUI, NgBlockUI } from "ng-block-ui";
|
||||
import { BuildingService } from "../../service/monitoring-api.service";
|
||||
import { LoginService } from "../../service/login.service";
|
||||
import { ToastrService } from "ngx-toastr";
|
||||
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { AddEditMasterBuildingComponent } from "../../master/master-building/add-edit-master-building/add-edit-master-building.component";
|
||||
import { AddEditMasterComponent } from "../../master/add-edit-master/add-edit-master.component";
|
||||
import { AddEditMasterRoomComponent } from "../../master/master-room/add-edit-master-room/add-edit-master-room.component";
|
||||
import Swal from "sweetalert2";
|
||||
|
||||
@Component({
|
||||
selector: 'app-add-edit-list',
|
||||
templateUrl: './add-edit-list.component.html',
|
||||
styleUrls: ['./add-edit-list.component.css']
|
||||
selector: "app-add-edit-list",
|
||||
templateUrl: "./add-edit-list.component.html",
|
||||
styleUrls: ["./add-edit-list.component.css"],
|
||||
})
|
||||
export class AddEditListComponent {
|
||||
// @ViewChild("f", { read: true }) userProfileForm: NgForm;
|
||||
@@ -21,15 +33,20 @@ export class AddEditListComponent {
|
||||
|
||||
dataBuildingList: any;
|
||||
dataRoomList: any;
|
||||
dataRoomListSementara: any;
|
||||
dataFloorList: any;
|
||||
dataMasterStatus: any;
|
||||
roombuildingId: any;
|
||||
dataRoomBuilding: any;
|
||||
disableButton: boolean = true;
|
||||
disableButtonSave: boolean = true;
|
||||
lewatModal: boolean = false;
|
||||
// userProfileForm: FormGroup;
|
||||
public userList: FormArray;
|
||||
|
||||
@BlockUI("projectInfo") blockUIProjectInfo: NgBlockUI;
|
||||
get userFormGroup() {
|
||||
return this.projectInfo.get('userArray') as FormArray;
|
||||
return this.projectInfo.get("userArray") as FormArray;
|
||||
}
|
||||
|
||||
constructor(
|
||||
@@ -37,100 +54,124 @@ export class AddEditListComponent {
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private monitoringApiService: BuildingService,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private toastr: ToastrService,
|
||||
private modalService: NgbModal
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.route.data.subscribe((data) => {
|
||||
this.mode = data.mode;
|
||||
});
|
||||
this.route.params.subscribe(params => {
|
||||
const id = params['id'];
|
||||
this.route.params.subscribe((params) => {
|
||||
const id = params["id"];
|
||||
this.roombuildingId = id;
|
||||
if (id) {
|
||||
this.loadRoomBuilding(id);
|
||||
}
|
||||
});
|
||||
this.setBreadcrumb();
|
||||
this.dataListBuilding();
|
||||
this.dataListRoom();
|
||||
this.dataListMaster();
|
||||
|
||||
|
||||
this.projectInfo = this.formBuilder.group({
|
||||
buildingId: ["", Validators.required],
|
||||
roomId: [""],
|
||||
statusId: ["", Validators.required],
|
||||
floorId: ["", Validators.required],
|
||||
userArray: this.formBuilder.array([this.createRoom()]),
|
||||
});
|
||||
this.userList = this.projectInfo.get('userArray') as FormArray;
|
||||
this.userList = this.projectInfo.get("userArray") as FormArray;
|
||||
|
||||
this.dataListBuilding();
|
||||
this.dataListRoom();
|
||||
this.dataListMaster();
|
||||
this.dataListFloor();
|
||||
}
|
||||
|
||||
createRoom(): FormGroup {
|
||||
return this.formBuilder.group({
|
||||
roomId: ['', Validators.required]
|
||||
roomId: ["", Validators.required],
|
||||
});
|
||||
}
|
||||
|
||||
addPhone() {
|
||||
this.userList.push(this.createRoom());
|
||||
this.disableButton = true;
|
||||
this.disableButtonSave = true;
|
||||
}
|
||||
|
||||
removePhone(index) {
|
||||
this.userList.removeAt(index);
|
||||
this.isRoomDuplicate(index);
|
||||
if (this.userList.value.length === 0) {
|
||||
this.disableButtonSave = true;
|
||||
}
|
||||
}
|
||||
|
||||
validateDouble(event: any, index: number) {
|
||||
const selectedRoomId = (event.target as HTMLSelectElement).value;
|
||||
if (this.isRoomDuplicate(index)) {
|
||||
this.disableButton = true;
|
||||
this.disableButtonSave = true;
|
||||
this.toastr.error("Room", "Data yang ada masukan double!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
} else {
|
||||
this.disableButton = false;
|
||||
this.disableButtonSave = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
isRoomDuplicate(index: number): boolean {
|
||||
const selectedRooms = this.userFormGroup.value.map((room) => room.roomId);
|
||||
const currentRoomId = selectedRooms[index];
|
||||
const roomOccurrences = selectedRooms.filter(
|
||||
(roomId) => roomId === currentRoomId
|
||||
).length;
|
||||
if (roomOccurrences === 0) {
|
||||
this.disableButton = false;
|
||||
this.disableButtonSave = false;
|
||||
}
|
||||
return roomOccurrences > 1;
|
||||
}
|
||||
|
||||
setBreadcrumb() {
|
||||
if (this.isAddMode()) {
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Cost Management",
|
||||
mainlabel: "List Monitoring",
|
||||
links: [
|
||||
{
|
||||
name: "Home",
|
||||
isLink: false,
|
||||
},
|
||||
{
|
||||
name: "Cost Management",
|
||||
name: "List Monitoring",
|
||||
isLink: false,
|
||||
},
|
||||
{
|
||||
name: "Add New Cost Management",
|
||||
name: "Add New List Monitoring",
|
||||
isLink: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
} else if (this.isEditMode()) {
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Cost Management",
|
||||
mainlabel: "List Monitoring",
|
||||
links: [
|
||||
{
|
||||
name: "Home",
|
||||
isLink: false,
|
||||
},
|
||||
{
|
||||
name: "Cost Management",
|
||||
name: "List Monitoring",
|
||||
isLink: false,
|
||||
},
|
||||
{
|
||||
name: "Edit New Cost Management",
|
||||
isLink: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
} else if (this.isViewMode()) {
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Cost Management",
|
||||
links: [
|
||||
{
|
||||
name: "Home",
|
||||
isLink: false,
|
||||
},
|
||||
{
|
||||
name: "Cost Management",
|
||||
isLink: false,
|
||||
},
|
||||
{
|
||||
name: "View New Cost Management",
|
||||
name: "Edit New List Monitoring",
|
||||
isLink: false,
|
||||
},
|
||||
],
|
||||
@@ -139,28 +180,31 @@ export class AddEditListComponent {
|
||||
}
|
||||
|
||||
loadRoomBuilding(deviceId: string) {
|
||||
this.monitoringApiService.getRoomBuildingById(deviceId).subscribe(data => {
|
||||
this.dataRoomBuilding = data;
|
||||
this.formGetDevice(data)
|
||||
});
|
||||
this.monitoringApiService
|
||||
.getRoomBuildingById(deviceId)
|
||||
.subscribe((data) => {
|
||||
this.dataRoomBuilding = data;
|
||||
this.formGetDevice(data);
|
||||
});
|
||||
}
|
||||
|
||||
formGetDevice(data){
|
||||
formGetDevice(data) {
|
||||
this.projectInfo.patchValue({
|
||||
buildingId: data.data.buildingId,
|
||||
roomId: data.data.roomId,
|
||||
floorId: data.data.floorId,
|
||||
statusId: data.data.statusId,
|
||||
});
|
||||
|
||||
if (this.mode === 'view') {
|
||||
|
||||
if (this.mode === "view") {
|
||||
this.formDisable();
|
||||
}
|
||||
}
|
||||
|
||||
formDisable(){
|
||||
this.projectInfo.get('buildingId').disable()
|
||||
this.projectInfo.get('roomId').disable()
|
||||
this.projectInfo.get('statusId').disable()
|
||||
formDisable() {
|
||||
this.projectInfo.get("buildingId").disable();
|
||||
this.projectInfo.get("roomId").disable();
|
||||
this.projectInfo.get("statusId").disable();
|
||||
}
|
||||
|
||||
isEditMode() {
|
||||
@@ -195,49 +239,227 @@ export class AddEditListComponent {
|
||||
}
|
||||
|
||||
dataListBuilding() {
|
||||
this.monitoringApiService.getBuildingList().subscribe(data => {
|
||||
this.dataBuildingList = data.data.filter(item => item.statusId === 2)
|
||||
this.monitoringApiService.getBuildingList().subscribe((data) => {
|
||||
this.dataBuildingList = data.data
|
||||
.filter(
|
||||
(item) =>
|
||||
item.statusName.toLowerCase() === "aktif" || item.status_id === 71
|
||||
)
|
||||
.sort((a, b) => b.id - a.id);
|
||||
|
||||
if (this.lewatModal) {
|
||||
this.projectInfo.patchValue({
|
||||
buildingId: this.dataBuildingList[0],
|
||||
});
|
||||
this.lewatModal = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dataListRoom() {
|
||||
this.monitoringApiService.getListRoomData().subscribe(data => {
|
||||
this.dataRoomList = data.data
|
||||
this.monitoringApiService.getListRoomDataUnmap().subscribe((data) => {
|
||||
const newArray = data.data.map((item) => ({
|
||||
id: item.id,
|
||||
name: `${item.name} (${item.code})`,
|
||||
})).sort((a, b) => b.id - a.id);
|
||||
this.dataRoomList = newArray;
|
||||
});
|
||||
}
|
||||
|
||||
trackByFn(index: number, option: any): any {
|
||||
return option.id;
|
||||
}
|
||||
|
||||
dataListFloor() {
|
||||
this.monitoringApiService.getListFloorDataUnmap(6).subscribe((data) => {
|
||||
const newArray = data.data.map((item) => ({
|
||||
id: item.id,
|
||||
name: `${item.name} (${item.code})`,
|
||||
status: item.status_name
|
||||
})).sort((a, b) => b.id - a.id);
|
||||
this.dataFloorList = newArray.filter((item) => item.status.toLowerCase() === "aktif");
|
||||
if (this.lewatModal) {
|
||||
this.projectInfo.patchValue({
|
||||
floorId: this.dataFloorList[0],
|
||||
});
|
||||
this.lewatModal = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dataListMaster() {
|
||||
this.monitoringApiService.getMasterListData().subscribe(data => {
|
||||
this.monitoringApiService.getMasterListData().subscribe((data) => {
|
||||
const dataStatus = data.data.find(
|
||||
(item) => item.name === "master_status"
|
||||
).headerDetailParam;
|
||||
this.dataMasterStatus = dataStatus.filter(item => item.statusName.toLowerCase() === "aktif")
|
||||
this.dataMasterStatus = dataStatus.filter(
|
||||
(item) =>
|
||||
item.statusName.toLowerCase() === "aktif" ||
|
||||
item.status.toLowerCase() === "71"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
save() {
|
||||
if (this.mode === 'add') {
|
||||
if (this.mode === "add") {
|
||||
if (this.projectInfo.invalid) {
|
||||
this.markFormGroupTouched(this.projectInfo)
|
||||
return;
|
||||
}
|
||||
const formData = this.projectInfo.value;
|
||||
const transformedData = {
|
||||
buildingId: formData.buildingId,
|
||||
roomId: formData.userArray.map(room => room.roomId),
|
||||
statusId: formData.statusId
|
||||
roomId: formData.userArray.map((room) => room.roomId),
|
||||
statusId: formData.statusId,
|
||||
floorId: formData.floorId,
|
||||
};
|
||||
this.monitoringApiService.postBatchBuilding(transformedData).subscribe((res) => {
|
||||
this.router.navigate(["/list-monitoring"]);
|
||||
});
|
||||
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"]);
|
||||
});
|
||||
this.monitoringApiService
|
||||
.putBuildingRoom(this.projectInfo.value, this.roombuildingId)
|
||||
.subscribe((data) => {
|
||||
this.router.navigate(["/list-monitoring"]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
markFormGroupTouched(formGroup: FormGroup) {
|
||||
(Object as any).values(formGroup.controls).forEach((control) => {
|
||||
control.markAsTouched();
|
||||
if (control.controls) {
|
||||
this.markFormGroupTouched(control);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.router.navigate(["/list-monitoring"]);
|
||||
if (this.projectInfo.dirty) { // Check if form has unsaved changes
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: "You have unsaved changes. Do you really want to leave?",
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#37a647',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes, leave',
|
||||
cancelButtonText: 'No, stay'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
this.router.navigate(["/list-monitoring"]);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.router.navigate(["/list-monitoring"]);
|
||||
}
|
||||
}
|
||||
|
||||
modalAddBuilding() {
|
||||
const modalRef = this.modalService.open(AddEditMasterBuildingComponent, {
|
||||
size: "lg",
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
});
|
||||
|
||||
modalRef.componentInstance.mode = "add";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
if (result) {
|
||||
if (
|
||||
this.dataBuildingList.some(
|
||||
(value) =>
|
||||
value.name.trim().toLowerCase() ===
|
||||
result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.postMasterBuildingParam(result)
|
||||
.subscribe((res) => {
|
||||
this.dataListBuilding();
|
||||
this.lewatModal = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
modalAddFloor() {
|
||||
const modalRef = this.modalService.open(AddEditMasterComponent, {
|
||||
size: "lg",
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
});
|
||||
|
||||
modalRef.componentInstance.headerId = 6;
|
||||
modalRef.componentInstance.mode = "add";
|
||||
modalRef.componentInstance.floor = true;
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
.postHeaderDetailParam(result)
|
||||
.subscribe((res) => {
|
||||
this.dataListFloor();
|
||||
this.lewatModal = true;
|
||||
if (res.status === 400) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
modalAddNewRoom(){
|
||||
const modalRef = this.modalService.open(AddEditMasterRoomComponent, {
|
||||
size: "lg",
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
});
|
||||
|
||||
modalRef.componentInstance.mode = "add";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
if (result) {
|
||||
const filteredData = {
|
||||
name: result.name,
|
||||
code: result.code.trim(),
|
||||
description: result.description,
|
||||
};
|
||||
this.monitoringApiService
|
||||
.postMasterRoomParam(filteredData)
|
||||
.subscribe((res) => {
|
||||
this.dataListRoom();
|
||||
}, (error) => {
|
||||
this.toastr.error("Error", error.error.message, {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,19 +271,21 @@
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -311,53 +313,38 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
/* Tambahkan ini ke styles.css atau CSS komponen */
|
||||
|
||||
/* Custom styles for Swal buttons */
|
||||
.div:where(.swal2-container) button:where(.swal2-styled).swal2-confirm {
|
||||
background-color: #bef264 !important;
|
||||
color: white !important;
|
||||
border: none !important;
|
||||
padding: 10px 20px !important;
|
||||
border-radius: 5px !important;
|
||||
font-size: 16px !important;
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.swal2-cancel.btn-cancel {
|
||||
background-color: #dc3545 !important;
|
||||
color: white !important;
|
||||
border: none !important;
|
||||
padding: 10px 20px !important;
|
||||
border-radius: 5px !important;
|
||||
font-size: 16px !important;
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.swal2-confirm.btn-confirm:hover {
|
||||
background-color: #218838 !important;
|
||||
}
|
||||
|
||||
.swal2-cancel.btn-cancel:hover {
|
||||
background-color: #c82333 !important;
|
||||
}
|
||||
|
||||
/* Custom Swal background */
|
||||
.swal2-popup.custom-swal-background {
|
||||
background-color: #000000 !important; /* Warna background hitam */
|
||||
color: white !important; /* Warna teks putih */
|
||||
}
|
||||
|
||||
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB !important">
|
||||
<div class="content-wrapper" style="height: 900px !important;">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,7 +7,7 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
@@ -26,9 +26,9 @@
|
||||
class="btn btn-secondary"
|
||||
[routerLink]="['/list-monitoring/add-row']"
|
||||
style="
|
||||
background-color: #bef264 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #000000 !important;
|
||||
background-color: #37A647 !important;
|
||||
border-color: #37A647 !important;
|
||||
color: #ffffff !important;
|
||||
"
|
||||
>
|
||||
<i class="feather ft-plus" style="color: #ffffff"></i
|
||||
@@ -40,7 +40,7 @@
|
||||
<div class="card-dashboard">
|
||||
<ngx-datatable
|
||||
class="bootstrap table-bordered"
|
||||
[limit]="5"
|
||||
[limit]="10"
|
||||
[rows]="filteredRows"
|
||||
[columnMode]="'force'"
|
||||
[headerHeight]="50"
|
||||
@@ -58,7 +58,7 @@
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
>
|
||||
<p style="color: #ffffff">{{ rowIndex + 1 }}</p>
|
||||
<p class="style-custom-label">{{ rowIndex + 1 }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
@@ -68,13 +68,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Building</span>
|
||||
<span class="style-custom-label">Building</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value.name }}</p>
|
||||
<p class="style-custom-label">{{ value.name }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
@@ -84,13 +84,29 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Room</span>
|
||||
<span class="style-custom-label">Room</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff">{{ value.name }}</p>
|
||||
<p class="style-custom-label">{{ value.name }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column
|
||||
name="floorEntity"
|
||||
[flexGrow]="1"
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span class="style-custom-label">Floor</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p class="style-custom-label">{{ value.name }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
@@ -100,13 +116,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Status</span>
|
||||
<span class="style-custom-label">Status</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff">{{ value.name }}</p>
|
||||
<p class="style-custom-label">{{ value.name }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
@@ -116,33 +132,30 @@
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Actions</span>
|
||||
<span class="style-custom-label">Actions</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
let-row="row"
|
||||
>
|
||||
<button
|
||||
class="btn btn-sm btn-info mr-1"
|
||||
style="background-color: #000000 !important; border-color: #BEF264 !important;"
|
||||
(click)="viewRow(row)"
|
||||
>
|
||||
<i class="ficon feather ft-eye" style="color: #BEF264 !important;"></i>
|
||||
</button>
|
||||
<button
|
||||
<!-- <button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="background-color: #000000 !important; border-color: #BEF264 !important;"
|
||||
style="background-color: #FBFBFB !important; border-color: #37A647 !important;"
|
||||
(click)="editRow(row)"
|
||||
>
|
||||
<i class="ficon feather ft-edit" style="color: #BEF264 !important;"></i>
|
||||
</button>
|
||||
<i class="ficon feather ft-edit" style="color: #37A647 !important;"></i>
|
||||
</button> -->
|
||||
<button
|
||||
class="btn btn-sm btn-danger"
|
||||
style="background-color: #000000 !important; border-color: #BEF264 !important;"
|
||||
style="
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="deleteRow(row)"
|
||||
>
|
||||
<i class="ficon feather ft-trash-2" style="color: #BEF264 !important;"></i>
|
||||
<i class="ficon feather ft-trash-2" style="color: #37A647 !important;"></i>
|
||||
</button>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { TableApiService } from "src/app/_services/table-api.service";
|
||||
import { BuildingService } from "../service/monitoring-api.service";
|
||||
import Swal from "sweetalert2";
|
||||
import { LoginService } from "../service/login.service";
|
||||
import { ToastrService } from "ngx-toastr";
|
||||
|
||||
@Component({
|
||||
selector: "app-list-monitoring",
|
||||
@@ -18,23 +19,24 @@ export class ListMonitoringComponent {
|
||||
rows: any = [];
|
||||
|
||||
constructor(
|
||||
private tableApiservice: TableApiService,
|
||||
private router: Router,
|
||||
private monitoringApiService: BuildingService,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private toastr: ToastrService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Cost Management",
|
||||
mainlabel: "List Monitoring",
|
||||
links: [
|
||||
{
|
||||
name: "Home",
|
||||
isLink: false,
|
||||
},
|
||||
{
|
||||
name: "Cost Management",
|
||||
name: "List Monitoring",
|
||||
isLink: false,
|
||||
},
|
||||
],
|
||||
@@ -45,25 +47,28 @@ export class ListMonitoringComponent {
|
||||
fetchData() {
|
||||
this.monitoringApiService.getBuildingRoomList().subscribe((res) => {
|
||||
this.data = res;
|
||||
this.filteredRows = this.data.results.data;
|
||||
// this.filteredRows = this.data.results.data;
|
||||
this.filteredRows = this.data.results.data.sort((a, b) => b.id - a.id);
|
||||
});
|
||||
}
|
||||
|
||||
filterRows() {
|
||||
if (!this.searchTerm) {
|
||||
this.filteredRows = [...this.data.rows];
|
||||
this.filteredRows = [...this.data.results.data];
|
||||
} else {
|
||||
this.filteredRows = this.data.rows.filter((row) =>
|
||||
this.rowContainsSearchTerm(row)
|
||||
const searchTermLC = this.searchTerm.toLowerCase();
|
||||
this.filteredRows = this.data.results.data.filter((row) =>
|
||||
this.rowContainsSearchTerm(row, searchTermLC)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
rowContainsSearchTerm(row: any): boolean {
|
||||
const searchTermLC = this.searchTerm.toLowerCase();
|
||||
return Object.values(row).some(
|
||||
(value) =>
|
||||
value !== null && value.toString().toLowerCase().includes(searchTermLC)
|
||||
rowContainsSearchTerm(row: any, searchTermLC: string): boolean {
|
||||
return (
|
||||
row.buildingEntity.name.toLowerCase().includes(searchTermLC) ||
|
||||
row.roomEntity.name.toLowerCase().includes(searchTermLC) ||
|
||||
row.statusEntity.name.toLowerCase().includes(searchTermLC) ||
|
||||
row.floorEntity?.name.toLowerCase().includes(searchTermLC)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -76,59 +81,25 @@ export class ListMonitoringComponent {
|
||||
}
|
||||
|
||||
deleteRow(row) {
|
||||
const swalWithBootstrapButtons = Swal.mixin({
|
||||
customClass: {
|
||||
confirmButton: "btn-confirm",
|
||||
cancelButton: "btn-cancel",
|
||||
popup: "custom-swal-background",
|
||||
},
|
||||
});
|
||||
swalWithBootstrapButtons.fire({
|
||||
title: "Are you sure?",
|
||||
text: "Do you want to delete?",
|
||||
icon: "question",
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
cancelButtonText: "No",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
Swal.fire({
|
||||
title: "Loading...",
|
||||
text: "Please wait",
|
||||
allowOutsideClick: false,
|
||||
customClass: {
|
||||
popup: "custom-swal-background",
|
||||
},
|
||||
didOpen: () => {
|
||||
Swal.showLoading();
|
||||
},
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.monitoringApiService
|
||||
.deleteRoomBuilding(row.id)
|
||||
.subscribe((data) => {
|
||||
Swal.fire({
|
||||
title: "Confirmed!",
|
||||
text: "You clicked Yes.",
|
||||
icon: "success",
|
||||
customClass: {
|
||||
popup: "custom-swal-background",
|
||||
},
|
||||
});
|
||||
this.fetchData();
|
||||
});
|
||||
}, 2000);
|
||||
} else if (result.isDismissed) {
|
||||
Swal.fire({
|
||||
title: "Cancelled",
|
||||
text: "You clicked No.",
|
||||
icon: "error",
|
||||
customClass: {
|
||||
popup: "custom-swal-background",
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
const confirmDelete = confirm("Are you sure you want to delete this item?");
|
||||
if (confirmDelete) {
|
||||
this.monitoringApiService.deleteRoomBuilding(row.id).subscribe(
|
||||
(res) => {
|
||||
this.fetchData();
|
||||
this.toastr.success("Success", "Delete Completed.", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Data sedang digunakan!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
onTouchStart(event: Event) {
|
||||
|
||||
@@ -1,56 +1,54 @@
|
||||
/* modal-add-edit.component.css */
|
||||
::ng-deep .modal-backdrop.show {
|
||||
z-index: auto !important;
|
||||
}
|
||||
|
||||
::ng-deep .input-group-append .btn {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-radius: 0;
|
||||
border-left: 0;
|
||||
flex-grow: 0;
|
||||
border-left: 1px solid #ced4da;
|
||||
padding: 0.375rem 0.75rem;
|
||||
}
|
||||
|
||||
::ng-deep .input-group {
|
||||
display: flex;
|
||||
flex-wrap: nowrap; /* Prevents wrapping of the items */
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
::ng-deep .form-control {
|
||||
flex-grow: 1; /* Ensures select takes up available space */
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
::ng-deep .input-group select,
|
||||
::ng-deep .input-group .input-group-append .btn {
|
||||
padding-right: 5px; /* Adjust padding if necessary */
|
||||
}
|
||||
|
||||
::ng-deep .input-group .form-control {
|
||||
margin-right: 2px; /* Adjust margin to make space */
|
||||
}
|
||||
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: calc(1.5em + 0.75rem + 2px);
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #495057;
|
||||
background-color: #fff;
|
||||
background-clip: padding-box;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.25rem;
|
||||
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
z-index: auto !important;
|
||||
}
|
||||
/*
|
||||
::ng-deep .input-group-append .btn {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-radius: 0;
|
||||
border-left: 0;
|
||||
flex-grow: 0;
|
||||
border-left: 1px solid #ced4da;
|
||||
padding: 0.375rem 0.75rem;
|
||||
}
|
||||
|
||||
::ng-deep .input-group {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
::ng-deep .form-control {
|
||||
flex-grow: 1;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
::ng-deep .input-group select,
|
||||
::ng-deep .input-group .input-group-append .btn {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
::ng-deep .input-group .form-control {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: calc(1.5em + 0.75rem + 2px);
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #495057;
|
||||
background-color: #fff;
|
||||
background-clip: padding-box;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.25rem;
|
||||
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
} */
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<div class="modal-header" style="background-color: #000000 !important">
|
||||
<h4 class="modal-title" style="color: #ffffff">{{labelModal}}</h4>
|
||||
<div class="modal-header" style="background-color: #FBFBFB !important">
|
||||
<h4 class="modal-title" style="color: #242222">{{labelModal}}</h4>
|
||||
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body" style="background-color: #000000 !important">
|
||||
<div class="modal-body" style="background-color: #FBFBFB !important">
|
||||
<form [formGroup]="myForm">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="name" style="color: #ffffff">Name:</label>
|
||||
<label for="name" style="color: #242222">Name:</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
@@ -20,18 +20,32 @@
|
||||
Name is required.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6" *ngIf="floor">
|
||||
<label for="code" style="color: #242222">Code:</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="code"
|
||||
formControlName="code"
|
||||
maxlength="10"
|
||||
(input)="toUppercase($event)"
|
||||
/>
|
||||
<div *ngIf="myForm.get('code').touched && myForm.get('code').invalid" class="text-danger">
|
||||
code is required.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6" *ngIf="category">
|
||||
<label for="icon" style="color: #ffffff">Icon:</label>
|
||||
<label for="icon" style="color: #242222">Icon:</label>
|
||||
<app-select-icon [selectedIcon]="selectedIcon" (iconSelected)="onIconSelected($event)"></app-select-icon>
|
||||
<div *ngIf="myForm.get('icon').touched && myForm.get('icon').invalid" class="text-danger">
|
||||
Icon is required.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="status" style="color: #ffffff">Status:</label>
|
||||
<label for="status" style="color: #242222">Status:</label>
|
||||
<select
|
||||
id="projectinput5"
|
||||
class="form-control"
|
||||
class="form-control custom-select"
|
||||
formControlName="status"
|
||||
>
|
||||
<option *ngFor="let data of dataMasterStatus" [value]="data.id">
|
||||
@@ -45,18 +59,18 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer" style="background-color: #000000 !important">
|
||||
<div class="modal-footer" style="background-color: #FBFBFB !important">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
style="color: #c3f164 !important; background-color: #000000 !important; border-color: #c3f164 !important;"
|
||||
style="color: #242222 !important; background-color: #FBFBFB !important; border-color: #FBFBFB !important;"
|
||||
(click)="activeModal.dismiss('Cross click')"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
style="color: #000000 !important; background-color: #c3f164 !important"
|
||||
style="color: #ffffff !important; background-color: #37A647 !important"
|
||||
class="btn btn-primary"
|
||||
(click)="addRow()"
|
||||
>
|
||||
|
||||
@@ -14,6 +14,7 @@ export class AddEditMasterComponent implements OnInit {
|
||||
@Input() dataRow: any;
|
||||
@Input() mode: any;
|
||||
@Input() category: boolean = false;
|
||||
@Input() floor: boolean = false;
|
||||
myForm: FormGroup;
|
||||
dataMasterStatus: any;
|
||||
selectedIcon: string = '';
|
||||
@@ -27,7 +28,8 @@ export class AddEditMasterComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.createForm();
|
||||
this.dataListMaster();
|
||||
if (this.mode === "add") {
|
||||
@@ -52,12 +54,21 @@ export class AddEditMasterComponent implements OnInit {
|
||||
formControls['icon'] = [undefined, Validators.required];
|
||||
}
|
||||
|
||||
if (this.floor) {
|
||||
formControls['code'] = ['', Validators.required];
|
||||
}
|
||||
|
||||
this.myForm = this.fb.group(formControls);
|
||||
}
|
||||
|
||||
toUppercase(event: Event) {
|
||||
const input = event.target as HTMLInputElement;
|
||||
input.value = input.value.toUpperCase();
|
||||
this.myForm.get('code').setValue(input.value);
|
||||
}
|
||||
|
||||
|
||||
editForm() {
|
||||
console.log(this.dataRow);
|
||||
|
||||
const formControls = {
|
||||
id: this.dataRow.id,
|
||||
name: [this.dataRow.name, Validators.required],
|
||||
@@ -70,6 +81,9 @@ export class AddEditMasterComponent implements OnInit {
|
||||
this.selectedIcon = this.dataRow.icon || undefined;
|
||||
}
|
||||
|
||||
if (this.floor) {
|
||||
formControls['code'] = [this.dataRow.code || '' , Validators.required];
|
||||
}
|
||||
this.myForm = this.fb.group(formControls);
|
||||
}
|
||||
|
||||
@@ -78,7 +92,7 @@ export class AddEditMasterComponent implements OnInit {
|
||||
const dataCategory = data.data.find(
|
||||
(item) => item.name === "master_status"
|
||||
).headerDetailParam;
|
||||
this.dataMasterStatus = dataCategory.filter(item => item.statusName.toLowerCase() === "aktif");
|
||||
this.dataMasterStatus = dataCategory.filter(item => item.statusName.toLowerCase() === "aktif" || item.status.toLowerCase() === "71" || item.status.toLowerCase() === "71");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -107,8 +121,6 @@ export class AddEditMasterComponent implements OnInit {
|
||||
}
|
||||
|
||||
onIconSelected(icon: string): void {
|
||||
console.log(icon);
|
||||
|
||||
this.selectedIcon = icon;
|
||||
this.myForm.get('icon').setValue(icon); // Set nilai icon ke dalam form
|
||||
}
|
||||
|
||||
@@ -1,42 +1,59 @@
|
||||
<div class="modal-header" style="background-color: #000000 !important">
|
||||
<h4 class="modal-title" style="color: #ffffff">{{labelModal}}</h4>
|
||||
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
|
||||
<div class="modal-header" style="background-color: #fbfbfb !important">
|
||||
<h4 class="modal-title" style="color: #242222">{{ labelModal }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
aria-label="Close"
|
||||
(click)="activeModal.dismiss('Cross click')"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body" style="background-color: #000000 !important">
|
||||
<div class="modal-body" style="background-color: #fbfbfb !important">
|
||||
<form [formGroup]="myForm">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="name" style="color: #ffffff">Name Building:</label>
|
||||
<label for="name" style="color: #242222">Name Building:</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="name"
|
||||
formControlName="name"
|
||||
maxlength="50"
|
||||
[ngClass]="{'is-invalid': myForm.get('name').invalid && myForm.get('name').touched}"
|
||||
[ngClass]="{
|
||||
'is-invalid':
|
||||
myForm.get('name').invalid && myForm.get('name').touched
|
||||
}"
|
||||
/>
|
||||
<div *ngIf="myForm.get('name').invalid && myForm.get('name').touched" class="text-danger">
|
||||
<div
|
||||
*ngIf="myForm.get('name').invalid && myForm.get('name').touched"
|
||||
class="text-danger"
|
||||
>
|
||||
Name is required.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="email" style="color: #ffffff">Email:</label>
|
||||
<label for="email" style="color: #242222">Email:</label>
|
||||
<input
|
||||
type="email"
|
||||
class="form-control"
|
||||
id="email"
|
||||
formControlName="email"
|
||||
maxlength="50"
|
||||
[ngClass]="{'is-invalid': myForm.get('email').invalid && myForm.get('email').touched}"
|
||||
[ngClass]="{
|
||||
'is-invalid':
|
||||
myForm.get('email').invalid && myForm.get('email').touched
|
||||
}"
|
||||
/>
|
||||
<div *ngIf="myForm.get('email').invalid && myForm.get('email').touched" class="text-danger">
|
||||
<div
|
||||
*ngIf="myForm.get('email').invalid && myForm.get('email').touched"
|
||||
class="text-danger"
|
||||
>
|
||||
Please enter a valid email.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="phone" style="color: #ffffff">Phone:</label>
|
||||
<label for="phone" style="color: #242222">Phone:</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
@@ -44,81 +61,112 @@
|
||||
formControlName="phone"
|
||||
pattern="^[0-9]*$"
|
||||
maxlength="13"
|
||||
[ngClass]="{'is-invalid': myForm.get('phone').invalid && myForm.get('phone').touched}"
|
||||
[ngClass]="{
|
||||
'is-invalid':
|
||||
myForm.get('phone').invalid && myForm.get('phone').touched
|
||||
}"
|
||||
/>
|
||||
<div *ngIf="myForm.get('phone').invalid && myForm.get('phone').touched" class="text-danger">
|
||||
<div
|
||||
*ngIf="myForm.get('phone').invalid && myForm.get('phone').touched"
|
||||
class="text-danger"
|
||||
>
|
||||
Please enter a valid phone number.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="owner" style="color: #ffffff">Owner:</label>
|
||||
<label for="owner" style="color: #242222">Owner:</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="owner"
|
||||
maxlength="30"
|
||||
formControlName="owner"
|
||||
[ngClass]="{'is-invalid': myForm.get('owner').invalid && myForm.get('owner').touched}"
|
||||
[ngClass]="{
|
||||
'is-invalid':
|
||||
myForm.get('owner').invalid && myForm.get('owner').touched
|
||||
}"
|
||||
/>
|
||||
<div *ngIf="myForm.get('owner').invalid && myForm.get('owner').touched" class="text-danger">
|
||||
<div
|
||||
*ngIf="myForm.get('owner').invalid && myForm.get('owner').touched"
|
||||
class="text-danger"
|
||||
>
|
||||
Owner is required.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="address" style="color: #ffffff">Address:</label>
|
||||
<label for="address" style="color: #242222">Address:</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="address"
|
||||
formControlName="address"
|
||||
maxlength="90"
|
||||
[ngClass]="{'is-invalid': myForm.get('address').invalid && myForm.get('address').touched}"
|
||||
[ngClass]="{
|
||||
'is-invalid':
|
||||
myForm.get('address').invalid && myForm.get('address').touched
|
||||
}"
|
||||
/>
|
||||
<div *ngIf="myForm.get('address').invalid && myForm.get('address').touched" class="text-danger">
|
||||
<div
|
||||
*ngIf="myForm.get('address').invalid && myForm.get('address').touched"
|
||||
class="text-danger"
|
||||
>
|
||||
Address is required.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="kwh" style="color: #ffffff">KWH:</label>
|
||||
<label for="kwh" style="color: #242222">KWH:</label>
|
||||
<input
|
||||
type="number"
|
||||
type="text"
|
||||
class="form-control no-arrow"
|
||||
id="kwh"
|
||||
formControlName="kwh"
|
||||
maxlength="20"
|
||||
[ngClass]="{'is-invalid': myForm.get('kwh').invalid && myForm.get('kwh').touched}"
|
||||
maxlength="15"
|
||||
[ngClass]="{
|
||||
'is-invalid': myForm.get('kwh').invalid && myForm.get('kwh').touched
|
||||
}"
|
||||
/>
|
||||
<div *ngIf="myForm.get('kwh').invalid && myForm.get('kwh').touched" class="text-danger">
|
||||
KWH is required.
|
||||
<div
|
||||
*ngIf="myForm.get('kwh').invalid && myForm.get('kwh').touched"
|
||||
class="text-danger"
|
||||
>
|
||||
Please enter a valid KWH.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="statusId" style="color: #ffffff">Status:</label>
|
||||
<label for="statusId" style="color: #242222">Status:</label>
|
||||
<select
|
||||
id="statusId"
|
||||
class="form-control"
|
||||
class="form-control custom-select"
|
||||
formControlName="statusId"
|
||||
[ngClass]="{'is-invalid': myForm.get('statusId').invalid && myForm.get('statusId').touched}"
|
||||
[ngClass]="{
|
||||
'is-invalid':
|
||||
myForm.get('statusId').invalid && myForm.get('statusId').touched
|
||||
}"
|
||||
>
|
||||
<option *ngFor="let data of filteredDataStatus" [value]="data.id">
|
||||
{{ data.name }}
|
||||
</option>
|
||||
</select>
|
||||
<div *ngIf="myForm.get('statusId').invalid && myForm.get('statusId').touched" class="text-danger">
|
||||
<div
|
||||
*ngIf="
|
||||
myForm.get('statusId').invalid && myForm.get('statusId').touched
|
||||
"
|
||||
class="text-danger"
|
||||
>
|
||||
Status is required.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer" style="background-color: #000000 !important">
|
||||
<div class="modal-footer" style="background-color: #fbfbfb !important">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #c3f164 !important;
|
||||
background-color: #000000 !important;
|
||||
border-color: #c3f164 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #fbfbfb !important;
|
||||
border-color: #fbfbfb !important;
|
||||
"
|
||||
(click)="activeModal.dismiss('Cross click')"
|
||||
>
|
||||
@@ -126,7 +174,7 @@
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
style="color: #000000 !important; background-color: #c3f164 !important"
|
||||
style="color: #ffffff !important; background-color: #37a647 !important"
|
||||
class="btn btn-primary"
|
||||
(click)="addRow()"
|
||||
>
|
||||
|
||||
@@ -27,7 +27,8 @@ export class AddEditMasterBuildingComponent {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.createForm();
|
||||
this.listDataStatus();
|
||||
if (this.mode === "add") {
|
||||
@@ -48,7 +49,7 @@ export class AddEditMasterBuildingComponent {
|
||||
owner: ["", Validators.required],
|
||||
address: ["", Validators.required],
|
||||
phone: ["", [Validators.required, Validators.pattern(/^[0-9]{10,15}$/)]],
|
||||
kwh: ["", Validators.required],
|
||||
kwh: ["", [Validators.required, Validators.maxLength(15), Validators.pattern(/^[0-9]{1,7}$/)]],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,13 +59,10 @@ export class AddEditMasterBuildingComponent {
|
||||
name: [this.dataRow.name, Validators.required],
|
||||
statusId: [this.dataRow.status_id, Validators.required],
|
||||
email: [this.dataRow.email, [Validators.required, Validators.pattern(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)]],
|
||||
owner: [this.dataRow.owner, Validators.required],
|
||||
address: [this.dataRow.address, [Validators.required, Validators.pattern(/^[0-9]{10,15}$/)]],
|
||||
phone: [
|
||||
this.dataRow.phone,
|
||||
[Validators.required, Validators.pattern("^[0-9]*$")],
|
||||
],
|
||||
kwh: [this.dataRow.kwh, Validators.required],
|
||||
address: [this.dataRow.address, Validators.required],
|
||||
phone: [this.dataRow.phone, [Validators.required, Validators.pattern(/^[0-9]{10,15}$/)]],
|
||||
owner: [this.dataRow.owner,Validators.required],
|
||||
kwh: [this.dataRow.kwh, [Validators.required, Validators.maxLength(15), Validators.pattern(/^[0-9]{1,7}$/)]],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -271,19 +271,21 @@
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -311,14 +313,38 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #fbfbfb !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,7 +7,7 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #fbfbfb !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
@@ -24,9 +24,9 @@
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #37a647 !important;
|
||||
background-color: #37a647 !important;
|
||||
"
|
||||
(click)="openAddMasterModal()"
|
||||
>
|
||||
@@ -60,7 +60,7 @@
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
>
|
||||
<p style="color: #ffffff">{{ rowIndex + 1 }}</p>
|
||||
<p class="style-custom-label">{{ rowIndex + 1 }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -69,13 +69,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Building Name</span>
|
||||
<span class="style-custom-label">Building Name</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -84,13 +84,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Email</span>
|
||||
<span class="style-custom-label">Email</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -99,13 +99,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Phone</span>
|
||||
<span class="style-custom-label">Phone</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -114,13 +114,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Owner</span>
|
||||
<span class="style-custom-label">Owner</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -129,13 +129,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Address</span>
|
||||
<span class="style-custom-label">Address</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -144,13 +144,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Status</span>
|
||||
<span class="style-custom-label">Status</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff">
|
||||
<p class="style-custom-label">
|
||||
{{ value }}
|
||||
</p>
|
||||
</ng-template>
|
||||
@@ -161,7 +161,7 @@
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Actions</span>
|
||||
<span class="style-custom-label">Actions</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
@@ -171,8 +171,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="editRow(row)"
|
||||
>
|
||||
@@ -181,8 +182,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-danger"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="deleteRow(row)"
|
||||
>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { AddEditMasterComponent } from '../add-edit-master/add-edit-master.component';
|
||||
import { TableApiService } from 'src/app/_services/table-api.service';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { Router } from '@angular/router';
|
||||
import { BuildingService } from '../../service/monitoring-api.service';
|
||||
import { AddEditMasterBuildingComponent } from './add-edit-master-building/add-edit-master-building.component';
|
||||
import { LoginService } from '../../service/login.service';
|
||||
import { Component } from "@angular/core";
|
||||
import { AddEditMasterComponent } from "../add-edit-master/add-edit-master.component";
|
||||
import { TableApiService } from "src/app/_services/table-api.service";
|
||||
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { Router } from "@angular/router";
|
||||
import { BuildingService } from "../../service/monitoring-api.service";
|
||||
import { AddEditMasterBuildingComponent } from "./add-edit-master-building/add-edit-master-building.component";
|
||||
import { LoginService } from "../../service/login.service";
|
||||
import { ToastrService } from "ngx-toastr";
|
||||
|
||||
@Component({
|
||||
selector: 'app-master-building',
|
||||
templateUrl: './master-building.component.html',
|
||||
styleUrls: ['./master-building.component.css']
|
||||
selector: "app-master-building",
|
||||
templateUrl: "./master-building.component.html",
|
||||
styleUrls: ["./master-building.component.css"],
|
||||
})
|
||||
export class MasterBuildingComponent {
|
||||
data: any;
|
||||
@@ -24,11 +25,13 @@ export class MasterBuildingComponent {
|
||||
private modalService: NgbModal,
|
||||
private router: Router,
|
||||
private monitoringApiService: BuildingService,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private toastr: ToastrService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Master Building",
|
||||
links: [
|
||||
@@ -74,20 +77,38 @@ export class MasterBuildingComponent {
|
||||
openAddMasterModal() {
|
||||
const modalRef = this.modalService.open(AddEditMasterBuildingComponent, {
|
||||
size: "lg",
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
});
|
||||
|
||||
modalRef.componentInstance.mode = "add";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
.postMasterBuildingParam(result)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) => value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.postMasterBuildingParam(result)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
// if (result) {
|
||||
// this.monitoringApiService
|
||||
// .postMasterBuildingParam(result)
|
||||
// .subscribe((res) => {
|
||||
// this.fetchData();
|
||||
// });
|
||||
// }
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
@@ -98,8 +119,8 @@ export class MasterBuildingComponent {
|
||||
editRow(row) {
|
||||
const modalRef = this.modalService.open(AddEditMasterBuildingComponent, {
|
||||
size: "lg",
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
});
|
||||
|
||||
modalRef.componentInstance.dataRow = row;
|
||||
@@ -107,12 +128,64 @@ export class MasterBuildingComponent {
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
.putMasterBuildingParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) => value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
if (row.name.trim().toLowerCase() === result.name.trim().toLowerCase()) {
|
||||
this.monitoringApiService
|
||||
.putMasterBuildingParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) =>
|
||||
value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.putMasterBuildingParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// if (result) {
|
||||
// console.log(result);
|
||||
// console.log(this.filteredRows);
|
||||
|
||||
// if (this.filteredRows.some(value => value.name.toLowerCase() === result.name.toLowerCase() && value.status_id === result.statusId)) {
|
||||
// this.toastr.error("Warning", "Nama Gedung yang anda masukan double.", {
|
||||
// timeOut: 5000,
|
||||
// closeButton: true,
|
||||
// });
|
||||
// } else {
|
||||
// this.monitoringApiService
|
||||
// .putMasterBuildingParam(result, row.id)
|
||||
// .subscribe((res) => {
|
||||
// this.fetchData();
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (result) {
|
||||
// this.monitoringApiService
|
||||
// .putMasterBuildingParam(result, row.id)
|
||||
// .subscribe((res) => {
|
||||
// this.fetchData();
|
||||
// });
|
||||
// }
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
@@ -127,6 +200,12 @@ export class MasterBuildingComponent {
|
||||
.deleteMasterBuildingParam(row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
}, (error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Data sedang digunakan!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,19 +271,21 @@
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -311,14 +313,38 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,7 +7,7 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
@@ -24,9 +24,9 @@
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #37A647 !important;
|
||||
background-color: #37A647 !important;
|
||||
"
|
||||
(click)="openAddMasterModal()"
|
||||
>
|
||||
@@ -60,7 +60,7 @@
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
>
|
||||
<p style="color: #ffffff">{{ rowIndex + 1 }}</p>
|
||||
<p class="style-custom-label">{{ rowIndex + 1 }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -69,13 +69,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Name</span>
|
||||
<span class="style-custom-label">Name</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -84,13 +84,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Icon</span>
|
||||
<span class="style-custom-label">Icon</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -99,13 +99,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Status</span>
|
||||
<span class="style-custom-label">Status</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff">{{ value}}</p>
|
||||
<p class="style-custom-label">{{ value}}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -114,7 +114,7 @@
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Actions</span>
|
||||
<span class="style-custom-label">Actions</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
@@ -124,8 +124,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="editRow(row)"
|
||||
>
|
||||
@@ -134,8 +135,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-danger"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="deleteRow(row)"
|
||||
>
|
||||
|
||||
@@ -33,7 +33,8 @@ export class MasterCategoryComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Master Category",
|
||||
links: [
|
||||
@@ -57,7 +58,9 @@ export class MasterCategoryComponent implements OnInit {
|
||||
(item) => item.name === "master_category"
|
||||
);
|
||||
// this.filteredRows = this.dataMasterCategori.headerDetailParam;
|
||||
this.filteredRows = this.dataMasterCategori.headerDetailParam.sort((a, b) => b.id - a.id);
|
||||
this.filteredRows = this.dataMasterCategori.headerDetailParam.sort(
|
||||
(a, b) => b.id - a.id
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -77,7 +80,7 @@ export class MasterCategoryComponent implements OnInit {
|
||||
rowContainsSearchTerm(row: any): boolean {
|
||||
const searchTermLC = this.searchTerm.toLowerCase();
|
||||
console.log(searchTermLC);
|
||||
|
||||
|
||||
return Object.values(row).some(
|
||||
(value) =>
|
||||
value !== null && value.toString().toLowerCase().includes(searchTermLC)
|
||||
@@ -87,8 +90,8 @@ export class MasterCategoryComponent implements OnInit {
|
||||
openAddMasterModal() {
|
||||
const modalRef = this.modalService.open(AddEditMasterComponent, {
|
||||
size: "lg",
|
||||
backdrop: 'static', // Add this line
|
||||
keyboard: false // Add this line
|
||||
backdrop: "static", // Add this line
|
||||
keyboard: false, // Add this line
|
||||
});
|
||||
|
||||
modalRef.componentInstance.headerId = this.dataMasterCategori.id;
|
||||
@@ -96,24 +99,24 @@ export class MasterCategoryComponent implements OnInit {
|
||||
modalRef.componentInstance.category = true;
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService.postHeaderDetailParam(result).subscribe(
|
||||
(res) => {
|
||||
this.fetchData();
|
||||
this.toastr.success("Success", "Save Completed.", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) => value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.postHeaderDetailParam(result)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Something went wrong!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
@@ -123,10 +126,12 @@ export class MasterCategoryComponent implements OnInit {
|
||||
}
|
||||
|
||||
editRow(row) {
|
||||
console.log(row);
|
||||
|
||||
const modalRef = this.modalService.open(AddEditMasterComponent, {
|
||||
size: "lg",
|
||||
backdrop: 'static', // Add this line
|
||||
keyboard: false // Add this line
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
});
|
||||
|
||||
modalRef.componentInstance.headerId = this.dataMasterCategori.id;
|
||||
@@ -135,26 +140,38 @@ export class MasterCategoryComponent implements OnInit {
|
||||
modalRef.componentInstance.category = true;
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe(
|
||||
(res) => {
|
||||
this.fetchData();
|
||||
this.toastr.success("Success", "Update Completed.", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) => value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
if (row.name.trim().toLowerCase() === result.name.trim().toLowerCase()) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Something went wrong!", {
|
||||
timeOut: 2000,
|
||||
} else {
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) =>
|
||||
value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
@@ -176,7 +193,7 @@ export class MasterCategoryComponent implements OnInit {
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Something went wrong!", {
|
||||
this.toastr.error("Error", "Data sedang digunakan!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
|
||||
@@ -271,19 +271,21 @@
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -311,14 +313,38 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,7 +7,7 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
@@ -24,9 +24,9 @@
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #37A647 !important;
|
||||
background-color: #37A647 !important;
|
||||
"
|
||||
(click)="openAddMasterModal()"
|
||||
>
|
||||
@@ -60,7 +60,7 @@
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
>
|
||||
<p style="color: #ffffff">{{ rowIndex + 1 }}</p>
|
||||
<p class="style-custom-label">{{ rowIndex + 1 }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -69,13 +69,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Name</span>
|
||||
<span class="style-custom-label">Name</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -84,13 +84,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Status</span>
|
||||
<span class="style-custom-label">Status</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -106,8 +106,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="editRow(row)"
|
||||
>
|
||||
@@ -116,8 +117,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-danger"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="deleteRow(row)"
|
||||
>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { Router } from '@angular/router';
|
||||
import { BuildingService } from '../../service/monitoring-api.service';
|
||||
import { LoginService } from '../../service/login.service';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
||||
@Component({
|
||||
selector: 'app-master-duration-use',
|
||||
@@ -24,11 +25,13 @@ export class MasterDurationUseComponent {
|
||||
private modalService: NgbModal,
|
||||
private router: Router,
|
||||
private monitoringApiService: BuildingService,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private toastr: ToastrService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Master Duration Use",
|
||||
links: [
|
||||
@@ -90,12 +93,27 @@ export class MasterDurationUseComponent {
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
.postHeaderDetailParam(result)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
if (result) {
|
||||
if (this.filteredRows.some(value => value.name.trim().toLowerCase() === result.name.trim().toLowerCase())) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.postHeaderDetailParam(result)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
// this.monitoringApiService
|
||||
// .postHeaderDetailParam(result)
|
||||
// .subscribe((res) => {
|
||||
// console.log(res);
|
||||
// this.fetchData();
|
||||
// });
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
@@ -116,14 +134,38 @@ export class MasterDurationUseComponent {
|
||||
modalRef.componentInstance.mode = "edit";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) => value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
if (row.name.trim().toLowerCase() === result.name.trim().toLowerCase()) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) =>
|
||||
value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
@@ -135,11 +177,22 @@ export class MasterDurationUseComponent {
|
||||
deleteRow(row) {
|
||||
const confirmDelete = confirm("Are you sure you want to delete this item?");
|
||||
if (confirmDelete) {
|
||||
this.monitoringApiService
|
||||
.deleteHeaderDetailParam(row.id)
|
||||
.subscribe((res) => {
|
||||
this.monitoringApiService.deleteHeaderDetailParam(row.id).subscribe(
|
||||
(res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
this.toastr.success("Success", "Delete Completed.", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Data sedang digunakan!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,19 +271,21 @@
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -311,14 +313,38 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,7 +7,7 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
@@ -24,9 +24,9 @@
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #37A647 !important;
|
||||
background-color: #37A647 !important;
|
||||
"
|
||||
(click)="openAddMasterModal()"
|
||||
>
|
||||
@@ -55,7 +55,7 @@
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
>
|
||||
<p style="color: #ffffff">{{ rowIndex + 1 }}</p>
|
||||
<p class="style-custom-label">{{ rowIndex + 1 }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -64,13 +64,30 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Name</span>
|
||||
<span class="style-custom-label">Name</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
name="code"
|
||||
[flexGrow]="1"
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span class="style-custom-label">Code</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p class="style-custom-label">
|
||||
{{ value }}
|
||||
</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -79,13 +96,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Status</span>
|
||||
<span class="style-custom-label">Status</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff">
|
||||
<p class="style-custom-label">
|
||||
{{ value }}
|
||||
</p>
|
||||
</ng-template>
|
||||
@@ -96,7 +113,7 @@
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Actions</span>
|
||||
<span class="style-custom-label">Actions</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
@@ -106,8 +123,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="editRow(row)"
|
||||
>
|
||||
@@ -116,8 +134,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-danger"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="deleteRow(row)"
|
||||
>
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { AddEditMasterComponent } from '../add-edit-master/add-edit-master.component';
|
||||
import { TableApiService } from 'src/app/_services/table-api.service';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { Router } from '@angular/router';
|
||||
import { BuildingService } from '../../service/monitoring-api.service';
|
||||
import { LoginService } from '../../service/login.service';
|
||||
import { Component } from "@angular/core";
|
||||
import { AddEditMasterComponent } from "../add-edit-master/add-edit-master.component";
|
||||
import { TableApiService } from "src/app/_services/table-api.service";
|
||||
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { Router } from "@angular/router";
|
||||
import { BuildingService } from "../../service/monitoring-api.service";
|
||||
import { LoginService } from "../../service/login.service";
|
||||
import { ToastrService } from "ngx-toastr";
|
||||
|
||||
@Component({
|
||||
selector: 'app-master-floor',
|
||||
templateUrl: './master-floor.component.html',
|
||||
styleUrls: ['./master-floor.component.css']
|
||||
selector: "app-master-floor",
|
||||
templateUrl: "./master-floor.component.html",
|
||||
styleUrls: ["./master-floor.component.css"],
|
||||
})
|
||||
export class MasterFloorComponent {
|
||||
data: any;
|
||||
@@ -24,11 +25,13 @@ export class MasterFloorComponent {
|
||||
private modalService: NgbModal,
|
||||
private router: Router,
|
||||
private monitoringApiService: BuildingService,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private toastr: ToastrService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Master Floor",
|
||||
links: [
|
||||
@@ -52,7 +55,9 @@ export class MasterFloorComponent {
|
||||
(item) => item.name === "master_floor"
|
||||
);
|
||||
// this.filteredRows = this.dataMasterCategori.headerDetailParam;
|
||||
this.filteredRows = this.dataMasterCategori.headerDetailParam.sort((a, b) => b.id - a.id);
|
||||
this.filteredRows = this.dataMasterCategori.headerDetailParam.sort(
|
||||
(a, b) => b.id - a.id
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -80,12 +85,13 @@ export class MasterFloorComponent {
|
||||
openAddMasterModal() {
|
||||
const modalRef = this.modalService.open(AddEditMasterComponent, {
|
||||
size: "lg",
|
||||
backdrop: 'static', // Add this line
|
||||
keyboard: false // Add this line
|
||||
backdrop: "static", // Add this line
|
||||
keyboard: false, // Add this line
|
||||
});
|
||||
|
||||
modalRef.componentInstance.headerId = this.dataMasterCategori.id;
|
||||
modalRef.componentInstance.mode = "add";
|
||||
modalRef.componentInstance.floor = true;
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
console.log(result);
|
||||
@@ -93,10 +99,23 @@ export class MasterFloorComponent {
|
||||
this.monitoringApiService
|
||||
.postHeaderDetailParam(result)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
if (res.status === 400) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// if (result) {
|
||||
// this.monitoringApiService
|
||||
// .postHeaderDetailParam(result)
|
||||
// .subscribe((res) => {
|
||||
// console.log(res);
|
||||
// this.fetchData();
|
||||
// });
|
||||
// }
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
@@ -107,22 +126,27 @@ export class MasterFloorComponent {
|
||||
editRow(row) {
|
||||
const modalRef = this.modalService.open(AddEditMasterComponent, {
|
||||
size: "lg",
|
||||
backdrop: 'static', // Add this line
|
||||
keyboard: false // Add this line
|
||||
backdrop: "static", // Add this line
|
||||
keyboard: false, // Add this line
|
||||
});
|
||||
|
||||
modalRef.componentInstance.headerId = this.dataMasterCategori.id;
|
||||
modalRef.componentInstance.dataRow = row;
|
||||
modalRef.componentInstance.mode = "edit";
|
||||
modalRef.componentInstance.floor = true;
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
if (res.status === 400) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -135,11 +159,22 @@ export class MasterFloorComponent {
|
||||
deleteRow(row) {
|
||||
const confirmDelete = confirm("Are you sure you want to delete this item?");
|
||||
if (confirmDelete) {
|
||||
this.monitoringApiService
|
||||
.deleteHeaderDetailParam(row.id)
|
||||
.subscribe((res) => {
|
||||
this.monitoringApiService.deleteHeaderDetailParam(row.id).subscribe(
|
||||
(res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
this.toastr.success("Success", "Delete Completed.", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Data sedang digunakan!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,19 +271,21 @@
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -311,14 +313,38 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -10,7 +10,7 @@
|
||||
class="col-12"
|
||||
*blockUI="'zeroConfiguration'; message: 'Loading'"
|
||||
>
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
@@ -28,9 +28,9 @@
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #37A647 !important;
|
||||
background-color: #37A647 !important;
|
||||
"
|
||||
(click)="openAddMasterModal()"
|
||||
>
|
||||
@@ -64,7 +64,7 @@
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
>
|
||||
<p style="color: #ffffff">{{ rowIndex + 1 }}</p>
|
||||
<p class="style-custom-label">{{ rowIndex + 1 }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -73,13 +73,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Name</span>
|
||||
<span class="style-custom-label">Name</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -88,13 +88,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Status</span>
|
||||
<span class="style-custom-label">Status</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff">
|
||||
<p class="style-custom-label">
|
||||
{{ value }}
|
||||
</p>
|
||||
</ng-template>
|
||||
@@ -105,7 +105,7 @@
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Actions</span>
|
||||
<span class="style-custom-label">Actions</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
@@ -115,8 +115,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="editRow(row)"
|
||||
>
|
||||
@@ -125,8 +126,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-danger"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="deleteRow(row)"
|
||||
>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { Router } from '@angular/router';
|
||||
import { BuildingService } from '../../service/monitoring-api.service';
|
||||
import { LoginService } from '../../service/login.service';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
||||
@Component({
|
||||
selector: 'app-master-role',
|
||||
@@ -24,11 +25,13 @@ export class MasterRoleComponent {
|
||||
private modalService: NgbModal,
|
||||
private router: Router,
|
||||
private monitoringApiService: BuildingService,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private toastr: ToastrService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Master Role",
|
||||
links: [
|
||||
@@ -90,13 +93,28 @@ export class MasterRoleComponent {
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
if (this.filteredRows.some(value => value.name.trim().toLowerCase() === result.name.trim().toLowerCase())) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.postHeaderDetailParam(result)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
// if (result) {
|
||||
// this.monitoringApiService
|
||||
// .postHeaderDetailParam(result)
|
||||
// .subscribe((res) => {
|
||||
// console.log(res);
|
||||
// this.fetchData();
|
||||
// });
|
||||
// }
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
@@ -116,14 +134,38 @@ export class MasterRoleComponent {
|
||||
modalRef.componentInstance.mode = "edit";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) => value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
if (row.name.trim().toLowerCase() === result.name.trim().toLowerCase()) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) =>
|
||||
value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
@@ -135,11 +177,22 @@ export class MasterRoleComponent {
|
||||
deleteRow(row) {
|
||||
const confirmDelete = confirm("Are you sure you want to delete this item?");
|
||||
if (confirmDelete) {
|
||||
this.monitoringApiService
|
||||
.deleteHeaderDetailParam(row.id)
|
||||
.subscribe((res) => {
|
||||
this.monitoringApiService.deleteHeaderDetailParam(row.id).subscribe(
|
||||
(res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
this.toastr.success("Success", "Delete Completed.", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Data sedang digunakan!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
<div class="modal-header" style="background-color: #000000 !important">
|
||||
<h4 class="modal-title" style="color: #ffffff">{{labelRoom}}</h4>
|
||||
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
|
||||
<div class="modal-header" style="background-color: #fbfbfb !important">
|
||||
<h4 class="modal-title" style="color: #242222">{{ labelRoom }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
aria-label="Close"
|
||||
(click)="activeModal.dismiss('Cross click')"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body" style="background-color: #000000 !important">
|
||||
<div class="modal-body" style="background-color: #fbfbfb !important">
|
||||
<form [formGroup]="myForm">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="name" style="color: #ffffff">Name Room:</label>
|
||||
<label for="name" style="color: #242222">Name Room:</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
@@ -24,7 +29,24 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="statusId" style="color: #ffffff">Building:</label>
|
||||
<label for="name" style="color: #242222">Room Code:</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="code"
|
||||
formControlName="code"
|
||||
maxlength="10"
|
||||
(input)="toUppercase($event)"
|
||||
/>
|
||||
<div
|
||||
*ngIf="myForm.get('code').touched && myForm.get('code').invalid"
|
||||
class="text-danger"
|
||||
>
|
||||
Code is required.
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="form-group col-md-6">
|
||||
<label for="statusId" style="color: #242222">Building:</label>
|
||||
<select
|
||||
id="projectinput5"
|
||||
class="form-control"
|
||||
@@ -42,9 +64,9 @@
|
||||
>
|
||||
Building is required.
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="form-group col-md-6">
|
||||
<label for="description" style="color: #ffffff">Description:</label>
|
||||
<label for="description" style="color: #242222">Description:</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
@@ -52,12 +74,18 @@
|
||||
formControlName="description"
|
||||
maxlength="50"
|
||||
/>
|
||||
<div *ngIf="myForm.get('description').touched && myForm.get('description').invalid" class="text-danger">
|
||||
<div
|
||||
*ngIf="
|
||||
myForm.get('description').touched &&
|
||||
myForm.get('description').invalid
|
||||
"
|
||||
class="text-danger"
|
||||
>
|
||||
Description is required.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="statusId" style="color: #ffffff">Status:</label>
|
||||
<!-- <div class="form-group col-md-6">
|
||||
<label for="statusId" style="color: #242222">Status:</label>
|
||||
<select
|
||||
id="projectinput5"
|
||||
class="form-control"
|
||||
@@ -70,18 +98,18 @@
|
||||
<div *ngIf="myForm.get('statusId').touched && myForm.get('statusId').invalid" class="text-danger">
|
||||
Status is required.
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer" style="background-color: #000000 !important">
|
||||
<div class="modal-footer" style="background-color: #fbfbfb !important">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #c3f164 !important;
|
||||
background-color: #000000 !important;
|
||||
border-color: #c3f164 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #fbfbfb !important;
|
||||
border-color: #fbfbfb !important;
|
||||
"
|
||||
(click)="activeModal.dismiss('Cross click')"
|
||||
>
|
||||
@@ -90,7 +118,7 @@
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
style="color: #000000 !important; background-color: #c3f164 !important"
|
||||
style="color: #ffffff !important; background-color: #37a647 !important"
|
||||
(click)="addRow()"
|
||||
>
|
||||
Save
|
||||
|
||||
@@ -30,15 +30,15 @@ export class AddEditMasterRoomComponent {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.createForm();
|
||||
this.listDataStatus();
|
||||
this.listDataBuilding();
|
||||
console.log(this.dataRow);
|
||||
if (this.mode) {
|
||||
if (this.mode === "add") {
|
||||
this.labelRoom = "Add New Row"
|
||||
} else {
|
||||
this.labelRoom = "Add New Row"
|
||||
this.labelRoom = "Edit Row"
|
||||
}
|
||||
if (this.dataRow) {
|
||||
this.editForm();
|
||||
@@ -48,8 +48,7 @@ export class AddEditMasterRoomComponent {
|
||||
createForm() {
|
||||
this.myForm = this.fb.group({
|
||||
name: ["", Validators.required],
|
||||
statusId: ["", Validators.required],
|
||||
buildingId: ["", Validators.required],
|
||||
code: ["", Validators.required],
|
||||
description: ["", Validators.required],
|
||||
});
|
||||
}
|
||||
@@ -59,13 +58,18 @@ export class AddEditMasterRoomComponent {
|
||||
|
||||
this.myForm = this.fb.group({
|
||||
id: this.dataRow.id,
|
||||
name: [this.dataRow.roomEntity.name, Validators.required],
|
||||
statusId: [this.dataRow.statusId, Validators.required],
|
||||
buildingId: [this.dataRow.buildingId, Validators.required],
|
||||
description: [this.dataRow.roomEntity.description, Validators.required],
|
||||
name: [this.dataRow.name, Validators.required],
|
||||
code: [this.dataRow.code, Validators.required],
|
||||
description: [this.dataRow.description, Validators.required],
|
||||
});
|
||||
}
|
||||
|
||||
toUppercase(event: Event) {
|
||||
const input = event.target as HTMLInputElement;
|
||||
input.value = input.value.toUpperCase();
|
||||
this.myForm.get('code').setValue(input.value);
|
||||
}
|
||||
|
||||
listDataStatus() {
|
||||
this.monitoringApiService.getMasterData().subscribe((res) => {
|
||||
this.data = res.results.data;
|
||||
|
||||
@@ -271,19 +271,21 @@
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -311,14 +313,38 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,7 +7,7 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
@@ -24,9 +24,9 @@
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #37A647 !important;
|
||||
background-color: #37A647 !important;
|
||||
"
|
||||
(click)="openAddMasterModal()"
|
||||
>
|
||||
@@ -42,7 +42,7 @@
|
||||
<div class="card-dashboard">
|
||||
<ngx-datatable
|
||||
class="bootstrap table-bordered"
|
||||
[limit]="5"
|
||||
[limit]="10"
|
||||
[rows]="filteredRows"
|
||||
[columnMode]="'force'"
|
||||
[headerHeight]="50"
|
||||
@@ -60,79 +60,64 @@
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
>
|
||||
<p style="color: #ffffff">{{ rowIndex + 1 }}</p>
|
||||
<p class="style-custom-label">{{ rowIndex + 1 }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
name="roomEntity"
|
||||
name="name"
|
||||
[flexGrow]="1"
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Room</span>
|
||||
<span class="style-custom-label">Room</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value.name }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column
|
||||
name="buildingEntity"
|
||||
name="code"
|
||||
[flexGrow]="1"
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Building</span>
|
||||
<span class="style-custom-label">Code Room</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value.name }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column
|
||||
name="roomEntity"
|
||||
name="description"
|
||||
[flexGrow]="1"
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Description</span>
|
||||
<span class="style-custom-label">Description</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value.description }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column
|
||||
name="statusEntity"
|
||||
[flexGrow]="1"
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Status</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff">{{ value.name }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
name="Actions"
|
||||
[flexGrow]="1"
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Actions</span>
|
||||
<span class="style-custom-label">Actions</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
@@ -142,8 +127,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="editRow(row)"
|
||||
>
|
||||
@@ -152,8 +138,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-danger"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="deleteRow(row)"
|
||||
>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { Router } from "@angular/router";
|
||||
import { BuildingService } from "../../service/monitoring-api.service";
|
||||
import { LoginService } from "../../service/login.service";
|
||||
import { ToastrService } from "ngx-toastr";
|
||||
|
||||
@Component({
|
||||
selector: "app-master-room",
|
||||
@@ -21,11 +22,13 @@ export class MasterRoomComponent {
|
||||
constructor(
|
||||
private modalService: NgbModal,
|
||||
private monitoringApiService: BuildingService,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private toastr: ToastrService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Master Room",
|
||||
links: [
|
||||
@@ -43,7 +46,7 @@ export class MasterRoomComponent {
|
||||
}
|
||||
|
||||
fetchData() {
|
||||
this.monitoringApiService.getBuildingRoomList().subscribe((res) => {
|
||||
this.monitoringApiService.getMasterRoomData().subscribe((res) => {
|
||||
this.data = res;
|
||||
this.filteredRows = this.data.results.data.sort((a, b) => b.id - a.id);
|
||||
// this.data.results.data.sort((a, b) => b.id - a.id);
|
||||
@@ -64,18 +67,17 @@ export class MasterRoomComponent {
|
||||
|
||||
rowContainsSearchTerm(row: any, searchTermLC: string): boolean {
|
||||
return (
|
||||
row.roomEntity.name.toLowerCase().includes(searchTermLC) ||
|
||||
row.roomEntity.description.toLowerCase().includes(searchTermLC) ||
|
||||
row.buildingEntity.name.toLowerCase().includes(searchTermLC) ||
|
||||
row.statusEntity.name.toLowerCase().includes(searchTermLC)
|
||||
row.name.toLowerCase().includes(searchTermLC) ||
|
||||
row.description.toLowerCase().includes(searchTermLC) ||
|
||||
row.code.toLowerCase().includes(searchTermLC)
|
||||
);
|
||||
}
|
||||
|
||||
openAddMasterModal() {
|
||||
const modalRef = this.modalService.open(AddEditMasterRoomComponent, {
|
||||
size: "lg",
|
||||
backdrop: "static", // Add this line
|
||||
keyboard: false, // Add this line
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
});
|
||||
|
||||
modalRef.componentInstance.mode = "add";
|
||||
@@ -84,21 +86,19 @@ export class MasterRoomComponent {
|
||||
if (result) {
|
||||
const filteredData = {
|
||||
name: result.name,
|
||||
code: result.code.trim(),
|
||||
description: result.description,
|
||||
};
|
||||
this.monitoringApiService
|
||||
.postMasterRoomParam(filteredData)
|
||||
.subscribe((res) => {
|
||||
const transformedData = {
|
||||
buildingId: result.buildingId,
|
||||
roomId: [res.data.id],
|
||||
statusId: result.statusId,
|
||||
};
|
||||
this.monitoringApiService
|
||||
.postBatchBuilding(transformedData)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
this.fetchData();
|
||||
}, (error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", error.error.message, {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -109,8 +109,6 @@ export class MasterRoomComponent {
|
||||
}
|
||||
|
||||
editRow(row) {
|
||||
console.log(row);
|
||||
|
||||
const modalRef = this.modalService.open(AddEditMasterRoomComponent, {
|
||||
size: "lg",
|
||||
backdrop: "static", // Add this line
|
||||
@@ -122,26 +120,22 @@ export class MasterRoomComponent {
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
if (result) {
|
||||
console.log(result);
|
||||
const filteredData = {
|
||||
id: result.id,
|
||||
id: result.roomId,
|
||||
name: result.name,
|
||||
code: result.code.trim(),
|
||||
description: result.description,
|
||||
};
|
||||
this.monitoringApiService
|
||||
.putMasterRoomParam(filteredData, row.id)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
const transformedData = {
|
||||
buildingId: result.buildingId,
|
||||
roomId: res.data.id,
|
||||
statusId: result.statusId,
|
||||
};
|
||||
this.monitoringApiService
|
||||
.puttBuildingRoom(transformedData, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
this.fetchData();
|
||||
}, (error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", error.error.message, {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -155,14 +149,19 @@ export class MasterRoomComponent {
|
||||
const confirmDelete = confirm("Are you sure you want to delete this item?");
|
||||
if (confirmDelete) {
|
||||
this.monitoringApiService
|
||||
.deleteHeaderDetailParam(row.roomEntity.id)
|
||||
.subscribe((res) => {
|
||||
this.monitoringApiService
|
||||
.deleteRoomBuilding(row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
.deleteRoom(row.id)
|
||||
.subscribe(
|
||||
(res) => {
|
||||
this.fetchData();
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Data sedang digunakan!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,19 +271,21 @@
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -311,14 +313,38 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,7 +7,7 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
@@ -24,9 +24,9 @@
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #37A647 !important;
|
||||
background-color: #37A647 !important;
|
||||
"
|
||||
(click)="openAddMasterModal()"
|
||||
>
|
||||
@@ -60,7 +60,7 @@
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
>
|
||||
<p style="color: #ffffff">{{ rowIndex + 1 }}</p>
|
||||
<p class="style-custom-label">{{ rowIndex + 1 }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -69,13 +69,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Name</span>
|
||||
<span class="style-custom-label">Name</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -84,13 +84,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Status</span>
|
||||
<span class="style-custom-label">Status</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff">
|
||||
<p class="style-custom-label">
|
||||
{{ value }}
|
||||
</p>
|
||||
</ng-template>
|
||||
@@ -101,7 +101,7 @@
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Actions</span>
|
||||
<span class="style-custom-label">Actions</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
@@ -111,8 +111,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="editRow(row)"
|
||||
>
|
||||
@@ -121,8 +122,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-danger"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="deleteRow(row)"
|
||||
>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { TableApiService } from 'src/app/_services/table-api.service';
|
||||
import { BuildingService } from '../../service/monitoring-api.service';
|
||||
import { AddEditMasterComponent } from '../add-edit-master/add-edit-master.component';
|
||||
import { LoginService } from '../../service/login.service';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
||||
@Component({
|
||||
selector: 'app-master-status',
|
||||
@@ -24,11 +25,13 @@ export class MasterStatusComponent {
|
||||
private modalService: NgbModal,
|
||||
private router: Router,
|
||||
private monitoringApiService: BuildingService,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private toastr: ToastrService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Master Status",
|
||||
links: [
|
||||
@@ -90,13 +93,28 @@ export class MasterStatusComponent {
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
if (this.filteredRows.some(value => value.name.trim().toLowerCase() === result.name.trim().toLowerCase())) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.postHeaderDetailParam(result)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
// if (result) {
|
||||
// this.monitoringApiService
|
||||
// .postHeaderDetailParam(result)
|
||||
// .subscribe((res) => {
|
||||
// console.log(res);
|
||||
// this.fetchData();
|
||||
// });
|
||||
// }
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
@@ -116,14 +134,38 @@ export class MasterStatusComponent {
|
||||
modalRef.componentInstance.mode = "edit";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) => value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
if (row.name.trim().toLowerCase() === result.name.trim().toLowerCase()) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) =>
|
||||
value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
@@ -135,11 +177,22 @@ export class MasterStatusComponent {
|
||||
deleteRow(row) {
|
||||
const confirmDelete = confirm("Are you sure you want to delete this item?");
|
||||
if (confirmDelete) {
|
||||
this.monitoringApiService
|
||||
.deleteHeaderDetailParam(row.id)
|
||||
.subscribe((res) => {
|
||||
this.monitoringApiService.deleteHeaderDetailParam(row.id).subscribe(
|
||||
(res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
this.toastr.success("Success", "Delete Completed.", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Data sedang digunakan!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,19 +271,21 @@
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -311,14 +313,38 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,7 +7,7 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
@@ -24,9 +24,9 @@
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #37A647 !important;
|
||||
background-color: #37A647 !important;
|
||||
"
|
||||
(click)="openAddMasterModal()"
|
||||
>
|
||||
@@ -60,7 +60,7 @@
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
>
|
||||
<p style="color: #ffffff">{{ rowIndex + 1 }}</p>
|
||||
<p class="style-custom-label">{{ rowIndex + 1 }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -69,13 +69,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Name</span>
|
||||
<span class="style-custom-label">Name</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -84,14 +84,14 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Status</span>
|
||||
<span class="style-custom-label">Status</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff">
|
||||
{{ value === "2" ? "Aktif" : "Nonaktif" }}
|
||||
<p class="style-custom-label">
|
||||
{{ value }}
|
||||
</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
@@ -101,7 +101,7 @@
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Actions</span>
|
||||
<span class="style-custom-label">Actions</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
@@ -111,8 +111,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="editRow(row)"
|
||||
>
|
||||
@@ -121,8 +122,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-danger"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="deleteRow(row)"
|
||||
>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { Router } from '@angular/router';
|
||||
import { BuildingService } from '../../service/monitoring-api.service';
|
||||
import { LoginService } from '../../service/login.service';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
||||
@Component({
|
||||
selector: 'app-master-type',
|
||||
@@ -24,11 +25,13 @@ export class MasterTypeComponent {
|
||||
private modalService: NgbModal,
|
||||
private router: Router,
|
||||
private monitoringApiService: BuildingService,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private toastr: ToastrService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Master Type",
|
||||
links: [
|
||||
@@ -88,15 +91,29 @@ export class MasterTypeComponent {
|
||||
modalRef.componentInstance.mode = "add";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
if (this.filteredRows.some(value => value.name.trim().toLowerCase() === result.name.trim().toLowerCase())) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.postHeaderDetailParam(result)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
// if (result) {
|
||||
// this.monitoringApiService
|
||||
// .postHeaderDetailParam(result)
|
||||
// .subscribe((res) => {
|
||||
// console.log(res);
|
||||
// this.fetchData();
|
||||
// });
|
||||
// }
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
@@ -116,14 +133,38 @@ export class MasterTypeComponent {
|
||||
modalRef.componentInstance.mode = "edit";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) => value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
if (row.name.trim().toLowerCase() === result.name.trim().toLowerCase()) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) =>
|
||||
value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
@@ -135,11 +176,22 @@ export class MasterTypeComponent {
|
||||
deleteRow(row) {
|
||||
const confirmDelete = confirm("Are you sure you want to delete this item?");
|
||||
if (confirmDelete) {
|
||||
this.monitoringApiService
|
||||
.deleteHeaderDetailParam(row.id)
|
||||
.subscribe((res) => {
|
||||
this.monitoringApiService.deleteHeaderDetailParam(row.id).subscribe(
|
||||
(res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
this.toastr.success("Success", "Delete Completed.", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Data sedang digunakan!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,19 +271,21 @@
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
background-color: #37A647;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #252525;
|
||||
color: #ededed;
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
@@ -311,14 +313,38 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: rgba(190, 242, 100, 0.11); /* Black color for table rows */
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #1a1a1a; /* Darker black for hover effect */
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB !important">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,7 +7,7 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
@@ -24,9 +24,9 @@
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #bef264 !important;
|
||||
color: #ffffff !important;
|
||||
border-color: #37A647 !important;
|
||||
background-color: #37A647 !important;
|
||||
"
|
||||
(click)="openAddMasterModal()"
|
||||
>
|
||||
@@ -60,7 +60,7 @@
|
||||
ngx-datatable-cell-template
|
||||
let-rowIndex="rowIndex"
|
||||
>
|
||||
<p style="color: #ffffff">{{ rowIndex + 1 }}</p>
|
||||
<p class="style-custom-label">{{ rowIndex + 1 }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -69,13 +69,13 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Name</span>
|
||||
<span class="style-custom-label">Name</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
let-value="value"
|
||||
ngx-datatable-cell-template
|
||||
>
|
||||
<p style="color: #ffffff">{{ value }}</p>
|
||||
<p class="style-custom-label">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
@@ -84,14 +84,14 @@
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Status</span>
|
||||
<span class="style-custom-label">Status</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
let-value="value"
|
||||
>
|
||||
<p style="color: #ffffff">
|
||||
{{ value === "2" ? "Aktif" : "Nonaktif" }}
|
||||
<p class="style-custom-label">
|
||||
{{ value }}
|
||||
</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
@@ -101,7 +101,7 @@
|
||||
[minWidth]="150"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #ffffff">Actions</span>
|
||||
<span class="style-custom-label">Actions</span>
|
||||
</ng-template>
|
||||
<ng-template
|
||||
ngx-datatable-cell-template
|
||||
@@ -111,8 +111,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-warning mr-1"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="editRow(row)"
|
||||
>
|
||||
@@ -121,8 +122,9 @@
|
||||
<button
|
||||
class="btn btn-sm btn-danger"
|
||||
style="
|
||||
background-color: #000000 !important;
|
||||
border-color: #bef264 !important;
|
||||
color: #37a647 !important;
|
||||
border-color: #DDE1E6 !important;
|
||||
background-color: #DDE1E6 !important;
|
||||
"
|
||||
(click)="deleteRow(row)"
|
||||
>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { Router } from '@angular/router';
|
||||
import { BuildingService } from '../../service/monitoring-api.service';
|
||||
import { LoginService } from '../../service/login.service';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
||||
@Component({
|
||||
selector: 'app-master-voltage',
|
||||
@@ -24,11 +25,13 @@ export class MasterVoltageComponent {
|
||||
private modalService: NgbModal,
|
||||
private router: Router,
|
||||
private monitoringApiService: BuildingService,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private toastr: ToastrService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Master Voltage",
|
||||
links: [
|
||||
@@ -88,14 +91,20 @@ export class MasterVoltageComponent {
|
||||
modalRef.componentInstance.mode = "add";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
if (this.filteredRows.some(value => value.name.trim().toLowerCase() === result.name.trim().toLowerCase())) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.postHeaderDetailParam(result)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
@@ -116,14 +125,38 @@ export class MasterVoltageComponent {
|
||||
modalRef.componentInstance.mode = "edit";
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
console.log(res);
|
||||
this.fetchData();
|
||||
});
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) => value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
if (row.name.trim().toLowerCase() === result.name.trim().toLowerCase()) {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
this.filteredRows.some(
|
||||
(value) =>
|
||||
value.name.trim().toLowerCase() === result.name.trim().toLowerCase()
|
||||
)
|
||||
) {
|
||||
this.toastr.error("Warning", "Data yang anda masukan double.", {
|
||||
timeOut: 5000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.monitoringApiService
|
||||
.putHeaderDetailParam(result, row.id)
|
||||
.subscribe((res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
@@ -135,11 +168,22 @@ export class MasterVoltageComponent {
|
||||
deleteRow(row) {
|
||||
const confirmDelete = confirm("Are you sure you want to delete this item?");
|
||||
if (confirmDelete) {
|
||||
this.monitoringApiService
|
||||
.deleteHeaderDetailParam(row.id)
|
||||
.subscribe((res) => {
|
||||
this.monitoringApiService.deleteHeaderDetailParam(row.id).subscribe(
|
||||
(res) => {
|
||||
this.fetchData();
|
||||
});
|
||||
this.toastr.success("Success", "Delete Completed.", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.toastr.error("Error", "Data sedang digunakan!", {
|
||||
timeOut: 2000,
|
||||
closeButton: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
:host ::ng-deep .gap_fl_btn {
|
||||
margin: 0 0.3rem;
|
||||
margin: 0 0.3rem;
|
||||
}
|
||||
|
||||
:host ::ng-deep .block-ui-wrapper {
|
||||
@@ -7,20 +7,70 @@
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart1 .ct-series-a .ct-slice-donut {
|
||||
stroke: #BEF264;
|
||||
stroke-width: 35px !important;
|
||||
stroke: #37A647;
|
||||
stroke-width: 50px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart1 .ct-series-b .ct-slice-donut {
|
||||
stroke: #ffffff;
|
||||
stroke-width: 35px !important;
|
||||
stroke-width: 50px !important;
|
||||
}
|
||||
|
||||
.btn-no-hover {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.btn-no-hover:hover {
|
||||
.custom-card-header {
|
||||
background-color: #dde1e6 !important;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
color: #242222 !important;
|
||||
font-weight: 600 !important;
|
||||
font-size: 20px !important;
|
||||
}
|
||||
|
||||
.header-subtitle {
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
color: #242222 !important;
|
||||
font-weight: 600 !important;
|
||||
font-size: 24px !important;
|
||||
}
|
||||
|
||||
.custom-divider {
|
||||
border-top: 6px solid rgb(0, 0, 0);
|
||||
}
|
||||
|
||||
.custom-total {
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 40px !important;
|
||||
color: #242222 !important;
|
||||
font-weight: 800 !important;
|
||||
}
|
||||
|
||||
.custom-label-chart {
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 20px !important;
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
.btn-room {
|
||||
background-color: #2f5137 !important;
|
||||
color: #ffffff;
|
||||
width: 163px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.btn-detail {
|
||||
background-color: transparent !important;
|
||||
border-color: #242222 !important;
|
||||
color: #242222;
|
||||
width: 163px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
/* .btn-no-hover:hover {
|
||||
background-color: transparent !important;
|
||||
color: inherit !important;
|
||||
}
|
||||
@@ -28,4 +78,4 @@
|
||||
.btn-primary.round:hover {
|
||||
color: #BEF264 !important;
|
||||
border-color: #BEF264 !important;
|
||||
}
|
||||
} */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important;">
|
||||
<div class="app-content content" style="background-color: #fbfbfb">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -6,41 +6,98 @@
|
||||
<div class="content-body">
|
||||
<section id="social-cards">
|
||||
<div class="row mb-2">
|
||||
<div class="col-md-6">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="Search..."
|
||||
[(ngModel)]="searchTerm"
|
||||
(input)="filterRows()"
|
||||
/>
|
||||
<div class="col-3">
|
||||
<div class="form-group">
|
||||
<ng-select
|
||||
class="select-custom"
|
||||
[items]="dataBuildingList"
|
||||
[searchable]="true"
|
||||
bindLabel="name"
|
||||
bindValue="id"
|
||||
placeholder="Select Building"
|
||||
[(ngModel)]="buildingSelected"
|
||||
(change)="buildingChange($event)"
|
||||
>
|
||||
</ng-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="form-group">
|
||||
<ng-select
|
||||
class="select-custom"
|
||||
[items]="dataFloorList"
|
||||
[searchable]="true"
|
||||
[disabled]="disableFloorList"
|
||||
bindLabel="name"
|
||||
bindValue="id"
|
||||
placeholder="Select Floor"
|
||||
[(ngModel)]="floorSelected"
|
||||
>
|
||||
</ng-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3 text-left">
|
||||
<div class="d-flex">
|
||||
<button
|
||||
type="button"
|
||||
class="btn ml-2"
|
||||
(click)="doFilter()"
|
||||
style="
|
||||
background-color: #37a647 !important;
|
||||
border-color: #37a647 !important;
|
||||
border-radius: 12px;
|
||||
color: #ffffff;
|
||||
"
|
||||
[disabled]="spinnerFilterActive"
|
||||
>
|
||||
<i
|
||||
class="la la-search"
|
||||
style="color: #ffffff !important"
|
||||
*ngIf="!spinnerFilterActive"
|
||||
></i>
|
||||
<i
|
||||
class="la la-spinner spinner"
|
||||
style="color: #ffffff !important"
|
||||
*ngIf="spinnerFilterActive"
|
||||
></i>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn ml-2"
|
||||
style="
|
||||
background-color: #fbfbfb !important;
|
||||
border-color: #242222 !important;
|
||||
color: #242222;
|
||||
border-radius: 12px;
|
||||
"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-2">
|
||||
<div
|
||||
class="col-xl-4 col-md-6 col-12"
|
||||
class="col-12 col-sm-12 col-md-12 col-lg-6 col-xl-4"
|
||||
*ngFor="let data of filteredRows"
|
||||
>
|
||||
<div class="card" style="background-color: #252525 !important; border-radius: 10px;">
|
||||
<div class="card-header mb-2" style="background-color: #252525 !important;">
|
||||
<div
|
||||
class="card"
|
||||
style="background-color: #dde1e6 !important; border-radius: 10px"
|
||||
>
|
||||
<div class="card-header mb-2 custom-card-header">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h4
|
||||
class="text-muted mb-1 font-weight-bold"
|
||||
style="font-family: Montserrat, sans-serif; color: #ffffff !important;"
|
||||
>
|
||||
Building
|
||||
</h4>
|
||||
<h3
|
||||
class="text-muted mb-0 open-sans"
|
||||
style="font-family: Open Sans, sans-serif; color: #ffffff !important; font-weight: 600;"
|
||||
>
|
||||
<h4 class="header-title">{{labelData}}</h4>
|
||||
<h3 class="header-subtitle">
|
||||
{{ data.build_name ? data.build_name : data.name }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<hr style="border-top: 4px solid #ffffff; border-color: #ffffff !important;" />
|
||||
<hr class="custom-divider" />
|
||||
</div>
|
||||
|
||||
<div class="card-content">
|
||||
<div class="donut-chart1">
|
||||
<x-chartist
|
||||
@@ -57,36 +114,27 @@
|
||||
class="text-center"
|
||||
style="
|
||||
position: absolute;
|
||||
top: 65%;
|
||||
top: 73%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
"
|
||||
>
|
||||
<h3
|
||||
class="display-4 blue-grey darken-1"
|
||||
style="font-size: 2em; color: #ffffff !important;"
|
||||
>
|
||||
{{ data.total }} kWh
|
||||
</h3>
|
||||
<h6 style="color: #ffffff !important;">Consumption</h6>
|
||||
<h3 class="custom-total">{{ data.total }} KWH</h3>
|
||||
<h6 class="custom-label-chart">Consumption</h6>
|
||||
</div>
|
||||
|
||||
<div class="form-group text-center">
|
||||
<button
|
||||
<!-- <button
|
||||
type="button"
|
||||
class="btn btn-primary round btn-min-width mr-1 mb-1"
|
||||
class="btn btn-min-width mr-1 mb-1 btn-room"
|
||||
(click)="viewRoom(data)"
|
||||
ngbTooltip="Room"
|
||||
style="background-color: #ffffff !important; color: #000000;"
|
||||
>
|
||||
Room
|
||||
</button>
|
||||
</button> -->
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-success round btn-min-width mr-1 mb-1"
|
||||
(click)="viewRow(data)"
|
||||
ngbTooltip="Detail"
|
||||
style="background-color: #BEF264 !important; color: #000000;"
|
||||
class="btn btn-min-width mr-1 mb-1 btn-room"
|
||||
(click)="viewDetail(data)"
|
||||
>
|
||||
Detail
|
||||
</button>
|
||||
@@ -96,6 +144,20 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12" *ngIf="filteredRows?.length === 0">
|
||||
<div class="card" style="background-color: #DDE1E6; min-height: 200px;">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<p class="text-center" style="color: #242222;">No data available</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { TableMonitoringService } from "../monitoring.service";
|
||||
import { Router } from "@angular/router";
|
||||
import { BuildingService } from "../../service/monitoring-api.service";
|
||||
import { LoginService } from "../../service/login.service";
|
||||
import { DeviceService } from "../../service/device.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-building",
|
||||
@@ -10,7 +11,6 @@ import { LoginService } from "../../service/login.service";
|
||||
styleUrls: ["./building.component.css"],
|
||||
})
|
||||
export class BuildingComponent {
|
||||
data: any;
|
||||
public breadcrumb: any;
|
||||
feedbacksdonutChart: any;
|
||||
donutChart1: any;
|
||||
@@ -18,16 +18,27 @@ export class BuildingComponent {
|
||||
topUseData: any;
|
||||
searchTerm: string = "";
|
||||
colorChart: string = "";
|
||||
spinnerFilterActive = false;
|
||||
typeData: any;
|
||||
labelData: any;
|
||||
disableFloorList = true;
|
||||
|
||||
dataBuildingList: any;
|
||||
buildingSelected: any;
|
||||
dataFloorList: any;
|
||||
floorSelected: any;
|
||||
|
||||
constructor(
|
||||
private monitoringService: TableMonitoringService,
|
||||
private monitoringApiService: BuildingService,
|
||||
private deviceService: DeviceService,
|
||||
private router: Router,
|
||||
private authService: LoginService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Dashboard",
|
||||
links: [
|
||||
@@ -50,42 +61,83 @@ export class BuildingComponent {
|
||||
showLabel: false,
|
||||
},
|
||||
};
|
||||
this.listBuilding();
|
||||
|
||||
this.dataListBuilding();
|
||||
this.listBuilding(this.buildingSelected, this.floorSelected);
|
||||
}
|
||||
|
||||
listBuilding() {
|
||||
this.monitoringApiService.listBuilding().subscribe((res) => {
|
||||
this.data = res.data;
|
||||
this.filteredRows = res.data;
|
||||
dataListBuilding() {
|
||||
this.monitoringApiService.getBuildingList().subscribe((data) => {
|
||||
this.dataBuildingList = data.data.filter(
|
||||
(item) => item.statusName.toLowerCase() === "aktif"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// buildingData() {
|
||||
// this.monitoringApiService.getBuildingData().subscribe((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
// }
|
||||
|
||||
filterRows() {
|
||||
if (!this.searchTerm) {
|
||||
this.filteredRows = [...this.data];
|
||||
buildingChange(e) {
|
||||
if (e) {
|
||||
this.dataListFloor(e.id);
|
||||
this.disableFloorList = false;
|
||||
this.floorSelected = null;
|
||||
} else {
|
||||
this.filteredRows = this.data.filter((row) =>
|
||||
this.rowContainsSearchTerm(row)
|
||||
);
|
||||
this.floorSelected = null;
|
||||
this.disableFloorList = true;
|
||||
}
|
||||
}
|
||||
|
||||
rowContainsSearchTerm(row: any): boolean {
|
||||
const searchTermLC = this.searchTerm.toLowerCase();
|
||||
return Object.values(row).some(
|
||||
(value) =>
|
||||
value !== null && value.toString().toLowerCase().includes(searchTermLC)
|
||||
);
|
||||
dataListFloor(buildingId) {
|
||||
this.monitoringApiService
|
||||
.getMasterDataListFloor(buildingId)
|
||||
.subscribe((data) => {
|
||||
const newArray = data.data
|
||||
.map((item) => ({
|
||||
id: item.id,
|
||||
name: `${item.name} (${item.code})`,
|
||||
}))
|
||||
.sort((a, b) => b.id - a.id);
|
||||
this.dataFloorList = newArray;
|
||||
});
|
||||
}
|
||||
|
||||
viewRow(row) {
|
||||
this.router.navigate(["/monitoring/view-new-building", row.id]);
|
||||
listBuilding(buildingId, floorId) {
|
||||
this.deviceService.filterDashboard(buildingId, floorId).subscribe((res) => {
|
||||
this.filteredRows = res.data;
|
||||
this.typeData = this.filteredRows[0].type;
|
||||
if (this.typeData === "building") {
|
||||
this.labelData = "Building";
|
||||
} else if (this.typeData === "floor") {
|
||||
this.labelData = "Floor";
|
||||
} else if (this.typeData === "room") {
|
||||
this.labelData = "Room";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
doFilter() {
|
||||
this.spinnerFilterActive = true;
|
||||
this.listBuilding(this.buildingSelected, this.floorSelected);
|
||||
setTimeout(() => {
|
||||
this.spinnerFilterActive = false;
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
viewDetail(row) {
|
||||
if (row.building_id !== undefined && row.floor_id === undefined) {
|
||||
this.router.navigate([
|
||||
"/monitoring/view-detail-floor",
|
||||
row.building_id,
|
||||
row.id,
|
||||
]);
|
||||
} else if (row.building_id !== undefined && row.floor_id !== undefined) {
|
||||
this.router.navigate([
|
||||
"/monitoring/view-detail-room",
|
||||
row.building_id,
|
||||
row.floor_id,
|
||||
row.id,
|
||||
]);
|
||||
} else {
|
||||
this.router.navigate(["/monitoring/view-detail-building", row.id]);
|
||||
}
|
||||
}
|
||||
|
||||
editRow(row) {
|
||||
|
||||
@@ -1,14 +1,37 @@
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #ffffff !important;
|
||||
background-color: #252525 !important;
|
||||
|
||||
/* :host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px;
|
||||
border-radius: 12px !important;
|
||||
} */
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
|
||||
.background-round {
|
||||
background-color: #252525 !important;
|
||||
padding: 8px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #bef264;
|
||||
border-color: #bef264 !important;
|
||||
background-color: #252525 !important;
|
||||
padding: 8px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #BEF264;
|
||||
border-color: #BEF264 !important;
|
||||
}
|
||||
|
||||
.text-custom-name{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.text-custom-category{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 12px;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #FBFBFB;">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -7,7 +7,7 @@
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #FBFBFB !important; box-shadow: none !important;">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
@@ -21,6 +21,7 @@
|
||||
bindValue="id"
|
||||
placeholder="Select Building"
|
||||
[(ngModel)]="buildingSelected"
|
||||
style="width: 100% !important;"
|
||||
>
|
||||
</ng-select>
|
||||
</div>
|
||||
@@ -35,6 +36,7 @@
|
||||
bindValue="id"
|
||||
placeholder="Select Category"
|
||||
[(ngModel)]="categorySelected"
|
||||
style="width: 100% !important;"
|
||||
>
|
||||
</ng-select>
|
||||
</div>
|
||||
@@ -49,6 +51,7 @@
|
||||
bindValue="id"
|
||||
placeholder="Select Status"
|
||||
[(ngModel)]="statusSelected"
|
||||
style="width: 100% !important;"
|
||||
>
|
||||
</ng-select>
|
||||
</div>
|
||||
@@ -57,12 +60,13 @@
|
||||
<div class="d-flex">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-success ml-2"
|
||||
class="btn ml-2"
|
||||
(click)="doFilter()"
|
||||
style="
|
||||
background-color: #252525 !important;
|
||||
border-color: #ffffff !important;
|
||||
background-color: #37A647 !important;
|
||||
border-color: #37A647 !important;
|
||||
border-radius: 12px;
|
||||
color: #ffffff;
|
||||
"
|
||||
[disabled]="spinnerFilterActive"
|
||||
>
|
||||
@@ -82,9 +86,9 @@
|
||||
class="btn btn-outline-success ml-2"
|
||||
(click)="doFilterCancel()"
|
||||
style="
|
||||
background-color: #252525 !important;
|
||||
border-color: #ffffff !important;
|
||||
color: #ffffff !important;
|
||||
background-color: #FBFBFB !important;
|
||||
border-color: #6B6B6B !important;
|
||||
color: #6B6B6B !important;
|
||||
border-radius: 12px;
|
||||
"
|
||||
>Cancel
|
||||
@@ -100,10 +104,19 @@
|
||||
</section>
|
||||
<section id="configuration">
|
||||
<div class="row">
|
||||
<div class="col-12" *ngIf="filteredRows?.length === 0">
|
||||
<div class="card" style="background-color: #DDE1E6; min-height: 200px;">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<p class="text-center" style="color: #242222;">No data available</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-12" *ngFor="let item of filteredDeviceRows">
|
||||
<div
|
||||
class="card"
|
||||
style="background-color: #252525; position: relative"
|
||||
style="background-color: #DDE1E6; position: relative"
|
||||
>
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
@@ -111,7 +124,7 @@
|
||||
<div class="align-self-center">
|
||||
<div
|
||||
style="
|
||||
background-color: #414F2B;
|
||||
background-color: #37A647;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
@@ -121,29 +134,28 @@
|
||||
"
|
||||
>
|
||||
<i
|
||||
class="ri-lightbulb-flash-fill font-large-1 blue-grey d-block"
|
||||
style="color: #bef264 !important"
|
||||
class="{{item.category_icon}} font-large-1 blue-grey d-block"
|
||||
style="color: #ffffff !important"
|
||||
></i>
|
||||
</div>
|
||||
<div style="margin-top: 10px">
|
||||
<span
|
||||
class="text-muted"
|
||||
style="color: #ffffff !important"
|
||||
class="text-custom-name"
|
||||
>{{ item.name }}</span
|
||||
>
|
||||
<br />
|
||||
<span
|
||||
class="text-muted"
|
||||
class="text-custom-category"
|
||||
>{{item.category_name}}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui-switch-container" style="position: absolute; bottom: 10px; right: 10px;">
|
||||
<ui-switch
|
||||
style="border-color: #bef264 !important"
|
||||
style="border-color: #ffffff !important"
|
||||
class="switchery"
|
||||
switchColor="black"
|
||||
color="rgb(190, 242, 100)"
|
||||
color="rgb(55, 166, 71)"
|
||||
size="small"
|
||||
[checked]="item.status_id === 2"
|
||||
(change)="switchChanged($event, item)"
|
||||
|
||||
@@ -23,7 +23,10 @@ export class ControlDeviceSeemoreComponent {
|
||||
dataMasterStatus: any;
|
||||
spinnerFilterActive = false;
|
||||
switchState: boolean;
|
||||
paramsId: any;
|
||||
buildingId: any;
|
||||
floorId: any;
|
||||
roomId: any;
|
||||
modeRoute: any;
|
||||
|
||||
public breadcrumb: any;
|
||||
spinnerActive: boolean = false;
|
||||
@@ -37,16 +40,18 @@ export class ControlDeviceSeemoreComponent {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.route.params.subscribe((params) => {
|
||||
const buildingId = params["id"];
|
||||
this.paramsId = buildingId ? buildingId: 0;
|
||||
this.buildingSelected = parseInt(this.paramsId);
|
||||
|
||||
this.modeRoute = params["mode"];
|
||||
this.buildingId = params["buildingId"] ? params["buildingId"] : 0;
|
||||
this.floorId = params["floorId"] ? params["floorId"] : 0;
|
||||
this.roomId = params["roomId"] ? params["roomId"] : 0;
|
||||
this.buildingSelected = parseInt(this.buildingId);
|
||||
});
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Control Device",
|
||||
linkBack: `/monitoring/view-new-building/${this.buildingSelected}`,
|
||||
linkBack: this.routeBack(''),
|
||||
isLinkBack: true,
|
||||
links: [
|
||||
{
|
||||
@@ -76,6 +81,17 @@ export class ControlDeviceSeemoreComponent {
|
||||
this.dataListBuilding();
|
||||
}
|
||||
|
||||
routeBack(route){
|
||||
if (this.modeRoute === 'building') {
|
||||
route = `/monitoring/view-detail-building/${this.buildingId}`;
|
||||
} else if (this.modeRoute === 'floor') {
|
||||
route = `/monitoring/view-detail-floor/${this.buildingId}/${this.floorId}`;
|
||||
} else if (this.modeRoute === 'room') {
|
||||
route = `/monitoring/view-detail-room/${this.buildingId}/${this.floorId}/${this.roomId}`;
|
||||
}
|
||||
return route
|
||||
}
|
||||
|
||||
fetchData(buildingSelected, categorySelected, statusSelected) {
|
||||
this.deviceService
|
||||
.getDeviceData(buildingSelected, categorySelected, statusSelected)
|
||||
@@ -89,7 +105,7 @@ export class ControlDeviceSeemoreComponent {
|
||||
filterDevices(devices: any[]): any[] {
|
||||
return devices.filter((device) =>
|
||||
device.mapping.some(
|
||||
(map) => map.name.startsWith("switch") && map.type === "Boolean"
|
||||
(map) => map.code.startsWith("switch") && map.type === "Boolean"
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -105,13 +121,13 @@ export class ControlDeviceSeemoreComponent {
|
||||
this.dataMasterCategori = dataCategory.filter(
|
||||
(item) => item.statusName.toLowerCase() === "aktif"
|
||||
);
|
||||
this.dataMasterStatus = dataStatus.filter((item) => item.statusName.toLowerCase() === "aktif");
|
||||
this.dataMasterStatus = dataStatus.filter((item) => item.statusName.toLowerCase() === "aktif" || item.status === "71");
|
||||
});
|
||||
}
|
||||
|
||||
dataListBuilding() {
|
||||
this.monitoringApiService.getBuildingList().subscribe((data) => {
|
||||
this.dataBuildingList = data.data.filter((item) => item.statusId === 2);
|
||||
this.dataBuildingList = data.data.filter((item) => item.statusName.toLowerCase() === "aktif" || item.status_id === 71);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -136,7 +152,7 @@ export class ControlDeviceSeemoreComponent {
|
||||
}
|
||||
|
||||
doFilterCancel(){
|
||||
this.buildingSelected = parseInt(this.paramsId);
|
||||
this.buildingSelected = parseInt(this.buildingId);
|
||||
this.categorySelected = undefined;
|
||||
this.statusSelected = undefined;
|
||||
this.fetchData(this.buildingSelected, 0, 0);
|
||||
@@ -162,13 +178,13 @@ export class ControlDeviceSeemoreComponent {
|
||||
|
||||
switchChanged(ev, data) {
|
||||
const requestData = {
|
||||
device_id: data.device_id,
|
||||
switch: data.mapping[0].switch,
|
||||
id: data.id,
|
||||
code: data.mapping[0].code,
|
||||
value: ev,
|
||||
command_type: "on_off",
|
||||
};
|
||||
this.deviceService.deviceSwitch(requestData).subscribe((res) => {
|
||||
console.log(res);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ canvas {
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart2 .ct-series-b .ct-slice-donut {
|
||||
stroke: #BEF264;
|
||||
stroke: #37A647;
|
||||
stroke-width: 20px !important;
|
||||
}
|
||||
|
||||
@@ -67,28 +67,110 @@ canvas {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-point{
|
||||
stroke: #BEF264;
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-point {
|
||||
stroke: #37A647;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-line{
|
||||
stroke: #BEF264;
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-line {
|
||||
stroke: #37A647;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-area{
|
||||
fill: #BEF264;
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-area {
|
||||
fill: #37A647;
|
||||
fill-opacity: 1;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-cost .ct-point{
|
||||
:host ::ng-deep .sp-line-total-cost .ct-point {
|
||||
stroke-width: 0px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .progress-bar {
|
||||
background-color: #BEF264 !important;
|
||||
background-color: #37A647 !important;
|
||||
}
|
||||
|
||||
.background-round {
|
||||
background-color: #252525 !important;
|
||||
padding: 8px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #BEF264;
|
||||
border-color: #BEF264 !important;
|
||||
}
|
||||
background-color: #37A647 !important;
|
||||
padding: 8px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #37A647;
|
||||
border-color: #37A647 !important;
|
||||
}
|
||||
|
||||
.custom-label {
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
color: #242222;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.custom-value {
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
color: #242222;
|
||||
font-weight: 800;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.custom-style-header{
|
||||
background-color: #DDE1E6 !important;
|
||||
border-bottom: 3px solid #242222;
|
||||
}
|
||||
|
||||
/* day */
|
||||
.days-container {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.day {
|
||||
font-family: "Nunito Sans", sans-serif;
|
||||
color: #242222;
|
||||
padding: 2px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.current-day {
|
||||
color: #37A647;
|
||||
}
|
||||
|
||||
.temperature-container {
|
||||
text-align: center;
|
||||
margin-top: 50px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.temperature {
|
||||
font-family: "Nunito Sans", sans-serif;
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
color: #242222;
|
||||
}
|
||||
|
||||
.date-time-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.current-date,
|
||||
.current-time {
|
||||
font-family: "Nunito Sans", sans-serif;
|
||||
font-size: 16px;
|
||||
color: #242222;
|
||||
}
|
||||
|
||||
.custom-card-temp{
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
/* echart */
|
||||
.custom-card-air {
|
||||
background-color: #dde1e6 !important;
|
||||
}
|
||||
|
||||
.echart-container {
|
||||
height: 200px; /* Tinggi awal untuk menentukan tinggi chart */
|
||||
width: 100%; /* Lebar maksimal */
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content" style="background-color: #fbfbfb">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -6,20 +6,25 @@
|
||||
<div class="content-body">
|
||||
<div class="row">
|
||||
<div class="col-xl-3 col-md-6 col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #dde1e6 !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h5 style="color: #ffffff">Kwh Consumption</h5>
|
||||
<h3 style="color: #ffffff">
|
||||
{{ topCard?.kwh_consumption ? topCard?.kwh_consumption.toFixed(3) : 0 }} Kwh
|
||||
<h5 class="custom-label">Kwh Consumption</h5>
|
||||
<h3 class="custom-value">
|
||||
{{
|
||||
topCard?.kwh_consumption
|
||||
? topCard?.kwh_consumption.toFixed(1)
|
||||
: 0
|
||||
}}
|
||||
Kwh
|
||||
</h3>
|
||||
</div>
|
||||
<div class="align-self-center">
|
||||
<div
|
||||
style="
|
||||
background-color: #414f2b;
|
||||
background-color: #37a647;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
@@ -30,7 +35,7 @@
|
||||
>
|
||||
<i
|
||||
class="icon-energy primary font-large-1 float-right"
|
||||
style="color: #bef264 !important"
|
||||
style="color: #ffffff !important"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -40,18 +45,18 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-md-6 col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #dde1e6 !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h5 style="color: #ffffff">Device</h5>
|
||||
<h3 style="color: #ffffff">{{ topCard?.total_device }}</h3>
|
||||
<h5 class="custom-label">Device</h5>
|
||||
<h3 class="custom-value">{{ topCard?.total_device }}</h3>
|
||||
</div>
|
||||
<div class="align-self-center">
|
||||
<div
|
||||
style="
|
||||
background-color: #414f2b;
|
||||
background-color: #37a647;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
@@ -62,7 +67,7 @@
|
||||
>
|
||||
<i
|
||||
class="ri-device-line primary font-large-1 float-right"
|
||||
style="color: #bef264 !important"
|
||||
style="color: #ffffff !important"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,18 +77,18 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-md-6 col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #dde1e6 !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h5 style="color: #ffffff">Room</h5>
|
||||
<h3 style="color: #ffffff">{{ topCard?.total_room }}</h3>
|
||||
<h5 class="custom-label">Room</h5>
|
||||
<h3 class="custom-value">{{ topCard?.total_room }}</h3>
|
||||
</div>
|
||||
<div class="align-self-center">
|
||||
<div
|
||||
style="
|
||||
background-color: #414f2b;
|
||||
background-color: #37a647;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
@@ -94,7 +99,7 @@
|
||||
>
|
||||
<i
|
||||
class="ri-building-2-line font-large-1 float-right"
|
||||
style="color: #bef264 !important"
|
||||
style="color: #ffffff !important"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -104,23 +109,25 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-md-6 col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #dde1e6 !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h5 style="color: #ffffff">Summary Cost</h5>
|
||||
<h3 style="color: #ffffff">
|
||||
<h5 class="custom-label">Summary Cost</h5>
|
||||
<h3 class="custom-value">
|
||||
{{
|
||||
summaryCost?.summary_cost
|
||||
| currency : "Rp " : "symbol" : "1.0-0"
|
||||
? (summaryCost?.summary_cost
|
||||
| currency : "Rp " : "symbol" : "1.0-0")
|
||||
: 0
|
||||
}}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="align-self-center">
|
||||
<div
|
||||
style="
|
||||
background-color: #414f2b;
|
||||
background-color: #37a647;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
@@ -131,7 +138,7 @@
|
||||
>
|
||||
<i
|
||||
class="ri-money-dollar-box-line font-large-1 float-right"
|
||||
style="color: #bef264 !important"
|
||||
style="color: #ffffff !important"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -141,54 +148,126 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<canvas
|
||||
style="
|
||||
background-color: #252525 !important;
|
||||
border-color: #252525;
|
||||
color: #ffffff;
|
||||
"
|
||||
class="barchart"
|
||||
height="400"
|
||||
width="1900"
|
||||
baseChart
|
||||
[datasets]="barChartData"
|
||||
[labels]="barChartLabels"
|
||||
[options]="barChartOptions"
|
||||
[legend]="barChartLegend"
|
||||
chartType="bar"
|
||||
<div class="card" style="background-color: #dde1e6 !important">
|
||||
<div class="card-body">
|
||||
<div
|
||||
(chartClick)="onChartClick($event)"
|
||||
echarts
|
||||
[options]="chartOptionBar"
|
||||
class="echart-container"
|
||||
style="height: 400px !important; display: block"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xl-4 col-md-6 col-12">
|
||||
<div
|
||||
class="card custom-card-temp"
|
||||
style="background-color: #dde1e6 !important"
|
||||
>
|
||||
<div class="card-header custom-style-header">
|
||||
<h4 class="card-title text-center text-custom-label">
|
||||
Temperature
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="days-container">
|
||||
<div
|
||||
*ngFor="let day of days"
|
||||
[ngClass]="{ 'current-day': day.isToday }"
|
||||
class="day"
|
||||
>
|
||||
</canvas>
|
||||
{{ day.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="temperature-container">
|
||||
<span class="temperature">{{ roomTemperature }}°C</span>
|
||||
</div>
|
||||
<div class="date-time-container">
|
||||
<span class="current-time">Time :{{ currentTime }}</span>
|
||||
<span class="current-date">{{ currentDate }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-md-6 col-12">
|
||||
<div class="card custom-card-air">
|
||||
<div class="card-header custom-style-header">
|
||||
<h4 class="card-title text-center text-custom-label">
|
||||
Air Quality
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div
|
||||
echarts
|
||||
[options]="chartOption"
|
||||
class="echart-container"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-4 col-md-6 col-12">
|
||||
<div
|
||||
class="card custom-card-temp"
|
||||
style="background-color: #dde1e6 !important"
|
||||
>
|
||||
<div class="card-header custom-style-header">
|
||||
<h4 class="card-title text-center text-custom-label">Humidity</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="days-container">
|
||||
<div
|
||||
*ngFor="let day of days"
|
||||
[ngClass]="{ 'current-day': day.isToday }"
|
||||
class="day"
|
||||
>
|
||||
{{ day.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="temperature-container">
|
||||
<span class="temperature">{{ roomHumidity }}%</span>
|
||||
</div>
|
||||
<div class="date-time-container">
|
||||
<span class="current-time">Time :{{ currentTime }}</span>
|
||||
<span class="current-date">{{ currentDate }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6" *ngFor="let item of deviceCategory?.usesd">
|
||||
<div class="col-6" *ngFor="let item of deviceCategory?.used">
|
||||
<div
|
||||
class="card overflow-hidden"
|
||||
style="background-color: #000000 !important"
|
||||
class="card"
|
||||
style="
|
||||
background-color: transparent !important;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
"
|
||||
>
|
||||
<div class="card-content">
|
||||
<div class="card-body clearfix">
|
||||
<div class="media align-items-stretch mb-2">
|
||||
<div class="align-self-center">
|
||||
<i
|
||||
class="{{item.icon}} background-round info font-large-1 mr-2"
|
||||
style="color: #bff264 !important"
|
||||
class="{{
|
||||
item.icon
|
||||
}} background-round info font-large-1 mr-2"
|
||||
style="color: #ffffff !important"
|
||||
></i>
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<p style="color: #ffffff !important">
|
||||
<p style="color: #242222 !important">
|
||||
{{ item.category_device }}
|
||||
<span
|
||||
class="float-right text-bold-600"
|
||||
style="color: #ffffff"
|
||||
style="color: #242222"
|
||||
>{{ item.value.toFixed(1) }}%</span
|
||||
>
|
||||
</p>
|
||||
@@ -214,13 +293,13 @@
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
style="
|
||||
background-color: #c3f164 !important;
|
||||
color: #000000 !important;
|
||||
background-color: #37a647 !important;
|
||||
color: #ffffff !important;
|
||||
border-radius: 10px;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-weight: 700;
|
||||
"
|
||||
(click)="seeMore(paramsId)"
|
||||
(click)="seeMore(buildingId, floorId, roomId)"
|
||||
>
|
||||
See More
|
||||
</button>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { Component, ElementRef, ViewChild } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { ChartOptions, ChartType, ChartDataset } from "chart.js";
|
||||
import { EnergyMonitoringService } from "../../service/energy-monitoring.service";
|
||||
import { CurrencyPipe } from "@angular/common";
|
||||
import { LoginService } from "../../service/login.service";
|
||||
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { ModalExportComponent } from "../modal-export/modal-export.component";
|
||||
import { CostManagementService } from "../../service/cost-management.service";
|
||||
import { BuildingService } from "../../service/monitoring-api.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-detail",
|
||||
@@ -15,111 +18,45 @@ export class DetailComponent {
|
||||
data: any;
|
||||
mode: string;
|
||||
breadcrumb: any;
|
||||
donutChart1: any;
|
||||
donutChart2: any;
|
||||
|
||||
dataChart = {
|
||||
donut: {
|
||||
series: [20, 20, 20, 20, 20],
|
||||
},
|
||||
};
|
||||
|
||||
dataChart2 = {
|
||||
donut: {
|
||||
series: [50, 50],
|
||||
},
|
||||
};
|
||||
// temperature
|
||||
days = [
|
||||
{ name: "Sun", isToday: false },
|
||||
{ name: "Mon", isToday: false },
|
||||
{ name: "Tue", isToday: false },
|
||||
{ name: "Wed", isToday: false },
|
||||
{ name: "Thu", isToday: false },
|
||||
{ name: "Fri", isToday: false },
|
||||
{ name: "Sat", isToday: false },
|
||||
];
|
||||
roomTemperature: number = 0;
|
||||
roomHumidity: number = 0;
|
||||
valueAirQuality: number = 0;
|
||||
currentDate: string;
|
||||
currentTime: string;
|
||||
chartOption: any;
|
||||
chartOptionBar: any;
|
||||
|
||||
// chart bar
|
||||
public barChartOptions: ChartOptions = {
|
||||
responsive: true,
|
||||
animation: {
|
||||
duration: 0
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
stacked: true,
|
||||
},
|
||||
y: {
|
||||
stacked: true,
|
||||
beginAtZero: true
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
public barChartLabels: string[] = [];
|
||||
public barChartType: ChartType = "bar";
|
||||
public barChartLegend = true;
|
||||
public barChartData: ChartDataset[] = [
|
||||
{
|
||||
data: [],
|
||||
label: "KWH Consumption",
|
||||
backgroundColor: "#C3F164",
|
||||
borderColor: "#C3F164",
|
||||
pointBackgroundColor: "#C3F164",
|
||||
pointBorderColor: "#C3F164",
|
||||
pointHoverBackgroundColor: "#ffffff",
|
||||
pointHoverBorderColor: "#C3F164",
|
||||
barPercentage: 0.5,
|
||||
categoryPercentage: 0.5,
|
||||
},
|
||||
// {
|
||||
// data: [],
|
||||
// label: "Water Consumption",
|
||||
// backgroundColor: "#64CFF1",
|
||||
// borderColor: "#64CFF1",
|
||||
// pointBackgroundColor: "#64CFF1",
|
||||
// pointBorderColor: "#64CFF1",
|
||||
// pointHoverBackgroundColor: "#ffffff",
|
||||
// pointHoverBorderColor: "#64CFF1",
|
||||
// barPercentage: 0.5,
|
||||
// categoryPercentage: 0.5,
|
||||
// },
|
||||
{
|
||||
type: "line",
|
||||
data: [],
|
||||
label: "Weekly Kwh Average",
|
||||
backgroundColor: "rgba(0,255,255,0)",
|
||||
borderColor: "#ffffff",
|
||||
fill: false,
|
||||
pointBorderColor: "#ffffff",
|
||||
pointBackgroundColor: "#FFF",
|
||||
pointBorderWidth: 2,
|
||||
pointHoverBorderWidth: 2,
|
||||
pointRadius: 4,
|
||||
tension: 0.3,
|
||||
spanGaps: true
|
||||
},
|
||||
// {
|
||||
// type: "line",
|
||||
// data: [],
|
||||
// label: "Weekly Water Average",
|
||||
// backgroundColor: "rgba(0,255,255,0)",
|
||||
// borderColor: "#ffffff",
|
||||
// fill: false,
|
||||
// pointBorderColor: "#ffffff",
|
||||
// pointBackgroundColor: "#FFF",
|
||||
// pointBorderWidth: 2,
|
||||
// pointHoverBorderWidth: 2,
|
||||
// pointRadius: 4,
|
||||
// tension: 0.3,
|
||||
// spanGaps: true
|
||||
// },
|
||||
];
|
||||
public barChartData: number[] = [];
|
||||
public barChartData2: number[] = [];
|
||||
//..........................
|
||||
|
||||
// integrasi
|
||||
electric: any;
|
||||
water: any;
|
||||
device: any;
|
||||
room: any;
|
||||
topCard: any;
|
||||
summaryCost: any;
|
||||
airQuality: any;
|
||||
temperature: any;
|
||||
deviceCategory: any;
|
||||
chartKwhWater: any;
|
||||
paramsId: any;
|
||||
buildingId: any;
|
||||
floorId: any;
|
||||
roomId: any;
|
||||
buildingName: any;
|
||||
floorName: any;
|
||||
roomName: any;
|
||||
//......
|
||||
|
||||
constructor(
|
||||
@@ -127,7 +64,10 @@ export class DetailComponent {
|
||||
private energyMonitoringService: EnergyMonitoringService,
|
||||
private currencyPipe: CurrencyPipe,
|
||||
private router: Router,
|
||||
private authService: LoginService
|
||||
private authService: LoginService,
|
||||
private modalService: NgbModal,
|
||||
private costService: CostManagementService,
|
||||
private buildingService: BuildingService
|
||||
) {}
|
||||
|
||||
get formattedSummaryCost(): string {
|
||||
@@ -140,195 +80,396 @@ export class DetailComponent {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.route.data.subscribe((data) => {
|
||||
this.mode = data.mode;
|
||||
});
|
||||
this.breadcrumbLink();
|
||||
this.route.params.subscribe((params) => {
|
||||
const buildingId = params["id"];
|
||||
this.paramsId = params["id"];
|
||||
if (buildingId) {
|
||||
this.dataEnergyMonitoringTopCard(buildingId);
|
||||
this.dataEnergyMonitoringSummary(buildingId);
|
||||
this.dataEnergyMonitoringSAir(buildingId);
|
||||
this.dataEnergyMonitoringSTemperature(buildingId);
|
||||
this.dataEnergyDeviceCategory(buildingId);
|
||||
this.dataEnergyChartKwhWater(buildingId);
|
||||
this.buildingId = params["buildingId"] ? params["buildingId"] : 0;
|
||||
this.floorId = params["floorId"] ? params["floorId"] : 0;
|
||||
this.roomId = params["roomId"] ? params["roomId"] : 0;
|
||||
this.dataBuilding(this.buildingId);
|
||||
if (
|
||||
this.buildingId !== undefined &&
|
||||
this.floorId === undefined &&
|
||||
this.roomId === undefined
|
||||
) {
|
||||
this.dataEnergyMonitoringTopCard(this.buildingId, 0, 0);
|
||||
this.dataEnergyMonitoringSummary(this.buildingId, 0, 0);
|
||||
this.dataEnergyDeviceCategory(this.buildingId, 0, 0);
|
||||
this.dataEnergyChartKwhWater(this.buildingId, 0, 0);
|
||||
} else if (
|
||||
this.buildingId !== undefined &&
|
||||
this.floorId !== undefined &&
|
||||
this.roomId === undefined
|
||||
) {
|
||||
this.dataEnergyMonitoringTopCard(this.buildingId, this.floorId, 0);
|
||||
this.dataEnergyMonitoringSummary(this.buildingId, this.floorId, 0);
|
||||
this.dataEnergyDeviceCategory(this.buildingId, this.floorId, 0);
|
||||
this.dataEnergyChartKwhWater(this.buildingId, this.floorId, 0);
|
||||
|
||||
} else if (
|
||||
this.buildingId !== undefined &&
|
||||
this.floorId !== undefined &&
|
||||
this.roomId !== undefined
|
||||
) {
|
||||
this.dataEnergyMonitoringTopCard(
|
||||
this.buildingId,
|
||||
this.floorId,
|
||||
this.roomId
|
||||
);
|
||||
this.dataEnergyMonitoringSummary(
|
||||
this.buildingId,
|
||||
this.floorId,
|
||||
this.roomId
|
||||
);
|
||||
this.dataEnergyDeviceCategory(
|
||||
this.buildingId,
|
||||
this.floorId,
|
||||
this.roomId
|
||||
);
|
||||
this.dataEnergyChartKwhWater(
|
||||
this.buildingId,
|
||||
this.floorId,
|
||||
this.roomId
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
this.donutChart1 = {
|
||||
type: "Pie",
|
||||
data: this.dataChart.donut,
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: "300px",
|
||||
donut: true,
|
||||
donutWidth: 70,
|
||||
startAngle: 270,
|
||||
total: 200,
|
||||
showLabel: true,
|
||||
},
|
||||
};
|
||||
this.dataDeviceIr();
|
||||
this.getAirQualityData();
|
||||
});
|
||||
}
|
||||
|
||||
breadcrumbLink() {
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Energy Monitoring",
|
||||
linkBack: "/monitoring",
|
||||
isLinkBack: true,
|
||||
links: [
|
||||
if (this.mode === "building") {
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Energy Monitoring",
|
||||
linkBack: "/monitoring",
|
||||
isLinkBack: true,
|
||||
links: [
|
||||
{
|
||||
name: this.buildingName,
|
||||
isLink: false,
|
||||
link: "",
|
||||
},
|
||||
],
|
||||
};
|
||||
} else if (this.mode === "floor") {
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Energy Monitoring",
|
||||
linkBack: "/monitoring",
|
||||
isLinkBack: true,
|
||||
links: [
|
||||
{
|
||||
name: this.buildingName,
|
||||
isLink: false,
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
name: this.floorName,
|
||||
isLink: false,
|
||||
link: "",
|
||||
},
|
||||
],
|
||||
};
|
||||
} else if (this.mode === "room") {
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Energy Monitoring",
|
||||
linkBack: "/monitoring",
|
||||
isLinkBack: true,
|
||||
links: [
|
||||
{
|
||||
name: this.buildingName,
|
||||
isLink: false,
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
name: this.floorName,
|
||||
isLink: false,
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
name: this.roomName,
|
||||
isLink: false,
|
||||
link: "",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getAirQualityData() {
|
||||
this.valueAirQuality = Math.floor(Math.random() * 501);
|
||||
this.chartOption = {
|
||||
series: [
|
||||
{
|
||||
name: "Dashboard",
|
||||
isLink: false,
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
name: "Energy Monitoring",
|
||||
isLink: false,
|
||||
link: "",
|
||||
type: "gauge",
|
||||
startAngle: 180,
|
||||
endAngle: 0,
|
||||
center: ["50%", "75%"],
|
||||
radius: "130%", // Adjust the radius to make the chart smaller
|
||||
min: 0,
|
||||
max: 500,
|
||||
splitNumber: 5,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 20,
|
||||
color: [
|
||||
[1 / 6, "#6BD67C"], // 0 - 50: Green
|
||||
[2 / 6, "#A2D856"], // 51 - 100: Light Green
|
||||
[3 / 6, "#FFE45E"], // 101 - 150: Yellow
|
||||
[4 / 6, "#FFA644"], // 151 - 200: Orange
|
||||
[5 / 6, "#FF6E76"], // 201 - 300: Light Red
|
||||
[6 / 6, "#E768A7"], // 301 - 500: Purple
|
||||
],
|
||||
},
|
||||
},
|
||||
pointer: {
|
||||
icon: "path://M12.8,0.7l12,40.1H0.7L12.8,0.7z",
|
||||
length: "12%",
|
||||
width: 15,
|
||||
offsetCenter: [0, "-50%"],
|
||||
itemStyle: {
|
||||
color: "auto",
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
length: 10,
|
||||
lineStyle: {
|
||||
color: "auto",
|
||||
width: 2,
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
length: 15,
|
||||
lineStyle: {
|
||||
color: "auto",
|
||||
width: 5,
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
color: "#464646",
|
||||
fontSize: 16, // Adjust font size
|
||||
distance: -40, // Adjust distance
|
||||
rotate: "tangential",
|
||||
formatter: function (value: number) {
|
||||
// return Math.round(value) === 100 ? "100" : Math.round(value) + "";
|
||||
return value.toString();
|
||||
},
|
||||
},
|
||||
title: {
|
||||
offsetCenter: [0, " 15%"],
|
||||
fontSize: 18, // Adjust font size
|
||||
},
|
||||
detail: {
|
||||
fontSize: 24, // Adjust font size
|
||||
offsetCenter: [0, "-25%"], // Adjust offset
|
||||
valueAnimation: true,
|
||||
formatter: function (value: number) {
|
||||
return Math.round(value) + "";
|
||||
},
|
||||
color: "#242222",
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: this.valueAirQuality,
|
||||
name: this.getGradeName(this.valueAirQuality),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
getGradeName(value: number): string {
|
||||
if (value <= 50) {
|
||||
return "Good";
|
||||
} else if (value <= 100) {
|
||||
return "Moderate";
|
||||
} else if (value <= 150) {
|
||||
return "Unhealthy for Sensitive Groups";
|
||||
} else if (value <= 200) {
|
||||
return "Unhealthy";
|
||||
} else if (value <= 300) {
|
||||
return "Very Unhealthy";
|
||||
} else {
|
||||
return "Hazardous";
|
||||
}
|
||||
}
|
||||
|
||||
dataDeviceIr() {
|
||||
const today = new Date().getDay();
|
||||
this.days[today].isToday = true;
|
||||
const now = new Date();
|
||||
this.currentDate = now.toLocaleDateString();
|
||||
this.currentTime = now.toLocaleTimeString();
|
||||
this.energyMonitoringService.getDeviceStatus(452).subscribe((res) => {
|
||||
this.roomTemperature = res.result[0].value;
|
||||
this.roomHumidity = res.result[1].value;
|
||||
});
|
||||
}
|
||||
//integrasi
|
||||
dataEnergyMonitoringTopCard(buildingId) {
|
||||
dataEnergyMonitoringTopCard(buildingId, floorId, roomId) {
|
||||
this.energyMonitoringService
|
||||
.getDashboardTopCard(buildingId)
|
||||
.getDashboardTopCard(buildingId, floorId, roomId)
|
||||
.subscribe((res) => {
|
||||
this.topCard = res.data;
|
||||
});
|
||||
}
|
||||
dataEnergyMonitoringSummary(buildingId) {
|
||||
|
||||
dataBuilding(buildingId) {
|
||||
this.costService.getBUildingById(buildingId).subscribe((res) => {
|
||||
this.buildingName = res.data.name
|
||||
this.breadcrumbLink();
|
||||
if (this.floorId) {
|
||||
this.dataFloor(this.floorId)
|
||||
}
|
||||
if (this.roomId) {
|
||||
this.dataRoom(this.roomId)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dataFloor(floorId) {
|
||||
this.buildingService.getHeaderDetailParam(floorId).subscribe((res) => {
|
||||
this.floorName = res.data.name;
|
||||
this.breadcrumbLink();
|
||||
});
|
||||
}
|
||||
|
||||
dataRoom(roomId) {
|
||||
this.buildingService.getRoom(roomId).subscribe((res) => {
|
||||
this.roomName = res.data.name;
|
||||
this.breadcrumbLink();
|
||||
});
|
||||
}
|
||||
|
||||
dataEnergyMonitoringSummary(buildingId, floorId, roomId) {
|
||||
this.energyMonitoringService
|
||||
.getDashboardSummary(buildingId)
|
||||
.getDashboardSummary(buildingId, floorId, roomId)
|
||||
.subscribe((res) => {
|
||||
this.summaryCost = res.data;
|
||||
});
|
||||
}
|
||||
dataEnergyMonitoringSAir(buildingId) {
|
||||
|
||||
dataEnergyDeviceCategory(buildingId, floorId, roomId) {
|
||||
this.energyMonitoringService
|
||||
.getDashboardAirQuality(buildingId)
|
||||
.subscribe((res) => {
|
||||
this.airQuality = res.data;
|
||||
});
|
||||
}
|
||||
dataEnergyMonitoringSTemperature(buildingId) {
|
||||
this.energyMonitoringService
|
||||
.getDashboardTemperature(buildingId)
|
||||
.subscribe((res) => {
|
||||
this.temperature = res.data;
|
||||
this.donutChart2 = {
|
||||
type: "Pie",
|
||||
data: this.dataChart2.donut,
|
||||
options: {
|
||||
chartPadding: 0,
|
||||
fullwidth: true,
|
||||
height: "150px",
|
||||
donut: true,
|
||||
showLabel: true,
|
||||
startAngle: 0,
|
||||
labelInterpolationFnc: (value) => {
|
||||
const total = this.temperature;
|
||||
return total + "°C";
|
||||
},
|
||||
},
|
||||
events: {
|
||||
draw: (data: any) => {
|
||||
if (data.type === "label") {
|
||||
if (data.index === 0) {
|
||||
data.element.attr({
|
||||
dx: data.element.root().width() / 2,
|
||||
dy: data.element.root().height() / 2,
|
||||
});
|
||||
} else {
|
||||
data.element.remove();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
dataEnergyDeviceCategory(buildingId) {
|
||||
this.energyMonitoringService
|
||||
.getDashboardDeviceCategory(buildingId)
|
||||
.getDashboardDeviceCategory(buildingId, floorId, roomId)
|
||||
.subscribe((res) => {
|
||||
this.deviceCategory = res.data[0];
|
||||
});
|
||||
}
|
||||
dataEnergyChartKwhWater(buildingId) {
|
||||
|
||||
dataEnergyChartKwhWater(buildingId, floorId, roomId) {
|
||||
this.energyMonitoringService
|
||||
.getDashboardChartKwhWater(buildingId)
|
||||
.getDashboardChartKwhWater(buildingId, floorId, roomId)
|
||||
.subscribe((res) => {
|
||||
this.chartKwhWater = res.data;
|
||||
this.barChartData[0].data = [];
|
||||
// this.barChartData[1].data = [];
|
||||
this.chartKwhWater.forEach((entry) => {
|
||||
this.barChartData[0].data.push(entry.kwh);
|
||||
// this.barChartData[1].data.push(entry.water);
|
||||
this.barChartData.push(entry.kwh.toFixed(1));
|
||||
this.barChartData2.push(entry.cost);
|
||||
this.barChartLabels.push(entry.day);
|
||||
});
|
||||
|
||||
const weeklyKwh = this.aggregateKwhWeekly(this.chartKwhWater);
|
||||
// const weeklyWater = this.aggregateWaterWeekly(this.chartKwhWater);
|
||||
|
||||
// Populate Appointment data at every multiple of 7
|
||||
let weekIndex = 0;
|
||||
for (let i = 0; i < this.barChartData[0].data.length; i++) {
|
||||
if (i % 7 === 6 && weekIndex < weeklyKwh.length) {
|
||||
this.barChartData[2].data[i] = weeklyKwh[weekIndex++];
|
||||
} else {
|
||||
this.barChartData[2].data[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
// let weekIndexWater = 0;
|
||||
// for (let i = 0; i < this.barChartData[0].data.length; i++) {
|
||||
// if (i % 7 === 6 && weekIndexWater < weeklyWater.length) {
|
||||
// this.barChartData[3].data[i] = weeklyWater[weekIndexWater++];
|
||||
// } else {
|
||||
// this.barChartData[3].data[i] = null;
|
||||
// }
|
||||
// }
|
||||
this.chartOptionBar = {
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow",
|
||||
},
|
||||
},
|
||||
legend: {},
|
||||
toolbox: {
|
||||
show: true,
|
||||
orient: "vertical",
|
||||
feature: {
|
||||
dataView: { show: true, readOnly: false },
|
||||
magicType: { show: true, type: ["line", "bar"] },
|
||||
restore: { show: true },
|
||||
saveAsImage: { show: true },
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
left: "3%",
|
||||
right: "4%",
|
||||
bottom: "3%",
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: "category",
|
||||
data: this.barChartLabels,
|
||||
},
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: "value",
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "KWH Consumption",
|
||||
type: "bar",
|
||||
color: "#242222",
|
||||
stack: "Ad",
|
||||
emphasis: {
|
||||
focus: "series",
|
||||
},
|
||||
data: this.barChartData,
|
||||
},
|
||||
{
|
||||
name: "Summary Cost",
|
||||
type: "bar",
|
||||
stack: "Ad",
|
||||
color: "#37a647",
|
||||
emphasis: {
|
||||
focus: "series",
|
||||
},
|
||||
data: this.barChartData2,
|
||||
},
|
||||
],
|
||||
};
|
||||
onClick: (params) => {
|
||||
this.onChartClick(params);
|
||||
};
|
||||
});
|
||||
}
|
||||
aggregateKwhWeekly(data: any[]): number[] {
|
||||
const weeks = [];
|
||||
let weekSum = 0;
|
||||
let dayCount = 0;
|
||||
|
||||
data.forEach((entry, index) => {
|
||||
weekSum += entry.kwh;
|
||||
dayCount++;
|
||||
if (dayCount === 7 || index === data.length - 1) {
|
||||
weeks.push(weekSum);
|
||||
weekSum = 0;
|
||||
dayCount = 0;
|
||||
}
|
||||
onChartClick(params) {
|
||||
console.log(params);
|
||||
const modalRef = this.modalService.open(ModalExportComponent, {
|
||||
size: "xl",
|
||||
centered: true,
|
||||
});
|
||||
modalRef.componentInstance.dataIndex = params.dataIndex;
|
||||
modalRef.componentInstance.buildingId = this.buildingId;
|
||||
modalRef.componentInstance.floorId = this.floorId;
|
||||
modalRef.componentInstance.roomId = this.roomId;
|
||||
modalRef.componentInstance.mode = this.mode;
|
||||
|
||||
return weeks;
|
||||
}
|
||||
aggregateWaterWeekly(data: any[]): number[] {
|
||||
const weeks = [];
|
||||
let weekSum = 0;
|
||||
let dayCount = 0;
|
||||
|
||||
data.forEach((entry, index) => {
|
||||
weekSum += entry.water;
|
||||
dayCount++;
|
||||
if (dayCount === 7 || index === data.length - 1) {
|
||||
weeks.push(weekSum);
|
||||
weekSum = 0;
|
||||
dayCount = 0;
|
||||
modalRef.result.then(
|
||||
(result) => {
|
||||
if (result) {
|
||||
console.log(result);
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
console.log(`Dismissed: ${reason}`);
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
return weeks;
|
||||
// Show popup with details
|
||||
// alert(`Day: ${params.name}\nKWH Consumption: ${params.value}`);
|
||||
}
|
||||
seeMore(paramsId){
|
||||
this.router.navigate(["/monitoring/control-device-see-more/", paramsId]);
|
||||
|
||||
seeMore(buildingId, floorId, roomId) {
|
||||
this.router.navigate([
|
||||
"/monitoring/control-device-see-more/",
|
||||
buildingId,
|
||||
floorId,
|
||||
roomId,
|
||||
this.mode,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,444 @@
|
||||
:host ::ng-deep .progress-bar {
|
||||
background-color: #bef264 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart2 .ct-series-a .ct-slice-donut {
|
||||
stroke: #8a8a8a;
|
||||
stroke-width: 20px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart2 .ct-series-b .ct-slice-donut {
|
||||
stroke: #bef264;
|
||||
stroke-width: 20px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart2 .ct-label {
|
||||
fill: #ffffff;
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-point {
|
||||
stroke: #bef264;
|
||||
}
|
||||
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-line {
|
||||
stroke: #bef264;
|
||||
}
|
||||
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-area {
|
||||
fill: #bef264;
|
||||
fill-opacity: 1;
|
||||
}
|
||||
|
||||
:host ::ng-deep .sp-line-total-cost .ct-point {
|
||||
stroke-width: 0px;
|
||||
}
|
||||
|
||||
.ct-chart-bar .ct-series .ct-bar {
|
||||
stroke-width: 20px !important; /* Atur lebar bar sesuai kebutuhan */
|
||||
}
|
||||
|
||||
.ct-chart-bar .ct-label.ct-horizontal {
|
||||
margin-left: -10px !important; /* Mengatur margin label horizontal */
|
||||
margin-right: -10px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart3 .ct-series-a .ct-bar {
|
||||
stroke: #bef264;
|
||||
fill: none;
|
||||
stroke-width: 30px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart3 .ct-series-b .ct-bar {
|
||||
stroke: #bef264;
|
||||
fill: none;
|
||||
stroke-width: 30px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart3 .ct-label {
|
||||
fill: #ffffff;
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-label.ct-horizontal {
|
||||
font-size: 12px; /* Adjust font size */
|
||||
transform: rotate(-45deg); /* Rotate labels if needed for better fit */
|
||||
text-anchor: end;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-chart-bar .ct-labels .ct-label.ct-horizontal {
|
||||
margin-right: 20px; /* Adjust margin for labels */
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
font-size: 18px;
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Hide the default calendar icon */
|
||||
input[type="month"]::-webkit-calendar-picker-indicator {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/* table */
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-header
|
||||
.datatable-header-cell
|
||||
.datatable-header-cell-label {
|
||||
font-family: inherit;
|
||||
font-size: medium;
|
||||
font-weight: bold;
|
||||
color: #6b6f82;
|
||||
}
|
||||
:host ::ng-deep .ngx-datatable .datatable-row-center,
|
||||
.ngx-datatable .datatable-row-group,
|
||||
.ngx-datatable .datatable-row-right {
|
||||
position: relative;
|
||||
height: 50px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-right:before {
|
||||
font-family: "icofont";
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-skip:before {
|
||||
font-family: "icofont";
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-left:before {
|
||||
font-family: "icofont";
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-left:before {
|
||||
content: "\2039";
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-prev:before {
|
||||
content: "\00AB";
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-right:before {
|
||||
content: "\203A";
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-skip:before {
|
||||
content: "\00BB";
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-left,
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-right,
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-prev {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #d4d2e7;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-right,
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-right {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #d4d2e7;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-skip {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #d4d2e7;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-prev {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #d4d2e7;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
ul
|
||||
li:not(.disabled).active
|
||||
a,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11]
|
||||
.datatable-footer[_ngcontent-c11]
|
||||
.datatable-pager[_ngcontent-c11]
|
||||
ul[_ngcontent-c11]
|
||||
li[_ngcontent-c11]:not(.disabled):hover
|
||||
a[_ngcontent-c11] {
|
||||
background-color: #d4d2e7;
|
||||
font-weight: bold;
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager a {
|
||||
height: 32px;
|
||||
min-width: 34px;
|
||||
line-height: 22px;
|
||||
padding: 0;
|
||||
border-radius: 3px;
|
||||
margin: 0 3px;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
padding-top: 3px;
|
||||
text-decoration: none;
|
||||
vertical-align: bottom;
|
||||
color: #7c8091;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-left,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11]
|
||||
.datatable-footer[_ngcontent-c11]
|
||||
.datatable-pager[_ngcontent-c11]
|
||||
.datatable-icon-right[_ngcontent-c11],
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11]
|
||||
.datatable-footer[_ngcontent-c11]
|
||||
.datatable-pager[_ngcontent-c11]
|
||||
.datatable-icon-prev[_ngcontent-c11] {
|
||||
font-size: 14px;
|
||||
line-height: 9px;
|
||||
padding: 0px 08px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-left,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11]
|
||||
.datatable-footer[_ngcontent-c11]
|
||||
.datatable-pager[_ngcontent-c11]
|
||||
.datatable-icon-right[_ngcontent-c11],
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11]
|
||||
.datatable-footer[_ngcontent-c11]
|
||||
.datatable-pager[_ngcontent-c11]
|
||||
.datatable-icon-prev[_ngcontent-c11] {
|
||||
font-size: 0px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-right,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11]
|
||||
.datatable-footer[_ngcontent-c11]
|
||||
.datatable-pager[_ngcontent-c11]
|
||||
.datatable-icon-right[_ngcontent-c11],
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11]
|
||||
.datatable-footer[_ngcontent-c11]
|
||||
.datatable-pager[_ngcontent-c11]
|
||||
.datatable-icon-prev[_ngcontent-c11] {
|
||||
font-size: 0px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-skip,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11]
|
||||
.datatable-footer[_ngcontent-c11]
|
||||
.datatable-pager[_ngcontent-c11]
|
||||
.datatable-icon-right[_ngcontent-c11],
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11]
|
||||
.datatable-footer[_ngcontent-c11]
|
||||
.datatable-pager[_ngcontent-c11]
|
||||
.datatable-icon-prev[_ngcontent-c11] {
|
||||
font-size: 0px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
.datatable-icon-prev,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11]
|
||||
.datatable-footer[_ngcontent-c11]
|
||||
.datatable-pager[_ngcontent-c11]
|
||||
.datatable-icon-right[_ngcontent-c11],
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11]
|
||||
.datatable-footer[_ngcontent-c11]
|
||||
.datatable-pager[_ngcontent-c11]
|
||||
.datatable-icon-prev[_ngcontent-c11] {
|
||||
font-size: 0px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #545454;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
ul
|
||||
li:not(.disabled).active
|
||||
a,
|
||||
.ngx-datatable.bootstrap
|
||||
.datatable-footer
|
||||
.datatable-pager
|
||||
ul
|
||||
li:not(.disabled):hover
|
||||
a {
|
||||
background-color: #252525;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
background: #DDE1E6;
|
||||
color: #242222;
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable .datatable-footer .datatable-pager {
|
||||
flex: 0 0 0%;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable .datatable-footer .datatable-pager .pager {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
:host
|
||||
::ng-deep
|
||||
.ngx-datatable
|
||||
.datatable-footer
|
||||
.selected-count
|
||||
.datatable-pager {
|
||||
flex: 0 0 0%;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable {
|
||||
display: -webkit-box;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #242222 !important;
|
||||
background-color: #FBFBFB !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 2px 4px rgba(36, 34, 34, 0.2) !important; /* Bayangan lebih tipis */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input {
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row {
|
||||
background-color: #FBFBFB; /* Black color for table rows */
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body-row:hover {
|
||||
background-color: #DDE1E6; /* Darker black for hover effect */
|
||||
}
|
||||
|
||||
.text-custom-label{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.text-custom-data{
|
||||
color: #242222 !important;
|
||||
font-family: "Open Sans", sans-serif !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.style-custom-label{
|
||||
color: #242222 !important;
|
||||
}
|
||||
|
||||
::ng-deep .modal-backdrop.show {
|
||||
z-index: auto !important;
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
<div class="modal-body" style="background-color: #fbfbfb !important">
|
||||
<h4 style="color: #242222; margin-bottom: 20px !important">
|
||||
<div *ngIf="buildingOnly">
|
||||
<strong>{{ data_cost[0].BuildingName }}</strong>
|
||||
</div>
|
||||
<div *ngIf="floorOnly">
|
||||
{{data_cost[0].BuildingName}} > <strong>{{ data_cost[0].floorName }}</strong>
|
||||
</div>
|
||||
<div *ngIf="roomOnly">
|
||||
{{data_cost[0].BuildingName}} > {{data_cost[0].floorName}} > <strong>{{ data_cost[0].roomName }}</strong>
|
||||
</div>
|
||||
</h4>
|
||||
<!-- <p style="color: #242222">Room : dfd</p>
|
||||
<p style="color: #242222">Category : gdfg</p> -->
|
||||
|
||||
<div class="card-dashboard">
|
||||
<ngx-datatable
|
||||
class="bootstrap table-bordered"
|
||||
[limit]="10"
|
||||
[rows]="data_cost"
|
||||
[columnMode]="'force'"
|
||||
[headerHeight]="50"
|
||||
[footerHeight]="50"
|
||||
[rowHeight]="50"
|
||||
fxFlex="auto"
|
||||
[scrollbarH]="true"
|
||||
>
|
||||
<ngx-datatable-column name="#" [flexGrow]="0.5" [minWidth]="30">
|
||||
<ng-template ngx-datatable-cell-template let-rowIndex="rowIndex">
|
||||
<p style="color: #242222 !important">
|
||||
{{ rowIndex + 1 }}
|
||||
</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<!-- <ngx-datatable-column name="periode" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #242222 !important">Tanggal</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #242222 !important">
|
||||
{{ value | date : "dd/MM/yyyy" }}
|
||||
</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column> -->
|
||||
<ngx-datatable-column name="floorName" [flexGrow]="1" [minWidth]="90" *ngIf="buildingOnly">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #242222 !important">Floor</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #242222 !important">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="roomName" [flexGrow]="1" [minWidth]="90" *ngIf="buildingOnly || floorOnly">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #242222 !important">Room</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #242222 !important">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="deviceName" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #242222 !important">Device</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #242222 !important">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="duration" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #242222 !important">Duration</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #242222 !important">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<!-- <ngx-datatable-column name="priceKwh" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #242222 !important">Price Kwh</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #242222 !important">{{ value }}</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column> -->
|
||||
|
||||
<ngx-datatable-column name="priceKwh" [flexGrow]="1" [minWidth]="90">
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #242222 !important">Price Kwh</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #242222 !important">
|
||||
{{
|
||||
value.toLocaleString("id-ID", {
|
||||
style: "currency",
|
||||
currency: "IDR"
|
||||
})
|
||||
}}
|
||||
</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column
|
||||
name="estimationCost"
|
||||
[flexGrow]="1"
|
||||
[minWidth]="90"
|
||||
>
|
||||
<ng-template ngx-datatable-header-template>
|
||||
<span style="color: #242222 !important">Estimation Cost</span>
|
||||
</ng-template>
|
||||
<ng-template let-value="value" ngx-datatable-cell-template>
|
||||
<p style="color: #242222 !important">
|
||||
{{
|
||||
value.toLocaleString("id-ID", {
|
||||
style: "currency",
|
||||
currency: "IDR"
|
||||
})
|
||||
}}
|
||||
</p>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="modal-footer "
|
||||
style="background-color: #fbfbfb !important; border-style: none !important"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
style="
|
||||
color: #242222;
|
||||
width: 10%;
|
||||
background-color: #fbfbfb !important;
|
||||
border-color: #242222 !important;
|
||||
border-radius: 10px;
|
||||
"
|
||||
(click)="activeModal.dismiss('Cross click')"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
style="
|
||||
color: #ffffff !important;
|
||||
width: 10%;
|
||||
background-color: #37a647 !important;
|
||||
border-color: #37a647 !important;
|
||||
border-radius: 10px;
|
||||
"
|
||||
[disabled]="spinnerExportActive"
|
||||
(click)="export()"
|
||||
>
|
||||
<i class="la la-spinner spinner" *ngIf="spinnerExportActive"></i>
|
||||
Export
|
||||
</button>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ModalExportComponent } from './modal-export.component';
|
||||
|
||||
describe('ModalExportComponent', () => {
|
||||
let component: ModalExportComponent;
|
||||
let fixture: ComponentFixture<ModalExportComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ModalExportComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ModalExportComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,146 @@
|
||||
import { Component, Input } from "@angular/core";
|
||||
import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { TableexcelService } from "src/app/_services/tableexcel.service";
|
||||
import { LoginService } from "../../service/login.service";
|
||||
import { BuildingService } from "../../service/monitoring-api.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-modal-export",
|
||||
templateUrl: "./modal-export.component.html",
|
||||
styleUrls: ["./modal-export.component.css"],
|
||||
})
|
||||
export class ModalExportComponent {
|
||||
@Input() buildingId: any = 0;
|
||||
@Input() dataIndex: any = 0;
|
||||
@Input() floorId: any = 0;
|
||||
@Input() roomId: any = 0;
|
||||
@Input() mode: any = "";
|
||||
|
||||
buildingOnly = false;
|
||||
floorOnly = false;
|
||||
roomOnly = false;
|
||||
|
||||
data: any;
|
||||
filteredRows: any[];
|
||||
data_device: any[];
|
||||
kwhTerm: string = "";
|
||||
costTerm: string = "";
|
||||
data_cost: any;
|
||||
dataExport: any;
|
||||
formattedEndDate: any;
|
||||
spinnerExportActive = false;
|
||||
constructor(
|
||||
public activeModal: NgbActiveModal,
|
||||
private tableexcelService: TableexcelService,
|
||||
private authService: LoginService,
|
||||
private monitoringService: BuildingService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.fetchData();
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
if (this.buildingId !== 0 && this.floorId === 0 && this.roomId === 0) {
|
||||
this.buildingOnly = true;
|
||||
this.floorOnly = false;
|
||||
this.roomOnly = false;
|
||||
} else if (
|
||||
this.buildingId !== 0 &&
|
||||
this.floorId !== 0 &&
|
||||
this.roomId === 0
|
||||
) {
|
||||
this.buildingOnly = false;
|
||||
this.floorOnly = true;
|
||||
this.roomOnly = false;
|
||||
} else if (
|
||||
this.buildingId !== 0 &&
|
||||
this.floorId !== 0 &&
|
||||
this.roomId !== 0
|
||||
) {
|
||||
this.buildingOnly = false;
|
||||
this.floorOnly = false;
|
||||
this.roomOnly = true;
|
||||
}
|
||||
}
|
||||
|
||||
fetchData() {
|
||||
this.monitoringService
|
||||
.getDetailChart(
|
||||
this.dataIndex + 1,
|
||||
this.buildingId,
|
||||
this.floorId,
|
||||
this.roomId
|
||||
)
|
||||
.subscribe((response) => {
|
||||
this.dataExport = response.data;
|
||||
this.data_cost = response.data.map((item) => ({
|
||||
BuildingName: item.building_name,
|
||||
floorName: item.floor_name,
|
||||
roomName: item.room_name,
|
||||
deviceName: item.device_name,
|
||||
duration: item.duration,
|
||||
priceKwh: item.price_kwh,
|
||||
estimationCost: item.estimation_cost,
|
||||
// periode: this.convertToUTC7(item.periode)
|
||||
}));
|
||||
console.log(this.data_cost);
|
||||
});
|
||||
}
|
||||
|
||||
convertToUTC7(dateString: string): string {
|
||||
const date = new Date(dateString);
|
||||
const utc7Offset = 7 * 60; // UTC+7 in minutes
|
||||
const localOffset = date.getTimezoneOffset();
|
||||
const totalOffset = utc7Offset - localOffset;
|
||||
const utc7Date = new Date(date.getTime() + totalOffset * 60 * 1000);
|
||||
return utc7Date.toISOString();
|
||||
}
|
||||
|
||||
export() {
|
||||
this.spinnerExportActive = true;
|
||||
setTimeout(() => {
|
||||
let columnsToExport = [];
|
||||
let exportText = "";
|
||||
if (this.mode === "building") {
|
||||
columnsToExport = [
|
||||
"floorName",
|
||||
"roomName",
|
||||
"deviceName",
|
||||
"duration",
|
||||
"priceKwh",
|
||||
"estimationCost",
|
||||
];
|
||||
exportText = "export_detail_monitoring_building";
|
||||
} else if (this.mode === "floor") {
|
||||
columnsToExport = [
|
||||
"roomName",
|
||||
"deviceName",
|
||||
"duration",
|
||||
"priceKwh",
|
||||
"estimationCost",
|
||||
];
|
||||
exportText = "export_detail_monitoring_floor";
|
||||
} else if (this.mode === "room") {
|
||||
columnsToExport = [
|
||||
"deviceName",
|
||||
"duration",
|
||||
"priceKwh",
|
||||
"estimationCost",
|
||||
];
|
||||
exportText = "export_detail_monitoring_room";
|
||||
}
|
||||
|
||||
this.tableexcelService.exportAsExcelFileMonitoringDetail(
|
||||
this.data_cost,
|
||||
exportText,
|
||||
columnsToExport,
|
||||
this.mode
|
||||
);
|
||||
this.spinnerExportActive = false;
|
||||
this.activeModal.close("Export completed");
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,8 @@ import { NgSelectModule } from '@ng-select/ng-select';
|
||||
import { ControlDeviceSeemoreComponent } from './control-device-seemore/control-device-seemore.component';
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { HttpErrorInterceptorService } from 'src/app/interceptors/http-error-interceptor.service';
|
||||
import { ClipboardModule } from 'ngx-clipboard';
|
||||
import { ModalExportComponent } from './modal-export/modal-export.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -39,7 +41,8 @@ import { HttpErrorInterceptorService } from 'src/app/interceptors/http-error-int
|
||||
FilterTopUsePipe,
|
||||
SurveillanceComponent,
|
||||
WaterComponent,
|
||||
ControlDeviceSeemoreComponent
|
||||
ControlDeviceSeemoreComponent,
|
||||
ModalExportComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
@@ -59,6 +62,7 @@ import { HttpErrorInterceptorService } from 'src/app/interceptors/http-error-int
|
||||
NgxMasonryModule,
|
||||
UiSwitchModule,
|
||||
NgSelectModule,
|
||||
ClipboardModule,
|
||||
NgxEchartsModule.forRoot({
|
||||
echarts: () => import('echarts')
|
||||
}),
|
||||
@@ -79,7 +83,7 @@ import { HttpErrorInterceptorService } from 'src/app/interceptors/http-error-int
|
||||
component: WaterComponent,
|
||||
},
|
||||
{
|
||||
path: 'control-device-see-more/:id',
|
||||
path: 'control-device-see-more/:buildingId/:floorId/:roomId/:mode',
|
||||
component: ControlDeviceSeemoreComponent,
|
||||
},
|
||||
{
|
||||
@@ -88,10 +92,21 @@ import { HttpErrorInterceptorService } from 'src/app/interceptors/http-error-int
|
||||
data: { mode: 'room' }
|
||||
},
|
||||
{
|
||||
path: 'view-new-building/:id',
|
||||
path: 'view-detail-building/:buildingId',
|
||||
component: DetailComponent,
|
||||
data: { mode: 'build' }
|
||||
data: { mode: 'building' }
|
||||
},
|
||||
{
|
||||
path: 'view-detail-floor/:buildingId/:floorId',
|
||||
component: DetailComponent,
|
||||
data: { mode: 'floor' }
|
||||
},
|
||||
{
|
||||
path: 'view-detail-room/:buildingId/:floorId/:roomId',
|
||||
component: DetailComponent,
|
||||
data: { mode: 'room' }
|
||||
},
|
||||
|
||||
{
|
||||
path: 'view-new-room/:id',
|
||||
component: DetailComponent,
|
||||
|
||||
@@ -6,5 +6,10 @@
|
||||
background: rgba(255, 249, 249, 0.5) !important;
|
||||
}
|
||||
:host ::ng-deep .progress-bar {
|
||||
background-color: #bef264 !important;
|
||||
background-color: #2f5137 !important;
|
||||
}
|
||||
|
||||
.room-custom{
|
||||
font-family: Montserrat, sans-serif;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="app-content content" style="background-color: #000000 !important">
|
||||
<div class="app-content content">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
@@ -24,20 +24,20 @@
|
||||
class="col-xl-3 col-lg-6 col-12"
|
||||
*ngFor="let data of filteredRows"
|
||||
>
|
||||
<div class="card pull-up" style="background-color: #252525 !important">
|
||||
<div class="card pull-up" style="background-color: #DDE1E6 !important">
|
||||
<div class="card-content">
|
||||
<div class="card-header mb-2" style="background-color: #252525 !important">
|
||||
<div class="card-header mb-2" style="background-color: #DDE1E6 !important">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h5
|
||||
class="text-muted mb-1"
|
||||
style="font-family: Montserrat, sans-serif; color: #ffffff !important;"
|
||||
class="text-muted mb-1 room-custom"
|
||||
style="color: #242222 !important;"
|
||||
>
|
||||
Room
|
||||
</h5>
|
||||
<h4
|
||||
class="text-muted mb-0"
|
||||
style="font-family: Montserrat, sans-serif; color: #ffffff !important;"
|
||||
style="font-family: Montserrat, sans-serif; color: #242222 !important;"
|
||||
>
|
||||
{{ data.name }}
|
||||
</h4>
|
||||
@@ -49,13 +49,13 @@
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<!-- <h3 class="info">{{ data.value }} kWh</h3> -->
|
||||
<h3 style="color: #ffffff;">{{data.totalKwh}} kWh</h3>
|
||||
<h6 style="color: #ffffff;">Consumption</h6>
|
||||
<h3 style="color: #242222;">{{data.totalKwh}} kWh</h3>
|
||||
<h6 style="color: #242222;">Consumption</h6>
|
||||
</div>
|
||||
<div>
|
||||
<i
|
||||
class="feather ft-server info font-large-2 float-right"
|
||||
style="color: #bef264 !important;"
|
||||
style="color: #2f5137 !important;"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,8 @@ export class RoomComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
this.route.data.subscribe((data) => {
|
||||
this.mode = data.mode;
|
||||
console.log(this.mode);
|
||||
|
||||
@@ -71,7 +71,7 @@ export class DeviceService {
|
||||
|
||||
deviceSwitch(data): Observable<any> {
|
||||
const endpoint = `/devices`;
|
||||
const url = `${BASE_URL}${endpoint}/device-switch`;
|
||||
const url = `${BASE_URL}${endpoint}/device-command`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
@@ -88,4 +88,91 @@ export class DeviceService {
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
getDeviceStatus(id): Observable<any> {
|
||||
const endpoint = `/devices`;
|
||||
const url = `${BASE_URL}${endpoint}/status?id=${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
getDeviceByid(id): Observable<any> {
|
||||
const endpoint = `/devices`;
|
||||
const url = `${BASE_URL}${endpoint}/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
filterDashboard(building, floor): Observable<any> {
|
||||
const endpoint = `/building/dashboard/list`;
|
||||
const params = new URLSearchParams({
|
||||
building_id: building ? building : 0,
|
||||
floor_id: floor ? floor :0,
|
||||
});
|
||||
// if (category) {
|
||||
// params.append("category_id", category);
|
||||
// }
|
||||
const url = `${BASE_URL}${endpoint}?${params.toString()}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
getDeviceScheduler(id): Observable<any> {
|
||||
const endpoint = `/device-scheduler`;
|
||||
const url = `${BASE_URL}${endpoint}?device_id=${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
postDeviceScheduler(data): Observable<any> {
|
||||
const endpoint = `/device-scheduler`;
|
||||
const url = `${BASE_URL}${endpoint}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.post<any>(url, data, { headers });
|
||||
}
|
||||
|
||||
putDeviceScheduler(data, id): Observable<any> {
|
||||
const endpoint = `/device-scheduler/${id}`;
|
||||
const url = `${BASE_URL}${endpoint}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.put<any>(url, data, { headers });
|
||||
}
|
||||
|
||||
putDeviceSchedulerActive(data, id): Observable<any> {
|
||||
const endpoint = `/device-scheduler/${id}/Active`;
|
||||
const url = `${BASE_URL}${endpoint}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.put<any>(url, data, { headers });
|
||||
}
|
||||
|
||||
deleteDeviceScheduler(id): Observable<any> {
|
||||
const endpoint = `/device-scheduler/${id}`;
|
||||
const url = `${BASE_URL}${endpoint}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.delete<any>(url, { headers });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,71 +1,46 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { HttpClient, HttpHeaders } from "@angular/common/http";
|
||||
import { HttpClient, HttpHeaders } from "@angular/common/http";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class EnergyMonitoringService {
|
||||
private readonly baseUrl = 'https://kapi.absys.ninja/hemat';
|
||||
private readonly apiKey = 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT';
|
||||
private readonly headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': this.apiKey
|
||||
});
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
private get<T>(endpoint: string, params: any = {}): Observable<T> {
|
||||
const url = `${this.baseUrl}/${endpoint}`;
|
||||
return this.http.get<T>(url, { headers: this.headers, params });
|
||||
}
|
||||
|
||||
getListRoomData(): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room/list`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
return this.get<any>('room/list');
|
||||
}
|
||||
|
||||
getDashboardTopCard(id): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/dashboard/top-card?building_id=${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
getDashboardTopCard(buildingId: string, floorId: string, roomId: string): Observable<any> {
|
||||
return this.get<any>('dashboard/top-card', { building_id: buildingId, floor_id: floorId, room_id: roomId });
|
||||
}
|
||||
|
||||
getDashboardSummary(id): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/dashboard/summary-cost?building_id=${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
getDashboardSummary(buildingId: string, floorId: string, roomId: string): Observable<any> {
|
||||
return this.get<any>('dashboard/summary-cost', { building_id: buildingId, floor_id: floorId, room_id: roomId });
|
||||
}
|
||||
|
||||
getDashboardAirQuality(id): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/dashboard/air-quality?building_id=${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
getDashboardDeviceCategory(buildingId: string, floorId: string, roomId: string): Observable<any> {
|
||||
return this.get<any>('dashboard/device-category-use', { building_id: buildingId, floor_id: floorId, room_id: roomId });
|
||||
}
|
||||
|
||||
getDashboardTemperature(id): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/dashboard/temperature-humidity?building_id=${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
getDashboardChartKwhWater(buildingId: string, floorId: string, roomId: string): Observable<any> {
|
||||
return this.get<any>('dashboard/chartKwhWater', { building_id: buildingId, floor_id: floorId, room_id: roomId });
|
||||
}
|
||||
getDashboardDeviceCategory(id): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/dashboard/device-category-use?building_id=${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
getDashboardChartKwhWater(id): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/dashboard/chartKwhWater?building_id=${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
|
||||
getDeviceStatus(deviceId: any): Observable<any> {
|
||||
return this.get<any>('devices/status', { id: deviceId });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
// src/app/services/login.service.ts
|
||||
import { Injectable, NgZone } from "@angular/core";
|
||||
import { HttpClient, HttpHeaders } from "@angular/common/http";
|
||||
import { Observable } from "rxjs";
|
||||
import {
|
||||
BehaviorSubject,
|
||||
Observable,
|
||||
of,
|
||||
Subject,
|
||||
timer,
|
||||
fromEvent,
|
||||
merge,
|
||||
} from "rxjs";
|
||||
import { jwtDecode } from "jwt-decode";
|
||||
import { Router } from "@angular/router";
|
||||
import { switchMap, debounceTime, mapTo, startWith } from "rxjs/operators";
|
||||
import { AuthService } from "src/app/_services/auth.service";
|
||||
import { error } from "console";
|
||||
|
||||
const BASE_URL = "https://kapi.absys.ninja/hemat";
|
||||
interface CustomJwtPayload {
|
||||
@@ -23,11 +34,28 @@ interface CustomJwtPayload {
|
||||
})
|
||||
export class LoginService {
|
||||
private readonly tokenKey = "currentUser";
|
||||
private tabSelected = new BehaviorSubject<string | null>(null);
|
||||
public _tabSelected = this.tabSelected.asObservable();
|
||||
|
||||
private activitySubject = new Subject<boolean>();
|
||||
public activity$: Observable<boolean> = this.activitySubject.asObservable();
|
||||
|
||||
currentUser: any;
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
private router: Router,
|
||||
public logoutService: AuthService
|
||||
) {}
|
||||
private authService: AuthService,
|
||||
private ngZone: NgZone
|
||||
) {
|
||||
this.startTrackingActivity();
|
||||
this.startTokenCheck();
|
||||
this.currentUser = JSON.parse(localStorage.getItem("currentUser"));
|
||||
}
|
||||
|
||||
setTabsSelected(e: string) {
|
||||
this.tabSelected.next(e);
|
||||
}
|
||||
|
||||
updatePassword(data: any): Observable<any> {
|
||||
const endpoint = `/users`;
|
||||
@@ -39,7 +67,7 @@ export class LoginService {
|
||||
return this.http.put<any>(url, data, { headers });
|
||||
}
|
||||
|
||||
getDataProfil(id): Observable<any> {
|
||||
getDataProfil(id: string): Observable<any> {
|
||||
const endpoint = `/users`;
|
||||
const url = `${BASE_URL}${endpoint}/byUserid/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
@@ -56,7 +84,7 @@ export class LoginService {
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
|
||||
return this.http.post(`${url}`, data, { headers });
|
||||
return this.http.post<any>(`${url}`, data, { headers });
|
||||
}
|
||||
|
||||
updateUserProfile(data: any): Observable<any> {
|
||||
@@ -67,36 +95,113 @@ export class LoginService {
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
|
||||
return this.http.post(`${url}`, body, { headers });
|
||||
return this.http.post<any>(`${url}`, body, { headers });
|
||||
}
|
||||
|
||||
isTokenExpired(): boolean {
|
||||
isTokenExpired(): Observable<boolean> {
|
||||
const tokenData = localStorage.getItem(this.tokenKey);
|
||||
if (tokenData) {
|
||||
const tokenInfo = JSON.parse(tokenData);
|
||||
const decodedToken = jwtDecode<CustomJwtPayload>(tokenInfo.refresh_token);
|
||||
const expiryDate = decodedToken.exp * 1000;
|
||||
const now = new Date().getTime();
|
||||
return now > expiryDate;
|
||||
const timeLeft = expiryDate - now;
|
||||
return of(timeLeft <= 2 * 60 * 1000);
|
||||
}
|
||||
return true;
|
||||
return of(true);
|
||||
}
|
||||
|
||||
checkTokenAndRedirect(): void {
|
||||
if (this.isTokenExpired()) {
|
||||
// Token sudah kedaluwarsa, arahkan ke halaman login
|
||||
// console.log("Token expired, redirecting to login page...");
|
||||
this.logoutService.doLogout().then(
|
||||
(res) => {
|
||||
this.router.navigate(["/login"]);
|
||||
},
|
||||
(err) => {
|
||||
console.log(err);
|
||||
this.isTokenExpired().subscribe((isExpired) => {
|
||||
if (isExpired) {
|
||||
this.authService.doLogout().then(
|
||||
() => {
|
||||
this.router.navigate(["/login"]);
|
||||
window.location.reload();
|
||||
},
|
||||
(err) => {
|
||||
console.log(err);
|
||||
}
|
||||
);
|
||||
this.router.navigate(["/login"]);
|
||||
window.location.reload();
|
||||
} else {
|
||||
console.log("Token is valid, continuing...");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
startTokenCheck(): void {
|
||||
timer(0, 2 * 60 * 1000) // Check every 5 minutes
|
||||
.pipe(switchMap(() => this.isTokenExpired()))
|
||||
.subscribe((isExpired) => {
|
||||
// console.log(isExpired);
|
||||
|
||||
if (isExpired) {
|
||||
this.activity$.subscribe((isActive) => {
|
||||
// console.log(isActive);
|
||||
|
||||
if (!isActive) {
|
||||
this.checkTokenAndRedirect();
|
||||
} else {
|
||||
console.log(
|
||||
"Token expired but user is active. Refresh token not implemented."
|
||||
);
|
||||
|
||||
this.updateUserProfile(this.currentUser.refresh_token).subscribe(
|
||||
(resp) => {
|
||||
const decodedToken = jwtDecode<CustomJwtPayload>(
|
||||
resp.access_token
|
||||
);
|
||||
localStorage.setItem(
|
||||
"account_info",
|
||||
JSON.stringify(decodedToken)
|
||||
);
|
||||
const userProfile = {
|
||||
access_token: resp.access_token,
|
||||
refresh_token: resp.refresh_token,
|
||||
displayName: decodedToken.name,
|
||||
buildingId: 4,
|
||||
};
|
||||
localStorage.setItem(
|
||||
"currentUser",
|
||||
JSON.stringify(userProfile)
|
||||
);
|
||||
window.location.reload();
|
||||
}, (error) => {
|
||||
console.error(error);
|
||||
this.checkTokenAndRedirect();
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
startTrackingActivity(): void {
|
||||
this.ngZone.runOutsideAngular(() => {
|
||||
const activityEvents$ = merge(
|
||||
fromEvent(window, "mousemove"),
|
||||
fromEvent(window, "click"),
|
||||
fromEvent(window, "keypress"),
|
||||
fromEvent(window, "scroll")
|
||||
);
|
||||
this.router.navigate(["/login"]);
|
||||
} else {
|
||||
console.log("Token is valid, continuing...");
|
||||
}
|
||||
|
||||
activityEvents$
|
||||
.pipe(
|
||||
startWith(null),
|
||||
switchMap(() =>
|
||||
merge(
|
||||
timer(0).pipe(mapTo(true)),
|
||||
timer(5 * 60 * 1000).pipe(mapTo(false)) // 5 minutes of inactivity
|
||||
)
|
||||
),
|
||||
debounceTime(300)
|
||||
)
|
||||
.subscribe((active) => {
|
||||
this.ngZone.run(() => this.activitySubject.next(active));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,131 +14,6 @@ export class MasterService {
|
||||
this.loadDataIcon = `${this.apiBaseURL}/hemat/remixicons.json`;
|
||||
}
|
||||
|
||||
getMasterListData(): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/header-param/list`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
getMasterData(page: number = 1, limit: number = 100): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/header-param?page=${page}&limit=${limit}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
postHeaderDetailParam(data: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/header-detail-param`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.post<any>(url, data, { headers });
|
||||
}
|
||||
putHeaderDetailParam(data: any, id: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/header-detail-param/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.put<any>(url, data, { headers });
|
||||
}
|
||||
|
||||
deleteHeaderDetailParam(id: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/header-detail-param/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.delete<any>(url, { headers });
|
||||
}
|
||||
|
||||
postMasterBuildingParam(data: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.post<any>(url, data, { headers });
|
||||
}
|
||||
|
||||
getMasterBuildingData(page: number = 1, limit: number = 100): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building?page=${page}&limit=${limit}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
getBuildingList(): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building/list`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
putMasterBuildingParam(data: any, id: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.put<any>(url, data, { headers });
|
||||
}
|
||||
|
||||
deleteMasterBuildingParam(id: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.delete<any>(url, { headers });
|
||||
}
|
||||
|
||||
postMasterRoomParam(data: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.post<any>(url, data, { headers });
|
||||
}
|
||||
|
||||
putMasterRoomParam(data: any, id: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.put<any>(url, data, { headers });
|
||||
}
|
||||
|
||||
getListRoomData(): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room/list`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
getMasterRoomData(page: number = 1, limit: number = 100): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room?page=${page}&limit=${limit}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT'
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
getIconData(): Observable<any> {
|
||||
return this.http.get(this.loadDataIcon, httpOptions);
|
||||
}
|
||||
|
||||
@@ -2,252 +2,175 @@ import { Injectable } from "@angular/core";
|
||||
import { HttpClient, HttpHeaders } from "@angular/common/http";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
const httpOptions = {
|
||||
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
|
||||
};
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class BuildingService {
|
||||
private readonly apiBaseURL = 'https://kapi.absys.ninja/hemat';
|
||||
private readonly apiKey = 'j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT';
|
||||
private readonly headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": this.apiKey,
|
||||
});
|
||||
|
||||
loadDataIcon = null;
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
private get<T>(endpoint: string, params: any = {}): Observable<T> {
|
||||
const url = `${this.apiBaseURL}/${endpoint}`;
|
||||
return this.http.get<T>(url, { headers: this.headers, params });
|
||||
}
|
||||
|
||||
private post<T>(endpoint: string, data: any): Observable<T> {
|
||||
const url = `${this.apiBaseURL}/${endpoint}`;
|
||||
return this.http.post<T>(url, data, { headers: this.headers });
|
||||
}
|
||||
|
||||
private put<T>(endpoint: string, data: any): Observable<T> {
|
||||
const url = `${this.apiBaseURL}/${endpoint}`;
|
||||
return this.http.put<T>(url, data, { headers: this.headers });
|
||||
}
|
||||
|
||||
private delete<T>(endpoint: string, params: any = {}): Observable<T> {
|
||||
const url = `${this.apiBaseURL}/${endpoint}`;
|
||||
return this.http.delete<T>(url, { headers: this.headers, params });
|
||||
}
|
||||
|
||||
postLogin(data: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/users/login`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.post<any>(url, data, { headers });
|
||||
return this.post<any>('users/login', data);
|
||||
}
|
||||
|
||||
listBuilding(): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building/dashboard/list`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
return this.get<any>('building/dashboard/list');
|
||||
}
|
||||
|
||||
getBuildingData(page: number = 1, limit: number = 10): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building?page=${page}&limit=${limit}`;
|
||||
// const headers = new HttpHeaders().set('Content-Type', 'application/json');
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
getRoomByBuildingId(buildingId: string): Observable<any> {
|
||||
return this.get<any>('room-building/list/byIds', { buildingId });
|
||||
}
|
||||
|
||||
getRoomByBuildingId(buildingId: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room-building/list/byIds?buildingId=${buildingId}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
}
|
||||
|
||||
getDeviceById(deviceId: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/devices/${deviceId}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
getDeviceById(deviceId: string): Observable<any> {
|
||||
return this.get<any>(`devices/${deviceId}`);
|
||||
}
|
||||
|
||||
getMasterListData(): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/header-param/list`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
return this.get<any>('header-param/list');
|
||||
}
|
||||
|
||||
getMasterData(page: number = 1, limit: number = 100): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/header-param?page=${page}&limit=${limit}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
return this.get<any>('header-param', { page, limit });
|
||||
}
|
||||
|
||||
getMasterBuildingData(
|
||||
page: number = 1,
|
||||
limit: number = 100
|
||||
): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building?page=${page}&limit=${limit}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
getMasterDataListFloor(buildingId: string): Observable<any> {
|
||||
return this.get<any>('header-detail-param/list', { headerId: 6, building_id: buildingId });
|
||||
}
|
||||
|
||||
getMasterBuildingData(page: number = 1, limit: number = 100): Observable<any> {
|
||||
return this.get<any>('building', { page, limit });
|
||||
}
|
||||
|
||||
getBuildingList(): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building/list`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
return this.get<any>('building/list');
|
||||
}
|
||||
|
||||
getListRoomData(): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room/list`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
return this.get<any>('room/list');
|
||||
}
|
||||
|
||||
getRoom(id: any): Observable<any> {
|
||||
return this.get<any>(`room/${id}`);
|
||||
}
|
||||
|
||||
getListRoomDataUnmap(): Observable<any> {
|
||||
return this.get<any>('room/list/unmap');
|
||||
}
|
||||
|
||||
getListFloorDataUnmap(id: any): Observable<any> {
|
||||
return this.get<any>('header-detail-param/list/unmap-room-building', { headerId: id });
|
||||
}
|
||||
|
||||
getMasterRoomData(page: number = 1, limit: number = 100): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room?page=${page}&limit=${limit}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
return this.get<any>('room', { page, limit });
|
||||
}
|
||||
|
||||
getCostManagement(page: number = 1, limit: number = 100): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/cost_management?page=${page}&limit=${limit}&building_id=4&periode=2024-06`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
return this.get<any>('cost_management', { page, limit, building_id: 4, periode: '2024-06' });
|
||||
}
|
||||
|
||||
postHeaderDetailParam(data: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/header-detail-param`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.post<any>(url, data, { headers });
|
||||
}
|
||||
putHeaderDetailParam(data: any, id: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/header-detail-param/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.put<any>(url, data, { headers });
|
||||
return this.post<any>('header-detail-param', data);
|
||||
}
|
||||
|
||||
deleteHeaderDetailParam(id: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/header-detail-param/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.delete<any>(url, { headers });
|
||||
putHeaderDetailParam(data: any, id: string): Observable<any> {
|
||||
return this.put<any>(`header-detail-param/${id}`, data);
|
||||
}
|
||||
|
||||
getHeaderDetailParam(id: any): Observable<any> {
|
||||
return this.get<any>(`header-detail-param/${id}`);
|
||||
}
|
||||
|
||||
deleteHeaderDetailParam(id: string): Observable<any> {
|
||||
return this.delete<any>(`header-detail-param/${id}`);
|
||||
}
|
||||
|
||||
postMasterBuildingParam(data: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.post<any>(url, data, { headers });
|
||||
}
|
||||
putMasterBuildingParam(data: any, id: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.put<any>(url, data, { headers });
|
||||
return this.post<any>('building', data);
|
||||
}
|
||||
|
||||
deleteMasterBuildingParam(id: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/building/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.delete<any>(url, { headers });
|
||||
putMasterBuildingParam(data: any, id: string): Observable<any> {
|
||||
return this.put<any>(`building/${id}`, data);
|
||||
}
|
||||
|
||||
deleteMasterBuildingParam(id: string): Observable<any> {
|
||||
return this.delete<any>(`building/${id}`);
|
||||
}
|
||||
|
||||
postMasterRoomParam(data: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.post<any>(url, data, { headers });
|
||||
return this.post<any>('room', data);
|
||||
}
|
||||
|
||||
putMasterRoomParam(data: any, id: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room/${id}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.put<any>(url, data, { headers });
|
||||
|
||||
putMasterRoomParam(data: any, id: string): Observable<any> {
|
||||
return this.put<any>(`room/${id}`, data);
|
||||
}
|
||||
|
||||
deleteRoom(id: string): Observable<any> {
|
||||
return this.delete<any>(`room/${id}`);
|
||||
}
|
||||
|
||||
postBatchBuilding(data: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room-building/post-batch/room`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.post<any>(url, data, { headers });
|
||||
return this.post<any>('room-building/post-batch/room', data);
|
||||
}
|
||||
|
||||
getBuildingRoomList(page: number = 1, limit: number = 1000): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/room-building?page=${page}&limit=${limit}`;
|
||||
const headers = new HttpHeaders({
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
||||
});
|
||||
return this.http.get<any>(url, { headers });
|
||||
return this.get<any>('room-building', { page, limit });
|
||||
}
|
||||
|
||||
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 });
|
||||
putBuildingRoom(data: any, id: string): Observable<any> {
|
||||
return this.put<any>(`room-building/${id}`, data);
|
||||
}
|
||||
|
||||
putDevice(data: any, id: any): Observable<any> {
|
||||
const url = `https://kapi.absys.ninja/hemat/devices/${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: string): Observable<any> {
|
||||
return this.put<any>(`devices/${id}`, data);
|
||||
}
|
||||
|
||||
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 });
|
||||
getRoomBuildingById(roomBuildingId: string): Observable<any> {
|
||||
return this.get<any>(`room-building/${roomBuildingId}`);
|
||||
}
|
||||
|
||||
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 });
|
||||
deleteRoomBuilding(id: string): Observable<any> {
|
||||
return this.delete<any>(`room-building/${id}`);
|
||||
}
|
||||
|
||||
getDevicesWithSwitchMapping(devices: any[]): any[] {
|
||||
return devices.filter((device) =>
|
||||
device.mapping.some((map: any) => map.name.includes('switch'))
|
||||
// device.mapping.some((map: any) => console.log(map))
|
||||
);
|
||||
getIconData(): Observable<any> {
|
||||
return this.http.get(this.loadDataIcon, httpOptions);
|
||||
}
|
||||
|
||||
getDetailChart(date_index: any, building_id: any, floor_id: any, room_id: any): Observable<any> {
|
||||
return this.get<any>(`/dashboard/chartKwhWater/detail?date_index=${date_index}&building_id=${building_id}&floor_id=${floor_id}&room_id=${room_id}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
33
src/app/content/hemat-app/service/user-activity.service.ts
Normal file
33
src/app/content/hemat-app/service/user-activity.service.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Injectable, NgZone } from '@angular/core';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UserActivityService {
|
||||
private activitySubject = new Subject<boolean>();
|
||||
private timeoutId: any;
|
||||
|
||||
constructor(private ngZone: NgZone) {
|
||||
this.setupActivityListeners();
|
||||
}
|
||||
|
||||
private setupActivityListeners(): void {
|
||||
const events = ['click', 'mousemove', 'keypress'];
|
||||
events.forEach(event => {
|
||||
window.addEventListener(event, () => this.resetTimeout(), true);
|
||||
});
|
||||
}
|
||||
|
||||
private resetTimeout(): void {
|
||||
this.ngZone.runOutsideAngular(() => {
|
||||
clearTimeout(this.timeoutId);
|
||||
this.timeoutId = setTimeout(() => this.activitySubject.next(false), 300000); // 5 minutes
|
||||
this.activitySubject.next(true);
|
||||
});
|
||||
}
|
||||
|
||||
get activity$(): Observable<boolean> {
|
||||
return this.activitySubject.asObservable();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #fbfbfb !important">
|
||||
<div class="card-content">
|
||||
<div class="card-header" style="background-color: #252525 !important">
|
||||
<h2 style="color: #ffffff"></h2>
|
||||
<div class="card-header" style="background-color: #fbfbfb !important">
|
||||
<h2 style="color: #242222"></h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form [formGroup]="profilInfo" (ngSubmit)="onProjectInfoSubmit()">
|
||||
@@ -9,14 +9,13 @@
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="form-group">
|
||||
<label for="firstName" style="color: #ffffff">First Name</label>
|
||||
<label for="firstName" style="color: #242222">First Name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="firstName"
|
||||
class="form-control"
|
||||
formControlName="firstName"
|
||||
maxlength="20"
|
||||
placeholder="John Vander"
|
||||
[ngClass]="{'is-invalid': profilInfo.get('firstName').invalid && profilInfo.get('firstName').touched}"
|
||||
/>
|
||||
<div *ngIf="profilInfo.get('firstName').invalid && profilInfo.get('firstName').touched" class="text-danger">
|
||||
@@ -24,14 +23,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="lastName" style="color: #ffffff">Last Name</label>
|
||||
<label for="lastName" style="color: #242222">Last Name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="lastName"
|
||||
class="form-control"
|
||||
formControlName="lastName"
|
||||
maxlength="20"
|
||||
placeholder="John Vander"
|
||||
[ngClass]="{'is-invalid': profilInfo.get('lastName').invalid && profilInfo.get('lastName').touched}"
|
||||
/>
|
||||
<div *ngIf="profilInfo.get('firstName').invalid && profilInfo.get('firstName').touched" class="text-danger">
|
||||
@@ -39,13 +37,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email" style="color: #ffffff">Email</label>
|
||||
<label for="email" style="color: #242222">Email</label>
|
||||
<input
|
||||
type="text"
|
||||
id="email"
|
||||
class="form-control"
|
||||
formControlName="email"
|
||||
placeholder="email@email.com"
|
||||
maxlength="50"
|
||||
[ngClass]="{'is-invalid': profilInfo.get('email').invalid && profilInfo.get('email').touched}"
|
||||
/>
|
||||
@@ -54,14 +51,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="phone" style="color: #ffffff">Phone</label>
|
||||
<label for="phone" style="color: #242222">Phone</label>
|
||||
<input
|
||||
type="text"
|
||||
id="phone"
|
||||
class="form-control"
|
||||
formControlName="phone"
|
||||
maxlength="13"
|
||||
placeholder="08**************"
|
||||
pattern="^[0-9]*$"
|
||||
[ngClass]="{'is-invalid': profilInfo.get('phone').invalid && profilInfo.get('phone').touched}"
|
||||
/>
|
||||
@@ -117,9 +113,9 @@
|
||||
type="button"
|
||||
class="btn btn-warning mr-1"
|
||||
style="
|
||||
color: #ffffff !important;
|
||||
color: #242222 !important;
|
||||
background-color: transparent !important;
|
||||
border-color: #ffffff !important;
|
||||
border-color: #fbfbfb !important;
|
||||
border-radius: 10px;
|
||||
width: 145px;
|
||||
"
|
||||
@@ -131,8 +127,8 @@
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
background-color: #c3f164 !important;
|
||||
color: #ffffff !important;
|
||||
background-color: #37a647 !important;
|
||||
border-radius: 10px;
|
||||
width: 145px;
|
||||
"
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ToastrService } from "ngx-toastr";
|
||||
import { jwtDecode } from "jwt-decode";
|
||||
import { AuthService } from "src/app/_services/auth.service";
|
||||
import { Router } from "@angular/router";
|
||||
import * as _ from "lodash"
|
||||
interface CustomJwtPayload {
|
||||
exp: number;
|
||||
scope: string;
|
||||
@@ -30,7 +31,7 @@ export class ProfilInformationComponent {
|
||||
storedData: any;
|
||||
currentUser: any;
|
||||
disableButton: boolean = false;
|
||||
|
||||
oldData: any;
|
||||
url: any = "https://www.w3schools.com/howto/img_avatar.png";
|
||||
fileSelected: any = null;
|
||||
|
||||
@@ -40,19 +41,35 @@ export class ProfilInformationComponent {
|
||||
private toastr: ToastrService,
|
||||
public logoutService: AuthService,
|
||||
private router: Router
|
||||
) {}
|
||||
) {
|
||||
this.authService._tabSelected.subscribe(res => {
|
||||
console.log(res);
|
||||
console.log(this.oldData);
|
||||
console.log(this.profilInfo.value);
|
||||
if (res === "update-password") {
|
||||
if (this.oldData !== this.profilInfo.value) {
|
||||
console.log('ada perubahan');
|
||||
return false
|
||||
} else {
|
||||
console.log('tidak ada perubahan');
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.storedData = JSON.parse(localStorage.getItem("account_info"));
|
||||
this.currentUser = JSON.parse(localStorage.getItem("currentUser"));
|
||||
this.authService.checkTokenAndRedirect();
|
||||
this.authService.startTokenCheck();
|
||||
this.authService.startTrackingActivity();
|
||||
|
||||
this.profilInfo = this.formBuilder.group({
|
||||
firstName: ["", Validators.required],
|
||||
lastName: ["", Validators.required],
|
||||
email: ["", [Validators.required, Validators.pattern(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)]],
|
||||
phone: ["", [Validators.required, Validators.pattern(/^[0-9]{10,15}$/)]],
|
||||
image: [null],
|
||||
image: [null, Validators.required],
|
||||
});
|
||||
this.dataProfil(this.storedData.sub);
|
||||
this.profilInfo.valueChanges.subscribe(() => {
|
||||
@@ -69,6 +86,10 @@ export class ProfilInformationComponent {
|
||||
phone: data.data.phone,
|
||||
image: [null],
|
||||
});
|
||||
// this.oldData._.cloneDeep(this.profilInfo.value);
|
||||
this.oldData = _.cloneDeep(this.profilInfo.value)
|
||||
console.log(this.oldData);
|
||||
|
||||
if (
|
||||
data.data.image_path !== "https://kapi.absys.ninja/hemat/image/null"
|
||||
) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<section id="update-password">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="card" style="background-color: #252525 !important">
|
||||
<div class="card" style="background-color: #fbfbfb !important">
|
||||
<div class="card-content">
|
||||
<div class="card-header" style="background-color: #252525 !important">
|
||||
<h2 style="color: #ffffff">Update Password</h2>
|
||||
<div class="card-header" style="background-color: #fbfbfb !important">
|
||||
<h2 style="color: #242222">Update Password</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form [formGroup]="profilInfo" (ngSubmit)="onProjectInfoSubmit()">
|
||||
@@ -49,7 +49,9 @@
|
||||
</button>
|
||||
</div> -->
|
||||
<div class="form-group">
|
||||
<label for="newPass" style="color: #ffffff">New Password</label>
|
||||
<label for="newPass" style="color: #242222"
|
||||
>New Password</label
|
||||
>
|
||||
<div class="input-group">
|
||||
<input
|
||||
[type]="showNewPass ? 'text' : 'password'"
|
||||
@@ -67,29 +69,38 @@
|
||||
type="button"
|
||||
class="btn btn-link"
|
||||
(click)="toggleNewPassVisibility()"
|
||||
style="color: #c3f164 !important;"
|
||||
style="color: #37a647 !important"
|
||||
>
|
||||
<i [class]="showNewPass ? 'fa fa-eye-slash' : 'fa fa-eye'"></i>
|
||||
<i
|
||||
[class]="
|
||||
showNewPass ? 'fa fa-eye-slash' : 'fa fa-eye'
|
||||
"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
<small
|
||||
class="form-text text-muted danger"
|
||||
*ngIf="submitted && f.newPass.errors"
|
||||
class="invalid-feedback"
|
||||
>
|
||||
<div *ngIf="f.newPass.errors.required">
|
||||
New Password is required
|
||||
</div>
|
||||
<div *ngIf="f.newPass.errors.minlength">
|
||||
New Password must be at least 8 characters long
|
||||
</div>
|
||||
<div *ngIf="f.newPass.errors.pattern">
|
||||
New Password must contain at least one uppercase
|
||||
letter, one lowercase letter, and one number
|
||||
</div>
|
||||
</small>
|
||||
</div>
|
||||
<small
|
||||
class="form-text text-muted danger"
|
||||
*ngIf="submitted && f.newPass.errors"
|
||||
class="invalid-feedback"
|
||||
>
|
||||
<div *ngIf="f.newPass.errors.required">New Password is required</div>
|
||||
<div *ngIf="f.newPass.errors.minlength">
|
||||
New Password must be at least 8 characters long
|
||||
</div>
|
||||
<div *ngIf="f.newPass.errors.pattern">
|
||||
New Password must contain at least one uppercase letter, one lowercase letter, and one number
|
||||
</div>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="confirmPass" style="color: #ffffff">Confirm Password</label>
|
||||
<label for="confirmPass" style="color: #242222"
|
||||
>Confirm Password</label
|
||||
>
|
||||
<div class="input-group">
|
||||
<input
|
||||
[type]="showConfirmPass ? 'text' : 'password'"
|
||||
@@ -107,22 +118,30 @@
|
||||
type="button"
|
||||
class="btn btn-link"
|
||||
(click)="toggleConfirmPassVisibility()"
|
||||
style="color: #c3f164 !important;"
|
||||
style="color: #37a647 !important"
|
||||
>
|
||||
<i [class]="showConfirmPass ? 'fa fa-eye-slash' : 'fa fa-eye'"></i>
|
||||
<i
|
||||
[class]="
|
||||
showConfirmPass
|
||||
? 'fa fa-eye-slash'
|
||||
: 'fa fa-eye'
|
||||
"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
<small
|
||||
class="form-text text-muted danger"
|
||||
*ngIf="submitted && f.confirmPass.errors"
|
||||
class="invalid-feedback"
|
||||
>
|
||||
<div *ngIf="f.confirmPass.errors.required">
|
||||
Confirm Password is required
|
||||
</div>
|
||||
<div *ngIf="f.confirmPass.errors.matchPassword">
|
||||
Confirm Password must match the New Password
|
||||
</div>
|
||||
</small>
|
||||
</div>
|
||||
<small
|
||||
class="form-text text-muted danger"
|
||||
*ngIf="submitted && f.confirmPass.errors"
|
||||
class="invalid-feedback"
|
||||
>
|
||||
<div *ngIf="f.confirmPass.errors.required">Confirm Password is required</div>
|
||||
<div *ngIf="f.confirmPass.errors.matchPassword">
|
||||
Confirm Password must match the New Password
|
||||
</div>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -132,9 +151,9 @@
|
||||
type="button"
|
||||
class="btn btn-warning mr-1"
|
||||
style="
|
||||
color: #ffffff !important;
|
||||
color: #242222 !important;
|
||||
background-color: transparent !important;
|
||||
border-color: #ffffff !important;
|
||||
border-color: #fbfbfb !important;
|
||||
border-radius: 10px;
|
||||
width: 145px;
|
||||
"
|
||||
@@ -146,8 +165,8 @@
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
style="
|
||||
color: #000000 !important;
|
||||
background-color: #c3f164 !important;
|
||||
color: #fff !important;
|
||||
background-color: #37a647 !important;
|
||||
border-radius: 10px;
|
||||
width: 145px;
|
||||
"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user