Moves API methods to reusable library.

This commit is contained in:
Aaron Louie 2020-01-15 12:16:57 -05:00
parent 8121ec1796
commit e74e1c309a
10 changed files with 30 additions and 132 deletions

View File

@ -115,7 +115,7 @@
"src/assets"
],
"codeCoverageExclude": [
"src/testing/mocks/*.ts",
"src/testing/**/*",
"src/app/_interfaces/*.ts",
"src/polyfills.ts",
"src/test.ts"

6
package-lock.json generated
View File

@ -9917,9 +9917,9 @@
"dev": true
},
"sartography-workflow-lib": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.5.tgz",
"integrity": "sha512-1hcYDfwCaCWz9Oed1mcGc/whIcXZ/+FMm3+SNbTJ3rzgCMdfFhAM97MgV+eLKHz2TuoEy2hyRF77qhx4kD+9NQ==",
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.8.tgz",
"integrity": "sha512-0fOCHoLUWuMh828iXJVUlADiMCNdU/WBihJ9DCvFbdU24qvuKklAXxgF9a7pu3CrCHPTajNrL7pfAbjSUwx21w==",
"requires": {
"tslib": "^1.9.0"
}

View File

@ -41,7 +41,7 @@
"file-saver": "^2.0.2",
"hammerjs": "^2.0.8",
"rxjs": "~6.5.4",
"sartography-workflow-lib": "0.0.5",
"sartography-workflow-lib": "^0.0.8",
"tslib": "^1.10.0",
"zone.js": "~0.9.1"
},

View File

@ -1,23 +0,0 @@
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {TestBed} from '@angular/core/testing';
import {ApiService} from './api.service';
describe('ApiService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [ApiService]
});
});
afterEach(() => {
const httpMock = TestBed.get(HttpTestingController);
httpMock.verify();
});
it('should be created', () => {
const service: ApiService = TestBed.get(ApiService);
expect(service).toBeTruthy();
});
});

View File

@ -1,97 +0,0 @@
import {HttpClient, HttpParams} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable, throwError} from 'rxjs';
import {catchError} from 'rxjs/operators';
import {environment} from '../../environments/environment';
import {WorkflowSpec} from 'sartography-workflow-lib';
import {FileMeta} from 'sartography-workflow-lib';
export interface ApiError {
code: string;
message: string;
}
@Injectable({
providedIn: 'root'
})
export class ApiService {
apiUrl: string = environment.api;
constructor(private httpClient: HttpClient) {
}
listWorkflowSpecifications(): Observable<WorkflowSpec[]> {
const url = this.apiUrl + '/workflow-specification';
return this.httpClient
.get<WorkflowSpec[]>(url)
.pipe(catchError(this._handleError));
}
addWorkflowSpecification(newSpec: WorkflowSpec): Observable<WorkflowSpec> {
const url = this.apiUrl + '/workflow-specification';
return this.httpClient
.post<WorkflowSpec>(url, newSpec)
.pipe(catchError(this._handleError));
}
updateWorkflowSpecification(specId: string, newSpec: WorkflowSpec): Observable<WorkflowSpec> {
const url = this.apiUrl + '/workflow-specification/' + specId;
return this.httpClient
.post<WorkflowSpec>(url, newSpec)
.pipe(catchError(this._handleError));
}
listBpmnFiles(specId: string): Observable<FileMeta[]> {
const url = this.apiUrl + '/file';
const params = new HttpParams().set('spec_id', specId);
return this.httpClient
.get<FileMeta[]>(url, {params: params})
.pipe(catchError(this._handleError));
}
getFileData(fileId: number): Observable<Blob> {
const url = this.apiUrl + '/file/' + fileId + '/data';
return this.httpClient
.get(url, {responseType: 'blob'})
.pipe(catchError(this._handleError));
}
addFileMeta(specId: string, fileMeta: FileMeta): Observable<FileMeta> {
const url = this.apiUrl + '/file';
const params = new HttpParams().set('spec_id', specId);
const formData = new FormData();
formData.append('workflow_spec_id', fileMeta.workflow_spec_id);
formData.append('file', fileMeta.file);
return this.httpClient
.post<FileMeta>(url, formData, {params: params})
.pipe(catchError(this._handleError));
}
updateFileMeta(fileMeta: FileMeta): Observable<FileMeta> {
const url = this.apiUrl + '/file/' + fileMeta.id;
const formData = new FormData();
formData.append('workflow_spec_id', fileMeta.workflow_spec_id);
formData.append('file', fileMeta.file);
return this.httpClient
.put<FileMeta>(url, formData)
.pipe(catchError(this._handleError));
}
getBpmnXml(url: string): Observable<string> {
return this.httpClient
.get(url, {responseType: 'text'})
.pipe(catchError(this._handleError));
}
private _handleError(error: ApiError) {
return throwError(error.message || 'Could not complete your request; please try again later.');
}
}

View File

@ -12,6 +12,7 @@ import {MatSnackBarModule} from '@angular/material/snack-bar';
import {MatToolbarModule} from '@angular/material/toolbar';
import {MatTooltipModule} from '@angular/material/tooltip';
import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations';
import {ApiService, MockEnvironment} from 'sartography-workflow-lib';
import {BPMN_DIAGRAM, BPMN_DIAGRAM_WITH_WARNINGS} from '../testing/mocks/diagram.mocks';
import {BpmnWarning} from './_interfaces/bpmn-warning';
import {AppComponent} from './app.component';
@ -43,7 +44,12 @@ describe('AppComponent', () => {
ReactiveFormsModule,
MatFormFieldModule,
HttpClientTestingModule,
],
providers: [
ApiService,
{provide: 'APP_ENVIRONMENT', useClass: MockEnvironment}
]
}).compileComponents();
httpMock = TestBed.get(HttpTestingController);
fixture = TestBed.createComponent(AppComponent);

View File

@ -2,11 +2,10 @@ import {DatePipe} from '@angular/common';
import {AfterViewInit, Component, ViewChild} from '@angular/core';
import {MatDialog, MatDialogRef} from '@angular/material/dialog';
import {MatSnackBar} from '@angular/material/snack-bar';
import {FileMeta, FileType, WorkflowSpec} from 'sartography-workflow-lib';
import {FileMeta, FileType, WorkflowSpec, ApiService} from 'sartography-workflow-lib';
import {BpmnWarning} from './_interfaces/bpmn-warning';
import {ImportEvent} from './_interfaces/import-event';
import {NewFileDialogData} from './_interfaces/new-file-dialog-data';
import {ApiService} from './_services/api.service';
import {DiagramComponent} from './diagram/diagram.component';
import {NewFileDialogComponent} from './new-file-dialog/new-file-dialog.component';
@ -147,7 +146,7 @@ export class AppComponent implements AfterViewInit {
}
private loadFilesFromDb() {
this.api.listWorkflowSpecifications().subscribe(wfs => {
this.api.getWorkflowSpecList().subscribe(wfs => {
this.workflowSpecs = wfs;
this.workflowSpecs.forEach(w => {
this.api.listBpmnFiles(w.id).subscribe(files => {

View File

@ -14,10 +14,19 @@ import {MatToolbarModule} from '@angular/material/toolbar';
import {MatTooltipModule} from '@angular/material/tooltip';
import {BrowserModule} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {AppEnvironment} from 'sartography-workflow-lib';
import {environment} from '../environments/environment';
import {AppComponent} from './app.component';
import {DiagramComponent} from './diagram/diagram.component';
import { NewFileDialogComponent } from './new-file-dialog/new-file-dialog.component';
class ThisEnvironment implements AppEnvironment {
production = environment.production;
api = environment.api;
googleAnalyticsKey = environment.googleAnalyticsKey;
irbUrl = environment.irbUrl;
}
@NgModule({
declarations: [
AppComponent,
@ -44,6 +53,7 @@ import { NewFileDialogComponent } from './new-file-dialog/new-file-dialog.compon
],
bootstrap: [AppComponent],
entryComponents: [NewFileDialogComponent],
providers: [{provide: 'APP_ENVIRONMENT', useClass: ThisEnvironment}]
})
export class AppModule {
}

View File

@ -4,8 +4,8 @@ import {DebugNode} from '@angular/core';
import {async, ComponentFixture, getTestBed, TestBed} from '@angular/core/testing';
import {MatIconModule} from '@angular/material/icon';
import * as FileSaver from 'file-saver';
import {ApiService, MockEnvironment} from 'sartography-workflow-lib';
import {BPMN_DIAGRAM, BPMN_DIAGRAM_WITH_WARNINGS} from '../../testing/mocks/diagram.mocks';
import {ApiService} from '../_services/api.service';
import {DiagramComponent} from './diagram.component';
@ -24,7 +24,10 @@ describe('DiagramComponent', () => {
MatIconModule,
],
declarations: [DiagramComponent],
providers: [ApiService]
providers: [
ApiService,
{provide: 'APP_ENVIRONMENT', useClass: MockEnvironment}
]
});
fixture = TestBed.createComponent(DiagramComponent);

View File

@ -8,9 +8,9 @@ import * as camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda.
import minimapModule from 'diagram-js-minimap';
import * as fileSaver from 'file-saver';
import {ApiService} from 'sartography-workflow-lib';
import {BpmnWarning} from '../_interfaces/bpmn-warning';
import {ImportEvent} from '../_interfaces/import-event';
import {ApiService} from '../_services/api.service';
@Component({
selector: 'app-diagram',
@ -146,7 +146,7 @@ export class DiagramComponent implements ControlValueAccessor, AfterViewInit {
* Load diagram from URL and emit completion event
*/
loadUrl(url: string) {
this.api.getBpmnXml(url).subscribe(xml => {
this.api.getStringFromUrl(url).subscribe(xml => {
this.openDiagram(xml);
}, error => this._handleErrors(error));
}