This commit is contained in:
crusader 2018-10-12 14:14:02 +09:00
parent 673c9cab57
commit 4c630efc84
54 changed files with 416 additions and 283 deletions

View File

@ -2,6 +2,8 @@ import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { CommonsUIModule } from '@overflow/commons/ui/commons-ui.module'; import { CommonsUIModule } from '@overflow/commons/ui/commons-ui.module';
import { import {
@ -19,6 +21,7 @@ import { COMPONENTS } from './component';
import { PAGES } from './pages'; import { PAGES } from './pages';
import { SERVICES } from './service'; import { SERVICES } from './service';
import { I18nService } from './service/i18n.service';
const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = { const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = {
suppressScrollX: true suppressScrollX: true
@ -29,7 +32,12 @@ const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = {
imports: [ imports: [
BrowserModule, BrowserModule,
BrowserAnimationsModule, BrowserAnimationsModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useExisting: I18nService,
}
}),
PerfectScrollbarModule, PerfectScrollbarModule,
CommonsUIModule, CommonsUIModule,

View File

@ -7,12 +7,12 @@ import {
} from './menu'; } from './menu';
import { import {
COMPONENTS as TARGET_COMPONENTS COMPONENTS as INFRA_COMPONENTS
} from './target'; } from './infra';
export const COMPONENTS = [ export const COMPONENTS = [
...LAYOUT_COMPONENTS, ...LAYOUT_COMPONENTS,
...MENU_COMPONENTS, ...MENU_COMPONENTS,
...TARGET_COMPONENTS, ...INFRA_COMPONENTS,
]; ];

View File

@ -11,7 +11,7 @@ import { PingService } from '../../../service/ping.service';
import { PingOption } from '@overflow/model/config/ping'; import { PingOption } from '@overflow/model/config/ping';
@Component({ @Component({
selector: 'app-target-detail-host', selector: 'app-infra-detail-host',
templateUrl: './host.component.html', templateUrl: './host.component.html',
styleUrls: ['./host.component.scss'], styleUrls: ['./host.component.scss'],
}) })

View File

@ -0,0 +1,26 @@
<div class="ui-g">
<div class="ui-g-12">
<ng-container [ngSwitch]="selectedInfra.group">
<ng-container *ngSwitchCase="'zone'">
<app-infra-detail-zone [zone]="selectedInfra.infra" (otherHostSelect)="otherHostSelected($event)"></app-infra-detail-zone>
</ng-container>
<ng-container *ngSwitchCase="'host'">
<app-infra-detail-host [host]="selectedInfra.infra" (ping)="ping.emit($event)"></app-infra-detail-host>
</ng-container>
<ng-container *ngSwitchCase="'service'">
<app-infra-detail-service [service]="selectedInfra.infra" (ping)="ping.emit($event)"></app-infra-detail-service>
</ng-container>
<ng-container *ngSwitchDefault>
</ng-container>
</ng-container>
</div>
</div>

View File

@ -4,13 +4,13 @@ import { Host, Port, Service } from '@overflow/model/discovery';
@Component({ @Component({
selector: 'app-target-detail-node', selector: 'app-infra-detail-node',
templateUrl: './node.component.html', templateUrl: './node.component.html',
styleUrls: ['./node.component.scss'], styleUrls: ['./node.component.scss'],
}) })
export class NodeComponent { export class NodeComponent {
@Input() selectedTarget: { group: string, target: Host | Port | Service } | null; @Input() selectedInfra: { group: string, infra: Host | Port | Service } | null;
@Output() otherHostSelect = new EventEmitter<Host>(); @Output() otherHostSelect = new EventEmitter<Host>();
@Output() ping = new EventEmitter<PingResult>(); @Output() ping = new EventEmitter<PingResult>();

View File

@ -11,7 +11,7 @@ import { PingService } from '../../../service/ping.service';
import { PingOption } from '@overflow/model/config/ping'; import { PingOption } from '@overflow/model/config/ping';
@Component({ @Component({
selector: 'app-target-detail-service', selector: 'app-infra-detail-service',
templateUrl: './service.component.html', templateUrl: './service.component.html',
styleUrls: ['./service.component.scss'], styleUrls: ['./service.component.scss'],
}) })

View File

@ -5,7 +5,7 @@ import { AutoHeightDirective } from '@overflow/commons/ui/directive/auto-height.
const IPCIDR = require('ip-cidr'); const IPCIDR = require('ip-cidr');
@Component({ @Component({
selector: 'app-target-detail-zone', selector: 'app-infra-detail-zone',
templateUrl: './zone.component.html', templateUrl: './zone.component.html',
styleUrls: ['./zone.component.scss'], styleUrls: ['./zone.component.scss'],
}) })

View File

@ -1,8 +1,8 @@
<div> <div>
<ng-container [ngSwitch]="(targetDisplayType$ | async)"> <ng-container [ngSwitch]="(infraDisplayType$ | async)">
<app-target-display-map *ngSwitchCase="'MAP'"></app-target-display-map> <app-infra-display-map *ngSwitchCase="'MAP'"></app-infra-display-map>
<app-target-display-grid *ngSwitchCase="'GRID'"></app-target-display-grid> <app-infra-display-grid *ngSwitchCase="'GRID'"></app-infra-display-grid>
<app-target-display-tree *ngSwitchCase="'TREE'"></app-target-display-tree> <app-infra-display-tree *ngSwitchCase="'TREE'"></app-infra-display-tree>
</ng-container> </ng-container>
@ -10,8 +10,8 @@
<p-sidebar [(visible)]="displaySidebar" [modal]="false" [appendTo]="detailSidebar" styleClass="ui-sidebar-md" <p-sidebar [(visible)]="displaySidebar" [modal]="false" [appendTo]="detailSidebar" styleClass="ui-sidebar-md"
position="right" (onHide)="onHideDetail()" [style]="{position:'absolute'}"> position="right" (onHide)="onHideDetail()" [style]="{position:'absolute'}">
<div *ngIf="selectedTarget"> <div *ngIf="selectedInfra">
<app-target-detail-node [selectedTarget]="selectedTarget" (otherHostSelect)="otherHostSelected($event)"></app-target-detail-node> <app-infra-detail-node [selectedInfra]="selectedInfra" (otherHostSelect)="otherHostSelected($event)"></app-infra-detail-node>
</div> </div>
</p-sidebar> </p-sidebar>

View File

@ -1,4 +1,4 @@
/deep/ .target-display { /deep/ .infra-display {
width: 100%; width: 100%;
height: 100vh; height: 100vh;
margin: -0.6em -0.9em -0.7em -0.9em; //-0.5em -0.75em; margin: -0.6em -0.9em -0.7em -0.9em; //-0.5em -0.75em;

View File

@ -13,22 +13,22 @@ import { map, catchError, take, tap } from 'rxjs/operators';
import { Port, Service, Host } from '@overflow/model/discovery'; import { Port, Service, Host } from '@overflow/model/discovery';
import { TargetDisplayType, DiscoveryStatusType } from '../../../core/type'; import { InfraDisplayType, DiscoveryStatusType } from '../../../core/type';
import * as AppStore from '../../../store'; import * as AppStore from '../../../store';
import * as TargetStore from '../../../store/target/target'; import * as InfraStore from '../../../store/infra/infra';
@Component({ @Component({
selector: 'app-target-display', selector: 'app-infra-display',
templateUrl: './display.component.html', templateUrl: './display.component.html',
styleUrls: ['./display.component.scss'] styleUrls: ['./display.component.scss']
}) })
export class DisplayComponent implements OnInit, AfterContentInit, OnDestroy { export class DisplayComponent implements OnInit, AfterContentInit, OnDestroy {
private targetDisplayType$: Observable<TargetDisplayType>; private infraDisplayType$: Observable<InfraDisplayType>;
displaySidebar = false; displaySidebar = false;
selectedTargetSubscription: Subscription | null; selectedInfraSubscription: Subscription | null;
selectedTarget: { group: string, target: Host | Port | Service } | null; selectedInfra: { group: string, infra: Host | Port | Service } | null;
displayDiscoveryStopping: boolean; displayDiscoveryStopping: boolean;
discoveryStatusSubscription: Subscription | null; discoveryStatusSubscription: Subscription | null;
@ -42,18 +42,18 @@ export class DisplayComponent implements OnInit, AfterContentInit, OnDestroy {
ngOnInit(): void { ngOnInit(): void {
const __this = this; const __this = this;
this.targetDisplayType$ = this.store.pipe(select(AppStore.TargetSelector.TargetSelector.selectTargetDisplayType)); this.infraDisplayType$ = this.store.pipe(select(AppStore.InfraSelector.InfraSelector.selectInfraDisplayType));
this.selectedTargetSubscription = this.store.pipe( this.selectedInfraSubscription = this.store.pipe(
select(AppStore.TargetSelector.TargetSelector.selectSelectedTarget) select(AppStore.InfraSelector.InfraSelector.selectSelectedInfra)
).pipe( ).pipe(
map((_selectedTarget) => { map((_selectedInfra) => {
if (null === _selectedTarget) { if (null === _selectedInfra) {
__this.displaySidebar = false; __this.displaySidebar = false;
__this.selectedTarget = null; __this.selectedInfra = null;
} else { } else {
__this.displaySidebar = true; __this.displaySidebar = true;
__this.selectedTarget = _selectedTarget; __this.selectedInfra = _selectedInfra;
} }
__this.changeDetector.detectChanges(); __this.changeDetector.detectChanges();
}), }),
@ -84,8 +84,8 @@ export class DisplayComponent implements OnInit, AfterContentInit, OnDestroy {
} }
ngOnDestroy(): void { ngOnDestroy(): void {
if (null !== this.selectedTargetSubscription) { if (null !== this.selectedInfraSubscription) {
this.selectedTargetSubscription.unsubscribe(); this.selectedInfraSubscription.unsubscribe();
} }
if (null !== this.discoveryStatusSubscription) { if (null !== this.discoveryStatusSubscription) {
this.discoveryStatusSubscription.unsubscribe(); this.discoveryStatusSubscription.unsubscribe();
@ -93,7 +93,7 @@ export class DisplayComponent implements OnInit, AfterContentInit, OnDestroy {
} }
onHideDetail() { onHideDetail() {
this.store.dispatch(new TargetStore.ChangeSelectedTarget(null)); this.store.dispatch(new InfraStore.ChangeSelectedInfra(null));
} }
} }

View File

@ -8,7 +8,7 @@ import {
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
@Component({ @Component({
selector: 'app-target-display-grid', selector: 'app-infra-display-grid',
templateUrl: './grid.component.html', templateUrl: './grid.component.html',
styleUrls: ['./grid.component.scss'] styleUrls: ['./grid.component.scss']
}) })

View File

@ -1,5 +1,5 @@
<div class="target-display"> <div class="infra-display">
<svg #displayTarget width="100%" height="100%"> <svg #displayInfra width="100%" height="100%">
<g> <g>
<g *ngFor="let link of links"> <g *ngFor="let link of links">
<g class="link-container" [ngClass]="'link-'+link.target.group" [attr.sourceId]="link.source.id" <g class="link-container" [ngClass]="'link-'+link.target.group" [attr.sourceId]="link.source.id"

View File

@ -24,7 +24,7 @@ import { Node } from '../../../core/model/node';
import * as AppStore from '../../../store'; import * as AppStore from '../../../store';
import * as DiscoveryConfigStore from '../../../store/discovery/config'; import * as DiscoveryConfigStore from '../../../store/discovery/config';
import * as TargetStore from '../../../store/target/target'; import * as InfraStore from '../../../store/infra/infra';
import * as UILayoutStore from '../../../store/ui/layout'; import * as UILayoutStore from '../../../store/ui/layout';
import { DiscoverySession } from '../../../core/discovery/discovery-session'; import { DiscoverySession } from '../../../core/discovery/discovery-session';
import { DiscoveryMessageType } from 'src/app/core/type'; import { DiscoveryMessageType } from 'src/app/core/type';
@ -92,7 +92,7 @@ export class DisplaySummary {
} }
@Component({ @Component({
selector: 'app-target-display-map', selector: 'app-infra-display-map',
templateUrl: './map.component.html', templateUrl: './map.component.html',
styleUrls: ['./map.component.scss'] styleUrls: ['./map.component.scss']
}) })
@ -109,26 +109,26 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
selectedNode: Node | null = null; selectedNode: Node | null = null;
@ViewChild('displayTarget') set displayTarget(content: ElementRef) { @ViewChild('displayInfra') set displayInfra(content: ElementRef) {
this.displayTargetRef = content; this.displayInfraRef = content;
this.store.dispatch(new TargetStore.ChangeTargetDisplayElementRef({ targetDisplayElementRef: content })); this.store.dispatch(new InfraStore.ChangeInfraDisplayElementRef({ infraDisplayElementRef: content }));
} }
private displayTargetRef: ElementRef; private displayInfraRef: ElementRef;
public simulation: d3.Simulation<Node, Link> | undefined; public simulation: d3.Simulation<Node, Link> | undefined;
private zoomBehavior: d3.ZoomBehavior<Element, {}>; private zoomBehavior: d3.ZoomBehavior<Element, {}>;
private displayTargetWidth: number; private displayInfraWidth: number;
private displayTargetHeight: number; private displayInfraHeight: number;
private readonly maxScale: number; private readonly maxScale: number;
private readonly minScale: number; private readonly minScale: number;
displaySummary: DisplaySummary | null = null; displaySummary: DisplaySummary | null = null;
discoverySessionSubscription: Subscription | null = null; discoverySessionSubscription: Subscription | null = null;
refreshTargetDisplaySubscription: Subscription | null = null; refreshInfraDisplaySubscription: Subscription | null = null;
targetSubscription: Subscription | null = null; infraSubscription: Subscription | null = null;
targetObservable: Observable<void>; infraObservable: Observable<void>;
selectedTargetSubscription: Subscription | null = null; selectedInfraSubscription: Subscription | null = null;
discoverySubscription: Subscription | null = null; discoverySubscription: Subscription | null = null;
@ -146,13 +146,13 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
this.minScale = 0.7; this.minScale = 0.7;
const __this = this; const __this = this;
this.targetObservable = this.store.pipe( this.infraObservable = this.store.pipe(
take(1), take(1),
select((state) => { select((state) => {
const zone = AppStore.DiscoverySelector.ConfigSelector.selectZone(state); const zone = AppStore.DiscoverySelector.ConfigSelector.selectZone(state);
const hosts = AppStore.TargetSelector.TargetSelector.selectHosts(state); const hosts = AppStore.InfraSelector.InfraSelector.selectHosts(state);
const ports = AppStore.TargetSelector.TargetSelector.selectPorts(state); const ports = AppStore.InfraSelector.InfraSelector.selectPorts(state);
const services = AppStore.TargetSelector.TargetSelector.selectServices(state); const services = AppStore.InfraSelector.InfraSelector.selectServices(state);
__this.initMapDisplay(zone, hosts, ports, services); __this.initMapDisplay(zone, hosts, ports, services);
}), }),
@ -169,12 +169,12 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
@HostListener('window:resize', ['$event']) @HostListener('window:resize', ['$event'])
onResize(event) { onResize(event) {
if (undefined !== this.displayTargetRef) { if (undefined !== this.displayInfraRef) {
this.displayTargetWidth = this.displayTargetRef.nativeElement.clientWidth; this.displayInfraWidth = this.displayInfraRef.nativeElement.clientWidth;
this.displayTargetHeight = this.displayTargetRef.nativeElement.clientHeight; this.displayInfraHeight = this.displayInfraRef.nativeElement.clientHeight;
this.zoneNode.fx = this.displayTargetWidth / 2; this.zoneNode.fx = this.displayInfraWidth / 2;
this.zoneNode.fy = this.displayTargetHeight / 2; this.zoneNode.fy = this.displayInfraHeight / 2;
this.simulationRestart(false); this.simulationRestart(false);
} }
@ -242,14 +242,14 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
}), }),
).subscribe(); ).subscribe();
this.refreshTargetDisplaySubscription = this.store.pipe( this.refreshInfraDisplaySubscription = this.store.pipe(
select(AppStore.TargetSelector.TargetSelector.selectRefreshTargetDisplay), select(AppStore.InfraSelector.InfraSelector.selectRefreshInfraDisplay),
filter(v => !!v), filter(v => !!v),
map((refreshTargetDisplay: boolean) => { map((refreshInfraDisplay: boolean) => {
if (!refreshTargetDisplay) { if (!refreshInfraDisplay) {
return; return;
} }
__this.targetObservable.subscribe(); __this.infraObservable.subscribe();
}), }),
catchError(error => { catchError(error => {
console.log(error); console.log(error);
@ -257,11 +257,11 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
}), }),
).subscribe(); ).subscribe();
this.selectedTargetSubscription = this.store.pipe( this.selectedInfraSubscription = this.store.pipe(
select(AppStore.TargetSelector.TargetSelector.selectSelectedTarget) select(AppStore.InfraSelector.InfraSelector.selectSelectedInfra)
).pipe( ).pipe(
map((selectedTarget) => { map((selectedInfra) => {
if (null === selectedTarget) { if (null === selectedInfra) {
__this.onHideDetail(); __this.onHideDetail();
return; return;
} else { } else {
@ -293,26 +293,26 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
} }
ngAfterContentInit(): void { ngAfterContentInit(): void {
this.displayTargetWidth = this.displayTargetRef.nativeElement.clientWidth; this.displayInfraWidth = this.displayInfraRef.nativeElement.clientWidth;
this.displayTargetHeight = this.displayTargetRef.nativeElement.clientHeight; this.displayInfraHeight = this.displayInfraRef.nativeElement.clientHeight;
this.targetObservable.subscribe(); this.infraObservable.subscribe();
} }
ngOnDestroy(): void { ngOnDestroy(): void {
this.store.dispatch(new TargetStore.ChangeTargetDisplayElementRef({ targetDisplayElementRef: null })); this.store.dispatch(new InfraStore.ChangeInfraDisplayElementRef({ infraDisplayElementRef: null }));
if (null !== this.targetSubscription) { if (null !== this.infraSubscription) {
this.targetSubscription.unsubscribe(); this.infraSubscription.unsubscribe();
} }
if (null !== this.refreshTargetDisplaySubscription) { if (null !== this.refreshInfraDisplaySubscription) {
this.refreshTargetDisplaySubscription.unsubscribe(); this.refreshInfraDisplaySubscription.unsubscribe();
} }
if (null !== this.discoverySessionSubscription) { if (null !== this.discoverySessionSubscription) {
this.discoverySessionSubscription.unsubscribe(); this.discoverySessionSubscription.unsubscribe();
} }
if (null !== this.selectedTargetSubscription) { if (null !== this.selectedInfraSubscription) {
this.selectedTargetSubscription.unsubscribe(); this.selectedInfraSubscription.unsubscribe();
} }
if (null !== this.preventBrowserCloseSubscription) { if (null !== this.preventBrowserCloseSubscription) {
this.preventBrowserCloseSubscription.unsubscribe(); this.preventBrowserCloseSubscription.unsubscribe();
@ -360,7 +360,7 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
return; return;
} }
const svg = d3.select(this.displayTargetRef.nativeElement); const svg = d3.select(this.displayInfraRef.nativeElement);
this.zoomBehavior = d3.zoom() this.zoomBehavior = d3.zoom()
.scaleExtent([0.2, 4]) .scaleExtent([0.2, 4])
@ -376,7 +376,7 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
.nodes(this.nodes) .nodes(this.nodes)
.force('charge', d3.forceManyBody().strength(-200)) .force('charge', d3.forceManyBody().strength(-200))
.force('link', d3.forceLink(this.links).distance(150)) .force('link', d3.forceLink(this.links).distance(150))
.force('center', d3.forceCenter(this.displayTargetWidth / 2, this.displayTargetHeight / 2)) .force('center', d3.forceCenter(this.displayInfraWidth / 2, this.displayInfraHeight / 2))
.force('collision', d3.forceCollide().radius(function (node: Node) { .force('collision', d3.forceCollide().radius(function (node: Node) {
return node.r * 1.2; return node.r * 1.2;
})) }))
@ -391,7 +391,7 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
this.simulation this.simulation
.nodes(this.nodes) .nodes(this.nodes)
.force('link', d3.forceLink(this.links).distance(150)) .force('link', d3.forceLink(this.links).distance(150))
.force('center', d3.forceCenter(this.displayTargetWidth / 2, this.displayTargetHeight / 2)) .force('center', d3.forceCenter(this.displayInfraWidth / 2, this.displayInfraHeight / 2))
.alpha(1) .alpha(1)
.restart() .restart()
; ;
@ -400,8 +400,8 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
if (attachEvent) { if (attachEvent) {
const __this = this; const __this = this;
const nodeElements = d3.select(this.displayTargetRef.nativeElement).selectAll('.node-container'); const nodeElements = d3.select(this.displayInfraRef.nativeElement).selectAll('.node-container');
const linkElements = d3.select(this.displayTargetRef.nativeElement).selectAll('.link-container'); const linkElements = d3.select(this.displayInfraRef.nativeElement).selectAll('.link-container');
function getNodeFromElement(element: Element): Node | null { function getNodeFromElement(element: Element): Node | null {
const container = d3.select(element); const container = d3.select(element);
@ -480,7 +480,7 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
const nodeElement = this as Element; const nodeElement = this as Element;
const node = getNodeFromElement(nodeElement); const node = getNodeFromElement(nodeElement);
if (null === node || 'zone' === node.group) { if (null === node || 'zone' === node.group) {
__this.onTargetClick(node); __this.onInfraClick(node);
return; return;
} }
@ -536,14 +536,14 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
}); });
__this.onTargetClick(node); __this.onInfraClick(node);
}); });
// Highlight // Highlight
const displayTarget = d3.select(this.displayTargetRef.nativeElement); const displayInfra = d3.select(this.displayInfraRef.nativeElement);
displayTarget.on('click', function () { displayInfra.on('click', function () {
__this.selectedNode = null; __this.selectedNode = null;
__this.store.dispatch(new TargetStore.ChangeSelectedTarget(null)); __this.store.dispatch(new InfraStore.ChangeSelectedInfra(null));
nodeElements.each(function () { nodeElements.each(function () {
const _thisElement = this as Element; const _thisElement = this as Element;
@ -649,11 +649,11 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
} }
zoomToFit(paddingPercent, transitionDuration) { zoomToFit(paddingPercent, transitionDuration) {
const root = d3.select(this.displayTargetRef.nativeElement); const root = d3.select(this.displayInfraRef.nativeElement);
const bounds = root.node().getBBox(); const bounds = root.node().getBBox();
const fullWidth = this.displayTargetWidth; const fullWidth = this.displayInfraWidth;
const fullHeight = this.displayTargetHeight; const fullHeight = this.displayInfraHeight;
const width = bounds.width; const width = bounds.width;
const height = bounds.height; const height = bounds.height;
@ -681,7 +681,7 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
.call(this.zoomBehavior.transform, d3.zoomIdentity.translate(translate[0], translate[1]).scale(scale)); .call(this.zoomBehavior.transform, d3.zoomIdentity.translate(translate[0], translate[1]).scale(scale));
} }
onTargetClick(node: Node) { onInfraClick(node: Node) {
console.log(node); console.log(node);
switch (node.group) { switch (node.group) {
@ -709,9 +709,9 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
break; break;
} }
this.store.dispatch(new TargetStore.ChangeSelectedTarget({ this.store.dispatch(new InfraStore.ChangeSelectedInfra({
group: node.group, group: node.group,
target: node.target, infra: node.target,
})); }));
this.selectedNode = node; this.selectedNode = node;
@ -720,8 +720,8 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
onHideDetail() { onHideDetail() {
const __this = this; const __this = this;
const nodeElements = d3.select(this.displayTargetRef.nativeElement).selectAll('.node-container'); const nodeElements = d3.select(this.displayInfraRef.nativeElement).selectAll('.node-container');
const linkElements = d3.select(this.displayTargetRef.nativeElement).selectAll('.link-container'); const linkElements = d3.select(this.displayInfraRef.nativeElement).selectAll('.link-container');
__this.selectedNode = null; __this.selectedNode = null;
@ -752,7 +752,7 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
} }
refreshTargetDisplay(zone: Zone, hosts: Host[], services: Service[]) { refreshInfraDisplay(zone: Zone, hosts: Host[], services: Service[]) {
} }
@ -764,8 +764,8 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
this.zoneNode = new Node(zone.network); this.zoneNode = new Node(zone.network);
this.zoneNode.group = 'zone'; this.zoneNode.group = 'zone';
this.zoneNode.target = zone; this.zoneNode.target = zone;
this.zoneNode.fx = this.displayTargetWidth / 2; this.zoneNode.fx = this.displayInfraWidth / 2;
this.zoneNode.fy = this.displayTargetHeight / 2; this.zoneNode.fy = this.displayInfraHeight / 2;
this.zoneNode.r = 60; this.zoneNode.r = 60;
this.nodes.push( this.nodes.push(

View File

@ -8,7 +8,7 @@ import {
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
@Component({ @Component({
selector: 'app-target-display-tree', selector: 'app-infra-display-tree',
templateUrl: './tree.component.html', templateUrl: './tree.component.html',
styleUrls: ['./tree.component.scss'] styleUrls: ['./tree.component.scss']
}) })

View File

@ -3,7 +3,7 @@ import { Store, select } from '@ngrx/store';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
import * as AppStore from '../../store'; import * as AppStore from '../../store';
import { TargetDisplayType } from '../../core/type'; import { InfraDisplayType } from '../../core/type';
import { Message } from 'primeng/primeng'; import { Message } from 'primeng/primeng';
const { saveSvgAsPng, svgAsDataUri } = require('save-svg-as-png'); const { saveSvgAsPng, svgAsDataUri } = require('save-svg-as-png');
@ -37,10 +37,10 @@ export class ExportJPEGComponent implements OnInit, AfterContentInit, OnDestroy
this.store.pipe( this.store.pipe(
take(1), take(1),
select((state) => { select((state) => {
const targetDisplayType = AppStore.TargetSelector.TargetSelector.selectTargetDisplayType(state); const infraDisplayType = AppStore.InfraSelector.InfraSelector.selectInfraDisplayType(state);
const targetDisplayElementRef = AppStore.TargetSelector.TargetSelector.selectTargetDisplayElementRef(state); const infraDisplayElementRef = AppStore.InfraSelector.InfraSelector.selectInfraDisplayElementRef(state);
if (TargetDisplayType.MAP !== targetDisplayType) { if (InfraDisplayType.MAP !== infraDisplayType) {
this.msgs = []; this.msgs = [];
this.msgs.push({ this.msgs.push({
severity: 'error', severity: 'error',
@ -50,10 +50,10 @@ export class ExportJPEGComponent implements OnInit, AfterContentInit, OnDestroy
return; return;
} }
// svgAsDataUri(targetDisplayElementRef.nativeElement, {}, function (uri) { // svgAsDataUri(infraDisplayElementRef.nativeElement, {}, function (uri) {
// console.log(`uri: ${uri}`); // console.log(`uri: ${uri}`);
// }); // });
saveSvgAsPng(targetDisplayElementRef.nativeElement, 'diagram.jpeg', { backgroundColor: '#ffffff', encoderType: 'image/jpeg' }); saveSvgAsPng(infraDisplayElementRef.nativeElement, 'diagram.jpeg', { backgroundColor: '#ffffff', encoderType: 'image/jpeg' });
}), }),
).subscribe(); ).subscribe();
} }

View File

@ -3,7 +3,7 @@ import { Store, select } from '@ngrx/store';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
import * as AppStore from '../../store'; import * as AppStore from '../../store';
import { TargetDisplayType } from '../../core/type'; import { InfraDisplayType } from '../../core/type';
import { Message } from 'primeng/primeng'; import { Message } from 'primeng/primeng';
const { saveSvgAsPng, svgAsDataUri } = require('save-svg-as-png'); const { saveSvgAsPng, svgAsDataUri } = require('save-svg-as-png');
@ -37,10 +37,10 @@ export class ExportPNGComponent implements OnInit, AfterContentInit, OnDestroy {
this.store.pipe( this.store.pipe(
take(1), take(1),
select((state) => { select((state) => {
const targetDisplayType = AppStore.TargetSelector.TargetSelector.selectTargetDisplayType(state); const infraDisplayType = AppStore.InfraSelector.InfraSelector.selectInfraDisplayType(state);
const targetDisplayElementRef = AppStore.TargetSelector.TargetSelector.selectTargetDisplayElementRef(state); const infraDisplayElementRef = AppStore.InfraSelector.InfraSelector.selectInfraDisplayElementRef(state);
if (TargetDisplayType.MAP !== targetDisplayType) { if (InfraDisplayType.MAP !== infraDisplayType) {
this.msgs = []; this.msgs = [];
this.msgs.push({ this.msgs.push({
severity: 'error', severity: 'error',
@ -50,10 +50,10 @@ export class ExportPNGComponent implements OnInit, AfterContentInit, OnDestroy {
return; return;
} }
// svgAsDataUri(targetDisplayElementRef.nativeElement, {}, function (uri) { // svgAsDataUri(infraDisplayElementRef.nativeElement, {}, function (uri) {
// console.log(`uri: ${uri}`); // console.log(`uri: ${uri}`);
// }); // });
saveSvgAsPng(targetDisplayElementRef.nativeElement, 'diagram.png', { backgroundColor: '#ffffff' }); saveSvgAsPng(infraDisplayElementRef.nativeElement, 'diagram.png', { backgroundColor: '#ffffff' });
}), }),
).subscribe(); ).subscribe();
} }

View File

@ -3,7 +3,7 @@ import { Store, select } from '@ngrx/store';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
import * as AppStore from '../../store'; import * as AppStore from '../../store';
import { TargetDisplayType } from '../../core/type'; import { InfraDisplayType } from '../../core/type';
import { Message } from 'primeng/primeng'; import { Message } from 'primeng/primeng';
const { saveSvgAsPng, svgAsDataUri, download } = require('save-svg-as-png'); const { saveSvgAsPng, svgAsDataUri, download } = require('save-svg-as-png');
@ -37,10 +37,10 @@ export class ExportSVGComponent implements OnInit, AfterContentInit, OnDestroy {
this.store.pipe( this.store.pipe(
take(1), take(1),
select((state) => { select((state) => {
const targetDisplayType = AppStore.TargetSelector.TargetSelector.selectTargetDisplayType(state); const infraDisplayType = AppStore.InfraSelector.InfraSelector.selectInfraDisplayType(state);
const targetDisplayElementRef = AppStore.TargetSelector.TargetSelector.selectTargetDisplayElementRef(state); const infraDisplayElementRef = AppStore.InfraSelector.InfraSelector.selectInfraDisplayElementRef(state);
if (TargetDisplayType.MAP !== targetDisplayType) { if (InfraDisplayType.MAP !== infraDisplayType) {
this.msgs = []; this.msgs = [];
this.msgs.push({ this.msgs.push({
severity: 'error', severity: 'error',
@ -50,7 +50,7 @@ export class ExportSVGComponent implements OnInit, AfterContentInit, OnDestroy {
return; return;
} }
svgAsDataUri(targetDisplayElementRef.nativeElement, { backgroundColor: '#ffffff' }, function (uri) { svgAsDataUri(infraDisplayElementRef.nativeElement, { backgroundColor: '#ffffff' }, function (uri) {
download('diagram.svg', uri); download('diagram.svg', uri);
}); });
}), }),

View File

@ -1,26 +0,0 @@
<div class="ui-g">
<div class="ui-g-12">
<ng-container [ngSwitch]="selectedTarget.group">
<ng-container *ngSwitchCase="'zone'">
<app-target-detail-zone [zone]="selectedTarget.target" (otherHostSelect)="otherHostSelected($event)"></app-target-detail-zone>
</ng-container>
<ng-container *ngSwitchCase="'host'">
<app-target-detail-host [host]="selectedTarget.target" (ping)="ping.emit($event)"></app-target-detail-host>
</ng-container>
<ng-container *ngSwitchCase="'service'">
<app-target-detail-service [service]="selectedTarget.target" (ping)="ping.emit($event)"></app-target-detail-service>
</ng-container>
<ng-container *ngSwitchDefault>
</ng-container>
</ng-container>
</div>
</div>

View File

@ -10,9 +10,9 @@ import { DiscoverRequestInfo } from '../model';
import * as AppStore from '../../store'; import * as AppStore from '../../store';
import * as DiscoveryRequestStore from '../../store/discovery/request'; import * as DiscoveryRequestStore from '../../store/discovery/request';
import * as UserStore from '../../store/environment/user'; import * as UserStore from '../../store/environment/user';
import * as TargetTargetStore from '../../store/target/target'; import * as InfraInfraStore from '../../store/infra/infra';
import { take, map } from 'rxjs/operators'; import { take, map } from 'rxjs/operators';
import { DiscoveryMessageType, TargetDisplayType, DiscoveryStatusType } from '../type'; import { DiscoveryMessageType, InfraDisplayType, DiscoveryStatusType } from '../type';
import { Subject, Observable } from 'rxjs'; import { Subject, Observable } from 'rxjs';
export class DiscoverySession { export class DiscoverySession {
@ -65,11 +65,11 @@ export class DiscoverySession {
} }
store.dispatch(new UserStore.ChangeShowWelcomPage({ showWelcomPage: false })); store.dispatch(new UserStore.ChangeShowWelcomPage({ showWelcomPage: false }));
store.dispatch(new TargetTargetStore.ChangeTargetDisplayType({ targetDisplayType: TargetDisplayType.MAP })); store.dispatch(new InfraInfraStore.ChangeInfraDisplayType({ infraDisplayType: InfraDisplayType.MAP }));
store.dispatch(new DiscoveryRequestStore.RequestDiscover({ discoverySession })); store.dispatch(new DiscoveryRequestStore.RequestDiscover({ discoverySession }));
// store.dispatch(new UserStore.ChangeShowWelcomPage({ showWelcomPage: false })); // store.dispatch(new UserStore.ChangeShowWelcomPage({ showWelcomPage: false }));
// store.dispatch(new TargetTargetStore.ChangeTargetDisplayType({ targetDisplayType: TargetDisplayType.MAP })); // store.dispatch(new InfraInfraStore.ChangeInfraDisplayType({ infraDisplayType: InfraDisplayType.MAP }));
}), }),
).subscribe(); ).subscribe();
} }

View File

@ -1,3 +1,3 @@
export * from './discovery-message'; export * from './discovery-message';
export * from './discovery-status'; export * from './discovery-status';
export * from './target-display'; export * from './infra-display';

View File

@ -1,5 +1,5 @@
export enum TargetDisplayType { export enum InfraDisplayType {
NONE = 'NONE', NONE = 'NONE',
MAP = 'MAP', MAP = 'MAP',
GRID = 'GRID', GRID = 'GRID',

View File

@ -16,7 +16,7 @@
</div> </div>
<div *ngIf="!(showWelcomPage$ | async)" class="display-container"> <div *ngIf="!(showWelcomPage$ | async)" class="display-container">
<app-target-display></app-target-display> <app-infra-display></app-infra-display>
</div> </div>
</of-p-div> </of-p-div>

View File

@ -64,4 +64,18 @@ export class ElectronProxyService {
public getAppMenu(): void { public getAppMenu(): void {
ipcRenderer.send('get-app-menu'); ipcRenderer.send('get-app-menu');
} }
public getRendererI18n({ filePath, fileName }: { filePath: string, fileName: string }): Promise<any> {
return new Promise<any>((resolve, reject) => {
ipcRenderer.once(
'get-renderer-i18n-result',
(event: Electron.IpcMessageEvent, { result }: { result: any }) => {
resolve(result);
}
);
ipcRenderer.send('get-renderer-i18n', { filePath, fileName });
});
}
} }

View File

@ -0,0 +1,30 @@
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { TranslateLoader } from '@ngx-translate/core';
import { ElectronProxyService } from './electron-proxy.service';
@Injectable({
providedIn: 'root'
})
export class I18nService extends TranslateLoader {
private prefix: string;
private suffix: string;
public constructor(
private electronProxyService: ElectronProxyService,
) {
super();
this.prefix = 'assets/i18n';
this.suffix = '.json';
}
getTranslation(lang: string): Observable<any> {
return of(this.electronProxyService.getRendererI18n({
filePath: `${this.prefix}`,
fileName: `${lang}.${this.suffix}`,
}));
}
}

View File

@ -5,6 +5,7 @@ import { ProbeService } from './probe.service';
import { MachineService } from './machine.service'; import { MachineService } from './machine.service';
import { DiscoveryService } from './discovery.service'; import { DiscoveryService } from './discovery.service';
import { PingService } from './ping.service'; import { PingService } from './ping.service';
import { I18nService } from './i18n.service';
export const SERVICES = [ export const SERVICES = [
DatabaseService, DatabaseService,
@ -14,4 +15,5 @@ export const SERVICES = [
MachineService, MachineService,
DiscoveryService, DiscoveryService,
PingService, PingService,
I18nService,
]; ];

View File

@ -11,7 +11,7 @@ import { storeFreeze } from 'ngrx-store-freeze';
import * as DiscoveryStore from './discovery'; import * as DiscoveryStore from './discovery';
import * as EnvironmentStore from './environment'; import * as EnvironmentStore from './environment';
import * as TargetStore from './target'; import * as InfraStore from './infra';
import * as UIStore from './ui'; import * as UIStore from './ui';
@ -20,7 +20,7 @@ import { environment } from '../../environments/environment';
export const EFFECTS: Type<any>[] = [ export const EFFECTS: Type<any>[] = [
...DiscoveryStore.EFFECTS, ...DiscoveryStore.EFFECTS,
...EnvironmentStore.EFFECTS, ...EnvironmentStore.EFFECTS,
...TargetStore.EFFECTS, ...InfraStore.EFFECTS,
...UIStore.EFFECTS, ...UIStore.EFFECTS,
]; ];
@ -28,7 +28,7 @@ export const REDUCERS: ActionReducerMap<any> = {
router: fromRouter.routerReducer, router: fromRouter.routerReducer,
discovery: DiscoveryStore.REDUCER, discovery: DiscoveryStore.REDUCER,
environment: EnvironmentStore.REDUCER, environment: EnvironmentStore.REDUCER,
target: TargetStore.REDUCER, infra: InfraStore.REDUCER,
ui: UIStore.REDUCER, ui: UIStore.REDUCER,
}; };
@ -54,7 +54,7 @@ export interface State {
router: fromRouter.RouterReducerState; router: fromRouter.RouterReducerState;
discovery: DiscoveryStore.State; discovery: DiscoveryStore.State;
environment: EnvironmentStore.State; environment: EnvironmentStore.State;
target: TargetStore.State; infra: InfraStore.State;
ui: UIStore.State; ui: UIStore.State;
} }
@ -66,8 +66,8 @@ export const EnvironmentSelector = EnvironmentStore.getSelectors(
(state: State) => state.environment, (state: State) => state.environment,
); );
export const TargetSelector = TargetStore.getSelectors( export const InfraSelector = InfraStore.getSelectors(
(state: State) => state.target, (state: State) => state.infra,
); );
export const UISelector = UIStore.getSelectors( export const UISelector = UIStore.getSelectors(

View File

@ -5,26 +5,26 @@ import {
combineReducers combineReducers
} from '@ngrx/store'; } from '@ngrx/store';
import * as TargetStore from './target'; import * as InfraStore from './infra';
export interface State { export interface State {
target: TargetStore.State; infra: InfraStore.State;
} }
export const EFFECTS: Type<any>[] = [ export const EFFECTS: Type<any>[] = [
TargetStore.TargetEffects, InfraStore.InfraEffects,
]; ];
export const REDUCER = combineReducers({ export const REDUCER = combineReducers({
target: TargetStore.reducer, infra: InfraStore.reducer,
}); });
export function getSelectors<S>(selector: Selector<any, State>) { export function getSelectors<S>(selector: Selector<any, State>) {
return { return {
TargetSelector: TargetStore.getSelectors(createSelector( InfraSelector: InfraStore.getSelectors(createSelector(
selector, selector,
(state: State) => state.target, (state: State) => state.infra,
)), )),
}; };
} }

View File

@ -0,0 +1,4 @@
export * from './infra.action';
export * from './infra.effect';
export * from './infra.reducer';
export * from './infra.state';

View File

@ -0,0 +1,68 @@
import { ElementRef } from '@angular/core';
import { Action } from '@ngrx/store';
import { Host, Port, Service } from '@overflow/model/discovery';
import { InfraDisplayType } from '../../../core/type';
export enum ActionType {
SetHosts = '[app.infra] SetHosts',
SetPorts = '[app.infra] SetPorts',
SetServices = '[app.infra] SetServices',
ChangeInfraDisplayType = '[app.infra] ChangeInfraDisplayType',
RefreshInfraDisplay = '[app.infra] RefreshInfraDisplay',
ChangeSelectedInfra = '[app.infra] ChangeSelectedInfra',
ChangeInfraDisplayElementRef = '[app.infra] ChangeInfraDisplayElementRef',
}
export class SetHosts implements Action {
readonly type = ActionType.SetHosts;
constructor(public payload: Host[]) { }
}
export class SetPorts implements Action {
readonly type = ActionType.SetPorts;
constructor(public payload: Port[]) { }
}
export class SetServices implements Action {
readonly type = ActionType.SetServices;
constructor(public payload: Service[]) { }
}
export class ChangeInfraDisplayType implements Action {
readonly type = ActionType.ChangeInfraDisplayType;
constructor(public payload: { infraDisplayType: InfraDisplayType }) { }
}
export class RefreshInfraDisplay implements Action {
readonly type = ActionType.RefreshInfraDisplay;
constructor(public payload: boolean) { }
}
export class ChangeSelectedInfra implements Action {
readonly type = ActionType.ChangeSelectedInfra;
constructor(public payload: { group: string, infra: Host | Port | Service }) { }
}
export class ChangeInfraDisplayElementRef implements Action {
readonly type = ActionType.ChangeInfraDisplayElementRef;
constructor(public payload: { infraDisplayElementRef: ElementRef }) { }
}
export type Actions =
| SetHosts
| SetPorts
| SetServices
| ChangeInfraDisplayType
| RefreshInfraDisplay
| ChangeSelectedInfra
| ChangeInfraDisplayElementRef
;

View File

@ -4,7 +4,7 @@ import { Actions, Effect, ofType } from '@ngrx/effects';
import { map, tap } from 'rxjs/operators'; import { map, tap } from 'rxjs/operators';
@Injectable() @Injectable()
export class TargetEffects { export class InfraEffects {
constructor( constructor(
private actions$: Actions, private actions$: Actions,

View File

@ -1,12 +1,12 @@
import { import {
Actions, Actions,
ActionType, ActionType,
} from './target.action'; } from './infra.action';
import { import {
State, State,
initialState, initialState,
} from './target.state'; } from './infra.state';
export function reducer(state: State = initialState, action: Actions): State { export function reducer(state: State = initialState, action: Actions): State {
switch (action.type) { switch (action.type) {
@ -31,31 +31,31 @@ export function reducer(state: State = initialState, action: Actions): State {
}; };
} }
case ActionType.ChangeTargetDisplayType: { case ActionType.ChangeInfraDisplayType: {
return { return {
...state, ...state,
targetDisplayType: action.payload.targetDisplayType, infraDisplayType: action.payload.infraDisplayType,
}; };
} }
case ActionType.RefreshTargetDisplay: { case ActionType.RefreshInfraDisplay: {
return { return {
...state, ...state,
refreshTargetDisplay: action.payload, refreshInfraDisplay: action.payload,
}; };
} }
case ActionType.ChangeSelectedTarget: { case ActionType.ChangeSelectedInfra: {
return { return {
...state, ...state,
selectedTarget: action.payload, selectedInfra: action.payload,
}; };
} }
case ActionType.ChangeTargetDisplayElementRef: { case ActionType.ChangeInfraDisplayElementRef: {
return { return {
...state, ...state,
targetDisplayElementRef: action.payload.targetDisplayElementRef, infraDisplayElementRef: action.payload.infraDisplayElementRef,
}; };
} }

View File

@ -0,0 +1,41 @@
import { ElementRef } from '@angular/core';
import { Selector, createSelector } from '@ngrx/store';
import { Host, Port, Service } from '@overflow/model/discovery';
import { InfraDisplayType } from '../../../core/type';
export interface State {
hosts: Host[] | null;
ports: Port[] | null;
services: Service[] | null;
infraDisplayType: InfraDisplayType;
refreshInfraDisplay: boolean;
selectedInfra: {
group: string;
infra: Host | Port | Service;
} | null;
infraDisplayElementRef: ElementRef;
}
export const initialState: State = {
hosts: null,
ports: null,
services: null,
infraDisplayType: InfraDisplayType.NONE,
refreshInfraDisplay: false,
selectedInfra: null,
infraDisplayElementRef: null,
};
export function getSelectors<S>(selector: Selector<any, State>) {
return {
selectHosts: createSelector(selector, (state: State) => state.hosts),
selectPorts: createSelector(selector, (state: State) => state.ports),
selectServices: createSelector(selector, (state: State) => state.services),
selectInfraDisplayType: createSelector(selector, (state: State) => state.infraDisplayType),
selectRefreshInfraDisplay: createSelector(selector, (state: State) => state.refreshInfraDisplay),
selectSelectedInfra: createSelector(selector, (state: State) => state.selectedInfra),
selectInfraDisplayElementRef: createSelector(selector, (state: State) => state.infraDisplayElementRef),
};
}

View File

@ -1,4 +0,0 @@
export * from './target.action';
export * from './target.effect';
export * from './target.reducer';
export * from './target.state';

View File

@ -1,68 +0,0 @@
import { ElementRef } from '@angular/core';
import { Action } from '@ngrx/store';
import { Host, Port, Service } from '@overflow/model/discovery';
import { TargetDisplayType } from '../../../core/type';
export enum ActionType {
SetHosts = '[app.target] SetHosts',
SetPorts = '[app.target] SetPorts',
SetServices = '[app.target] SetServices',
ChangeTargetDisplayType = '[app.target] ChangeTargetDisplayType',
RefreshTargetDisplay = '[app.target] RefreshTargetDisplay',
ChangeSelectedTarget = '[app.target] ChangeSelectedTarget',
ChangeTargetDisplayElementRef = '[app.target] ChangeTargetDisplayElementRef',
}
export class SetHosts implements Action {
readonly type = ActionType.SetHosts;
constructor(public payload: Host[]) { }
}
export class SetPorts implements Action {
readonly type = ActionType.SetPorts;
constructor(public payload: Port[]) { }
}
export class SetServices implements Action {
readonly type = ActionType.SetServices;
constructor(public payload: Service[]) { }
}
export class ChangeTargetDisplayType implements Action {
readonly type = ActionType.ChangeTargetDisplayType;
constructor(public payload: { targetDisplayType: TargetDisplayType }) { }
}
export class RefreshTargetDisplay implements Action {
readonly type = ActionType.RefreshTargetDisplay;
constructor(public payload: boolean) { }
}
export class ChangeSelectedTarget implements Action {
readonly type = ActionType.ChangeSelectedTarget;
constructor(public payload: { group: string, target: Host | Port | Service }) { }
}
export class ChangeTargetDisplayElementRef implements Action {
readonly type = ActionType.ChangeTargetDisplayElementRef;
constructor(public payload: { targetDisplayElementRef: ElementRef }) { }
}
export type Actions =
| SetHosts
| SetPorts
| SetServices
| ChangeTargetDisplayType
| RefreshTargetDisplay
| ChangeSelectedTarget
| ChangeTargetDisplayElementRef
;

View File

@ -1,41 +0,0 @@
import { ElementRef } from '@angular/core';
import { Selector, createSelector } from '@ngrx/store';
import { Host, Port, Service } from '@overflow/model/discovery';
import { TargetDisplayType } from '../../../core/type';
export interface State {
hosts: Host[] | null;
ports: Port[] | null;
services: Service[] | null;
targetDisplayType: TargetDisplayType;
refreshTargetDisplay: boolean;
selectedTarget: {
group: string;
target: Host | Port | Service;
} | null;
targetDisplayElementRef: ElementRef;
}
export const initialState: State = {
hosts: null,
ports: null,
services: null,
targetDisplayType: TargetDisplayType.NONE,
refreshTargetDisplay: false,
selectedTarget: null,
targetDisplayElementRef: null,
};
export function getSelectors<S>(selector: Selector<any, State>) {
return {
selectHosts: createSelector(selector, (state: State) => state.hosts),
selectPorts: createSelector(selector, (state: State) => state.ports),
selectServices: createSelector(selector, (state: State) => state.services),
selectTargetDisplayType: createSelector(selector, (state: State) => state.targetDisplayType),
selectRefreshTargetDisplay: createSelector(selector, (state: State) => state.refreshTargetDisplay),
selectSelectedTarget: createSelector(selector, (state: State) => state.selectedTarget),
selectTargetDisplayElementRef: createSelector(selector, (state: State) => state.targetDisplayElementRef),
};
}

48
src/assets/i18n/en.json Normal file
View File

@ -0,0 +1,48 @@
{
"ui": {
"button": {
"apply": "Apply",
"reset": "Reset"
},
"menu": {
"save": "Save",
"export_as": "Export as",
"print": "Print",
"toggle_full_screen": "Toggle Full Screen"
}
},
"network": {
"ip": "IP",
"port": "Port",
"range": "Range"
},
"infra": {
"detail": {
"title": {
"general": "General",
"metadata": "Metadata",
"ports": "Ports",
"health": "Health"
},
"general": {
"ip_address": "IP Address",
"type": "Type",
"vendor": "Vendor",
"model": "Model",
"os": "OS"
},
"health": {
"count": "Count",
"interval": "Interval",
"deadline": "Deadline",
"ping": "Ping"
}
}
},
"discovery": {
"total_hosts": "Total Hosts",
"total_ports": "Total Ports",
"total_services": "Total Services",
"elapsed": "Elapsed"
}
}

6
src/assets/i18n/ko.json Normal file
View File

@ -0,0 +1,6 @@
{
"HOME": {
"TITLE": "Hello Angular with ngx-translate!",
"SELECT": "Change language"
}
}

12
src/electron/app-path.ts Normal file
View File

@ -0,0 +1,12 @@
import * as fse from 'fs-extra';
import * as path from 'path';
const _root = __DEV__
? path.resolve(__dirname, '..', '..')
: path.resolve(__dirname);
export function root(...paths: string[]) {
const args = Array.prototype.slice.call(paths, 0);
return path.join.apply(path, [_root].concat(args));
}

View File

@ -15,6 +15,7 @@ import { parseAppURL } from '@overflow/core/parse-app-url';
import { now } from '@overflow/core/now'; import { now } from '@overflow/core/now';
import { IMenuItem } from '@overflow/core/menu-item'; import { IMenuItem } from '@overflow/core/menu-item';
import { root } from './app-path';
import { AppWindow } from './app-window'; import { AppWindow } from './app-window';
import { handleSquirrelEvent } from './squirrel-updater'; import { handleSquirrelEvent } from './squirrel-updater';
@ -227,6 +228,18 @@ app.on('ready', () => {
let menu = buildDefaultMenu(); let menu = buildDefaultMenu();
Menu.setApplicationMenu(menu); Menu.setApplicationMenu(menu);
ipcMain.on(
'get-renderer-i18n', (
event: Electron.IpcMessageEvent,
{ filePath, fileName }: { filePath: string, fileName: string }
) => {
const rBuf = fse.readFileSync(root(filePath, fileName));
const i18n = JSON.parse(rBuf.toString('utf8'));
event.sender.send('get-renderer-i18n-result', { i18n });
}
);
ipcMain.on( ipcMain.on(
'update-preferred-app-menu-item-labels', 'update-preferred-app-menu-item-labels',
(event: Electron.IpcMessageEvent) => { (event: Electron.IpcMessageEvent) => {