diff --git a/ngapp/src/app/activities/add-activity-wizard/add-activity-wizard.component.ts b/ngapp/src/app/activities/add-activity-wizard/add-activity-wizard.component.ts
index b3cf601f..c27f3395 100644
--- a/ngapp/src/app/activities/add-activity-wizard/add-activity-wizard.component.ts
+++ b/ngapp/src/app/activities/add-activity-wizard/add-activity-wizard.component.ts
@@ -239,6 +239,7 @@ export class AddActivityWizardComponent implements OnInit {
self.step2bConfig.nextEnabled = false;
},
(error) => {
+ self.logger.error("[AddActivityWizardComponent] Error: %o", error);
self.createComplete = true;
self.createSuccessful = false;
}
diff --git a/ngapp/src/app/app-routing.module.ts b/ngapp/src/app/app-routing.module.ts
index 40fae7ab..b49afffa 100644
--- a/ngapp/src/app/app-routing.module.ts
+++ b/ngapp/src/app/app-routing.module.ts
@@ -20,6 +20,7 @@ import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { Routes } from "@angular/router";
import { ConnectionsConstants } from "@connections/shared/connections-constants";
+import { DataservicesConstants } from "@dataservices/shared/dataservices-constants";
import { environment } from "@environments/environment";
import { PageNotFoundComponent } from "@shared/page-not-found/page-not-found.component";
@@ -27,6 +28,7 @@ const appRoutes: Routes = [
{ path: "", redirectTo: environment.homePagePath, pathMatch: "full" },
{ path: ConnectionsConstants.connectionsRootRoute, loadChildren: "@connections/connections.module#ConnectionsModule" },
{ path: ActivitiesConstants.activitiesRootRoute, loadChildren: "@activities/activities.module#ActivitiesModule" },
+ { path: DataservicesConstants.dataservicesRootRoute, loadChildren: "@dataservices/dataservices.module#DataservicesModule" },
{ path: "**", component: PageNotFoundComponent }, // always last
];
diff --git a/ngapp/src/app/app.module.ts b/ngapp/src/app/app.module.ts
index f1acc022..ffe2ca9d 100644
--- a/ngapp/src/app/app.module.ts
+++ b/ngapp/src/app/app.module.ts
@@ -25,6 +25,8 @@ import { AppComponent } from "@app/app.component";
import { ConnectionsRoutingModule } from "@connections/connections-routing.module";
import { ConnectionsModule } from "@connections/connections.module";
import { CoreModule } from "@core/core.module";
+import { DataservicesModule } from "@dataservices/dataservices.module";
+import { DataservicesRoutingModule } from "@dataservices/dataservices-routing.module";
import { SharedModule } from "@shared/shared.module";
@NgModule({
@@ -36,10 +38,12 @@ import { SharedModule } from "@shared/shared.module";
BrowserModule,
ConnectionsModule,
CoreModule,
+ DataservicesModule,
RouterModule,
SharedModule,
ActivitiesRoutingModule,
ConnectionsRoutingModule,
+ DataservicesRoutingModule,
AppRoutingModule // last so its routes are check after all other routes
],
providers: [],
diff --git a/ngapp/src/app/connections/add-connection-wizard/add-connection-wizard.component.ts b/ngapp/src/app/connections/add-connection-wizard/add-connection-wizard.component.ts
index 5b907fe5..aecaace3 100644
--- a/ngapp/src/app/connections/add-connection-wizard/add-connection-wizard.component.ts
+++ b/ngapp/src/app/connections/add-connection-wizard/add-connection-wizard.component.ts
@@ -285,6 +285,7 @@ export class AddConnectionWizardComponent implements OnInit {
self.step3bConfig.nextEnabled = false;
},
(error) => {
+ self.logger.error("[AddConnectionWizardComponent] Error: %o", error);
self.createComplete = true;
self.createSuccessful = false;
}
diff --git a/ngapp/src/app/connections/add-connection/add-connection.component.html b/ngapp/src/app/connections/add-connection/add-connection.component.html
index 983950e3..250c1ea7 100644
--- a/ngapp/src/app/connections/add-connection/add-connection.component.html
+++ b/ngapp/src/app/connections/add-connection/add-connection.component.html
@@ -1,8 +1,8 @@
diff --git a/ngapp/src/app/connections/connections.component.spec.ts b/ngapp/src/app/connections/connections.component.spec.ts
index 757dfb21..99eb20d0 100644
--- a/ngapp/src/app/connections/connections.component.spec.ts
+++ b/ngapp/src/app/connections/connections.component.spec.ts
@@ -107,7 +107,7 @@ describe("ConnectionsComponent", () => {
component.filterConnections();
fixture.detectChanges();
- // Now expect 0 activities match
+ // Now expect 0 connections match
connections = component.filteredConnections;
expect(connections.length).toEqual(0);
});
diff --git a/ngapp/src/app/core/api.service.ts b/ngapp/src/app/core/api.service.ts
index 293020e8..0e95798c 100644
--- a/ngapp/src/app/core/api.service.ts
+++ b/ngapp/src/app/core/api.service.ts
@@ -15,7 +15,6 @@
* limitations under the License.
*/
-import { Injectable } from "@angular/core";
import { Headers, RequestOptions, Response } from "@angular/http";
import { LoggerService } from "@core/logger.service";
import "rxjs/add/observable/throw";
diff --git a/ngapp/src/app/core/vertical-nav/vertical-nav.component.html b/ngapp/src/app/core/vertical-nav/vertical-nav.component.html
index e20bf9da..80963454 100644
--- a/ngapp/src/app/core/vertical-nav/vertical-nav.component.html
+++ b/ngapp/src/app/core/vertical-nav/vertical-nav.component.html
@@ -6,6 +6,11 @@
Activities
+
diff --git a/ngapp/src/app/core/vertical-nav/vertical-nav.component.ts b/ngapp/src/app/core/vertical-nav/vertical-nav.component.ts
index fe3094d6..275511d7 100644
--- a/ngapp/src/app/core/vertical-nav/vertical-nav.component.ts
+++ b/ngapp/src/app/core/vertical-nav/vertical-nav.component.ts
@@ -19,13 +19,14 @@ import { ActivitiesConstants } from "@activities/shared/activities-constants";
import { Component, OnInit } from "@angular/core";
import { NavigationEnd, Router } from "@angular/router";
import { ConnectionsConstants } from "@connections/shared/connections-constants";
+import { DataservicesConstants } from "@dataservices/shared/dataservices-constants";
import { LoggerService } from "@core/logger.service";
/**
* Models the menus off the main left-hand vertical nav.
*/
enum VerticalNavType {
- Home, Activities, Connections
+ Home, Activities, Connections, Dataservices
}
@Component({
@@ -79,7 +80,18 @@ export class VerticalNavComponent implements OnInit {
});
}
- /**
+ /**
+ * Called when the user clicks the vertical menu Dataservices item.
+ */
+ public onDataservicesClick(): void {
+ this.currentMenu = VerticalNavType.Dataservices;
+ const link: string[] = [ DataservicesConstants.dataservicesRootPath ];
+ this.router.navigate(link).then(() => {
+ // nothing to do
+ });
+ }
+
+ /**
* Called when the user clicks the vertical menu shade (the grey shaded area behind the submenu div that
* is displayed when a sub-menu is selected). Clicking the shade makes the sub-menu div go away.
*/
diff --git a/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.css b/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.css
new file mode 100644
index 00000000..0f0ecbda
--- /dev/null
+++ b/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.css
@@ -0,0 +1,5 @@
+.wizard-pf-failed-icon {
+ color: #9c3535;
+ font-size: 67px;
+ line-height: 67px;
+}
diff --git a/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.html b/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.html
new file mode 100644
index 00000000..51c22fa3
--- /dev/null
+++ b/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.html
@@ -0,0 +1,78 @@
+
+
+
+
+
+ {{ step1InstructionMessage }}
+
+
+
+
+
+
+
+
+
+ {{ step2InstructionMessage }}
+ Dataservice Properties:
+
+
+
+
+
+
+
+
+
Creation in progress
+
The dataservice is being created.
+
+
+
+
+
Creation was successful
+
The dataservice was created successfully. Click on the button to see all dataservices.
+
View All Dataservices
+
+
+
+
+
Creation failed
+
The dataservice creation failed. Correct any properties and retry.
+
+
+
+
+
diff --git a/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.spec.ts b/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.spec.ts
new file mode 100644
index 00000000..be3c7a2d
--- /dev/null
+++ b/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.spec.ts
@@ -0,0 +1,42 @@
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+
+import { FormsModule, ReactiveFormsModule } from "@angular/forms";
+import { RouterTestingModule } from "@angular/router/testing";
+import { DataserviceService } from "@dataservices/shared/dataservice.service";
+import { MockDataserviceService } from "@dataservices/shared/mock-dataservice.service";
+import { CoreModule } from "@core/core.module";
+import { PropertyFormPropertyComponent } from "@shared/property-form/property-form-property/property-form-property.component";
+import { PropertyFormComponent } from "@shared/property-form/property-form.component";
+import { PatternFlyNgModule } from "patternfly-ng";
+import { AddDataserviceWizardComponent } from "./add-dataservice-wizard.component";
+import { ConnectionService } from "@connections/shared/connection.service";
+import { MockConnectionService } from "@connections/shared/mock-connection.service";
+
+describe("AddDataserviceWizardComponent", () => {
+ let component: AddDataserviceWizardComponent;
+ let fixture: ComponentFixture
;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [ CoreModule, FormsModule, PatternFlyNgModule, ReactiveFormsModule, RouterTestingModule ],
+ declarations: [ AddDataserviceWizardComponent, PropertyFormComponent, PropertyFormPropertyComponent ],
+ providers: [
+ { provide: DataserviceService, useClass: MockDataserviceService },
+ { provide: ConnectionService, useClass: MockConnectionService },
+ ]
+ })
+ .compileComponents().then(() => {
+ // nothing to do
+ });
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AddDataserviceWizardComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it("should be created", () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.ts b/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.ts
new file mode 100644
index 00000000..cc347b06
--- /dev/null
+++ b/ngapp/src/app/dataservices/add-dataservice-wizard/add-dataservice-wizard.component.ts
@@ -0,0 +1,321 @@
+/**
+ * @license
+ * Copyright 2017 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ Component,
+ OnInit,
+ ViewChild,
+ ViewEncapsulation,
+} from "@angular/core";
+
+import { FormControl, FormGroup } from "@angular/forms";
+import { AbstractControl } from "@angular/forms";
+import { Validators } from "@angular/forms";
+import { Router } from "@angular/router";
+import { Connection } from "@connections/shared/connection.model";
+import { ConnectionService } from "@connections/shared/connection.service";
+import { DataserviceService } from "@dataservices/shared/dataservice.service";
+import { DataservicesConstants } from "@dataservices/shared/dataservices-constants";
+import { NewDataservice } from "@dataservices/shared/new-dataservice.model";
+import { LoggerService } from "@core/logger.service";
+import { WizardComponent } from "patternfly-ng";
+import { WizardEvent } from "patternfly-ng";
+import { WizardStepConfig } from "patternfly-ng";
+import { WizardConfig } from "patternfly-ng";
+
+@Component({
+ encapsulation: ViewEncapsulation.None,
+ selector: "app-add-dataservice-wizard",
+ templateUrl: "./add-dataservice-wizard.component.html"
+})
+export class AddDataserviceWizardComponent implements OnInit {
+ public readonly dataserviceSummaryLink: string = DataservicesConstants.dataservicesRootPath;
+
+ // Wizard Config
+ public wizardConfig: WizardConfig;
+
+ public basicPropertyForm: FormGroup;
+ public createComplete = true;
+ public createSuccessful = false;
+ public connectionsLoaded = false;
+
+ // Wizard Step 1
+ public step1Config: WizardStepConfig;
+
+ // Wizard Step 2
+ public step2Config: WizardStepConfig;
+ public step2aConfig: WizardStepConfig;
+ public step2bConfig: WizardStepConfig;
+
+ @ViewChild("wizard") public wizard: WizardComponent;
+
+ private connectionService: ConnectionService;
+ private dataserviceService: DataserviceService;
+ private allConnections: Connection[] = [];
+ private logger: LoggerService;
+ private router: Router;
+
+ constructor( router: Router, connectionService: ConnectionService, dataserviceService: DataserviceService, logger: LoggerService ) {
+ this.connectionService = connectionService;
+ this.dataserviceService = dataserviceService;
+ this.router = router;
+ this.logger = logger;
+ this.createBasicPropertyForm();
+ }
+
+ /*
+ * Initialization
+ */
+ public ngOnInit(): void {
+ // Step 1 - Basic Properties
+ this.step1Config = {
+ id: "step1",
+ priority: 0,
+ title: "Basic Properties",
+ allowClickNav: false
+ } as WizardStepConfig;
+
+ // Step 2 - Review and Create
+ this.step2Config = {
+ id: "step2",
+ priority: 0,
+ title: "Review and Create",
+ allowClickNav: false
+ } as WizardStepConfig;
+ this.step2aConfig = {
+ id: "step2a",
+ priority: 0,
+ title: "Review",
+ allowClickNav: false
+ } as WizardStepConfig;
+ this.step2bConfig = {
+ id: "step2b",
+ priority: 1,
+ title: "Create",
+ allowClickNav: false
+ } as WizardStepConfig;
+
+ // Wizard Configuration
+ this.wizardConfig = {
+ embedInPage: true,
+ loadingTitle: "Add Dataservice Wizard loading",
+ loadingSecondaryInfo: "Please wait for the wizard to finish loading...",
+ title: "Add Dataservice",
+ contentHeight: "500px"
+ } as WizardConfig;
+
+ // Load the connections for the first step
+ this.connectionsLoaded = false;
+ const self = this;
+ this.connectionService
+ .getAllConnections()
+ .subscribe(
+ (conns) => {
+ self.allConnections = conns;
+ self.connectionsLoaded = true;
+ },
+ (error) => {
+ self.logger.error("[AddDataserviceWizardComponent] Error getting connections: %o", error);
+ }
+ );
+
+ this.setNavAway(false);
+ }
+
+ // ----------------
+ // Public Methods
+ // ----------------
+ /*
+ * Return the name valid state
+ */
+ public get nameValid(): boolean {
+ return this.basicPropertyForm.controls["name"].valid;
+ }
+
+ /*
+ * Return the connection valid state
+ */
+ public get connectionValid(): boolean {
+ return this.basicPropertyForm.controls["connection"].valid;
+ }
+
+ /*
+ * Step 1 instruction message
+ */
+ public get step1InstructionMessage(): string {
+ if (!this.nameValid) {
+ return "Please enter a name for the Dataservice";
+ } else if (!this.connectionValid) {
+ return "Please choose a connection for the Dataservice";
+ } else {
+ return "When finished entering properties, click Next to continue";
+ }
+ }
+
+ /*
+ * Step 2 instruction message
+ */
+ public get step2InstructionMessage(): string {
+ return "Review your entries. When finished, click Create to create the Dataservice";
+ }
+
+ /*
+ * Return the name error message if invalid
+ */
+ public getBasicPropertyErrorMessage( name: string ): string {
+ const control: AbstractControl = this.basicPropertyForm.controls[name];
+ if (control.invalid) {
+ // The first error found is returned
+ if (control.errors.required) {
+ return name + " is a required property";
+ }
+ }
+ return "";
+ }
+
+ public nextClicked($event: WizardEvent): void {
+ // When leaving page 1, load the driver-specific property definitions
+ if ($event.step.config.id === "step1") {
+ }
+ }
+
+ public cancelClicked($event: WizardEvent): void {
+ const link: string[] = [ DataservicesConstants.dataservicesRootPath ];
+ this.logger.log("[AddDataserviceWizardComponent] Navigating to: %o", link);
+ this.router.navigate(link).then(() => {
+ // nothing to do
+ });
+ }
+
+ /*
+ * Create the Dataservice via komodo REST interface,
+ * using the currently entered properties
+ */
+ public createDataservice(): void {
+ this.createComplete = false;
+ this.wizardConfig.done = true;
+
+ const dataservice: NewDataservice = new NewDataservice();
+
+ // Dataservice basic properties from step 1
+ dataservice.setId(this.dataserviceName);
+
+ const self = this;
+ this.dataserviceService
+ .createDataservice(dataservice)
+ .subscribe(
+ () => {
+ self.createComplete = true;
+ self.createSuccessful = true;
+ self.step2bConfig.nextEnabled = false;
+ },
+ (error) => {
+ self.logger.error("[AddDataserviceWizardComponent] Error: %o", error);
+ self.createComplete = true;
+ self.createSuccessful = false;
+ }
+ );
+ }
+
+ public stepChanged($event: WizardEvent): void {
+ if ($event.step.config.id === "step1") {
+ this.updatePage1ValidStatus();
+ this.wizardConfig.nextTitle = "Next >";
+ } else if ($event.step.config.id === "step2a") {
+ this.wizardConfig.nextTitle = "Create";
+ } else if ($event.step.config.id === "step2b") {
+ // Note: The next button is not disabled by default when wizard is done
+ this.step2Config.nextEnabled = false;
+ } else {
+ this.wizardConfig.nextTitle = "Next >";
+ }
+ }
+
+ /**
+ * Handler for property form initialization
+ * @param {boolean} isValid form valid state
+ */
+ public onDetailPropertyInit(isValid: boolean): void {
+ this.updatePage2ValidStatus(isValid);
+ }
+
+ /**
+ * Handler for property form changes
+ * @param {boolean} isValid form valid state
+ */
+ public onDetailPropertyChanged(isValid: boolean): void {
+ this.updatePage2ValidStatus(isValid);
+ }
+
+ /**
+ * @returns {string} the name of the dataservice
+ */
+ public get dataserviceName(): string {
+ return this.basicPropertyForm.controls["name"].value;
+ }
+
+ /**
+ * @returns {string} the connection name of the dataservice
+ */
+ public get connectionName(): string {
+ return this.basicPropertyForm.controls["connection"].value;
+ }
+
+ /*
+ * Return the array of connection names
+ */
+ public get connectionNames(): string[] {
+ const connNames: string[] = [];
+ for ( const conn of this.allConnections ) {
+ connNames.push(conn.getId());
+ }
+ return connNames.sort();
+ }
+
+ // ----------------
+ // Private Methods
+ // ----------------
+
+ /*
+ * Create the BasicProperty form (page 1)
+ */
+ private createBasicPropertyForm(): void {
+ this.basicPropertyForm = new FormGroup({
+ name: new FormControl("", Validators.required),
+ connection: new FormControl("", Validators.required)
+ });
+ // Responds to basic property changes - updates the page status
+ this.basicPropertyForm.valueChanges.subscribe((val) => {
+ this.updatePage1ValidStatus( );
+ });
+ }
+
+ private setNavAway(allow: boolean): void {
+ this.step1Config.allowNavAway = allow;
+ }
+
+ private updatePage1ValidStatus( ): void {
+ this.step1Config.nextEnabled = this.basicPropertyForm.valid;
+ this.setNavAway(this.step1Config.nextEnabled);
+ }
+
+ private updatePage2ValidStatus(formValid: boolean): void {
+ this.step2Config.nextEnabled = formValid;
+ this.setNavAway(this.step2Config.nextEnabled);
+ }
+
+}
diff --git a/ngapp/src/app/dataservices/add-dataservice/add-dataservice.component.css b/ngapp/src/app/dataservices/add-dataservice/add-dataservice.component.css
new file mode 100644
index 00000000..e69de29b
diff --git a/ngapp/src/app/dataservices/add-dataservice/add-dataservice.component.html b/ngapp/src/app/dataservices/add-dataservice/add-dataservice.component.html
new file mode 100644
index 00000000..be280356
--- /dev/null
+++ b/ngapp/src/app/dataservices/add-dataservice/add-dataservice.component.html
@@ -0,0 +1,18 @@
+
+
diff --git a/ngapp/src/app/dataservices/add-dataservice/add-dataservice.component.spec.ts b/ngapp/src/app/dataservices/add-dataservice/add-dataservice.component.spec.ts
new file mode 100644
index 00000000..eff5b9f8
--- /dev/null
+++ b/ngapp/src/app/dataservices/add-dataservice/add-dataservice.component.spec.ts
@@ -0,0 +1,42 @@
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+
+import { FormsModule, ReactiveFormsModule } from "@angular/forms";
+import { RouterTestingModule } from "@angular/router/testing";
+import { AddDataserviceWizardComponent } from "@dataservices/add-dataservice-wizard/add-dataservice-wizard.component";
+import { CoreModule } from "@core/core.module";
+import { SharedModule } from "@shared/shared.module";
+import { PatternFlyNgModule } from "patternfly-ng";
+import { AddDataserviceComponent } from "./add-dataservice.component";
+import { DataserviceService } from "@dataservices/shared/dataservice.service";
+import { MockDataserviceService } from "@dataservices/shared/mock-dataservice.service";
+import { ConnectionService } from "@connections/shared/connection.service";
+import { MockConnectionService } from "@connections/shared/mock-connection.service";
+
+describe("AddDataserviceComponent", () => {
+ let component: AddDataserviceComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [ CoreModule, PatternFlyNgModule, FormsModule, ReactiveFormsModule, RouterTestingModule, SharedModule ],
+ declarations: [ AddDataserviceComponent, AddDataserviceWizardComponent ],
+ providers: [
+ { provide: DataserviceService, useClass: MockDataserviceService },
+ { provide: ConnectionService, useClass: MockConnectionService }
+ ]
+ })
+ .compileComponents().then(() => {
+ // nothing to do
+ });
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AddDataserviceComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it("should be created", () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/ngapp/src/app/dataservices/add-dataservice/add-dataservice.component.ts b/ngapp/src/app/dataservices/add-dataservice/add-dataservice.component.ts
new file mode 100644
index 00000000..d5b96f24
--- /dev/null
+++ b/ngapp/src/app/dataservices/add-dataservice/add-dataservice.component.ts
@@ -0,0 +1,40 @@
+/**
+ * @license
+ * Copyright 2017 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Component, OnInit } from "@angular/core";
+import { DataservicesConstants } from "@dataservices/shared/dataservices-constants";
+
+@Component({
+ selector: "app-add-dataservice-page",
+ templateUrl: "./add-dataservice.component.html",
+ styleUrls: ["./add-dataservice.component.css"]
+})
+export class AddDataserviceComponent implements OnInit {
+
+ public readonly dataservicesLink = DataservicesConstants.dataservicesRootPath;
+
+ public pageError: any = "";
+
+ constructor() {
+ // Nothing
+ }
+
+ public ngOnInit(): void {
+ // Nothing
+ }
+
+}
diff --git a/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.css b/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.css
new file mode 100644
index 00000000..64e6b57d
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.css
@@ -0,0 +1,70 @@
+.container-cards-pf {
+ padding: 0;
+ margin-top: 0;
+}
+
+.row-cards-pf {
+ padding: 0;
+}
+
+.dataservice-card-action-icon {
+ cursor: pointer;
+}
+
+.dataservice-card-icon {
+ border: 2px solid #39a5dc;
+ border-radius: 50%;
+ padding: 5px;
+ margin-right: 10px;
+ width: 32px;
+}
+
+.dataservice-card .dataservice-card-title {
+ font-size: 16px;
+ font-weight: bold;
+}
+
+.dataservice-card {
+ -webkit-transition: background-color 300ms;
+ -moz-transition: background-color 300ms;
+ //-ms-transition: background-color 300ms;
+ -o-transition: background-color 300ms;
+ transition: background-color 300ms;
+ height: 160px;
+}
+.dataservice-card:hover {
+ background-color: rgb(237, 237, 237);
+}
+
+.dataservice-card.active {
+ background-color: rgb(221, 234, 255);
+}
+
+/*
+.dataservice-description {
+ font-size: 13px;
+ overflow-y: auto;
+}
+*/
+
+.dataservice-card .dataservice-tags {
+ margin-bottom: 8px;
+}
+.dataservice-card .dataservice-tags .dataservice-tags-label {
+ font-weight: bold;
+ margin-right: 5px;
+}
+.dataservice-card .dataservice-tags /*.dataservice-tag*/ {
+ margin-right: 5px;
+ border: 1px solid #ccc;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ padding: 2px 4px;
+}
+.dataservice-card .dataservice-tags /*.dataservice-tag:hover*/ {
+ cursor: pointer;
+ background-color: #0088ce;
+ border-color: #00659c;
+ color: white;
+}
diff --git a/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.html b/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.html
new file mode 100644
index 00000000..98f74c50
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.html
@@ -0,0 +1,29 @@
+
diff --git a/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.spec.ts b/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.spec.ts
new file mode 100644
index 00000000..c701242b
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.spec.ts
@@ -0,0 +1,28 @@
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+import { RouterTestingModule } from "@angular/router/testing";
+import { DataservicesCardsComponent } from "@dataservices/dataservices-cards/dataservices-cards.component";
+
+describe("DataservicesCardsComponent", () => {
+ let component: DataservicesCardsComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [ RouterTestingModule ],
+ declarations: [ DataservicesCardsComponent ]
+ })
+ .compileComponents().then(() => {
+ // nothing to do
+ });
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DataservicesCardsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it("should be created", () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.ts b/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.ts
new file mode 100644
index 00000000..c3aa26d6
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices-cards/dataservices-cards.component.ts
@@ -0,0 +1,65 @@
+/**
+ * @license
+ * Copyright 2017 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Component, EventEmitter, Input, Output } from "@angular/core";
+import { Dataservice } from "@dataservices/shared/dataservice.model";
+
+@Component({
+ moduleId: module.id,
+ selector: "app-dataservices-cards",
+ templateUrl: "dataservices-cards.component.html",
+ styleUrls: ["dataservices-cards.component.css"]
+})
+export class DataservicesCardsComponent {
+
+ @Input() public dataservices: Dataservice[];
+ @Input() public selectedDataservices: Dataservice[];
+ @Output() public dataserviceSelected: EventEmitter = new EventEmitter();
+ @Output() public dataserviceDeselected: EventEmitter = new EventEmitter();
+ @Output() public tagSelected: EventEmitter = new EventEmitter();
+ @Output() public deleteDataservice: EventEmitter = new EventEmitter();
+
+ /**
+ * Constructor.
+ */
+ constructor() {
+ // nothing to do
+ }
+
+ public toggleDataserviceSelected(dataservice: Dataservice): void {
+ if (this.isSelected(dataservice)) {
+ this.dataserviceDeselected.emit(dataservice);
+ } else {
+ this.dataserviceSelected.emit(dataservice);
+ }
+ }
+
+ public isSelected(dataservice: Dataservice): boolean {
+ return this.selectedDataservices.indexOf(dataservice) !== -1;
+ }
+
+ public onDeleteDataservice(dataserviceName: string): void {
+ this.deleteDataservice.emit(dataserviceName);
+ }
+
+ public onSelectTag(tag: string, event: MouseEvent): void {
+ event.stopPropagation();
+ event.preventDefault();
+ this.tagSelected.emit(tag);
+ }
+
+}
diff --git a/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.css b/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.css
new file mode 100644
index 00000000..e84a38a3
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.css
@@ -0,0 +1,39 @@
+.list-view-pf-main-info {
+ padding-bottom: 5px;
+ padding-top: 5px;
+}
+.list-group-item {
+ -webkit-transition: background-color 300ms;
+ -moz-transition: background-color 300ms;
+ //-ms-transition: background-color 300ms;
+ -o-transition: background-color 300ms;
+ transition: background-color 300ms;
+}
+.list-group-item, .list-group-item:first-child {
+ margin-bottom: 5px;
+ border-top: 1px solid rgb(57, 165, 220);
+}
+.list-group-item.active {
+ background-color: #ffffff;
+}
+
+.list-group-item .dataservice-tags {
+}
+.list-group-item .dataservice-tags .dataservice-tags-label {
+ font-weight: bold;
+ margin-right: 5px;
+}
+.list-group-item .dataservice-tags /*.dataservice-tag*/ {
+ margin-right: 5px;
+ border: 1px solid #ccc;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ padding: 2px 4px;
+}
+.list-group-item .dataservice-tags /*.dataservice-tag:hover*/ {
+ cursor: pointer;
+ background-color: #0088ce;
+ border-color: #00659c;
+ color: white;
+}
diff --git a/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.html b/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.html
new file mode 100644
index 00000000..04e91f78
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.html
@@ -0,0 +1,33 @@
+
diff --git a/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.spec.ts b/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.spec.ts
new file mode 100644
index 00000000..8a5fe78e
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.spec.ts
@@ -0,0 +1,28 @@
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+import { RouterTestingModule } from "@angular/router/testing";
+import { DataservicesListComponent } from "@dataservices/dataservices-list/dataservices-list.component";
+
+describe("DataservicesListComponent", () => {
+ let component: DataservicesListComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [ RouterTestingModule ],
+ declarations: [ DataservicesListComponent ]
+ })
+ .compileComponents().then(() => {
+ // nothing to do
+ });
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DataservicesListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it("should be created", () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.ts b/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.ts
new file mode 100644
index 00000000..699d7055
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices-list/dataservices-list.component.ts
@@ -0,0 +1,68 @@
+/**
+ * @license
+ * Copyright 2017 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Component, EventEmitter, Input, Output } from "@angular/core";
+import { Router } from "@angular/router";
+import { Dataservice } from "@dataservices/shared/dataservice.model";
+
+@Component({
+ moduleId: module.id,
+ selector: "app-dataservices-list",
+ templateUrl: "dataservices-list.component.html",
+ styleUrls: ["dataservices-list.component.css"]
+})
+export class DataservicesListComponent {
+
+ @Input() public dataservices: Dataservice[];
+ @Input() public selectedDataservices: Dataservice[];
+ @Output() public dataserviceSelected: EventEmitter = new EventEmitter();
+ @Output() public dataserviceDeselected: EventEmitter = new EventEmitter();
+ @Output() public tagSelected: EventEmitter = new EventEmitter();
+ @Output() public deleteDataservice: EventEmitter = new EventEmitter();
+
+ private router: Router;
+
+ /**
+ * Constructor.
+ */
+ constructor(router: Router) {
+ this.router = router;
+ }
+
+ public toggleDataserviceSelected(dataservice: Dataservice): void {
+ if (this.isSelected(dataservice)) {
+ this.dataserviceDeselected.emit(dataservice);
+ } else {
+ this.dataserviceSelected.emit(dataservice);
+ }
+ }
+
+ public isSelected(dataservice: Dataservice): boolean {
+ return this.selectedDataservices.indexOf(dataservice) !== -1;
+ }
+
+ public onDeleteDataservice(dataserviceName: string): void {
+ this.deleteDataservice.emit(dataserviceName);
+ }
+
+ public onSelectTag(tag: string, event: MouseEvent): void {
+ event.stopPropagation();
+ event.preventDefault();
+ this.tagSelected.emit(tag);
+ }
+
+}
diff --git a/ngapp/src/app/dataservices/dataservices-routing.module.ts b/ngapp/src/app/dataservices/dataservices-routing.module.ts
new file mode 100644
index 00000000..7494aff7
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices-routing.module.ts
@@ -0,0 +1,38 @@
+/**
+ * @license
+ * Copyright 2017 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { NgModule } from "@angular/core";
+import { RouterModule } from "@angular/router";
+import { Routes } from "@angular/router";
+import { AddDataserviceComponent } from "@dataservices/add-dataservice/add-dataservice.component";
+import { DataservicesComponent } from "@dataservices/dataservices.component";
+import { DataservicesConstants } from "@dataservices/shared/dataservices-constants";
+
+const dataservicesRoutes: Routes = [
+ { path: DataservicesConstants.dataservicesRootRoute, component: DataservicesComponent },
+ { path: DataservicesConstants.addDataserviceRoute, component: AddDataserviceComponent }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild( dataservicesRoutes )
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class DataservicesRoutingModule {}
diff --git a/ngapp/src/app/dataservices/dataservices.component.css b/ngapp/src/app/dataservices/dataservices.component.css
new file mode 100644
index 00000000..c3505e40
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices.component.css
@@ -0,0 +1,57 @@
+.toolbar-pf {
+ margin-top: 5px;
+}
+
+.toolbar-pf form {
+ margin-bottom: 0;
+}
+
+.toolbar-pf-results {
+ margin-top: 0;
+}
+
+.dataservice-list-items {
+ margin-top: 10px
+}
+
+.dataservice-list-dataservices .toolbar-pf {
+ background-color: transparent;
+}
+
+.dataservice-list-dataservices .toolbar-pf .toolbar-pf-results {
+ background-color: white;
+}
+
+a.clear-filters {
+ cursor: pointer;
+}
+
+.toolbar-pf-view-selector {
+ float: right;
+}
+
+.toolbar-pf-view-selector li a {
+ cursor: pointer;
+ color: #333;
+}
+
+.toolbar-pf-view-selector li a:hover {
+ color: #0088ce;
+}
+
+.dataservice-list-items .empty-state {
+ text-align: center;
+}
+
+.blank-slate-pf {
+ background-color: white;
+ width: 50%;
+ min-width: 500px;
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 15px;
+}
+
+.dataservice-list-items .none-matched-state .alert {
+ background-color: white;
+}
diff --git a/ngapp/src/app/dataservices/dataservices.component.html b/ngapp/src/app/dataservices/dataservices.component.html
new file mode 100644
index 00000000..7fce43ae
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices.component.html
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
Dataservices
+
+
+
+
+
+
+
+
+
+
No Dataservices Found
+
+ No Dataservices were found - please click below to create a new Dataservice!
+
+
+
+
+
+
+
+ No Dataservices matched the filter! Please try changing your filter criteria...
+
+
+
+
+
+
+
+
+
+
+ Loading Dataservices...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Do you really want to delete the selected Dataservice?
+
diff --git a/ngapp/src/app/dataservices/dataservices.component.spec.ts b/ngapp/src/app/dataservices/dataservices.component.spec.ts
new file mode 100644
index 00000000..5f8bbab1
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices.component.spec.ts
@@ -0,0 +1,115 @@
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+import { FormsModule } from "@angular/forms";
+import { HttpModule } from "@angular/http";
+import { By } from "@angular/platform-browser";
+import { RouterTestingModule } from "@angular/router/testing";
+import { DataservicesCardsComponent } from "@dataservices/dataservices-cards/dataservices-cards.component";
+import { DataservicesListComponent } from "@dataservices/dataservices-list/dataservices-list.component";
+import { DataservicesComponent } from "@dataservices/dataservices.component";
+import { DataserviceService } from "@dataservices/shared/dataservice.service";
+import { MockDataserviceService } from "@dataservices/shared/mock-dataservice.service";
+import { CoreModule } from "@core/core.module";
+import { SharedModule } from "@shared/shared.module";
+import { ModalModule } from "ngx-bootstrap";
+
+describe("DataservicesComponent", () => {
+ let component: DataservicesComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [ CoreModule, FormsModule, HttpModule, ModalModule.forRoot(), RouterTestingModule, SharedModule ],
+ declarations: [ DataservicesComponent, DataservicesListComponent, DataservicesCardsComponent ]
+ });
+
+ // use mock service
+ TestBed.overrideComponent( DataservicesComponent, {
+ set: {
+ providers: [
+ { provide: DataserviceService, useClass: MockDataserviceService },
+ ]
+ }
+ });
+
+ fixture = TestBed.createComponent(DataservicesComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ }));
+
+ it("should be created", () => {
+ expect(component).toBeTruthy();
+ });
+
+ it("should have Dataservices Title", () => {
+ // query for the title by CSS element selector
+ const de = fixture.debugElement.query(By.css("h2"));
+ const el = de.nativeElement;
+ expect(el.textContent).toEqual("Dataservices");
+ });
+
+ it("should have Toolbar", () => {
+ // query for the toolbar by css classname
+ const de = fixture.debugElement.query(By.css(".toolbar-pf"));
+ expect(de).toBeDefined();
+ });
+
+ it("should have Dataservices", () => {
+ // Check component object
+ const dataservices = component.allDataservices;
+ expect(dataservices.length).toEqual(3);
+
+ // Check html has the same number of dataservice cards
+ const cardDebugElems = fixture.debugElement.queryAll(By.css(".dataservice-card-title"));
+ expect(cardDebugElems).toBeDefined();
+ expect(cardDebugElems.length).toEqual(3);
+ });
+
+ it("should have initial card layout", () => {
+ // app-dataservices-cards should be present
+ let debugEl = fixture.debugElement.query(By.css("app-dataservices-cards"));
+ const element = debugEl.nativeElement;
+ expect(element).toBeDefined();
+
+ // app-dataservices-list should not be present
+ debugEl = fixture.debugElement.query(By.css("app-dataservices-list"));
+ expect(debugEl).toBeNull();
+ });
+
+ it("should toggle layout", () => {
+ // Initial layout should be Card Layout
+ let cardDebugElem = fixture.debugElement.query(By.css("app-dataservices-cards"));
+ let listDebugElem = fixture.debugElement.query(By.css("app-dataservices-list"));
+ expect(cardDebugElem).toBeDefined();
+ expect(listDebugElem).toBeNull();
+ const cardElem = cardDebugElem.nativeElement;
+ expect(cardElem).toBeDefined();
+
+ // Change the layout to ListLayout
+ component.setListLayout();
+ fixture.detectChanges();
+
+ // Verify that the layout has changed
+ cardDebugElem = fixture.debugElement.query(By.css("app-dataservices-cards"));
+ listDebugElem = fixture.debugElement.query(By.css("app-dataservices-list"));
+ expect(cardDebugElem).toBeNull();
+ expect(listDebugElem).toBeDefined();
+ const listElem = listDebugElem.nativeElement;
+ expect(listElem).toBeDefined();
+ });
+
+ it("should filter dataservices", () => {
+ // Expect 3 dataservices initially.
+ let dataservices = component.filteredDataservices;
+ expect(dataservices.length).toEqual(3);
+
+ // Set a name filter which satisfies none of the dataservices
+ component.nameFilter = "g";
+ component.filterDataservices();
+ fixture.detectChanges();
+
+ // Now expect 0 services match
+ dataservices = component.filteredDataservices;
+ expect(dataservices.length).toEqual(0);
+ });
+
+});
diff --git a/ngapp/src/app/dataservices/dataservices.component.ts b/ngapp/src/app/dataservices/dataservices.component.ts
new file mode 100644
index 00000000..7a9a76d4
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices.component.ts
@@ -0,0 +1,252 @@
+/**
+ * @license
+ * Copyright 2017 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Component, ViewChild } from "@angular/core";
+import { ActivatedRoute, Router } from "@angular/router";
+import { Dataservice } from "@dataservices/shared/dataservice.model";
+import { DataserviceService } from "@dataservices/shared/dataservice.service";
+import { DataservicesConstants } from "@dataservices/shared/dataservices-constants";
+import { NewDataservice } from "@dataservices/shared/new-dataservice.model";
+import { LoggerService } from "@core/logger.service";
+import { ArrayUtils } from "@core/utils/array-utils";
+import { AbstractPageComponent } from "@shared/abstract-page.component";
+import { ConfirmDeleteComponent } from "@shared/confirm-delete/confirm-delete.component";
+import { IdFilter } from "@shared/id-filter";
+import { LayoutType } from "@shared/layout-type.enum";
+import { SortDirection } from "@shared/sort-direction.enum";
+
+@Component({
+ moduleId: module.id,
+ selector: "app-dataservices",
+ templateUrl: "./dataservices.component.html",
+ styleUrls: ["./dataservices.component.css"]
+})
+export class DataservicesComponent extends AbstractPageComponent {
+
+ public readonly addDataserviceLink: string = DataservicesConstants.addDataservicePath;
+
+ private allServices: Dataservice[] = [];
+ private filteredServices: Dataservice[] = [];
+ private selectedServices: Dataservice[] = [];
+ private dataserviceNameForDelete: string;
+ private router: Router;
+ private dataserviceService: DataserviceService;
+ private filter: IdFilter = new IdFilter();
+ private layout: LayoutType = LayoutType.CARD;
+ private sortDirection: SortDirection = SortDirection.ASC;
+
+ @ViewChild(ConfirmDeleteComponent) private confirmDeleteDialog: ConfirmDeleteComponent;
+
+ constructor(router: Router, route: ActivatedRoute, dataserviceService: DataserviceService, logger: LoggerService) {
+ super(route, logger);
+ this.router = router;
+ this.dataserviceService = dataserviceService;
+ }
+
+ public loadAsyncPageData(): void {
+ const self = this;
+ this.dataserviceService
+ .getAllDataservices()
+ .subscribe(
+ (dataservices) => {
+ self.allServices = dataservices;
+ self.filteredServices = this.filterDataservices();
+ self.loaded("dataservices");
+ },
+ (error) => {
+ self.logger.error("[DataservicesComponent] Error getting dataservices.");
+ self.error(error);
+ }
+ );
+ }
+
+ /**
+ * @returns {boolean} true if dataservices are being represented by cards
+ */
+ public get isCardLayout(): boolean {
+ return this.layout === LayoutType.CARD;
+ }
+
+ /**
+ * @returns {boolean} true if dataservices are being represented by items in a list
+ */
+ public get isListLayout(): boolean {
+ return this.layout === LayoutType.LIST;
+ }
+
+ /**
+ * @returns {boolean} true if sorting dataservice names in ascending order
+ */
+ public get isSortAscending(): boolean {
+ return this.sortDirection === SortDirection.ASC;
+ }
+
+ /**
+ * @returns {boolean} true if sorting dataservice names in descending order
+ */
+ public get isSortDescending(): boolean {
+ return this.sortDirection === SortDirection.DESC;
+ }
+
+ /**
+ * @returns {Dataservice[]} the array of all dataservices
+ */
+ public get allDataservices(): Dataservice[] {
+ return this.allServices;
+ }
+
+ /**
+ * @returns {Dataservice[]} the array of filtered dataservices
+ */
+ public get filteredDataservices(): Dataservice[] {
+ return this.filteredServices;
+ }
+
+ /**
+ * @returns {Dataservice[]} the array of selected dataservices
+ */
+ public get selectedDataservices(): Dataservice[] {
+ return this.selectedServices;
+ }
+
+ public onSelected(dataservice: Dataservice): void {
+ // Only allow one item to be selected
+ this.selectedServices.shift();
+ this.selectedServices.push(dataservice);
+ }
+
+ public onDeselected(dataservice: Dataservice): void {
+ // Only one item is selected at a time
+ this.selectedServices.shift();
+ // this.selectedServices.splice(this.selectedServices.indexOf(dataservice), 1);
+ }
+
+ public onDelete(svcName: string): void {
+ this.dataserviceNameForDelete = svcName;
+ this.confirmDeleteDialog.open();
+ }
+
+ public isFiltered(): boolean {
+ return this.allServices.length !== this.filteredServices.length;
+ }
+
+ public get nameFilter(): string {
+ return this.filter.getPattern();
+ }
+
+ /**
+ * @param {string} pattern the new pattern for the dataservice name filter (can be null or empty)
+ */
+ public set nameFilter( pattern: string ) {
+ this.filter.setFilter( pattern );
+ }
+
+ public toggleSortDirection(): void {
+ if (this.sortDirection === SortDirection.ASC) {
+ this.sortDirection = SortDirection.DESC;
+ } else {
+ this.sortDirection = SortDirection.ASC;
+ }
+ this.filterDataservices();
+ }
+
+ public clearFilters(): void {
+ this.filter.reset();
+ this.filterDataservices();
+ }
+
+ public setListLayout(): void {
+ this.layout = LayoutType.LIST;
+ }
+
+ public setCardLayout(): void {
+ this.layout = LayoutType.CARD;
+ }
+
+ /**
+ * Called to doDelete all selected APIs.
+ */
+ public onDeleteDataservice(): void {
+ const selectedService = this.filterDataservices().find((x) => x.getId() === this.dataserviceNameForDelete);
+
+ // const itemsToDelete: Dataservice[] = ArrayUtils.intersect(this.selectedServices, this.filteredServices);
+ // const selectedService = itemsToDelete[0];
+
+ const dataserviceToDelete: NewDataservice = new NewDataservice();
+ dataserviceToDelete.setId(selectedService.getId());
+
+ // Note: we can only doDelete selected items that we can see in the UI.
+ this.logger.log("[DataservicesPageComponent] Deleting selected Dataservice.");
+ const self = this;
+ this.dataserviceService
+ .deleteDataservice(dataserviceToDelete)
+ .subscribe(
+ () => {
+ self.removeDataserviceFromList(selectedService);
+ const link: string[] = [ DataservicesConstants.dataservicesRootPath ];
+ self.logger.log("[CreateApiPageComponent] Navigating to: %o", link);
+ self.router.navigate(link).then(() => {
+ // nothing to do
+ });
+ }
+ );
+ }
+
+ /**
+ * Filters and sorts the list of dataservices based on the user input
+ */
+ public filterDataservices(): Dataservice[] {
+ // Clear the array first.
+ this.filteredServices.splice(0, this.filteredServices.length);
+ for (const dataservice of this.allServices) {
+ if (this.filter.accepts(dataservice)) {
+ this.filteredServices.push(dataservice);
+ }
+ }
+ this.filteredServices.sort( (c1: Dataservice, c2: Dataservice) => {
+ let rval = 0;
+
+ if ( c1.getId() ) {
+ if ( c2.getId() ) {
+ // both dataservices have an ID
+ rval = c1.getId().localeCompare( c2.getId() );
+ } else {
+ // c2 does not have an ID
+ rval = 1;
+ }
+ } else if ( c2.getId() ) {
+ // c1 does not have an ID and c2 does
+ rval = -1;
+ }
+
+ if ( this.sortDirection === SortDirection.DESC ) {
+ rval *= -1;
+ }
+
+ return rval;
+ });
+
+ this.selectedServices = ArrayUtils.intersect(this.selectedServices, this.filteredServices);
+
+ return this.filteredServices;
+ }
+
+ private removeDataserviceFromList(dataservice: Dataservice): void {
+ this.allServices.splice(this.allServices.indexOf(dataservice), 1);
+ this.filterDataservices();
+ }
+}
diff --git a/ngapp/src/app/dataservices/dataservices.module.ts b/ngapp/src/app/dataservices/dataservices.module.ts
new file mode 100644
index 00000000..b9e91610
--- /dev/null
+++ b/ngapp/src/app/dataservices/dataservices.module.ts
@@ -0,0 +1,59 @@
+/**
+ * @license
+ * Copyright 2017 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { FormsModule, ReactiveFormsModule } from "@angular/forms";
+import { RouterModule } from "@angular/router";
+import { DataservicesCardsComponent } from "@dataservices/dataservices-cards/dataservices-cards.component";
+import { DataservicesListComponent } from "@dataservices/dataservices-list/dataservices-list.component";
+import { DataservicesRoutingModule } from "@dataservices/dataservices-routing.module";
+import { DataservicesComponent } from "@dataservices/dataservices.component";
+import { DataserviceService } from "@dataservices/shared/dataservice.service";
+import { CoreModule } from "@core/core.module";
+import { SharedModule } from "@shared/shared.module";
+import { PatternFlyNgModule } from "patternfly-ng";
+import { AddDataserviceWizardComponent } from "./add-dataservice-wizard/add-dataservice-wizard.component";
+import { AddDataserviceComponent } from "./add-dataservice/add-dataservice.component";
+import { LoggerService } from "@core/logger.service";
+
+@NgModule({
+ imports: [
+ DataservicesRoutingModule,
+ CommonModule,
+ CoreModule,
+ SharedModule,
+ FormsModule,
+ ReactiveFormsModule,
+ RouterModule,
+ PatternFlyNgModule
+ ],
+ declarations: [
+ DataservicesCardsComponent,
+ DataservicesComponent,
+ DataservicesListComponent,
+ AddDataserviceWizardComponent,
+ AddDataserviceComponent
+ ],
+ providers: [
+ DataserviceService,
+ LoggerService
+ ],
+ exports: [
+ ]
+})
+export class DataservicesModule { }
diff --git a/ngapp/src/app/dataservices/shared/dataservice.model.ts b/ngapp/src/app/dataservices/shared/dataservice.model.ts
new file mode 100644
index 00000000..53f473bc
--- /dev/null
+++ b/ngapp/src/app/dataservices/shared/dataservice.model.ts
@@ -0,0 +1,89 @@
+/**
+ * @license
+ * Copyright 2017 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Identifiable } from "@shared/identifiable";
+
+export class Dataservice implements Identifiable< string > {
+
+ private keng__id: string;
+ private tko__description: string;
+
+ /**
+ * @param {Object} json the JSON representation of a Dataservice
+ * @returns {Dataservice} the new Dataservice (never null)
+ */
+ public static create( json: object = {} ): Dataservice {
+ const svc = new Dataservice();
+ svc.setValues( json );
+ return svc;
+ }
+
+ constructor() {
+ // nothing to do
+ }
+
+ /**
+ * @returns {string} the dataservice identifier (can be null)
+ */
+ public getId(): string {
+ return this.keng__id;
+ }
+
+ /**
+ * @returns {string} the dataservice description (can be null)
+ */
+ public getDescription(): string {
+ return this.tko__description;
+ }
+
+ /**
+ * @returns {string} the dataservice dataPath (can be null)
+ */
+ public getDataPath(): string {
+ return "/tko:komodo/tko:workspace/dsbUser/" + this.keng__id;
+ }
+
+ /**
+ * @returns {string} the dataservice type name (can be null)
+ */
+ public getType(): string {
+ return "Dataservice";
+ }
+
+ /**
+ * @param {string} id the dataservice identifier (optional)
+ */
+ public setId( id?: string ): void {
+ this.keng__id = id ? id : null;
+ }
+
+ /**
+ * @param {string} id the dataservice description (optional)
+ */
+ public setDescription( description?: string ): void {
+ this.tko__description = description ? description : null;
+ }
+
+ /**
+ * Set all object values using the supplied Dataservice json
+ * @param {Object} values
+ */
+ public setValues(values: object = {}): void {
+ Object.assign(this, values);
+ }
+
+}
diff --git a/ngapp/src/app/dataservices/shared/dataservice.service.spec.ts b/ngapp/src/app/dataservices/shared/dataservice.service.spec.ts
new file mode 100644
index 00000000..ea4f4099
--- /dev/null
+++ b/ngapp/src/app/dataservices/shared/dataservice.service.spec.ts
@@ -0,0 +1,18 @@
+import { inject, TestBed } from "@angular/core/testing";
+import { HttpModule } from "@angular/http";
+import { DataserviceService } from "@dataservices/shared/dataservice.service";
+import { LoggerService } from "@core/logger.service";
+
+describe("DataserviceService", () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [ HttpModule ],
+ providers: [DataserviceService, LoggerService]
+ });
+ });
+
+ it("should be created", inject([DataserviceService, LoggerService],
+ ( service: DataserviceService ) => {
+ expect(service).toBeTruthy();
+ }));
+});
diff --git a/ngapp/src/app/dataservices/shared/dataservice.service.ts b/ngapp/src/app/dataservices/shared/dataservice.service.ts
new file mode 100644
index 00000000..2d564259
--- /dev/null
+++ b/ngapp/src/app/dataservices/shared/dataservice.service.ts
@@ -0,0 +1,80 @@
+/**
+ * @license
+ * Copyright 2017 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Injectable } from "@angular/core";
+import { Http } from "@angular/http";
+import { Dataservice } from "@dataservices/shared/dataservice.model";
+import { DataservicesConstants } from "@dataservices/shared/dataservices-constants";
+import { NewDataservice } from "@dataservices/shared/new-dataservice.model";
+import { ApiService } from "@core/api.service";
+import { LoggerService } from "@core/logger.service";
+import { environment } from "@environments/environment";
+import { Observable } from "rxjs/Observable";
+
+@Injectable()
+export class DataserviceService extends ApiService {
+
+ private http: Http;
+
+ constructor( http: Http, logger: LoggerService ) {
+ super( logger );
+ this.http = http;
+ }
+
+ /**
+ * Get the dataservices from the komodo rest interface
+ * @returns {Observable}
+ */
+ public getAllDataservices(): Observable {
+ return this.http
+ .get(environment.komodoWorkspaceUrl + DataservicesConstants.dataservicesRootPath, this.getAuthRequestOptions())
+ .map((response) => {
+ const dataservices = response.json();
+ return dataservices.map((dataservice) => Dataservice.create( dataservice ));
+ })
+ .catch( ( error ) => this.handleError( error ) );
+ }
+
+ /**
+ * Create a dataservice via the komodo rest interface
+ * @param {NewDataservice} dataservice
+ * @returns {Observable}
+ */
+ public createDataservice(dataservice: NewDataservice): Observable {
+ return this.http
+ .post(environment.komodoWorkspaceUrl + DataservicesConstants.dataservicesRootPath + "/" + dataservice.getId(),
+ dataservice, this.getAuthRequestOptions())
+ .map((response) => {
+ return new Dataservice();
+ })
+ .catch( ( error ) => this.handleError( error ) );
+ }
+
+ /**
+ * Delete a dataservice via the komodo rest interface
+ * @param {NewDataservice} dataservice
+ * @returns {Observable}
+ */
+ public deleteDataservice(dataservice: NewDataservice): Observable {
+ return this.http
+ .delete(environment.komodoWorkspaceUrl + DataservicesConstants.dataservicesRootPath + "/" + dataservice.getId(),
+ this.getAuthRequestOptions())
+ .map((response) => null)
+ .catch( ( error ) => this.handleError( error ) );
+ }
+
+}
diff --git a/ngapp/src/app/dataservices/shared/dataservices-constants.ts b/ngapp/src/app/dataservices/shared/dataservices-constants.ts
new file mode 100644
index 00000000..3c99d8f4
--- /dev/null
+++ b/ngapp/src/app/dataservices/shared/dataservices-constants.ts
@@ -0,0 +1,20 @@
+/**
+ * @license
+ * Copyright 2017 JBoss Inc
+ *
+ * Licensed under the Apache License, /
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export class DataservicesConstants {
+
+ public static readonly dataservicesRootRoute = "dataservices";
+ public static readonly dataservicesRootPath = "/" + DataservicesConstants.dataservicesRootRoute;
+
+ public static readonly addDataserviceRoute = DataservicesConstants.dataservicesRootRoute + "/add-dataservice";
+ public static readonly addDataservicePath = DataservicesConstants.dataservicesRootPath + "/add-dataservice";
+}
diff --git a/ngapp/src/app/dataservices/shared/mock-dataservice.service.ts b/ngapp/src/app/dataservices/shared/mock-dataservice.service.ts
new file mode 100644
index 00000000..2a85806c
--- /dev/null
+++ b/ngapp/src/app/dataservices/shared/mock-dataservice.service.ts
@@ -0,0 +1,55 @@
+import { Injectable } from "@angular/core";
+import { Http } from "@angular/http";
+import { Dataservice } from "@dataservices/shared/dataservice.model";
+import { DataserviceService } from "@dataservices/shared/dataservice.service";
+import { NewDataservice } from "@dataservices/shared/new-dataservice.model";
+import { LoggerService } from "@core/logger.service";
+import "rxjs/add/observable/of";
+import "rxjs/add/observable/throw";
+import "rxjs/add/operator/catch";
+import "rxjs/add/operator/map";
+import { Observable } from "rxjs/Observable";
+
+@Injectable()
+export class MockDataserviceService extends DataserviceService {
+
+ private newDataservice = new NewDataservice();
+ private serv1 = new Dataservice();
+ private serv2 = new Dataservice();
+ private serv3 = new Dataservice();
+ private services: Dataservice[] = [this.serv1, this.serv2, this.serv3];
+
+ constructor( http: Http, logger: LoggerService ) {
+ super(http, logger);
+ this.serv1.setId("serv1");
+ this.serv2.setId("serv2");
+ this.serv3.setId("serv3");
+ }
+
+ /**
+ * Get the dataservices from the komodo rest interface
+ * @returns {Observable}
+ */
+ public getAllDataservices(): Observable {
+ return Observable.of(this.services);
+ }
+
+ /**
+ * Create a dataservice via the komodo rest interface
+ * @param {NewDataservice} dataservice
+ * @returns {Observable}
+ */
+ public createDataservice(dataservice: NewDataservice): Observable {
+ return Observable.of(this.newDataservice);
+ }
+
+ /**
+ * Delete a dataservice via the komodo rest interface
+ * @param {NewDataservice} dataservice
+ * @returns {Observable}
+ */
+ public deleteDataservice(dataservice: NewDataservice): Observable {
+ return Observable.of(this.newDataservice);
+ }
+
+}
diff --git a/ngapp/src/app/dataservices/shared/new-dataservice.model.ts b/ngapp/src/app/dataservices/shared/new-dataservice.model.ts
new file mode 100644
index 00000000..499b6c27
--- /dev/null
+++ b/ngapp/src/app/dataservices/shared/new-dataservice.model.ts
@@ -0,0 +1,60 @@
+/**
+ * @license
+ * Copyright 2017 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export class NewDataservice {
+
+ private keng__id: string;
+ private keng__dataPath: string;
+ private keng__kType: string;
+ private tko__description: string;
+
+ /**
+ * Constructor
+ */
+ constructor() {
+ this.keng__kType = "Dataservice";
+ }
+
+ /**
+ * @returns {string} the dataservice name (can be null)
+ */
+ public getId(): string {
+ return this.keng__id;
+ }
+
+ /**
+ * @returns {string} the dataservice description (can be null)
+ */
+ public getDescription(): string {
+ return this.tko__description;
+ }
+
+ /**
+ * @param {string} name the dataservice name
+ */
+ public setId( name: string ): void {
+ this.keng__id = name;
+ this.keng__dataPath = "/tko:komodo/tko:workspace/dsbUser/" + name;
+ }
+
+ /**
+ * @param {string} description the dataservice description (optional)
+ */
+ public setDescription( description?: string ): void {
+ this.tko__description = description ? description : null;
+ }
+}
diff --git a/ngapp/tsconfig.json b/ngapp/tsconfig.json
index 107cad33..ca20e4b5 100644
--- a/ngapp/tsconfig.json
+++ b/ngapp/tsconfig.json
@@ -7,6 +7,7 @@
"@app/*": ["app/*"],
"@connections/*": ["app/connections/*"],
"@core/*": ["app/core/*"],
+ "@dataservices/*": ["app/dataservices/*"],
"@environments/*": ["environments/*"],
"@shared/*": ["app/shared/*"]
},