MikroWizard Initial commit | MikroFront Welcome to the world :)

This commit is contained in:
sepehr 2024-07-07 14:48:52 +03:30
commit b97aec6b97
203 changed files with 41097 additions and 0 deletions

View file

@ -0,0 +1,21 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { DeviceComponent } from './device.component';
const routes: Routes = [
{
path: '',
component: DeviceComponent,
data: {
title: $localize`Device Detail`
}
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class DeviceRoutingModule {
}

View file

@ -0,0 +1,167 @@
<c-alert style="margin-bottom: 5px;margin-top: 5px;" *ngIf="!loading && devdata['update_availble']"
(click)="logger(devdata['sensors'])" color="warning">Firmware
Update availble For This Device!</c-alert>
<c-alert style="margin-bottom: 5px;margin-top: 5px;" *ngIf="!loading && devdata['upgrade_availble']"
(click)="logger(devdata['upgrade_availble'])" color="info">Device is updated but needs to upgrade firmware!</c-alert>
<c-row *ngIf="!loading">
<c-col xs>
<c-card class="mb-1">
<c-card-header>
<c-row>
<c-col md="3">
<h3>{{devdata['name'] }}<small style="font-size: 50%;"> ( {{devdata['ip'] }} )</small></h3>
</c-col>
<c-col md="9" class="justify-content-end" style="text-align: end;">
<c-button-group class="mb-2" aria-label="Upate interval" role="group">
<button cButton color="primary" (click)="delta='5m';updateData()" [active]="delta=='5m'">5 minute</button>
<button cButton color="primary" (click)="delta='1h';updateData()" [active]="delta=='1h'">Hourly</button>
<button cButton color="primary" (click)="delta='daily';updateData()"
[active]="delta=='daily'">Daily</button>
<button cButton color="primary" (click)="delta='live';updateData()" [active]="delta=='live'">Live</button>
</c-button-group>
</c-col>
</c-row>
</c-card-header>
<c-card-body>
<app-widgets-dropdown *ngIf="!loading" [devicedata]=devsensors></app-widgets-dropdown>
</c-card-body>
</c-card>
</c-col>
</c-row>
<c-row>
<c-col xs>
<c-card class="mb-1">
<c-card-body>
<c-row style="flex-direction:row">
<ng-container *ngFor="let item of devdata | keyvalue; index as i">
<!-- <c-col *ngIf="checkitem(item)" class="mb-2" >
<c-card color="dark" textColor="white" class="h-100 ">
<c-card-header style="padding: 5px 0 2px 9px;text-transform: capitalize;">{{item.key}}</c-card-header>
<c-card-body class="bg-gradient" style="padding:2px 0 2px 9px;">
<p cCardText>{{item.value}}</p>
</c-card-body>
</c-card>
</c-col> -->
<c-input-group *ngIf="checkitem(item)" class="mr-0 ml-0 mb-1"
style="padding-right:unset;width: auto;flex: 1 1 auto;flex-flow: nowrap;flex: unset;">
<span
style="padding: 0.175rem 0.35rem;background-color:#4f5d73;text-transform: capitalize;color:#fff;font-size:0.7rem"
cInputGroupText>{{item.key}}</span>
<!-- <input cFormControl disabled style="font-size:0.8rem" [value]="item.value"/> -->
<span _ngcontent-ng-c666080582="" cinputgrouptext=""
style="padding: 0.175rem 0.35rem;color: rgba(44, 56, 74, 0.95);font-size: 0.7rem;background-color: #d8dbe0;border-color: #b1b7c1;"
class="input-group-text">{{ item.value }}</span>
<!-- <span style="background-color:#4f5d73;text-transform: capitalize;color:#fff;font-size:0.8rem" cInputGroupText >{{item.key}}</span> -->
</c-input-group>
</ng-container>
</c-row>
</c-card-body>
</c-card>
</c-col>
</c-row>
<!-- Mikrotik interfaces table -->
<c-row>
<c-col xs>
<c-card class="mb-1">
<c-card-body>
<c-row style="flex-direction:row">
<gui-grid [source]="interfaces" [columnMenu]="columnMenu" [sorting]="sorting" [infoPanel]="infoPanel"
[rowSelection]="rowSelection" [autoResizeWidth]=true>
<gui-grid-column header="Name" field="name">
<ng-template let-value="item.name" let-item="item" let-index="index">
{{value}} - {{item['default-name']}}
</ng-template>
</gui-grid-column>
<gui-grid-column header="MAC" field="mac-address">
<ng-template let-value="item['mac-address']" let-item="item" let-index="index">
{{value}}
</ng-template>
</gui-grid-column>
<gui-grid-column header="rx" field="rx-byte">
<ng-template let-value="item['rx-byte']" let-item="item" let-index="index">
<div>{{convert_bw_human(value,'rx')}}</div>
</ng-template>
</gui-grid-column>
<gui-grid-column header="tx" field="tx-byte">
<ng-template let-value="item['tx-byte']" let-item="item" let-index="index">
{{convert_bw_human(value,'tx')}}
</ng-template>
</gui-grid-column>
<gui-grid-column header="l2mtu" field="l2mtu">
<ng-template let-value="item.l2mtu" let-item="item" let-index="index">
curr:{{value}}<br />
max : {{item['max-l2mtu']}}
</ng-template>
</gui-grid-column>
<gui-grid-column header="rx/s" field="rx-bits-per-second" [enabled]="false">
<ng-template let-value="item['rx-bits-per-second']" let-item="item" let-index="index">
{{convert_bw_human(value,'rx')}}
</ng-template>
</gui-grid-column>
<gui-grid-column header="tx/s" field="tx-bits-per-second" [enabled]="false">
<ng-template let-value="item['tx-bits-per-second']" let-item="item" let-index="index">
{{convert_bw_human(value,'tx')}}
</ng-template>
</gui-grid-column>
<gui-grid-column header="Created" field="created" [enabled]="false">
<ng-template let-value="item.created" let-item="item.id" let-index="index">
{{value}}
</ng-template>
</gui-grid-column>
<gui-grid-column header="Last Up" field="last-link-up-time">
<ng-template let-value="item['last-link-up-time']" let-item="item" let-index="index">
{{value}}
</ng-template>
</gui-grid-column>
<gui-grid-column header="Created" field="created" [enabled]="false">
<ng-template let-value="item.created" let-item="item.id" let-index="index">
{{value}}
</ng-template>
</gui-grid-column>
<gui-grid-column header="Actions" field="action" width="100" align="center">
<ng-template let-value="item.id" let-item="item" let-index="index">
<button cButton color="info" size="sm" (click)="show_interface_rate(item['default-name'])"
class="mx-1"><i class="fa-solid fa-chart-line"></i></button>
</ng-template>
</gui-grid-column>
</gui-grid>
</c-row>
</c-card-body>
</c-card>
</c-col>
</c-row>
<c-modal #staticBackdropModal backdrop="static" size="xl" [visible]="InterfaceChartModalVisible"
id="InterfaceChartModal">
<c-modal-header>
<h5 cModalTitle>{{interface_rate['name']}}</h5>
<button [cModalToggle]="staticBackdropModal.id" cButtonClose></button>
</c-modal-header>
<c-modal-body>
<c-chart [data]="interface_rate" [options]="options" type="line">
</c-chart>
</c-modal-body>
<c-modal-footer>
<button [cModalToggle]="staticBackdropModal.id" cButton color="secondary">
Close
</button>
</c-modal-footer>
</c-modal>

View file

@ -0,0 +1,7 @@
:host {
.legend {
small {
font-size: x-small;
}
}
}

View file

@ -0,0 +1,36 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ButtonModule, DropdownModule, GridModule, WidgetModule } from '@coreui/angular';
import { IconModule } from '@coreui/icons-angular';
import { ChartjsModule } from '@coreui/angular-chartjs';
import { IconSetService } from '@coreui/icons-angular';
import { iconSubset } from '../../icons/icon-subset';
import { DeviceComponent } from './device.component';
describe('DeviceComponent', () => {
let component: DeviceComponent;
let fixture: ComponentFixture<DeviceComponent>;
let iconSetService: IconSetService;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ DeviceComponent ],
imports: [WidgetModule, DropdownModule, IconModule, ButtonModule, ChartjsModule, GridModule],
providers: [IconSetService]
})
.compileComponents();
});
beforeEach(() => {
iconSetService = TestBed.inject(IconSetService);
iconSetService.icons = { ...iconSubset };
fixture = TestBed.createComponent(DeviceComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,437 @@
import { Component, OnInit } from "@angular/core";
import { Router, ActivatedRoute } from "@angular/router";
import { dataProvider } from "../../providers/mikrowizard/data";
import { loginChecker } from "../../providers/login_checker";
import {
GuiInfoPanel,
GuiColumn,
GuiColumnMenu,
GuiPaging,
GuiPagingDisplay,
GuiRowSelectionMode,
GuiRowSelection,
GuiRowSelectionType,
} from "@generic-ui/ngx-grid";
import { __setFunctionName } from "tslib";
interface IUser {
name: string;
state: string;
registered: string;
country: string;
usage: number;
period: string;
payment: string;
activity: string;
avatar: string;
status: string;
color: string;
}
@Component({
templateUrl: "device.component.html",
styleUrls: ["device.component.scss"],
})
export class DeviceComponent implements OnInit {
public uid: number;
public uname: string;
public tz: string;
constructor(
private data_provider: dataProvider,
private route: ActivatedRoute,
private router: Router,
private login_checker: loginChecker
) {
var _self = this;
if (!this.login_checker.isLoggedIn()) {
setTimeout(function () {
_self.router.navigate(["login"]);
}, 100);
}
this.data_provider.getSessionInfo().then((res) => {
_self.uid = res.uid;
_self.uname = res.name;
_self.tz = res.tz;
const userId = _self.uid;
if (res.role != "admin") {
setTimeout(function () {
_self.router.navigate(["/user/dashboard"]);
}, 100);
}
});
//get datagrid data
function isNotEmpty(value: any): boolean {
return value !== undefined && value !== null && value !== "";
}
}
public devdata: any;
public devsensors: any;
public columns: Array<GuiColumn> = [];
public loading: boolean = true;
public InterfaceChartModalVisible: boolean = false;
public rows: any = [];
public Selectedrows: any;
public devid: number = 0;
public data_interval: any;
public delta: string = "5m";
public total_type: string = "bps";
public interface_rate: any = {};
public options: any;
public sorting = {
enabled: true,
multiSorting: true,
};
public interfaces: Array<any> = [];
public paging: GuiPaging = {
enabled: true,
page: 1,
pageSize: 10,
pageSizes: [5, 10, 25, 50],
display: GuiPagingDisplay.ADVANCED,
};
public columnMenu: GuiColumnMenu = {
enabled: true,
sort: true,
columnsManager: true,
};
public infoPanel: GuiInfoPanel = {
enabled: true,
infoDialog: false,
columnsManager: true,
schemaManager: true,
};
public rowSelection: boolean | GuiRowSelection = {
enabled: true,
type: GuiRowSelectionType.CHECKBOX,
mode: GuiRowSelectionMode.MULTIPLE,
};
Chartoptions = {
plugins: {
tooltip: {
callbacks: {
label: function (context: any) {
const units = ["bit", "Kib", "Mib", "Gib", "Tib"];
let label = context.dataset.label || "";
var res = context.parsed.y;
let unitIndex = 0;
// if (res>8) res /=8;
while (res >= 1024 && unitIndex < units.length - 1) {
res /= 1024;
unitIndex++;
}
switch (context.dataset.unit) {
case "rx":
return "rx/s :" + res.toFixed(3) + " " + units[unitIndex];
break;
case "tx":
return "tx/s :" + res.toFixed(3) + " " + units[unitIndex];
break;
case "rxp":
return "rxp/s :" + context.parsed.y;
break;
case "txp":
return "txp/s :" + context.parsed.y;
break;
default:
return context.parsed.y;
break;
}
},
},
},
legend: {
display: true,
},
},
maintainAspectRatio: true,
scales: {
x: { display: false },
yA: {
display: true,
stacked: true,
position: "left",
type: "linear",
color: "#17522f",
grid: {
color: "rgba(23, 82, 47, 0.3)",
borderDash: [5, 5],
},
ticks: {
color: "#17522f",
callback: function (value: any, index: any, ticks: any) {
const units = ["bit", "Kib", "Mib", "Gib", "Tib"];
var res = value;
let unitIndex = 0;
while (res >= 1024 && unitIndex < units.length - 1) {
res /= 1024;
unitIndex++;
}
return res.toFixed(3) + " " + units[unitIndex];
},
},
scaleLabel: {
display: true,
},
},
yB: {
display: true,
stacked: true,
position: "right",
type: "linear",
grid: {
color: "rgba(23, 25, 81, 0.3)",
borderDash: [8, 8],
},
border: {
width: 2,
},
ticks: {
color: "#171951",
callback: function (value: any, index: any, ticks: any) {
const units = ["bit", "Kib", "Mib", "Gib", "Tib"];
var res = value;
let unitIndex = 0;
while (res >= 1024 && unitIndex < units.length - 1) {
res /= 1024;
unitIndex++;
}
return res.toFixed(3) + " " + units[unitIndex];
},
},
},
},
elements: {
line: {
borderWidth: 1,
tension: 0.4,
},
point: {
radius: 4,
hitRadius: 10,
hoverRadius: 6,
},
},
};
ngOnInit(): void {
this.devid = Number(this.route.snapshot.paramMap.get("id"));
this.options = this.Chartoptions;
this.initDeviceInfo();
}
optionsDefault = {
plugins: {
legend: {
display: false,
},
},
maintainAspectRatio: true,
scales: {
x: {
grid: {
display: false,
drawBorder: false,
},
ticks: {
display: false,
},
},
y: {
display: false,
grid: {
display: false,
},
ticks: {
display: false,
},
},
},
elements: {
line: {
borderWidth: 1,
tension: 0.4,
},
point: {
radius: 4,
hitRadius: 10,
hoverRadius: 6,
},
},
};
setOptions() {
for (let idx = 0; idx < 5; idx++) {
const options = JSON.parse(JSON.stringify(this.optionsDefault));
switch (idx) {
case 0: {
this.options.push(options);
break;
}
case 1: {
options.scales.y.min = -9;
options.scales.y.max = 39;
this.options.push(options);
break;
}
case 2: {
options.scales.x = { display: false };
options.scales.y = { display: false };
options.elements.line.borderWidth = 2;
options.elements.point.radius = 2;
this.options.push(options);
break;
}
case 3: {
options.scales.x.grid = { display: false, drawTicks: false };
options.scales.x.grid = {
display: false,
drawTicks: false,
drawBorder: false,
};
options.scales.y.min = undefined;
options.scales.y.max = undefined;
options.elements = {};
this.options.push(options);
break;
}
case 4: {
options.plugins = {
tooltip: {
callbacks: {
label: function (context: any) {
const units = ["bit", "Kib", "Mib", "Gib", "Tib"];
let label = context.dataset.label || "";
var res = context.parsed.y;
let unitIndex = 0;
// if (res>8) res /=8;
while (res >= 1024 && unitIndex < units.length - 1) {
res /= 1024;
unitIndex++;
}
switch (context.dataset.unit) {
case "rx":
return "rx/s :" + res.toFixed(3) + " " + units[unitIndex];
break;
case "tx":
return "tx/s :" + res.toFixed(3) + " " + units[unitIndex];
break;
case "rxp":
return "rxp/s :" + context.parsed.y;
break;
case "txp":
return "txp/s :" + context.parsed.y;
break;
default:
return context.parsed.y;
break;
}
},
},
},
legend: {
display: false,
},
};
options.scales = {
x: { display: false },
yA: {
display: false,
stacked: true,
position: "left",
type: "linear",
scaleLabel: {
display: true,
},
},
yB: {
display: false,
stacked: true,
position: "right",
type: "linear",
},
};
options.elements.line.borderWidth = 2;
options.elements.point.radius = 2;
this.options.push(options);
break;
}
}
}
}
logger(item: any) {
console.dir(item);
}
updateData(): void {
var _self = this;
this.data_provider.get_dev_info(this.devid).then((res) => {
_self.devdata = res;
_self.interfaces = res.interfaces;
_self.data_provider
.get_dev_sensors(_self.devid, _self.delta, _self.total_type)
.then((res) => {
_self.devsensors = res;
_self.loading = false;
});
});
}
checkitem(item: any) {
if (item.value && !item.key.match("sensors|id|_availble|interfaces")) {
return true;
} else {
return false;
}
}
convert_bw_human(mynumber: number = 0, unit: string) {
const units = ["bit", "Kib", "Mib", "Gib", "Tib"];
let unitIndex = 0;
while (mynumber >= 1024 && unitIndex < units.length - 1) {
mynumber /= 1024;
unitIndex++;
}
switch (unit) {
case "rx":
return mynumber.toFixed(3) + " " + units[unitIndex];
break;
case "tx":
return mynumber.toFixed(3) + " " + units[unitIndex];
break;
default:
return mynumber;
break;
}
}
show_interface_rate(name: string) {
var _self = this;
_self.InterfaceChartModalVisible = false;
this.data_provider
.get_dev_ifstat(_self.devid, _self.delta, name, _self.total_type)
.then((res) => {
_self.interface_rate = res["data"];
_self.InterfaceChartModalVisible = true;
});
}
initDeviceInfo(): void {
var _self = this;
clearInterval(this.data_interval);
this.updateData();
this.data_interval = setInterval(() => {
this.data_provider.get_dev_info(this.devid).then((res) => {
_self.devdata = res;
_self.interfaces = res.interfaces;
_self.data_provider
.get_dev_sensors(_self.devid, _self.delta, _self.total_type)
.then((res) => {
_self.devsensors = res;
_self.loading = false;
});
});
}, 1000000);
}
}

View file

@ -0,0 +1,42 @@
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import {
ButtonGroupModule,
ButtonModule,
CardModule,
FormModule,
GridModule,
ProgressModule,
NavbarModule,
AlertModule,
ModalModule,
} from "@coreui/angular";
import { ChartjsModule } from "@coreui/angular-chartjs";
import { DeviceRoutingModule } from "./device-routing.module";
import { DeviceComponent } from "./device.component";
import { GuiGridModule } from "@generic-ui/ngx-grid";
import { WidgetsModule } from "../widgets/widgets.module";
@NgModule({
imports: [
DeviceRoutingModule,
CardModule,
AlertModule,
CommonModule,
GridModule,
ProgressModule,
FormModule,
ButtonModule,
ButtonGroupModule,
ChartjsModule,
WidgetsModule,
GuiGridModule,
NavbarModule,
ModalModule,
],
declarations: [DeviceComponent],
})
export class DeviceModule {}