Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(integrations): create integration
- Loading branch information
1 parent
2ead07e
commit 91fbf33
Showing
19 changed files
with
1,105 additions
and
0 deletions.
There are no files selected for viewing
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
gravitee-apim-console-webui/src/entities/integrations/integration.fixture.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Integration } from '../../management/integrations/integrations.model'; | ||
|
||
export function fakeIntegration(attribute?: Partial<Integration>) { | ||
const base: Integration = { | ||
id: 'test_id', | ||
name: 'test_name', | ||
description: 'test_description', | ||
provider: 'test_provider', | ||
owner: 'test_owner', | ||
status: 'test_status', | ||
agent: 'test_agent', | ||
} | ||
|
||
return { | ||
...base, | ||
...attribute | ||
} | ||
} |
107 changes: 107 additions & 0 deletions
107
...le-webui/src/management/integrations/create-integration/create-integration.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
<!-- | ||
Copyright (C) 2015 The Gravitee team (http://gravitee.io) | ||
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. | ||
--> | ||
|
||
<div> | ||
<div class="page-header"> | ||
<h1>Integrations</h1> | ||
<span class="page-header__description">Connect to third-party API gateways and event brokers to create a unified control plane and API portal with | ||
Gravitee</span> | ||
</div> | ||
|
||
|
||
<mat-card> | ||
<mat-card-content> | ||
<div class="card-header"> | ||
<div class="card-header__title"> | ||
<h3>Create Integration</h3> | ||
</div> | ||
|
||
<div class="card-header__actions"> | ||
<button | ||
mat-raised-button | ||
[disabled]="false" | ||
data-testid="exit-create-integration-button" | ||
routerLink=".." | ||
> | ||
<mat-icon svgIcon="gio:cancel"></mat-icon> | ||
Exit without saving | ||
</button> | ||
</div> | ||
</div> | ||
|
||
|
||
<form [formGroup]="informationForm" class="form" (ngSubmit)="onSubmit()"> | ||
<div class="form__body"> | ||
<mat-card class="form-card"> | ||
<mat-card-content> | ||
<div> | ||
<h5>General Information</h5> | ||
<p class="info">Enter the general information for this new integration.</p> | ||
</div> | ||
<div> | ||
<mat-form-field appearance="outline" class="form-field"> | ||
<input | ||
id="name" | ||
type="text" | ||
matInput | ||
formControlName="name" | ||
required="true" | ||
data-testid="create-integration-name-input" | ||
/> | ||
<mat-label>Name</mat-label> | ||
<mat-error *ngIf="informationForm.controls.name.errors?.required">Name is required</mat-error> | ||
</mat-form-field> | ||
</div> | ||
<div> | ||
<mat-form-field appearance="outline" class="form-field"> | ||
<textarea | ||
id="description" | ||
matInput #input | ||
maxlength="250" | ||
formControlName="description" | ||
rows="2" | ||
data-testid="create-integration-description" | ||
></textarea> | ||
<mat-label>Description</mat-label> | ||
<mat-hint align="start">{{ input.value.length }}/250</mat-hint> | ||
</mat-form-field> | ||
</div> | ||
</mat-card-content> | ||
</mat-card> | ||
</div> | ||
|
||
<div class="form__actions"> | ||
<button | ||
mat-flat-button | ||
[disabled]="true" | ||
data-testid="back-create-integration-button" | ||
routerLink=".." | ||
> | ||
Back | ||
</button> | ||
|
||
<button | ||
type="submit" | ||
mat-raised-button | ||
color="primary" | ||
data-testid="create-integration-submit-button" | ||
[disabled]="!informationForm.valid" | ||
> | ||
Create Integration | ||
</button> | ||
</div> | ||
</form> | ||
|
||
</mat-card-content> | ||
</mat-card> | ||
</div> |
81 changes: 81 additions & 0 deletions
81
...le-webui/src/management/integrations/create-integration/create-integration.component.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* | ||
* Copyright (C) 2015 The Gravitee team (http://gravitee.io) | ||
* | ||
* 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. | ||
*/ | ||
|
||
@use '@angular/material' as mat; | ||
@use '@gravitee/ui-particles-angular' as gio; | ||
@use '../../../scss/gio-layout' as gio-layout; | ||
|
||
:host { | ||
@include gio-layout.gio-responsive-content-container | ||
} | ||
|
||
.page-header { | ||
margin-bottom: 24px; | ||
|
||
&__description { | ||
color: mat.get-color-from-palette(gio.$mat-space-palette, 'lighter40'); | ||
} | ||
} | ||
|
||
.card-header { | ||
display: flex; | ||
justify-content: space-between; | ||
padding-bottom: 24px; | ||
|
||
&__title { | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: center; | ||
|
||
h3 { | ||
margin: 0; | ||
} | ||
} | ||
} | ||
|
||
.form { | ||
&__body { | ||
display: flex; | ||
justify-content: center; | ||
padding: 24px 0; | ||
|
||
.mat-mdc-card { | ||
width: 600px; | ||
border: 1px solid var(--Dove-Darker10, #E7E8EF); | ||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.20); | ||
} | ||
} | ||
|
||
&__actions { | ||
display: flex; | ||
justify-content: space-between; | ||
padding-top: 24px; | ||
} | ||
|
||
.form-field { | ||
width: 100%; | ||
} | ||
} | ||
|
||
textarea { | ||
resize: none; | ||
} | ||
|
||
.info { | ||
color: mat.get-color-from-palette(gio.$mat-space-palette, 'lighter40'); | ||
} | ||
|
||
|
78 changes: 78 additions & 0 deletions
78
...webui/src/management/integrations/create-integration/create-integration.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Copyright (C) 2015 The Gravitee team (http://gravitee.io) | ||
* | ||
* 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 { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations'; | ||
import { HttpTestingController } from '@angular/common/http/testing'; | ||
import { InteractivityChecker } from '@angular/cdk/a11y'; | ||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; | ||
|
||
|
||
import { CreateIntegrationComponent } from './create-integration.component'; | ||
import { CreateIntegrationHarness } from './create-integration.harness'; | ||
|
||
import { IntegrationsModule } from '../integrations.module'; | ||
import { CONSTANTS_TESTING, GioTestingModule } from '../../../shared/testing'; | ||
|
||
describe('CreateIntegrationComponent', () => { | ||
let fixture: ComponentFixture<CreateIntegrationComponent>; | ||
let componentHarness: CreateIntegrationHarness; | ||
let httpTestingController: HttpTestingController; | ||
|
||
beforeEach(async () => { | ||
await TestBed.configureTestingModule({ | ||
declarations: [CreateIntegrationComponent], | ||
imports: [GioTestingModule, IntegrationsModule, BrowserAnimationsModule, NoopAnimationsModule] | ||
}) | ||
.overrideProvider(InteractivityChecker, { | ||
useValue: { | ||
isFocusable: () => true, // This traps focus checks and so avoid warnings when dealing with | ||
isTabbable: () => true // This traps focus checks and so avoid warnings when dealing with | ||
} | ||
}) | ||
.compileComponents(); | ||
}); | ||
|
||
beforeEach(async () => { | ||
fixture = TestBed.createComponent(CreateIntegrationComponent); | ||
httpTestingController = TestBed.inject(HttpTestingController); | ||
componentHarness = await TestbedHarnessEnvironment.harnessForFixture(fixture, CreateIntegrationHarness); | ||
fixture.detectChanges(); | ||
}); | ||
|
||
afterEach(() => { | ||
httpTestingController.verify(); | ||
}); | ||
|
||
describe('form', () => { | ||
it('should not submit empty form', async () => { | ||
await componentHarness.clickOnSubmit(); | ||
httpTestingController.expectNone(`${CONSTANTS_TESTING.env.v2BaseURL}/integrations`); | ||
}); | ||
|
||
it('should create integration with valid form', async () => { | ||
await componentHarness.setName('TEST123'); | ||
await componentHarness.clickOnSubmit(); | ||
expectIntegrationPostRequest(); | ||
}) | ||
}); | ||
|
||
function expectIntegrationPostRequest(): void { | ||
const req = httpTestingController.expectOne(`${CONSTANTS_TESTING.env.v2BaseURL}/integrations`); | ||
req.flush([]); | ||
expect(req.request.method).toEqual('POST'); | ||
} | ||
}); |
78 changes: 78 additions & 0 deletions
78
...sole-webui/src/management/integrations/create-integration/create-integration.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Copyright (C) 2015 The Gravitee team (http://gravitee.io) | ||
* | ||
* 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, DestroyRef, inject } from '@angular/core'; | ||
import { ActivatedRoute, Router } from '@angular/router'; | ||
import { FormBuilder, Validators } from '@angular/forms'; | ||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; | ||
import { catchError, tap } from 'rxjs/operators'; | ||
import { EMPTY } from 'rxjs'; | ||
|
||
import { CreateIntegrationPayload } from '../integrations.model'; | ||
import { IntegrationsService } from '../../../services-ngx/integrations.service'; | ||
import { SnackBarService } from '../../../services-ngx/snack-bar.service'; | ||
|
||
@Component({ | ||
selector: 'app-create-integration', | ||
templateUrl: './create-integration.component.html', | ||
styleUrls: ['./create-integration.component.scss'] | ||
}) | ||
export class CreateIntegrationComponent { | ||
public isLoading = false; | ||
private destroyRef = inject(DestroyRef); | ||
|
||
public informationForm = this.formBuilder.group({ | ||
name: ['', Validators.minLength(1)], | ||
description: [''] | ||
}); | ||
|
||
constructor( | ||
private integrationsService: IntegrationsService, | ||
private formBuilder: FormBuilder, | ||
private readonly router: Router, | ||
private activatedRoute: ActivatedRoute, | ||
private snackBarService: SnackBarService | ||
) { | ||
} | ||
|
||
public onSubmit(): void { | ||
const payload: CreateIntegrationPayload = { | ||
name: this.informationForm.controls.name.getRawValue(), | ||
description: this.informationForm.controls.description.getRawValue(), | ||
provider: 'AWS' | ||
}; | ||
|
||
this.isLoading = true; | ||
this.integrationsService | ||
.createIntegration(payload) | ||
.pipe( | ||
tap(() => { | ||
this.isLoading = false; | ||
this.snackBarService.success(`Integration ${payload.name} created successfully`); | ||
}), | ||
catchError((_) => { | ||
this.isLoading = false; | ||
this.snackBarService.error('An error occurred. Integration not created'); | ||
return EMPTY; | ||
}), | ||
takeUntilDestroyed(this.destroyRef) | ||
) | ||
.subscribe(() => { | ||
this.isLoading = false; | ||
this.router.navigate(['..'], { relativeTo: this.activatedRoute }); | ||
}); | ||
} | ||
} |
Oops, something went wrong.