This is an automated email from the ASF dual-hosted git repository.

sardell pushed a commit to branch feature/METRON-1856-parser-aggregation
in repository https://gitbox.apache.org/repos/asf/metron.git


The following commit(s) were added to 
refs/heads/feature/METRON-1856-parser-aggregation by this push:
     new 5599d18  METRON-2136 Add parser aggregation sidebar (ruffle1986 via 
sardell) closes apache/metron#1427
5599d18 is described below

commit 5599d181d552924ef2c035337574f01529c26c53
Author: ruffle1986 <ftamas.m...@gmail.com>
AuthorDate: Fri Aug 2 14:36:41 2019 +0200

    METRON-2136 Add parser aggregation sidebar (ruffle1986 via sardell) closes 
apache/metron#1427
---
 .../{effects/index.ts => models/parser.model.ts}   |   9 +-
 .../sensor-parser-aggregate-sidebar.component.html |  74 ++++++++++
 .../sensor-parser-aggregate-sidebar.component.scss |  97 +++++++++++++
 .../sensor-parser-aggregate-sidebar.component.ts   | 157 +++++++++++++++++++++
 .../sensor-parser-aggregate-sidebar.module.ts}     |  19 ++-
 .../sensor-parser-aggregate-sidebar.routing.ts}    |  13 +-
 6 files changed, 357 insertions(+), 12 deletions(-)

diff --git a/metron-interface/metron-config/src/app/sensors/effects/index.ts 
b/metron-interface/metron-config/src/app/sensors/models/parser.model.ts
similarity index 85%
copy from metron-interface/metron-config/src/app/sensors/effects/index.ts
copy to metron-interface/metron-config/src/app/sensors/models/parser.model.ts
index 8f6ad93..bc02f0c 100644
--- a/metron-interface/metron-config/src/app/sensors/effects/index.ts
+++ b/metron-interface/metron-config/src/app/sensors/models/parser.model.ts
@@ -15,9 +15,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+export interface ParserModel {
+  group?: string,
 
- import { SensorsEffects } from './sensors.effects';
+  setName(value: string)
 
- export * from './sensors.effects';
+  getName(): string
 
- export const effects = [ SensorsEffects ];
+  getDescription(): string
+}
diff --git 
a/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.component.html
 
b/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.component.html
new file mode 100644
index 0000000..8b3692c
--- /dev/null
+++ 
b/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.component.html
@@ -0,0 +1,74 @@
+<!--
+  Licensed to the Apache Software
+       Foundation (ASF) under one or more contributor license agreements. See 
the
+       NOTICE file distributed with this work for additional information 
regarding
+       copyright ownership. The ASF licenses this file to You under the Apache 
License,
+       Version 2.0 (the "License"); you may not use this file except in 
compliance
+       with the License. You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software 
distributed
+       under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+       OR CONDITIONS OF ANY KIND, either express or implied. See the License 
for
+  the specific language governing permissions and limitations under the 
License.
+  -->
+<metron-config-metron-modal>
+  <div class="metron-slider-pane-edit load-right-to-left dialog1x 
aggregate-sensors-pane">
+    <i class="fa fa-times float-right close-button" (click)="close()"></i>
+    <div class="form-title">
+      Aggregate Sensors
+    </div>
+    <div>
+      <div *ngIf="showCreateForm()">
+        <div class="form-fields">
+          <div class="form-field">
+            <label>
+              <span class="label-text">NAME *</span>
+              <input #groupNameInput type="text" class="form-control" 
[value]="name" [readOnly]="existingGroup" (keyup)="onNameChange($event)" />
+              <div *ngIf="groupNameInvalid"><label><span class="warning-text"> 
Group already exists </span></label></div>
+            </label>
+          </div>
+          <div class="form-field">
+            <label>
+              <span class="label-text">DESCRIPTION</span>
+              <input #descriptionInput type="text" class="form-control" 
[value]="description"/>
+            </label>
+          </div>
+        </div>
+        <div>
+          <button (click)="createNew(groupNameInput.value, 
descriptionInput.value)"
+                  (keyup.enter)="createNew(groupNameInput.value, 
descriptionInput.value)"
+                  class="btn save-button"
+                  [disabled]="groupNameInvalid">DONE</button>
+          <button (click)="close()"
+                  (keyup.enter)="close()"
+                  class="btn form-enable-disable-button">CANCEL</button>
+        </div>
+      </div>
+      <div *ngIf="!showCreateForm()">
+        <div class="form-fields">
+          <span class="label-text">JOIN BY GROUP</span>
+          <div class="switch-buttons">
+            <button
+              (click)="allowMerge = true"
+              [ngClass]="{ 'active': allowMerge }"
+            >
+              MERGE
+            </button><button
+              (click)="allowMerge = false"
+              [ngClass]="{ 'active': !allowMerge }"
+            >
+              CREATE NEW
+            </button>
+          </div>
+        </div>
+        <div>
+          <button (click)="mergeOrCreate()" class="btn 
save-button">DONE</button>
+          <button (click)="close()" class="btn 
form-enable-disable-button">CANCEL</button>
+        </div>
+      </div>
+    </div>
+
+  </div>
+</metron-config-metron-modal>
\ No newline at end of file
diff --git 
a/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.component.scss
 
b/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.component.scss
new file mode 100644
index 0000000..4264588
--- /dev/null
+++ 
b/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.component.scss
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+$base-gutter: 20px;
+
+.aggregate-sensors-pane {
+  padding: $base-gutter;
+}
+
+.form-title {
+  margin-bottom: $base-gutter;
+}
+
+.form-fields {
+  border-top: 1px solid #2B576B;
+  border-bottom: 1px solid #2B576B;
+  padding: $base-gutter 0 0;
+  margin-bottom: $base-gutter;
+}
+
+.form-field {
+
+  margin-bottom: $base-gutter;
+
+  label {
+    display: block;
+  }
+
+  & .label-text {
+    display: block;
+  }
+
+  & input {
+    width: 100%;
+  }
+}
+
+.save-button {
+  background-color: #006ea0;
+  border-color: #006ea0;
+  color: white;
+  font-size: 14px;
+  width: 32%;
+}
+
+.switch-buttons {
+  margin-bottom: $base-gutter;
+
+  & button {
+    appearance: none;
+    display: inline-block;
+    color: #999;
+    border-color: #4D4D4D;
+    width: 139px;
+    height: 35px;
+    line-height: 35px;
+    vertical-align: middle;
+    font-size: 14px;
+    cursor: pointer;
+    background: #404040;
+    outline: none;
+
+    &:first-child {
+      border-right: none;
+    }
+
+    &:nth-child(2) {
+      border-left: none;
+    }
+
+    &.active {
+      color: #fff;
+      background: #2C5E6B;
+      border-color: #2C5E6B;
+      cursor: default;
+    }
+  }
+}
+
+label .warning-text {
+  font-size: 12px;
+  font-family: Roboto-Medium;
+}
\ No newline at end of file
diff --git 
a/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.component.ts
 
b/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.component.ts
new file mode 100644
index 0000000..a68f93c
--- /dev/null
+++ 
b/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.component.ts
@@ -0,0 +1,157 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Component, OnInit, OnDestroy } from '@angular/core';
+import { Router, ActivatedRoute } from '@angular/router';
+import { Store, select } from '@ngrx/store';
+import { Observable, Subscription, combineLatest } from 'rxjs';
+import * as fromReducers from '../reducers';
+import * as fromActions from '../actions';
+import { getGroups, GroupState } from '../reducers';
+
+@Component({
+  selector: 'metron-config-sensor-aggregate',
+  templateUrl: './sensor-parser-aggregate-sidebar.component.html',
+  styleUrls: ['./sensor-parser-aggregate-sidebar.component.scss']
+})
+export class SensorParserAggregateSidebarComponent implements OnInit, 
OnDestroy {
+
+  private forceCreate = false;
+  private draggedId: string;
+  private dropTargetId: string;
+  private state$: Observable<fromReducers.SensorState>;
+  private stateSub: Subscription;
+  private targetGroup: string;
+  private groupDetails = {
+    name: '',
+    description: ''
+  };
+  groups: GroupState;
+  name: string;
+  description: string;
+  existingGroup = null;
+  allowMerge = true;
+  groupNameInvalid = false;
+
+  constructor(
+    private router: Router,
+    private store: Store<fromReducers.State>,
+    private route: ActivatedRoute,
+  ) {
+    this.state$ = store.pipe(select(fromReducers.getSensorsState));
+  }
+
+  ngOnInit() {
+    const combined = combineLatest(this.state$, this.route.params);
+    this.stateSub = combined.subscribe(([state, routeParams]) => {
+      this.draggedId = state.layout.dnd.draggedId;
+      this.dropTargetId = state.layout.dnd.dropTargetId;
+      this.targetGroup = state.layout.dnd.targetGroup;
+      this.groups = state.groups;
+      if (routeParams['id']) {
+        this.existingGroup = this.groups.items.filter(g => g.config.getName() 
=== routeParams['id']);
+        this.name = this.existingGroup[0].config.getName();
+        this.description = this.existingGroup[0].config.getDescription();
+      } else {
+        this.name = 'Aggregate-' + [this.draggedId, 
this.dropTargetId].join('-') ;
+        this.description = '';
+      }
+    });
+  }
+
+  close() {
+    this.forceCreate = false;
+    this.router.navigateByUrl('/sensors');
+  }
+
+  createNew(groupName: string, groupDescription: string) {
+    groupName = groupName.trim();
+    groupDescription = groupDescription.trim();
+
+    this.groupDetails.name = groupName;
+    this.groupDetails.description = groupDescription;
+    const group = this.groups.items.filter(item => item.config.getName() === 
this.name);
+    if (group.length) {
+      this.store.dispatch(new 
fromActions.UpdateGroupDescription(this.groupDetails));
+      this.close();
+      return;
+    } else {
+      this.store.dispatch(new fromActions.CreateGroup(this.groupDetails));
+    }
+
+    if (!this.targetGroup) {
+      this.store.dispatch(new fromActions.AggregateParsers({
+        groupName,
+        parserIds: [
+          this.dropTargetId,
+          this.draggedId,
+        ]
+      }));
+    } else {
+      const parserIds = [this.draggedId, this.dropTargetId];
+      this.store.dispatch(new fromActions.AddToGroup({
+        groupName,
+        parserIds
+      }));
+      parserIds.forEach((parserId) => {
+        this.store.dispatch(new fromActions.InjectAfter({
+          reference: groupName,
+          parserId,
+        }));
+      });
+    }
+
+    this.close();
+  }
+
+  mergeOrCreate() {
+    if (this.allowMerge) {
+      this.addToExisting();
+    } else {
+      this.forceCreate = true;
+    }
+  }
+
+  addToExisting() {
+
+    this.store.dispatch(new fromActions.AddToGroup({
+      groupName: this.targetGroup,
+      parserIds: [this.draggedId]
+    }));
+
+    this.store.dispatch(new fromActions.InjectAfter({
+      reference: this.dropTargetId,
+      parserId: this.draggedId,
+    }));
+
+    this.close();
+  }
+
+  showCreateForm(): boolean {
+    return !this.targetGroup || this.forceCreate;
+  }
+
+  onNameChange(e) {
+    const value = e.target.value.trim();
+    const groupWithSameName = this.groups.items.find(group => 
group.config.getName() === value);
+    this.groupNameInvalid = !!(groupWithSameName);
+  }
+
+  ngOnDestroy() {
+    this.stateSub.unsubscribe();
+  }
+}
diff --git a/metron-interface/metron-config/src/app/sensors/effects/index.ts 
b/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.module.ts
similarity index 64%
copy from metron-interface/metron-config/src/app/sensors/effects/index.ts
copy to 
metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.module.ts
index 8f6ad93..c5f2522 100644
--- a/metron-interface/metron-config/src/app/sensors/effects/index.ts
+++ 
b/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.module.ts
@@ -15,9 +15,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import { NgModule } from '@angular/core';
+import { routing } from './sensor-parser-aggregate-sidebar.routing';
+import { SensorParserAggregateSidebarComponent } from 
'./sensor-parser-aggregate-sidebar.component';
+import { SharedModule } from '../../shared/shared.module';
 
- import { SensorsEffects } from './sensors.effects';
-
- export * from './sensors.effects';
-
- export const effects = [ SensorsEffects ];
+@NgModule({
+  imports: [
+    routing,
+    SharedModule
+  ],
+  declarations: [
+    SensorParserAggregateSidebarComponent
+  ],
+})
+export class SensorParserAggregateSidebarModule {}
diff --git a/metron-interface/metron-config/src/app/sensors/effects/index.ts 
b/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.routing.ts
similarity index 56%
rename from metron-interface/metron-config/src/app/sensors/effects/index.ts
rename to 
metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.routing.ts
index 8f6ad93..ba994f7 100644
--- a/metron-interface/metron-config/src/app/sensors/effects/index.ts
+++ 
b/metron-interface/metron-config/src/app/sensors/sensor-parser-aggregate-sidebar/sensor-parser-aggregate-sidebar.routing.ts
@@ -15,9 +15,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import { ModuleWithProviders }  from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+import { SensorParserAggregateSidebarComponent } from 
'./sensor-parser-aggregate-sidebar.component';
+import { AuthGuard } from '../../shared/auth-guard';
 
- import { SensorsEffects } from './sensors.effects';
+const routes: Routes = [
+  { path: 'sensor-aggregate', component: 
SensorParserAggregateSidebarComponent, canActivate: [ AuthGuard ], outlet: 
'dialog'},
+  { path: 'sensor-aggregate/:id', component: 
SensorParserAggregateSidebarComponent, canActivate: [ AuthGuard ], outlet: 
'dialog'}
+];
 
- export * from './sensors.effects';
-
- export const effects = [ SensorsEffects ];
+export const routing: ModuleWithProviders = RouterModule.forChild(routes);

Reply via email to