mirror of
https://github.com/MikroWizard/mikrofront.git
synced 2025-08-29 22:29:33 +02:00
MikroWizard Initial commit | MikroFront Welcome to the world :)
This commit is contained in:
commit
b97aec6b97
203 changed files with 41097 additions and 0 deletions
135
src/app/app-routing.module.ts
Normal file
135
src/app/app-routing.module.ts
Normal file
|
@ -0,0 +1,135 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { DefaultLayoutComponent } from './containers';
|
||||
import { Page404Component } from './views/pages/page404/page404.component';
|
||||
import { Page500Component } from './views/pages/page500/page500.component';
|
||||
import { LoginComponent } from './views/pages/login/login.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'dashboard',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: DefaultLayoutComponent,
|
||||
data: {
|
||||
title: 'Home'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'dashboard',
|
||||
loadChildren: () =>
|
||||
import('./views/dashboard/dashboard.module').then((m) => m.DashboardModule)
|
||||
},
|
||||
{
|
||||
path: 'devices',
|
||||
loadChildren: () =>
|
||||
import('./views/devices/devices.module').then((m) => m.DevicesModule)
|
||||
},
|
||||
{
|
||||
path: 'device-stats',
|
||||
loadChildren: () =>
|
||||
import('./views/device_detail/device.module').then((m) => m.DeviceModule)
|
||||
},
|
||||
{
|
||||
path: 'deviceGroup',
|
||||
loadChildren: () =>
|
||||
import('./views/devices_group/devgroup.module').then((m) => m.DevicesGroupModule)
|
||||
},
|
||||
{
|
||||
path: 'authlog',
|
||||
loadChildren: () =>
|
||||
import('./views/auth_log/auth.module').then((m) => m.AuthModule)
|
||||
},
|
||||
{
|
||||
path: 'devlogs',
|
||||
loadChildren: () =>
|
||||
import('./views/device_logs/devlogs.module').then((m) => m.DevLogsModule)
|
||||
},
|
||||
{
|
||||
path: 'syslog',
|
||||
loadChildren: () =>
|
||||
import('./views/syslog/syslog.module').then((m) => m.SyslogModule)
|
||||
},
|
||||
{
|
||||
path: 'backups',
|
||||
loadChildren: () =>
|
||||
import('./views/backups/backups.module').then((m) => m.BackupsModule)
|
||||
},
|
||||
{
|
||||
path: 'settings',
|
||||
loadChildren: () =>
|
||||
import('./views/settings/settings.module').then((m) => m.SettingsModule)
|
||||
},
|
||||
{
|
||||
path: 'accountlog',
|
||||
loadChildren: () =>
|
||||
import('./views/acc_log/acc.module').then((m) => m.AccModule)
|
||||
},
|
||||
{
|
||||
path: 'user_tasks',
|
||||
loadChildren: () =>
|
||||
import('./views/user_tasks/user_tasks.module').then((m) => m.UserTasksModule)
|
||||
},
|
||||
{
|
||||
path: 'snippets',
|
||||
loadChildren: () =>
|
||||
import('./views/snippets/snippets.module').then((m) => m.SnippetsModule)
|
||||
},
|
||||
{
|
||||
path: 'user_manager',
|
||||
loadChildren: () =>
|
||||
import('./views/user_manager/user_manager.module').then((m) => m.UserManagerModule)
|
||||
},
|
||||
{
|
||||
path: 'permissions',
|
||||
loadChildren: () =>
|
||||
import('./views/permissions/permissions.module').then((m) => m.PermissionsModule)
|
||||
},
|
||||
{
|
||||
path: 'pages',
|
||||
loadChildren: () =>
|
||||
import('./views/pages/pages.module').then((m) => m.PagesModule)
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '404',
|
||||
component: Page404Component,
|
||||
data: {
|
||||
title: 'Page 404'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '500',
|
||||
component: Page500Component,
|
||||
data: {
|
||||
title: 'Page 500'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'login',
|
||||
component: LoginComponent,
|
||||
data: {
|
||||
title: 'Login Page'
|
||||
}
|
||||
},
|
||||
{path: '**', redirectTo: 'dashboard'}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot(routes, {
|
||||
scrollPositionRestoration: 'top',
|
||||
anchorScrolling: 'enabled',
|
||||
initialNavigation: 'enabledBlocking'
|
||||
// relativeLinkResolution: 'legacy'
|
||||
})
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule {
|
||||
}
|
28
src/app/app.component.spec.ts
Normal file
28
src/app/app.component.spec.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have as title 'CoreUI Free Angular Admin Template'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('CoreUI Free Angular Admin Template');
|
||||
});
|
||||
});
|
33
src/app/app.component.ts
Normal file
33
src/app/app.component.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, NavigationEnd } from '@angular/router';
|
||||
|
||||
import { IconSetService } from '@coreui/icons-angular';
|
||||
import { iconSubset } from './icons/icon-subset';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: '<router-outlet></router-outlet>',
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
title = 'MikroWizard , Mikrotik router managent system';
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private titleService: Title,
|
||||
private iconSetService: IconSetService
|
||||
) {
|
||||
titleService.setTitle(this.title);
|
||||
// iconSet singleton
|
||||
iconSetService.icons = { ...iconSubset };
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
console.log(this.router.url);
|
||||
this.router.events.subscribe((evt) => {
|
||||
if (!(evt instanceof NavigationEnd)) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
116
src/app/app.module.ts
Normal file
116
src/app/app.module.ts
Normal file
|
@ -0,0 +1,116 @@
|
|||
import { NgModule ,APP_INITIALIZER} from '@angular/core';
|
||||
import { HashLocationStrategy, LocationStrategy, PathLocationStrategy } from '@angular/common';
|
||||
import { BrowserModule, Title } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { ReactiveFormsModule,FormsModule } from '@angular/forms';
|
||||
|
||||
import { NgScrollbarModule } from 'ngx-scrollbar';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
// Import routing module
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { provideDateFnsAdapter } from 'ngx-material-date-fns-adapter';
|
||||
|
||||
// Import app component
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
// Import containers
|
||||
import { DefaultFooterComponent, DefaultHeaderComponent, DefaultLayoutComponent } from './containers';
|
||||
import { MikroWizardProvider } from './providers/mikrowizard/provider';
|
||||
import { dataProvider } from './providers/mikrowizard/data';
|
||||
import { loginChecker } from './providers/login_checker';
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
||||
import { provideHighlightOptions, Highlight, HighlightAuto } from 'ngx-highlightjs';
|
||||
|
||||
import {
|
||||
AvatarModule,
|
||||
BadgeModule,
|
||||
BreadcrumbModule,
|
||||
ButtonGroupModule,
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
DropdownModule,
|
||||
FooterModule,
|
||||
FormModule,
|
||||
GridModule,
|
||||
HeaderModule,
|
||||
ListGroupModule,
|
||||
NavModule,
|
||||
ProgressModule,
|
||||
SharedModule,
|
||||
SidebarModule,
|
||||
TabsModule,
|
||||
UtilitiesModule,
|
||||
ModalModule
|
||||
} from '@coreui/angular';
|
||||
|
||||
import { IconModule, IconSetService } from '@coreui/icons-angular';
|
||||
|
||||
const APP_CONTAINERS = [
|
||||
DefaultFooterComponent,
|
||||
DefaultHeaderComponent,
|
||||
DefaultLayoutComponent
|
||||
];
|
||||
export function loginStatusProviderFactory(provider: loginChecker) {
|
||||
return () => provider.load();
|
||||
}
|
||||
@NgModule({
|
||||
declarations: [AppComponent, ...APP_CONTAINERS],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
AppRoutingModule,
|
||||
AvatarModule,
|
||||
BreadcrumbModule,
|
||||
FooterModule,
|
||||
DropdownModule,
|
||||
GridModule,
|
||||
HeaderModule,
|
||||
SidebarModule,
|
||||
IconModule,
|
||||
NavModule,
|
||||
HttpClientModule,
|
||||
ButtonModule,
|
||||
FormModule,
|
||||
UtilitiesModule,
|
||||
ButtonGroupModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
SidebarModule,
|
||||
SharedModule,
|
||||
TabsModule,
|
||||
ListGroupModule,
|
||||
ProgressModule,
|
||||
BadgeModule,
|
||||
ListGroupModule,
|
||||
CardModule,
|
||||
NgScrollbarModule,
|
||||
ModalModule,
|
||||
FontAwesomeModule
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: LocationStrategy,
|
||||
useClass: HashLocationStrategy
|
||||
},
|
||||
MikroWizardProvider,
|
||||
dataProvider,
|
||||
loginChecker,
|
||||
IconSetService,
|
||||
provideDateFnsAdapter(),
|
||||
provideHighlightOptions({
|
||||
fullLibraryLoader: () => import('highlight.js'),
|
||||
lineNumbersLoader: () => import('ngx-highlightjs/line-numbers')
|
||||
}),
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: loginStatusProviderFactory,
|
||||
deps: [loginChecker],
|
||||
multi: true,
|
||||
},
|
||||
Title
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
158
src/app/containers/default-layout/_nav.ts
Normal file
158
src/app/containers/default-layout/_nav.ts
Normal file
|
@ -0,0 +1,158 @@
|
|||
import { INavData } from '@coreui/angular';
|
||||
|
||||
export const navItems: INavData[] = [
|
||||
{
|
||||
name: 'Dashboard',
|
||||
url: '/dashboard',
|
||||
iconComponent: { name: 'cil-speedometer' },
|
||||
|
||||
},
|
||||
{
|
||||
title: true,
|
||||
name: 'Device Managment'
|
||||
},
|
||||
{
|
||||
name: 'Devices',
|
||||
url: '/devices',
|
||||
icon: 'fa-solid fa-server'
|
||||
},
|
||||
{
|
||||
name: 'Device Groups',
|
||||
url: '/deviceGroup',
|
||||
// linkProps: { fragment: 'someAnchor' },
|
||||
icon: 'fa-solid fa-layer-group'
|
||||
},
|
||||
// {
|
||||
// name: 'Tools',
|
||||
// url: '/login',
|
||||
// icon: 'fa-solid fa-screwdriver-wrench',
|
||||
// children: [
|
||||
// {
|
||||
// name: 'BW test',
|
||||
// url: '/login',
|
||||
// icon: 'fa-solid fa-file-circle-check'
|
||||
// },
|
||||
// {
|
||||
// name: 'Ping test',
|
||||
// url: '/register',
|
||||
// icon: 'fa-solid fa-arrow-right-arrow-left'
|
||||
// },
|
||||
// ]
|
||||
// },
|
||||
{
|
||||
name: 'Backup & Config',
|
||||
title: true
|
||||
},
|
||||
{
|
||||
name: 'Task Planer',
|
||||
url: '/user_tasks',
|
||||
icon: 'fa-solid fa-calendar-week'
|
||||
},
|
||||
{
|
||||
name: 'Backups',
|
||||
url: '/backups',
|
||||
icon: 'fa-solid fa-database'
|
||||
},
|
||||
{
|
||||
name: 'snippets',
|
||||
url: '/snippets',
|
||||
icon: 'fa-solid fa-code'
|
||||
},
|
||||
// {
|
||||
// name: 'Tools',
|
||||
// url: '/login',
|
||||
// icon: 'fa-solid fa-screwdriver-wrench',
|
||||
// children: [
|
||||
// {
|
||||
// name: 'Backup comparator',
|
||||
// url: '/login',
|
||||
// icon: 'fa-solid fa-code-compare'
|
||||
// },
|
||||
// {
|
||||
// name: 'Backup search',
|
||||
// url: '/register',
|
||||
// icon: 'fa-solid fa-magnifying-glass-arrow-right'
|
||||
// },
|
||||
// {
|
||||
// name: 'batch execute',
|
||||
// url: '/register',
|
||||
// icon: 'fa-solid fa-terminal'
|
||||
// },
|
||||
// ]
|
||||
// },
|
||||
{
|
||||
name: 'Reports',
|
||||
title: true
|
||||
},
|
||||
{
|
||||
name: 'Authentication',
|
||||
url: '/authlog',
|
||||
icon: 'fa-solid fa-check-to-slot',
|
||||
|
||||
},
|
||||
{
|
||||
name: 'Accounting',
|
||||
url: '/accountlog',
|
||||
icon: 'fa-solid fa-list-check',
|
||||
|
||||
},
|
||||
{
|
||||
name: 'Device Logs',
|
||||
url: '/devlogs',
|
||||
icon: 'fa-regular fa-rectangle-list',
|
||||
|
||||
},
|
||||
{
|
||||
name: 'System Logs',
|
||||
url: '/syslog',
|
||||
icon: 'fa-solid fa-person-circle-question',
|
||||
|
||||
},
|
||||
{
|
||||
title: true,
|
||||
name: 'Users'
|
||||
},
|
||||
{
|
||||
name: 'Users Management',
|
||||
url: '/user_manager',
|
||||
icon: 'fa-solid fa-user-gear' ,
|
||||
},
|
||||
{
|
||||
name: 'Permissions',
|
||||
url: '/permissions',
|
||||
icon: 'fa-solid fa-users' ,
|
||||
},
|
||||
{
|
||||
title: true,
|
||||
name: 'System',
|
||||
class: 'py-0'
|
||||
},
|
||||
{
|
||||
name: 'Settings',
|
||||
url: '/settings',
|
||||
icon: 'fa-solid fa-gear' ,
|
||||
},
|
||||
// {
|
||||
// name: 'Backup',
|
||||
// url: '/login',
|
||||
// icon: 'cil-star' ,
|
||||
// },
|
||||
{
|
||||
title: true,
|
||||
name: 'Links',
|
||||
class: 'py-0'
|
||||
},
|
||||
{
|
||||
name: 'Docs',
|
||||
url: 'https://mikrowizard.com/docs',
|
||||
iconComponent: { name: 'cil-description' },
|
||||
attributes: { target: '_blank', class: '-text-dark' },
|
||||
class: 'mt-auto'
|
||||
},
|
||||
{
|
||||
name: 'Buy Pro',
|
||||
url: 'https://mikrowizard.com/pricing/',
|
||||
icon:'fa-solid fa-money-check-dollar',
|
||||
attributes: { target: '_blank' }
|
||||
}
|
||||
];
|
|
@ -0,0 +1,6 @@
|
|||
<!--<c-footer>-->
|
||||
<div>
|
||||
<a href="https://mikrowizard.com" target="_blank">MikroWizard</a>
|
||||
<span> © 2024 </span>
|
||||
</div>
|
||||
<!--</c-footer>-->
|
|
@ -0,0 +1,25 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DefaultFooterComponent } from './default-footer.component';
|
||||
|
||||
describe('DefaultFooterComponent', () => {
|
||||
let component: DefaultFooterComponent;
|
||||
let fixture: ComponentFixture<DefaultFooterComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ DefaultFooterComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DefaultFooterComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { FooterComponent } from '@coreui/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-default-footer',
|
||||
templateUrl: './default-footer.component.html',
|
||||
styleUrls: ['./default-footer.component.scss'],
|
||||
})
|
||||
export class DefaultFooterComponent extends FooterComponent {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
|
||||
|
||||
|
||||
<!--<c-header class="mb-4 d-print-none" position="sticky">-->
|
||||
<ng-container>
|
||||
<c-container [fluid]="true">
|
||||
<button
|
||||
toggle="visible"
|
||||
cHeaderToggler
|
||||
[cSidebarToggle]="sidebarId"
|
||||
class="ps-1"
|
||||
>
|
||||
<svg cIcon
|
||||
name="cilMenu"
|
||||
size="lg"
|
||||
></svg>
|
||||
</button>
|
||||
<!-- <c-header-nav class="d-none d-lg-flex me-auto">
|
||||
<c-nav-item>
|
||||
<a cNavLink routerLink="/dashboard" routerLinkActive="active">
|
||||
Dashboard
|
||||
</a>
|
||||
</c-nav-item>
|
||||
<c-nav-item>
|
||||
<a cNavLink routerLink="/users" routerLinkActive="active">Users</a>
|
||||
</c-nav-item>
|
||||
<c-nav-item>
|
||||
<a cNavLink routerLink="/settings" routerLinkActive="active">
|
||||
Settings
|
||||
</a>
|
||||
</c-nav-item>
|
||||
</c-header-nav> -->
|
||||
|
||||
<!-- <c-header-nav class="d-none d-lg-flex">
|
||||
<c-nav-item>
|
||||
<a routerLink="./" cNavLink>
|
||||
<svg cIcon name="cilBell" size="lg"></svg>
|
||||
</a>
|
||||
</c-nav-item>
|
||||
<c-nav-item>
|
||||
<a routerLink="./" cNavLink>
|
||||
<svg cIcon name="cilList" size="lg"></svg>
|
||||
</a>
|
||||
</c-nav-item>
|
||||
<c-nav-item>
|
||||
<a routerLink="./" cNavLink>
|
||||
<svg cIcon name="cilEnvelopeOpen" size="lg"></svg>
|
||||
</a>
|
||||
</c-nav-item>
|
||||
</c-header-nav> -->
|
||||
<c-header-nav class="ms-3">
|
||||
<ng-container *ngTemplateOutlet="userDropdown"></ng-container>
|
||||
</c-header-nav>
|
||||
|
||||
</c-container>
|
||||
<c-header-divider></c-header-divider>
|
||||
<c-container [fluid]="true">
|
||||
<c-breadcrumb-router class="ms-2"></c-breadcrumb-router>
|
||||
</c-container>
|
||||
</ng-container>
|
||||
<!--</c-header>-->
|
||||
|
||||
<ng-template #userDropdown>
|
||||
<c-dropdown alignment="end" variant="nav-item">
|
||||
<button
|
||||
cButton
|
||||
color=""
|
||||
[caret]="false"
|
||||
cDropdownToggle
|
||||
class="py-0"
|
||||
>
|
||||
<svg cIcon class="me-2" name="cilUser"></svg>
|
||||
{{fname}} {{lname}}
|
||||
</button>
|
||||
<ul cDropdownMenu class="pt-0 pr-5 w-auto">
|
||||
<li>
|
||||
<h6 cDropdownHeader class="bg-light fw-semibold py-2">User Menu</h6>
|
||||
</li>
|
||||
<li>
|
||||
<button (click)="callParent()" cDropdownItem>
|
||||
<svg cIcon class="me-2" name="cilUser"></svg>
|
||||
Change password
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<a routerLink="./" (click)="logout()" cDropdownItem>
|
||||
<svg cIcon class="me-2" name="cilExitToApp"></svg>
|
||||
Logout
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</c-dropdown>
|
||||
</ng-template>
|
|
@ -0,0 +1,43 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import {
|
||||
AvatarModule,
|
||||
BadgeModule,
|
||||
BreadcrumbModule,
|
||||
DropdownModule,
|
||||
GridModule,
|
||||
HeaderModule,
|
||||
NavModule, SidebarModule
|
||||
} from '@coreui/angular';
|
||||
import { IconSetService } from '@coreui/icons-angular';
|
||||
import { iconSubset } from '../../../icons/icon-subset';
|
||||
import { DefaultHeaderComponent } from './default-header.component';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
|
||||
describe('DefaultHeaderComponent', () => {
|
||||
let component: DefaultHeaderComponent;
|
||||
let fixture: ComponentFixture<DefaultHeaderComponent>;
|
||||
let iconSetService: IconSetService;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [DefaultHeaderComponent],
|
||||
imports: [GridModule, HeaderModule, NavModule, BadgeModule, AvatarModule, DropdownModule, BreadcrumbModule, RouterTestingModule, SidebarModule],
|
||||
providers: [IconSetService]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
iconSetService = TestBed.inject(IconSetService);
|
||||
iconSetService.icons = { ...iconSubset };
|
||||
|
||||
fixture = TestBed.createComponent(DefaultHeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
import { Component, Input ,Output,EventEmitter} from '@angular/core';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { loginChecker } from '../../../providers/login_checker';
|
||||
import { Router } from "@angular/router";
|
||||
import { dataProvider } from '../../../providers/mikrowizard/data';
|
||||
import { User } from '../../../providers/mikrowizard/user';
|
||||
|
||||
import { ClassToggleService, HeaderComponent } from '@coreui/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-default-header',
|
||||
templateUrl: './default-header.component.html',
|
||||
})
|
||||
export class DefaultHeaderComponent extends HeaderComponent {
|
||||
|
||||
@Input() sidebarId: string = "sidebar";
|
||||
@Output() UserModalEvent = new EventEmitter<any>();
|
||||
|
||||
public newMessages = new Array(4)
|
||||
public newTasks = new Array(5)
|
||||
public newNotifications = new Array(5)
|
||||
public current_user: User;
|
||||
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
public fname: string;
|
||||
public lname: string;
|
||||
public UserProfileModalVisible : boolean = false;
|
||||
|
||||
constructor(
|
||||
private classToggler: ClassToggleService,
|
||||
private router: Router,
|
||||
private login_checker: loginChecker,
|
||||
private data_provider: dataProvider,
|
||||
) {
|
||||
super();
|
||||
var _self = this;
|
||||
var session_info: string = localStorage.getItem('current_user') || "[]]";
|
||||
this.current_user = JSON.parse(session_info);
|
||||
}
|
||||
|
||||
submit(){
|
||||
}
|
||||
|
||||
get_user_info() {
|
||||
var _self = this;
|
||||
this.uid = this.current_user.partner_id;
|
||||
this.uname = this.current_user.name;
|
||||
this.fname = this.current_user.firstname;
|
||||
this.lname = this.current_user.lastname;
|
||||
}
|
||||
|
||||
callParent(): void {
|
||||
this.UserModalEvent.next('test');
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.data_provider.logout().then(res => {
|
||||
this.router.navigate(['login']);
|
||||
})
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
var _self = this;
|
||||
this.get_user_info();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<!--sidebar-->
|
||||
<c-sidebar
|
||||
#sidebar="cSidebar"
|
||||
class="d-print-none sidebar sidebar-fixed"
|
||||
id="sidebar"
|
||||
visible
|
||||
>
|
||||
<c-sidebar-brand
|
||||
[brandFull]="{
|
||||
src: 'assets/img/brand/logo-MIkroWizard-big-white.svg',
|
||||
width: 200,
|
||||
height: 46,
|
||||
alt: 'MikroWizard Logo'
|
||||
}"
|
||||
[brandNarrow]="{
|
||||
src: 'assets/img/brand/logo-MIkroWizard-small-color.svg',
|
||||
width: 46,
|
||||
height: 46,
|
||||
alt: 'MikroWizard Logo'
|
||||
}"
|
||||
routerLink="./"
|
||||
/>
|
||||
|
||||
<ng-scrollbar pointerEventsMethod="scrollbar">
|
||||
<c-sidebar-nav
|
||||
[navItems]="navItems"
|
||||
dropdownMode="close"
|
||||
/>
|
||||
</ng-scrollbar>
|
||||
<c-sidebar-toggler
|
||||
*ngIf="!sidebar.narrow"
|
||||
toggle="unfoldable"
|
||||
cSidebarToggle="sidebar"
|
||||
/>
|
||||
</c-sidebar>
|
||||
|
||||
<!--main-->
|
||||
<div class="wrapper d-flex flex-column min-vh-100 bg-light dark:bg-transparent">
|
||||
<!--app-header-->
|
||||
<app-default-header (UserModalEvent)="show_user_modal()" class="mb-4 d-print-none header header-sticky" position="sticky" sidebarId="sidebar" />
|
||||
<!--app-body-->
|
||||
<div class="body flex-grow-1 px-3">
|
||||
<c-container breakpoint="fluid" class="h-auto">
|
||||
<router-outlet />
|
||||
</c-container>
|
||||
</div>
|
||||
<!--app footer-->
|
||||
<app-default-footer />
|
||||
</div>
|
||||
|
||||
<c-modal #UserProfileModal backdrop="static" size="lg" [(visible)]="UserProfileModalVisible" id="UserProfileModal">
|
||||
<c-modal-header>
|
||||
<h5 cModalTitle>Change Password Form of<code><b>{{ uname }}({{ fname }} {{lname}})</b></code></h5>
|
||||
<button [cModalToggle]="UserProfileModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
|
||||
<div [cFormFloating]="true" class="mb-3">
|
||||
<input type="password" cFormControl id="floatingInput" [(ngModel)]="password['cupass']" placeholder="Current Password" />
|
||||
<label cLabel for="floatingInput">Current Password</label>
|
||||
</div>
|
||||
|
||||
<div [cFormFloating]="true" class="mb-3">
|
||||
<input type="password" cFormControl (ngModelChange)="password_changed('pass1',$event)" [(ngModel)]="password['pass1']" id="floatingInput" placeholder="New Password" />
|
||||
<label cLabel for="floatingInput">New Password</label>
|
||||
</div>
|
||||
|
||||
<div [cFormFloating]="true" class="mb-3">
|
||||
<input type="password" cFormControl (ngModelChange)="password_changed('pass2',$event)" [(ngModel)]="password['pass2']" [valid]="passvalid['pass2']" id="floatingInput" placeholder="New Password confirm" />
|
||||
<label cLabel for="floatingInput">New Password confirm</label>
|
||||
</div>
|
||||
<code *ngIf="error"><i class="fa-solid fa-triangle-exclamation"></i><small> {{error}}</small></code>
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<button (click)="submit()" cButton color="primary">submit</button>
|
||||
<button [cModalToggle]="UserProfileModal.id" cButton color="secondary">
|
||||
Close
|
||||
</button>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
|
@ -0,0 +1,7 @@
|
|||
:host {
|
||||
ng-scrollbar {
|
||||
--scrollbar-thumb-color: var(--cui-border-color, #999);
|
||||
--scrollbar-track-color: var(--cui-body-color, #fff);
|
||||
--scrollbar-hover-size: calc(var(--scrollbar-size) * 1.5);
|
||||
}
|
||||
}
|
125
src/app/containers/default-layout/default-layout.component.ts
Normal file
125
src/app/containers/default-layout/default-layout.component.ts
Normal file
|
@ -0,0 +1,125 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, NavigationEnd } from "@angular/router";
|
||||
import { loginChecker } from '../../providers/login_checker';
|
||||
import { User } from '../../providers/mikrowizard/user';
|
||||
import { navItems } from './_nav';
|
||||
import { dataProvider } from '../../providers/mikrowizard/data';
|
||||
import { version } from 'os';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard',
|
||||
templateUrl: './default-layout.component.html',
|
||||
styleUrls: ['./default-layout.component.scss'],
|
||||
})
|
||||
export class DefaultLayoutComponent implements OnInit {
|
||||
|
||||
public navItems = navItems;
|
||||
public current_user: User;
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
public fname: string;
|
||||
public lname: string;
|
||||
public UserProfileModalVisible:boolean;
|
||||
public error:any=false;
|
||||
public password:any={
|
||||
'cupass':'',
|
||||
'pass1':'',
|
||||
'pass2':''
|
||||
};
|
||||
|
||||
public passvalid:any={
|
||||
'cupass':false,
|
||||
'pass1':false,
|
||||
'pass2':false
|
||||
};
|
||||
version=require('../../../../package.json').version;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private login_checker: loginChecker,
|
||||
private data_provider: dataProvider,
|
||||
|
||||
) {
|
||||
var _self = this;
|
||||
var session_info: string = localStorage.getItem('current_user') || "[]";
|
||||
this.current_user = JSON.parse(session_info);
|
||||
this.router.events.subscribe((ev) => {
|
||||
if (ev instanceof NavigationEnd) {
|
||||
if (!this.login_checker.isLoggedIn()) {
|
||||
setTimeout(function () {
|
||||
_self.router.navigate(['login']);
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
password_changed(variable:string,value:any){
|
||||
var _self=this;
|
||||
this.password[variable]=value;
|
||||
console.dir(this.password['pass1']);
|
||||
console.dir(this.password['pass2']);
|
||||
if(this.password['pass1']==this.password['pass2']){
|
||||
_self.passvalid['pass2']=true;
|
||||
}
|
||||
else{
|
||||
_self.passvalid['pass2']=false;
|
||||
}
|
||||
}
|
||||
|
||||
show_user_modal(){
|
||||
this.UserProfileModalVisible = true;
|
||||
}
|
||||
|
||||
submit(){
|
||||
var _self=this;
|
||||
if(!_self.passvalid['pass2']){
|
||||
return;
|
||||
}
|
||||
this.data_provider.change_password(this.password['cupass'], this.password['pass1']).then(res => {
|
||||
if(res['status']=='success'){
|
||||
_self.logout();
|
||||
setTimeout(function () {
|
||||
_self.router.navigate(['login']);
|
||||
}, 100);
|
||||
}
|
||||
else{
|
||||
_self.error=res['err'];
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
console.dir(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
get_user_info() {
|
||||
var _self = this;
|
||||
this.uid = this.current_user.partner_id;
|
||||
this.uname = this.current_user.name;
|
||||
this.fname = this.current_user.firstname;
|
||||
this.lname = this.current_user.lastname;
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.data_provider.logout();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
var _self = this;
|
||||
this.get_user_info();
|
||||
_self.data_provider.get_front_version().then((res:any) => {
|
||||
console.log("ressssssssssssssssss");
|
||||
console.dir(res['version']);
|
||||
console.dir(this.version);
|
||||
if(res['version']!=this.version){
|
||||
console.dir("New version is available. Please refresh the page.");
|
||||
window.location.href = window.location.href.replace(/#.*$/, '');
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
3
src/app/containers/default-layout/index.ts
Normal file
3
src/app/containers/default-layout/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export * from './default-footer/default-footer.component';
|
||||
export * from './default-header/default-header.component';
|
||||
export * from './default-layout.component';
|
1
src/app/containers/index.ts
Normal file
1
src/app/containers/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './default-layout';
|
281
src/app/icons/icon-subset.ts
Normal file
281
src/app/icons/icon-subset.ts
Normal file
|
@ -0,0 +1,281 @@
|
|||
import {
|
||||
cibCcAmex,
|
||||
cibCcApplePay,
|
||||
cibCcMastercard,
|
||||
cibCcPaypal,
|
||||
cibCcStripe,
|
||||
cibCcVisa,
|
||||
cibFacebook,
|
||||
cibGoogle,
|
||||
cibLinkedin,
|
||||
cibSkype,
|
||||
cibTwitter,
|
||||
cifBr,
|
||||
cifEs,
|
||||
cifFr,
|
||||
cifIn,
|
||||
cifPl,
|
||||
cifUs,
|
||||
cilAlignCenter,
|
||||
cilAlignLeft,
|
||||
cilAlignRight,
|
||||
cilApplicationsSettings,
|
||||
cilArrowBottom,
|
||||
cilArrowRight,
|
||||
cilArrowTop,
|
||||
cilBasket,
|
||||
cilBell,
|
||||
cilBold,
|
||||
cilBookmark,
|
||||
cilCalculator,
|
||||
cilCalendar,
|
||||
cilChart,
|
||||
cilChartPie,
|
||||
cilCheck,
|
||||
cilChevronLeft,
|
||||
cilChevronRight,
|
||||
cilCloudDownload,
|
||||
cilCode,
|
||||
cilCommentSquare,
|
||||
cilCreditCard,
|
||||
cilCursor,
|
||||
cilDescription,
|
||||
cilDollar,
|
||||
cilDrop,
|
||||
cilEnvelopeClosed,
|
||||
cilEnvelopeOpen,
|
||||
cilFile,
|
||||
cilHome,
|
||||
cilInbox,
|
||||
cilIndentDecrease,
|
||||
cilIndentIncrease,
|
||||
cilItalic,
|
||||
cilJustifyCenter,
|
||||
cilLayers,
|
||||
cilList,
|
||||
cilListNumbered,
|
||||
cilLocationPin,
|
||||
cilLockLocked,
|
||||
cilMagnifyingGlass,
|
||||
cilMap,
|
||||
cilMediaPlay,
|
||||
cilMenu,
|
||||
cilMoon,
|
||||
cilNotes,
|
||||
cilOptions,
|
||||
cilPaperclip,
|
||||
cilPaperPlane,
|
||||
cilPen,
|
||||
cilPencil,
|
||||
cilPeople,
|
||||
cilPrint,
|
||||
cilPuzzle,
|
||||
cilReportSlash,
|
||||
cilSave,
|
||||
cilSettings,
|
||||
cilShare,
|
||||
cilShareAll,
|
||||
cilShareBoxed,
|
||||
cilSpeech,
|
||||
cilSpeedometer,
|
||||
cilSpreadsheet,
|
||||
cilStar,
|
||||
cilSun,
|
||||
cilTags,
|
||||
cilTask,
|
||||
cilTrash,
|
||||
cilUnderline,
|
||||
cilUser,
|
||||
cilUserFemale,
|
||||
cilUserFollow,
|
||||
cilUserUnfollow,
|
||||
cilExitToApp
|
||||
} from '@coreui/icons';
|
||||
|
||||
export const iconSubset = {
|
||||
cibCcAmex,
|
||||
cibCcApplePay,
|
||||
cibCcMastercard,
|
||||
cibCcPaypal,
|
||||
cibCcStripe,
|
||||
cibCcVisa,
|
||||
cibFacebook,
|
||||
cibGoogle,
|
||||
cibLinkedin,
|
||||
cibSkype,
|
||||
cibTwitter,
|
||||
cifBr,
|
||||
cifEs,
|
||||
cifFr,
|
||||
cifIn,
|
||||
cifPl,
|
||||
cifUs,
|
||||
cilAlignCenter,
|
||||
cilAlignLeft,
|
||||
cilAlignRight,
|
||||
cilApplicationsSettings,
|
||||
cilArrowBottom,
|
||||
cilArrowRight,
|
||||
cilArrowTop,
|
||||
cilBasket,
|
||||
cilBell,
|
||||
cilBold,
|
||||
cilBookmark,
|
||||
cilCalculator,
|
||||
cilCalendar,
|
||||
cilChart,
|
||||
cilChartPie,
|
||||
cilCheck,
|
||||
cilChevronLeft,
|
||||
cilChevronRight,
|
||||
cilCloudDownload,
|
||||
cilCode,
|
||||
cilCommentSquare,
|
||||
cilCreditCard,
|
||||
cilCursor,
|
||||
cilDescription,
|
||||
cilDollar,
|
||||
cilDrop,
|
||||
cilEnvelopeClosed,
|
||||
cilEnvelopeOpen,
|
||||
cilFile,
|
||||
cilHome,
|
||||
cilInbox,
|
||||
cilIndentDecrease,
|
||||
cilIndentIncrease,
|
||||
cilItalic,
|
||||
cilJustifyCenter,
|
||||
cilLayers,
|
||||
cilList,
|
||||
cilListNumbered,
|
||||
cilLocationPin,
|
||||
cilLockLocked,
|
||||
cilMagnifyingGlass,
|
||||
cilMap,
|
||||
cilMediaPlay,
|
||||
cilMenu,
|
||||
cilMoon,
|
||||
cilNotes,
|
||||
cilOptions,
|
||||
cilPaperclip,
|
||||
cilPaperPlane,
|
||||
cilPen,
|
||||
cilPencil,
|
||||
cilPeople,
|
||||
cilPrint,
|
||||
cilPuzzle,
|
||||
cilReportSlash,
|
||||
cilSave,
|
||||
cilSettings,
|
||||
cilShare,
|
||||
cilShareAll,
|
||||
cilShareBoxed,
|
||||
cilSpeech,
|
||||
cilSpeedometer,
|
||||
cilSpreadsheet,
|
||||
cilStar,
|
||||
cilSun,
|
||||
cilTags,
|
||||
cilTask,
|
||||
cilTrash,
|
||||
cilUnderline,
|
||||
cilUser,
|
||||
cilUserFemale,
|
||||
cilUserFollow,
|
||||
cilUserUnfollow,
|
||||
cilExitToApp
|
||||
};
|
||||
|
||||
export enum IconSubset {
|
||||
cibCcAmex = 'cibCcAmex',
|
||||
cibCcApplePay = 'cibCcApplePay',
|
||||
cibCcMastercard = 'cibCcMastercard',
|
||||
cibCcPaypal = 'cibCcPaypal',
|
||||
cibCcStripe = 'cibCcStripe',
|
||||
cibCcVisa = 'cibCcVisa',
|
||||
cibFacebook = 'cibFacebook',
|
||||
cibGoogle = 'cibGoogle',
|
||||
cibLinkedin = 'cibLinkedin',
|
||||
cibSkype = 'cibSkype',
|
||||
cibTwitter = 'cibTwitter',
|
||||
cifBr = 'cifBr',
|
||||
cifEs = 'cifEs',
|
||||
cifFr = 'cifFr',
|
||||
cifIn = 'cifIn',
|
||||
cifPl = 'cifPl',
|
||||
cifUs = 'cifUs',
|
||||
cilAlignCenter = 'cilAlignCenter',
|
||||
cilAlignLeft = 'cilAlignLeft',
|
||||
cilAlignRight = 'cilAlignRight',
|
||||
cilApplicationsSettings = 'cilApplicationsSettings',
|
||||
cilArrowBottom = 'cilArrowBottom',
|
||||
cilArrowRight = 'cilArrowRight',
|
||||
cilArrowTop = 'cilArrowTop',
|
||||
cilBasket = 'cilBasket',
|
||||
cilBell = 'cilBell',
|
||||
cilBold = 'cilBold',
|
||||
cilBookmark = 'cilBookmark',
|
||||
cilCalculator = 'cilCalculator',
|
||||
cilCalendar = 'cilCalendar',
|
||||
cilChart = 'cilChart',
|
||||
cilChartPie = 'cilChartPie',
|
||||
cilCheck = 'cilCheck',
|
||||
cilChevronLeft = 'cilChevronLeft',
|
||||
cilChevronRight = 'cilChevronRight',
|
||||
cilCloudDownload = 'cilCloudDownload',
|
||||
cilCode = 'cilCode',
|
||||
cilCommentSquare = 'cilCommentSquare',
|
||||
cilCreditCard = 'cilCreditCard',
|
||||
cilCursor = 'cilCursor',
|
||||
cilDescription = 'cilDescription',
|
||||
cilDollar = 'cilDollar',
|
||||
cilDrop = 'cilDrop',
|
||||
cilEnvelopeClosed = 'cilEnvelopeClosed',
|
||||
cilEnvelopeOpen = 'cilEnvelopeOpen',
|
||||
cilFile = 'cilFile',
|
||||
cilHome = 'cilHome',
|
||||
cilInbox = 'cilInbox',
|
||||
cilIndentDecrease = 'cilIndentDecrease',
|
||||
cilIndentIncrease = 'cilIndentIncrease',
|
||||
cilItalic = 'cilItalic',
|
||||
cilJustifyCenter = 'cilJustifyCenter',
|
||||
cilLayers = 'cilLayers',
|
||||
cilList = 'cilList',
|
||||
cilListNumbered = 'cilListNumbered',
|
||||
cilLocationPin = 'cilLocationPin',
|
||||
cilLockLocked = 'cilLockLocked',
|
||||
cilMagnifyingGlass = 'cilMagnifyingGlass',
|
||||
cilMap = 'cilMap',
|
||||
cilMediaPlay = 'cilMediaPlay',
|
||||
cilMenu = 'cilMenu',
|
||||
cilMoon = 'cilMoon',
|
||||
cilNotes = 'cilNotes',
|
||||
cilOptions = 'cilOptions',
|
||||
cilPaperclip = 'cilPaperclip',
|
||||
cilPaperPlane = 'cilPaperPlane',
|
||||
cilPen = 'cilPen',
|
||||
cilPencil = 'cilPencil',
|
||||
cilPeople = 'cilPeople',
|
||||
cilPrint = 'cilPrint',
|
||||
cilPuzzle = 'cilPuzzle',
|
||||
cilReportSlash = 'cilReportSlash',
|
||||
cilSave = 'cilSave',
|
||||
cilSettings = 'cilSettings',
|
||||
cilShare = 'cilShare',
|
||||
cilShareAll = 'cilShareAll',
|
||||
cilShareBoxed = 'cilShareBoxed',
|
||||
cilSpeech = 'cilSpeech',
|
||||
cilSpeedometer = 'cilSpeedometer',
|
||||
cilSpreadsheet = 'cilSpreadsheet',
|
||||
cilStar = 'cilStar',
|
||||
cilSun = 'cilSun',
|
||||
cilTags = 'cilTags',
|
||||
cilTask = 'cilTask',
|
||||
cilTrash = 'cilTrash',
|
||||
cilUnderline = 'cilUnderline',
|
||||
cilUser = 'cilUser',
|
||||
cilUserFemale = 'cilUserFemale',
|
||||
cilUserFollow = 'cilUserFollow',
|
||||
cilUserUnfollow = 'cilUserUnfollow',
|
||||
cilExitToApp = 'cilExitToApp'
|
||||
}
|
28
src/app/providers/login_checker.ts
Normal file
28
src/app/providers/login_checker.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { dataProvider } from './mikrowizard/data';
|
||||
|
||||
@Injectable()
|
||||
export class loginChecker {
|
||||
private logged_in: boolean = false;
|
||||
private pinging: boolean = false;
|
||||
|
||||
constructor(private data_provider: dataProvider) {
|
||||
}
|
||||
public isLoggedIn(): boolean {
|
||||
return this.logged_in;
|
||||
}
|
||||
load() {
|
||||
var _self = this;
|
||||
return this.data_provider.isLoggedIn().then(result => {
|
||||
_self.logged_in = result;
|
||||
}).catch(err => {
|
||||
_self.logged_in = false;
|
||||
})
|
||||
}
|
||||
setStatus(status: boolean): void {
|
||||
this.logged_in = status;
|
||||
}
|
||||
setPinging(ping: boolean): void {
|
||||
this.pinging = ping;
|
||||
}
|
||||
}
|
86
src/app/providers/messaging.service.ts
Normal file
86
src/app/providers/messaging.service.ts
Normal file
|
@ -0,0 +1,86 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { AngularFireDatabase } from '@angular/fire/database';
|
||||
import { AngularFireAuth } from '@angular/fire/auth';
|
||||
import { AngularFireMessaging } from '@angular/fire/messaging';
|
||||
import { mergeMapTo } from 'rxjs/operators';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { BehaviorSubject } from 'rxjs'
|
||||
import { dataProvider } from './odoorpchttp/data';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
||||
@Injectable()
|
||||
export class MessagingService {
|
||||
|
||||
currentMessage = new BehaviorSubject(null);
|
||||
|
||||
constructor(
|
||||
private angularFireDB: AngularFireDatabase,
|
||||
private angularFireAuth: AngularFireAuth,
|
||||
private data_provider: dataProvider,
|
||||
private toastr: ToastrService,
|
||||
private angularFireMessaging: AngularFireMessaging,
|
||||
) {
|
||||
this.angularFireMessaging.messaging.subscribe(
|
||||
(_messaging) => {
|
||||
_messaging.onMessage = _messaging.onMessage.bind(_messaging);
|
||||
_messaging.onTokenRefresh = _messaging.onTokenRefresh.bind(_messaging);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* update token in firebase database
|
||||
*
|
||||
* @param userId userId as a key
|
||||
* @param token token as a value
|
||||
*/
|
||||
updateToken(userId, token) {
|
||||
// we can change this function to request our backend service
|
||||
this.angularFireAuth.authState.pipe(take(1)).subscribe(
|
||||
() => {
|
||||
const data = {};
|
||||
data[userId] = token
|
||||
this.angularFireDB.object('fcmTokens/').update(data)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* request permission for notification from firebase cloud messaging
|
||||
*
|
||||
* @param userId userId
|
||||
*/
|
||||
requestPermission(userId) {
|
||||
this.angularFireMessaging.requestToken.subscribe(
|
||||
(token) => {
|
||||
this.data_provider.update_FBC_token(token).then(result => {
|
||||
if(result.result!='success'){
|
||||
console.error('Unable to write token.');
|
||||
}
|
||||
});
|
||||
this.updateToken(userId, token);
|
||||
},
|
||||
(err) => {
|
||||
console.error('Unable to get permission to notify.', err);
|
||||
}
|
||||
);
|
||||
}
|
||||
shownotification(payload){
|
||||
if(typeof(payload) !== 'undefined'){
|
||||
if(document.visibilityState){
|
||||
this.toastr.warning(payload.notification.title, payload.notification.body,{
|
||||
disableTimeOut:true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* hook method when new notification received in foreground
|
||||
*/
|
||||
receiveMessage() {
|
||||
this.angularFireMessaging.messages.subscribe(
|
||||
(payload) => {
|
||||
this.shownotification(payload);
|
||||
this.currentMessage.next(payload);
|
||||
})
|
||||
}
|
||||
}
|
455
src/app/providers/mikrowizard/data.ts
Normal file
455
src/app/providers/mikrowizard/data.ts
Normal file
|
@ -0,0 +1,455 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
// import { MikroWizardrpcProvider } from '../MikroWizardrpc/MikroWizardrpc';
|
||||
import { MikroWizardProvider } from './provider';
|
||||
|
||||
|
||||
import { User } from './user';
|
||||
|
||||
@Injectable()
|
||||
export class dataProvider {
|
||||
|
||||
// public serverUrl: string = "/api";
|
||||
public serverUrl: string = "";
|
||||
private db: string = "NothingImportant";
|
||||
|
||||
constructor(
|
||||
// private http: HTTP,
|
||||
// public MikroWizardRPC: MikroWizardrpcProvider,
|
||||
public MikroWizardRPC: MikroWizardProvider,
|
||||
) {
|
||||
this.MikroWizardRPC.init({
|
||||
MikroWizard_server: this.serverUrl
|
||||
});
|
||||
}
|
||||
|
||||
isLoggedIn() {
|
||||
return this.MikroWizardRPC.isLoggedIn();
|
||||
}
|
||||
|
||||
login(username: string = "", password: string = "", ga: string = "") {
|
||||
var _self = this;
|
||||
this.MikroWizardRPC.clearCookeis();
|
||||
return this.MikroWizardRPC.login(this.db, username, password, ga).then(res => {
|
||||
if ('uid' in res && res['uid']) {
|
||||
let usr: User = new User(
|
||||
res.name,
|
||||
res.username,
|
||||
res.partner_id,
|
||||
res.uid,
|
||||
res.first_name,
|
||||
res.last_name,
|
||||
res.role,
|
||||
res.perms,
|
||||
res.tz,
|
||||
);
|
||||
// console.dir(JSON.stringify(usr))
|
||||
localStorage.setItem('current_user', JSON.stringify(usr));
|
||||
}
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
logout() {
|
||||
var _self = this;
|
||||
_self.MikroWizardRPC.clearCookeis();
|
||||
this.MikroWizardRPC.setNewSession('', '');
|
||||
localStorage.removeItem('current_user');
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/logout", {});
|
||||
}
|
||||
|
||||
////
|
||||
//// MikroWizard API
|
||||
////
|
||||
get_front_version(){
|
||||
return this.MikroWizardRPC.sendHttpGetRequest("/api/frontver/");
|
||||
}
|
||||
change_password(oldpass:string,newpass:string){
|
||||
var data={
|
||||
'oldpass':oldpass,
|
||||
'newpass':newpass
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/user/change_password", data);
|
||||
}
|
||||
dashboard_stats(versioncheck:boolean){
|
||||
var data={
|
||||
'versioncheck':versioncheck
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/dashboard/stats", data);
|
||||
}
|
||||
|
||||
dashboard_traffic(delta:string){
|
||||
var data={
|
||||
'delta':delta
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/dashboard/traffic", data);
|
||||
}
|
||||
|
||||
get_dev_list(data:any) {
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/dev/list", data);
|
||||
}
|
||||
|
||||
get_devgroup_list() {
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/devgroup/list", {});
|
||||
}
|
||||
|
||||
get_devgroup_members(gid:number) {
|
||||
var data={
|
||||
'gid':gid
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/devgroup/members", data);
|
||||
}
|
||||
delete_group(id:number){
|
||||
var data={
|
||||
'gid':id
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/devgroup/delete", data);
|
||||
}
|
||||
|
||||
delete_devices(devids:any){
|
||||
var data = {
|
||||
'devids':devids
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/dev/delete", data);
|
||||
}
|
||||
|
||||
get_dev_info(id: number) {
|
||||
var data={
|
||||
'devid':id
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/dev/info", data);
|
||||
}
|
||||
|
||||
get_editform(id: number) {
|
||||
var data={
|
||||
'devid':id
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/dev/get_editform", data);
|
||||
}
|
||||
save_editform(data:any){
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/dev/save_editform", data);
|
||||
}
|
||||
get_dev_sensors(id: number,delta:string="5m",total_type:string="bps") {
|
||||
var data={
|
||||
'devid':id,
|
||||
'delta':delta,
|
||||
'total':total_type
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/dev/sensors", data);
|
||||
}
|
||||
|
||||
get_dev_ifstat(id: number,delta:string="5m",iface:string="ether1",type:string="bps") {
|
||||
var data={
|
||||
'devid':id,
|
||||
'delta':delta,
|
||||
'type':type,
|
||||
'interface':iface
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/dev/ifstat", data);
|
||||
}
|
||||
|
||||
get_auth_logs(filters:any) {
|
||||
var data=filters;
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/auth/list", data);
|
||||
}
|
||||
|
||||
get_account_logs(filters:any) {
|
||||
var data=filters;
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/account/list", data);
|
||||
}
|
||||
|
||||
get_dev_logs(filters:any) {
|
||||
var data=filters;
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/devlogs/list", data);
|
||||
}
|
||||
|
||||
get_syslog(filters:any) {
|
||||
var data=filters;
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/syslog/list", data);
|
||||
}
|
||||
get_details_grouped(devid:number=0){
|
||||
var data={
|
||||
'devid':devid
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/devlogs/details/list", data);
|
||||
}
|
||||
|
||||
scan_devs(type:string,info:any){
|
||||
var data: any={
|
||||
'type':type
|
||||
}
|
||||
if(type=="ip"){
|
||||
data = Object.assign(data, info);
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/scanner/scan", data);
|
||||
}
|
||||
|
||||
get_groups(searchstr:string=""){
|
||||
var data={
|
||||
'searchstr':searchstr
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/search/groups", data);
|
||||
}
|
||||
|
||||
get_devices(searchstr:string=""){
|
||||
var data={
|
||||
'searchstr':searchstr
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/search/devices", data);
|
||||
}
|
||||
|
||||
update_save_group(group:any){
|
||||
var data={
|
||||
...group
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/devgroup/update_save_group", data);
|
||||
}
|
||||
|
||||
get_snippets(name:string,desc:string,content:string,page:number=0,size:number=1000){
|
||||
var data={
|
||||
'name':name,
|
||||
'description':desc,
|
||||
'content':content,
|
||||
'page':page,
|
||||
'size':size
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/snippet/list", data);
|
||||
}
|
||||
|
||||
save_snippet(data:any){
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/snippet/save", {...data});
|
||||
}
|
||||
|
||||
delete_snippet(id:number){
|
||||
var data={
|
||||
'id':id
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/snippet/delete", data);
|
||||
}
|
||||
|
||||
get_user_task_list() {
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/user_tasks/list", {});
|
||||
}
|
||||
|
||||
|
||||
Add_task(data:any,members:any) {
|
||||
data['members']=members;
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/user_tasks/create", data);
|
||||
}
|
||||
|
||||
Delete_task(taskid:Number) {
|
||||
var data={
|
||||
'taskid':taskid,
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/user_tasks/delete", data);
|
||||
}
|
||||
|
||||
Edit_task(data:any,members:any) {
|
||||
data['members']=members;
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/user_tasks/edit", data);
|
||||
}
|
||||
|
||||
get_task_members(taskid:Number) {
|
||||
var data={
|
||||
'taskid':taskid,
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/taskmember/details", data);
|
||||
}
|
||||
|
||||
|
||||
get_users(page:Number,size:Number,search:string) {
|
||||
var data={
|
||||
'page':page,
|
||||
'size':size,
|
||||
'search':search
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/users/list", data);
|
||||
}
|
||||
|
||||
get_perms(page:Number,size:Number,search:string) {
|
||||
var data={
|
||||
'page':page,
|
||||
'size':size,
|
||||
'search':search
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/perms/list", data);
|
||||
}
|
||||
|
||||
create_perm(name:string,perms:any) {
|
||||
var data={
|
||||
'name':name,
|
||||
'perms':perms
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/perms/create", data);
|
||||
}
|
||||
|
||||
edit_perm(id:Number,name:string,perms:any) {
|
||||
|
||||
var data = {
|
||||
'id':id,
|
||||
'name':name,
|
||||
'perms':perms
|
||||
}
|
||||
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/perms/edit", data);
|
||||
}
|
||||
|
||||
delete_perm(id:number){
|
||||
var data={
|
||||
'id':id
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/perms/delete", data);
|
||||
}
|
||||
|
||||
user_perms(uid:string) {
|
||||
|
||||
var data = {
|
||||
'uid':uid,
|
||||
}
|
||||
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/userperms/list", data);
|
||||
}
|
||||
|
||||
Add_user_perm(uid:Number,permid:Number,devgroupid:Number){
|
||||
|
||||
var data = {
|
||||
'uid':uid,
|
||||
'pid':permid,
|
||||
'gid':devgroupid
|
||||
}
|
||||
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/userperms/create", data);
|
||||
}
|
||||
Delete_user_perm(id:number){
|
||||
var data={
|
||||
'id':id
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/userperms/delete", data);
|
||||
}
|
||||
edit_user(data:any) {
|
||||
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/user/edit", data);
|
||||
}
|
||||
|
||||
create_user(data:any) {
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/user/create", data);
|
||||
}
|
||||
delete_user(id:number){
|
||||
var data={
|
||||
'uid':id
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/user/delete", data);
|
||||
}
|
||||
check_firmware(devids:any) {
|
||||
var data = {
|
||||
'devids':devids
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/firmware/check_firmware_update", data);
|
||||
}
|
||||
|
||||
get_firms(page:Number,size:Number,search:any) {
|
||||
var data = {
|
||||
'page':page,
|
||||
'size':size,
|
||||
'search':search
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/firmware/get_firms", data);
|
||||
}
|
||||
|
||||
get_backups(devid:Number=0,page:Number,size:Number,search:any) {
|
||||
var data = {
|
||||
'devid':devid,
|
||||
'page':page,
|
||||
'size':size,
|
||||
'search':search
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/backup/list", data);
|
||||
}
|
||||
|
||||
|
||||
get_backup(id:number){
|
||||
var data = {
|
||||
'id':id
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/backup/get", data);
|
||||
}
|
||||
|
||||
get_downloadable_firms() {
|
||||
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/firmware/get_downloadable_firms", {});
|
||||
}
|
||||
|
||||
download_firmware_to_repository(version:string){
|
||||
var data = {
|
||||
'version':version
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/firmware/download_firmware_to_repository", data);
|
||||
}
|
||||
|
||||
save_firmware_setting(updatebehavior:string,firmwaretoinstall:string,firmwaretoinstallv6:string){
|
||||
var data = {
|
||||
'updatebehavior':updatebehavior,
|
||||
'firmwaretoinstall':firmwaretoinstall,
|
||||
'firmwaretoinstallv6':firmwaretoinstallv6
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/firmware/update_firmware_settings", data);
|
||||
}
|
||||
|
||||
update_firmware(devids:string){
|
||||
var data = {
|
||||
'devids':devids
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/firmware/update_firmware", data);
|
||||
}
|
||||
|
||||
upgrade_firmware(devids:string){
|
||||
var data = {
|
||||
'devids':devids
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/firmware/upgrade_firmware", data);
|
||||
}
|
||||
|
||||
reboot_devices(devids:string){
|
||||
var data = {
|
||||
'devids':devids
|
||||
}
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/firmware/reboot_devices", data);
|
||||
}
|
||||
|
||||
get_settings(){
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/sysconfig/get_all", {});
|
||||
}
|
||||
|
||||
save_sys_setting(data:any){
|
||||
return this.MikroWizardRPC.sendJsonRequest("/api/sysconfig/save_all", data);
|
||||
}
|
||||
|
||||
|
||||
////
|
||||
//// End api funcs
|
||||
////
|
||||
setupSession(context: any, session: any) {
|
||||
this.MikroWizardRPC.clearCookeis();
|
||||
this.MikroWizardRPC.setNewSession(context, session);
|
||||
}
|
||||
|
||||
checkSessionExpired(error: any) {
|
||||
console.log(error);
|
||||
if ('title' in error && error.title == "session_expired")
|
||||
this.logout();
|
||||
return Promise.reject(error.message || error);
|
||||
}
|
||||
|
||||
|
||||
setSession(context: any, session_id: any) {
|
||||
this.MikroWizardRPC.setNewSession(context, session_id);
|
||||
}
|
||||
|
||||
getSessionInfo() {
|
||||
return this.MikroWizardRPC.getSessionInfo();
|
||||
}
|
||||
|
||||
getFullUrl(url: any) {
|
||||
return this.serverUrl + url;
|
||||
}
|
||||
}
|
209
src/app/providers/mikrowizard/provider.ts
Normal file
209
src/app/providers/mikrowizard/provider.ts
Normal file
|
@ -0,0 +1,209 @@
|
|||
import { Injectable, Inject } from '@angular/core';
|
||||
|
||||
import { HttpClient,HttpResponse } from '@angular/common/http';
|
||||
|
||||
class Cookies { // cookies doesn't work with Android default browser / Ionic
|
||||
private session_id: string = "";
|
||||
|
||||
delete_sessionId() {
|
||||
this.session_id = "";
|
||||
document.cookie = "";
|
||||
}
|
||||
|
||||
get_sessionId() {
|
||||
return document
|
||||
.cookie.split("; ")
|
||||
.filter(x => { return x.indexOf("session_id") === 0; })
|
||||
.map(x => { return x.split("=")[1]; })
|
||||
.pop() || this.session_id || "";
|
||||
}
|
||||
|
||||
set_sessionId(val: string) {
|
||||
// document.cookie = `session_id=${val}`;
|
||||
// this.session_id = val;
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class MikroWizardProvider {
|
||||
|
||||
private MikroWizard_server: string;
|
||||
private http_auth: string;
|
||||
private cookies: Cookies;
|
||||
private uniq_id_counter: number = 0;
|
||||
private shouldManageSessionId: boolean = false; // try without first
|
||||
private context: Object = {"lang": "en_US"};
|
||||
private headers: any;
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
this.cookies = new Cookies();
|
||||
}
|
||||
|
||||
private buildRequest(url: string, params: any) {
|
||||
this.uniq_id_counter += 1;
|
||||
if (this.shouldManageSessionId) {
|
||||
params.session_id = this.cookies.get_sessionId();
|
||||
}
|
||||
|
||||
this.headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Session-Id": this.cookies.get_sessionId(),
|
||||
"Authorization": "Basic " + btoa(`${this.http_auth}`)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
|
||||
private handleMikroWizardErrors(response: any) {
|
||||
//response = JSON.parse(response.data);
|
||||
if (!response.error) {
|
||||
if (typeof response.result === 'string' || response.result instanceof String)
|
||||
return JSON.parse(response.result);
|
||||
return response.result;
|
||||
}
|
||||
|
||||
let error = response.error;
|
||||
let errorObj = {
|
||||
title: " ",
|
||||
message: "",
|
||||
fullTrace: error
|
||||
};
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
private handleRequestErrors(response: any) {
|
||||
if (!response.error) {
|
||||
if (typeof response.result === 'string' || response.result instanceof String)
|
||||
return JSON.parse(response.result);
|
||||
return response.result;
|
||||
}
|
||||
|
||||
let error = response.error;
|
||||
let errorObj = {
|
||||
title: " ",
|
||||
message: "",
|
||||
fullTrace: error
|
||||
};
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
private handleHttpErrors(error: any) {
|
||||
try{
|
||||
console.log(error, Object.getOwnPropertyNames(error));
|
||||
}
|
||||
catch(e){
|
||||
console.log(error);
|
||||
}
|
||||
return Promise.reject(error.message || error);
|
||||
}
|
||||
|
||||
public init(configs: any) {
|
||||
this.MikroWizard_server = configs.MikroWizard_server;
|
||||
this.http_auth = configs.http_auth || null;
|
||||
}
|
||||
|
||||
public setMikroWizardServer(MikroWizard_server: string) {
|
||||
this.MikroWizard_server = MikroWizard_server;
|
||||
}
|
||||
|
||||
public setHttpAuth(http_auth: string) {
|
||||
this.http_auth = http_auth;
|
||||
}
|
||||
public sendRequestauth(url: string, params: Object){
|
||||
let body = this.buildRequest(url, params);
|
||||
console.dir(body);
|
||||
return this.http.post(this.MikroWizard_server + url, body, {observe: "response",headers: this.headers,withCredentials:true});
|
||||
}
|
||||
public sendRequest(url: string, params: Object): Promise<any> {
|
||||
let body = this.buildRequest(url, params);
|
||||
return this.http.post(this.MikroWizard_server + url, body, {headers: this.headers,withCredentials:true})
|
||||
.toPromise()
|
||||
.then((response: any) => this.handleMikroWizardErrors(response))
|
||||
.catch((response: any) => this.handleHttpErrors(response));
|
||||
}
|
||||
|
||||
public sendJsonRequest(url: string, params: Object) {
|
||||
let headers = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
return this.http.post(url, params,
|
||||
{headers:this.headers,withCredentials:true}
|
||||
).toPromise()
|
||||
.then(this.handleRequestErrors)
|
||||
.catch(this.handleHttpErrors);
|
||||
}
|
||||
|
||||
public sendHttpRequest(url: string, params: any) {
|
||||
let headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
};
|
||||
return this.http.post(this.MikroWizard_server + url, params,
|
||||
{headers:headers,withCredentials:true}
|
||||
).toPromise()
|
||||
.then(this.handleRequestErrors)
|
||||
.catch(this.handleHttpErrors);
|
||||
}
|
||||
public sendHttpGetRequest(url: string) {
|
||||
let headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
};
|
||||
return this.http.get( url,
|
||||
{ responseType: 'json' }
|
||||
).toPromise()
|
||||
}
|
||||
|
||||
public getServerInfo() {
|
||||
return this.sendRequest("/api/version_info", {});
|
||||
}
|
||||
|
||||
public getSessionInfo() {
|
||||
return this.sendRequest("/api/me", {});
|
||||
}
|
||||
//Set-Cookie
|
||||
public login(db: string, login: string, password: string, ga: string) {
|
||||
let params = {
|
||||
username : login,
|
||||
password : password,
|
||||
// token: token,
|
||||
ga: ga
|
||||
};
|
||||
let $this = this;
|
||||
return this.sendRequest("/api/login", params);
|
||||
}
|
||||
|
||||
public isLoggedIn() {
|
||||
return this.getSessionInfo().then(function(result: any) {
|
||||
// console.dir("result");
|
||||
console.dir(result);
|
||||
// return true;
|
||||
if ( "uid" in result === false ) return false;
|
||||
else return true;
|
||||
});
|
||||
}
|
||||
|
||||
public clearCookeis() {
|
||||
this.cookies = new Cookies();
|
||||
}
|
||||
|
||||
public logout() {
|
||||
this.clearCookeis();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public getUserContext(context: any) {
|
||||
localStorage.setItem("user_context", JSON.stringify(context));
|
||||
|
||||
}
|
||||
|
||||
public getContext() {
|
||||
return this.context;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public setNewSession(user_context: any, session_id: any) {
|
||||
this.context = user_context;
|
||||
localStorage.setItem("user_context", JSON.stringify(this.context));
|
||||
}
|
||||
}
|
21
src/app/providers/mikrowizard/user.ts
Normal file
21
src/app/providers/mikrowizard/user.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
export class User {
|
||||
name: string;
|
||||
username: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
partner_id: number;
|
||||
id: number;
|
||||
role: string;
|
||||
perms:any;
|
||||
tz:string;
|
||||
constructor(name: any, username: any, partner_id: any, user_id: any,firstname: any,lastname: any,role: any,perms:any,tz:string) { this.name = name;
|
||||
this.username = username;
|
||||
this.partner_id = partner_id;
|
||||
this.id = user_id;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.role = role;
|
||||
this.perms = perms;
|
||||
this.tz=tz;
|
||||
}
|
||||
}
|
20
src/app/views/acc_log/acc-routing.module.ts
Normal file
20
src/app/views/acc_log/acc-routing.module.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
|
||||
import { AccComponent } from "./acc.component";
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: "",
|
||||
component: AccComponent,
|
||||
data: {
|
||||
title: $localize`Accounting Logs`,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AccRoutingModule {}
|
112
src/app/views/acc_log/acc.component.html
Normal file
112
src/app/views/acc_log/acc.component.html
Normal file
|
@ -0,0 +1,112 @@
|
|||
<c-row>
|
||||
<c-col xs>
|
||||
<c-card class="mb-4">
|
||||
<c-card-header>
|
||||
<c-row>
|
||||
<c-col xs [lg]="11">
|
||||
Accunting Logs
|
||||
</c-col>
|
||||
<c-col xs [lg]="1">
|
||||
<button (click)="toggleCollapse()" cButton class="me-1" color="primary"><i
|
||||
class="fa-solid fa-filter mr-1"></i>Filter</button>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-card-header>
|
||||
<c-card-body>
|
||||
<c-row>
|
||||
<div [visible]="filters_visible" cCollapse>
|
||||
<c-col xs [lg]="12" class="example-form">
|
||||
<mat-form-field>
|
||||
<mat-label>Start date</mat-label>
|
||||
<input matInput [matDatepicker]="picker1" (dateChange)="reinitgrid('start',$event)"
|
||||
[(ngModel)]="filters['start_time']" />
|
||||
<mat-datepicker-toggle matIconSuffix [for]="picker1"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker1></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>End date</mat-label>
|
||||
<input matInput [matDatepicker]="picker2" (dateChange)="reinitgrid('end',$event)"
|
||||
[(ngModel)]="filters['end_time']" />
|
||||
<mat-datepicker-toggle matIconSuffix [for]="picker2"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker2></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Select section</mat-label>
|
||||
<mat-select placeholder="Event Section" (ngModelChange)="reinitgrid('section',$event)"
|
||||
[(ngModel)]="filters['section']" #multiSelect>
|
||||
<mat-option value="All">All</mat-option>
|
||||
<mat-option *ngFor="let sec of event_section " [value]="sec">
|
||||
{{sec}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Select action</mat-label>
|
||||
<mat-select placeholder="Event Section" (ngModelChange)="reinitgrid('action',$event)"
|
||||
[(ngModel)]="filters['action']" #multiSelect>
|
||||
<mat-option value="All">All</mat-option>
|
||||
<mat-option *ngFor="let ac of event_action" [value]="ac">
|
||||
{{ac}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Config</mat-label>
|
||||
<input (ngModelChange)="reinitgrid('config',$event)" [(ngModel)]="filters['config']" matInput>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>IP</mat-label>
|
||||
<input (ngModelChange)="reinitgrid('ip',$event)" [(ngModel)]="filters['ip']" matInput>
|
||||
</mat-form-field>
|
||||
</c-col>
|
||||
|
||||
</div>
|
||||
|
||||
</c-row>
|
||||
<gui-grid [rowDetail]="rowDetail" [source]="source" [columnMenu]="columnMenu" [paging]="paging"
|
||||
[sorting]="sorting" [infoPanel]="infoPanel" [autoResizeWidth]=true>
|
||||
<gui-grid-column header="#No" type="NUMBER" field="index" width=25 align="CENTER">
|
||||
<ng-template let-value="item.index" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Device Name" field="name">
|
||||
<ng-template let-value="item.name" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Device IP" field="devip">
|
||||
<ng-template let-value="item.devip" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Username" field="username">
|
||||
<ng-template let-value="item.username" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Action" field="action">
|
||||
<ng-template let-value="item.action" let-item="item" let-index="index">
|
||||
<div>{{value}}</div>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Section" field="section">
|
||||
<ng-template let-value="item.section" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Date" field="created">
|
||||
<ng-template let-value="item.created" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Message" field="message" [enabled]="false">
|
||||
<ng-template let-value="item.message" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
86
src/app/views/acc_log/acc.component.scss
Normal file
86
src/app/views/acc_log/acc.component.scss
Normal file
|
@ -0,0 +1,86 @@
|
|||
@use '@angular/material' as mat;
|
||||
|
||||
:host {
|
||||
.legend {
|
||||
small {
|
||||
font-size: x-small;
|
||||
}
|
||||
}
|
||||
}
|
||||
.gui-drawer-content{
|
||||
background-color: #efefef!important;
|
||||
|
||||
}
|
||||
.log-detail{
|
||||
padding:30px 10px;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
.log-detail h1{
|
||||
font-size:2em;
|
||||
font-weight:bold;
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
.log-detail small{
|
||||
position:relative;
|
||||
top:-7px;
|
||||
padding:0;
|
||||
font-weight:bold;
|
||||
font-size:1.1em;
|
||||
}
|
||||
.log-detail table {
|
||||
width: 100%;
|
||||
border-collapse: collapse!important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #fff!important;
|
||||
}
|
||||
.log-detail th {
|
||||
text-align: left;
|
||||
}
|
||||
.log-detail th,
|
||||
.log-detail td {
|
||||
border: 1px solid #dfdfdf!important;
|
||||
padding: 1rem!important;
|
||||
}
|
||||
|
||||
.log-detail code{
|
||||
padding:5px!important;
|
||||
display:block;
|
||||
background:#1d1f21;
|
||||
color:#c5c8c6;
|
||||
border-bottom-left-radius:3px;
|
||||
border-bottom-right-radius:3px;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.log-detail .code-title{
|
||||
background-color:#393e42!important;;
|
||||
width:100%;
|
||||
padding:2px 15px;
|
||||
display:inline-block;
|
||||
margin-top:10px;
|
||||
color:#d2d2d2;
|
||||
border-top-left-radius:3px;
|
||||
border-top-right-radius:3px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
|
||||
.example-form {
|
||||
@include mat.button-density(-5);
|
||||
|
||||
@include mat.form-field-density(-5);
|
||||
@include mat.button-toggle-density(-5);
|
||||
@include mat.datepicker-density(-5);
|
||||
@include mat.all-component-densities(-5);
|
||||
@include mat.icon-button-density(-5);
|
||||
@include mat.icon-density(-5);
|
||||
.mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) .mat-mdc-floating-label { display: inline; }
|
||||
mat-form-field *{
|
||||
font-size:13px!important;
|
||||
}
|
||||
.mat-mdc-form-field-infix{
|
||||
width:150px;
|
||||
}
|
||||
}
|
204
src/app/views/acc_log/acc.component.ts
Normal file
204
src/app/views/acc_log/acc.component.ts
Normal file
|
@ -0,0 +1,204 @@
|
|||
import { Component, OnInit, ViewEncapsulation } from "@angular/core";
|
||||
import { dataProvider } from "../../providers/mikrowizard/data";
|
||||
import { Router, ActivatedRoute } from "@angular/router";
|
||||
import { loginChecker } from "../../providers/login_checker";
|
||||
import {
|
||||
GuiRowDetail,
|
||||
GuiSelectedRow,
|
||||
GuiInfoPanel,
|
||||
GuiColumn,
|
||||
GuiColumnMenu,
|
||||
GuiPaging,
|
||||
GuiPagingDisplay,
|
||||
GuiRowSelectionMode,
|
||||
GuiRowSelection,
|
||||
GuiRowSelectionType,
|
||||
} from "@generic-ui/ngx-grid";
|
||||
import { formatInTimeZone } from "date-fns-tz";
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: "acc.component.html",
|
||||
styleUrls: ["acc.component.scss"],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class AccComponent implements OnInit {
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
public tz: string;
|
||||
public filterText: string;
|
||||
public filters: any = {
|
||||
devid: false,
|
||||
ip: "",
|
||||
command: "",
|
||||
user: false,
|
||||
state: "all",
|
||||
with: "all",
|
||||
start_time: false,
|
||||
end_time: false,
|
||||
};
|
||||
public filters_visible: boolean = false;
|
||||
public event_action: any = [];
|
||||
public event_section: any = [];
|
||||
|
||||
constructor(
|
||||
private data_provider: dataProvider,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
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 source: Array<any> = [];
|
||||
public columns: Array<GuiColumn> = [];
|
||||
public loading: boolean = true;
|
||||
public rows: any = [];
|
||||
public Selectedrows: any;
|
||||
public devid: number = 0;
|
||||
public sorting = {
|
||||
enabled: true,
|
||||
multiSorting: true,
|
||||
};
|
||||
rowDetail: GuiRowDetail = {
|
||||
enabled: true,
|
||||
template: (item) => {
|
||||
return `
|
||||
<div class='log-detail'>
|
||||
<h1>${item.name}</h1>
|
||||
<small>${item.devip}</small>
|
||||
<table>
|
||||
<tr>
|
||||
<td>User Address</td>
|
||||
<td>${item.address}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>User Name</td>
|
||||
<td>${item.username}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Connection Type</td>
|
||||
<td>${item.ctype}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Section</td>
|
||||
<td>${item.section}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Exec time</td>
|
||||
<td>${item.created}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="code-title">Executed Config</div>
|
||||
<code>
|
||||
${item.config}
|
||||
</code>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
reinitgrid(field: string, $event: any) {
|
||||
if (field == "start") this.filters["start_time"] = $event.target.value;
|
||||
else if (field == "end") this.filters["end_time"] = $event.target.value;
|
||||
else if (field == "ip") this.filters["ip"] = $event;
|
||||
else if (field == "section") this.filters["section"] = $event;
|
||||
else if (field == "config") this.filters["config"] = $event;
|
||||
else if (field == "action") this.filters["action"] = $event;
|
||||
this.initGridTable();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.devid = Number(this.route.snapshot.paramMap.get("devid"));
|
||||
if (this.devid > 0) {
|
||||
this.filters["devid"] = this.devid;
|
||||
}
|
||||
this.initGridTable();
|
||||
}
|
||||
OnDestroy(): void {}
|
||||
onSelectedRows(rows: Array<GuiSelectedRow>): void {
|
||||
this.rows = rows;
|
||||
this.Selectedrows = rows.map((m: GuiSelectedRow) => m.source.id);
|
||||
}
|
||||
|
||||
removefilter(filter: any) {
|
||||
delete this.filters[filter];
|
||||
this.initGridTable();
|
||||
}
|
||||
toggleCollapse(): void {
|
||||
this.filters_visible = !this.filters_visible;
|
||||
}
|
||||
logger(item: any) {
|
||||
console.dir(item);
|
||||
}
|
||||
|
||||
initGridTable(): void {
|
||||
var _self = this;
|
||||
this.data_provider.get_account_logs(this.filters).then((res) => {
|
||||
let index = 1;
|
||||
this.source = res.map((d: any) => {
|
||||
d.index = index;
|
||||
if (!_self.event_section.includes(d.section))
|
||||
_self.event_section.push(d.section);
|
||||
|
||||
if (!_self.event_action.includes(d.action))
|
||||
_self.event_action.push(d.action);
|
||||
d.created = formatInTimeZone(
|
||||
d.created.split(".")[0] + ".000Z",
|
||||
_self.tz,
|
||||
"yyyy-MM-dd HH:mm:ss XXX"
|
||||
);
|
||||
index += 1;
|
||||
return d;
|
||||
});
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
42
src/app/views/acc_log/acc.module.ts
Normal file
42
src/app/views/acc_log/acc.module.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
|
||||
import {
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
FormModule,
|
||||
GridModule,
|
||||
CollapseModule,
|
||||
} from "@coreui/angular";
|
||||
|
||||
import { AccRoutingModule } from "./acc-routing.module";
|
||||
import { AccComponent } from "./acc.component";
|
||||
import { GuiGridModule } from "@generic-ui/ngx-grid";
|
||||
|
||||
import { MatDatepickerModule } from "@angular/material/datepicker";
|
||||
import { MatInputModule } from "@angular/material/input";
|
||||
import { MatFormFieldModule } from "@angular/material/form-field";
|
||||
import { MatSelectModule } from "@angular/material/select";
|
||||
|
||||
import { FormsModule } from "@angular/forms";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
AccRoutingModule,
|
||||
CardModule,
|
||||
CommonModule,
|
||||
GridModule,
|
||||
FormsModule,
|
||||
ButtonModule,
|
||||
FormModule,
|
||||
ButtonModule,
|
||||
GuiGridModule,
|
||||
CollapseModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatDatepickerModule,
|
||||
MatSelectModule,
|
||||
],
|
||||
declarations: [AccComponent],
|
||||
})
|
||||
export class AccModule {}
|
21
src/app/views/auth_log/auth-routing.module.ts
Normal file
21
src/app/views/auth_log/auth-routing.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { AuthComponent } from './auth.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: AuthComponent,
|
||||
data: {
|
||||
title: $localize`Authentication Logs`
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AuthRoutingModule {
|
||||
}
|
142
src/app/views/auth_log/auth.component.html
Normal file
142
src/app/views/auth_log/auth.component.html
Normal file
|
@ -0,0 +1,142 @@
|
|||
<c-row>
|
||||
<c-col xs>
|
||||
<c-card class="mb-4">
|
||||
<c-card-header>
|
||||
<c-row>
|
||||
<c-col xs [lg]="11">
|
||||
Authentication Logs
|
||||
</c-col>
|
||||
<c-col xs [lg]="1">
|
||||
<button (click)="toggleCollapse()" cButton class="me-1" color="primary"><i
|
||||
class="fa-solid fa-filter mr-1"></i>Filter</button>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-card-header>
|
||||
<c-card-body>
|
||||
<c-row>
|
||||
<div [visible]="filters_visible" cCollapse>
|
||||
<c-col xs [lg]="12" class="example-form">
|
||||
<mat-form-field>
|
||||
<mat-label>Start date</mat-label>
|
||||
<input matInput [matDatepicker]="picker1" (dateChange)="reinitgrid('start',$event)"
|
||||
[(ngModel)]="filters['start_time']" />
|
||||
<mat-datepicker-toggle matIconSuffix [for]="picker1"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker1></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>End date</mat-label>
|
||||
<input matInput [matDatepicker]="picker2" (dateChange)="reinitgrid('end',$event)"
|
||||
[(ngModel)]="filters['end_time']" />
|
||||
<mat-datepicker-toggle matIconSuffix [for]="picker2"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker2></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Connection Type</mat-label>
|
||||
<mat-select placeholder="Connection Type" (ngModelChange)="reinitgrid('connection_type',$event)"
|
||||
[(ngModel)]="filters['connection_type']" #multiSelect>
|
||||
<mat-option value="All">All</mat-option>
|
||||
<mat-option *ngFor="let con of connection_types " [value]="con">
|
||||
{{con}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Select action</mat-label>
|
||||
<mat-select placeholder="State" (ngModelChange)="reinitgrid('state',$event)"
|
||||
[(ngModel)]="filters['state']" #multiSelect>
|
||||
<mat-option value="All">All</mat-option>
|
||||
<mat-option *ngFor="let ac of ['Logged In','Logged Out','Failed']" [value]="ac">
|
||||
{{ac}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field >
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>Server</mat-label>
|
||||
<mat-select placeholder="Server" (ngModelChange)="reinitgrid('server',$event)"
|
||||
[(ngModel)]="filters['server']" #multiSelect>
|
||||
<mat-option value="All">All</mat-option>
|
||||
<mat-option *ngFor="let ac of ['Local','Mikrowizard']" [value]="ac">
|
||||
{{ac}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field >
|
||||
<mat-form-field>
|
||||
<mat-label>Device IP</mat-label>
|
||||
<input (ngModelChange)="reinitgrid('devip',$event)" [(ngModel)]="filters['devip']" matInput>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>IP/MAC</mat-label>
|
||||
<input (ngModelChange)="reinitgrid('ip',$event)" [(ngModel)]="filters['ip']" matInput>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Username</mat-label>
|
||||
<input (ngModelChange)="reinitgrid('user',$event)" [(ngModel)]="filters['user']" matInput>
|
||||
</mat-form-field>
|
||||
</c-col>
|
||||
|
||||
</div>
|
||||
|
||||
</c-row>
|
||||
<gui-grid [source]="source" [paging]="paging" [columnMenu]="columnMenu" [sorting]="sorting"
|
||||
[infoPanel]="infoPanel" [autoResizeWidth]=true>
|
||||
<gui-grid-column header="#No" type="NUMBER" field="index" width=25 align="CENTER">
|
||||
<ng-template let-value="item.index" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Device Name" field="name">
|
||||
<ng-template let-value="item.name" let-item="item" let-index="index">
|
||||
<i *ngIf="item.stype=='local'" cTooltip="local user"
|
||||
style="color: rgb(255, 42, 0); margin-right: 3px;font-size: .7em;" class="fa-solid fa-user-tie"></i>
|
||||
<i *ngIf="item.stype=='radius'" cTooltip="Update failed"
|
||||
style="color: rgb(9, 97, 20); margin-right: 3px;font-size: .7em;" class="fa-solid fa-server"></i>
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Device IP" field="devip">
|
||||
<ng-template let-value="item.devip" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Username" field="username">
|
||||
<ng-template let-value="item.username" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="With" field="by">
|
||||
<ng-template let-value="item.by" let-item="item" let-index="index">
|
||||
<div>{{value}}</div>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="IP Address" field="ip">
|
||||
<ng-template let-value="item.ip" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
|
||||
<gui-grid-column header="Time/Msg" field="duration">
|
||||
<ng-template let-value="item.duration" let-item="item" let-index="index">
|
||||
<span *ngIf="item.ltype!='failed'">{{value}}</span>
|
||||
<span *ngIf="item.ltype=='failed'">{{item.message}}</span>
|
||||
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
|
||||
<gui-grid-column header="State" field="ltype" [width]="110">
|
||||
<ng-template let-value="item.ltype" let-item="item.id" let-index="index">
|
||||
<c-badge color="success" *ngIf="value=='loggedin'"> Logged In</c-badge>
|
||||
<c-badge color="warning" *ngIf="value=='loggedout'"> Logged Out</c-badge>
|
||||
<c-badge color="danger" *ngIf="value=='failed'"> Failed</c-badge>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Date" field="created">
|
||||
<ng-template let-value="item.created" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
36
src/app/views/auth_log/auth.component.scss
Normal file
36
src/app/views/auth_log/auth.component.scss
Normal file
|
@ -0,0 +1,36 @@
|
|||
|
||||
@use '@angular/material' as mat;
|
||||
// Plus imports for other components in your app.
|
||||
|
||||
// Include the common styles for Angular Material. We include this here so that you only
|
||||
// have to load a single css file for Angular Material in your app.
|
||||
// Be sure that you only ever include this mixin once!
|
||||
|
||||
// Include theme styles for core and each component used in your app.
|
||||
// Alternatively, you can import and @include the theme mixins for each component
|
||||
// that you are using.
|
||||
.example-form {
|
||||
@include mat.button-density(-5);
|
||||
|
||||
@include mat.form-field-density(-5);
|
||||
@include mat.button-toggle-density(-5);
|
||||
@include mat.datepicker-density(-5);
|
||||
@include mat.all-component-densities(-5);
|
||||
@include mat.icon-button-density(-5);
|
||||
@include mat.icon-density(-5);
|
||||
.mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) .mat-mdc-floating-label { display: inline; }
|
||||
mat-form-field *{
|
||||
font-size:13px!important;
|
||||
}
|
||||
.mat-mdc-form-field-infix{
|
||||
width:150px;
|
||||
}
|
||||
}
|
||||
|
||||
:host {
|
||||
.legend {
|
||||
small {
|
||||
font-size: x-small;
|
||||
}
|
||||
}
|
||||
}
|
222
src/app/views/auth_log/auth.component.ts
Normal file
222
src/app/views/auth_log/auth.component.ts
Normal file
|
@ -0,0 +1,222 @@
|
|||
import { Component, OnInit, ViewEncapsulation } from "@angular/core";
|
||||
import { dataProvider } from "../../providers/mikrowizard/data";
|
||||
import { Router, ActivatedRoute } from "@angular/router";
|
||||
import { loginChecker } from "../../providers/login_checker";
|
||||
import {
|
||||
GuiSelectedRow,
|
||||
GuiInfoPanel,
|
||||
GuiColumn,
|
||||
GuiColumnMenu,
|
||||
GuiPaging,
|
||||
GuiPagingDisplay,
|
||||
GuiRowSelectionMode,
|
||||
GuiRowSelection,
|
||||
GuiRowSelectionType,
|
||||
} from "@generic-ui/ngx-grid";
|
||||
import { formatInTimeZone } from "date-fns-tz";
|
||||
|
||||
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: "auth.component.html",
|
||||
styleUrls: ["auth.component.scss"],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class AuthComponent implements OnInit {
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
public tz: string = "UTC";
|
||||
public filterText: string;
|
||||
public devid: number = 0;
|
||||
public filters: any = {
|
||||
devid: false,
|
||||
ip: "",
|
||||
devip: "",
|
||||
user: "",
|
||||
state: "All",
|
||||
server: "All",
|
||||
connection_type: "All",
|
||||
start_time: false,
|
||||
end_time: false,
|
||||
};
|
||||
public filters_visible: boolean = false;
|
||||
public connection_types: any = [];
|
||||
|
||||
constructor(
|
||||
private data_provider: dataProvider,
|
||||
private router: Router,
|
||||
private login_checker: loginChecker,
|
||||
private route: ActivatedRoute
|
||||
) {
|
||||
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 source: Array<any> = [];
|
||||
public columns: Array<GuiColumn> = [];
|
||||
public loading: boolean = true;
|
||||
public rows: any = [];
|
||||
public Selectedrows: any;
|
||||
|
||||
public sorting = {
|
||||
enabled: true,
|
||||
multiSorting: true,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
reinitgrid(field: string, $event: any) {
|
||||
if (field == "start") this.filters["start_time"] = $event.target.value;
|
||||
else if (field == "end") this.filters["end_time"] = $event.target.value;
|
||||
else if (field == "ip") this.filters["ip"] = $event;
|
||||
else if (field == "devip") this.filters["devip"] = $event;
|
||||
else if (field == "user") this.filters["user"] = $event;
|
||||
else if (field == "connection_type")
|
||||
this.filters["connection_type"] = $event;
|
||||
else if (field == "state") this.filters["state"] = $event;
|
||||
else if (field == "server") this.filters["server"] = $event;
|
||||
this.initGridTable();
|
||||
}
|
||||
secondsToString(seconds: number) {
|
||||
var years = Math.floor(seconds / 31536000);
|
||||
var max = 2;
|
||||
var current = 0;
|
||||
var str = "";
|
||||
if (years && current < max) {
|
||||
str += years + "y ";
|
||||
current++;
|
||||
}
|
||||
var days = Math.floor((seconds %= 31536000) / 86400);
|
||||
if (days && current < max) {
|
||||
str += days + "d ";
|
||||
current++;
|
||||
}
|
||||
var hours = Math.floor((seconds %= 86400) / 3600);
|
||||
if (hours && current < max) {
|
||||
str += hours + "h ";
|
||||
current++;
|
||||
}
|
||||
var minutes = Math.floor((seconds %= 3600) / 60);
|
||||
if (minutes && current < max) {
|
||||
str += minutes + "m ";
|
||||
current++;
|
||||
}
|
||||
var seconds = seconds % 60;
|
||||
if (seconds && current < max) {
|
||||
str += seconds + "s ";
|
||||
current++;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
ngOnInit(): void {
|
||||
this.devid = Number(this.route.snapshot.paramMap.get("devid"));
|
||||
if (this.devid > 0) {
|
||||
this.filters["devid"] = this.devid;
|
||||
}
|
||||
this.initGridTable();
|
||||
}
|
||||
onSelectedRows(rows: Array<GuiSelectedRow>): void {
|
||||
this.rows = rows;
|
||||
this.Selectedrows = rows.map((m: GuiSelectedRow) => m.source.id);
|
||||
}
|
||||
|
||||
removefilter(filter: any) {
|
||||
delete this.filters[filter];
|
||||
this.initGridTable();
|
||||
}
|
||||
toggleCollapse(): void {
|
||||
this.filters_visible = !this.filters_visible;
|
||||
}
|
||||
logger(item: any) {
|
||||
console.dir(item);
|
||||
}
|
||||
|
||||
initGridTable(): void {
|
||||
var _self = this;
|
||||
this.data_provider.get_auth_logs(this.filters).then((res) => {
|
||||
let index = 1;
|
||||
this.source = res.map((d: any) => {
|
||||
d.index = index;
|
||||
if (!_self.connection_types.includes(d.by))
|
||||
_self.connection_types.push(d.by);
|
||||
|
||||
if (!d.sessionid) {
|
||||
d.stype = "local";
|
||||
d.duration = "Local Access";
|
||||
} else {
|
||||
d.stype = "radius";
|
||||
if (d.ended != 0) {
|
||||
d.duration = _self.secondsToString(d.ended - d.started);
|
||||
} else {
|
||||
d.duration = "live";
|
||||
}
|
||||
}
|
||||
d.created = formatInTimeZone(
|
||||
d.created.split(".")[0] + ".000Z",
|
||||
_self.tz,
|
||||
"yyyy-MM-dd HH:mm:ss XXX"
|
||||
);
|
||||
index += 1;
|
||||
return d;
|
||||
});
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
41
src/app/views/auth_log/auth.module.ts
Normal file
41
src/app/views/auth_log/auth.module.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import {
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
GridModule,
|
||||
CollapseModule,
|
||||
BadgeModule,
|
||||
} from '@coreui/angular';
|
||||
import { AuthRoutingModule } from './auth-routing.module';
|
||||
import { AuthComponent } from './auth.component';
|
||||
import { GuiGridModule } from '@generic-ui/ngx-grid';
|
||||
|
||||
import { faCoffee } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import {MatDatepickerModule} from '@angular/material/datepicker';
|
||||
import {MatInputModule} from '@angular/material/input';
|
||||
import {MatFormFieldModule} from '@angular/material/form-field';
|
||||
import {MatSelectModule} from '@angular/material/select';
|
||||
@NgModule({
|
||||
imports: [
|
||||
AuthRoutingModule,
|
||||
CardModule,
|
||||
CommonModule,
|
||||
GridModule,
|
||||
FormsModule,
|
||||
ButtonModule,
|
||||
GuiGridModule,
|
||||
CollapseModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatDatepickerModule,
|
||||
MatSelectModule,
|
||||
BadgeModule
|
||||
],
|
||||
declarations: [AuthComponent]
|
||||
})
|
||||
export class AuthModule {
|
||||
}
|
21
src/app/views/backups/backups-routing.module.ts
Normal file
21
src/app/views/backups/backups-routing.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { BackupsComponent } from './backups.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: BackupsComponent,
|
||||
data: {
|
||||
title: $localize`Backups`
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class BackupsRoutingModule {
|
||||
}
|
68
src/app/views/backups/backups.component.html
Normal file
68
src/app/views/backups/backups.component.html
Normal file
|
@ -0,0 +1,68 @@
|
|||
<c-row>
|
||||
<c-col xs>
|
||||
<c-card class="mb-4">
|
||||
<c-card-header>Backups</c-card-header>
|
||||
<c-card-body>
|
||||
<c-badge color="warning" *ngIf="devid!=0">Filtered Result For Device ID {{devid}}</c-badge>
|
||||
|
||||
<gui-grid [source]="source" [searching]="searching" [paging]="paging" [columnMenu]="columnMenu"
|
||||
[sorting]="sorting" [infoPanel]="infoPanel" [columnMenu]="columnMenu" [sorting]="sorting"
|
||||
[infoPanel]="infoPanel" [autoResizeWidth]=true>
|
||||
<gui-grid-column header="#No" type="NUMBER" field="index" width=25 align="CENTER">
|
||||
<ng-template let-value="item.index" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Device Name" field="devname">
|
||||
<ng-template let-value="item.devname" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Device IP" field="devip">
|
||||
<ng-template let-value="item.devip" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="backup Time" field="createdC">
|
||||
<ng-template let-value="item.createdC" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="File Size" field="filesize">
|
||||
<ng-template let-value="item.filesize" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="MAC" field="devmac" [enabled]="false">
|
||||
<ng-template let-value="item.devmac" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Action" field="id">
|
||||
<ng-template let-value="item.id" let-item="item" let-index="index">
|
||||
<button cButton color="info" size="sm" (click)="ShowBackup(item.id)" class="mx-1"><i
|
||||
style="margin: 1px 5px;color:#ffffff;" class="fa-solid fa-eye"></i>Show backup</button>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
||||
|
||||
<c-modal #BakcupModal backdrop="static" [(visible)]="BakcupModalVisible" id="BakcupModal" size="xl">
|
||||
<c-modal-header>
|
||||
<h6 cModalTitle>Please Confirm Action </h6>
|
||||
<button [cModalToggle]="BakcupModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
<pre>
|
||||
<code *ngIf="!loading" language="properties" style="height:70vh" [highlight]="codeForHighlightAuto"
|
||||
lineNumbers></code></pre>
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<button [cModalToggle]="BakcupModal.id" cButton color="info">
|
||||
Close
|
||||
</button>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
0
src/app/views/backups/backups.component.scss
Normal file
0
src/app/views/backups/backups.component.scss
Normal file
153
src/app/views/backups/backups.component.ts
Normal file
153
src/app/views/backups/backups.component.ts
Normal file
|
@ -0,0 +1,153 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import { dataProvider } from "../../providers/mikrowizard/data";
|
||||
import { Router, ActivatedRoute } from "@angular/router";
|
||||
import { loginChecker } from "../../providers/login_checker";
|
||||
import {
|
||||
GuiSearching,
|
||||
GuiInfoPanel,
|
||||
GuiColumn,
|
||||
GuiColumnMenu,
|
||||
GuiPaging,
|
||||
GuiPagingDisplay,
|
||||
GuiRowSelectionMode,
|
||||
GuiRowSelection,
|
||||
GuiRowSelectionType,
|
||||
} from "@generic-ui/ngx-grid";
|
||||
import { formatInTimeZone } from "date-fns-tz";
|
||||
|
||||
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: "backups.component.html",
|
||||
})
|
||||
export class BackupsComponent implements OnInit {
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
public tz: string = "UTC";
|
||||
public filterText: string;
|
||||
public filters: any = {};
|
||||
public codeForHighlightAuto: string = "";
|
||||
|
||||
constructor(
|
||||
private data_provider: dataProvider,
|
||||
private router: Router,
|
||||
private login_checker: loginChecker,
|
||||
private route: ActivatedRoute
|
||||
) {
|
||||
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 source: Array<any> = [];
|
||||
public columns: Array<GuiColumn> = [];
|
||||
public loading: boolean = true;
|
||||
public rows: any = [];
|
||||
public Selectedrows: any;
|
||||
public BakcupModalVisible: boolean = false;
|
||||
public devid: number = 0;
|
||||
|
||||
public sorting = {
|
||||
enabled: true,
|
||||
multiSorting: true,
|
||||
};
|
||||
searching: GuiSearching = {
|
||||
enabled: true,
|
||||
placeholder: "Search Devices",
|
||||
};
|
||||
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,
|
||||
};
|
||||
|
||||
ngOnInit(): void {
|
||||
this.devid = Number(this.route.snapshot.paramMap.get("devid"));
|
||||
this.initGridTable();
|
||||
}
|
||||
|
||||
logger(item: any) {
|
||||
console.dir(item);
|
||||
}
|
||||
|
||||
ShowBackup(id: number) {
|
||||
this.BakcupModalVisible = true;
|
||||
this.loading = true;
|
||||
this.data_provider.get_backup(id).then((res) => {
|
||||
this.codeForHighlightAuto = res.content;
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
initGridTable(): void {
|
||||
var _self=this;
|
||||
this.data_provider.get_backups(this.devid, 0, 0, false).then((res) => {
|
||||
let index = 1;
|
||||
this.source = res.map((d: any) => {
|
||||
d.index = index;
|
||||
d.createdC = formatInTimeZone(
|
||||
d.created.split(".")[0] + ".000Z",
|
||||
_self.tz,
|
||||
"yyyy-MM-dd HH:mm:ss XXX"
|
||||
);
|
||||
// d.created = [d.created.split("T")[0],d.created.split("T")[1].split(".")[0]].join(" ")
|
||||
index += 1;
|
||||
return d;
|
||||
});
|
||||
console.dir(this.source);
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
36
src/app/views/backups/backups.module.ts
Normal file
36
src/app/views/backups/backups.module.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Highlight, HighlightAuto } from "ngx-highlightjs";
|
||||
import { HighlightLineNumbers } from "ngx-highlightjs/line-numbers";
|
||||
|
||||
import {
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
GridModule,
|
||||
CollapseModule,
|
||||
BadgeModule,
|
||||
ModalModule,
|
||||
} from "@coreui/angular";
|
||||
import { BackupsRoutingModule } from "./backups-routing.module";
|
||||
import { BackupsComponent } from "./backups.component";
|
||||
import { GuiGridModule } from "@generic-ui/ngx-grid";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BackupsRoutingModule,
|
||||
CardModule,
|
||||
CommonModule,
|
||||
GridModule,
|
||||
ButtonModule,
|
||||
ButtonModule,
|
||||
GuiGridModule,
|
||||
CollapseModule,
|
||||
BadgeModule,
|
||||
Highlight,
|
||||
HighlightAuto,
|
||||
HighlightLineNumbers,
|
||||
ModalModule,
|
||||
],
|
||||
declarations: [BackupsComponent],
|
||||
})
|
||||
export class BackupsModule {}
|
21
src/app/views/dashboard/dashboard-routing.module.ts
Normal file
21
src/app/views/dashboard/dashboard-routing.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: DashboardComponent,
|
||||
data: {
|
||||
title: $localize`Dashboard`
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class DashboardRoutingModule {
|
||||
}
|
168
src/app/views/dashboard/dashboard.component.html
Normal file
168
src/app/views/dashboard/dashboard.component.html
Normal file
|
@ -0,0 +1,168 @@
|
|||
<c-row *ngIf="stats">
|
||||
<c-col xs>
|
||||
<c-card *ngIf="stats" class="mb-1">
|
||||
<c-card-header>Past 24 Hour Statics</c-card-header>
|
||||
<c-card-body>
|
||||
<c-row>
|
||||
<c-col md="12" xl="12" xs="12">
|
||||
<c-row>
|
||||
<c-col class="mb-sm-1 mb-0">
|
||||
<c-widget-stat-f [title]="'Failed Logins'" class="mb-1" color="danger" padding
|
||||
value="{{stats['FailedLogins']}}">
|
||||
<ng-template cTemplateId="widgetIconTemplate">
|
||||
<i style="font-size: 2em;" class="fa-solid fa-person-circle-exclamation"></i>
|
||||
</ng-template>
|
||||
</c-widget-stat-f>
|
||||
</c-col>
|
||||
<c-col class="mb-sm-1 mb-0">
|
||||
<c-widget-stat-f [title]="'Success Logins'" class="mb-1" color="success" padding
|
||||
value="{{stats['SuccessfulLogins']}}">
|
||||
<ng-template cTemplateId="widgetIconTemplate">
|
||||
<i style="font-size: 2em;" class="fa-solid fa-arrow-right-to-bracket"></i>
|
||||
</ng-template>
|
||||
</c-widget-stat-f>
|
||||
</c-col>
|
||||
<c-col class="mb-sm-1 mb-0">
|
||||
<c-widget-stat-f [title]="'Critical Events'" class="mb-1" color="danger" padding
|
||||
value="{{stats['Critical']}}">
|
||||
<ng-template cTemplateId="widgetIconTemplate">
|
||||
<i style="font-size: 2em;" class="fa-solid fa-skull-crossbones"></i>
|
||||
</ng-template>
|
||||
</c-widget-stat-f>
|
||||
</c-col>
|
||||
<c-col class="mb-sm-1 mb-0">
|
||||
<c-widget-stat-f [title]="'Warning Events'" class="mb-1" color="warning" padding
|
||||
value="{{stats['Warning']}}">
|
||||
<ng-template cTemplateId="widgetIconTemplate">
|
||||
<i style="font-size: 2em;" class="fa-solid fa-triangle-exclamation"></i>
|
||||
</ng-template>
|
||||
</c-widget-stat-f>
|
||||
</c-col>
|
||||
<c-col class="mb-sm-1 mb-0">
|
||||
<c-widget-stat-f [title]="'Info Events'" class="mb-1" color="info" padding value="{{stats['Info']}}">
|
||||
<ng-template cTemplateId="widgetIconTemplate">
|
||||
<i style="font-size: 2em;" class="fa-solid fa-circle-info"></i>
|
||||
</ng-template>
|
||||
</c-widget-stat-f>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-card-body>
|
||||
<c-card-footer class="pb-0">
|
||||
<c-col xs>
|
||||
<c-row>
|
||||
<c-col md="12" xl="12" xs="12">
|
||||
<c-row>
|
||||
<c-col class="mb-0 pb-0">
|
||||
<div class="border-start border-start-4 border-start-info pt-1 px-3 mb-1">
|
||||
<div class="text-medium-emphasis small">Total users</div>
|
||||
<div class="fs-6 fw-semibold">{{stats['Users']}}</div>
|
||||
</div>
|
||||
</c-col>
|
||||
<c-col class="mb-0 pb-0">
|
||||
<div class="border-start border-start-4 border-start-warning pt-1 px-3 mb-1">
|
||||
<div class="text-medium-emphasis small">Total Devices</div>
|
||||
<div class="fs-6 fw-semibold">{{stats['Devices']}}</div>
|
||||
</div>
|
||||
</c-col>
|
||||
<c-col class="mb-0 pb-0">
|
||||
<div class="border-start border-start-4 border-start-success pt-1 px-3 mb-1">
|
||||
<div class="text-medium-emphasis small">Total Events</div>
|
||||
<div class="fs-6 fw-semibold">{{stats['Events']}}</div>
|
||||
</div>
|
||||
</c-col>
|
||||
<c-col class="mb-0 pb-0">
|
||||
<div class="border-start border-start-4 border-start-success pt-1 px-3 mb-1">
|
||||
<div class="text-medium-emphasis small">Total Auth Logs</div>
|
||||
<div class="fs-6 fw-semibold">{{stats['Auth']}}</div>
|
||||
</div>
|
||||
</c-col>
|
||||
<c-col class="mb-0 pb-0">
|
||||
<div class="border-start border-start-4 border-start-success pt-1 px-3 mb-1">
|
||||
<div class="text-medium-emphasis small">Total Acc Logs</div>
|
||||
<div class="fs-6 fw-semibold">{{stats['Acc']}}</div>
|
||||
</div>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-col>
|
||||
</c-card-footer>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
||||
|
||||
<c-card class="mb-1">
|
||||
<c-card-body>
|
||||
<c-row>
|
||||
<c-col sm="5">
|
||||
<h4 class="card-title mb-0" id="traffic">Total Devices Traffic</h4>
|
||||
</c-col>
|
||||
<c-col class="d-none d-md-block" sm="7">
|
||||
<form [formGroup]="trafficRadioGroup">
|
||||
<c-button-group class="float-end me-3" role="group">
|
||||
<input class="btn-check" formControlName="trafficRadio" type="radio" value="5m" />
|
||||
<label (click)="setTrafficPeriod('5m')" cButton cFormCheckLabel color="secondary" variant="outline">5
|
||||
Minues</label>
|
||||
|
||||
<input class="btn-check" formControlName="trafficRadio" type="radio" value="1h" />
|
||||
<label (click)="setTrafficPeriod('1h')" cButton cFormCheckLabel color="secondary"
|
||||
variant="outline">Hourly</label>
|
||||
|
||||
<input class="btn-check" formControlName="trafficRadio" type="radio" value="daily" />
|
||||
<label (click)="setTrafficPeriod('daily')" cButton cFormCheckLabel color="secondary"
|
||||
variant="outline">Daily</label>
|
||||
<input class="btn-check" formControlName="trafficRadio" type="radio" value="live" />
|
||||
<label (click)="setTrafficPeriod('live')" cButton cFormCheckLabel color="secondary"
|
||||
variant="outline">Live</label>
|
||||
</c-button-group>
|
||||
</form>
|
||||
</c-col>
|
||||
</c-row>
|
||||
<c-chart [data]="chart_data" [options]="options" [height]="200" type="line">
|
||||
</c-chart>
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
<c-row>
|
||||
<c-col xl="6" *ngIf="stats" lg="12" class="h-100">
|
||||
<c-widget-stat-b [title]="stats['version']" class="mb-1 h-100" value="Version">
|
||||
<div class="my-1">
|
||||
<code style="padding: 0!important;">Serial:</code> <small
|
||||
style="background-color: #ccc;padding: 5px;border-radius: 5px;cursor: pointer;" (click)="copy_this()"
|
||||
[cdkCopyToClipboard]="stats['serial']">{{ stats['serial'] }}</small>
|
||||
<span *ngIf="copy_msg" style="color: #fff!important;" class="badge text-bg-success mx-1"><i
|
||||
class="fa-solid fa-check"></i>Copy</span>
|
||||
</div>
|
||||
<div *ngIf="!stats['license']" class="my-1">
|
||||
<c-badge color="danger">Not Registred</c-badge>
|
||||
<a class="mx-1" target="_blank" href="http://MikroWizard.com">Learn how to register and get automatic
|
||||
updates!</a>
|
||||
</div>
|
||||
<div *ngIf="stats['license']" class="my-1">
|
||||
<c-badge color="success">Registred</c-badge>
|
||||
<c-badge class="mx-1" color="info">License Type : {{stats['license']}}</c-badge>
|
||||
</div>
|
||||
</c-widget-stat-b>
|
||||
</c-col>
|
||||
|
||||
<c-col xl="6" lg="12" class="h-100">
|
||||
<c-card class="mb-1 p-1 h-100" *ngIf="stats">
|
||||
<c-carousel [dark]="true" [animate]="false" [wrap]="false" [interval]="1000000">
|
||||
<c-carousel-indicators></c-carousel-indicators>
|
||||
<c-carousel-inner>
|
||||
<c-carousel-item style="display: flex;" *ngFor="let slide of stats['blog']; index as i;">
|
||||
<img [src]="slide.media_content" alt="{{slide.title}}" class="d-block" loading="lazy" style=" float: left;"
|
||||
height="150px" />
|
||||
<div style="padding: 20px;">
|
||||
<h5>{{slide.title}}</h5>
|
||||
<p style="max-width: 90%;" [innerHTML]="slide.summery"></p>
|
||||
</div>
|
||||
</c-carousel-item>
|
||||
</c-carousel-inner>
|
||||
<c-carousel-control [routerLink] caption="Previous" direction="prev"></c-carousel-control>
|
||||
<c-carousel-control [routerLink] caption="Next" direction="next"></c-carousel-control>
|
||||
</c-carousel>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
217
src/app/views/dashboard/dashboard.component.ts
Normal file
217
src/app/views/dashboard/dashboard.component.ts
Normal file
|
@ -0,0 +1,217 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import { UntypedFormControl, UntypedFormGroup } from "@angular/forms";
|
||||
import { dataProvider } from "../../providers/mikrowizard/data";
|
||||
import { loginChecker } from "../../providers/login_checker";
|
||||
import { Router } from "@angular/router";
|
||||
import { formatInTimeZone } from "date-fns-tz";
|
||||
|
||||
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: "dashboard.component.html",
|
||||
})
|
||||
export class DashboardComponent implements OnInit {
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
public tz: string;
|
||||
public copy_msg: any = false;
|
||||
constructor(
|
||||
private data_provider: dataProvider,
|
||||
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;
|
||||
});
|
||||
//get datagrid data
|
||||
function isNotEmpty(value: any): boolean {
|
||||
return value !== undefined && value !== null && value !== "";
|
||||
}
|
||||
}
|
||||
|
||||
public trafficRadioGroup = new UntypedFormGroup({
|
||||
trafficRadio: new UntypedFormControl("5m"),
|
||||
});
|
||||
public chart_data: any = {};
|
||||
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)",
|
||||
backgroundColor: "transparent",
|
||||
borderColor: "#f86c6b",
|
||||
pointHoverBackgroundColor: "#f86c6b",
|
||||
borderWidth: 1,
|
||||
borderDash: [8, 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, 82, 47, 0.3)",
|
||||
backgroundColor: "transparent",
|
||||
borderColor: "#f86c6b",
|
||||
pointHoverBackgroundColor: "#f86c6b",
|
||||
borderWidth: 1,
|
||||
borderDash: [8, 5],
|
||||
},
|
||||
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: 2,
|
||||
hitRadius: 10,
|
||||
hoverRadius: 6,
|
||||
},
|
||||
},
|
||||
};
|
||||
public options: any;
|
||||
public delta: string = "5m";
|
||||
public stats: any = false;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.options = this.Chartoptions;
|
||||
this.initStats();
|
||||
this.initTrafficChart();
|
||||
}
|
||||
|
||||
initTrafficChart(): void {
|
||||
var _self = this;
|
||||
this.data_provider.dashboard_traffic(this.delta).then((res) => {
|
||||
let labels = res["data"]["labels"].map((d: any) => {
|
||||
return (d = formatInTimeZone(
|
||||
d.split(".")[0] + ".000Z",
|
||||
_self.tz,
|
||||
"yyyy-MM-dd HH:mm:ss"
|
||||
));
|
||||
});
|
||||
_self.chart_data = { datasets: res["data"]["datasets"], labels: labels };
|
||||
});
|
||||
}
|
||||
initStats() {
|
||||
var _self = this;
|
||||
this.data_provider.dashboard_stats(true).then((res) => {
|
||||
console.dir(res);
|
||||
_self.stats = res;
|
||||
});
|
||||
}
|
||||
|
||||
copy_this() {
|
||||
//show text copy to clipboard for 3 seconds
|
||||
this.copy_msg = true;
|
||||
setTimeout(() => {
|
||||
this.copy_msg = false;
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// Traffic Chart
|
||||
setTrafficPeriod(value: string): void {
|
||||
this.trafficRadioGroup.setValue({ trafficRadio: value });
|
||||
this.delta = value;
|
||||
this.initTrafficChart();
|
||||
}
|
||||
}
|
43
src/app/views/dashboard/dashboard.module.ts
Normal file
43
src/app/views/dashboard/dashboard.module.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { ReactiveFormsModule } from "@angular/forms";
|
||||
|
||||
import {
|
||||
ButtonGroupModule,
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
GridModule,
|
||||
WidgetModule,
|
||||
ProgressModule,
|
||||
TemplateIdDirective,
|
||||
BadgeModule,
|
||||
CarouselModule,
|
||||
} from "@coreui/angular";
|
||||
|
||||
import { ChartjsModule } from "@coreui/angular-chartjs";
|
||||
|
||||
import { DashboardRoutingModule } from "./dashboard-routing.module";
|
||||
import { DashboardComponent } from "./dashboard.component";
|
||||
import { ClipboardModule } from "@angular/cdk/clipboard";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
DashboardRoutingModule,
|
||||
CardModule,
|
||||
WidgetModule,
|
||||
CommonModule,
|
||||
GridModule,
|
||||
ProgressModule,
|
||||
ReactiveFormsModule,
|
||||
ButtonModule,
|
||||
TemplateIdDirective,
|
||||
ButtonModule,
|
||||
ButtonGroupModule,
|
||||
ChartjsModule,
|
||||
CarouselModule,
|
||||
BadgeModule,
|
||||
ClipboardModule,
|
||||
],
|
||||
declarations: [DashboardComponent],
|
||||
})
|
||||
export class DashboardModule {}
|
21
src/app/views/device_detail/device-routing.module.ts
Normal file
21
src/app/views/device_detail/device-routing.module.ts
Normal 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 {
|
||||
}
|
167
src/app/views/device_detail/device.component.html
Normal file
167
src/app/views/device_detail/device.component.html
Normal 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>
|
7
src/app/views/device_detail/device.component.scss
Normal file
7
src/app/views/device_detail/device.component.scss
Normal file
|
@ -0,0 +1,7 @@
|
|||
:host {
|
||||
.legend {
|
||||
small {
|
||||
font-size: x-small;
|
||||
}
|
||||
}
|
||||
}
|
36
src/app/views/device_detail/device.component.spec.ts
Normal file
36
src/app/views/device_detail/device.component.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
437
src/app/views/device_detail/device.component.ts
Normal file
437
src/app/views/device_detail/device.component.ts
Normal 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);
|
||||
}
|
||||
}
|
42
src/app/views/device_detail/device.module.ts
Normal file
42
src/app/views/device_detail/device.module.ts
Normal 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 {}
|
21
src/app/views/device_logs/devlogs-routing.module.ts
Normal file
21
src/app/views/device_logs/devlogs-routing.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { DevLogsComponent } from './devlogs.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: DevLogsComponent,
|
||||
data: {
|
||||
title: $localize`Device Logs`
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class DevLogsRoutingModule {
|
||||
}
|
139
src/app/views/device_logs/devlogs.component.html
Normal file
139
src/app/views/device_logs/devlogs.component.html
Normal file
|
@ -0,0 +1,139 @@
|
|||
<c-row>
|
||||
<c-col xs>
|
||||
<c-card class="mb-4">
|
||||
<c-card-header>
|
||||
<c-row>
|
||||
<c-col xs [lg]="11">
|
||||
Device LOGS
|
||||
</c-col>
|
||||
<c-col xs [lg]="1">
|
||||
<button (click)="toggleCollapse()" cButton class="me-1" color="primary"><i
|
||||
class="fa-solid fa-filter mr-1"></i>Filter</button>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-card-header>
|
||||
<c-card-body>
|
||||
<c-row>
|
||||
<div [visible]="filters_visible" cCollapse>
|
||||
<c-col xs [lg]="12" class="example-form">
|
||||
<mat-form-field>
|
||||
<mat-label>Start date</mat-label>
|
||||
<input matInput [matDatepicker]="picker1" (dateChange)="reinitgrid('start',$event)"
|
||||
[(ngModel)]="filters['start_time']" />
|
||||
<mat-datepicker-toggle matIconSuffix [for]="picker1"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker1></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>End date</mat-label>
|
||||
<input matInput [matDatepicker]="picker2" (dateChange)="reinitgrid('end',$event)"
|
||||
[(ngModel)]="filters['end_time']" />
|
||||
<mat-datepicker-toggle matIconSuffix [for]="picker2"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker2></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field *ngIf="event_types_filtered.length>0">
|
||||
<mat-label>Select event type</mat-label>
|
||||
<mat-select placeholder="Event Type" [multiple]="true" (ngModelChange)="reinitgrid('detail',$event)"
|
||||
[(ngModel)]="filters['detail']" #multiSelect>
|
||||
<mat-option>
|
||||
<ngx-mat-select-search [showToggleAllCheckbox]="true" placeholderLabel="Find type..."
|
||||
[formControl]="bankMultiFilterCtrl"></ngx-mat-select-search>
|
||||
</mat-option>
|
||||
<mat-option *ngFor="let bank of event_types_filtered " [value]="bank">
|
||||
{{bank}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Select event type</mat-label>
|
||||
<mat-select placeholder="Event Level" (ngModelChange)="reinitgrid('level',$event)"
|
||||
[(ngModel)]="filters['level']" #multiSelect>
|
||||
<mat-option value="All">All</mat-option>
|
||||
<mat-option *ngFor="let level of ['Critical','Warning','Error','info'] " [value]="level">
|
||||
{{level}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Status</mat-label>
|
||||
<mat-select placeholder="Event Status" (ngModelChange)="reinitgrid('status',$event)"
|
||||
[(ngModel)]="filters['status']" #multiSelect>
|
||||
<mat-option value="All">All</mat-option>
|
||||
<mat-option [value]="true">Fixed</mat-option>
|
||||
<mat-option [value]="false">Not Fixed</mat-option>
|
||||
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Comment</mat-label>
|
||||
<input (ngModelChange)="reinitgrid('comment',$event)" [(ngModel)]="filters['comment']" matInput>
|
||||
</mat-form-field>
|
||||
</c-col>
|
||||
|
||||
</div>
|
||||
|
||||
</c-row>
|
||||
<gui-grid wid [rowDetail]="rowDetail" [horizontalGrid]="true" [rowHeight]="52" [source]="source"
|
||||
[columnMenu]="columnMenu" [paging]="paging" [sorting]="sorting" [infoPanel]="infoPanel"
|
||||
[autoResizeWidth]="true">
|
||||
<gui-grid-column header="#No" type="NUMBER" field="index" width="1" align="CENTER">
|
||||
<ng-template let-value="item.index" let-item="item" let-index="index">
|
||||
{{ value }}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
|
||||
<gui-grid-column header="level" width='90' wid field="level">
|
||||
<ng-template let-value="item.level" let-item="item" let-index="index">
|
||||
<c-badge style="cursor: pointer; font-weight: normal" color="danger" *ngIf="value == 'Critical'">{{ value
|
||||
}}</c-badge>
|
||||
<c-badge style="cursor: pointer; font-weight: normal" color="warning" *ngIf="value == 'Error'">{{ value
|
||||
}}</c-badge>
|
||||
<c-badge style="cursor: pointer; font-weight: normal" color="warning" *ngIf="value == 'Warning'">{{ value
|
||||
}}</c-badge>
|
||||
<c-badge style="cursor: pointer; font-weight: normal; min-width: 60px;" color="info"
|
||||
*ngIf="value == 'info'">{{ value }}</c-badge>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Event" width='200' field="detail">
|
||||
<ng-template let-value="item.detail" let-item="item" let-index="index">
|
||||
{{ value }}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Detail" field="comment">
|
||||
<ng-template let-value="item.comment" let-item="item" let-index="index">
|
||||
|
||||
<div class="gui-dev-info">
|
||||
{{ value }}
|
||||
</div>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Source" width='90' field="src">
|
||||
<ng-template let-value="item.src" let-item="item" let-index="index">
|
||||
{{ value }}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="status" width='100' field="status" align="CENTER">
|
||||
<ng-template let-value="item.status" let-item="item" let-index="index">
|
||||
<c-badge style=" cursor: pointer; font-weight: normal" color="success"
|
||||
*ngIf="value == true">Fixed</c-badge>
|
||||
<c-badge style="cursor: pointer; font-weight: normal" color="danger" *ngIf="value != true">Not
|
||||
Fixed</c-badge>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="eventtime" width='200' field="eventtime">
|
||||
<ng-template let-value="item.eventtime" let-item="item" let-index="index">
|
||||
{{ value }}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Device" width='200' field="name">
|
||||
<ng-template let-value="item.name" let-item="item" let-index="index">
|
||||
<div class="gui-dev-info">
|
||||
<span class="gui-dev-info-name">{{ value }}</span>
|
||||
<span class="gui-dev-info-ip">{{ item.devip }}</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
125
src/app/views/device_logs/devlogs.component.scss
Normal file
125
src/app/views/device_logs/devlogs.component.scss
Normal file
|
@ -0,0 +1,125 @@
|
|||
@use '@angular/material' as mat;
|
||||
|
||||
:host {
|
||||
.legend {
|
||||
small {
|
||||
font-size: x-small;
|
||||
}
|
||||
}
|
||||
}
|
||||
// .gui-drawer-content{
|
||||
// background-color: #efefef!important;
|
||||
|
||||
// }
|
||||
.log-detail{
|
||||
padding:30px 10px;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
.log-detail h1{
|
||||
font-size:2em;
|
||||
font-weight:bold;
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
.log-detail small{
|
||||
position:relative;
|
||||
top:-7px;
|
||||
padding:0;
|
||||
font-weight:bold;
|
||||
font-size:1.1em;
|
||||
}
|
||||
.log-detail table {
|
||||
width: 100%;
|
||||
border-collapse: collapse!important;
|
||||
margin: 5px 0 0 0;
|
||||
padding: 0;
|
||||
background-color: #ffffff29 !important;
|
||||
color: #000;
|
||||
}
|
||||
.log-detail th {
|
||||
text-align: left;
|
||||
}
|
||||
.log-detail th,
|
||||
.log-detail td {
|
||||
border: 1px solid #ffffff4a!important;
|
||||
padding: 0.5rem!important;
|
||||
}
|
||||
.gui-close-icon-wrapper .gui-close-icon:after,.gui-close-icon-wrapper .gui-close-icon:before {
|
||||
background-color: #ffffff !important;
|
||||
|
||||
}
|
||||
.log-detail code{
|
||||
padding:5px!important;
|
||||
display:block;
|
||||
background:#1d1f21;
|
||||
color:#c5c8c6;
|
||||
border-bottom-left-radius:3px;
|
||||
border-bottom-right-radius:3px;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.log-detail .code-title{
|
||||
background-color:#393e42!important;;
|
||||
width:100%;
|
||||
padding:2px 15px;
|
||||
display:inline-block;
|
||||
margin-top:10px;
|
||||
color:#d2d2d2;
|
||||
border-top-left-radius:3px;
|
||||
border-top-right-radius:3px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.gui-row-detail{
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.gui-dev-info {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
white-space: normal;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
.gui-dev-info-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.gui-dev-info-ip {
|
||||
color: #525252;
|
||||
font-style: italic;
|
||||
font-size: 13px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.gui-row-detail > div{
|
||||
height:100%;
|
||||
}
|
||||
.gui-row-detail .log-detail{
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.gui-structure{
|
||||
min-height: 550px;
|
||||
}
|
||||
|
||||
|
||||
.example-form {
|
||||
@include mat.button-density(-5);
|
||||
|
||||
@include mat.form-field-density(-5);
|
||||
@include mat.button-toggle-density(-5);
|
||||
@include mat.datepicker-density(-5);
|
||||
@include mat.all-component-densities(-5);
|
||||
@include mat.icon-button-density(-5);
|
||||
@include mat.icon-density(-5);
|
||||
.mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) .mat-mdc-floating-label { display: inline; }
|
||||
mat-form-field *{
|
||||
font-size:13px!important;
|
||||
}
|
||||
.mat-mdc-form-field-infix{
|
||||
width:150px;
|
||||
}
|
||||
}
|
234
src/app/views/device_logs/devlogs.component.ts
Normal file
234
src/app/views/device_logs/devlogs.component.ts
Normal file
|
@ -0,0 +1,234 @@
|
|||
import { Component, OnInit, ViewEncapsulation } from "@angular/core";
|
||||
import { FormControl } from "@angular/forms";
|
||||
import { dataProvider } from "../../providers/mikrowizard/data";
|
||||
import { Router, ActivatedRoute } from "@angular/router";
|
||||
import { loginChecker } from "../../providers/login_checker";
|
||||
import {
|
||||
GuiRowDetail,
|
||||
GuiInfoPanel,
|
||||
GuiColumn,
|
||||
GuiColumnMenu,
|
||||
GuiPaging,
|
||||
GuiPagingDisplay,
|
||||
GuiRowSelectionMode,
|
||||
GuiRowSelection,
|
||||
GuiRowSelectionType,
|
||||
} from "@generic-ui/ngx-grid";
|
||||
import { formatInTimeZone } from "date-fns-tz";
|
||||
import { takeUntil } from "rxjs/operators";
|
||||
import { Subject } from "rxjs";
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: "devlogs.component.html",
|
||||
styleUrls: ["devlogs.component.scss"],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class DevLogsComponent implements OnInit {
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
public tz: string = "UTC"
|
||||
public filterText: string;
|
||||
public filters: any = {
|
||||
start_time: false,
|
||||
end_time: false,
|
||||
detail: [],
|
||||
level: false,
|
||||
comment: "",
|
||||
status: "all",
|
||||
};
|
||||
public event_types: any = [];
|
||||
public event_types_filtered: any = [];
|
||||
public filters_visible: boolean = false;
|
||||
constructor(
|
||||
private data_provider: dataProvider,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
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 source: Array<any> = [];
|
||||
public columns: Array<GuiColumn> = [];
|
||||
public loading: boolean = true;
|
||||
public rows: any = [];
|
||||
public Selectedrows: any;
|
||||
public devid: number = 0;
|
||||
public sorting = {
|
||||
enabled: true,
|
||||
multiSorting: true,
|
||||
};
|
||||
public bankMultiFilterCtrl: FormControl = new FormControl<string>("");
|
||||
protected _onDestroy = new Subject<void>();
|
||||
|
||||
public campaignOnestart: any;
|
||||
public campaignOneend: any;
|
||||
rowDetail: GuiRowDetail = {
|
||||
enabled: true,
|
||||
template: (item) => {
|
||||
return `
|
||||
<div class='log-detail' style="color:#fff;background-color:${(() => {
|
||||
if (item.level == "Critical") return "#e55353";
|
||||
else if (item.level == "Warning") return "#f9b115";
|
||||
else item.level == "Info";
|
||||
return "#3399ff";
|
||||
})()}">
|
||||
<h1>Device :</h1>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Device Name</td>
|
||||
<td>${item.name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Device IP</td>
|
||||
<td>${item.devip}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Device MAC</td>
|
||||
<td>${item.mac}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h1 style="margin-top: 10px;">Alert Detail :
|
||||
|
||||
</h1>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Event</td>
|
||||
<td>${item.detail}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Event Status</td>
|
||||
<td><span (click)="logger(${item})" style="display:inline-block;background-color:${
|
||||
item.status ? "green" : "#db4848"
|
||||
} ;padding: 4px 10px;border-radius: 5px;line-height: 10px;color: rgba(255, 255, 255, 0.87);">${
|
||||
item.status ? "Fixed" : "Not Fixed"
|
||||
}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Event Category</td>
|
||||
<td>${item.eventtype}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Exec time</td>
|
||||
<td>${item.eventtime}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Detail</td>
|
||||
<td>${item.comment}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Source</td>
|
||||
<td>${item.src}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
ngOnInit(): void {
|
||||
var _self = this;
|
||||
this.devid = Number(this.route.snapshot.paramMap.get("devid"));
|
||||
if (this.devid > 0) {
|
||||
this.filters["devid"] = this.devid;
|
||||
}
|
||||
this.initGridTable();
|
||||
|
||||
this.bankMultiFilterCtrl.valueChanges
|
||||
.pipe(takeUntil(this._onDestroy))
|
||||
.subscribe(() => {
|
||||
let search = this.bankMultiFilterCtrl.value;
|
||||
if (!search) {
|
||||
this.event_types_filtered = this.event_types;
|
||||
}
|
||||
_self.event_types_filtered = _self.event_types_filtered.filter(
|
||||
(item: any) => item.toLowerCase().indexOf(search.toLowerCase()) > -1
|
||||
);
|
||||
console.dir(_self.event_types_filtered);
|
||||
});
|
||||
}
|
||||
toggleCollapse(): void {
|
||||
this.filters_visible = !this.filters_visible;
|
||||
}
|
||||
logger(item: any) {
|
||||
console.dir(item);
|
||||
}
|
||||
reinitgrid(field: string, $event: any) {
|
||||
if (field == "start") this.filters["start_time"] = $event.target.value;
|
||||
else if (field == "end") this.filters["end_time"] = $event.target.value;
|
||||
else if (field == "detail") this.filters["detail"] = $event;
|
||||
else if (field == "level") this.filters["level"] = $event;
|
||||
else if (field == "comment") this.filters["comment"] = $event;
|
||||
else if (field == "status") this.filters["status"] = $event;
|
||||
this.initGridTable();
|
||||
}
|
||||
initGridTable(): void {
|
||||
var _self = this;
|
||||
this.data_provider.get_dev_logs(this.filters).then((res) => {
|
||||
let index = 1;
|
||||
this.source = res.map((d: any) => {
|
||||
d.index = index;
|
||||
if (d.detail.indexOf("Link Down") >= 0) d.detail = "Link Down";
|
||||
else if (d.detail.indexOf("Link Up") >= 0) d.detail = "Link Up";
|
||||
if (!_self.event_types.includes(d.detail))
|
||||
_self.event_types.push(d.detail);
|
||||
d.eventtime = formatInTimeZone(
|
||||
d.eventtime.split(".")[0] + ".000Z",
|
||||
_self.tz,
|
||||
"yyyy-MM-dd HH:mm:ss XXX"
|
||||
);
|
||||
index += 1;
|
||||
return d;
|
||||
});
|
||||
_self.event_types_filtered = _self.event_types;
|
||||
console.dir(this.source);
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
47
src/app/views/device_logs/devlogs.module.ts
Normal file
47
src/app/views/device_logs/devlogs.module.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { ReactiveFormsModule } from "@angular/forms";
|
||||
|
||||
import {
|
||||
ButtonGroupModule,
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
FormModule,
|
||||
GridModule,
|
||||
CollapseModule,
|
||||
BadgeModule,
|
||||
} from "@coreui/angular";
|
||||
import { NgxMatSelectSearchModule } from "ngx-mat-select-search";
|
||||
import { DevLogsRoutingModule } from "./devlogs-routing.module";
|
||||
import { DevLogsComponent } from "./devlogs.component";
|
||||
import { GuiGridModule } from "@generic-ui/ngx-grid";
|
||||
import { MatDatepickerModule } from "@angular/material/datepicker";
|
||||
import { MatInputModule } from "@angular/material/input";
|
||||
import { MatFormFieldModule } from "@angular/material/form-field";
|
||||
import { FormsModule } from "@angular/forms";
|
||||
|
||||
import { MatSelectModule } from "@angular/material/select";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
DevLogsRoutingModule,
|
||||
CardModule,
|
||||
CommonModule,
|
||||
GridModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
FormModule,
|
||||
ButtonModule,
|
||||
ButtonGroupModule,
|
||||
GuiGridModule,
|
||||
CollapseModule,
|
||||
BadgeModule,
|
||||
MatInputModule,
|
||||
MatFormFieldModule,
|
||||
MatSelectModule,
|
||||
NgxMatSelectSearchModule,
|
||||
MatDatepickerModule,
|
||||
],
|
||||
declarations: [DevLogsComponent],
|
||||
})
|
||||
export class DevLogsModule {}
|
21
src/app/views/devices/devices-routing.module.ts
Normal file
21
src/app/views/devices/devices-routing.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { DevicesComponent } from './devices.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: DevicesComponent,
|
||||
data: {
|
||||
title: $localize`Device List`
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class DevicesRoutingModule {
|
||||
}
|
346
src/app/views/devices/devices.component.html
Normal file
346
src/app/views/devices/devices.component.html
Normal file
|
@ -0,0 +1,346 @@
|
|||
<c-row>
|
||||
<c-col xs>
|
||||
<c-card class="mb-4">
|
||||
<c-card-header>
|
||||
<c-row>
|
||||
<c-col xs [lg]="3">
|
||||
Devices
|
||||
</c-col>
|
||||
<c-col xs [lg]="9">
|
||||
<h6 style="text-align: right;">
|
||||
<button cButton color="danger" class="mx-1" size="sm" style="color: #fff;">{{updates.length}} Updatable
|
||||
</button>
|
||||
<button cButton color="warning" class="mx-1" size="sm" style="color: #fff;">{{upgrades.length}}
|
||||
Upgradable</button>
|
||||
|
|
||||
<button cButton color="dark" (click)="scanwizard(1,'')" [cModalToggle]="ScannerModal.id" class="mx-1"
|
||||
size="sm" style="color: #fff;"><i class="fa-solid fa-magnifying-glass"></i> Scanner</button>
|
||||
</h6>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-card-header>
|
||||
<c-card-body>
|
||||
<c-row>
|
||||
<c-col [lg]="3">
|
||||
<c-input-group *ngIf="groups.length>0">
|
||||
<span cInputGroupText>Group</span>
|
||||
<select [(ngModel)]="selected_group" (change)="groupselected($event)" cSelect>
|
||||
<option value="0" [selected]="selected_group == 0">Select a group</option>
|
||||
<option *ngFor="let g of groups" [value]="g.id" [selected]=" selected_group == g.id ">{{g.name}}
|
||||
</option>
|
||||
</select>
|
||||
</c-input-group>
|
||||
|
||||
</c-col>
|
||||
</c-row>
|
||||
<gui-grid #grid [rowClass]="rowClass" [source]="source" [searching]="searching" [paging]="paging"
|
||||
[columnMenu]="columnMenu" [sorting]="sorting" [infoPanel]="infoPanel" [rowSelection]="rowSelection"
|
||||
(selectedRows)="onSelectedRows($event)" [autoResizeWidth]=true>
|
||||
<gui-grid-column header="Name" field="name">
|
||||
<ng-template let-value="item.name" let-item="item" let-index="index">
|
||||
<img *ngIf="item.status=='updating'" width="20px" src="assets/img/loading.svg" />
|
||||
<i *ngIf="item.status=='updated'" cTooltip="Tooltip text"
|
||||
style="color: green; margin-right: 3px;font-size: .7em;" class="fa-solid fa-check"></i>
|
||||
<i *ngIf="item.status=='failed'" cTooltip="Update failed"
|
||||
style="color: red; margin-right: 3px;font-size: .7em;" class="fa-solid fa-x"></i>
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="CPU Type" field="arch">
|
||||
<ng-template let-value="item.arch" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Firmware" field="current_firmware">
|
||||
<ng-template let-value="item.current_firmware" let-item="item" let-index="index">
|
||||
<div>{{value}}</div>
|
||||
<i *ngIf="item.update_availble" cTooltip="Firmware Update availble"
|
||||
class="fa-solid fa-up-long text-primary mx-1"></i>
|
||||
<i *ngIf="item.update_availble" cTooltip="Device Firmware not Upgraded"
|
||||
class="fa-solid fa-microchip text-danger mx-1"></i>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="IP Address" field="ip">
|
||||
<ng-template let-value="item.ip" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="MAC Address" field="mac">
|
||||
<ng-template let-value="item.mac" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="License" field="license" [enabled]="false">
|
||||
<ng-template let-value="item.license" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Interface" field="interface" [enabled]="false">
|
||||
<ng-template let-value="item.interface" 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="Uptime" field="uptime">
|
||||
<ng-template let-value="item.uptime" 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 align="center" [cellEditing]="false" [sorting]="false" header="Action">
|
||||
<ng-template let-value="value" let-item="item">
|
||||
<button size="sm" shape="rounded-0" variant="outline" cButton color="primary" (click)="show_detail(item)"
|
||||
style="border: none;padding: 4px 7px;"><i class="fa-regular fa-eye"></i><small> Details</small>
|
||||
</button>
|
||||
<button color="primary" shape="rounded-0" variant="ghost" style="padding: 4px 7px;"
|
||||
[matMenuTriggerFor]="menu" cButton>
|
||||
<i class="fa-solid fa-bars"></i>
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<div cListGroup>
|
||||
<li cListGroupItem [active]="false" color="dark">Actions Menu</li>
|
||||
<button size="sm" (click)="single_device_action(item,'edit')" style="padding: 4px 7px;"
|
||||
cListGroupItem><i class="fa-solid fa-pencil"></i><small>
|
||||
Edit Device</small></button>
|
||||
<button size="sm" (click)="single_device_action(item,'firmware')" style="padding: 4px 7px;"
|
||||
cListGroupItem><i class="text-primary fa-solid fa-magnifying-glass"></i><small>
|
||||
Check Firmware</small></button>
|
||||
<button size="sm" (click)="single_device_action(item,'update')" style="padding: 4px 7px;"
|
||||
cListGroupItem><i class="text-primary fa-solid fa-upload"></i><small>
|
||||
Update Firmware</small></button>
|
||||
<!-- <button size="sm" (click)="single_device_action(item,'upgrade')" style="padding: 4px 7px;"
|
||||
cListGroupItem><i class="text-primary fa-solid fa-microchip"></i><small>
|
||||
Upgrade Firmware</small></button> -->
|
||||
<button size="sm" (click)="single_device_action(item,'logauth')" style="padding: 4px 7px;"
|
||||
cListGroupItem><i class="text-primary fa-regular fa-clock"></i><small>
|
||||
Show Auth Logs</small></button>
|
||||
<button size="sm" (click)="single_device_action(item,'logacc')" style="padding: 4px 7px;"
|
||||
cListGroupItem><i class="text-primary fa-solid fa-table-list"></i><small>
|
||||
Show Acc Logs</small></button>
|
||||
<button size="sm" (click)="single_device_action(item,'backup')" style="padding: 4px 7px;"
|
||||
cListGroupItem><i class="text-success fa-solid fa-database"></i><small>
|
||||
Show Backups</small></button>
|
||||
<button size="sm" (click)="single_device_action(item,'delete')" style="padding: 4px 7px;"
|
||||
cListGroupItem><i class="text-danger fa-solid fa-trash"></i><small>
|
||||
Delete Device</small></button>
|
||||
</div>
|
||||
</mat-menu>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
<c-navbar *ngIf="rows.length!= 0" class="bg-light" colorScheme="light" expand="lg">
|
||||
<c-container [fluid]="true">
|
||||
<a cNavbarBrand href="javascript:;">
|
||||
Batch Action :
|
||||
</a>
|
||||
<button [cNavbarToggler]="collapseRef"></button>
|
||||
<div #collapseRef="cCollapse" [navbar]="true" cCollapse>
|
||||
<c-navbar-nav class="me-auto mb-2 mb-lg-0">
|
||||
<c-nav-item>
|
||||
<c-dropdown variant="nav-item" [popper]="false">
|
||||
<a cDropdownToggle cNavLink>Select</a>
|
||||
<ul cDropdownMenu dark>
|
||||
<li><button cDropdownItem (click)="ConfirmAction='checkfirm';ConfirmModalVisible=true">Check
|
||||
Firmware</button></li>
|
||||
<li><button cDropdownItem
|
||||
(click)="ConfirmAction='update';ConfirmModalVisible=true">Update</button></li>
|
||||
<!-- <li><button cDropdownItem>Upgrade</button></li>
|
||||
<li><button cDropdownItem>Update and Upgrade</button></li> -->
|
||||
</ul>
|
||||
</c-dropdown>
|
||||
</c-nav-item>
|
||||
</c-navbar-nav>
|
||||
</div>
|
||||
</c-container>
|
||||
</c-navbar>
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
||||
|
||||
|
||||
<c-modal #ScannerModal [visible]="scanwizard_modal" (visibleChange)="handleScanwizard_modal($event)" backdrop="static"
|
||||
id="ScannerModal">
|
||||
<c-modal-header>
|
||||
<h5 cModalTitle>Scanner Wizard</h5>
|
||||
<button [cModalToggle]="ScannerModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
<div *ngIf="scanwizard_step==1" class="mb-5" style="text-align: center;">
|
||||
<h5 class="mb-5">Please select searching method</h5>
|
||||
<button cButton color="info" (click)="scanwizard(2,'chip')" [disabled]="true" class="mx-1" size="lg"><img width="100px"
|
||||
src="assets/img/chip.png" /><br />Layer2 Scan</button>
|
||||
<button cButton color="info" (click)="scanwizard(2,'ip')" class="mx-1" size="lg"><img width="100px"
|
||||
src="assets/img/tcpip.png" /><br />TCP/IP Scan</button>
|
||||
</div>
|
||||
<div *ngIf="scanwizard_step==2 && scan_type=='ip'" class="mb-2" style="text-align: center;">
|
||||
<h5 class="mb-5">Please Provide needed information</h5>
|
||||
<c-input-group class="mb-3">
|
||||
<span cInputGroupText>Start IP</span>
|
||||
<input aria-label="start" cFormControl [(ngModel)]="ip_scanner['start']" [valid]="checkvalid('start')"
|
||||
placeholder="192.168.1.1" />
|
||||
<span cInputGroupText>End IP</span>
|
||||
<input aria-label="end" cFormControl [(ngModel)]="ip_scanner['end']" [valid]="checkvalid('end')"
|
||||
placeholder="192.168.1.255" />
|
||||
</c-input-group>
|
||||
<c-input-group class="mb-3">
|
||||
<span cInputGroupText>Username</span>
|
||||
<input aria-label="start" cFormControl [(ngModel)]="ip_scanner['user']" placeholder="Default username" />
|
||||
</c-input-group>
|
||||
<c-input-group class="mb-3">
|
||||
<span cInputGroupText>Password</span>
|
||||
<input aria-label="end" cFormControl [(ngModel)]="ip_scanner['password']" placeholder="********" />
|
||||
</c-input-group>
|
||||
<c-input-group class="mb-3">
|
||||
<span cInputGroupText>Port</span>
|
||||
<input aria-label="end" cFormControl [valid]="checkvalid('port')" [(ngModel)]="ip_scanner['port']"
|
||||
placeholder="8728" />
|
||||
</c-input-group>
|
||||
<button cButton color="info" (click)="scanwizard(3,'ip')" class="mx-1" size="lg">Start Scanning</button>
|
||||
</div>
|
||||
<div class="mwand" *ngIf="scanwizard_step==3">
|
||||
<svg viewBox="0 0 203 148.27">
|
||||
<g id="wand">
|
||||
<g class="cls-1">
|
||||
<path d="M194.63,152.18v-7.76C194.6,147,194.6,149.59,194.63,152.18Z" transform="translate(-10 -31.06)" />
|
||||
</g>
|
||||
<rect class="cls-2" x="5.07" y="129.83" width="117.08" height="17.1"
|
||||
transform="translate(-77.95 30.6) rotate(-35.06)" />
|
||||
<rect class="cls-3" x="106.38" y="88.26" width="32.89" height="17.1"
|
||||
transform="translate(-43.33 57.07) rotate(-35.06)" />
|
||||
<ellipse class="cls-4" cx="136.21" cy="87.42" rx="3.29" ry="8.55"
|
||||
transform="translate(-35.5 63.06) rotate(-35.06)" />
|
||||
<ellipse class="cls-2" cx="15.6" cy="172.07" rx="3.29" ry="8.55"
|
||||
transform="translate(-106.02 9.13) rotate(-35.06)" />
|
||||
<ellipse class="cls-3" cx="109.5" cy="106.16" rx="3.29" ry="8.55"
|
||||
transform="translate(-51.12 51.12) rotate(-35.06)" />
|
||||
<path class="cls-5" d="M138.71,85.25s4.26,6.06,2.68,9L20.15,179.32s-3.27.49-7.53-5.57Z"
|
||||
transform="translate(-10 -31.06)" />
|
||||
</g>
|
||||
<g id="stars">
|
||||
<g id="star1">
|
||||
<polygon class="cls-6"
|
||||
points="142.22 4.88 138.59 13.13 147.13 17.7 137.94 19.78 139.9 28.82 132.07 23.15 125.96 29.86 125.38 20.71 115.81 20.03 122.93 14.3 117.1 6.74 126.55 8.74 128.85 0 133.51 8.22 142.22 4.88" />
|
||||
<polygon class="cls-7"
|
||||
points="142.29 4.89 136.56 13.87 144.96 17.35 136.17 18.98 138.3 26.2 131.33 20.74 125.88 29.85 132.06 23.11 139.91 28.82 137.95 19.81 147.12 17.74 138.59 13.11 142.29 4.89" />
|
||||
</g>
|
||||
<g id="star2">
|
||||
<polygon class="cls-6"
|
||||
points="166.3 14.45 165.13 17.09 167.87 18.55 164.93 19.22 165.55 22.12 163.04 20.3 161.09 22.45 160.9 19.52 157.83 19.3 160.11 17.46 158.25 15.04 161.27 15.68 162.01 12.88 163.51 15.52 166.3 14.45" />
|
||||
<polygon class="cls-7"
|
||||
points="166.32 14.45 164.48 17.33 167.18 18.44 164.36 18.96 165.04 21.28 162.81 19.53 161.06 22.45 163.04 20.29 165.56 22.12 164.93 19.23 167.87 18.57 165.13 17.08 166.32 14.45" />
|
||||
</g>
|
||||
<g id="star3">
|
||||
<polygon class="cls-6"
|
||||
points="202.01 38.12 194.78 46.34 203 54.75 191.61 53.79 190.56 64.97 183.57 55.54 174.05 61.06 176.73 50.27 165.91 45.98 176.24 41.95 172.26 31.08 182.46 36.84 188.33 27.58 190.71 38.8 202.01 38.12" />
|
||||
<polygon class="cls-7"
|
||||
points="202.08 38.15 192.17 46.45 200.62 53.55 189.85 52.21 189.67 61.34 183.6 52.48 173.96 61.03 183.58 55.49 190.57 64.97 191.6 53.83 202.97 54.79 194.8 46.31 202.08 38.15" />
|
||||
</g>
|
||||
<g id="star4">
|
||||
<polygon class="cls-6"
|
||||
points="155.07 63.05 153.01 67.75 157.87 70.35 152.64 71.52 153.75 76.67 149.3 73.44 145.83 77.25 145.5 72.05 140.06 71.67 144.1 68.41 140.79 64.11 146.16 65.25 147.47 60.28 150.13 64.95 155.07 63.05" />
|
||||
<polygon class="cls-7"
|
||||
points="155.11 63.06 151.86 68.17 156.63 70.14 151.63 71.07 152.84 75.17 148.88 72.07 145.78 77.25 149.29 73.42 153.76 76.67 152.65 71.54 157.86 70.36 153.01 67.73 155.11 63.06" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<h5>{{scanwizard_prompt}}</h5>
|
||||
</div>
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<small *ngIf="scan_type=='ip'" style="margin: 0 auto;">Empty username and password means system default
|
||||
configuration</small>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
||||
|
||||
|
||||
<c-modal #ConfirmModal backdrop="static" [(visible)]="ConfirmModalVisible" id="runConfirmModal">
|
||||
<c-modal-header>
|
||||
<h6 cModalTitle>Please Confirm Action </h6>
|
||||
<button [cModalToggle]="ConfirmModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
<span *ngIf="ConfirmAction=='checkfirm'">Are you sure that You want to Check firmware of selected devices for
|
||||
update?</span>
|
||||
<span *ngIf="ConfirmAction=='update'">Are you sure that You want to <code>update firmware</code> of selected
|
||||
devices?</span>
|
||||
<ng-container *ngIf="ConfirmAction=='delete'">
|
||||
Are you sure that You want to<code>Delete Device {{selected_device.name}} ?</code><br />
|
||||
<hr>
|
||||
<p class="text-danger">
|
||||
All Related Configuration will be deleted/Modified :<br /><br />
|
||||
* User Permision Related to this Device<br />
|
||||
* Device Groups including this Device<br />
|
||||
* All Logs related to this device<br />
|
||||
</p>
|
||||
</ng-container>
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<button *ngIf="ConfirmAction=='checkfirm'" (click)="check_firmware()" cButton color="danger">
|
||||
Yes
|
||||
</button>
|
||||
<button *ngIf="ConfirmAction=='update'" (click)="update_firmware()" cButton color="danger">
|
||||
Yes
|
||||
</button>
|
||||
<button *ngIf="ConfirmAction=='delete'" (click)="delete_device()" cButton color="danger">
|
||||
Yes,Delete Device
|
||||
</button>
|
||||
<button cButton [cModalToggle]="ConfirmModal.id" color="info">
|
||||
Cancel
|
||||
</button>
|
||||
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
||||
|
||||
<c-modal #EditDevModal backdrop="static" [(visible)]="EditDevModalVisible" id="EditDevModal">
|
||||
<c-modal-header>
|
||||
<h6 cModalTitle>Editing Device</h6>
|
||||
<button [cModalToggle]="EditDevModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body *ngIf="EditDevModalVisible">
|
||||
<c-input-group class="mb-3">
|
||||
<span cInputGroupText>Username</span>
|
||||
<input aria-label="start" [(ngModel)]="selected_device['editform']['user_name']" cFormControl
|
||||
placeholder=" username" />
|
||||
</c-input-group>
|
||||
<c-input-group class="mb-3">
|
||||
<span cInputGroupText>Password</span>
|
||||
<input aria-label="start" [type]="show_pass ? 'text' : 'password'"
|
||||
[(ngModel)]="selected_device['editform']['password']" cFormControl placeholder=" username" />
|
||||
<button cButton (click)="show_pass=!show_pass" color="secondary" variant="outline">
|
||||
<i *ngIf="show_pass" class="fa-solid fa-eye"></i>
|
||||
<i *ngIf="!show_pass" class="fa-solid fa-eye-slash"></i>
|
||||
</button>
|
||||
</c-input-group>
|
||||
<c-input-group class="mb-3">
|
||||
<span cInputGroupText>ip</span>
|
||||
<input aria-label="start" [(ngModel)]="selected_device['editform']['ip']" cFormControl
|
||||
placeholder="Default username" />
|
||||
</c-input-group>
|
||||
<c-input-group class="mb-3">
|
||||
<span cInputGroupText>peer ip</span>
|
||||
<select aria-label="Default select example" cFormControl [(ngModel)]="selected_device['editform']['peer_ip']" cSelect>
|
||||
<option *ngFor="let o of selected_device['editform']['ips']" [value]="o">{{o}}</option>
|
||||
</select>
|
||||
</c-input-group>
|
||||
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<button cButton (click)="save_device()" color="danger">
|
||||
Save
|
||||
</button>
|
||||
<button cButton [cModalToggle]="EditDevModal.id" color="info">
|
||||
Cancel
|
||||
</button>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
||||
|
||||
<c-toaster position="fixed" placement="top-end"></c-toaster>
|
460
src/app/views/devices/devices.component.ts
Normal file
460
src/app/views/devices/devices.component.ts
Normal file
|
@ -0,0 +1,460 @@
|
|||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
OnDestroy,
|
||||
QueryList,
|
||||
ViewChild,
|
||||
ViewChildren,
|
||||
} from "@angular/core";
|
||||
import { dataProvider } from "../../providers/mikrowizard/data";
|
||||
import { Router, ActivatedRoute } from "@angular/router";
|
||||
import { loginChecker } from "../../providers/login_checker";
|
||||
import {
|
||||
GuiGridComponent,
|
||||
GuiGridApi,
|
||||
GuiRowClass,
|
||||
GuiSearching,
|
||||
GuiSelectedRow,
|
||||
GuiInfoPanel,
|
||||
GuiColumn,
|
||||
GuiColumnMenu,
|
||||
GuiPaging,
|
||||
GuiPagingDisplay,
|
||||
GuiRowSelectionMode,
|
||||
GuiRowSelection,
|
||||
GuiRowSelectionType,
|
||||
} from "@generic-ui/ngx-grid";
|
||||
import { ToasterComponent } from "@coreui/angular";
|
||||
import { AppToastComponent } from "../toast-simple/toast.component";
|
||||
|
||||
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: "devices.component.html",
|
||||
})
|
||||
export class DevicesComponent implements OnInit, OnDestroy {
|
||||
public uid: number;
|
||||
public uname: 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;
|
||||
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 !== "";
|
||||
}
|
||||
}
|
||||
@ViewChild("grid", { static: true }) gridComponent: GuiGridComponent;
|
||||
@ViewChildren(ToasterComponent) viewChildren!: QueryList<ToasterComponent>;
|
||||
public source: Array<any> = [];
|
||||
public columns: Array<GuiColumn> = [];
|
||||
public loading: boolean = true;
|
||||
public rows: any = [];
|
||||
public Selectedrows: any;
|
||||
public upgrades: any = [];
|
||||
public updates: any = [];
|
||||
public scanwizard_step: number = 1;
|
||||
public scanwizard_modal: boolean = false;
|
||||
public ConfirmModalVisible: boolean = false;
|
||||
public EditDevModalVisible: boolean = false;
|
||||
public ConfirmAction: string = "checkfirm";
|
||||
public scan_type: string = "ip";
|
||||
public scan_timer: any;
|
||||
public list_update_timer: any;
|
||||
public scanwizard_prompt: string = "Scanning Network!";
|
||||
public groups: any = [];
|
||||
public selected_group: number = 0;
|
||||
public selected_devices: any = {};
|
||||
public selected_device: any = {};
|
||||
public show_pass: boolean = false;
|
||||
toasterForm = {
|
||||
autohide: true,
|
||||
delay: 3000,
|
||||
position: "fixed",
|
||||
fade: true,
|
||||
closeButton: true,
|
||||
};
|
||||
rowClass: GuiRowClass = {
|
||||
class: "row-highlighted",
|
||||
};
|
||||
public sorting = {
|
||||
enabled: true,
|
||||
multiSorting: true,
|
||||
};
|
||||
public ip_scanner: any;
|
||||
|
||||
searching: GuiSearching = {
|
||||
enabled: true,
|
||||
placeholder: "Search Devices",
|
||||
};
|
||||
|
||||
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: GuiRowSelection = {
|
||||
enabled: true,
|
||||
type: GuiRowSelectionType.CHECKBOX,
|
||||
mode: GuiRowSelectionMode.MULTIPLE,
|
||||
};
|
||||
|
||||
ngOnInit(): void {
|
||||
this.selected_group = Number(this.route.snapshot.paramMap.get("id"));
|
||||
this.initGridTable();
|
||||
this.get_groups();
|
||||
}
|
||||
|
||||
show_detail(item: any) {
|
||||
this.router.navigate(["/device-stats", { id: item.id }]);
|
||||
}
|
||||
|
||||
single_device_action(dev: any, action: string) {
|
||||
const api: GuiGridApi = this.gridComponent.api;
|
||||
api.unselectAll();
|
||||
this.Selectedrows = [dev["id"]];
|
||||
switch (action) {
|
||||
case "edit":
|
||||
this.edit_device_form(dev);
|
||||
break;
|
||||
case "firmware":
|
||||
this.check_firmware();
|
||||
break;
|
||||
case "update":
|
||||
this.update_firmware();
|
||||
break;
|
||||
case "upgrade":
|
||||
this.upgrade_firmware();
|
||||
break;
|
||||
case "logauth":
|
||||
this.router.navigate(["/authlog", { devid: dev.id }]);
|
||||
break;
|
||||
case "logacc":
|
||||
this.router.navigate(["/accountlog", { devid: dev.id }]);
|
||||
break;
|
||||
case "backup":
|
||||
this.router.navigate(["/backups", { devid: dev.id }]);
|
||||
break;
|
||||
case "reboot":
|
||||
this.reboot_devices();
|
||||
break;
|
||||
case "delete":
|
||||
this.ConfirmAction = "delete";
|
||||
this.ConfirmModalVisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
edit_device_form(dev: any) {
|
||||
var _self = this;
|
||||
this.selected_device = dev;
|
||||
this.data_provider.get_editform(dev.id).then((res) => {
|
||||
if ("error" in res) {
|
||||
if (res.error.indexOf("Unauthorized")) {
|
||||
_self.show_toast(
|
||||
"Error",
|
||||
"You are not authorized to perform this action",
|
||||
"danger"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.selected_device["editform"] = res;
|
||||
this.EditDevModalVisible = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
save_device() {
|
||||
var _self = this;
|
||||
this.data_provider
|
||||
.save_editform(this.selected_device["editform"])
|
||||
.then((res) => {
|
||||
_self.show_toast("Success", "Device Saved", "success");
|
||||
this.initGridTable();
|
||||
this.EditDevModalVisible = false;
|
||||
});
|
||||
}
|
||||
groupselected(item: any) {
|
||||
this.selected_group = item.target.value;
|
||||
if (this.selected_group != 0) {
|
||||
this.router.navigate([".", { id: this.selected_group }]);
|
||||
}
|
||||
this.initGridTable();
|
||||
}
|
||||
|
||||
delete_device() {
|
||||
var _self = this;
|
||||
this.ConfirmModalVisible = false;
|
||||
this.data_provider.delete_devices(this.Selectedrows).then((res) => {
|
||||
_self.show_toast("Success", "Device Deleted", "success");
|
||||
this.initGridTable();
|
||||
});
|
||||
}
|
||||
|
||||
onSelectedRows(rows: Array<GuiSelectedRow>): void {
|
||||
this.rows = rows;
|
||||
this.Selectedrows = rows.map((m: GuiSelectedRow) => m.source.id);
|
||||
}
|
||||
|
||||
checkvalid(type: string): boolean {
|
||||
var rx =
|
||||
/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||||
if (type == "start") return rx.test(this.ip_scanner.start);
|
||||
else if (type == "end") return rx.test(this.ip_scanner.end);
|
||||
else if (type == "port") {
|
||||
if (this.ip_scanner.port == "") return true;
|
||||
return Boolean(Number(this.ip_scanner.port));
|
||||
} else return false;
|
||||
}
|
||||
|
||||
scanwizard(step: number, type: string) {
|
||||
var _self = this;
|
||||
this.data_provider.scan_devs(this.scan_type, {}).then((res) => {
|
||||
if (res.status == true) {
|
||||
_self.scanwizard_step = 3;
|
||||
this.wait_scan();
|
||||
return;
|
||||
}
|
||||
if (step == 1) {
|
||||
_self.scan_type = "";
|
||||
_self.ip_scanner = {
|
||||
start: "",
|
||||
end: "",
|
||||
port: "",
|
||||
user: "",
|
||||
password: "",
|
||||
};
|
||||
}
|
||||
if (step == 2) {
|
||||
_self.scan_type = "";
|
||||
if (type == "ip") {
|
||||
_self.scan_type = "ip";
|
||||
} else if (type == "chip") {
|
||||
_self.scan_type = "mac";
|
||||
}
|
||||
}
|
||||
if (step == 3) {
|
||||
if (_self.scan_type == "ip") {
|
||||
if (_self.ip_scanner.start == "" || _self.ip_scanner.end == "") {
|
||||
return;
|
||||
}
|
||||
//test if start and end are valid ip addresses and port is valid
|
||||
if (
|
||||
!_self.checkvalid("start") ||
|
||||
!_self.checkvalid("end") ||
|
||||
!_self.checkvalid("port")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (_self.ip_scanner.port == "") {
|
||||
_self.ip_scanner.port = false;
|
||||
}
|
||||
if (_self.ip_scanner.user == "") {
|
||||
_self.ip_scanner.user = false;
|
||||
}
|
||||
if (_self.ip_scanner.password == "") {
|
||||
_self.ip_scanner.password = false;
|
||||
}
|
||||
|
||||
_self.data_provider
|
||||
.scan_devs(_self.scan_type, _self.ip_scanner)
|
||||
.then((res) => {
|
||||
_self.scanwizard_prompt = "Scanning Network!";
|
||||
_self.wait_scan();
|
||||
});
|
||||
} else if (type == "chip") {
|
||||
_self.data_provider
|
||||
.scan_devs(_self.scan_type, _self.ip_scanner)
|
||||
.then((res) => {
|
||||
// console.dir(res);
|
||||
});
|
||||
}
|
||||
}
|
||||
_self.scanwizard_step = step;
|
||||
});
|
||||
}
|
||||
|
||||
wait_scan() {
|
||||
clearTimeout(this.scan_timer);
|
||||
var _self = this;
|
||||
this.scan_timer = setTimeout(function () {
|
||||
_self.data_provider.scan_devs(_self.scan_type, {}).then((res) => {
|
||||
if (res.status == false) {
|
||||
_self.initGridTable();
|
||||
_self.scanwizard_prompt = "Scanning done! Reloading data";
|
||||
setTimeout(function () {
|
||||
_self.scanwizard_modal = false;
|
||||
}, 3000);
|
||||
} else {
|
||||
_self.wait_scan();
|
||||
}
|
||||
});
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
logger(item: any) {
|
||||
console.dir(item);
|
||||
}
|
||||
|
||||
handleScanwizard_modal(event: any) {
|
||||
this.scanwizard_modal = event;
|
||||
}
|
||||
show_toast(title: string, body: string, color: string) {
|
||||
const { ...props } = { ...this.toasterForm, color, title, body };
|
||||
const componentRef = this.viewChildren.first.addToast(
|
||||
AppToastComponent,
|
||||
props,
|
||||
{}
|
||||
);
|
||||
componentRef.instance["closeButton"] = props.closeButton;
|
||||
}
|
||||
check_firmware() {
|
||||
var _self = this;
|
||||
this.data_provider
|
||||
.check_firmware(this.Selectedrows.toString())
|
||||
.then((res) => {
|
||||
_self.show_toast("info", "Checking Firmwares", "light");
|
||||
_self.ConfirmModalVisible = false;
|
||||
setTimeout(function () {
|
||||
if (_self.Selectedrows.length < 1) _self.initGridTable();
|
||||
}, 1);
|
||||
});
|
||||
}
|
||||
|
||||
update_firmware() {
|
||||
var _self = this;
|
||||
this.data_provider
|
||||
.update_firmware(this.Selectedrows.toString())
|
||||
.then((res) => {
|
||||
_self.show_toast("info", "Updating Firmwares Sent", "light");
|
||||
_self.initGridTable();
|
||||
});
|
||||
}
|
||||
|
||||
upgrade_firmware() {
|
||||
var _self = this;
|
||||
this.data_provider
|
||||
.upgrade_firmware(this.Selectedrows.toString())
|
||||
.then((res) => {
|
||||
_self.show_toast("info", "Upgrading Firmwares", "light");
|
||||
_self.initGridTable();
|
||||
});
|
||||
}
|
||||
|
||||
reboot_devices() {
|
||||
var _self = this;
|
||||
this.data_provider
|
||||
.reboot_devices(this.Selectedrows.toString())
|
||||
.then((res) => {
|
||||
_self.show_toast("info", "Reboot sent", "light");
|
||||
_self.ConfirmModalVisible = !_self.ConfirmModalVisible;
|
||||
_self.initGridTable();
|
||||
});
|
||||
}
|
||||
|
||||
get_groups() {
|
||||
var _self = this;
|
||||
this.data_provider.get_devgroup_list().then((res) => {
|
||||
_self.groups = res;
|
||||
});
|
||||
}
|
||||
|
||||
initGridTable(): void {
|
||||
var _self = this;
|
||||
_self.upgrades = [];
|
||||
_self.updates = [];
|
||||
clearTimeout(this.list_update_timer);
|
||||
var data = {
|
||||
group_id: this.selected_group,
|
||||
search: false,
|
||||
page: this.paging.page,
|
||||
size: this.paging.pageSize,
|
||||
};
|
||||
|
||||
_self.data_provider.get_dev_list(data).then((res) => {
|
||||
_self.source = res.map((x: any) => {
|
||||
if (x.upgrade_availble) _self.upgrades.push(x);
|
||||
if (x.update_availble) _self.updates.push(x);
|
||||
return x;
|
||||
});
|
||||
_self.device_interval();
|
||||
_self.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
device_interval() {
|
||||
var _self = this;
|
||||
var data = {
|
||||
group_id: this.selected_group,
|
||||
search: false,
|
||||
page: this.paging.page,
|
||||
size: this.paging.pageSize,
|
||||
};
|
||||
clearTimeout(this.list_update_timer);
|
||||
_self.list_update_timer = setTimeout(function () {
|
||||
// _self.data_provider.get_dev_list(data).then(res => {
|
||||
// _self.source =res.map( (x:any) => {
|
||||
// if(x.upgrade_availble)
|
||||
// _self.upgrades.push(x);
|
||||
// if(x.update_availble)
|
||||
// _self.updates.push(x);
|
||||
// return x;
|
||||
// });
|
||||
// // _self.device_interval()
|
||||
// _self.loading = false;
|
||||
// });
|
||||
//we don't want to reload table if user is selected devices from list
|
||||
if (_self.Selectedrows.length < 1) _self.initGridTable();
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
clearTimeout(this.scan_timer);
|
||||
}
|
||||
}
|
50
src/app/views/devices/devices.module.ts
Normal file
50
src/app/views/devices/devices.module.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { FormsModule } from "@angular/forms";
|
||||
|
||||
import {
|
||||
ButtonGroupModule,
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
FormModule,
|
||||
GridModule,
|
||||
NavModule,
|
||||
NavbarModule,
|
||||
CollapseModule,
|
||||
DropdownModule,
|
||||
BadgeModule,
|
||||
ToastModule,
|
||||
ModalModule,
|
||||
ListGroupModule,
|
||||
TooltipModule,
|
||||
} from "@coreui/angular";
|
||||
import { MatMenuModule } from "@angular/material/menu";
|
||||
import { DevicesRoutingModule } from "./devices-routing.module";
|
||||
import { DevicesComponent } from "./devices.component";
|
||||
import { GuiGridModule } from "@generic-ui/ngx-grid";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
DevicesRoutingModule,
|
||||
CardModule,
|
||||
NavModule,
|
||||
CommonModule,
|
||||
GridModule,
|
||||
FormModule,
|
||||
ButtonModule,
|
||||
ButtonGroupModule,
|
||||
GuiGridModule,
|
||||
NavbarModule,
|
||||
CollapseModule,
|
||||
DropdownModule,
|
||||
BadgeModule,
|
||||
ModalModule,
|
||||
ToastModule,
|
||||
FormsModule,
|
||||
ListGroupModule,
|
||||
MatMenuModule,
|
||||
TooltipModule,
|
||||
],
|
||||
declarations: [DevicesComponent],
|
||||
})
|
||||
export class DevicesModule {}
|
21
src/app/views/devices_group/devgroup-routing.module.ts
Normal file
21
src/app/views/devices_group/devgroup-routing.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { DevicesGroupComponent } from './devgroup.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: DevicesGroupComponent,
|
||||
data: {
|
||||
title: $localize`Device Group`
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class DevicesGroupRoutingModule {
|
||||
}
|
178
src/app/views/devices_group/devgroup.component.html
Normal file
178
src/app/views/devices_group/devgroup.component.html
Normal file
|
@ -0,0 +1,178 @@
|
|||
<c-row>
|
||||
<c-col xs>
|
||||
<c-card class="mb-4">
|
||||
<c-card-header>
|
||||
<c-row>
|
||||
<c-col xs [lg]="10">
|
||||
Device Groups
|
||||
</c-col>
|
||||
<c-col xs [lg]="2" style="text-align: right;">
|
||||
<button cButton color="primary" (click)="editAddGroup({},'showadd')"><i
|
||||
class="fa-solid fa-plus"></i></button>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-card-header>
|
||||
<c-card-body>
|
||||
<gui-grid [source]="source" [columnMenu]="columnMenu" [sorting]="sorting" [infoPanel]="infoPanel"
|
||||
[autoResizeWidth]=true>
|
||||
<gui-grid-column header="Name" field="name">
|
||||
<ng-template let-value="item.name" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Devices" field="array_agg" align="CENTER">
|
||||
<ng-template let-value="item.array_agg" let-item="item" let-index="index">
|
||||
<ng-container *ngIf="item.id==1 ; then Default;else NotDefault">
|
||||
</ng-container>
|
||||
<ng-template #Default>
|
||||
<c-badge color="info">All Devices</c-badge>
|
||||
</ng-template>
|
||||
<ng-template #NotDefault>
|
||||
<c-badge color="info" *ngIf="value[0]==null && item.id!=1">0 Members</c-badge>
|
||||
<c-badge color="info" *ngIf="value[0]!=null">{{value.length}} Members</c-badge>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Create Time" field="created">
|
||||
<ng-template let-value="item.created" let-item="item" let-index="index">
|
||||
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
|
||||
<gui-grid-column header="Actions" field="action">
|
||||
<ng-template let-value="item.id" let-item="item" let-index="index">
|
||||
<button [disabled]="value==1" cButton color="warning" size="sm" (click)="editAddGroup(item,'showedit');"
|
||||
class="mx-1"><i class="fa-regular fa-pen-to-square"></i></button>
|
||||
<button [disabled]="value==1" cButton color="info" size="sm" (click)="show_members(item.id);"
|
||||
class="mx-1"><i class="fa-regular fa-eye"></i></button>
|
||||
<button [disabled]="value==1" cButton color="danger" size="sm" (click)="show_delete_group(item);"
|
||||
class="mx-1"><i class="fa-regular fa-trash-can"></i></button>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
||||
|
||||
|
||||
|
||||
<c-modal #EditGroupModal backdrop="static" size="lg" [(visible)]="EditGroupModalVisible" id="EditGroupModal">
|
||||
<c-modal-header>
|
||||
<h5 cModalTitle> Group Edit</h5>
|
||||
<button [cModalToggle]="EditGroupModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
<c-input-group class="mb-3">
|
||||
<div [cFormFloating]="true" class="mb-3">
|
||||
<input cFormControl id="floatingInput" placeholder="Group Name" [(ngModel)]="currentGroup['name']" />
|
||||
<label cLabel for="floatingInput">Group Name</label>
|
||||
</div>
|
||||
</c-input-group>
|
||||
<c-input-group class="mb-3">
|
||||
<h5>Group Members :</h5>
|
||||
<gui-grid [autoResizeWidth]="true" [searching]="searching" [source]="groupMembers" [columnMenu]="columnMenu"
|
||||
[sorting]="sorting" [infoPanel]="infoPanel" [rowSelection]="rowSelection"
|
||||
(selectedRows)="onSelectedRowsMembers($event)" [autoResizeWidth]=true [paging]="paging">
|
||||
<gui-grid-column header="Member Name" field="name">
|
||||
<ng-template let-value="item.name" let-item="item" let-index="index">
|
||||
{{value}} </ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="perm Name" field="ip">
|
||||
<ng-template let-value="item.ip" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Actions" width="120" field="action">
|
||||
<ng-template let-value="item.id" let-item="item" let-index="index">
|
||||
<button cButton color="danger" size="sm" (click)="remove_from_group(item.id)"><i
|
||||
class="fa-regular fa-trash-can"></i></button>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
<br />
|
||||
<button *ngIf="MemberRows.length!= 0" style="margin: 10px 0;" cButton color="danger" size="sm"><i
|
||||
class="fa-regular fa-trash-can"></i>Delete {{MemberRows.length}} Selected</button>
|
||||
</c-input-group>
|
||||
<hr />
|
||||
<button cButton color="primary" (click)="show_new_member_form()">+ Add new Members</button>
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<button cButton color="primary" (click)="save_group()">save</button>
|
||||
<button [cModalToggle]="EditGroupModal.id" cButton color="secondary">
|
||||
Close
|
||||
</button>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
||||
|
||||
<c-modal #NewMemberModal backdrop="static" size="lg" [(visible)]="NewMemberModalVisible" id="NewMemberModal">
|
||||
<c-modal-header>
|
||||
<h5 cModalTitle>Members not in Group</h5>
|
||||
<button (click)="NewMemberModalVisible=!NewMemberModalVisible" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
<c-input-group class="mb-3">
|
||||
<h5>Members Availble to add:</h5>
|
||||
<gui-grid [autoResizeWidth]="true" *ngIf="NewMemberModalVisible" [searching]="searching"
|
||||
[source]="availbleMembers" [columnMenu]="columnMenu" [sorting]="sorting" [infoPanel]="infoPanel"
|
||||
[rowSelection]="rowSelection" (selectedRows)="onSelectedRowsNewMembers($event)" [autoResizeWidth]=true
|
||||
[paging]="paging">
|
||||
<gui-grid-column header="Group Name" field="name">
|
||||
<ng-template let-value="item.name" let-item="item" let-index="index">
|
||||
{{value}} </ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="perm Name" field="ip">
|
||||
<ng-template let-value="item.ip" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="perm Name" field="mac">
|
||||
<ng-template let-value="item.mac" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
<br />
|
||||
</c-input-group>
|
||||
<hr />
|
||||
</c-modal-body>
|
||||
|
||||
<c-modal-footer>
|
||||
<button *ngIf="NewMemberRows.length!= 0" (click)="add_new_members()" cButton color="primary">Add {{
|
||||
NewMemberRows.length }}</button>
|
||||
<button (click)="NewMemberModalVisible=!NewMemberModalVisible" cButton color="secondary">
|
||||
Close
|
||||
</button>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
||||
|
||||
|
||||
|
||||
|
||||
<c-modal #ConfirmModal backdrop="static" [(visible)]="ConfirmModalVisible" id="ConfirmModal">
|
||||
<c-modal-header>
|
||||
<h5 cModalTitle> Are You Sure?</h5>
|
||||
<button [cModalToggle]="ConfirmModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
<ng-container *ngIf="ConfirmAction=='delete'">
|
||||
<span>
|
||||
Are you sure that you want to delete <b class="text-danger-emphasis">{{currentGroup['name']}}</b>?
|
||||
</span>
|
||||
<br />
|
||||
<p class="text-danger">
|
||||
All Related Configuration will be deleted/Modified :<br />
|
||||
* User Permision Related to this group<br />
|
||||
* Tasks including this Group<br />
|
||||
</p>
|
||||
</ng-container>
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<button cButton color="danger" (click)="delete_group()">Confirm</button>
|
||||
<button [cModalToggle]="ConfirmModal.id" cButton color="secondary">
|
||||
Close
|
||||
</button>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
240
src/app/views/devices_group/devgroup.component.ts
Normal file
240
src/app/views/devices_group/devgroup.component.ts
Normal file
|
@ -0,0 +1,240 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import { dataProvider } from "../../providers/mikrowizard/data";
|
||||
import { Router } from "@angular/router";
|
||||
import { loginChecker } from "../../providers/login_checker";
|
||||
import {
|
||||
GuiSearching,
|
||||
GuiSelectedRow,
|
||||
GuiInfoPanel,
|
||||
GuiColumn,
|
||||
GuiColumnMenu,
|
||||
GuiPaging,
|
||||
GuiPagingDisplay,
|
||||
GuiRowSelectionMode,
|
||||
GuiRowSelection,
|
||||
GuiRowSelectionType,
|
||||
} from "@generic-ui/ngx-grid";
|
||||
|
||||
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: "devgroup.component.html",
|
||||
})
|
||||
export class DevicesGroupComponent implements OnInit {
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
|
||||
constructor(
|
||||
private data_provider: dataProvider,
|
||||
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;
|
||||
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 source: Array<any> = [];
|
||||
public columns: Array<GuiColumn> = [];
|
||||
public loading: boolean = true;
|
||||
public MemberRows: any = [];
|
||||
public NewMemberRows: any = [];
|
||||
|
||||
public SelectedMemberRows: any;
|
||||
public SelectedNewMemberRows: any;
|
||||
public ConfirmModalVisible: boolean = false;
|
||||
public ConfirmAction: string = "delete";
|
||||
public EditGroupModalVisible: boolean = false;
|
||||
public NewMemberModalVisible: boolean = false;
|
||||
public groupMembers: any = [];
|
||||
public availbleMembers: any = [];
|
||||
public currentGroup: any = {
|
||||
array_agg: [],
|
||||
created: "",
|
||||
id: 0,
|
||||
name: "",
|
||||
};
|
||||
public DefaultCurrentGroup: any = {
|
||||
array_agg: [],
|
||||
created: "",
|
||||
id: 0,
|
||||
name: "",
|
||||
};
|
||||
public sorting = {
|
||||
enabled: true,
|
||||
multiSorting: true,
|
||||
};
|
||||
|
||||
searching: GuiSearching = {
|
||||
enabled: true,
|
||||
placeholder: "Search Devices",
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
ngOnInit(): void {
|
||||
this.initGridTable();
|
||||
}
|
||||
|
||||
public show_members(id: number) {
|
||||
this.router.navigate(["devices", { id: id }]);
|
||||
}
|
||||
|
||||
public show_delete_group(item: any) {
|
||||
this.currentGroup = item;
|
||||
this.ConfirmModalVisible = true;
|
||||
this.ConfirmAction = "delete";
|
||||
}
|
||||
public delete_group() {
|
||||
var _self = this;
|
||||
this.data_provider.delete_group(this.currentGroup.id).then((res) => {
|
||||
_self.initGridTable();
|
||||
_self.ConfirmModalVisible = false;
|
||||
});
|
||||
}
|
||||
|
||||
onSelectedRowsMembers(rows: Array<GuiSelectedRow>): void {
|
||||
this.MemberRows = rows;
|
||||
this.SelectedMemberRows = rows.map((m: GuiSelectedRow) => m.source.id);
|
||||
}
|
||||
onSelectedRowsNewMembers(rows: Array<GuiSelectedRow>): void {
|
||||
this.NewMemberRows = rows;
|
||||
this.SelectedNewMemberRows = rows.map((m: GuiSelectedRow) => m.source.id);
|
||||
}
|
||||
add_new_members() {
|
||||
var _self = this;
|
||||
this.currentGroup["array_agg"] = [
|
||||
...new Set(
|
||||
this.currentGroup["array_agg"].concat(this.SelectedNewMemberRows)
|
||||
),
|
||||
];
|
||||
this.groupMembers = [
|
||||
...new Set(
|
||||
this.groupMembers.concat(
|
||||
this.NewMemberRows.map((m: GuiSelectedRow) => m.source)
|
||||
)
|
||||
),
|
||||
];
|
||||
this.NewMemberModalVisible = false;
|
||||
}
|
||||
remove_from_group(id: number) {
|
||||
var _self = this;
|
||||
this.currentGroup["array_agg"] = this.currentGroup["array_agg"].filter(
|
||||
(x: any) => x != id
|
||||
);
|
||||
this.groupMembers = this.groupMembers.filter((x: any) => x.id != id);
|
||||
}
|
||||
|
||||
save_group() {
|
||||
var _self = this;
|
||||
this.data_provider.update_save_group(this.currentGroup).then((res) => {
|
||||
_self.initGridTable();
|
||||
_self.EditGroupModalVisible = false;
|
||||
});
|
||||
}
|
||||
|
||||
editAddGroup(item: any, action: string) {
|
||||
var _self = this;
|
||||
if (action == "showadd") {
|
||||
this.currentGroup = { ...this.DefaultCurrentGroup };
|
||||
this.groupMembers = [];
|
||||
this.EditGroupModalVisible = true;
|
||||
return;
|
||||
}
|
||||
this.currentGroup = item;
|
||||
this.groupMembers = [];
|
||||
this.data_provider.get_devgroup_members(item.id).then((res) => {
|
||||
_self.groupMembers = res;
|
||||
_self.currentGroup = { ...item };
|
||||
// simple hack to remove null from devices list
|
||||
_self.currentGroup["array_agg"] = item["array_agg"].filter(
|
||||
(x: any) => x != null
|
||||
);
|
||||
_self.EditGroupModalVisible = true;
|
||||
});
|
||||
}
|
||||
|
||||
show_new_member_form() {
|
||||
this.NewMemberModalVisible = true;
|
||||
var _self = this;
|
||||
_self.availbleMembers = [];
|
||||
this.SelectedNewMemberRows = [];
|
||||
this.NewMemberRows = [];
|
||||
var data = {
|
||||
group_id: false,
|
||||
search: false,
|
||||
page: false,
|
||||
size: 10000,
|
||||
};
|
||||
_self.data_provider.get_dev_list(data).then((res) => {
|
||||
_self.availbleMembers = res.filter(
|
||||
(x: any) => !_self.currentGroup["array_agg"].includes(x.id)
|
||||
);
|
||||
_self.NewMemberModalVisible = true;
|
||||
});
|
||||
}
|
||||
|
||||
logger(item: any) {
|
||||
console.dir(item);
|
||||
}
|
||||
initGridTable(): void {
|
||||
this.data_provider.get_devgroup_list().then((res) => {
|
||||
this.source = res;
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
35
src/app/views/devices_group/devgroup.module.ts
Normal file
35
src/app/views/devices_group/devgroup.module.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
|
||||
import {
|
||||
ButtonGroupModule,
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
FormModule,
|
||||
GridModule,
|
||||
CollapseModule,
|
||||
ModalModule,
|
||||
} from "@coreui/angular";
|
||||
import { DevicesGroupRoutingModule } from "./devgroup-routing.module";
|
||||
import { DevicesGroupComponent } from "./devgroup.component";
|
||||
import { GuiGridModule } from "@generic-ui/ngx-grid";
|
||||
import { BadgeModule } from "@coreui/angular";
|
||||
import { FormsModule } from "@angular/forms";
|
||||
@NgModule({
|
||||
imports: [
|
||||
DevicesGroupRoutingModule,
|
||||
CardModule,
|
||||
CommonModule,
|
||||
GridModule,
|
||||
FormsModule,
|
||||
FormModule,
|
||||
ButtonModule,
|
||||
ButtonGroupModule,
|
||||
GuiGridModule,
|
||||
CollapseModule,
|
||||
ModalModule,
|
||||
BadgeModule,
|
||||
],
|
||||
declarations: [DevicesGroupComponent],
|
||||
})
|
||||
export class DevicesGroupModule {}
|
16
src/app/views/icons/coreui-icons.component.html
Normal file
16
src/app/views/icons/coreui-icons.component.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
<div class="fade-in">
|
||||
<c-card>
|
||||
<c-card-header>
|
||||
{{ title }}
|
||||
<app-docs-link href="https://github.com/coreui/coreui-icons" text="GitHub"></app-docs-link>
|
||||
</c-card-header>
|
||||
<c-card-body>
|
||||
<c-row class="text-center">
|
||||
<c-col *ngFor="let icon of icons" class="mb-5" md="3" sm="4" xl="2" xs="6">
|
||||
<svg cIcon [name]="icon[0]" [title]="icon[0]" size="3xl"></svg>
|
||||
<div>{{ toKebabCase(icon[0]) }}</div>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
</div>
|
46
src/app/views/icons/coreui-icons.component.ts
Normal file
46
src/app/views/icons/coreui-icons.component.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
import { IconSetService } from '@coreui/icons-angular';
|
||||
import { brandSet, flagSet, freeSet } from '@coreui/icons';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'coreui-icons.component.html',
|
||||
providers: [IconSetService],
|
||||
})
|
||||
export class CoreUIIconsComponent implements OnInit {
|
||||
public title = 'CoreUI Icons';
|
||||
public icons!: [string, string[]][];
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute, public iconSet: IconSetService
|
||||
) {
|
||||
iconSet.icons = { ...freeSet, ...brandSet, ...flagSet };
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const path = this.route?.routeConfig?.path;
|
||||
let prefix = 'cil';
|
||||
if (path === 'coreui-icons') {
|
||||
this.title = `${this.title} - Free`;
|
||||
prefix = 'cil';
|
||||
} else if (path === 'brands') {
|
||||
this.title = `${this.title} - Brands`;
|
||||
prefix = 'cib';
|
||||
} else if (path === 'flags') {
|
||||
this.title = `${this.title} - Flags`;
|
||||
prefix = 'cif';
|
||||
}
|
||||
this.icons = this.getIconsView(prefix);
|
||||
}
|
||||
|
||||
toKebabCase(str: string) {
|
||||
return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase();
|
||||
}
|
||||
|
||||
getIconsView(prefix: string) {
|
||||
return Object.entries(this.iconSet.icons).filter((icon) => {
|
||||
return icon[0].startsWith(prefix);
|
||||
});
|
||||
}
|
||||
}
|
48
src/app/views/icons/icons-routing.module.ts
Normal file
48
src/app/views/icons/icons-routing.module.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { CoreUIIconsComponent } from './coreui-icons.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
data: {
|
||||
title: 'Icons'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
redirectTo: 'coreui-icons'
|
||||
},
|
||||
{
|
||||
path: 'coreui-icons',
|
||||
component: CoreUIIconsComponent,
|
||||
data: {
|
||||
title: 'CoreUI Icons'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'brands',
|
||||
component: CoreUIIconsComponent,
|
||||
data: {
|
||||
title: 'Brands'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'flags',
|
||||
component: CoreUIIconsComponent,
|
||||
data: {
|
||||
title: 'Flags'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class IconsRoutingModule {
|
||||
}
|
25
src/app/views/icons/icons.module.ts
Normal file
25
src/app/views/icons/icons.module.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { CardModule, GridModule } from '@coreui/angular';
|
||||
import { IconModule } from '@coreui/icons-angular';
|
||||
|
||||
import { CoreUIIconsComponent } from './coreui-icons.component';
|
||||
import { IconsRoutingModule } from './icons-routing.module';
|
||||
import { DocsComponentsModule } from '@docs-components/docs-components.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
IconsRoutingModule,
|
||||
CardModule,
|
||||
GridModule,
|
||||
IconModule,
|
||||
CommonModule,
|
||||
DocsComponentsModule
|
||||
],
|
||||
declarations: [
|
||||
CoreUIIconsComponent
|
||||
]
|
||||
})
|
||||
export class IconsModule {
|
||||
}
|
51
src/app/views/pages/login/login.component.html
Normal file
51
src/app/views/pages/login/login.component.html
Normal file
|
@ -0,0 +1,51 @@
|
|||
<div class="bg-light min-vh-100 d-flex flex-row align-items-center">
|
||||
<c-container>
|
||||
<c-row class="justify-content-center">
|
||||
<c-col md="8">
|
||||
<c-card-group>
|
||||
<c-card [ngStyle]="{'width.%': 44}" class="text-white py-5" style="background-color: #303c54;">
|
||||
<c-card-body class="text-center">
|
||||
<img style="width: 200px;" src="assets/img/brand/mikrowizard-full.jpg">
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
<c-card class="p-4">
|
||||
<c-card-body>
|
||||
<form cForm [formGroup]="loginForm" >
|
||||
<h1>Login</h1>
|
||||
<p class="text-medium-emphasis">Sign In to your account</p>
|
||||
<c-input-group class="mb-3">
|
||||
<span cInputGroupText>
|
||||
<svg cIcon name="cilUser"></svg>
|
||||
</span>
|
||||
<input autoComplete="username" cFormControl placeholder="Username" formControlName="username" required #username/>
|
||||
</c-input-group>
|
||||
<c-input-group class="mb-1">
|
||||
<span cInputGroupText>
|
||||
<svg cIcon name="cilLockLocked"></svg>
|
||||
</span>
|
||||
<input
|
||||
autoComplete="current-password"
|
||||
cFormControl
|
||||
placeholder="Password"
|
||||
type="password"
|
||||
formControlName="password"
|
||||
required #password
|
||||
/>
|
||||
</c-input-group>
|
||||
<code *ngIf="error_msg"><i class="fa-solid fa-triangle-exclamation"></i><small> {{error_msg}}</small></code>
|
||||
<c-row>
|
||||
<c-col mb-3 xs="6">
|
||||
<button type="submit" cButton (click)="onClickSubmit()" class="px-4" color="primary">
|
||||
Login
|
||||
</button>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</form>
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
|
||||
</c-card-group>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-container>
|
||||
</div>
|
0
src/app/views/pages/login/login.component.scss
Normal file
0
src/app/views/pages/login/login.component.scss
Normal file
35
src/app/views/pages/login/login.component.spec.ts
Normal file
35
src/app/views/pages/login/login.component.spec.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ButtonModule, CardModule, FormModule, GridModule } from '@coreui/angular';
|
||||
import { LoginComponent } from './login.component';
|
||||
import { IconModule } from '@coreui/icons-angular';
|
||||
import { IconSetService } from '@coreui/icons-angular';
|
||||
import { iconSubset } from '../../../icons/icon-subset';
|
||||
|
||||
describe('LoginComponent', () => {
|
||||
let component: LoginComponent;
|
||||
let fixture: ComponentFixture<LoginComponent>;
|
||||
let iconSetService: IconSetService;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ LoginComponent ],
|
||||
imports: [FormModule, CardModule, GridModule, ButtonModule, IconModule],
|
||||
providers: [IconSetService]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
iconSetService = TestBed.inject(IconSetService);
|
||||
iconSetService.icons = { ...iconSubset };
|
||||
|
||||
fixture = TestBed.createComponent(LoginComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
66
src/app/views/pages/login/login.component.ts
Normal file
66
src/app/views/pages/login/login.component.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { dataProvider } from '../../../providers/mikrowizard/data';
|
||||
import { loginChecker } from '../../../providers/login_checker';
|
||||
import { Validators, FormControl, FormGroup} from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
templateUrl: './login.component.html',
|
||||
styleUrls: ['./login.component.scss']
|
||||
})
|
||||
export class LoginComponent {
|
||||
public loginForm: FormGroup;
|
||||
public forgotForm: FormGroup;
|
||||
public error_msg: string = "";
|
||||
public forgot_error_msg: string = "";
|
||||
public success_msg: string = "";
|
||||
public submitted = false;
|
||||
public forgot_page: boolean = false;
|
||||
public forgot_btn_disable: boolean = false;
|
||||
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private data_provider: dataProvider,
|
||||
private login_checker: loginChecker,
|
||||
) {
|
||||
this.createForm();
|
||||
};
|
||||
|
||||
createForm() {
|
||||
this.loginForm = new FormGroup({
|
||||
username: new FormControl(''),
|
||||
password: new FormControl(''),
|
||||
ga_code: new FormControl(''),
|
||||
});
|
||||
this.forgotForm = new FormGroup({
|
||||
email: new FormControl(''),
|
||||
});
|
||||
}
|
||||
|
||||
onClickSubmit(){
|
||||
var _self = this;
|
||||
let uname = _self.loginForm.get('username')!.value;
|
||||
let passwd = _self.loginForm.get('password')!.value;
|
||||
let ga_code = '';
|
||||
console.dir(uname);
|
||||
_self.data_provider.login(uname, passwd, '').then(res => {
|
||||
if ('uid' in res && res['uid']){
|
||||
_self.error_msg = "";
|
||||
_self.login_checker.setStatus(true);
|
||||
_self.router.navigate(['/'], {replaceUrl: true});
|
||||
}
|
||||
else {
|
||||
if ('reason' in res) {
|
||||
}
|
||||
else
|
||||
_self.error_msg = res.error;
|
||||
}
|
||||
}).catch(err => {
|
||||
_self.error_msg = "Wrong username or password!";
|
||||
});
|
||||
// });
|
||||
}
|
||||
|
||||
}
|
22
src/app/views/pages/page404/page404.component.html
Normal file
22
src/app/views/pages/page404/page404.component.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<div class="bg-light min-vh-100 d-flex flex-row align-items-center">
|
||||
<c-container>
|
||||
<c-row class="justify-content-center">
|
||||
<c-col md="6">
|
||||
<div class="clearfix">
|
||||
<h1 class="float-start display-3 me-4">404</h1>
|
||||
<h4 class="pt-3">Oops! You're lost.</h4>
|
||||
<p class="text-medium-emphasis float-start">
|
||||
The page you are looking for was not found.
|
||||
</p>
|
||||
</div>
|
||||
<c-input-group class="input-prepend">
|
||||
<span cInputGroupText>
|
||||
<svg cIcon name="cilMagnifyingGlass"></svg>
|
||||
</span>
|
||||
<input cFormControl placeholder="What are you looking for?" type="text" />
|
||||
<button cButton color="info">Search</button>
|
||||
</c-input-group>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-container>
|
||||
</div>
|
0
src/app/views/pages/page404/page404.component.scss
Normal file
0
src/app/views/pages/page404/page404.component.scss
Normal file
35
src/app/views/pages/page404/page404.component.spec.ts
Normal file
35
src/app/views/pages/page404/page404.component.spec.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ButtonModule, FormModule, GridModule } from '@coreui/angular';
|
||||
import { IconModule } from '@coreui/icons-angular';
|
||||
import { IconSetService } from '@coreui/icons-angular';
|
||||
import { iconSubset } from '../../../icons/icon-subset';
|
||||
import { Page404Component } from './page404.component';
|
||||
|
||||
describe('Page404Component', () => {
|
||||
let component: Page404Component;
|
||||
let fixture: ComponentFixture<Page404Component>;
|
||||
let iconSetService: IconSetService;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ Page404Component ],
|
||||
imports: [FormModule, GridModule, ButtonModule, IconModule],
|
||||
providers: [IconSetService]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
iconSetService = TestBed.inject(IconSetService);
|
||||
iconSetService.icons = { ...iconSubset };
|
||||
|
||||
fixture = TestBed.createComponent(Page404Component);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
12
src/app/views/pages/page404/page404.component.ts
Normal file
12
src/app/views/pages/page404/page404.component.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-page404',
|
||||
templateUrl: './page404.component.html',
|
||||
styleUrls: ['./page404.component.scss']
|
||||
})
|
||||
export class Page404Component {
|
||||
|
||||
constructor() { }
|
||||
|
||||
}
|
22
src/app/views/pages/page500/page500.component.html
Normal file
22
src/app/views/pages/page500/page500.component.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<div class="bg-light min-vh-100 d-flex flex-row align-items-center">
|
||||
<c-container>
|
||||
<c-row class="justify-content-center">
|
||||
<c-col md="6">
|
||||
<span class="clearfix">
|
||||
<h1 class="float-start display-3 me-4">500</h1>
|
||||
<h4 class="pt-3">Houston, we have a problem!</h4>
|
||||
<p class="text-medium-emphasis float-start">
|
||||
The page you are looking for is temporarily unavailable.
|
||||
</p>
|
||||
</span>
|
||||
<c-input-group class="input-prepend">
|
||||
<span cInputGroupText>
|
||||
<svg cIcon name="cilMagnifyingGlass"></svg>
|
||||
</span>
|
||||
<input cFormControl placeholder="What are you looking for?" type="text" />
|
||||
<button cButton color="info">Search</button>
|
||||
</c-input-group>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-container>
|
||||
</div>
|
0
src/app/views/pages/page500/page500.component.scss
Normal file
0
src/app/views/pages/page500/page500.component.scss
Normal file
35
src/app/views/pages/page500/page500.component.spec.ts
Normal file
35
src/app/views/pages/page500/page500.component.spec.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ButtonModule, FormModule, GridModule } from '@coreui/angular';
|
||||
import { IconModule } from '@coreui/icons-angular';
|
||||
import { IconSetService } from '@coreui/icons-angular';
|
||||
import { iconSubset } from '../../../icons/icon-subset';
|
||||
import { Page500Component } from './page500.component';
|
||||
|
||||
describe('Page500Component', () => {
|
||||
let component: Page500Component;
|
||||
let fixture: ComponentFixture<Page500Component>;
|
||||
let iconSetService: IconSetService;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ Page500Component ],
|
||||
imports: [GridModule, ButtonModule, FormModule, IconModule],
|
||||
providers: [IconSetService]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
iconSetService = TestBed.inject(IconSetService);
|
||||
iconSetService.icons = { ...iconSubset };
|
||||
|
||||
fixture = TestBed.createComponent(Page500Component);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
12
src/app/views/pages/page500/page500.component.ts
Normal file
12
src/app/views/pages/page500/page500.component.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-page500',
|
||||
templateUrl: './page500.component.html',
|
||||
styleUrls: ['./page500.component.scss']
|
||||
})
|
||||
export class Page500Component {
|
||||
|
||||
constructor() { }
|
||||
|
||||
}
|
36
src/app/views/pages/pages-routing.module.ts
Normal file
36
src/app/views/pages/pages-routing.module.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { Page404Component } from './page404/page404.component';
|
||||
import { Page500Component } from './page500/page500.component';
|
||||
import { LoginComponent } from './login/login.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '404',
|
||||
component: Page404Component,
|
||||
data: {
|
||||
title: 'Page 404'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '500',
|
||||
component: Page500Component,
|
||||
data: {
|
||||
title: 'Page 500'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'login',
|
||||
component: LoginComponent,
|
||||
data: {
|
||||
title: 'Login Page'
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PagesRoutingModule {
|
||||
}
|
32
src/app/views/pages/pages.module.ts
Normal file
32
src/app/views/pages/pages.module.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { PagesRoutingModule } from './pages-routing.module';
|
||||
import { LoginComponent } from './login/login.component';
|
||||
import { Page404Component } from './page404/page404.component';
|
||||
import { Page500Component } from './page500/page500.component';
|
||||
import { ButtonModule, CardModule, FormModule, GridModule } from '@coreui/angular';
|
||||
import { IconModule } from '@coreui/icons-angular';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
LoginComponent,
|
||||
Page404Component,
|
||||
Page500Component
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
PagesRoutingModule,
|
||||
CardModule,
|
||||
ButtonModule,
|
||||
GridModule,
|
||||
IconModule,
|
||||
FormModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule
|
||||
]
|
||||
})
|
||||
export class PagesModule {
|
||||
}
|
21
src/app/views/permissions/permissions-routing.module.ts
Normal file
21
src/app/views/permissions/permissions-routing.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { PermissionsComponent } from './permissions.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: PermissionsComponent,
|
||||
data: {
|
||||
title: $localize`Permissions`
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PermissionsRoutingModule {
|
||||
}
|
137
src/app/views/permissions/permissions.component.html
Normal file
137
src/app/views/permissions/permissions.component.html
Normal file
|
@ -0,0 +1,137 @@
|
|||
<c-row>
|
||||
<c-col xs>
|
||||
<c-card class="mb-4">
|
||||
<c-card-header>
|
||||
<c-row>
|
||||
<c-col xs [lg]="10">
|
||||
Permissions
|
||||
</c-col>
|
||||
<c-col xs [lg]="2" style="text-align: right;">
|
||||
<button cButton color="primary" (click)="editAddTask({},'showadd')"><i
|
||||
class="fa-solid fa-plus"></i></button>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-card-header>
|
||||
<c-card-body>
|
||||
<gui-grid [rowHeight]="82" [autoResizeWidth]="true" [source]="source" [columnMenu]="columnMenu"
|
||||
[sorting]="sorting" [autoResizeWidth]=true [paging]="paging">
|
||||
<gui-grid-column header="Name" field="name">
|
||||
<ng-template let-value="item.name" let-item="item" let-index="index">
|
||||
{{value}} </ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column width="auto" header="Perms" field="perms">
|
||||
<ng-template let-value="item.role" let-item="item" let-index="index">
|
||||
<div style="text-wrap: initial;">
|
||||
<ng-container *ngFor="let perm of item['perms'] | keyvalue">
|
||||
<c-badge *ngIf="perm.value" class="m-1" color="success">{{perm.key}}</c-badge>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Actions" width="120" field="action">
|
||||
<ng-template let-value="item.id" let-item="item" let-index="index">
|
||||
<button cButton color="warning" size="sm" class="mx-1" (click)="editAddTask(item,'edit');"><i
|
||||
class="fa-regular fa-pen-to-square"></i></button>
|
||||
<button cButton color="danger" size="sm" (click)="confirm_delete(item);"><i
|
||||
class="fa-regular fa-trash-can"></i></button>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
||||
<c-modal-header>
|
||||
|
||||
|
||||
<c-modal #EditTaskModal backdrop="static" size="lg" [(visible)]="EditTaskModalVisible" id="EditTaskModal">
|
||||
<c-modal-header>
|
||||
<h5 *ngIf="action=='edit'" cModalTitle>Editing Permission {{SelectedPerm['name']}}</h5>
|
||||
<h5 *ngIf="action=='add'" cModalTitle>Adding new Permission Rule</h5>
|
||||
<button [cModalToggle]="EditTaskModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
|
||||
<div [cFormFloating]="true" class="mb-3">
|
||||
<input cFormControl id="floatingInput" placeholder="permname" [(ngModel)]="permname" />
|
||||
<label cLabel for="floatingInput">Name</label>
|
||||
</div>
|
||||
<c-row>
|
||||
<c-col>
|
||||
<c-form-check *ngFor='let val of ["api","ftp","password","read","romon","sniff","telnet","tikapp","winbox"]'
|
||||
[switch]="true">
|
||||
<input cFormCheckInput [(ngModel)]="perms[val] " type="checkbox" />
|
||||
<label cFormCheckLabel>{{ val}}</label>
|
||||
</c-form-check>
|
||||
</c-col>
|
||||
<c-col>
|
||||
<c-form-check
|
||||
*ngFor='let val of ["dude","local","policy","reboot","rest-api","sensitive","ssh","test","web","write"]'
|
||||
[switch]="true">
|
||||
<input cFormCheckInput [(ngModel)]="perms[val] " type="checkbox" />
|
||||
<label cFormCheckLabel>{{ val}}</label>
|
||||
</c-form-check>
|
||||
</c-col>
|
||||
</c-row>
|
||||
<ng-container *ngIf="SelectedMembers.length>0 && EditTaskModalVisible">
|
||||
<c-badge class="mx-1" *ngFor="let id of splitids(SelectedPermItems)"
|
||||
color="dark">{{get_member_by_id(id).name}}</c-badge>
|
||||
</ng-container>
|
||||
<!--
|
||||
<c-input-group class="mb-3">
|
||||
<cron-editor #cronEditorDemo1 [(ngModel)]="SelectedPerm['cron']" [options]="cronOptions">Cron here...</cron-editor>
|
||||
</c-input-group>
|
||||
-->
|
||||
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<button *ngIf="action=='add'" (click)="submit('add')" cButton color="primary">Add</button>
|
||||
<button *ngIf="action=='edit'" (click)="submit('edit')" cButton color="primary">save</button>
|
||||
<button [cModalToggle]="EditTaskModal.id" cButton color="secondary">
|
||||
Close
|
||||
</button>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
||||
|
||||
|
||||
<c-modal #DeleteConfirmModal backdrop="static" [(visible)]="DeleteConfirmModalVisible" id="DeleteConfirmModal">
|
||||
<c-modal-header>
|
||||
<h5 cModalTitle>Confirm delete {{ SelectedPerm['name'] }}</h5>
|
||||
<button [cModalToggle]="DeleteConfirmModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
Are you sure that You want to delete following Permission?
|
||||
<br />
|
||||
<br />
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td><b>Permission name : </b>{{ SelectedPerm['name'] }}
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ng-container *ngFor="let perm of SelectedPerm['perms'] | keyvalue">
|
||||
<c-badge *ngIf="perm.value" class="m-1" color="success">{{perm.key}}</c-badge>
|
||||
</ng-container>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p><code
|
||||
style="padding: 0!important;"><b>Warning:</b> ALL Given <b>device access</b> related to this permision in Users Section <b>will be deleted</b> for each user</code>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<button (click)="confirm_delete('',true)" cButton color="danger">
|
||||
Yes,Delete!
|
||||
</button>
|
||||
<button [cModalToggle]="DeleteConfirmModal.id" cButton color="info">
|
||||
Close
|
||||
</button>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
||||
|
||||
|
||||
<c-toaster position="fixed" placement="top-end"></c-toaster>
|
260
src/app/views/permissions/permissions.component.ts
Normal file
260
src/app/views/permissions/permissions.component.ts
Normal file
|
@ -0,0 +1,260 @@
|
|||
import { Component, OnInit, QueryList, ViewChildren } from "@angular/core";
|
||||
import { dataProvider } from "../../providers/mikrowizard/data";
|
||||
import { Router } from "@angular/router";
|
||||
import { loginChecker } from "../../providers/login_checker";
|
||||
import {
|
||||
GuiColumn,
|
||||
GuiColumnMenu,
|
||||
GuiPaging,
|
||||
GuiPagingDisplay,
|
||||
} from "@generic-ui/ngx-grid";
|
||||
|
||||
import { ToasterComponent } from "@coreui/angular";
|
||||
import { AppToastComponent } from "../toast-simple/toast.component";
|
||||
|
||||
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: "permissions.component.html",
|
||||
})
|
||||
export class PermissionsComponent implements OnInit {
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
|
||||
constructor(
|
||||
private data_provider: dataProvider,
|
||||
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;
|
||||
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 !== "";
|
||||
}
|
||||
}
|
||||
@ViewChildren(ToasterComponent) viewChildren!: QueryList<ToasterComponent>;
|
||||
|
||||
public source: Array<any> = [];
|
||||
public columns: Array<GuiColumn> = [];
|
||||
public loading: boolean = true;
|
||||
public rows: any = [];
|
||||
public SelectedPerm: any = {};
|
||||
public SelectedPermItems: string = "";
|
||||
|
||||
public EditTaskModalVisible: boolean = false;
|
||||
public DeleteConfirmModalVisible: boolean = false;
|
||||
public Members: any = "";
|
||||
public SelectedMembers: any = [];
|
||||
|
||||
public action: string = "add";
|
||||
public permid: number = 0;
|
||||
public permname: string = "";
|
||||
public perms: { [index: string]: boolean } = {
|
||||
api: false,
|
||||
ftp: false,
|
||||
password: false,
|
||||
read: false,
|
||||
romon: false,
|
||||
sniff: false,
|
||||
telnet: false,
|
||||
tikapp: false,
|
||||
winbox: false,
|
||||
dude: false,
|
||||
local: false,
|
||||
policy: false,
|
||||
reboot: false,
|
||||
"rest-api": false,
|
||||
sensitive: false,
|
||||
ssh: false,
|
||||
test: false,
|
||||
web: false,
|
||||
write: false,
|
||||
};
|
||||
|
||||
toasterForm = {
|
||||
autohide: true,
|
||||
delay: 3000,
|
||||
position: "fixed",
|
||||
fade: true,
|
||||
closeButton: true,
|
||||
};
|
||||
|
||||
public sorting = {
|
||||
enabled: true,
|
||||
multiSorting: true,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
show_toast(title: string, body: string, color: string) {
|
||||
const { ...props } = { ...this.toasterForm, color, title, body };
|
||||
const componentRef = this.viewChildren.first.addToast(
|
||||
AppToastComponent,
|
||||
props,
|
||||
{}
|
||||
);
|
||||
componentRef.instance["closeButton"] = props.closeButton;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.initGridTable();
|
||||
}
|
||||
submit(action: string) {
|
||||
var _self = this;
|
||||
if (action == "add") {
|
||||
this.data_provider
|
||||
.create_perm(_self.permname, _self.perms)
|
||||
.then((res) => {
|
||||
if (res["status"] == "failed") {
|
||||
_self.show_toast(
|
||||
"Error",
|
||||
res.err,
|
||||
"danger"
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
_self.initGridTable();
|
||||
this.EditTaskModalVisible = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.data_provider
|
||||
.edit_perm(_self.permid, _self.permname, _self.perms)
|
||||
.then((res) => {
|
||||
if (res["status"] == "failed") {
|
||||
_self.show_toast(
|
||||
"Error",
|
||||
res.err,
|
||||
"danger"
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
_self.initGridTable();
|
||||
this.EditTaskModalVisible = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
editAddTask(item: any, action: string) {
|
||||
if (action == "showadd") {
|
||||
this.permname = item["name"];
|
||||
this.perms = {
|
||||
api: false,
|
||||
ftp: false,
|
||||
password: false,
|
||||
read: false,
|
||||
romon: false,
|
||||
sniff: false,
|
||||
telnet: false,
|
||||
tikapp: false,
|
||||
winbox: false,
|
||||
dude: false,
|
||||
local: false,
|
||||
policy: false,
|
||||
reboot: false,
|
||||
"rest-api": false,
|
||||
sensitive: false,
|
||||
ssh: false,
|
||||
test: false,
|
||||
web: false,
|
||||
write: false,
|
||||
};
|
||||
this.permid = 0;
|
||||
this.action = "add";
|
||||
this.EditTaskModalVisible = true;
|
||||
return;
|
||||
}
|
||||
this.action = "edit";
|
||||
this.permname = item["name"];
|
||||
this.perms = item.perms;
|
||||
this.permid = item["id"];
|
||||
this.EditTaskModalVisible = true;
|
||||
}
|
||||
|
||||
splitids(ids: string = "") {
|
||||
return ids.split(",");
|
||||
}
|
||||
|
||||
get_member_by_id(id: string) {
|
||||
return this.Members.find((x: any) => x.id == id);
|
||||
}
|
||||
|
||||
confirm_delete(item: any = "", del: boolean = false) {
|
||||
if (!del) {
|
||||
this.SelectedPerm = { ...item };
|
||||
this.DeleteConfirmModalVisible = true;
|
||||
} else {
|
||||
var _self = this;
|
||||
this.data_provider.delete_perm(_self.SelectedPerm["id"]).then((res) => {
|
||||
if (res["status"] == "failed") {
|
||||
_self.show_toast(
|
||||
"Error",
|
||||
res.err,
|
||||
"danger"
|
||||
);
|
||||
return;
|
||||
}
|
||||
else{
|
||||
_self.initGridTable();
|
||||
_self.DeleteConfirmModalVisible = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
logger(item: any) {
|
||||
console.dir(item);
|
||||
}
|
||||
|
||||
initGridTable(): void {
|
||||
var _self = this;
|
||||
var page = 1;
|
||||
var pageSize = 10;
|
||||
var searchstr = "";
|
||||
this.data_provider.get_perms(page, pageSize, searchstr).then((res) => {
|
||||
_self.source = res.map((x: any) => {
|
||||
return x;
|
||||
});
|
||||
_self.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
43
src/app/views/permissions/permissions.module.ts
Normal file
43
src/app/views/permissions/permissions.module.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { FormsModule } from "@angular/forms";
|
||||
|
||||
import {
|
||||
ButtonGroupModule,
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
FormModule,
|
||||
GridModule,
|
||||
NavModule,
|
||||
TabsModule,
|
||||
ModalModule,
|
||||
BadgeModule,
|
||||
ToastModule,
|
||||
} from "@coreui/angular";
|
||||
import { IconModule } from "@coreui/icons-angular";
|
||||
|
||||
import { PermissionsRoutingModule } from "./permissions-routing.module";
|
||||
import { PermissionsComponent } from "./permissions.component";
|
||||
import { GuiGridModule } from "@generic-ui/ngx-grid";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
PermissionsRoutingModule,
|
||||
CardModule,
|
||||
NavModule,
|
||||
IconModule,
|
||||
TabsModule,
|
||||
CommonModule,
|
||||
GridModule,
|
||||
ToastModule,
|
||||
FormModule,
|
||||
ButtonModule,
|
||||
ButtonGroupModule,
|
||||
GuiGridModule,
|
||||
ModalModule,
|
||||
FormsModule,
|
||||
BadgeModule,
|
||||
],
|
||||
declarations: [PermissionsComponent],
|
||||
})
|
||||
export class PermissionsModule {}
|
21
src/app/views/settings/settings-routing.module.ts
Normal file
21
src/app/views/settings/settings-routing.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { SettingsComponent } from './settings.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: SettingsComponent,
|
||||
data: {
|
||||
title: $localize`Settings`
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class SettingsRoutingModule {
|
||||
}
|
227
src/app/views/settings/settings.component.html
Normal file
227
src/app/views/settings/settings.component.html
Normal file
|
@ -0,0 +1,227 @@
|
|||
<c-row>
|
||||
<c-col xs>
|
||||
<c-card class="mb-4">
|
||||
<c-card-header>Firmware Manager</c-card-header>
|
||||
<c-card-body>
|
||||
<c-input-group class="mb-3">
|
||||
<h5>Firmware in repository:</h5>
|
||||
<gui-grid [autoResizeWidth]="true" [source]="source" [columnMenu]="columnMenu" [sorting]="sorting"
|
||||
[infoPanel]="infoPanel" [autoResizeWidth]=true [paging]="paging">
|
||||
<gui-grid-column header="Version" field="version">
|
||||
<ng-template let-value="item.version" let-item="item" let-index="index">
|
||||
{{value}} </ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="arch" field="architecture">
|
||||
<ng-template let-value="item.architecture" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="sha256" field="sha256">
|
||||
<ng-template let-value="item.sha256" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
</c-input-group>
|
||||
|
||||
<hr />
|
||||
<table>
|
||||
<td>
|
||||
<span>Add new Permission</span>
|
||||
</td>
|
||||
<td *ngIf="loading">
|
||||
<button cButton class="m-1" disabled>
|
||||
<c-spinner aria-hidden="true" size="sm"></c-spinner>
|
||||
Fetching Information from mikrotik website...
|
||||
</button>
|
||||
</td>
|
||||
<td *ngIf="!loading">
|
||||
<mat-form-field>
|
||||
<mat-select cFormControl [(ngModel)]="firmtodownload" placeholder="Select Version For Download Group"
|
||||
#singleSelect>
|
||||
<mat-option>
|
||||
<ngx-mat-select-search placeholderLabel="Search"
|
||||
[hideClearSearchButton]="true"></ngx-mat-select-search>
|
||||
</mat-option>
|
||||
<mat-option *ngFor="let firm of firms" [value]="firm">
|
||||
{{firm}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</td>
|
||||
<td>
|
||||
<button *ngIf="!loading" cButton color="primary" (click)="ConfirmModalVisible=true">Download to
|
||||
repository</button>
|
||||
<!-- <button *ngIf="SelectedUser['action']=='add'" cButton color="primary" (click)="loading=!loading">++</button> -->
|
||||
</td>
|
||||
</table>
|
||||
|
||||
<hr />
|
||||
<c-input-group class="mb-3">
|
||||
<label cInputGroupText for="inputGroupSelect01">
|
||||
V6 Firmware update Behavior
|
||||
</label>
|
||||
<select cSelect [(ngModel)]="updateBehavior" id="inputGroupSelect01">
|
||||
<option>Choose...</option>
|
||||
<option value="keep">Keep v6 and don't update to v7</option>
|
||||
<option value="update">install latest</option>
|
||||
</select>
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* Choose how Mikrowizard should update old v6 firmwares</c-form-feedback>
|
||||
</c-input-group>
|
||||
|
||||
<c-input-group class="mb-3">
|
||||
<label cInputGroupText for="inputGroupSelect01">
|
||||
Firmware version to install
|
||||
</label>
|
||||
<select cSelect [(ngModel)]="firmwaretoinstall" id="inputGroupSelect01">
|
||||
<option>Choose...</option>
|
||||
<option *ngFor="let f of available_firmwares" [value]="f">{{f}}</option>
|
||||
|
||||
</select>
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* The version of firmware to install routers</c-form-feedback>
|
||||
</c-input-group>
|
||||
|
||||
<c-input-group *ngIf="updateBehavior=='keep'" class="mb-3">
|
||||
<label cInputGroupText for="inputGroupSelect01">
|
||||
Firmware version v6 to install
|
||||
</label>
|
||||
<select cSelect [(ngModel)]="firmwaretoinstallv6" id="inputGroupSelect01">
|
||||
<option>Choose...</option>
|
||||
<option *ngFor="let f of available_firmwaresv6" [value]="f">{{f}}</option>
|
||||
</select>
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* The version of firmware to install on V6 routers</c-form-feedback>
|
||||
</c-input-group>
|
||||
<button cButton color="primary" (click)="saveFirmwareSetting()">Save</button>
|
||||
</c-card-body>
|
||||
|
||||
</c-card>
|
||||
<c-card class="mb-4">
|
||||
<c-card-header>System Settings</c-card-header>
|
||||
<c-card-body *ngIf="!SysConfigloading">
|
||||
|
||||
<c-input-group class="mt-3">
|
||||
<span cInputGroupText>Rad Secret</span>
|
||||
<input cFormControl id="floatingInput" placeholder="rad_secret"
|
||||
[(ngModel)]="sysconfigs['rad_secret']['value']" />
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* Radius Secret of Mikrowizard Radius Server</c-form-feedback>
|
||||
</c-input-group>
|
||||
|
||||
|
||||
<c-input-group class="mt-3">
|
||||
<span cInputGroupText>System URL</span>
|
||||
<input cFormControl id="floatingInput" placeholder="System URL"
|
||||
[(ngModel)]="sysconfigs['system_url']['value']" />
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* Default system access URl</c-form-feedback>
|
||||
</c-input-group>
|
||||
|
||||
<c-input-group class="mt-3">
|
||||
<span cInputGroupText>Default IP</span>
|
||||
<input cFormControl id="floatingInput" placeholder="System URL"
|
||||
[(ngModel)]="sysconfigs['default_ip']['value']" />
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* Default Mikrowizard Access IP</c-form-feedback>
|
||||
</c-input-group>
|
||||
<c-input-group class="mt-3">
|
||||
<span cInputGroupText>System Time Zone</span>
|
||||
<mat-form-field class="form-control" subscriptSizing="dynamic">
|
||||
<mat-label>Select event type</mat-label>
|
||||
<mat-select cFormControl [(ngModel)]="sysconfigs['timezone']['value']"
|
||||
placeholder="Select Version For Download Group" #singleSelect>
|
||||
<mat-option>
|
||||
<ngx-mat-select-search placeholderLabel="Search" [hideClearSearchButton]="true"></ngx-mat-select-search>
|
||||
</mat-option>
|
||||
<mat-option *ngFor="let tz of timezones" [value]="tz.utc[0]">
|
||||
{{tz.text}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* Default TimeZone for the system</c-form-feedback>
|
||||
</c-input-group>
|
||||
|
||||
|
||||
<c-input-group class="mt-3">
|
||||
<span cInputGroupText>Default User</span>
|
||||
<input aria-label="Username" type="password" [(ngModel)]="sysconfigs['default_user']['value']" cFormControl />
|
||||
<span cInputGroupText>Default password</span>
|
||||
<input aria-label="Password" type="password" [(ngModel)]="sysconfigs['default_password']['value']"
|
||||
cFormControl />
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* Default username and Password for searching new devices</c-form-feedback>
|
||||
</c-input-group>
|
||||
<c-input-group class="mt-3 mb-3">
|
||||
<span cInputGroupText>License Username</span>
|
||||
<input aria-label="Username" type="text" [(ngModel)]="sysconfigs['username']['value']" cFormControl />
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* The username that you registred in Mikrowizard.com,Required for License Activation</c-form-feedback>
|
||||
</c-input-group>
|
||||
|
||||
<c-form-check [switch]="true" sizing="xl">
|
||||
<input cFormCheckInput [(ngModel)]="sysconfigs['force_perms']['value']" type="checkbox" />
|
||||
<label cFormCheckLabel>Force Perms</label>
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* Force User Groups under user>groups configuration of each router to match Mikrowizard Permissions and
|
||||
monitor for any change to prevent/fix the configuration.</c-form-feedback>
|
||||
</c-form-check>
|
||||
|
||||
<c-form-check [switch]="true" sizing="xl">
|
||||
<input cFormCheckInput [(ngModel)]="sysconfigs['force_radius']['value']" type="checkbox" />
|
||||
<label cFormCheckLabel>Force Radius</label>
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* Force Radius config under radius>client and user>aaa setting of each router that added to Mikrowizard and
|
||||
monitor for any change to prevent/fix the configuration.</c-form-feedback>
|
||||
</c-form-check>
|
||||
|
||||
<c-form-check [switch]="true" sizing="xl">
|
||||
<input cFormCheckInput [(ngModel)]="sysconfigs['force_syslog']['value']" type="checkbox" />
|
||||
<label cFormCheckLabel>Force Syslog</label>
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* Force Syslog config under system>logs setting of each router that added to Mikrowizard and monitor syslog
|
||||
setting for any change to prevent/fix the configuration.</c-form-feedback>
|
||||
</c-form-check>
|
||||
|
||||
<c-form-check [switch]="true" sizing="xl">
|
||||
<input cFormCheckInput [(ngModel)]="sysconfigs['safe_install']['value']" type="checkbox" />
|
||||
<label cFormCheckLabel>Safe Update</label>
|
||||
<c-form-feedback style="display: block;color: #979797;margin-top: 0;" [valid]="true">
|
||||
* Download and install reqired firmware before installing the target firmware . for example it will install
|
||||
latest 7.12 then upgrade to newer version >7.13</c-form-feedback>
|
||||
</c-form-check>
|
||||
|
||||
|
||||
<button cButton color="primary" (click)="saveSysSetting()">Save</button>
|
||||
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
||||
|
||||
<c-modal #ConfirmModal backdrop="static" [(visible)]="ConfirmModalVisible" id="runConfirmModal">
|
||||
<c-modal-header>
|
||||
<h6 cModalTitle>Downloading RouterOS ver {{firmtodownload}} </h6>
|
||||
<button [cModalToggle]="ConfirmModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
Are you sure that You want to download RouterOS version {{firmtodownload}} to the Repository?
|
||||
<br />
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<button *ngIf="loading" cButton cButton color="danger" class="m-1" disabled>
|
||||
<c-spinner aria-hidden="true" size="sm"></c-spinner>
|
||||
Downloading...
|
||||
</button>
|
||||
<button *ngIf="!loading" (click)="start_download()" cButton color="danger">
|
||||
Yes,Download!
|
||||
</button>
|
||||
<button [cModalToggle]="ConfirmModal.id" cButton color="info">
|
||||
No!,Close
|
||||
</button>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
||||
|
||||
<c-toaster position="fixed" placement="top-end"></c-toaster>
|
10
src/app/views/settings/settings.component.scss
Normal file
10
src/app/views/settings/settings.component.scss
Normal file
|
@ -0,0 +1,10 @@
|
|||
:host {
|
||||
.legend {
|
||||
small {
|
||||
font-size: x-small;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mdc-line-ripple.mdc-line-ripple--deactivating.ng-star-inserted {
|
||||
display: none!important;
|
||||
}
|
259
src/app/views/settings/settings.component.ts
Normal file
259
src/app/views/settings/settings.component.ts
Normal file
|
@ -0,0 +1,259 @@
|
|||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
QueryList,
|
||||
ViewChildren,
|
||||
ViewEncapsulation,
|
||||
} from "@angular/core";
|
||||
import { dataProvider } from "../../providers/mikrowizard/data";
|
||||
import { Router } from "@angular/router";
|
||||
import { loginChecker } from "../../providers/login_checker";
|
||||
import {
|
||||
GuiSelectedRow,
|
||||
GuiInfoPanel,
|
||||
GuiColumn,
|
||||
GuiColumnMenu,
|
||||
GuiPaging,
|
||||
GuiPagingDisplay,
|
||||
GuiRowSelectionMode,
|
||||
GuiRowSelection,
|
||||
GuiRowSelectionType,
|
||||
} from "@generic-ui/ngx-grid";
|
||||
import { ToasterComponent } from "@coreui/angular";
|
||||
import { AppToastComponent } from "../toast-simple/toast.component";
|
||||
import { TimeZones } from "./timezones-data";
|
||||
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: "settings.component.html",
|
||||
styleUrls: ["settings.component.scss"],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class SettingsComponent implements OnInit {
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
public filterText: string;
|
||||
public filters: any = {};
|
||||
public firms: any = {};
|
||||
public firmtodownload: any = {};
|
||||
constructor(
|
||||
private data_provider: dataProvider,
|
||||
private router: Router,
|
||||
private TimeZones: TimeZones,
|
||||
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;
|
||||
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 !== "";
|
||||
}
|
||||
}
|
||||
@ViewChildren(ToasterComponent) viewChildren!: QueryList<ToasterComponent>;
|
||||
|
||||
public source: Array<any> = [];
|
||||
public columns: Array<GuiColumn> = [];
|
||||
public loading: boolean = true;
|
||||
public SysConfigloading: boolean = true;
|
||||
|
||||
public ConfirmModalVisible: boolean = false;
|
||||
public rows: any = [];
|
||||
public Selectedrows: any;
|
||||
public updateBehavior: string = "keep";
|
||||
public firmwaretoinstall: string = "none";
|
||||
public firmwaretoinstallv6: string = "none";
|
||||
public available_firmwares: any = [];
|
||||
public available_firmwaresv6: any = [];
|
||||
public sysconfigs: any = [];
|
||||
|
||||
toasterForm = {
|
||||
autohide: true,
|
||||
delay: 3000,
|
||||
position: "fixed",
|
||||
fade: true,
|
||||
closeButton: true,
|
||||
};
|
||||
|
||||
public sorting = {
|
||||
enabled: true,
|
||||
multiSorting: true,
|
||||
};
|
||||
|
||||
public paging: GuiPaging = {
|
||||
enabled: true,
|
||||
page: 1,
|
||||
pageSize: 5,
|
||||
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,
|
||||
};
|
||||
public timezones = this.TimeZones.timezones;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.initAvailbleFirms();
|
||||
this.initFirmsTable();
|
||||
this.initsettings();
|
||||
}
|
||||
|
||||
start_download() {
|
||||
var _self = this;
|
||||
this.loading = true;
|
||||
this.data_provider
|
||||
.download_firmware_to_repository(this.firmtodownload)
|
||||
.then((res) => {
|
||||
if (res.status == true) {
|
||||
// show toast that we are already downloading
|
||||
_self.show_toast(
|
||||
"Firmware Download",
|
||||
"Firmware download in progress",
|
||||
"warning"
|
||||
);
|
||||
} else {
|
||||
// show toast that download started
|
||||
_self.show_toast(
|
||||
"Firmware Download",
|
||||
"Firmware download started",
|
||||
"success"
|
||||
);
|
||||
}
|
||||
_self.ConfirmModalVisible = !_self.ConfirmModalVisible;
|
||||
_self.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
onSelectedRows(rows: Array<GuiSelectedRow>): void {
|
||||
this.rows = rows;
|
||||
this.Selectedrows = rows.map((m: GuiSelectedRow) => m.source.id);
|
||||
}
|
||||
|
||||
show_toast(title: string, body: string, color: string) {
|
||||
const { ...props } = { ...this.toasterForm, color, title, body };
|
||||
const componentRef = this.viewChildren.first.addToast(
|
||||
AppToastComponent,
|
||||
props,
|
||||
{}
|
||||
);
|
||||
componentRef.instance["closeButton"] = props.closeButton;
|
||||
}
|
||||
|
||||
saveFirmwareSetting() {
|
||||
var _self = this;
|
||||
this.data_provider
|
||||
.save_firmware_setting(
|
||||
this.updateBehavior,
|
||||
this.firmwaretoinstall,
|
||||
this.firmwaretoinstallv6
|
||||
)
|
||||
.then((res) => {
|
||||
_self.initFirmsTable();
|
||||
});
|
||||
}
|
||||
|
||||
saveSysSetting() {
|
||||
var _self = this;
|
||||
this.data_provider.save_sys_setting(this.sysconfigs).then((res) => {
|
||||
_self.initsettings();
|
||||
});
|
||||
}
|
||||
|
||||
initFirmsTable(): void {
|
||||
var _self = this;
|
||||
this.data_provider.get_firms(0, 10000, false).then((res) => {
|
||||
let index = 1;
|
||||
_self.source = res.firms;
|
||||
_self.available_firmwares = [
|
||||
...new Set(
|
||||
res["firms"].map((x: any) => {
|
||||
return x.version;
|
||||
})
|
||||
),
|
||||
];
|
||||
_self.available_firmwaresv6 = [
|
||||
...new Set(
|
||||
res["firms"].map((x: any) => {
|
||||
return x.version;
|
||||
})
|
||||
),
|
||||
].filter((x: any) => x.match(/^6\./g));
|
||||
_self.firmwaretoinstall = res.firmwaretoinstall;
|
||||
_self.firmwaretoinstallv6 = res.firmwaretoinstallv6;
|
||||
});
|
||||
}
|
||||
|
||||
initsettings(): void {
|
||||
var _self = this;
|
||||
this.data_provider.get_settings().then((res) => {
|
||||
_self.sysconfigs = res.sysconfigs;
|
||||
_self.sysconfigs["default_user"]["value"] = "";
|
||||
_self.sysconfigs["default_password"]["value"] = "";
|
||||
_self.timezones = _self.TimeZones.timezones;
|
||||
_self.sysconfigs["force_syslog"]["value"] = /true/i.test(
|
||||
_self.sysconfigs["force_syslog"]["value"]
|
||||
);
|
||||
_self.sysconfigs["force_radius"]["value"] = /true/i.test(
|
||||
_self.sysconfigs["force_radius"]["value"]
|
||||
);
|
||||
_self.sysconfigs["force_perms"]["value"] = /true/i.test(
|
||||
_self.sysconfigs["force_perms"]["value"]
|
||||
);
|
||||
_self.sysconfigs["safe_install"]["value"] = /true/i.test(
|
||||
_self.sysconfigs["safe_install"]["value"]
|
||||
);
|
||||
_self.SysConfigloading = false;
|
||||
});
|
||||
}
|
||||
|
||||
initAvailbleFirms(): void {
|
||||
var _self = this;
|
||||
this.data_provider.get_downloadable_firms().then((res) => {
|
||||
let index = 1;
|
||||
_self.firms = res.versions;
|
||||
_self.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
41
src/app/views/settings/settings.module.ts
Normal file
41
src/app/views/settings/settings.module.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
|
||||
import {
|
||||
ButtonGroupModule,
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
FormModule,
|
||||
GridModule,
|
||||
SpinnerModule,
|
||||
ToastModule,
|
||||
ModalModule,
|
||||
} from "@coreui/angular";
|
||||
import { SettingsRoutingModule } from "./settings-routing.module";
|
||||
import { SettingsComponent } from "./settings.component";
|
||||
import { GuiGridModule } from "@generic-ui/ngx-grid";
|
||||
|
||||
import { FormsModule } from "@angular/forms";
|
||||
import { MatSelectModule } from "@angular/material/select";
|
||||
import { NgxMatSelectSearchModule } from "ngx-mat-select-search";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
SettingsRoutingModule,
|
||||
CardModule,
|
||||
CommonModule,
|
||||
GridModule,
|
||||
FormsModule,
|
||||
FormModule,
|
||||
ButtonModule,
|
||||
ButtonGroupModule,
|
||||
GuiGridModule,
|
||||
MatSelectModule,
|
||||
NgxMatSelectSearchModule,
|
||||
SpinnerModule,
|
||||
ToastModule,
|
||||
ModalModule,
|
||||
],
|
||||
declarations: [SettingsComponent],
|
||||
})
|
||||
export class SettingsModule {}
|
1456
src/app/views/settings/timezones-data.ts
Normal file
1456
src/app/views/settings/timezones-data.ts
Normal file
File diff suppressed because it is too large
Load diff
21
src/app/views/snippets/snippets-routing.module.ts
Normal file
21
src/app/views/snippets/snippets-routing.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { SnippetsComponent } from './snippets.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: SnippetsComponent,
|
||||
data: {
|
||||
title: $localize`Snippets`
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class SnippetsRoutingModule {
|
||||
}
|
130
src/app/views/snippets/snippets.component.html
Normal file
130
src/app/views/snippets/snippets.component.html
Normal file
|
@ -0,0 +1,130 @@
|
|||
<c-row>
|
||||
<c-col xs>
|
||||
<c-card class="mb-4">
|
||||
<c-card-header>
|
||||
<c-row>
|
||||
<c-col xs [lg]="3">
|
||||
Devices
|
||||
</c-col>
|
||||
<c-col xs [lg]="9">
|
||||
<h6 style="text-align: right;">
|
||||
<button cButton color="dark" class="mx-1" size="sm" (click)="Edit_Snippet('','showadd')"
|
||||
style="color: #fff;"><i class="fa-solid fa-plus"></i> </button>
|
||||
</h6>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-card-header>
|
||||
<c-card-body>
|
||||
<gui-grid [source]="source" [searching]="searching" [paging]="paging" [columnMenu]="columnMenu" [sorting]="sorting" [infoPanel]="infoPanel"
|
||||
[rowSelection]="rowSelection" (selectedRows)="onSelectedRows($event)" [autoResizeWidth]=true>
|
||||
<gui-grid-column header="Name" field="name">
|
||||
<ng-template let-value="item.name" let-item="item" let-index="index">
|
||||
<img *ngIf="item.status=='updating'" width="20px" src="assets/img/loading.svg" />
|
||||
<i *ngIf="item.status=='updated'" style="color: green;margin: 5px;" class="fa-solid fa-check"></i>
|
||||
<i *ngIf="item.status=='failed'" style="color: red;margin: 5px;" class="fa-solid fa-x"></i>
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Description" field="description">
|
||||
<ng-template let-value="item.description" let-item="item" let-index="index">
|
||||
{{value}}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Created" field="created">
|
||||
<ng-template let-value="item.created" let-item="item" let-index="index">
|
||||
|
||||
<div>{{value}}</div>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Actions" field="action">
|
||||
<ng-template let-value="item.id" let-item="item" let-index="index">
|
||||
<button cButton color="warning" size="sm" (click)="Edit_Snippet(item,'edit')" class="mx-1"><i
|
||||
class="fa-regular fa-pen-to-square mx-1"></i>Edit</button>
|
||||
<button cButton color="danger" size="sm" (click)="confirm_delete(item,false)" class="mx-1"><i
|
||||
class="fa-regular fa-trash-can mx-1"></i>Delete</button>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
||||
|
||||
|
||||
|
||||
<c-modal #EditModal backdrop="static" [(visible)]="EditModalVisible" id="runEditModal">
|
||||
<c-modal-header>
|
||||
<h6 *ngIf="ModalAction=='add'" cModalTitle>Add New Snippet</h6>
|
||||
<h6 *ngIf="ModalAction=='edit'" cModalTitle>Editing snippet {{current_snippet.name}}</h6>
|
||||
<button [cModalToggle]="EditModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
|
||||
<c-input-group class="mb-3">
|
||||
<div [cFormFloating]="true" class="mb-3">
|
||||
<input cFormControl id="floatingInput" placeholder="Snippet Name" [(ngModel)]="current_snippet['name']" />
|
||||
<label cLabel for="floatingInput">Name</label>
|
||||
</div>
|
||||
</c-input-group>
|
||||
<c-input-group class="mb-3">
|
||||
<div [cFormFloating]="true" class="mb-3">
|
||||
<input cFormControl id="floatingInput" placeholder="Snippet Description" [(ngModel)]="current_snippet['description']" />
|
||||
<label cLabel for="floatingInput">Description</label>
|
||||
</div>
|
||||
</c-input-group>
|
||||
<c-input-group class="mb-3">
|
||||
<div [cFormFloating]="true" class="mb-3">
|
||||
<textarea [style.height.px]="50 + (23 * lineNum)"
|
||||
cFormControl (ngModelChange)="calcline($event)" id="floatingInput" placeholder="Snippet code" [(ngModel)]="current_snippet['content']" ></textarea>
|
||||
<label cLabel for="floatingInput">Code</label>
|
||||
</div>
|
||||
</c-input-group>
|
||||
<br />
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<button cButton color="danger" (click)="save_snippet()">save</button>
|
||||
<button cButton [cModalToggle]="EditModal.id" color="info">Close</button>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
||||
|
||||
|
||||
|
||||
<c-modal #DeleteConfirmModal backdrop="static" [(visible)]="DeleteConfirmModalVisible"
|
||||
id="DeleteConfirmModal">
|
||||
<c-modal-header>
|
||||
<h5 cModalTitle>Confirm delete {{ SelectedSnippet['name'] }}</h5>
|
||||
<button [cModalToggle]="DeleteConfirmModal.id" cButtonClose></button>
|
||||
</c-modal-header>
|
||||
<c-modal-body>
|
||||
Are you sure that You want to delete following Snippet ?
|
||||
<br/>
|
||||
<br/>
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td><b>Snippet name : </b>{{ SelectedSnippet['name'] }}
|
||||
</tr>
|
||||
<tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p ><code style="padding: 0!important;"><b>Warning:</b> ALL <b>Tasks</b> related to this snippet Will be <b>modifed or deleted</b> and stop working!</code></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</c-modal-body>
|
||||
<c-modal-footer>
|
||||
<button (click)="confirm_delete('',true)" cButton color="danger">
|
||||
Yes,Delete!
|
||||
</button>
|
||||
<button [cModalToggle]="DeleteConfirmModal.id" cButton color="info">
|
||||
Close
|
||||
</button>
|
||||
</c-modal-footer>
|
||||
</c-modal>
|
||||
|
||||
|
||||
|
||||
|
||||
<c-toaster position="fixed" placement="top-end"></c-toaster>
|
||||
|
||||
|
214
src/app/views/snippets/snippets.component.ts
Normal file
214
src/app/views/snippets/snippets.component.ts
Normal file
|
@ -0,0 +1,214 @@
|
|||
import { Component, OnInit, OnDestroy, Inject, Renderer2, ViewChild, ElementRef, TemplateRef } from '@angular/core';
|
||||
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { dataProvider } from '../../providers/mikrowizard/data';
|
||||
import { Router } from "@angular/router";
|
||||
import { loginChecker } from '../../providers/login_checker';
|
||||
import { HttpClient, HttpClientModule, HttpParams } from '@angular/common/http';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { GuiCellView,GuiSearching, GuiSelectedRow, GuiInfoPanel, GuiColumn, GuiColumnMenu, GuiDataType, GuiPaging, GuiPagingDisplay, GuiRowColoring, GuiRowSelectionMode, GuiRowSelection, GuiRowSelectionType } from '@generic-ui/ngx-grid';
|
||||
|
||||
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: 'snippets.component.html',
|
||||
})
|
||||
|
||||
export class SnippetsComponent implements OnInit, OnDestroy {
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
|
||||
constructor(
|
||||
private data_provider: dataProvider,
|
||||
private router: Router,
|
||||
private login_checker: loginChecker,
|
||||
private renderer: Renderer2,
|
||||
private httpClient: HttpClient,
|
||||
@Inject(DOCUMENT) _document?: any,
|
||||
) {
|
||||
var _self = this;
|
||||
if (!this.login_checker.isLoggedIn()) {
|
||||
// setTimeout(function() {
|
||||
// _self.router.navigate(['login']);
|
||||
// }, 100);
|
||||
}
|
||||
this.data_provider.getSessionInfo().then(res => {
|
||||
// console.dir("res",res)
|
||||
_self.uid = res.uid;
|
||||
_self.uname = res.name;
|
||||
// console.dir("role",res.role);
|
||||
const userId = _self.uid;
|
||||
|
||||
if (res.role != "admin") {
|
||||
// console.dir(res.role);
|
||||
setTimeout(function () {
|
||||
_self.router.navigate(['/user/dashboard']);
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
//get datagrid data
|
||||
function isNotEmpty(value: any): boolean {
|
||||
return value !== undefined && value !== null && value !== "";
|
||||
}
|
||||
}
|
||||
@ViewChild('nameSummaryCell')
|
||||
nameSummaryCell: TemplateRef<any>;
|
||||
public source: Array<any> = [];
|
||||
public columns: Array<GuiColumn> = [];
|
||||
public loading: boolean = true;
|
||||
public rows: any=[];
|
||||
public Selectedrows: any;
|
||||
public EditModalVisible:boolean=false;
|
||||
public ModalAction:string="checkfirm";
|
||||
public lineNum:number=0;
|
||||
public DeleteConfirmModalVisible:boolean = false;
|
||||
public SelectedSnippet:any={'name':'',};
|
||||
|
||||
public current_snippet:any={
|
||||
"content": "",
|
||||
"created": "",
|
||||
"description": "",
|
||||
"id": 0,
|
||||
"name": ""
|
||||
};
|
||||
|
||||
public default_snippet:any={
|
||||
"content": "",
|
||||
"created": "",
|
||||
"description": "",
|
||||
"id": 0,
|
||||
"name": ""
|
||||
};
|
||||
|
||||
public sorting = {
|
||||
enabled: true,
|
||||
multiSorting: true
|
||||
};
|
||||
|
||||
public ip_scanner:any;
|
||||
|
||||
searching: GuiSearching = {
|
||||
enabled: true,
|
||||
placeholder: 'Search Devices'
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
this.initGridTable();
|
||||
}
|
||||
|
||||
confirm_delete(item: any="",del:boolean=false) {
|
||||
if (!del){
|
||||
this.SelectedSnippet={...item};
|
||||
this.DeleteConfirmModalVisible = true;
|
||||
console.dir(this.SelectedSnippet);
|
||||
}
|
||||
else{
|
||||
var _self=this;
|
||||
this.data_provider.delete_snippet(_self.SelectedSnippet['id']).then(res => {
|
||||
_self.initGridTable();
|
||||
_self.DeleteConfirmModalVisible = false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Edit_Snippet(item: any,action:string="showadd") {
|
||||
|
||||
if(action=="showadd"){
|
||||
this.current_snippet={...this.default_snippet};
|
||||
this.EditModalVisible=true;
|
||||
this.ModalAction="add";
|
||||
}
|
||||
else{
|
||||
this.current_snippet=item;
|
||||
this.EditModalVisible=true;
|
||||
this.lineNum = this.current_snippet['content'].match(/\n/g) .length ;
|
||||
|
||||
this.ModalAction="edit";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
calcline($ev:any){
|
||||
if($ev)
|
||||
this.lineNum = $ev.match(/\n/g) .length ;
|
||||
else
|
||||
this.lineNum = 0;
|
||||
}
|
||||
|
||||
save_snippet(){
|
||||
this.data_provider.save_snippet(this.current_snippet).then(res =>{
|
||||
this.EditModalVisible=false;
|
||||
this.initGridTable();
|
||||
})
|
||||
}
|
||||
|
||||
onSelectedRows(rows: Array<GuiSelectedRow>): void {
|
||||
this.rows = rows;
|
||||
this.Selectedrows = rows.map((m: GuiSelectedRow) => m.source.id);
|
||||
}
|
||||
|
||||
remove(item: any) {
|
||||
console.dir(item);
|
||||
}
|
||||
|
||||
logger(item: any) {
|
||||
console.dir(item)
|
||||
}
|
||||
|
||||
initGridTable(): void {
|
||||
var _self=this;
|
||||
_self.data_provider.get_snippets("","","",0,1000).then(res => {
|
||||
_self.source =res.map( (x:any) => {
|
||||
x.created = [x.created.split("T")[0],x.created.split("T")[1].split(".")[0]].join(" ")
|
||||
return x;
|
||||
|
||||
});
|
||||
_self.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ngOnDestroy(): void {
|
||||
}
|
||||
}
|
34
src/app/views/snippets/snippets.module.ts
Normal file
34
src/app/views/snippets/snippets.module.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { FormsModule } from "@angular/forms";
|
||||
|
||||
import {
|
||||
ButtonGroupModule,
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
FormModule,
|
||||
GridModule,
|
||||
ToastModule,
|
||||
ModalModule,
|
||||
} from "@coreui/angular";
|
||||
import { SnippetsRoutingModule } from "./snippets-routing.module";
|
||||
import { SnippetsComponent } from "./snippets.component";
|
||||
import { GuiGridModule } from "@generic-ui/ngx-grid";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
SnippetsRoutingModule,
|
||||
CardModule,
|
||||
CommonModule,
|
||||
GridModule,
|
||||
FormModule,
|
||||
ButtonModule,
|
||||
ButtonGroupModule,
|
||||
GuiGridModule,
|
||||
ModalModule,
|
||||
ToastModule,
|
||||
FormsModule,
|
||||
],
|
||||
declarations: [SnippetsComponent],
|
||||
})
|
||||
export class SnippetsModule {}
|
21
src/app/views/syslog/syslog-routing.module.ts
Normal file
21
src/app/views/syslog/syslog-routing.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { SyslogComponent } from './syslog.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: SyslogComponent,
|
||||
data: {
|
||||
title: $localize`Mikrowizard System Logs`
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class SyslogRoutingModule {
|
||||
}
|
104
src/app/views/syslog/syslog.component.html
Normal file
104
src/app/views/syslog/syslog.component.html
Normal file
|
@ -0,0 +1,104 @@
|
|||
<c-row>
|
||||
<c-col xs>
|
||||
<c-card class="mb-4">
|
||||
<c-card-header>
|
||||
<c-row>
|
||||
<c-col xs [lg]="11">
|
||||
Devices
|
||||
</c-col>
|
||||
<c-col xs [lg]="1">
|
||||
<button (click)="toggleCollapse()" cButton class="me-1" color="primary"><i
|
||||
class="fa-solid fa-filter mr-1"></i>Filter</button>
|
||||
</c-col>
|
||||
</c-row>
|
||||
</c-card-header>
|
||||
<c-card-body>
|
||||
<c-row>
|
||||
<div [visible]="filters_visible" cCollapse>
|
||||
<c-col xs [lg]="12" class="example-form">
|
||||
<mat-form-field>
|
||||
<mat-label>Start date</mat-label>
|
||||
<input matInput [matDatepicker]="picker1" (dateChange)="reinitgrid('start',$event)"
|
||||
[(ngModel)]="filters['start_time']" />
|
||||
<mat-datepicker-toggle matIconSuffix [for]="picker1"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker1></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>End date</mat-label>
|
||||
<input matInput [matDatepicker]="picker2" (dateChange)="reinitgrid('end',$event)"
|
||||
[(ngModel)]="filters['end_time']" />
|
||||
<mat-datepicker-toggle matIconSuffix [for]="picker2"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker2></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Select section</mat-label>
|
||||
<mat-select placeholder="Event Section" (ngModelChange)="reinitgrid('section',$event)"
|
||||
[(ngModel)]="filters['section']" #multiSelect>
|
||||
<mat-option value="All">All</mat-option>
|
||||
<mat-option *ngFor="let sec of event_section " [value]="sec">
|
||||
{{sec}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Select action</mat-label>
|
||||
<mat-select placeholder="Event action" (ngModelChange)="reinitgrid('action',$event)"
|
||||
[(ngModel)]="filters['action']" #multiSelect>
|
||||
<mat-option value="All">All</mat-option>
|
||||
<mat-option *ngFor="let ac of event_action" [value]="ac">
|
||||
{{ac}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>IP</mat-label>
|
||||
<input (ngModelChange)="reinitgrid('ip',$event)" [(ngModel)]="filters['ip']" matInput>
|
||||
</mat-form-field>
|
||||
</c-col>
|
||||
|
||||
</div>
|
||||
|
||||
</c-row>
|
||||
<gui-grid wid [rowDetail]="rowDetail" [horizontalGrid]="true" [rowHeight]="52" [source]="source"
|
||||
[columnMenu]="columnMenu" [paging]="paging" [sorting]="sorting" [infoPanel]="infoPanel"
|
||||
[autoResizeWidth]="true">
|
||||
<gui-grid-column header="#No" type="NUMBER" field="index" width="1" align="CENTER">
|
||||
<ng-template let-value="item.index" let-item="item" let-index="index">
|
||||
{{ value }}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
|
||||
<gui-grid-column header="username" field="username">
|
||||
<ng-template let-value="item.username" let-item="item" let-index="index">
|
||||
<div class="gui-dev-info">
|
||||
<span class="gui-dev-info-name">{{ value }}</span>
|
||||
<span class="gui-dev-info-ip">{{ item.first_name }} {{ item.last_name }}</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Section" field="section">
|
||||
<ng-template let-value="item.section" let-item="item" let-index="index">
|
||||
{{ value }}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="action" field="action">
|
||||
<ng-template let-value="item.action" let-item="item" let-index="index">
|
||||
{{ value }}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="ip" field="ip">
|
||||
<ng-template let-value="item.ip" let-item="item" let-index="index">
|
||||
{{ value }}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
<gui-grid-column header="Time" field="created">
|
||||
<ng-template let-value="item.created" let-item="item" let-index="index">
|
||||
{{ value }}
|
||||
</ng-template>
|
||||
</gui-grid-column>
|
||||
</gui-grid>
|
||||
|
||||
</c-card-body>
|
||||
</c-card>
|
||||
</c-col>
|
||||
</c-row>
|
128
src/app/views/syslog/syslog.component.scss
Normal file
128
src/app/views/syslog/syslog.component.scss
Normal file
|
@ -0,0 +1,128 @@
|
|||
@use '@angular/material' as mat;
|
||||
|
||||
:host {
|
||||
.legend {
|
||||
small {
|
||||
font-size: x-small;
|
||||
}
|
||||
}
|
||||
}
|
||||
// .gui-drawer-content{
|
||||
// background-color: #efefef!important;
|
||||
|
||||
// }
|
||||
.log-detail{
|
||||
padding:30px 10px;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
.log-detail h1{
|
||||
font-size:2em;
|
||||
font-weight:bold;
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
.log-detail small{
|
||||
position:relative;
|
||||
top:-7px;
|
||||
padding:0;
|
||||
font-weight:bold;
|
||||
font-size:1.1em;
|
||||
}
|
||||
.log-detail table {
|
||||
width: 100%;
|
||||
border-collapse: collapse!important;
|
||||
margin: 5px 0 0 0;
|
||||
padding: 0;
|
||||
background-color: #ffffff29 !important;
|
||||
color: #000;
|
||||
}
|
||||
.log-detail th {
|
||||
text-align: left;
|
||||
}
|
||||
.log-detail th,
|
||||
.log-detail td {
|
||||
border: 1px solid #ffffff4a!important;
|
||||
padding: 0.3rem!important;
|
||||
}
|
||||
.gui-close-icon-wrapper .gui-close-icon:after,.gui-close-icon-wrapper .gui-close-icon:before {
|
||||
background-color: #ffffff !important;
|
||||
|
||||
}
|
||||
.log-detail code{
|
||||
padding:5px!important;
|
||||
display:block;
|
||||
background:#1d1f21;
|
||||
color:#c5c8c6;
|
||||
border-bottom-left-radius:3px;
|
||||
border-bottom-right-radius:3px;
|
||||
width:100%;
|
||||
min-height: unset!important;
|
||||
height: 100px!important;
|
||||
overflow-y: scroll!important;
|
||||
}
|
||||
|
||||
.log-detail .code-title{
|
||||
background-color:#393e42!important;;
|
||||
width:100%;
|
||||
padding:2px 15px;
|
||||
display:inline-block;
|
||||
margin-top:10px;
|
||||
color:#d2d2d2;
|
||||
border-top-left-radius:3px;
|
||||
border-top-right-radius:3px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.gui-row-detail{
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.gui-dev-info {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
white-space: normal;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
.gui-dev-info-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.gui-dev-info-ip {
|
||||
color: #525252;
|
||||
font-style: italic;
|
||||
font-size: 13px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.gui-row-detail > div{
|
||||
height:100%;
|
||||
}
|
||||
.gui-row-detail .log-detail{
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.gui-structure{
|
||||
min-height: 550px;
|
||||
}
|
||||
|
||||
|
||||
.example-form {
|
||||
@include mat.button-density(-5);
|
||||
|
||||
@include mat.form-field-density(-5);
|
||||
@include mat.button-toggle-density(-5);
|
||||
@include mat.datepicker-density(-5);
|
||||
@include mat.all-component-densities(-5);
|
||||
@include mat.icon-button-density(-5);
|
||||
@include mat.icon-density(-5);
|
||||
.mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) .mat-mdc-floating-label { display: inline; }
|
||||
mat-form-field *{
|
||||
font-size:13px!important;
|
||||
}
|
||||
.mat-mdc-form-field-infix{
|
||||
width:150px;
|
||||
}
|
||||
}
|
204
src/app/views/syslog/syslog.component.ts
Normal file
204
src/app/views/syslog/syslog.component.ts
Normal file
|
@ -0,0 +1,204 @@
|
|||
import { Component, OnInit, ViewEncapsulation } from "@angular/core";
|
||||
import { dataProvider } from "../../providers/mikrowizard/data";
|
||||
import { Router, ActivatedRoute } from "@angular/router";
|
||||
import { loginChecker } from "../../providers/login_checker";
|
||||
import {
|
||||
GuiRowDetail,
|
||||
GuiInfoPanel,
|
||||
GuiColumn,
|
||||
GuiColumnMenu,
|
||||
GuiPaging,
|
||||
GuiPagingDisplay,
|
||||
GuiRowSelectionMode,
|
||||
GuiRowSelection,
|
||||
GuiRowSelectionType,
|
||||
} from "@generic-ui/ngx-grid";
|
||||
import { formatInTimeZone } from "date-fns-tz";
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: "syslog.component.html",
|
||||
styleUrls: ["syslog.component.scss"],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class SyslogComponent implements OnInit {
|
||||
public uid: number;
|
||||
public uname: string;
|
||||
public tz: string= "UTC";
|
||||
public filterText: string;
|
||||
public filters: any = {
|
||||
start_time: false,
|
||||
end_time: false,
|
||||
section: "All",
|
||||
action: "All",
|
||||
ip: "",
|
||||
};
|
||||
public event_section: any = [];
|
||||
public event_action: any = [];
|
||||
public filters_visible: boolean = false;
|
||||
constructor(
|
||||
private data_provider: dataProvider,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
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 source: Array<any> = [];
|
||||
public columns: Array<GuiColumn> = [];
|
||||
public loading: boolean = true;
|
||||
public rows: any = [];
|
||||
public Selectedrows: any;
|
||||
public userid: number = 0;
|
||||
public sorting = {
|
||||
enabled: true,
|
||||
multiSorting: true,
|
||||
};
|
||||
public campaignOnestart: any;
|
||||
public campaignOneend: any;
|
||||
rowDetail: GuiRowDetail = {
|
||||
enabled: true,
|
||||
template: (item) => {
|
||||
return `
|
||||
<div class='log-detail' style="color:#fff;background-color:#3399ff">
|
||||
<h2>System Log :</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Section</td>
|
||||
<td>${item.section}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Action</td>
|
||||
<td>${item.action}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Time</td>
|
||||
<td>${item.created}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2 style="margin-top: 5px;">User Detail :
|
||||
</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<td>User</td>
|
||||
<td>${item.username}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>FirstName</td>
|
||||
<td>${item.first_name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LastName</td>
|
||||
<td>${item.last_name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IP</td>
|
||||
<td>${item.ip}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Agent</td>
|
||||
<td><div style="height: 40px;overflow-y: scroll;">${item.agent}</div></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="code-title">data</div>
|
||||
<code>
|
||||
${item.data}
|
||||
</code>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
ngOnInit(): void {
|
||||
var _self = this;
|
||||
this.userid = Number(this.route.snapshot.paramMap.get("userid"));
|
||||
if (this.userid > 0) {
|
||||
this.filters["userid"] = this.userid;
|
||||
}
|
||||
this.initGridTable();
|
||||
}
|
||||
toggleCollapse(): void {
|
||||
this.filters_visible = !this.filters_visible;
|
||||
}
|
||||
logger(item: any) {
|
||||
console.dir(item);
|
||||
}
|
||||
reinitgrid(field: string, $event: any) {
|
||||
if (field == "start") this.filters["start_time"] = $event.target.value;
|
||||
else if (field == "end") this.filters["end_time"] = $event.target.value;
|
||||
else if (field == "section") this.filters["section"] = $event;
|
||||
else if (field == "action") this.filters["action"] = $event;
|
||||
else if (field == "ip") this.filters["ip"] = $event;
|
||||
this.initGridTable();
|
||||
}
|
||||
initGridTable(): void {
|
||||
var _self = this;
|
||||
_self.event_section = [];
|
||||
_self.event_action = [];
|
||||
this.data_provider.get_syslog(this.filters).then((res) => {
|
||||
let index = 1;
|
||||
this.source = res.map((d: any) => {
|
||||
d.index = index;
|
||||
if (!_self.event_section.includes(d.section))
|
||||
_self.event_section.push(d.section);
|
||||
|
||||
if (!_self.event_action.includes(d.action))
|
||||
_self.event_action.push(d.action);
|
||||
d.created = formatInTimeZone(
|
||||
d.created.split(".")[0] + ".000Z",
|
||||
_self.tz,
|
||||
"yyyy-MM-dd HH:mm:ss XXX"
|
||||
);
|
||||
index += 1;
|
||||
return d;
|
||||
});
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
41
src/app/views/syslog/syslog.module.ts
Normal file
41
src/app/views/syslog/syslog.module.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
|
||||
import {
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
GridModule,
|
||||
CollapseModule,
|
||||
DropdownModule,
|
||||
} from "@coreui/angular";
|
||||
import { NgxMatSelectSearchModule } from "ngx-mat-select-search";
|
||||
import { SyslogRoutingModule } from "./syslog-routing.module";
|
||||
import { SyslogComponent } from "./syslog.component";
|
||||
import { GuiGridModule } from "@generic-ui/ngx-grid";
|
||||
import { MatDatepickerModule } from "@angular/material/datepicker";
|
||||
import { MatInputModule } from "@angular/material/input";
|
||||
import { MatFormFieldModule } from "@angular/material/form-field";
|
||||
import { FormsModule } from "@angular/forms";
|
||||
|
||||
import { MatSelectModule } from "@angular/material/select";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
SyslogRoutingModule,
|
||||
CardModule,
|
||||
CommonModule,
|
||||
GridModule,
|
||||
FormsModule,
|
||||
ButtonModule,
|
||||
GuiGridModule,
|
||||
CollapseModule,
|
||||
DropdownModule,
|
||||
MatInputModule,
|
||||
MatFormFieldModule,
|
||||
MatSelectModule,
|
||||
NgxMatSelectSearchModule,
|
||||
MatDatepickerModule,
|
||||
],
|
||||
declarations: [SyslogComponent],
|
||||
})
|
||||
export class SyslogModule {}
|
11
src/app/views/toast-simple/toast-sample-icon.component.svg
Normal file
11
src/app/views/toast-simple/toast-sample-icon.component.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<svg
|
||||
class="rounded me-2"
|
||||
width="20"
|
||||
height="20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
preserveAspectRatio="xMidYMid slice"
|
||||
focusable="false"
|
||||
role="img"
|
||||
>
|
||||
<rect width="100%" height="100%" fill="#007aff"></rect>
|
||||
</svg>
|
After Width: | Height: | Size: 231 B |
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue