feature[TW19347]: ICD - Integrate Node API into MIM UI
- Adds editing functionality to the MIM UI
- Pulls graph data from rest api
- Fixes some tests that were broken from a previous commit
Change-Id: Ie8c11b3187da89b5219722bff4b3f6d75062e9cb
Signed-off-by: Luciano T Vaglienti <luciano.t.vaglienti@boeing.com>
diff --git a/plugins/org.eclipse.osee.web/angular.json b/plugins/org.eclipse.osee.web/angular.json
index fefc70d..076187e 100644
--- a/plugins/org.eclipse.osee.web/angular.json
+++ b/plugins/org.eclipse.osee.web/angular.json
@@ -122,7 +122,8 @@
"codeCoverageExclude": [
"src/app/ple/plconfig/types/**",
"src/app/ple/plconfig/testing/**",
- "src/app/ple/messaging/connection-view/mock/**"
+ "src/app/ple/messaging/connection-view/mock/**",
+ "**/*.mock.*"
],
"assets": [
"src/favicon.ico",
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.html
index 7a9d4c0..a9c83d5 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.html
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.html
@@ -1,5 +1,6 @@
+<button mat-raised-button (click)="openSettingsDialog()" style="float:right">Settings</button>
<div class="connection-view">
<osee-connectionview-branch-type-selector></osee-connectionview-branch-type-selector>
<osee-connectionview-branch-selector></osee-connectionview-branch-selector>
- <osee-connectionview-graph></osee-connectionview-graph>
+ <osee-connectionview-graph [editMode]="editMode"></osee-connectionview-graph>
</div>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.spec.ts
index 614fc5f..44ee7cb 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.spec.ts
@@ -1,30 +1,65 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule } from '@angular/material/dialog';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { RouteStateService } from '../../../services/route-state-service.service';
import { BranchDummySelector} from '../../../testing/MockComponents/BranchSelector.mock'
import { BranchTypeDummySelector } from '../../../testing/MockComponents/BranchTypeSelector.mock';
import { GraphDummy } from '../../../testing/MockComponents/Graph.mock';
+import { HarnessLoader } from '@angular/cdk/testing';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { BaseComponent } from './base.component';
+import { MatButtonHarness } from '@angular/material/button/testing';
+import { EditAuthService } from 'src/app/ple/messaging/shared/services/edit-auth-service.service';
+import { editAuthServiceMock } from '../../../mocks/EditAuthService.mock';
describe('BaseComponent', () => {
let component: BaseComponent;
+ let routeState: RouteStateService;
+ let loader: HarnessLoader;
let fixture: ComponentFixture<BaseComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
- imports:[],
+ imports: [MatDialogModule, MatButtonModule, NoopAnimationsModule],
+ providers:[{provide:EditAuthService,useValue:editAuthServiceMock}],
declarations: [ BaseComponent, BranchDummySelector, BranchTypeDummySelector, GraphDummy ]
})
- .compileComponents();
+ .compileComponents();
+ routeState = TestBed.inject(RouteStateService);
});
beforeEach(() => {
+ routeState.branchId = '10';
fixture = TestBed.createComponent(BaseComponent);
component = fixture.componentInstance;
fixture.detectChanges();
+ loader = TestbedHarnessEnvironment.loader(fixture);
+ });
+
+ beforeEach(function () {
+ var store:any = {10:'{mim:{editMode:true}}'};
+
+ spyOn(localStorage, 'getItem').and.callFake(function (key) {
+ return store[key];
+ });
+ spyOn(localStorage, 'setItem').and.callFake(function (key, value) {
+ return store[key] = value + '';
+ });
+ spyOn(localStorage, 'clear').and.callFake(function () {
+ store = {};
+ });
});
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ it('should open settings dialog', async () => {
+ let spy = spyOn(component, 'openSettingsDialog').and.callThrough();
+ (await (await loader.getHarness(MatButtonHarness)).click());
+ expect(spy).toHaveBeenCalled();
+ })
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.ts
index 65c1583..c9d07c5 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/base/base/base.component.ts
@@ -1,4 +1,9 @@
import { Component, OnInit } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { ColumnPreferencesDialogComponent } from 'src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component';
+import { RouteStateService } from '../../../services/route-state-service.service';
+import { branchStorage} from '../../../../shared/types/branchstorage'
+import { settingsDialogData } from 'src/app/ple/messaging/shared/types/settingsdialog';
@Component({
selector: 'osee-connectionview-base',
@@ -7,10 +12,58 @@
})
export class BaseComponent implements OnInit {
- constructor () { }
+ editMode: boolean = false;
+ constructor (private routeState: RouteStateService, public dialog: MatDialog) { }
ngOnInit(): void {
+ let branchStorage = JSON.parse(
+ localStorage.getItem(this.routeState.id.getValue()) || '{}'
+ ) as branchStorage;
+ if (branchStorage?.mim?.editMode) {
+ this.editMode = branchStorage.mim.editMode;
+ }
+ }
+
+ openSettingsDialog() {
+ let dialogData:settingsDialogData = {
+ branchId: this.routeState.id.getValue(),
+ allHeaders2: [],
+ allowedHeaders2: [],
+ allHeaders1: [],
+ allowedHeaders1: [],
+ editable: this.editMode,
+ headers1Label: '',
+ headers2Label: '',
+ headersTableActive: false,
+ };
+ const dialogRef = this.dialog.open(ColumnPreferencesDialogComponent, {
+ data: dialogData,
+ });
+ dialogRef.afterClosed().subscribe((result:settingsDialogData) => {
+ this.editMode = result.editable;
+ //@todo: remove when user preferences are available on backend
+ if (localStorage.getItem(this.routeState.id.getValue())) {
+ let branchStorage = JSON.parse(
+ localStorage.getItem(this.routeState.id.getValue()) ||
+ '{}'
+ ) as branchStorage;
+ branchStorage.mim['editMode'] = result.editable;
+ localStorage.setItem(
+ this.routeState.id.getValue(),
+ JSON.stringify(branchStorage)
+ );
+ } else {
+ localStorage.setItem(
+ this.routeState.id.getValue(),
+ JSON.stringify({
+ mim: {
+ editMode: result.editable,
+ },
+ })
+ );
+ }
+ });
}
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.html
new file mode 100644
index 0000000..e2df2ea
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.html
@@ -0,0 +1,16 @@
+<h1 mat-dialog-title>Remove {{data.type |titlecase}}</h1>
+<div mat-dialog-content>
+<mat-label>
+ Are you sure you want to remove {{data.type}} {{data.name}}
+ <ng-container *ngIf="data.extraNames.length>0">and it's associated relationships: </ng-container>
+ <ng-container *ngFor="let value of data.extraNames">
+ <br>
+ {{value}}
+ </ng-container>
+ <ng-container *ngIf="data.extraNames.length>0"><br></ng-container>?
+</mat-label>
+</div>
+<div mat-dialog-actions>
+ <button mat-button (click)="onNoClick()"> Cancel</button>
+ <button mat-raised-button [mat-dialog-close]="data" color="primary" [disabled]="data.name.length===0">Ok</button>
+</div>
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.spec.ts
new file mode 100644
index 0000000..de8d7f3
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.spec.ts
@@ -0,0 +1,55 @@
+import { HarnessLoader } from '@angular/cdk/testing';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatButtonHarness } from '@angular/material/button/testing';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { dialogRef } from '../../../mocks/dialogRef.mock';
+import { RemovalDialog } from '../../../types/ConfirmRemovalDialog';
+
+import { ConfirmRemovalDialogComponent } from './confirm-removal-dialog.component';
+
+describe('ConfirmRemovalDialogComponent', () => {
+ let component: ConfirmRemovalDialogComponent;
+ let fixture: ComponentFixture<ConfirmRemovalDialogComponent>;
+ let loader: HarnessLoader;
+ let dialogData: RemovalDialog = {
+ id: '',
+ name: '',
+ extraNames: [],
+ type:''
+ }
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[MatDialogModule,MatButtonModule,NoopAnimationsModule,MatFormFieldModule,FormsModule],
+ declarations: [ConfirmRemovalDialogComponent],
+ providers: [{ provide: MatDialogRef, useValue: dialogRef },
+ { provide: MAT_DIALOG_DATA, useValue: dialogData}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ConfirmRemovalDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ loader = TestbedHarnessEnvironment.loader(fixture);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should close without anything returning', async() => {
+ let buttons = await loader.getAllHarnesses(MatButtonHarness);
+ let spy = spyOn(component, 'onNoClick').and.callThrough();
+ if ((await buttons[0].getText()) === 'Cancel') {
+ await buttons[0].click();
+ expect(spy).toHaveBeenCalled()
+ }
+ })
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.ts
new file mode 100644
index 0000000..42f3a2c
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component.ts
@@ -0,0 +1,20 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { RemovalDialog } from '../../../types/ConfirmRemovalDialog';
+
+@Component({
+ selector: 'app-confirm-removal-dialog',
+ templateUrl: './confirm-removal-dialog.component.html',
+ styleUrls: ['./confirm-removal-dialog.component.sass']
+})
+export class ConfirmRemovalDialogComponent implements OnInit {
+
+ constructor(public dialogRef: MatDialogRef<ConfirmRemovalDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: RemovalDialog) { }
+
+ ngOnInit(): void {
+ }
+
+ onNoClick() {
+ this.dialogRef.close();
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.html
new file mode 100644
index 0000000..f8d4c46
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.html
@@ -0,0 +1,37 @@
+<h1 mat-dialog-title>Create Connection to Node: {{title}}</h1>
+<div mat-dialog-content>
+ <mat-form-field>
+ <mat-label>Add a Name</mat-label>
+ <input matInput type="text" [(ngModel)]="newConnection.connection.name" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <mat-label>Add a Description</mat-label>
+ <input matInput type="text" [(ngModel)]="newConnection.connection.description" #input>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <mat-label>Select a Transport Type</mat-label>
+ <mat-select [(ngModel)]="newConnection.connection.transportType" required>
+ <mat-option *ngFor="let option of ['ETHERNET','MILSTD1553_B']" [value]="option">
+ {{option}}
+ </mat-option>
+ </mat-select>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <mat-label>Select a Node to Connect To</mat-label>
+ <mat-select [(ngModel)]="newConnection.nodeId">
+ <mat-option *ngFor="let option of (nodes |async)" [value]="option.id">
+ {{option.name}}
+ </mat-option>
+ </mat-select>
+ </mat-form-field>
+</div>
+<div mat-dialog-actions>
+ <button mat-button (click)="onNoClick()">Cancel</button>
+ <button mat-raised-button [mat-dialog-close]="newConnection" color="primary" [disabled]="newConnection.connection.name.length ===0 || newConnection.nodeId.length ===0">Ok</button>
+</div>
+<!--
+
+-->
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.spec.ts
new file mode 100644
index 0000000..c69a1b2
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.spec.ts
@@ -0,0 +1,53 @@
+import { HarnessLoader } from '@angular/cdk/testing';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatButtonHarness } from '@angular/material/button/testing';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { graphServiceMock } from '../../../mocks/CurrentGraphService.mock';
+import { dialogRef } from '../../../mocks/dialogRef.mock';
+import { CurrentGraphService } from '../../../services/current-graph.service';
+
+import { CreateConnectionDialogComponent } from './create-connection-dialog.component';
+
+describe('CreateConnectionDialogComponent', () => {
+ let component: CreateConnectionDialogComponent;
+ let fixture: ComponentFixture<CreateConnectionDialogComponent>;
+ let loader: HarnessLoader;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[MatDialogModule,MatInputModule,MatFormFieldModule,MatSelectModule,MatButtonModule,NoopAnimationsModule,FormsModule],
+ declarations: [CreateConnectionDialogComponent],
+ providers: [{ provide: MatDialogRef, useValue: dialogRef },
+ { provide: MAT_DIALOG_DATA, useValue: {} },
+ {provide:CurrentGraphService,useValue:graphServiceMock}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CreateConnectionDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ loader = TestbedHarnessEnvironment.loader(fixture);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should close without anything returning', async() => {
+ let buttons = await loader.getAllHarnesses(MatButtonHarness);
+ let spy = spyOn(component, 'onNoClick').and.callThrough();
+ if ((await buttons[0].getText()) === 'Cancel') {
+ await buttons[0].click();
+ expect(spy).toHaveBeenCalled()
+ }
+ })
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.ts
new file mode 100644
index 0000000..7ad4339
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-connection-dialog/create-connection-dialog.component.ts
@@ -0,0 +1,42 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { from } from 'rxjs';
+import { filter, scan, share, switchMap } from 'rxjs/operators';
+import { CurrentGraphService } from '../../../services/current-graph.service';
+import { newConnection, transportType } from '../../../types/connection';
+import { node } from '../../../types/node';
+
+@Component({
+ selector: 'app-create-connection-dialog',
+ templateUrl: './create-connection-dialog.component.html',
+ styleUrls: ['./create-connection-dialog.component.sass']
+})
+export class CreateConnectionDialogComponent implements OnInit {
+
+ nodes = this.graphService.nodeOptions.pipe(
+ switchMap((nodeList) => from(nodeList).pipe(
+ filter((node)=>node.id!==this.data.id)
+ )),
+ scan((acc, curr) => [...acc, curr], [] as node[]),
+ share()
+ );
+ title: string = "";
+ newConnection: newConnection = {
+ nodeId: '',
+ connection: {
+ name: '',
+ transportType:transportType.Ethernet
+ }
+ }
+ constructor (private graphService: CurrentGraphService, public dialogRef: MatDialogRef<CreateConnectionDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: node) {
+ this.title = data.name;
+ }
+
+ ngOnInit(): void {
+ }
+
+ onNoClick() {
+ this.dialogRef.close();
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.html
new file mode 100644
index 0000000..0a8d678
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.html
@@ -0,0 +1,21 @@
+<h1 mat-dialog-title>Create New Node</h1>
+<div mat-dialog-content>
+ <mat-form-field>
+ <mat-label>Add a name</mat-label>
+ <input matInput [(ngModel)]="result.name" required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <mat-label>Add a description</mat-label>
+ <input matInput [(ngModel)]="result.description">
+ </mat-form-field>
+</div>
+<div mat-dialog-actions>
+ <button mat-button (click)="onNoClick()">Cancel</button>
+ <button mat-raised-button [mat-dialog-close]="result" color="primary" [disabled]="result.name.length===0">Ok</button>
+</div>
+<!--
+ mat-dialog-content:
+ input(name)
+ input(description)
+-->
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.spec.ts
new file mode 100644
index 0000000..176d5e6
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.spec.ts
@@ -0,0 +1,49 @@
+import { HarnessLoader } from '@angular/cdk/testing';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatButtonHarness } from '@angular/material/button/testing';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { dialogRef } from '../../../mocks/dialogRef.mock';
+
+import { CreateNewNodeDialogComponent } from './create-new-node-dialog.component';
+
+describe('CreateNewNodeDialogComponent', () => {
+ let component: CreateNewNodeDialogComponent;
+ let fixture: ComponentFixture<CreateNewNodeDialogComponent>;
+ let loader: HarnessLoader;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[MatDialogModule,MatButtonModule,MatFormFieldModule,MatInputModule,NoopAnimationsModule,FormsModule],
+ declarations: [CreateNewNodeDialogComponent],
+ providers: [{ provide: MatDialogRef, useValue: dialogRef },
+ { provide: MAT_DIALOG_DATA, useValue: {}}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CreateNewNodeDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ loader = TestbedHarnessEnvironment.loader(fixture);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should close without anything returning', async() => {
+ let buttons = await loader.getAllHarnesses(MatButtonHarness);
+ let spy = spyOn(component, 'onNoClick').and.callThrough();
+ if ((await buttons[0].getText()) === 'Cancel') {
+ await buttons[0].click();
+ expect(spy).toHaveBeenCalled()
+ }
+ })
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.ts
new file mode 100644
index 0000000..099d9ce
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/create-new-node-dialog/create-new-node-dialog.component.ts
@@ -0,0 +1,24 @@
+import { Component, OnInit } from '@angular/core';
+import { MatDialogRef } from '@angular/material/dialog';
+import { node } from '../../../types/node';
+
+@Component({
+ selector: 'app-create-new-node-dialog',
+ templateUrl: './create-new-node-dialog.component.html',
+ styleUrls: ['./create-new-node-dialog.component.sass']
+})
+export class CreateNewNodeDialogComponent implements OnInit {
+
+ result: node = {
+ name: '',
+ description:''
+ };
+ constructor(public dialogRef: MatDialogRef<CreateNewNodeDialogComponent> ) { }
+
+ ngOnInit(): void {
+ }
+
+ onNoClick() {
+ this.dialogRef.close();
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.html
new file mode 100644
index 0000000..007d2c5
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.html
@@ -0,0 +1,25 @@
+<h1 mat-dialog-title>Editing {{title}}</h1>
+<div mat-dialog-content>
+ <mat-form-field>
+ <mat-label>Add a Name</mat-label>
+ <input matInput type="text" [(ngModel)]="data.name" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <mat-label>Add a Description</mat-label>
+ <input matInput type="text" [(ngModel)]="data.description" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <mat-label>Select a Transport Type</mat-label>
+ <mat-select [(ngModel)]="data.transportType" required>
+ <mat-option *ngFor="let option of ['ETHERNET','MILSTD1553_B']" [value]="option">
+ {{option}}
+ </mat-option>
+ </mat-select>
+ </mat-form-field>
+</div>
+<div mat-dialog-actions>
+ <button mat-button (click)="onNoClick()">Cancel</button>
+ <button mat-raised-button [mat-dialog-close]="data" color="primary" [disabled]="data.name.length===0">Ok</button>
+</div>
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.spec.ts
new file mode 100644
index 0000000..9263725
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.spec.ts
@@ -0,0 +1,54 @@
+import { HarnessLoader } from '@angular/cdk/testing';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatButtonHarness } from '@angular/material/button/testing';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { dialogRef } from '../../../mocks/dialogRef.mock';
+import { connection, transportType } from '../../../types/connection';
+
+import { EditConnectionDialogComponent } from './edit-connection-dialog.component';
+
+describe('EditConnectionDialogComponent', () => {
+ let component: EditConnectionDialogComponent;
+ let fixture: ComponentFixture<EditConnectionDialogComponent>;
+ let loader: HarnessLoader;
+ let dialogData: connection = {
+ name: '',
+ transportType:transportType.Ethernet
+ }
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [MatDialogModule,MatInputModule,MatSelectModule,MatButtonModule,NoopAnimationsModule,FormsModule],
+ declarations: [EditConnectionDialogComponent],
+ providers: [{ provide: MatDialogRef, useValue: dialogRef },
+ { provide: MAT_DIALOG_DATA, useValue: dialogData}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditConnectionDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ loader = TestbedHarnessEnvironment.loader(fixture);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should close without anything returning', async() => {
+ let buttons = await loader.getAllHarnesses(MatButtonHarness);
+ let spy = spyOn(component, 'onNoClick').and.callThrough();
+ if ((await buttons[0].getText()) === 'Cancel') {
+ await buttons[0].click();
+ expect(spy).toHaveBeenCalled()
+ }
+ })
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.ts
new file mode 100644
index 0000000..de30146
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-connection-dialog/edit-connection-dialog.component.ts
@@ -0,0 +1,23 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { connection } from '../../../types/connection';
+
+@Component({
+ selector: 'app-edit-connection-dialog',
+ templateUrl: './edit-connection-dialog.component.html',
+ styleUrls: ['./edit-connection-dialog.component.sass']
+})
+export class EditConnectionDialogComponent implements OnInit {
+
+ title:string=""
+ constructor (public dialogRef: MatDialogRef<EditConnectionDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: connection) {
+ this.title = data.name;
+ }
+
+ ngOnInit(): void {
+ }
+
+ onNoClick() {
+ this.dialogRef.close();
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.html
new file mode 100644
index 0000000..e69cd4d
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.html
@@ -0,0 +1,16 @@
+<h1 mat-dialog-title>Editing {{title}}</h1>
+<div mat-dialog-content>
+ <mat-form-field>
+ <mat-label>Add a Name</mat-label>
+ <input matInput type="text" [(ngModel)]="data.name" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <mat-label>Add a Description</mat-label>
+ <input matInput type="text" [(ngModel)]="data.description" #input required>
+ </mat-form-field>
+</div>
+<div mat-dialog-actions>
+ <button mat-button (click)="onNoClick()">Cancel</button>
+ <button mat-raised-button [mat-dialog-close]="data" color="primary" [disabled]="data.name.length===0">Ok</button>
+</div>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.spec.ts
new file mode 100644
index 0000000..ee92ab4
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.spec.ts
@@ -0,0 +1,53 @@
+import { HarnessLoader } from '@angular/cdk/testing';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatButtonHarness } from '@angular/material/button/testing';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { dialogRef } from '../../../mocks/dialogRef.mock';
+import { node } from '../../../types/node';
+
+import { EditNodeDialogComponent } from './edit-node-dialog.component';
+
+describe('EditNodeDialogComponent', () => {
+ let component: EditNodeDialogComponent;
+ let fixture: ComponentFixture<EditNodeDialogComponent>;
+ let loader: HarnessLoader;
+ let dialogData: node = {
+ name:''
+ }
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[MatDialogModule,MatFormFieldModule,MatInputModule,MatButtonModule,NoopAnimationsModule,FormsModule],
+ declarations: [EditNodeDialogComponent],
+ providers: [{ provide: MatDialogRef, useValue: dialogRef },
+ { provide: MAT_DIALOG_DATA, useValue: dialogData}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditNodeDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ loader = TestbedHarnessEnvironment.loader(fixture);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should close without anything returning', async() => {
+ let buttons = await loader.getAllHarnesses(MatButtonHarness);
+ let spy = spyOn(component, 'onNoClick').and.callThrough();
+ if ((await buttons[0].getText()) === 'Cancel') {
+ await buttons[0].click();
+ expect(spy).toHaveBeenCalled()
+ }
+ })
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.ts
new file mode 100644
index 0000000..c95e99f
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/dialogs/edit-node-dialog/edit-node-dialog.component.ts
@@ -0,0 +1,23 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { node } from '../../../types/node';
+
+@Component({
+ selector: 'app-edit-node-dialog',
+ templateUrl: './edit-node-dialog.component.html',
+ styleUrls: ['./edit-node-dialog.component.sass']
+})
+export class EditNodeDialogComponent implements OnInit {
+
+ title:string=""
+ constructor (public dialogRef: MatDialogRef<EditNodeDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: node) {
+ this.title = data.name;
+ }
+
+ ngOnInit(): void {
+ }
+
+ onNoClick() {
+ this.dialogRef.close();
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/branch-selector/branch-selector.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/branch-selector/branch-selector.component.ts
index b8f534c..38bba34 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/branch-selector/branch-selector.component.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/branch-selector/branch-selector.component.ts
@@ -2,7 +2,6 @@
import { MatSelectChange } from '@angular/material/select';
import { BranchListService } from '../../../services/branch-list.service';
import { ConnectionViewRouterService } from '../../../services/connection-view-router.service';
-import { RouteStateService } from '../../../services/route-state-service.service';
@Component({
selector: 'osee-connectionview-branch-selector',
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/branch-type-selector/branch-type-selector.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/branch-type-selector/branch-type-selector.component.ts
index ba76f1c..6df5732 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/branch-type-selector/branch-type-selector.component.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/branch-type-selector/branch-type-selector.component.ts
@@ -1,7 +1,6 @@
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { Component,OnInit } from '@angular/core';
import { MatRadioChange } from '@angular/material/radio';
import { ConnectionViewRouterService } from '../../../services/connection-view-router.service';
-import { RouteStateService } from '../../../services/route-state-service.service';
@Component({
selector: 'osee-connectionview-branch-type-selector',
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.html
index 276578a..536e39b 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.html
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.html
@@ -1,5 +1,5 @@
<ng-container *ngIf="(data|async) as graphData">
- <div style="width:100vw;height:80vh">
+ <div style="width:100vw;height:80vh" (contextmenu)="openGraphDialog($event)">
<ngx-graph class="chart-container" layout="dagre"
[nodes]="graphData.nodes" [links]="graphData.edges" [update$]="update">
@@ -18,16 +18,22 @@
</ng-template>
<ng-template #nodeTemplate let-node>
- <svg:g class="node">
- <svg:rect [attr.width]="node.dimension.width" [attr.height]="node.dimension.height" [attr.fill]="node.data.color" />
+ <svg:g class="node" (contextmenu)="openNodeDialog($event,node,graphData.edges)">
+ <svg:rect [attr.width]="node.dimension.width" [attr.height]="node.dimension.height" [attr.fill]="node.data.bgColor" />
<svg:text alignment-baseline="central" [attr.x]="10" [attr.y]="node.dimension.height / 2">{{node.label}}</svg:text>
</svg:g>
</ng-template>
<ng-template #linkTemplate let-link>
- <svg:g class="edge" (click)="navigateToMessages(link.id)">
- <svg:path class="line" stroke-width="2" marker-end="url(#arrow)">
+ <svg:g class="edge" (click)="navigateToMessages(link.id.split('a')[1])" (contextmenu)="openLinkDialog($event,link,graphData.nodes)">
+ <ng-container *ngIf="link.data.dashed">
+ <svg:path class="line" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="4" marker-start="url(#arrow)">
</svg:path>
+ </ng-container>
+ <ng-container *ngIf="!link.data.dashed">
+ <svg:path class="line" stroke-width="2" marker-end="url(#arrow)" marker-start="url(#arrow)">
+ </svg:path>
+ </ng-container>
<svg:text class="edge-label" text-anchor="middle">
<textPath class="text-path" [attr.href]="'#' + link.id" [style.dominant-baseline]="link.dominantBaseline" startOffset="50%">
{{link.label}}
@@ -37,4 +43,55 @@
</ng-template>
</ngx-graph>
</div>
-</ng-container>
\ No newline at end of file
+</ng-container>
+<mat-menu #linkMenu="matMenu">
+ <ng-template matMenuContent let-data="data" let-source="source" let-target="target">
+ <button mat-menu-item (click)="navigateToMessages(data.id)"> Go to {{data.name}}</button>
+ <button mat-menu-item (click)="navigateToMessagesInNewTab(data.id)"> Go to {{data.name}} in new tab</button>
+ <ng-container *ngIf="editMode">
+ <button mat-menu-item (click)="openConnectionEditDialog(data)"> Edit {{data.name}}</button>
+ <button mat-menu-item (click)="openRemoveConnectionDialog(data,source,target)"> Remove connection {{data.name}}</button>
+ </ng-container>
+ </ng-template>
+</mat-menu>
+<mat-menu #nodeMenu="matMenu">
+ <ng-template matMenuContent let-data="data" let-sources="sources" let-targets="targets">
+ <ng-container *ngIf="editMode">
+ <button mat-menu-item (click)="openEditNodeDialog(data)">Edit {{data.name}}</button>
+ <button mat-menu-item (click)="removeNodeAndConnection(data,sources,targets)">Remove {{data.name}} & Connection</button>
+ <button mat-menu-item (click)="createConnectionToNode(data)">Create Connection To {{data.name}}</button>
+ </ng-container>
+ <ng-container *ngIf="!editMode">
+ <mat-label>
+ No Viewing Options Available for Node {{data.name}}.
+ </mat-label>
+ </ng-container>
+ </ng-template>
+</mat-menu>
+<mat-menu #graphMenu="matMenu">
+ <ng-template matMenuContent>
+ <ng-container *ngIf="editMode">
+ <button mat-menu-item (click)="createNewNode()">Create New Node</button>
+ </ng-container>
+ <ng-container *ngIf="!editMode">
+ <mat-label>
+ No Viewing Options Available.
+ </mat-label>
+ </ng-container>
+ </ng-template>
+</mat-menu>
+<div #linkMenuTrigger="matMenuTrigger" style="visibility: hidden; position: fixed;"
+[style.left]="linkPosition.x"
+[style.top]="linkPosition.y"
+[matMenuTriggerFor]="linkMenu">
+</div>
+<div #nodeMenuTrigger="matMenuTrigger" style="visibility: hidden; position: fixed;"
+[style.left]="nodePosition.x"
+[style.top]="nodePosition.y"
+[matMenuTriggerFor]="nodeMenu">
+</div>
+<div #graphMenuTrigger="matMenuTrigger" style="visibility: hidden; position: fixed;"
+[style.left]="graphMenuPosition.x"
+[style.top]="graphMenuPosition.y"
+[matMenuTriggerFor]="graphMenu">
+</div>
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.spec.ts
index 62864e9..a177003 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.spec.ts
@@ -1,22 +1,48 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatMenuModule } from '@angular/material/menu';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
+import { NgxGraphModule } from '@swimlane/ngx-graph';
+import { graphServiceMock } from '../../../mocks/CurrentGraphService.mock';
import { ConnectionViewRouterService } from '../../../services/connection-view-router.service';
+import { CurrentGraphService } from '../../../services/current-graph.service';
+import { HarnessLoader } from '@angular/cdk/testing';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
+
import { GraphComponent } from './graph.component';
+import { MatButtonHarness } from '@angular/material/button/testing';
+import { MatMenuHarness, MatMenuItemHarness } from '@angular/material/menu/testing';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { FormsModule } from '@angular/forms';
+import { MatSelectModule } from '@angular/material/select';
+import { MatInputModule } from '@angular/material/input';
+import { CommonModule } from '@angular/common';
+import { ConfirmRemovalDialogComponent } from '../../dialogs/confirm-removal-dialog/confirm-removal-dialog.component';
+import { CreateConnectionDialogComponent } from '../../dialogs/create-connection-dialog/create-connection-dialog.component';
+import { CreateNewNodeDialogComponent } from '../../dialogs/create-new-node-dialog/create-new-node-dialog.component';
+import { EditConnectionDialogComponent } from '../../dialogs/edit-connection-dialog/edit-connection-dialog.component';
+import { EditNodeDialogComponent } from '../../dialogs/edit-node-dialog/edit-node-dialog.component';
describe('GraphComponent', () => {
let component: GraphComponent;
let fixture: ComponentFixture<GraphComponent>;
+ let loader: HarnessLoader;
let router: any;
let routerService: ConnectionViewRouterService;
beforeEach(async () => {
router = jasmine.createSpyObj('Router', ['navigate', 'createUrlTree', 'serializeUrl'],{'url':new String()});
await TestBed.configureTestingModule({
- providers:[{ provide: Router, useValue: router }],
- imports:[RouterTestingModule],
- declarations: [ GraphComponent ]
+ imports:[MatDialogModule,NgxGraphModule,NoopAnimationsModule,RouterTestingModule,MatMenuModule,MatFormFieldModule,FormsModule,MatSelectModule,MatInputModule,CommonModule],
+ providers:
+ [
+ { provide: Router, useValue: router },
+ { provide: CurrentGraphService, useValue: graphServiceMock },
+ ],
+ declarations: [ GraphComponent,ConfirmRemovalDialogComponent,CreateConnectionDialogComponent,CreateNewNodeDialogComponent,EditConnectionDialogComponent,EditNodeDialogComponent ]
})
.compileComponents();
routerService=TestBed.inject(ConnectionViewRouterService)
@@ -26,7 +52,17 @@
fixture = TestBed.createComponent(GraphComponent);
component = fixture.componentInstance;
fixture.detectChanges();
+ loader = TestbedHarnessEnvironment.loader(fixture);
});
+ beforeEach(function () {
+ let window1 = spyOn(window, 'open').and.callFake((url,target,replace) => {
+ return null;
+ })
+ });
+ beforeEach(() => {
+ component.linkMenuTrigger.closeMenu();
+ component.nodeMenuTrigger.closeMenu();
+ })
it('should create', () => {
expect(component).toBeTruthy();
@@ -42,8 +78,190 @@
component.navigateToMessages("hello");
expect(router.navigate).toHaveBeenCalledWith(['', 'product line', '8', 'hello', 'messages'])
});
-
+ })
+ describe('Editing Menus', () => {
+ beforeEach(() => {
+ component.editMode = true;
+ })
+ describe('Link Menu', () => {
+ let menu: MatMenuHarness;
+ let items: MatMenuItemHarness[];
+ beforeEach(() => {
+ component.linkMenuTrigger.closeMenu();
+ component.openLinkDialog(new MouseEvent("contextmenu", { clientX: 100, clientY: 100 }), { id: '1', source: '10', target: '15', data: { name: '1' } }, [{ id: '10', label: '10' }, { id: '15', label: '15' }]);
+ expect(component.linkMenuTrigger.menuOpen).toBeTruthy();
+ })
+ describe('Editing Link Menu', () => {
+ beforeEach(async () => {
+ menu = await loader.getHarness(MatMenuHarness);
+ expect(menu).toBeDefined();
+ items = (await menu.getItems());
+ expect(items).toBeDefined();
+ expect(items.length).toEqual(4);
+ })
+ describe('Editing Functionality', () => {
+ it('should open edit connection dialog', async () => {
+ let spy = spyOn(component, 'openConnectionEditDialog').and.callThrough();
+ let item = (await menu?.getItems())[2] || items[2];
+ expect(item).toBeDefined();
+ expect(await item.getText()).toEqual('Edit 1');
+ await item.click();
+ expect(spy).toHaveBeenCalled();
+ })
+
+ it('should open remove connection dialog', async () => {
+ let spy = spyOn(component, 'openRemoveConnectionDialog').and.callThrough();
+ let item = (await menu?.getItems())[3] || items[3];
+ expect(item).toBeDefined();
+ expect(await item.getText()).toEqual('Remove connection 1');
+ await item.click();
+ expect(spy).toHaveBeenCalled();
+ })
+ })
+ describe('Navigation', () => {
+ it('should navigate to messages page', async () => {
+ let spy = spyOn(component, 'navigateToMessages').and.callThrough();
+ let item = (await menu?.getItems())[0] || items[0];
+ expect(item).toBeDefined();
+ expect(await item.getText()).toEqual('Go to 1');
+ await item.click();
+ expect(spy).toHaveBeenCalled();
+ })
+
+ it('should navigate to messages page in new tab', async () => {
+ let spy = spyOn(component, 'navigateToMessagesInNewTab').and.callThrough();
+ let item = (await menu?.getItems())[1] || items[1];
+ expect(item).toBeDefined();
+ expect(await item.getText()).toEqual('Go to 1 in new tab');
+ await item.click();
+ expect(spy).toHaveBeenCalled();
+ })
+ })
+ })
+ });
+ describe('Node Menu', () => {
+ let menu: MatMenuHarness;
+ let items: MatMenuItemHarness[];
+ beforeEach(() => {
+ component.nodeMenuTrigger.closeMenu();
+ component.linkMenuTrigger.closeMenu();
+ component.openNodeDialog(new MouseEvent("contextmenu", { clientX: 200, clientY: 200 }), {id:'1',data:{name:'first'}},[{id:'a3',source:'1',target:'2',data:{name:'a'}},{id:'a4',source:'2',target:'1',data:{name:'b'}}]);
+ expect(component.nodeMenuTrigger.menuOpen).toBeTruthy();
+ })
+ describe('Editing Node Menu', () => {
+ beforeEach(async () => {
+ (await loader.getAllHarnesses(MatMenuHarness)).forEach(async(tempMenu) => {
+ if ((await tempMenu.getItems()).length > 0) {
+ menu = tempMenu;
+ expect(menu).toBeDefined();
+ items = (await menu.getItems());
+ expect(items).toBeDefined();
+ expect(items.length).toEqual(3);
+ }
+ })
+ //menu = await loader.getHarness(MatMenuHarness);
+ })
+ describe('Editing Functionality', () => {
+ it('should open edit node dialog', async () => {
+ (await loader.getAllHarnesses(MatMenuHarness)).forEach(async(tempMenu) => {
+ if ((await tempMenu.getItems()).length > 0) {
+ menu = tempMenu;
+ expect(menu).toBeDefined();
+ items = (await menu.getItems());
+ expect(items).toBeDefined();
+ expect(items.length).toEqual(3);
+ let spy = spyOn(component, 'openEditNodeDialog').and.callThrough();
+ let item = (await menu?.getItems())[0] || items[0];
+ expect(item).toBeDefined();
+ expect(await item.getText()).toEqual('Edit first');
+ await item.click();
+ expect(spy).toHaveBeenCalled();
+ }
+ })
+ })
+
+ it('should open remove node dialog', async () => {
+ (await loader.getAllHarnesses(MatMenuHarness)).forEach(async(tempMenu) => {
+ if ((await tempMenu.getItems()).length > 0) {
+ menu = tempMenu;
+ expect(menu).toBeDefined();
+ items = (await menu.getItems());
+ expect(items).toBeDefined();
+ expect(items.length).toEqual(3);
+ let spy = spyOn(component, 'removeNodeAndConnection').and.callThrough();
+ let item = (await menu?.getItems())[1] || items[1];
+ expect(item).toBeDefined();
+ expect(await item.getText()).toEqual('Remove first & Connection');
+ await item.click();
+ expect(spy).toHaveBeenCalled();
+ }
+ })
+ })
+
+ it('should open create node dialog', async () => {
+ (await loader.getAllHarnesses(MatMenuHarness)).forEach(async(tempMenu) => {
+ if ((await tempMenu.getItems()).length > 0) {
+ menu = tempMenu;
+ expect(menu).toBeDefined();
+ items = (await menu.getItems());
+ expect(items).toBeDefined();
+ expect(items.length).toEqual(3);
+ let spy = spyOn(component, 'createConnectionToNode').and.callThrough();
+ let item = (await menu?.getItems())[2] || items[2];
+ expect(item).toBeDefined();
+ expect(await item.getText()).toEqual('Create Connection To first');
+ await item.click();
+ expect(spy).toHaveBeenCalled();
+ }
+ })
+ })
+ })
+ })
+ })
+ describe('Graph Menu', () => {
+ let menu: MatMenuHarness;
+ let items: MatMenuItemHarness[];
+ beforeEach(() => {
+ component.graphMenuTrigger.closeMenu();
+ let event = new MouseEvent("contextmenu", { clientX: 300, clientY: 300, },);
+ let el = document.createElement('button');
+ el.classList.add('panning-rect')
+ Object.defineProperty(event, 'target', {value: el, enumerable: true});
+ component.openGraphDialog(event);
+ expect(component.graphMenuTrigger.menuOpen).toBeTruthy();
+ })
+ describe('Editing Graph Menu', () => {
+ beforeEach(async () => {
+ (await loader.getAllHarnesses(MatMenuHarness)).forEach(async(tempMenu) => {
+ if ((await tempMenu.getItems()).length > 0) {
+ menu = tempMenu;
+ expect(menu).toBeDefined();
+ items = (await menu.getItems());
+ expect(items).toBeDefined();
+ expect(items.length).toEqual(1);
+ }
+ })
+ })
+ it('should open the create node dialog', async () => {
+ (await loader.getAllHarnesses(MatMenuHarness)).forEach(async(tempMenu) => {
+ if ((await tempMenu.getItems()).length > 0) {
+ menu = tempMenu;
+ expect(menu).toBeDefined();
+ items = (await menu.getItems());
+ expect(items).toBeDefined();
+ expect(items.length).toEqual(1);
+ let spy = spyOn(component, 'createNewNode').and.callThrough();
+ let item = (await menu?.getItems())[0] || items[0];
+ expect(item).toBeDefined();
+ expect(await item.getText()).toEqual('Create New Node');
+ await item.click();
+ expect(spy).toHaveBeenCalled();
+ }
+ })
+ })
+ })
+ })
+ })
})
- })
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.ts
index 50fdefb..2108982 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/components/misc/graph/graph.component.ts
@@ -1,7 +1,19 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { CurrentGraphService } from '../../../services/current-graph.service';
-import { Subject } from 'rxjs';
+import { from, of } from 'rxjs';
import { ConnectionViewRouterService } from '../../../services/connection-view-router.service';
+import { Edge, Node } from '@swimlane/ngx-graph';
+import { MatMenuTrigger } from '@angular/material/menu';
+import { MatDialog } from '@angular/material/dialog';
+import { EditConnectionDialogComponent } from '../../dialogs/edit-connection-dialog/edit-connection-dialog.component';
+import { connection, newConnection } from '../../../types/connection';
+import { filter, mergeMap, reduce, scan, switchMap, take, tap } from 'rxjs/operators';
+import { ConfirmRemovalDialogComponent } from '../../dialogs/confirm-removal-dialog/confirm-removal-dialog.component';
+import { node, nodeData } from '../../../types/node';
+import { EditNodeDialogComponent } from '../../dialogs/edit-node-dialog/edit-node-dialog.component';
+import { RemovalDialog } from '../../../types/ConfirmRemovalDialog';
+import { CreateConnectionDialogComponent } from '../../dialogs/create-connection-dialog/create-connection-dialog.component';
+import { CreateNewNodeDialogComponent } from '../../dialogs/create-new-node-dialog/create-new-node-dialog.component';
@Component({
selector: 'osee-connectionview-graph',
@@ -10,9 +22,25 @@
})
export class GraphComponent implements OnInit {
+ @Input() editMode: boolean = false;
data = this.graphService.nodes;
update = this.graphService.updated;
- constructor (private graphService: CurrentGraphService, private router: ConnectionViewRouterService) {}
+ linkPosition = {
+ x: "0",
+ y:"0"
+ }
+ nodePosition = {
+ x: "0",
+ y:"0"
+ }
+ graphMenuPosition = {
+ x: "0",
+ y:"0"
+ }
+ @ViewChild('linkMenuTrigger') linkMenuTrigger!: MatMenuTrigger;
+ @ViewChild('nodeMenuTrigger') nodeMenuTrigger!: MatMenuTrigger;
+ @ViewChild('graphMenuTrigger') graphMenuTrigger!: MatMenuTrigger;
+ constructor (private graphService: CurrentGraphService, private router: ConnectionViewRouterService, public dialog:MatDialog) {}
ngOnInit(): void {
this.graphService.update = true;
@@ -21,4 +49,173 @@
navigateToMessages(value: string) {
this.router.connection = value;
}
+
+ navigateToMessagesInNewTab(location: string) {
+ this.router.connectionInNewTab = location;
+ }
+ openLinkDialog(event:MouseEvent,value: Edge, nodes:Node[]) {
+ event.preventDefault();
+ this.linkPosition.x = event.clientX + 'px';
+ this.linkPosition.y = event.clientY + 'px';
+ //find node names based on value.data.source and value.data.target
+ let source = nodes.find((node) => node.id === value.source);
+ let target = nodes.find((node) => node.id === value.target);
+ this.linkMenuTrigger.menuData = {
+ data: value.data,
+ source: source,
+ target:target,
+ }
+ this.nodeMenuTrigger.closeMenu();
+ this.graphMenuTrigger.closeMenu();
+ this.linkMenuTrigger.openMenu();
+ }
+
+ /**
+ * Opens Edit Dialog to Edit a connection, and sends response to Api
+ * @param value connection to edit
+ */
+ openConnectionEditDialog(value: connection) {
+ let dialogRef=this.dialog.open(EditConnectionDialogComponent, {
+ data:Object.assign({},value)
+ })
+ dialogRef.afterClosed().pipe(
+ //only take first response
+ take(1),
+ //filter out non-valid responses
+ filter((dialogResponse) => dialogResponse !== undefined && dialogResponse !== null),
+ //convert object to key-value pair emissions emitted sequentially instead of all at once
+ mergeMap((arrayDialogResponse:connection) => from(Object.entries(arrayDialogResponse)).pipe(
+ //filter out key-value pairs that are unchanged on value, and maintain id property
+ filter((filteredProperties) => value[filteredProperties[0] as keyof connection] !== filteredProperties[1] || filteredProperties[0]==='id'),
+ //accumulate into an array of properties that are changed
+ reduce((acc, curr) => [...acc, curr], [] as [string, any][])
+ )),
+ //transform array of properties into Partial<connection> using Object.fromEntries()(ES2019)
+ switchMap((arrayOfProperties) => of(Object.fromEntries(arrayOfProperties) as Partial<connection>).pipe(
+ //HTTP PATCH call to update value
+ switchMap((changes)=>this.graphService.updateConnection(changes))
+ ))
+ ).subscribe();
+ }
+
+ openRemoveConnectionDialog(value: connection, source:Node, target:Node) {
+ let dialogRef = this.dialog.open(ConfirmRemovalDialogComponent, {
+ data: {
+ id: value.id,
+ name: value.name,
+ extraNames: [source.label,target.label],
+ type:'connection'
+ }
+ })
+ dialogRef.afterClosed().pipe(
+ //only take first response
+ take(1),
+ //filter out non-valid responses
+ filter((dialogResponse) => dialogResponse !== undefined && dialogResponse !== null),
+ //make sure there is a name and id, and extra names
+ filter((result) => result.name.length > 0 && result.id.length>0 && result.extraNames.length>0),
+ mergeMap((dialogResults) => from([{ node:source.id,connection:dialogResults.id }, { node:target.id,connection:dialogResults.id }]).pipe(
+ mergeMap((request)=>this.graphService.unrelateConnection(request.node,request.connection))
+ ))
+ ).subscribe();
+ }
+
+ openNodeDialog(event: MouseEvent, value: Node, edges:Edge[]) {
+ event.preventDefault();
+ this.nodePosition.x = event.clientX + 'px';
+ this.nodePosition.y = event.clientY + 'px';
+ let source = edges.filter((edge) => edge.source === value.id);
+ let target = edges.filter((edge) => edge.target === value.id);
+ this.nodeMenuTrigger.menuData = {
+ data: value.data,
+ sources: source,
+ targets:target
+ }
+ this.linkMenuTrigger.closeMenu();
+ this.graphMenuTrigger.closeMenu();
+ this.nodeMenuTrigger.openMenu();
+ }
+
+ openEditNodeDialog(value: nodeData) {
+ let dialogRef = this.dialog.open(EditNodeDialogComponent, {
+ data:Object.assign({},value)
+ })
+ dialogRef.afterClosed().pipe(
+ //only take first response
+ take(1),
+ //filter out non-valid responses
+ filter((dialogResponse) => dialogResponse !== undefined && dialogResponse !== null),
+ //convert object to key-value pair emissions emitted sequentially instead of all at once
+ mergeMap((arrayDialogResponse:node) => from(Object.entries(arrayDialogResponse)).pipe(
+ //filter out key-value pairs that are unchanged on value, and maintain id property
+ filter((filteredProperties) => value[filteredProperties[0] as keyof node] !== filteredProperties[1] || filteredProperties[0]==='id'),
+ //accumulate into an array of properties that are changed
+ reduce((acc, curr) => [...acc, curr], [] as [string, any][])
+ )),
+ //transform array of properties into Partial<node> using Object.fromEntries()(ES2019)
+ switchMap((arrayOfProperties) => of(Object.fromEntries(arrayOfProperties) as Partial<node>).pipe(
+ //HTTP PATCH call to update value
+ switchMap((results)=>this.graphService.updateNode(results))
+ ))
+ ).subscribe();
+ }
+
+ removeNodeAndConnection(value: nodeData,sources:Edge[],targets:Edge[]) {
+ let dialogRef = this.dialog.open(ConfirmRemovalDialogComponent, {
+ data: {
+ id: value.id,
+ name: value.name,
+ extraNames: [...sources.map(x=>x.label),...targets.map(x=>x.label)],
+ type:'node'
+ }
+ })
+ dialogRef.afterClosed().pipe(
+ //only take first response
+ take(1),
+ //filter out non-valid responses
+ filter((dialogResponse:RemovalDialog) => dialogResponse !== undefined && dialogResponse !== null),
+ //make sure there is a name and id
+ filter((result) => result.name.length > 0 && result.id.length > 0),
+ //delete Node api call, then unrelate connection from other node(s) using unrelate api call
+ switchMap((results)=>this.graphService.deleteNodeAndUnrelate(results.id,[...sources,...targets])) //needs testing
+ ).subscribe();
+ }
+
+ createConnectionToNode(value: nodeData) {
+ //todo open dialog to select node to connect to this node
+ let dialogRef = this.dialog.open(CreateConnectionDialogComponent, {
+ data:value
+ })
+ dialogRef.afterClosed().pipe(
+ //only take first response
+ take(1),
+ //filter out non-valid responses
+ filter((dialogResponse: newConnection) => dialogResponse !== undefined && dialogResponse !== null),
+ //HTTP Rest call to create connection(branch/nodes/nodeId/connections/type), then rest call to relate it to the associated nodes(branch/nodes/nodeId/connections/id/type)
+ switchMap((results)=>this.graphService.createNewConnection(results.connection,results.nodeId,value.id))
+ ).subscribe();
+ }
+
+ openGraphDialog(event: MouseEvent) {
+ event.stopPropagation();
+ event.preventDefault();
+ //hacky way of keeping the event to white space only instead of activating on right mouse click of other elements
+ let target = event.target as HTMLElement
+ if (target.attributes.getNamedItem('class')?.value == 'panning-rect') {
+ this.graphMenuPosition.x = event.clientX + 'px';
+ this.graphMenuPosition.y = event.clientY + 'px';
+ this.linkMenuTrigger.closeMenu();
+ this.nodeMenuTrigger.closeMenu();
+ this.graphMenuTrigger.openMenu();
+ }
+ }
+
+ createNewNode() {
+ let dialogRef = this.dialog.open(CreateNewNodeDialogComponent);
+ dialogRef.afterClosed().pipe(
+ take(1),
+ filter((dialogResponse: node) => dialogResponse !== undefined && dialogResponse !== null),
+ switchMap((results)=>this.graphService.createNewNode(results))
+ ).subscribe()
+ }
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/connection-view.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/connection-view.component.ts
index f6f4ad4..a186bc2 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/connection-view.component.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/connection-view.component.ts
@@ -1,6 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
-import { BehaviorSubject, Observable } from 'rxjs';
import { RouteStateService } from './services/route-state-service.service';
@Component({
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/connection-view.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/connection-view.module.ts
index 03dffd4..d294633 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/connection-view.module.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/connection-view.module.ts
@@ -12,17 +12,30 @@
import { MatFormFieldModule } from '@angular/material/form-field';
import { FormsModule } from '@angular/forms';
import { MatSelectModule } from '@angular/material/select';
+import { MatMenuModule } from '@angular/material/menu';
+import { EditConnectionDialogComponent } from './components/dialogs/edit-connection-dialog/edit-connection-dialog.component';
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatInputModule } from '@angular/material/input';
+import { MatButtonModule } from '@angular/material/button';
+import { ConfirmRemovalDialogComponent } from './components/dialogs/confirm-removal-dialog/confirm-removal-dialog.component';
+import { EditNodeDialogComponent } from './components/dialogs/edit-node-dialog/edit-node-dialog.component';
+import { CreateConnectionDialogComponent } from './components/dialogs/create-connection-dialog/create-connection-dialog.component';
+import { CreateNewNodeDialogComponent } from './components/dialogs/create-new-node-dialog/create-new-node-dialog.component';
@NgModule({
- declarations: [ConnectionViewComponent, BranchTypeSelectorComponent, BranchSelectorComponent, BaseComponent, GraphComponent],
+ declarations: [ConnectionViewComponent, BranchTypeSelectorComponent, BranchSelectorComponent, BaseComponent, GraphComponent, EditConnectionDialogComponent, ConfirmRemovalDialogComponent, EditNodeDialogComponent, CreateConnectionDialogComponent, CreateNewNodeDialogComponent],
imports: [
CommonModule,
ConnectionViewRoutingModule,
MatRadioModule,
+ MatDialogModule,
MatFormFieldModule,
+ MatButtonModule,
+ MatMenuModule,
FormsModule,
MatSelectModule,
+ MatInputModule,
NgxGraphModule
]
})
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mock/mock-graph-data.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mock/mock-graph-data.ts
deleted file mode 100644
index 1474483..0000000
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mock/mock-graph-data.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { mockData } from "../types/mockdata";
-
-export const data:mockData[] = [
- {
- id:'-1',
- nodes: [],
- edges:[]
- },
- {
- id: '8',
- nodes: [
- {
- id: '0',
- // dimension:
- // {
- // width: 500,
- // height:500
- // },
- label: "Basic Node",
-
- },
- {
- id: '1',
- // dimension:
- // {
- // width: 500,
- // height:500
- // },
- label: "Basic Node 2",
-
- }
- ],
- edges: [
- {
- id: 'a',
- source: '0',
- target: '1',
- label:'Ethernet Connection'
- }
- ]
- }
-]
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/CurrentGraphService.mock.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/CurrentGraphService.mock.ts
new file mode 100644
index 0000000..7fa997d
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/CurrentGraphService.mock.ts
@@ -0,0 +1,33 @@
+import { of, BehaviorSubject } from "rxjs";
+import { OSEEWriteApiResponse } from "../../shared/types/ApiWriteResponse";
+import { CurrentGraphService } from "../services/current-graph.service";
+import { connection } from '../types/connection'
+import { node } from '../types/node'
+import { response } from "./Response.mock";
+
+export const graphServiceMock: Partial<CurrentGraphService> = {
+ nodes: of({ nodes: [], edges: [] }),
+ updated: new BehaviorSubject<boolean>(true),
+ set update(value: boolean) {
+ return;
+ },
+ updateConnection(connection: Partial<connection>) {
+ return of(response);
+ },
+ unrelateConnection(nodeId: string, id: string) {
+ return of(response);
+ },
+ updateNode(node: Partial<node>) {
+ return of(response);
+ },
+ deleteNodeAndUnrelate(nodeId: string, edges: []) {
+ return of([response])
+ },
+ createNewConnection(connection: connection, sourceId: string, targetId: string) {
+ return of(response)
+ },
+ createNewNode(node: node) {
+ return of(response)
+ },
+ nodeOptions:of([])
+ }
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/EditAuthService.mock.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/EditAuthService.mock.ts
new file mode 100644
index 0000000..a61088f
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/EditAuthService.mock.ts
@@ -0,0 +1,27 @@
+import { of } from "rxjs";
+import { EditAuthService } from "../../shared/services/edit-auth-service.service";
+import { branchApplicability } from "../../shared/types/branch.applic";
+
+export const editAuthServiceMock: Partial<EditAuthService> = {
+ get branchEditability() {
+ return of<branchApplicability>({
+ associatedArtifactId: '-1',
+ branch: {
+ id: '-1',
+ viewId: '-1',
+ idIntValue: -1,
+ name: '',
+ },
+ editable: false,
+ features: [],
+ groups: [],
+ parentBranch: {
+ id: '-1',
+ viewId: '-1',
+ idIntValue: -1,
+ name: '',
+ },
+ views: [],
+ })
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/Response.mock.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/Response.mock.ts
new file mode 100644
index 0000000..27da643
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/Response.mock.ts
@@ -0,0 +1,20 @@
+import { OSEEWriteApiResponse } from "../../shared/types/ApiWriteResponse";
+
+export const response: OSEEWriteApiResponse = {
+ empty: true,
+ errorCount: 0,
+ errors: false,
+ failed: false,
+ ids: [],
+ infoCount: 0,
+ numErrors: 0,
+ numErrorsViaSearch: 0,
+ numWarnings: 0,
+ numWarningsViaSearch: 0,
+ results: [],
+ success: true,
+ tables: [],
+ title: '',
+ txId: '',
+ warningCount:0
+ }
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/dialogRef.mock.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/dialogRef.mock.ts
new file mode 100644
index 0000000..1b7d390
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/mocks/dialogRef.mock.ts
@@ -0,0 +1,5 @@
+export const dialogRef = {
+ close() {
+
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/connection-view-router.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/connection-view-router.service.ts
index 14a544f..3013289 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/connection-view-router.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/connection-view-router.service.ts
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
-import { ActivatedRoute, Router } from '@angular/router';
+import { Router } from '@angular/router';
import { RouteStateService } from './route-state-service.service';
@Injectable({
@@ -42,4 +42,10 @@
let baseUrl = this.router.url.split("connections")[0];
this.router.navigate([baseUrl,this.routerState.type.getValue(),this.routerState.id.getValue(),value,"messages"])
}
+
+ set connectionInNewTab(value: string) {
+ let baseUrl = this.router.url.split("connections")[0];
+ let url = this.router.serializeUrl(this.router.createUrlTree([baseUrl,this.routerState.type.getValue(),this.routerState.id.getValue(),value,"messages"]))
+ window.open(url, '_blank');
+ }
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/connection.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/connection.service.spec.ts
new file mode 100644
index 0000000..8f41dad
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/connection.service.spec.ts
@@ -0,0 +1,111 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+import { apiURL } from 'src/environments/environment';
+import { transportType } from '../types/connection';
+
+import { ConnectionService } from './connection.service';
+
+describe('ConnectionService', () => {
+ let service: ConnectionService;
+ let httpTestingController: HttpTestingController;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule]
+ });
+ service = TestBed.inject(ConnectionService);
+ httpTestingController = TestBed.inject(HttpTestingController);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ describe('Core Functionality', () => {
+
+ describe('Fetching data', () => {
+
+ it('should get all connections', () => {
+ service.getConnections('10').subscribe();
+ const req = httpTestingController.expectOne(apiURL+'/mim/branch/'+10+'/connections/');
+ expect(req.request.method).toEqual('GET');
+ req.flush([]);
+ httpTestingController.verify();
+ })
+
+ it('should get a connection', () => {
+ service.getConnection('10','10').subscribe();
+ const req = httpTestingController.expectOne(apiURL+'/mim/branch/'+10+'/connections/'+10);
+ expect(req.request.method).toEqual('GET');
+ req.flush({});
+ httpTestingController.verify();
+ })
+ })
+ describe('Adding data', () => {
+
+ it('should add a connection', () => {
+ service.addConnection('10', {}).subscribe();
+ const req = httpTestingController.expectOne(apiURL+'/mim/branch/'+10+'/connections/');
+ expect(req.request.method).toEqual('POST');
+ req.flush({});
+ httpTestingController.verify();
+ })
+
+ it('should create a valid connection', () => {
+ service.createConnection('10','10','primary', {id:'',name:'',description:'',transportType:transportType.Ethernet}).subscribe();
+ const req = httpTestingController.expectOne(apiURL+'/mim/branch/'+10+'/nodes/'+10+'/connections/'+'primary');
+ expect(req.request.method).toEqual('POST');
+ req.flush({});
+ httpTestingController.verify();
+ })
+ })
+
+ describe('Modifying data', () => {
+
+ it('should replace connection', () => {
+ service.replaceConnection('10', {}).subscribe();
+ const req = httpTestingController.expectOne(apiURL+'/mim/branch/'+10+'/connections/');
+ expect(req.request.method).toEqual('PUT');
+ req.flush({});
+ httpTestingController.verify();
+ })
+
+ it('should update connection', () => {
+ service.updateConnection('10', {id:'',name:'',description:'',transportType:transportType.Ethernet}).subscribe();
+ const req = httpTestingController.expectOne(apiURL+'/mim/branch/'+10+'/connections/');
+ expect(req.request.method).toEqual('PATCH');
+ req.flush({});
+ httpTestingController.verify();
+ })
+ })
+
+ describe('Removing data', () => {
+ it('should delete a connection', () => {
+ service.deleteConnection('10','10').subscribe();
+ const req = httpTestingController.expectOne(apiURL+'/mim/branch/'+10+'/connections/'+10);
+ expect(req.request.method).toEqual('DELETE');
+ req.flush({});
+ httpTestingController.verify();
+ })
+ })
+
+ describe('Relationship modification', () => {
+
+ it('should relate to a new node', () => {
+ service.relateConnection('10','10','primary','10', {id:'',name:'',description:'',transportType:transportType.Ethernet}).subscribe();
+ const req = httpTestingController.expectOne(apiURL+'/mim/branch/'+10+'/nodes/'+10+'/connections/'+10+'/primary');
+ expect(req.request.method).toEqual('PATCH');
+ req.flush({});
+ httpTestingController.verify();
+ })
+
+ it('should un-relate from node', () => {
+ service.unrelateConnection('10', '10', '10').subscribe();
+ const req = httpTestingController.expectOne(apiURL+'/mim/branch/'+10+'/nodes/'+10+'/connections/'+10);
+ expect(req.request.method).toEqual('DELETE');
+ req.flush({});
+ httpTestingController.verify();
+ })
+ })
+ })
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/connection.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/connection.service.ts
new file mode 100644
index 0000000..9f6a0a1
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/connection.service.ts
@@ -0,0 +1,50 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { apiURL } from 'src/environments/environment';
+import { OSEEWriteApiResponse } from '../../shared/types/ApiWriteResponse';
+import { connection } from '../types/connection';
+
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ConnectionService {
+
+ constructor (private http: HttpClient) { }
+
+ getConnections(branchId: string) {
+ return this.http.get<connection[]>(apiURL + '/mim/branch/' + branchId + '/connections/');
+ }
+
+ addConnection(branchId: string, body: any) {
+ return this.http.post<OSEEWriteApiResponse>(apiURL + '/mim/branch/' + branchId + '/connections/', body);
+ }
+
+ replaceConnection(branchId: string, body: any) {
+ return this.http.put<OSEEWriteApiResponse>(apiURL + '/mim/branch/' + branchId + '/connections/', body);
+ }
+
+ updateConnection(branchId: string, body: Partial<connection>) {
+ return this.http.patch<OSEEWriteApiResponse>(apiURL + '/mim/branch/' + branchId + '/connections/', body);
+ }
+
+ getConnection(branchId: string,connectionId:string) {;
+ return this.http.get<connection>(apiURL + '/mim/branch/' + branchId + '/connections/' + connectionId);
+ }
+
+ deleteConnection(branchId: string,connectionId:string) {
+ return this.http.delete<OSEEWriteApiResponse>(apiURL + '/mim/branch/' + branchId + '/connections/' + connectionId);
+ }
+
+ createConnection(branchId: string,nodeId:string,type:string, body: connection) {
+ return this.http.post<OSEEWriteApiResponse>(apiURL + '/mim/branch/' + branchId + '/nodes/' + nodeId + '/connections/' + type, body);
+ }
+
+ relateConnection(branchId: string,nodeId:string,type:string,connectionId:string, body: connection) {
+ return this.http.patch<OSEEWriteApiResponse>(apiURL + '/mim/branch/' + branchId + '/nodes/' + nodeId + '/connections/' + connectionId +"/"+ type, body);
+ }
+
+ unrelateConnection(branchId: string,nodeId:string,id:string) {
+ return this.http.delete<OSEEWriteApiResponse>(apiURL + '/mim/branch/' + branchId + '/nodes/' + nodeId + '/connections/' + id);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/current-graph.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/current-graph.service.spec.ts
index 65d4c6e..93a33aa 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/current-graph.service.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/current-graph.service.spec.ts
@@ -1,16 +1,142 @@
import { TestBed } from '@angular/core/testing';
+import { of, } from 'rxjs';
+import { filter } from 'rxjs/operators';
+import { TestScheduler } from 'rxjs/testing';
+import { response } from '../mocks/Response.mock';
+import { connection, transportType } from '../types/connection';
+import { node } from '../types/node';
+import { ConnectionService } from './connection.service';
import { CurrentGraphService } from './current-graph.service';
+import { GraphService } from './graph.service';
+import { NodeService } from './node.service';
+import { RouteStateService } from './route-state-service.service';
describe('CurrentGraphService', () => {
let service: CurrentGraphService;
+ let scheduler: TestScheduler;
+ let graphService: Partial<GraphService> = {
+ getNodes(id:string) {
+ return of({nodes:[{id:'1',name:'1'},{id:'2',name:'2'}],edges:[{id:'1234',source:'1',target:'2'}]})
+ },
+ }
+ let nodeService: Partial<NodeService> = {
+ getNodes(branchId: string) {
+ return of([])
+ },
+ patchNode(branchId: string, body: Partial<node>) {
+ return of(response);
+ },
+ deleteNode(branchId: string, nodeId: string) {
+ return of(response);
+ },
+ createNode(branchId: string, body: node) {
+ return of(response)
+ }
+ }
+ let connectionService: Partial<ConnectionService> = {
+ updateConnection(branchId: string, body: Partial<connection>) {
+ return of(response);
+ },
+ unrelateConnection(branchId: string, nodeId: string, id: string) {
+ return of(response);
+ },
+ createConnection(branchId: string, nodeId: string, id: string) {
+ return of(response);
+ },
+ relateConnection(branchId: string, nodeId: string, id: string) {
+ return of(response);
+ }
+ }
+ let routeState: RouteStateService;
beforeEach(() => {
- TestBed.configureTestingModule({});
+ TestBed.configureTestingModule({
+ providers: [{ provide: GraphService, useValue: graphService },
+ { provide: NodeService, useValue: nodeService },
+ {provide:ConnectionService,useValue:connectionService}]
+ });
service = TestBed.inject(CurrentGraphService);
+ routeState = TestBed.inject(RouteStateService)
});
+ beforeEach(() => scheduler = new TestScheduler((actual, expected) => {
+ expect(actual).toEqual(expected);
+ }));
+
it('should be created', () => {
expect(service).toBeTruthy();
});
+
+ it('should return a response when updating connection', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: response };
+ const expectedMarble = '(a|)'
+ routeState.branchId='10'
+ scheduler.expectObservable(service.updateConnection({})).toBe(expectedMarble, expectedfilterValues);
+ })
+ })
+
+ it('should return a response when unrelating connection', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: response };
+ const expectedMarble = '(a|)'
+ routeState.branchId='10'
+ scheduler.expectObservable(service.unrelateConnection('10','10')).toBe(expectedMarble, expectedfilterValues);
+ })
+ })
+
+ it('should return a response when updating a node', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: response };
+ const expectedMarble = '(a|)'
+ routeState.branchId='10'
+ scheduler.expectObservable(service.updateNode({})).toBe(expectedMarble, expectedfilterValues);
+ })
+ })
+
+ it('should return a response when deleting a node and unrelating', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: [response,response,response] };
+ const expectedMarble = '(a|)'
+ routeState.branchId='10'
+ scheduler.expectObservable(service.deleteNodeAndUnrelate('10', [{id:'20',source:'15',target:'10'},{id:'20',source:'10',target:'15'}])).toBe(expectedMarble, expectedfilterValues);
+ })
+ })
+
+ it('should return a response when creating a connection', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: response };
+ const expectedMarble = '(a|)'
+ routeState.branchId='10'
+ scheduler.expectObservable(service.createNewConnection({name:'connection',transportType:transportType.Ethernet},'10','15')).toBe(expectedMarble, expectedfilterValues);
+ })
+ })
+
+ it('should return a response when creating a node', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: response };
+ const expectedMarble = '(a|)'
+ routeState.branchId='10'
+ scheduler.expectObservable(service.createNewNode({name:'node'})).toBe(expectedMarble, expectedfilterValues);
+ })
+ })
+
+ it('should fetch empty array of nodes and edges', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: {nodes:[{id:'1',name:'1'},{id:'2',name:'2'}],edges:[{id:'a1234',source:'1',target:'2'}]} };
+ const expectedMarble = 'a'
+ routeState.branchId='10'
+ scheduler.expectObservable(service.nodes).toBe(expectedMarble, expectedfilterValues);
+ })
+ })
+
+ it('should fetch empty array of nodes', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: [] };
+ const expectedMarble = 'a'
+ routeState.branchId='10'
+ scheduler.expectObservable(service.nodeOptions).toBe(expectedMarble, expectedfilterValues);
+ })
+ })
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/current-graph.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/current-graph.service.ts
index 4eeef23..9e2fc11 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/current-graph.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/current-graph.service.ts
@@ -1,8 +1,14 @@
import { Injectable } from '@angular/core';
-import { Subject } from 'rxjs';
-import { filter, share, switchMap } from 'rxjs/operators';
+import { Node,Edge } from '@swimlane/ngx-graph';
+import { combineLatest, Observable, Subject } from 'rxjs';
+import { filter, map, repeatWhen, share, switchMap, take, tap } from 'rxjs/operators';
+import { ConnectionService } from './connection.service';
import { GraphService } from './graph.service';
+import { NodeService } from './node.service';
import { RouteStateService } from './route-state-service.service';
+import { connection } from '../types/connection'
+import { node } from '../types/node'
+import { OSEEWriteApiResponse } from '../../shared/types/ApiWriteResponse';
@Injectable({
providedIn: 'root'
@@ -13,11 +19,21 @@
share(),
filter((val)=>val!=="" && val!=='-1'),
switchMap((val) => this.graphService.getNodes(val).pipe(
+ map((split) => this.transform(split)),
+ repeatWhen(_=>this.updated),
share()
)),
)
+ private _nodeOptions = this.routeStateService.id.pipe(
+ share(),
+ filter((val) => val !== "" && val !== '-1'),
+ switchMap((val) => this.nodeService.getNodes(val).pipe(
+ repeatWhen(_ => this.updated),
+ share()
+ ))
+ )
private _update = new Subject<boolean>();
- constructor (private graphService: GraphService, private routeStateService: RouteStateService) { }
+ constructor (private graphService: GraphService,private nodeService:NodeService, private connectionService: ConnectionService, private routeStateService: RouteStateService) { }
get nodes() {
return this._nodes;
@@ -30,4 +46,102 @@
set update(value: boolean) {
this._update.next(true);
}
+
+ get nodeOptions() {
+ return this._nodeOptions;
+ }
+
+ updateConnection(connection: Partial<connection>) {
+ return this.connectionService.updateConnection(this.routeStateService.id.getValue(), connection).pipe(
+ tap((value) => {
+ if (!value.errors) {
+ this.update = true;
+ }
+ })
+ )
+ }
+
+ unrelateConnection(nodeId:string,id:string) {
+ return this.connectionService.unrelateConnection(this.routeStateService.id.getValue(),nodeId,id).pipe(
+ tap((value) => {
+ if (!value.errors) {
+ this.update = true;
+ }
+ })
+ )
+ }
+
+ updateNode(node: Partial<node>) {
+ return this.nodeService.patchNode(this.routeStateService.id.getValue(),node).pipe(
+ tap((value) => {
+ if (!value.errors) {
+ this.update = true;
+ }
+ })
+ )
+ }
+ deleteNode(nodeId: string) {
+ return this.nodeService.deleteNode(this.routeStateService.id.getValue(), nodeId).pipe(
+ tap((value) => {
+ if (!value.errors) {
+ this.update = true;
+ }
+ })
+ )
+ }
+
+ deleteNodeAndUnrelate(nodeId: string, edges: Edge[]) {
+ //find all ids in edge array where nodeId !== id
+ let relatedResponses: Observable<OSEEWriteApiResponse>[] = [];
+ edges.forEach((edge) => {
+ if (edge.source !== nodeId && edge.id !== undefined && edge.target === nodeId) {
+ //make unrelate observables for each id(source)
+ relatedResponses.push(this.unrelateConnection(edge.source, edge.id.replace('a','')));
+ }
+ if (edge.target !== nodeId && edge.id !== undefined && edge.source === nodeId) {
+ //make unrelate observables for each id(target)
+ relatedResponses.push(this.unrelateConnection(edge.target, edge.id.replace('a','')));
+ }
+ })
+ //return combineLatest with delete node
+ return combineLatest([...relatedResponses, this.deleteNode(nodeId)]);
+ }
+
+ createNewConnection(connection:connection,sourceId:string,targetId:string) {
+ return this.connectionService.createConnection(this.routeStateService.id.getValue(), sourceId, 'primary', connection).pipe(
+ take(1),
+ switchMap((val) => this.connectionService.relateConnection(this.routeStateService.id.getValue(), targetId, 'secondary', val.ids[0], connection).pipe(
+ tap((value) => {
+ if (!value.errors) {
+ this.update = true;
+ }
+ })
+ ))
+ )
+ }
+
+ createNewNode(node: node) {
+ return this.nodeService.createNode(this.routeStateService.id.getValue(), node).pipe(
+ tap((value) => {
+ if (!value.errors) {
+ this.update = true;
+ }
+ })
+ );
+ }
+ /**
+ * Changes edges to have an id containing a+id
+ * @param apiResponse api response containing nodes and edges
+ * @returns transformation of api response
+ */
+ private transform(apiResponse: { nodes: Node[], edges: Edge[] }) {
+ let returnObj: { nodes: Node[], edges: Edge[] }={nodes:[],edges:[]};
+ apiResponse.nodes.forEach((node) => {
+ returnObj.nodes.push({ ...node, id: node.id.toString() })
+ });
+ apiResponse.edges.forEach((edge) => {
+ returnObj.edges.push({ ...edge, id: 'a'+edge?.id?.toString() })
+ })
+ return returnObj;
+ }
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/graph.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/graph.service.spec.ts
index 3aebd00..10915ea 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/graph.service.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/graph.service.spec.ts
@@ -1,16 +1,30 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
+import { apiURL } from 'src/environments/environment';
import { GraphService } from './graph.service';
describe('GraphService', () => {
let service: GraphService;
+ let httpTestingController: HttpTestingController;
beforeEach(() => {
- TestBed.configureTestingModule({});
+ TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule]
+ });
service = TestBed.inject(GraphService);
+ httpTestingController = TestBed.inject(HttpTestingController);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
+
+ it('should call /mim/branch/10/graph', () => {
+ service.getNodes('10').subscribe();
+ const req = httpTestingController.expectOne(apiURL + '/mim/branch/10/graph');
+ expect(req.request.method).toEqual('GET');
+ req.flush({ nodes: [], edges: [] });
+ httpTestingController.verify();
+ })
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/graph.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/graph.service.ts
index 6d7620d..57b0575 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/graph.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/graph.service.ts
@@ -1,18 +1,16 @@
+import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
-import { from, of } from 'rxjs';
-import { filter, share } from 'rxjs/operators';
-import { data } from '../mock/mock-graph-data'
+import { Node,Edge } from '@swimlane/ngx-graph';
+import { apiURL } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class GraphService {
- constructor () { }
+ constructor (private http: HttpClient) { }
getNodes(id: string) {
- return from(data).pipe(
- filter((val) => val.id === id),
- )
+ return this.http.get<{nodes:Node[],edges:Edge[]}>(apiURL+'/mim/branch/'+id+"/graph")
}
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/node.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/node.service.spec.ts
new file mode 100644
index 0000000..e95b4b2
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/node.service.spec.ts
@@ -0,0 +1,83 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+import { apiURL } from 'src/environments/environment';
+
+import { NodeService } from './node.service';
+
+describe('NodeService', () => {
+ let service: NodeService;
+ let httpTestingController:HttpTestingController
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule]
+ });
+ service = TestBed.inject(NodeService);
+ httpTestingController = TestBed.inject(HttpTestingController);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ describe('Core Functionality', () => {
+
+ describe('Fetching data', () => {
+
+ it('should get all nodes', () => {
+ service.getNodes('10').subscribe();
+ const req = httpTestingController.expectOne(apiURL + '/mim/branch/' + 10 + '/nodes/');
+ expect(req.request.method).toEqual('GET');
+ req.flush([]);
+ httpTestingController.verify();
+ })
+
+ it('should get a node', () => {
+ service.getNode('10', '10').subscribe();
+ const req = httpTestingController.expectOne(apiURL + '/mim/branch/' + 10 + '/nodes/' + 10);
+ expect(req.request.method).toEqual('GET');
+ req.flush({});
+ httpTestingController.verify();
+ })
+ })
+ describe('Adding data', () => {
+
+ it('should add a node', () => {
+ service.createNode('10', {id:'',name:'',description:''}).subscribe();
+ const req = httpTestingController.expectOne(apiURL + '/mim/branch/' + 10 + '/nodes/');
+ expect(req.request.method).toEqual('POST');
+ req.flush({});
+ httpTestingController.verify();
+ })
+ })
+
+ describe('Modifying data', () => {
+
+ it('should replace node', () => {
+ service.replaceNode('10', {id:'',name:'',description:''}).subscribe();
+ const req = httpTestingController.expectOne(apiURL + '/mim/branch/' + 10 + '/nodes/');
+ expect(req.request.method).toEqual('PUT');
+ req.flush({});
+ httpTestingController.verify();
+ })
+
+ it('should update node', () => {
+ service.patchNode('10', {}).subscribe();
+ const req = httpTestingController.expectOne(apiURL + '/mim/branch/' + 10 + '/nodes/');
+ expect(req.request.method).toEqual('PATCH');
+ req.flush({});
+ httpTestingController.verify();
+ })
+ })
+
+ describe('Removing data', () => {
+ it('should delete a node', () => {
+ service.deleteNode('10', '10').subscribe();
+ const req = httpTestingController.expectOne(apiURL + '/mim/branch/' + 10 + '/nodes/' + 10);
+ expect(req.request.method).toEqual('DELETE');
+ req.flush({});
+ httpTestingController.verify();
+ })
+ })
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/node.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/node.service.ts
new file mode 100644
index 0000000..4666b99
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/services/node.service.ts
@@ -0,0 +1,37 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { apiURL } from 'src/environments/environment';
+import { OSEEWriteApiResponse } from '../../shared/types/ApiWriteResponse';
+import { node } from '../types/node';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class NodeService {
+
+ constructor (private http: HttpClient) { }
+
+ getNodes(branchId: string) {
+ return this.http.get<node[]>(apiURL + '/mim/branch/' + branchId + '/nodes/');
+ }
+
+ createNode(branchId: string,body:node) {
+ return this.http.post<OSEEWriteApiResponse>(apiURL + '/mim/branch/' + branchId + '/nodes/', body);
+ }
+
+ replaceNode(branchId: string,body:node) {
+ return this.http.put<OSEEWriteApiResponse>(apiURL + '/mim/branch/' + branchId + '/nodes/', body);
+ }
+
+ patchNode(branchId: string,body:Partial<node>) {
+ return this.http.patch<OSEEWriteApiResponse>(apiURL + '/mim/branch/' + branchId + '/nodes/', body);
+ }
+
+ getNode(branchId: string,nodeId:string) {
+ return this.http.get<node>(apiURL + '/mim/branch/' + branchId + '/nodes/'+nodeId);
+ }
+
+ deleteNode(branchId: string,nodeId:string) {
+ return this.http.delete<OSEEWriteApiResponse>(apiURL + '/mim/branch/' + branchId + '/nodes/'+nodeId);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/testing/MockComponents/Graph.mock.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/testing/MockComponents/Graph.mock.ts
index 17c6bc2..757024a 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/testing/MockComponents/Graph.mock.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/testing/MockComponents/Graph.mock.ts
@@ -1,7 +1,9 @@
-import { Component } from "@angular/core";
+import { Component, Input } from "@angular/core";
@Component({
selector: 'osee-connectionview-graph',
template:'<div>Dummy</div>'
})
- export class GraphDummy{}
\ No newline at end of file
+export class GraphDummy{
+ @Input() editMode: boolean = false;
+ }
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/ConfirmRemovalDialog.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/ConfirmRemovalDialog.d.ts
new file mode 100644
index 0000000..4dac5eb
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/ConfirmRemovalDialog.d.ts
@@ -0,0 +1,6 @@
+export interface RemovalDialog {
+ id: string,
+ name: string,
+ extraNames: [],
+ type:string
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/connection.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/connection.ts
new file mode 100644
index 0000000..bd2b6d5
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/connection.ts
@@ -0,0 +1,16 @@
+export interface connection {
+ id?: string,
+ name: string,
+ description?: string,
+ transportType: transportType
+}
+
+export enum transportType {
+ Ethernet = "ETHERNET",
+ MILSTD1553 ="MILSTD1553_B"
+}
+
+export interface newConnection {
+ connection: connection,
+ nodeId:string
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/mockdata.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/mockdata.d.ts
deleted file mode 100644
index 83ce6e1..0000000
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/mockdata.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { Edge, Node } from '@swimlane/ngx-graph/lib/models'
-export interface mockData {
- id:string,
- nodes: Node[],
- edges:Edge[]
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/node.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/node.d.ts
new file mode 100644
index 0000000..f44861b
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/connection-view/types/node.d.ts
@@ -0,0 +1,12 @@
+export interface nodeData {
+ id: string,
+ name: string,
+ description?:string
+ bgColor:string
+}
+
+export interface node {
+ id?: string,
+ name: string,
+ description?:string
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.spec.ts
index d0a30ce..6f17404 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.spec.ts
@@ -43,9 +43,10 @@
uiService.BranchIdString = '8';
uiService.messageIdString = '10';
uiService.subMessageIdString = '20';
+ uiService.connectionIdString = '10';
component.updateStructure('description', 'v2');
tick(500);
- const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + "8" + "/messages/" + '10' + "/submessages/"+ '20'+"/structures");
+ const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + "8" + "/connections/"+"10"+"/messages/" + '10' + "/submessages/"+ '20'+"/structures");
expect(req.request.method).toEqual('PATCH');
}));
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.ts
index c1d6236..8afdcbc 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.ts
@@ -44,7 +44,9 @@
this.dataSource.data = this.data;
}
ngOnChanges(changes: SimpleChanges): void {
- this.dataSource.data = this.data;
+ if (Array.isArray(this.data)) {
+ this.dataSource.data = this.data;
+ }
if (this.filter !== "") {
this.dataSource.filter = this.filter.replace('element: ', '');
this.filter = this.filter.replace('element: ', "");
@@ -55,7 +57,9 @@
}
ngOnInit(): void {
- this.dataSource.data = this.data;
+ if (Array.isArray(this.data)) {
+ this.dataSource.data = this.data;
+ }
if (this.filter !== "") {
this.dataSource.filter = this.filter.replace('element: ','');
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.ts
index ac56c03..1809d36 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.ts
@@ -119,6 +119,7 @@
this.structureService.branchId = values.get('branchId') || '';
this.structureService.messageId = values.get('messageId') || '';
this.structureService.subMessageId = values.get('subMessageId') || '';
+ this.structureService.connection = values.get('connection') || '';
});
//@todo: remove when user preferences are available on backend
let branchStorage = JSON.parse(
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.spec.ts
index bba81c0..fd6c55c 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.spec.ts
@@ -41,8 +41,9 @@
service.filter = "0";
service.messageId = "1";
service.subMessageId = "2";
+ service.connection="3"
tick(500);
- const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + 0 + "/messages/" + 1 + "/submessages/" + 2 + "/structures/filter/" + 0);
+ const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + 0 + "/connections/"+"3"+"/messages/" + 1 + "/submessages/" + 2 + "/structures/filter/" + 0);
expect(req.request.method).toEqual('GET');
req.flush(testData);
httpTestingController.verify();
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.ts
index 7111530..264a1df 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.ts
@@ -14,7 +14,7 @@
})
export class CurrentStateService {
- private _structures = combineLatest(this.ui.filter, this.ui.BranchId, this.ui.messageId, this.ui.subMessageId).pipe(
+ private _structures = combineLatest(this.ui.filter, this.ui.BranchId, this.ui.messageId, this.ui.subMessageId,this.ui.connectionId).pipe(
share(),
debounceTime(500),
distinctUntilChanged(),
@@ -71,13 +71,21 @@
this.ui.subMessageIdString = value;
}
+ set connection(id: string) {
+ this.ui.connectionIdString = id;
+ }
+
+ get connectionId() {
+ return this.ui.connectionId;
+ }
+
private get structureObservable(){
- return this.messages.getMessages(this.BranchId.getValue()).pipe(
+ return this.messages.getMessages(this.BranchId.getValue(),this.connectionId.getValue()).pipe(
mergeMap(messages => from(messages).pipe(
mergeMap(message => of(message?.subMessages).pipe(
mergeMap(submessage => from(submessage).pipe(
distinct((x) => { return x.id }),
- mergeMap((submessage) => this.structure.getFilteredStructures("", this.BranchId.getValue(), message?.id, submessage?.id).pipe(
+ mergeMap((submessage) => this.structure.getFilteredStructures("", this.BranchId.getValue(), message?.id, submessage?.id,this.connectionId.getValue()).pipe(
mergeMap(structures => from(structures).pipe(
distinct((structure)=>{return structure.id})
))
@@ -107,7 +115,7 @@
}
createStructure(body:Partial<structure>) {
- return this.structure.createStructure(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue()).pipe(
+ return this.structure.createStructure(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(),this.connectionId.getValue()).pipe(
tap(() => {
this.ui.updateMessages = true;
})
@@ -115,14 +123,14 @@
}
relateStructure(structureId:string) {
- return this.structure.relateStructure(this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId).pipe(
+ return this.structure.relateStructure(this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId,this.connectionId.getValue()).pipe(
tap(() => {
this.ui.updateMessages = true;
})
);
}
partialUpdateStructure(body:Partial<structure>) {
- return this.structure.partialUpdateStructure(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue()).pipe(
+ return this.structure.partialUpdateStructure(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(),this.connectionId.getValue()).pipe(
tap(() => {
this.ui.updateMessages = true;
})
@@ -130,7 +138,7 @@
}
partialUpdateElement(body: Partial<element>, structureId: string) {
- return this.elements.partialUpdateElement(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId).pipe(
+ return this.elements.partialUpdateElement(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId,this.connectionId.getValue()).pipe(
tap(() => {
this.ui.updateMessages = true;
})
@@ -138,20 +146,20 @@
}
createNewElement(body: Partial<element>, structureId:string, typeId: string) {
- return this.elements.createNewElement(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId).pipe(
+ return this.elements.createNewElement(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId,this.connectionId.getValue()).pipe(
switchMap((val) => this.changeElementPlatformType(structureId, val.ids[0], typeId)),
first()
)
}
relateElement(structureId: string, elementId: string) {
- return this.elements.relateElement(this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId,elementId).pipe(
+ return this.elements.relateElement(this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId,elementId,this.connectionId.getValue()).pipe(
tap(() => {
this.ui.updateMessages = true;
})
)
}
changeElementPlatformType(structureId:string,elementId:string,typeId:string) {
- return this.elements.relateElementToPlatformType(this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId, elementId, typeId).pipe(
+ return this.elements.relateElementToPlatformType(this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId, elementId, typeId,this.connectionId.getValue()).pipe(
tap(() => {
this.ui.updateMessages = true;
})
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/element.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/element.service.ts
index b2b6edf..dc32f12 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/element.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/element.service.ts
@@ -12,18 +12,18 @@
constructor (private http: HttpClient) { }
- partialUpdateElement(body: Partial<element>, branchId: string, messageId: string,subMessageId: string, structureId:string):Observable<StructureApiResponse> {
- return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements", body);
+ partialUpdateElement(body: Partial<element>, branchId: string, messageId: string,subMessageId: string, structureId:string,connectionId:string):Observable<StructureApiResponse> {
+ return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements", body);
}
- createNewElement(body: Partial<element>, branchId: string, messageId: string,subMessageId: string, structureId:string):Observable<StructureApiResponse> {
- return this.http.post<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements", body);
+ createNewElement(body: Partial<element>, branchId: string, messageId: string,subMessageId: string, structureId:string,connectionId:string):Observable<StructureApiResponse> {
+ return this.http.post<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements", body);
}
- relateElement(branchId: string,messageId: string, subMessageId: string, structureId: string, elementId: string) {
- return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements/"+elementId, null);
+ relateElement(branchId: string,messageId: string, subMessageId: string, structureId: string, elementId: string,connectionId:string) {
+ return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements/"+elementId, null);
}
- relateElementToPlatformType(branchId: string, messageId: string,subMessageId: string, structureId:string,elementId:string, typeId:string):Observable<StructureApiResponse> {
- return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements/"+elementId+"/setType/"+typeId, null);
+ relateElementToPlatformType(branchId: string, messageId: string,subMessageId: string, structureId:string,elementId:string, typeId:string,connectionId:string):Observable<StructureApiResponse> {
+ return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements/"+elementId+"/setType/"+typeId, null);
}
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/messages.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/messages.service.ts
index eabb057..a0d6169 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/messages.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/messages.service.ts
@@ -16,7 +16,7 @@
* @param branchId branch to look for messages on
* @returns Observable of an array of messages matching filter condition
*/
- getMessages(branchId: string):Observable<message[]> {
- return this.http.get<message[]>(apiURL + "/mim/branch/" + branchId + "/messages");
+ getMessages(branchId: string,connectionId:string):Observable<message[]> {
+ return this.http.get<message[]>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages");
}
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.spec.ts
index 46aa829..74737b6 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.spec.ts
@@ -41,8 +41,8 @@
interfaceStructureCategory: '1',
interfaceTaskFileType:1
}]
- service.getFilteredStructures('0', '0', '1', '2').subscribe();
- const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + 0 + "/messages/" + 1 + "/submessages/" + 2 + "/structures/filter/" + 0);
+ service.getFilteredStructures('0', '0', '1', '2','3').subscribe();
+ const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + 0 + "/connections/"+'3'+"/messages/" + 1 + "/submessages/" + 2 + "/structures/filter/" + 0);
expect(req.request.method).toEqual('GET');
req.flush(testData);
httpTestingController.verify();
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.ts
index 0dbfbe8..9682c41 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.ts
@@ -12,16 +12,16 @@
constructor (private http: HttpClient) { }
- getFilteredStructures(filter: string, branchId: string, messageId:string,subMessageId:string): Observable<structure[]> {
- return this.http.get<structure[]>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId + "/structures/filter/" + filter);
+ getFilteredStructures(filter: string, branchId: string, messageId:string,subMessageId:string,connectionId:string): Observable<structure[]> {
+ return this.http.get<structure[]>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages/" + subMessageId + "/structures/filter/" + filter);
}
- createStructure(body:Partial<structure>,branchId: string,messageId: string, subMessageId: string) {
- return this.http.post<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId + "/structures", body);
+ createStructure(body:Partial<structure>,branchId: string,messageId: string, subMessageId: string,connectionId:string) {
+ return this.http.post<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages/" + subMessageId + "/structures", body);
}
- relateStructure(branchId: string, messageId: string, subMessageId: string, structureId: string) {
- return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId + "/structures/"+structureId,null);
+ relateStructure(branchId: string, messageId: string, subMessageId: string, structureId: string,connectionId:string) {
+ return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages/" + subMessageId + "/structures/"+structureId,null);
}
- partialUpdateStructure(body: Partial<structure>, branchId: string, messageId: string,subMessageId: string):Observable<StructureApiResponse> {
- return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/"+ subMessageId+"/structures", body);
+ partialUpdateStructure(body: Partial<structure>, branchId: string, messageId: string,subMessageId: string,connectionId:string):Observable<StructureApiResponse> {
+ return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages/"+ subMessageId+"/structures", body);
}
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/ui.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/ui.service.ts
index cb53aa1..c7b2a50 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/ui.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/ui.service.ts
@@ -12,6 +12,7 @@
private _branchId: BehaviorSubject<string> = new BehaviorSubject<string>("0");
private _messageId: BehaviorSubject<string> = new BehaviorSubject<string>("0");
private _subMessageId: BehaviorSubject<string> = new BehaviorSubject<string>("0");
+ private _connectionId: BehaviorSubject<string> = new BehaviorSubject<string>("0");
constructor() { }
get filter() {
@@ -55,4 +56,12 @@
set subMessageIdString(value: string) {
this._subMessageId.next(value);
}
+
+ get connectionId() {
+ return this._connectionId;
+ }
+
+ set connectionIdString(value: string) {
+ this._connectionId.next(value);
+ }
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.spec.ts
index 7d35744..41a3c75 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.spec.ts
@@ -39,10 +39,11 @@
});
it('should update value', fakeAsync(() => {
- uiService.BranchIdString='8'
+ uiService.BranchIdString = '8'
+ uiService.connectionIdString='10'
component.updateMessage('description', 'v2');
tick(500);
- const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + '8' + "/messages");
+ const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + '8' + "/connections/10/messages");
expect(req.request.method).toEqual('PATCH');
}));
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.ts
index 3254aec..20375ed 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.ts
@@ -17,6 +17,7 @@
this.route.paramMap.subscribe((values) => {
this.messageService.filter = values.get('type')?.trim().toLowerCase() || '';
this.messageService.branch = values.get('branchId') || '';
+ this.messageService.connection = values.get('connection') || '';
})
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.spec.ts
index d9b5597..9cdee24 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.spec.ts
@@ -30,9 +30,10 @@
const testData: message[] = [];
service.filter = 'filter';
service.branch = '10';
+ service.connection = '10';
service.messages.subscribe();
tick(500);
- const req=httpTestingController.expectOne(apiURL + "/mim/branch/" + '10' + "/messages/filter/" + 'filter');
+ const req=httpTestingController.expectOne(apiURL + "/mim/branch/" + '10' + "/connections/"+'10'+"/messages/filter/" + 'filter');
expect(req.request.method).toEqual("GET");
req.flush(testData);
httpTestingController.verify();
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.ts
index 514d8a6..a699714 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.ts
@@ -12,19 +12,19 @@
})
export class CurrentMessagesService {
- private _messages = combineLatest(this.ui.filter,this.BranchId).pipe(
+ private _messages = combineLatest(this.ui.filter,this.BranchId,this.connectionId).pipe(
share(),
debounceTime(500),
distinctUntilChanged(),
- switchMap(x => this.messageService.getFilteredMessages(x[0], x[1]).pipe(
+ switchMap(x => this.messageService.getFilteredMessages(x[0], x[1],x[2]).pipe(
repeatWhen(_ => this.ui.UpdateRequired),
share(),
))
)
- private _allMessages = combineLatest(this.BranchId).pipe(
+ private _allMessages = combineLatest(this.BranchId,this.connectionId).pipe(
share(),
- switchMap(x => this.messageService.getFilteredMessages("", x[0]).pipe(
+ switchMap(x => this.messageService.getFilteredMessages("", x[0],x[1]).pipe(
repeatWhen(_ => this.ui.UpdateRequired),
share(),
))
@@ -52,8 +52,16 @@
return this.ui.BranchId;
}
+ set connection(id: string) {
+ this.ui.connectionIdString = id;
+ }
+
+ get connectionId() {
+ return this.ui.connectionId;
+ }
+
partialUpdateSubMessage(body:Partial<subMessage>,messageId:string) {
- return this.subMessageService.partialUpdateSubMessage(body, this.BranchId.getValue(), messageId).pipe(
+ return this.subMessageService.partialUpdateSubMessage(body, this.BranchId.getValue(), messageId,this.connectionId.getValue()).pipe(
tap(() => {
this.ui.updateMessages = true;
})
@@ -61,7 +69,7 @@
}
partialUpdateMessage(body: Partial<message>) {
- return this.messageService.partialUpdateMessage(body, this.BranchId.getValue()).pipe(
+ return this.messageService.partialUpdateMessage(body, this.BranchId.getValue(),this.connectionId.getValue()).pipe(
tap(() => {
this.ui.updateMessages = true;
})
@@ -69,7 +77,7 @@
}
relateSubMessage(messageId:string,subMessageId:string) {
- return this.subMessageService.relateSubMessage(this.BranchId.getValue(), messageId, subMessageId).pipe(
+ return this.subMessageService.relateSubMessage(this.BranchId.getValue(), messageId, subMessageId,this.connectionId.getValue()).pipe(
tap(() => {
this.ui.updateMessages = true;
})
@@ -77,7 +85,7 @@
}
createSubMessage(body:subMessage,messageId:string) {
- return this.subMessageService.addSubMessage(body, this.BranchId.getValue(), messageId).pipe(
+ return this.subMessageService.addSubMessage(body, this.BranchId.getValue(), messageId,this.connectionId.getValue()).pipe(
tap(() => {
this.ui.updateMessages = true;
})
@@ -85,7 +93,7 @@
}
createMessage(body:message) {
- return this.messageService.addMessage(body,this.BranchId.getValue()).pipe(
+ return this.messageService.addMessage(body,this.BranchId.getValue(),this.connectionId.getValue()).pipe(
tap(() => {
this.ui.updateMessages = true;
})
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/messages.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/messages.service.ts
index 5fb4e59..3538b30 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/messages.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/messages.service.ts
@@ -18,8 +18,8 @@
* @param branchId branch to look for messages on
* @returns Observable of an array of messages matching filter condition
*/
- getFilteredMessages(filter: string, branchId: string):Observable<message[]> {
- return this.http.get<message[]>(apiURL + "/mim/branch/" + branchId + "/messages/filter/" + filter);
+ getFilteredMessages(filter: string, branchId: string,connectionId:string):Observable<message[]> {
+ return this.http.get<message[]>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/filter/" + filter);
}
/**
@@ -28,8 +28,8 @@
* @param branchId branch to look for messages on
* @returns api response of whether or not the insertion was successful
*/
- addMessage(body: message, branchId:string):Observable<MessageApiResponse> {
- return this.http.post<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages", body);
+ addMessage(body: message, branchId:string,connectionId:string):Observable<MessageApiResponse> {
+ return this.http.post<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages", body);
}
/**
@@ -38,8 +38,8 @@
* @param branchId branch to look for messages on
* @returns api response of whether or not the element was updated successfully
*/
- partialUpdateMessage(body: Partial<message>, branchId: string):Observable<MessageApiResponse> {
- return this.http.patch<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages", body);
+ partialUpdateMessage(body: Partial<message>, branchId: string,connectionId:string):Observable<MessageApiResponse> {
+ return this.http.patch<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages", body);
}
/**
@@ -48,8 +48,8 @@
* @param messageId id of message to delete
* @returns api response of whether or not the message was removed
*/
- removeMessage(branchId: string, messageId: string):Observable<MessageApiResponse> {
- return this.http.delete<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/"+messageId);
+ removeMessage(branchId: string, messageId: string,connectionId:string):Observable<MessageApiResponse> {
+ return this.http.delete<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/"+messageId);
}
/**
@@ -58,8 +58,8 @@
* @param messageId id of message to find
* @returns message contents, if found
*/
- getMessage(branchId: string, messageId: string):Observable<message> {
- return this.http.get<message>(apiURL + "/mim/branch/" + branchId + "/messages/"+messageId);
+ getMessage(branchId: string, messageId: string,connectionId:string):Observable<message> {
+ return this.http.get<message>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/"+messageId);
}
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/sub-messages.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/sub-messages.service.ts
index 9a4e00d..e5b27d7 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/sub-messages.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/sub-messages.service.ts
@@ -12,23 +12,23 @@
constructor (private http: HttpClient) { }
- addSubMessage(body: subMessage, branchId: string, messageId: string):Observable<MessageApiResponse> {
- return this.http.post<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages", body);
+ addSubMessage(body: subMessage, branchId: string, messageId: string,connectionId:string):Observable<MessageApiResponse> {
+ return this.http.post<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages", body);
}
- partialUpdateSubMessage(body: Partial<subMessage>, branchId: string, messageId: string):Observable<MessageApiResponse> {
- return this.http.patch<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages", body);
+ partialUpdateSubMessage(body: Partial<subMessage>, branchId: string, messageId: string,connectionId:string):Observable<MessageApiResponse> {
+ return this.http.patch<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages", body);
}
- relateSubMessage(branchId: string, messageId: string, subMessageId:string):Observable<MessageApiResponse> {
- return this.http.patch<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId, null);
+ relateSubMessage(branchId: string, messageId: string, subMessageId:string,connectionId:string):Observable<MessageApiResponse> {
+ return this.http.patch<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages/" + subMessageId, null);
}
- unRelateSubMessage(branchId: string, messageId: string, subMessageId:string):Observable<MessageApiResponse> {
- return this.http.delete<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId);
+ unRelateSubMessage(branchId: string, messageId: string, subMessageId:string,connectionId:string):Observable<MessageApiResponse> {
+ return this.http.delete<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages/" + messageId + "/submessages/" + subMessageId);
}
- getSubMessage(branchId: string, messageId: string, subMessageId:string):Observable<subMessage> {
- return this.http.get<subMessage>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId);
+ getSubMessage(branchId: string, messageId: string, subMessageId:string,connectionId:string):Observable<subMessage> {
+ return this.http.get<subMessage>(apiURL + "/mim/branch/" + branchId + "/connections/"+connectionId+"/messages//" + messageId + "/submessages/" + subMessageId);
}
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/ui.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/ui.service.ts
index 2ee70a9..e059c71 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/ui.service.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/ui.service.ts
@@ -10,6 +10,7 @@
private _UpdateRequired: Subject<boolean> = new Subject<boolean>();
private _branchId: BehaviorSubject<string> = new BehaviorSubject<string>("0");
+ private _connectionId: BehaviorSubject<string> = new BehaviorSubject<string>("0");
constructor() { }
get filter() {
@@ -37,4 +38,12 @@
set BranchIdString(value: string) {
this._branchId.next(value);
}
+
+ get connectionId() {
+ return this._connectionId;
+ }
+
+ set connectionIdString(value: string) {
+ this._connectionId.next(value);
+ }
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.ts
index dcfd595..b4fe14a 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.ts
@@ -25,8 +25,4 @@
onNoClick() {
this.dialogRef.close();
}
-
- log(value: any) {
- console.log(value);
- }
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/ApiWriteResponse.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/ApiWriteResponse.d.ts
new file mode 100644
index 0000000..a7dea33
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/ApiWriteResponse.d.ts
@@ -0,0 +1,21 @@
+/**
+ * Response the OSEE API should return when doing a POST,PUT,PATCH, or DELETE to indicate success/status of API
+ */
+ export interface OSEEWriteApiResponse {
+ empty: boolean,
+ errorCount: number,
+ errors: boolean,
+ failed: boolean,
+ ids: string[],
+ infoCount: number,
+ numErrors: number,
+ numErrorsViaSearch: number,
+ numWarnings: number,
+ numWarningsViaSearch: number,
+ results: string[],
+ success: boolean,
+ tables: string[],
+ title: string,
+ txId: string,
+ warningCount: number
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/testing/mockBranchService.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/testing/mockBranchService.ts
index c33cecd..dd883c1 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/testing/mockBranchService.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/testing/mockBranchService.ts
@@ -84,7 +84,8 @@
configurations: [
{
id: "12345",
- name:"group1"
+ name: "group1",
+ values:[]
}
],
setValueStr(): void {
@@ -116,7 +117,8 @@
configurations: [
{
id: "12345",
- name:"group1"
+ name: "group1",
+ values:[]
}
],
setValueStr(): void {
@@ -148,7 +150,8 @@
configurations: [
{
id: "12345",
- name:"group1"
+ name: "group1",
+ values:[]
}
],
setValueStr(): void {
@@ -181,7 +184,8 @@
configurations: [
{
id: "12345",
- name:"group1"
+ name: "group1",
+ values:[]
}
],
setValueStr(): void {
diff --git a/plugins/org.eclipse.osee.web/tsconfig.json b/plugins/org.eclipse.osee.web/tsconfig.json
index 94a24fe..436c7af 100644
--- a/plugins/org.eclipse.osee.web/tsconfig.json
+++ b/plugins/org.eclipse.osee.web/tsconfig.json
@@ -17,7 +17,7 @@
"target": "es2015",
"module": "es2020",
"lib": [
- "es2018",
+ "es2019",
"dom"
]
},