Compare commits

..

82 Commits

Author SHA1 Message Date
b00896d407 validasi mandatory hari 2024-08-28 15:16:05 +07:00
7c443080d6 perbaikan UI scheduler 2024-08-27 16:41:09 +07:00
98159a1584 penambahan label detail 2024-08-26 14:13:37 +07:00
5c5ca65f53 perbaikan label 2024-08-26 11:54:17 +07:00
ecef25f30d integrasi edit scheduler 2024-08-26 11:43:22 +07:00
45e280c007 penyesuaian scheduler 2024-08-26 11:21:56 +07:00
ca5f0c8c0c integrasi add dan delete scheduler 2024-08-26 11:04:02 +07:00
b1ee612602 penambahan UI scheduler list 2024-08-23 00:27:24 +07:00
9654cf92e8 perbakan UI scheduler 2024-08-22 15:45:48 +07:00
a2d166ac1a penambahan UI control scheduler 2024-08-22 14:09:13 +07:00
a9a7e6edd3 warning perubahan data pada list monitoring 2024-08-22 10:42:01 +07:00
b5e0962079 perbaikan logic save device 2024-08-22 10:10:38 +07:00
633effdb9b penambahan pop up table dan export chart 2024-08-21 15:29:28 +07:00
7a28e52e89 perbaikan service 2024-08-21 11:51:04 +07:00
c54fdd0f55 perbaikan alert watt 2024-08-21 10:53:06 +07:00
04972e33b1 validasi device 2024-08-21 10:20:59 +07:00
f81dc7bf66 perubahan icon back 2024-08-20 16:27:49 +07:00
2b1f6c0cfe logic save ketika room di remove semua 2024-08-20 16:12:48 +07:00
9529da581a alert mandatory monitoring list 2024-08-20 16:04:45 +07:00
b195055651 perbaikan validasi penempatan device dalam ruangan 2024-08-20 15:37:50 +07:00
2a4135c966 perbaikan monitoring list search 2024-08-20 11:45:47 +07:00
cd1f56e07b filter floor status aktif 2024-08-20 11:37:45 +07:00
9377bebcb4 perbaikan UI 2024-08-20 11:02:10 +07:00
57bcbcccde hapus validasi name floor 2024-08-20 10:30:31 +07:00
d753a3a634 perbaikan onchange select floor 2024-08-19 15:16:33 +07:00
a9d135f8ef integrasi select floor per building id 2024-08-19 14:58:00 +07:00
0aac2ff194 perbaikan tampilan cost management 2024-08-19 13:08:35 +07:00
379bdb24da perbaikan routing see more 2024-08-19 12:48:09 +07:00
21b75ca610 klik detail per floor dan room 2024-08-19 11:29:59 +07:00
b5cf71d008 penambahan route floor dan room 2024-08-19 10:06:37 +07:00
cd777f11ad penambahan ui tidak ada data 2024-08-19 09:32:57 +07:00
f4036b1a06 penambahan filter 2024-08-19 09:26:56 +07:00
4fdaa8c1bd penambahan filter dashboard 2024-08-14 12:45:13 +07:00
5410d966d0 update versi 2024-08-13 10:16:21 +07:00
irfan.ms
bfb828c15c Fixing select Room 2024-08-12 16:13:40 +07:00
124f3eef4c penambahan UI pada setiap inputan monitoring list 2024-08-12 13:54:40 +07:00
9b4ac3b992 penambahan floor pada room building dan code pada mster floor 2024-08-08 16:19:07 +07:00
d70edcebd8 perubahan backgound login 2024-07-26 10:16:28 +07:00
a458f2ce3c update versi 2024-07-26 09:42:03 +07:00
db9a9e415a perbaikan master 2024-07-26 09:41:23 +07:00
a9f3da867f update versi 2024-07-25 09:47:13 +07:00
03c7e54bc8 penambahan search code 2024-07-25 09:46:28 +07:00
df1cd2339e perbaikan master room dan detail monitoring 2024-07-23 13:25:47 +07:00
2a6cf6410d perbaikan edit master 2024-07-22 15:21:50 +07:00
3b3757e2a7 pernambahan code pada master room 2024-07-22 15:09:38 +07:00
95fa99799c perbaikan cost management 2024-07-22 13:41:58 +07:00
8cc1a2b9fb perubahan background maintenance 2024-07-22 11:35:51 +07:00
9d8e31e7fe update UI profil 2024-07-22 11:15:05 +07:00
c04cafa384 perbaikan tampilan device edit 2024-07-22 11:01:46 +07:00
e3be28b4b6 perubahan tampilan detail 2024-07-22 09:38:57 +07:00
da4100993b perbaikan master layout button 2024-07-18 15:15:40 +07:00
0c1dd29554 perbaikan master 2024-07-18 14:56:37 +07:00
f86dfb7829 penjagaan double room 2024-07-18 14:35:07 +07:00
9a29e2e4e0 update versi 2024-07-18 14:03:54 +07:00
721d4e9af9 penambahan UI untuk room building ID 2024-07-18 14:02:57 +07:00
153b47eaaa perbaikan detail building 2024-07-17 17:44:41 +07:00
c337a8941c penambahan temperature, air quality dan humidity 2024-07-17 15:40:55 +07:00
bd1cd42ed6 slicing design baru 2024-07-17 11:51:29 +07:00
7bc1fa5fe9 slicing cost manager 2024-07-16 16:33:20 +07:00
768c9ee6ca perbaikan service 2024-07-16 15:53:22 +07:00
efb6ae0060 slicing device 2024-07-16 15:04:12 +07:00
d22eaa50e1 slicing see all control device 2024-07-16 14:24:45 +07:00
60d14b2fce perbaikan service 2024-07-16 13:48:21 +07:00
6b91c937ab implement refresh token 2024-07-16 13:46:58 +07:00
fa12fcec50 kwh max lenght 2024-07-16 11:43:08 +07:00
9570b77e32 update versi 2024-07-16 11:40:31 +07:00
dd1deb0812 perbaikan master dan ngecek token jika ada kegiatan 2024-07-16 11:39:44 +07:00
751c36209e slicing dashboard 2024-07-15 21:39:12 +07:00
4c2d40986e perbaikan master building 2024-07-14 13:56:25 +07:00
5782af4c75 perbaikan master edit 2024-07-13 22:47:01 +07:00
5b3c9bcba4 perbaikan list building 2024-07-12 16:53:04 +07:00
45f3c9b86b perbaikan css 2024-07-12 16:04:47 +07:00
9a0d0d919e perbaikan label master room 2024-07-12 15:25:32 +07:00
13e5ee01d2 perbaikan master 2024-07-12 15:16:53 +07:00
a9034c1a32 perbaikan profil, update password dan master 2024-07-11 14:39:06 +07:00
28067d1704 penambahan maxleght 2024-07-11 11:45:53 +07:00
4ae3b51530 perbaiki kwh 2024-07-11 11:28:41 +07:00
dc4be31103 perbaikan kwh 2024-07-11 11:23:42 +07:00
0b37bcd8ee update versi 2024-07-11 10:26:13 +07:00
a79493d329 edit room building 2024-07-11 10:24:59 +07:00
52481cbc4b salah posisi validator 2024-07-11 10:04:48 +07:00
d43a26513e perbaikan edit building 2024-07-11 10:03:08 +07:00
110 changed files with 5602 additions and 2184 deletions

1
package-lock.json generated
View File

@@ -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",

View File

@@ -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",

View File

@@ -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>

View File

@@ -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 &copy; 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>

View File

@@ -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

View File

@@ -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">

View File

@@ -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",
},
],
},
},

View File

@@ -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);
}
}

View File

@@ -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; */
}

View File

@@ -31,6 +31,5 @@ export class SelectIconComponent {
} else {
this.iconSelected.emit(undefined);
}
}
}

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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],
},
],
};

View File

@@ -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()"

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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"

View File

@@ -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);
}

View File

@@ -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'"

View File

@@ -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() {
@@ -228,8 +255,50 @@ export class AddEditDeviceComponent implements OnInit{
}
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);
}
});
}

View File

@@ -0,0 +1,3 @@
::ng-deep .modal-backdrop.show {
z-index: auto !important;
}

View File

@@ -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">&times;</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>

View File

@@ -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();
});
});

View File

@@ -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);
}
});
}
}

View File

@@ -1,11 +1,12 @@
: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;
@@ -13,3 +14,41 @@
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;
}

View File

@@ -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;
"
>
&#x22EE;
</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)"

View File

@@ -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;
});
}
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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");
});
}

View File

@@ -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 { }

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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();
});
});

View File

@@ -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;
});
}
}

View File

@@ -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

View File

@@ -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}`);
}
);
}
}

View File

@@ -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;
.style-custom-label{
color: #242222 !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 */
}

View File

@@ -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>

View File

@@ -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) {

View File

@@ -1,56 +1,54 @@
/* modal-add-edit.component.css */
::ng-deep .modal-backdrop.show {
z-index: auto !important;
}
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-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 .input-group {
display: flex;
flex-wrap: nowrap; /* Prevents wrapping of the items */
align-items: center;
}
::ng-deep .form-control {
flex-grow: 1;
padding-right: 0.5rem;
}
::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;
}
::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;
}
::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;
}
.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;
} */

View File

@@ -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">&times;</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()"
>

View File

@@ -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);
}
editForm() {
console.log(this.dataRow);
toUppercase(event: Event) {
const input = event.target as HTMLInputElement;
input.value = input.value.toUpperCase();
this.myForm.get('code').setValue(input.value);
}
editForm() {
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
}

View File

@@ -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">&times;</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()"
>

View File

@@ -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}$/)]],
});
}

View File

@@ -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;
}

View File

@@ -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)"
>

View File

@@ -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,
});
});
}
}

View File

@@ -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;
}

View File

@@ -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)"
>

View File

@@ -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
);
});
}
@@ -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,
});

View File

@@ -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;
}

View File

@@ -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)"
>

View File

@@ -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,
});
}
);
}
}
}

View File

@@ -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;
}

View File

@@ -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)"
>

View File

@@ -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,
});
}
);
}
}
}

View File

@@ -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;
}

View File

@@ -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)"
>

View File

@@ -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,
});
}
);
}
}
}

View File

@@ -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">&times;</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

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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)"
>

View File

@@ -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,
});
});
}
);
}
}
}

View File

@@ -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;
}

View File

@@ -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)"
>

View File

@@ -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,
});
}
);
}
}
}

View File

@@ -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;
}

View File

@@ -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)"
>

View File

@@ -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,
});
}
);
}
}
}

View File

@@ -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;
}

View File

@@ -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)"
>

View File

@@ -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,
});
}
);
}
}
}

View File

@@ -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;
}
} */

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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)"

View File

@@ -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);
});
}
}

View File

@@ -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 */
}

View File

@@ -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>

View File

@@ -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);
this.donutChart1 = {
type: "Pie",
data: this.dataChart.donut,
options: {
fullwidth: true,
height: "300px",
donut: true,
donutWidth: 70,
startAngle: 270,
total: 200,
showLabel: true,
},
};
} 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.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,
]);
}
}

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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();
});
});

View File

@@ -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);
}
}

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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);

View File

@@ -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 });
}
}

View File

@@ -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 });
}
}

View File

@@ -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));
});
});
}
}

View File

@@ -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);
}

View File

@@ -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}`);
}
}

View 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();
}
}

View File

@@ -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;
"

View File

@@ -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"
) {

View File

@@ -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