This commit is contained in:
snoop 2018-05-02 17:49:05 +09:00
commit 8b6cf4b46c
27 changed files with 7 additions and 773 deletions

3
.gitignore vendored
View File

@ -42,4 +42,5 @@ testem.log
.DS_Store
Thumbs.db
yarn.lock
yarn.lock
package-lock.json

2
package-lock.json generated
View File

@ -259,7 +259,7 @@
"@overflow/commons-typescript": {
"version": "0.0.1",
"resolved": "https://nexus.loafle.net/repository/npm-all/@overflow/commons-typescript/-/commons-typescript-0.0.1.tgz",
"integrity": "sha512-TQYJfBlRgkti8lPiwDi8FtKUkWUKNOBE4+uUGQyLBCPHzchjbN4edVtyKsQzHcDHqI+rIIJutYU3eaB1hhKl4A==",
"integrity": "sha512-gmSOtX2unwGIaPPomwFhREi7I5hIdhV/SaEST9oUH/SpfrHNPkRd3ptW2PL57W3j70UvGf2xh853DsJqpcdLtA==",
"dev": true
},
"@schematics/angular": {

View File

@ -6,9 +6,9 @@ import { ReadAllByMemberSelector, ReadSelector } from 'packages/notification/sto
import { Page, PageParams } from '../../../model';
import { RPCClientError } from '@loafer/ng-rpc/protocol';
import { AuthSelector } from 'packages/member/store';
import { Member } from 'packages/member/model';
import { Member } from '@overflow/commons-typescript/model/member';
import { PagesComponent } from 'app/pages/pages.component';
import { Notification } from 'packages/notification/model';
import { Notification } from '@overflow/commons-typescript/model/notification';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';

View File

@ -5,7 +5,7 @@ import {ActivatedRoute, Router} from '@angular/router';
import * as AuthStore from '../../../../../packages/member/store/auth';
import {select, Store} from '@ngrx/store';
import {AuthSelector} from '../../../../../packages/member/store';
import {Member} from '../../../../../packages/member/model';
import {Member} from '@overflow/commons-typescript/model/member';
@Component({
selector: 'of-inline-profile',

View File

@ -1,16 +0,0 @@
<p-panel header="{{title}}">
<div *ngIf="crawler; else info" class="ui-g" style="height: 180px; overflow: auto">
<div class="ui-g-12" *ngFor="let item of inputItems">
<span class="md-inputfield">
<input id="name" type="text" pInputText />
<label for="name">User</label>
</span>
</div>
</div>
<ng-template #info>
<div>개발자의 배려가 돋보이는 친절한 안내 메시지</div>
</ng-template>
<button *ngIf="crawler" type="button" label="Test" icon="ui-icon-send" pButton (click)="testCredentials()"></button>
</p-panel>

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CrawlerAuthComponent } from './crawler-auth.component';
describe('FilterComponent', () => {
let component: CrawlerAuthComponent;
let fixture: ComponentFixture<CrawlerAuthComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CrawlerAuthComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CrawlerAuthComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,96 +0,0 @@
import { Component, OnInit, Input, OnChanges, Output, EventEmitter } from '@angular/core';
import { Router } from '@angular/router';
import { MetaCrawler } from '../../../../meta/crawler/model/MetaCrawler';
import { Store, select } from '@ngrx/store';
import { RPCClientError } from '@loafer/ng-rpc/protocol';
import * as ListStore from 'packages/meta/crawler-input-item/store/list';
import { ReadCrawlerInputItemSelector } from 'packages/meta/crawler-input-item/store';
import { MetaCrawlerInputItem } from 'packages/meta/crawler-input-item/model/MetaCrawlerInputItem';
@Component({
selector: 'of-crawler-auth',
templateUrl: './crawler-auth.component.html',
})
export class CrawlerAuthComponent implements OnInit, OnChanges {
inputItems$ = this.listStore.pipe(select(ReadCrawlerInputItemSelector.select('inputs')));
inputItems: MetaCrawlerInputItem[];
title: string;
@Output() credentialPassed = new EventEmitter<boolean>();
@Input() crawler: MetaCrawler;
constructor(
private router: Router,
private listStore: Store<ListStore.State>,
) { }
ngOnInit() {
// this.inputItems$.subscribe(
// (list: MetaCrawlerInputItem[]) => {
// if (list !== null) {
// if (this.inputItems !== list) {
// this.testPassEvent.emit(false);
// }
// this.inputItems = list;
// }
// },
// (error: RPCClientError) => {
// console.log(error.response.message);
// }
// );
}
ngOnChanges() {
// this.getCrawlerAuthInputItems();
this.title = '3. Credentials';
this.inputItems = [];
// Temporary data
if (null == this.crawler) {
return;
}
this.title += ' for ' + this.crawler.name;
for (let i = 0; i < 10; i++) {
const item: MetaCrawlerInputItem = {
id: i,
// inputType: {
// id: i,
// name: '',
// description: '',
// },
crawler: null,
description: '',
name: '',
createDate: new Date(),
required: true,
defaultValue: '',
pattern: '',
keyName: '',
keyValue: '',
};
this.inputItems.push(item);
}
}
getCrawlerAuthInputItems() {
this.listStore.dispatch(new ListStore.ReadAll(this.crawler));
}
testCredentials() {
// switch (this.crawler.id) {
// case 1:
// break;
// case 2:
// break;
// case 3:
// break;
// default :
// break;
// }
this.credentialPassed.emit(true);
}
}

View File

@ -1,16 +0,0 @@
<div *ngIf="target; else info">
<p-orderList [value]="crawlers" [listStyle]="{'height':'200px'}" [responsive]="true" header="2. Choose a Crawler" filterBy="name"
(onSelectionChange)="onSelectionChange($event)">
<ng-template let-crawler pTemplate="item">
<div class="ui-helper-clearfix">
<div style="font-size:14px;float:right;margin:15px 5px 0 0">{{crawler.name}}</div>
</div>
</ng-template>
</p-orderList>
</div>
<ng-template #info>
<p-panel header="2. Choose a Crawler">
<div>개발자의 배려가 돋보이는 친절한 안내 메시지</div>
</p-panel>
</ng-template>

View File

@ -1,8 +0,0 @@
.radio-group {
display: inline-flex;
flex-direction: column;
}
.radio-button {
margin: 5px;
}

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CrawlerSelectorComponent } from './crawler-selector.component';
describe('FilterComponent', () => {
let component: CrawlerSelectorComponent;
let fixture: ComponentFixture<CrawlerSelectorComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CrawlerSelectorComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CrawlerSelectorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,68 +0,0 @@
import { Component, OnInit, Input, OnChanges, AfterContentInit, Output, EventEmitter } from '@angular/core';
import { Router } from '@angular/router';
import { Target } from 'packages/target/model';
import { Store, select } from '@ngrx/store';
import { RPCClientError } from '@loafer/ng-rpc/protocol';
import * as ListStore from 'packages/meta/crawler/store/list';
import { ReadAllCrawlerSelector } from 'packages/meta/crawler/store';
import { MetaCrawler } from 'packages/meta/crawler/model/MetaCrawler';
@Component({
selector: 'of-crawler-selector',
templateUrl: './crawler-selector.component.html',
styleUrls: ['./crawler-selector.component.scss']
})
export class CrawlerSelectorComponent implements OnInit, OnChanges, AfterContentInit {
crawlers$ = this.listStore.pipe(select(ReadAllCrawlerSelector.select('metaCrawlerList')));
@Input() target: Target;
crawlers: MetaCrawler[];
@Output() crawlerSelected = new EventEmitter<MetaCrawler>();
constructor(
private router: Router,
private listStore: Store<ListStore.State>,
) { }
ngOnInit() {
// this.crawlers$.subscribe(
// (list: MetaCrawler[]) => {
// if (list !== null) {
// this.crawlers = list;
// }
// },
// (error: RPCClientError) => {
// console.log(error.response.message);
// }
// );
}
ngAfterContentInit() {
// this.listStore.dispatch(new ListStore.ReadAll());
}
ngOnChanges() {
this.crawlers = [];
if (null == this.target) {
return;
}
// Temporary Data
for (let i = 0; i < 4; i++) {
const c: MetaCrawler = {
id: i,
name: 'CrawlerName' + i + ' For ' + this.target.displayName,
};
this.crawlers.push(c);
}
}
onSelectionChange(event) {
this.crawlerSelected.emit(event.value[0]);
}
}

View File

@ -1,10 +0,0 @@
<p-panel header="4. Choose sensor items">
<div *ngIf="crawler && target; else info" class="ui-g" style="height: 200px; overflow: auto">
<p-tree [value]="itemTreeNode" selectionMode="checkbox" [(selection)]="selectedItems" (onNodeSelect)="onNodeSelect($event)"
(onNodeUnselect)="onNodeUnselect($event)"></p-tree>
</div>
<ng-template #info>
<div>개발자의 배려가 돋보이는 친절한 안내 메시지</div>
</ng-template>
</p-panel>

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SensorItemSelectorComponent } from './sensor-item-selector.component';
describe('SensorItemSelectorComponent', () => {
let component: SensorItemSelectorComponent;
let fixture: ComponentFixture<SensorItemSelectorComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SensorItemSelectorComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SensorItemSelectorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,127 +0,0 @@
import { Component, OnInit, OnChanges, Input, Output, EventEmitter, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { Store, select } from '@ngrx/store';
import { RPCClientError } from '@loafer/ng-rpc/protocol';
import * as ListStore from 'packages/meta/sensor-display-item/store/list';
import { ReadAllSensorDisplayItemByCrawlerSelector } from 'packages/meta/sensor-display-item/store';
import { MetaSensorDisplayItem } from 'packages/meta/sensor-display-item/model/MetaSensorDisplayItem';
import { MetaCrawler } from 'packages/meta/crawler/model/MetaCrawler';
import { MetaSensorItemType } from 'packages/meta/sensor-item-type/model/MetaSensorItemType';
import { TreeNode } from 'primeng/primeng';
import { Target } from 'packages/target/model';
@Component({
selector: 'of-sensor-item-selector',
templateUrl: './sensor-item-selector.component.html',
styleUrls: ['./sensor-item-selector.component.scss']
})
export class SensorItemSelectorComponent implements OnInit, OnChanges {
@Input() target: Target;
@Input() crawler: MetaCrawler;
@Output() sensorItemsSelected = new EventEmitter<TreeNode[]>();
items$ = this.listStore.pipe(select(ReadAllSensorDisplayItemByCrawlerSelector.select('list')));
selectedItems: TreeNode[];
itemTreeNode: TreeNode[];
constructor(
private router: Router,
private listStore: Store<ListStore.State>,
) { }
ngOnInit() {
// this.selectedItems = new Set();
// this.items$.subscribe(
// (list: MetaSensorDisplayItem[]) => {
// if (list !== null) {
// }
// },
// (error: RPCClientError) => {
// console.log(error.response.message);
// }
// );
}
ngOnChanges() {
// this.selectedItems.clear();
// this.listStore.dispatch(new ListStore.ReadAllByCrawler(this.crawler));
this.itemTreeNode = [];
if (!this.target || !this.crawler) {
return;
}
// Temporary data
const displayItems = [];
for (let i = 0; i < 10; i++) {
let isDefault = false;
const t: MetaSensorItemType = {
name: 'CPU'
};
if (i % 2) {
isDefault = true;
t.name = 'Memory';
}
const si: MetaSensorDisplayItem = {
id: i,
key: 'SensorDisplayItemKey' + i,
displayName: 'this.is.display.item.name' + i,
description: 'Description' + i,
default: isDefault,
itemType: t
};
displayItems.push(si);
}
this.generateTreeData(displayItems);
}
generateTreeData(items) {
this.itemTreeNode = [];
for (const item of items) {
const categoryNode = this.existCategory(item);
if (categoryNode === null) {
const childrenNode = [];
childrenNode.push(this.getChildNode(item));
const node = {
label: item.itemType.name,
children: childrenNode,
expanded: true,
};
this.itemTreeNode.push(node);
} else {
categoryNode.children.push(this.getChildNode(item));
}
}
}
getChildNode(item) {
const childNode = {
label: item.displayName,
expandedIcon: item.default ? 'ui-icon-star' : '',
collapsedIcon: item.default ? 'ui-icon-star' : '',
expanded: true,
data: item
};
return childNode;
}
existCategory(item: MetaSensorDisplayItem) {
let categoryNode = null;
for (const node of this.itemTreeNode) {
if (node.label === item.itemType.name) {
categoryNode = node;
}
}
return categoryNode;
}
onNodeSelect(event) {
this.sensorItemsSelected.emit(this.selectedItems);
}
onNodeUnselect(event) {
this.sensorItemsSelected.emit(this.selectedItems);
}
}

View File

@ -1,3 +0,0 @@
<div>
page 2222222
</div>

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SettingETCComponent } from './setting-etc.component';
describe('SettingETCComponent', () => {
let component: SettingETCComponent;
let fixture: ComponentFixture<SettingETCComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SettingETCComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SettingETCComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,32 +0,0 @@
import { Component, OnInit, Input } from '@angular/core';
import { Router } from '@angular/router';
import { MetaCrawler } from 'packages/meta/crawler/model/MetaCrawler';
import { MetaSensorDisplayItem } from '../../../../meta/sensor-display-item/model/MetaSensorDisplayItem';
import { Target } from 'packages/target/model';
@Component({
selector: 'of-sensor-setting-etc',
templateUrl: './setting-etc.component.html',
})
export class SettingETCComponent implements OnInit {
@Input() selectedTarget: Target;
@Input() selectedCrawler: MetaCrawler;
@Input() selectedItems: MetaSensorDisplayItem[];
intervals = [
'600 sec',
'400 sec',
'200 sec',
];
constructor(
private router: Router,
) { }
ngOnInit() {
}
}

View File

@ -1,28 +0,0 @@
<div [hidden]="step !== 1">
<div class="ui-g">
<div class="ui-g-6">
<of-target-selector [preTarget]="preTarget" (targetSelected)="onTargetSelect($event)"></of-target-selector>
</div>
<div class="ui-g-6">
<of-crawler-auth [crawler]="selectedCrawler" (credentialPassed)="onCredentialPass($event)"></of-crawler-auth>
</div>
<div class="ui-g-6">
<of-crawler-selector [target]="selectedTarget" (crawlerSelected)="onCrawlerSelect($event)"></of-crawler-selector>
</div>
<div class="ui-g-6">
<of-sensor-item-selector [target]="selectedTarget" [crawler]="selectedCrawler" (sensorItemsSelected)="onItemsSelect($event)"></of-sensor-item-selector>
</div>
</div>
</div>
<div *ngIf="step === 2">
<of-sensor-setting-etc [selectedTarget]="selectedTarget" [selectedCrawler]="selectedCrawler" [selectedItems]="selectedSensorDisplayItems"></of-sensor-setting-etc>
</div>
<div>
<button pButton *ngIf="step === 1" class="ui-button-danger" type="button" label="Cancel" icon="ui-icon-close" (click)="onCancel()"></button>
<button pButton *ngIf="step === 2" class="ui-button-danger" type="button" label="Prev" icon="ui-icon-close" (click)="onPrev()"></button>
<button pButton *ngIf="step === 1" [disabled]="!nextable" type="button" label="Next" icon="fa-check" (click)="onNext()"></button>
<button pButton *ngIf="step === 2" type="button" label="Done" icon="fa-check" (click)="onDone()"></button>
</div>

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SettingComponent } from './setting.component';
describe('SensorSettingComponent', () => {
let component: SettingComponent;
let fixture: ComponentFixture<SettingComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SettingComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SettingComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,113 +0,0 @@
import { Component, OnInit, Input, Inject, DoCheck, ViewEncapsulation, Output, EventEmitter, OnChanges } from '@angular/core';
import { Target } from 'packages/target/model';
import { Infra } from 'packages/infra/model';
import { MetaCrawler } from 'packages/meta/crawler/model/MetaCrawler';
import { MetaSensorDisplayItem } from 'packages/meta/sensor-display-item/model/MetaSensorDisplayItem';
import { Store, select } from '@ngrx/store';
import { RPCClientError } from '@loafer/ng-rpc/protocol';
import * as SensorItemKeyListStore from 'packages/sensor-item/store/key-list';
import { ReadSensorItemKeySelector } from 'packages/sensor-item/store';
import { MetaSensorItemKey } from 'packages/meta/sensor-item-key/model/MetaSensorItemKey';
import { TreeNode } from 'primeng/primeng';
@Component({
selector: 'of-sensor-setting',
templateUrl: './setting.component.html',
encapsulation: ViewEncapsulation.None
})
export class SettingComponent implements OnInit, DoCheck, OnChanges {
@Input() preTarget: Target;
@Output() close = new EventEmitter();
nextable = false;
selectedTarget: Target;
selectedCrawler: MetaCrawler;
credentialPassed: boolean;
selectedSensorDisplayItems: MetaSensorDisplayItem[];
itemNodes: TreeNode[];
step = 1;
sensorItemKeys$ = this.keyListStore.pipe(select(ReadSensorItemKeySelector.select('list')));
constructor(
private keyListStore: Store<SensorItemKeyListStore.State>,
) {
}
ngOnInit() {
// this.sensorItemKeys$.subscribe(
// (list: MetaSensorItemKey[]) => {
// if (list !== null) {
// console.log(list);
// }
// },
// (error: RPCClientError) => {
// console.log(error.response.message);
// }
// );
}
ngOnChanges(changes) {
}
ngDoCheck() {
try {
if (
this.selectedTarget === null ||
this.selectedCrawler === null ||
this.itemNodes === null ||
this.itemNodes.length === 0 ||
!this.credentialPassed
) {
this.nextable = false;
} else {
this.nextable = true;
}
} catch (exception) {
this.nextable = false;
}
}
onCancel() {
this.selectedTarget = null;
this.selectedCrawler = null;
this.credentialPassed = false;
this.selectedSensorDisplayItems = null;
this.close.emit();
}
onNext() {
this.step += 1;
}
onPrev() {
this.step -= 1;
}
onDone() {
this.selectedSensorDisplayItems = [];
for (const node of this.itemNodes) {
if (node.data && node.data !== undefined) {
this.selectedSensorDisplayItems.push(node.data);
}
}
console.log(this.selectedSensorDisplayItems);
}
onTargetSelect(t: Target) {
this.selectedTarget = t;
}
onCrawlerSelect(c: MetaCrawler) {
this.selectedCrawler = c;
}
onCredentialPass(b: boolean) {
this.credentialPassed = b;
}
onItemsSelect(nodes: TreeNode[]) {
this.itemNodes = nodes;
}
}

View File

@ -1,9 +0,0 @@
<p-orderList [value]="targets" [listStyle]="{'height':'200px'}" [responsive]="true" header="1. Choose a target" filterBy="displayName"
(onSelectionChange)="onSelectionChange($event)">
<ng-template let-target pTemplate="item">
<div class="ui-helper-clearfix">
<img src="assets/demo/images/car/BMW.gif" style="display:inline-block;margin:2px 0 2px 2px" />
<div style="font-size:14px;float:right;margin:15px 5px 0 0">{{target.displayName}}</div>
</div>
</ng-template>
</p-orderList>

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TargetSelectorComponent } from './target-selector.component';
describe('FilterComponent', () => {
let component: TargetSelectorComponent;
let fixture: ComponentFixture<TargetSelectorComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TargetSelectorComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TargetSelectorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,90 +0,0 @@
import { Component, OnInit, Output, EventEmitter, Input, AfterContentInit, OnChanges } from '@angular/core';
import { Router } from '@angular/router';
import { Target } from 'packages/target/model';
import { RPCClientError } from '@loafer/ng-rpc/protocol';
import { Domain } from 'packages/domain/model';
import { AuthSelector } from 'packages/member/store';
import * as ListStore from 'packages/infra/store/list';
import { ListSelector } from 'packages/infra/store';
import { Store, select } from '@ngrx/store';
import { Page, PageParams } from 'app/commons/model';
import { SelectItem } from 'primeng/primeng';
@Component({
selector: 'of-target-selector',
templateUrl: './target-selector.component.html',
})
export class TargetSelectorComponent implements OnInit, OnChanges {
targets$ = this.store.pipe(select(ListSelector.select('page')));
@Input() preTarget: Target = null;
@Output() targetSelected = new EventEmitter<Target>();
targets: Target[] = null;
constructor(
private router: Router,
private store: Store<ListStore.State>
) { }
ngOnInit() {
// this.targets$.subscribe(
// (page: Page) => {
// if (page !== null) {
// this.convertInfraToTarget(page);
// }
// },
// (error: RPCClientError) => {
// console.log(error.response.message);
// }
// );
}
ngOnChanges(changes) {
this.targets = [];
if (this.preTarget === null) {
this.getTargetList();
} else {
this.targets.push(this.preTarget);
}
}
convertInfraToTarget(page: Page) {
for (const infra of page.content) {
this.targets.push(infra.target);
}
}
getTargetList() {
// this.store.select(AuthSelector.select('domain')).subscribe(
// (domain: Domain) => {
// const pageParams: PageParams = {
// pageNo: '0',
// countPerPage: '9999',
// sortCol: 'id',
// sortDirection: 'descending'
// };
// this.store.dispatch(new ListStore.ReadAllByDomain({ domain, pageParams }));
// },
// (error) => {
// console.log(error);
// }
// );
// Temporary data
for (let i = 0; i < 10; i++) {
const t: Target = {
id: i,
displayName: 'DisplayName' + i,
createDate: new Date(),
description: 'Description' + i,
};
this.targets.push(t);
}
}
onSelectionChange(event) {
this.targetSelected.emit(event.value[0]);
}
}

View File

@ -12,7 +12,6 @@ import { MetaCrawler } from '@overflow/commons-typescript/model/meta';
@Component({
selector: 'of-crawler-selector',
templateUrl: './crawler-selector.component.html',
styleUrls: ['./crawler-selector.component.scss']
})
export class CrawlerSelectorComponent implements OnInit, OnChanges, AfterContentInit {

View File

@ -15,7 +15,7 @@ import 'rxjs/add/operator/take';
import { RPCClientError } from '@loafer/ng-rpc/protocol';
import { Sensor } from '../../model';
import { Sensor } from '@overflow/commons-typescript/model/sensor';
import { SensorService } from '../../service/sensor.service';
import {