Merge pull request #40 from sartography/testing

Testing --> Staging
This commit is contained in:
Aaron Louie 2020-06-15 17:15:48 -04:00 committed by GitHub
commit c6d728b90d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 212 additions and 235 deletions

View File

@ -32,6 +32,6 @@ RUN echo "pushstate: enabled" > /etc/nginx/html/Staticfile
# then starts/reloads nginx. # then starts/reloads nginx.
ENTRYPOINT ["./entrypoint.sh", \ ENTRYPOINT ["./entrypoint.sh", \
"/etc/nginx/html/index.html,/etc/nginx/conf.d/default.conf", \ "/etc/nginx/html/index.html,/etc/nginx/conf.d/default.conf", \
"PRODUCTION,API_URL,IRB_URL,HOME_ROUTE,BASE_HREF,DEPLOY_URL,PORT0", \ "PRODUCTION,API_URL,IRB_URL,HOME_ROUTE,BASE_HREF,DEPLOY_URL,PORT0,GOOGLE_ANALYTICS_KEY,SENTRY_KEY,TITLE", \
"/etc/nginx/html", \ "/etc/nginx/html", \
"true"] "true"]

View File

@ -1,14 +1,20 @@
version: "3.3" version: "3.3"
services: services:
ldap:
container_name: ldap
image: tuxmonteiro/ldap-mock
ports:
- "3890:3890"
db: db:
container_name: db container_name: db
image: sartography/cr-connect-db:dev image: sartography/cr-connect-db:$E2E_TAG
ports: ports:
- "5432:5432" - "5432:5432"
environment: environment:
- POSTGRES_USER=rrt_user - POSTGRES_USER=crc_user
- POSTGRES_PASSWORD=rrt_pass - POSTGRES_PASSWORD=crc_pass
- POSTGRES_MULTIPLE_DATABASES=rrt - POSTGRES_MULTIPLE_DATABASES=crc_test,pb_test
healthcheck: healthcheck:
test: ["CMD", "pg_isready"] test: ["CMD", "pg_isready"]
timeout: 20s timeout: 20s
@ -18,52 +24,73 @@ services:
container_name: backend container_name: backend
depends_on: depends_on:
- db - db
image: sartography/cr-connect-workflow:dev image: sartography/cr-connect-workflow:$E2E_TAG
environment: environment:
- APPLICATION_ROOT=/api - APPLICATION_ROOT=/
- CORS_ALLOW_ORIGINS=localhost:5002,bpmn:5002,localhost:4200,frontend:4200 - CORS_ALLOW_ORIGINS=localhost:5002,bpmn:5002,localhost:4200,frontend:4200
- DB_HOST=db - DB_HOST=db
- DB_NAME=rrt - DB_NAME=crc_test
- DB_PASSWORD=rrt_pass - DB_PASSWORD=crc_pass
- DB_PORT=5432 - DB_PORT=5432
- DB_USER=rrt_user - DB_USER=crc_user
- LDAP_URL=ldap.virginia.edu - LDAP_URL=ldap
- PB_ENABLED=false - PB_ENABLED=true
- PB_BASE_URL=http://pb:5001/v2.0/
- PORT0=5000 - PORT0=5000
- RESET_DB=true - RESET_DB=true
- UPGRADE_DB=true - UPGRADE_DB=true
- TESTING=true
ports: ports:
- "5000:5000" - "5000:5000"
command: ./wait-for-it.sh db:5432 -t 0 -- ./docker_run.sh command: ./wait-for-it.sh db:5432 -t 0 -- ./docker_run.sh
bpmn: pb:
container_name: bpmn container_name: pb
depends_on: depends_on:
- db - db
- backend image: sartography/protocol-builder-mock:$E2E_TAG
image: sartography/cr-connect-bpmn:dev
environment: environment:
- API_URL=http://localhost:5000/api/v1.0 - APPLICATION_ROOT=/
- BASE_HREF=/bpmn/ - CORS_ALLOW_ORIGINS=localhost:5000,backend:5000,localhost:5002,bpmn:5002,localhost:4200,frontend:4200
- DEPLOY_URL=/bpmn/ - DB_HOST=db
- HOME_ROUTE=home - DB_NAME=pb_test
- PORT0=5002 - DB_PASSWORD=crc_pass
- PRODUCTION=false - DB_PORT=5432
- DB_USER=crc_user
- PORT0=5001
- UPGRADE_DB=true
ports: ports:
- "5002:5002" - "5001:5001"
command: ./wait-for-it.sh db:5432 -t 0 -- ./docker_run.sh
frontend: # bpmn:
container_name: frontend # container_name: bpmn
depends_on: # depends_on:
- db # - db
- backend # - backend
image: sartography/cr-connect-frontend:dev # image: sartography/cr-connect-bpmn:dev
environment: # environment:
- API_URL=http://localhost:5000/api/v1.0 # - API_URL=http://localhost:5000/api/v1.0
- BASE_HREF=/app/ # - BASE_HREF=/bpmn/
- DEPLOY_URL=/app/ # - DEPLOY_URL=/bpmn/
- HOME_ROUTE=home # - HOME_ROUTE=home
- PORT0=4200 # - PORT0=5002
- PRODUCTION=false # - PRODUCTION=false
ports: # ports:
- "4200:4200" # - "5002:5002"
#
# frontend:
# container_name: frontend
# depends_on:
# - db
# - backend
# image: sartography/cr-connect-frontend:dev
# environment:
# - API_URL=http://localhost:5000/api/v1.0
# - BASE_HREF=/app/
# - DEPLOY_URL=/app/
# - HOME_ROUTE=home
# - PORT0=4200
# - PRODUCTION=false
# ports:
# - "4200:4200"

63
package-lock.json generated
View File

@ -3138,6 +3138,63 @@
} }
} }
}, },
"@sentry/browser": {
"version": "5.16.1",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-5.16.1.tgz",
"integrity": "sha512-uXXKRGLWDqwaKO09K1GTTV0Yj+OfELVs+0cDDYqPDow+DlIXyx0gSnZPd0caCqFllUy8JSxb4S9OprYinvks2A==",
"requires": {
"@sentry/core": "5.16.1",
"@sentry/types": "5.16.1",
"@sentry/utils": "5.16.1",
"tslib": "^1.9.3"
}
},
"@sentry/core": {
"version": "5.16.1",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.16.1.tgz",
"integrity": "sha512-CDKUAUWefZ+bx7tUGm7pgkuJbwn+onAlwzKkLGVg730IP+N/AWSpVtbvFTPiel2+NPiFhWX5/F0SpxDMLPRKfg==",
"requires": {
"@sentry/hub": "5.16.1",
"@sentry/minimal": "5.16.1",
"@sentry/types": "5.16.1",
"@sentry/utils": "5.16.1",
"tslib": "^1.9.3"
}
},
"@sentry/hub": {
"version": "5.16.1",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.16.1.tgz",
"integrity": "sha512-Og4zxp0lM9yS6TyKbZ5lQR94f/fNOalodm71Dk4qfBWi0OzfFCVpO4fPOhHtbXEsvMNg5xh0Pe8ezqX3CZ3hTw==",
"requires": {
"@sentry/types": "5.16.1",
"@sentry/utils": "5.16.1",
"tslib": "^1.9.3"
}
},
"@sentry/minimal": {
"version": "5.16.1",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.16.1.tgz",
"integrity": "sha512-RCwEKLneV5BQlv1MEmsCR3I5jajHgVGusBgwGgnFv+4Cn4cNC7OHWH4QbuZ3IHOEHJl7YS074BeluM+7jn0+Tw==",
"requires": {
"@sentry/hub": "5.16.1",
"@sentry/types": "5.16.1",
"tslib": "^1.9.3"
}
},
"@sentry/types": {
"version": "5.16.1",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.16.1.tgz",
"integrity": "sha512-uERNhBdsiWvWG7qTC9QVsvFmOSL8rFfy8usEXeH3l4oCQao9TvGUvXJv6gRfiWmoiJZ1A0608Lj15CORygdbng=="
},
"@sentry/utils": {
"version": "5.16.1",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.16.1.tgz",
"integrity": "sha512-hn2jTc6ZH1lXGij7yqkV6cGhEYxsdjqB5P4MjfrRHB5bk5opY9R89bsAhs1rpanTdwv6Ul0ieR1z18gdIgUf0g==",
"requires": {
"@sentry/types": "5.16.1",
"tslib": "^1.9.3"
}
},
"@types/color-name": { "@types/color-name": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
@ -12299,9 +12356,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"sartography-workflow-lib": { "sartography-workflow-lib": {
"version": "0.0.213", "version": "0.0.265",
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.213.tgz", "resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.265.tgz",
"integrity": "sha512-2y4UQk3zYeY0Xu3wqq3UptORxVN/Dp8MPyr7JMNBjM9XCdoDL+nIyhpOA7pS+VfraoEzbm9m4CQamQ9YSGRu6w==" "integrity": "sha512-cb1Wc09m83hgpjz7d60KHGDjHvrpq6oZns8lL+kgjFUrGwsL8lRxwsjt1cOGMnCTzi48icybEogvSsluhU7RhA=="
}, },
"sass": { "sass": {
"version": "1.23.3", "version": "1.23.3",

View File

@ -12,16 +12,12 @@
"test:coverage": "ng test --codeCoverage=true --watch=false --browsers=ChromeHeadless", "test:coverage": "ng test --codeCoverage=true --watch=false --browsers=ChromeHeadless",
"lint": "ng lint", "lint": "ng lint",
"e2e": "./node_modules/protractor/bin/webdriver-manager update && ng e2e", "e2e": "./node_modules/protractor/bin/webdriver-manager update && ng e2e",
"e2e:with-wf": "npm run e2e-wf && ng e2e && npm run e2e-wf:stop && npm run e2e-wf:clean", "e2e:with-wf": "npm run e2e-wf && ng e2e && npm run e2e-wf:stop",
"e2e-wf:stop": "docker stop db || true && docker stop backend || true && docker stop pb || true", "e2e-wf:stop": "cd docker && docker-compose down && cd ..",
"e2e-wf:clean": "docker system prune -f && cd docker && docker-compose rm -f -v -s && cd ..", "e2e-wf:build": "cd docker && docker-compose pull && docker-compose build && cd ..",
"e2e-wf:build": "cd docker && docker-compose pull && docker-compose build --no-cache && cd ..", "e2e-wf:start": "cd docker && docker-compose up -d --force-recreate && cd ..",
"e2e-wf:start": "cd docker && docker-compose up -d && cd ..", "e2e-wf": "npm run e2e-wf:stop && npm run e2e-wf:build && npm run e2e-wf:start",
"e2e-wf:db-upgrade": "docker exec -it backend pipenv run flask db upgrade", "env": "chmod +x ./docker/substitute-env-variables.sh && ./docker/substitute-env-variables.sh src/index.html PRODUCTION,API_URL,IRB_URL,HOME_ROUTE,BASE_HREF,DEPLOY_URL,PORT0,GOOGLE_ANALYTICS_KEY,SENTRY_KEY,TITLE",
"e2e-wf:db-setup": "docker exec -it backend pipenv run flask load-example-data",
"e2e-wf:pb-setup": "docker exec -it pb pipenv run flask db upgrade",
"e2e-wf": "npm run e2e-wf:stop && npm run e2e-wf:clean && npm run e2e-wf:build && npm run e2e-wf:start && npm run e2e-wf:db-upgrade && npm run e2e-wf:db-setup && npm run e2e-wf:pb-setup",
"env": "chmod +x ./docker/substitute-env-variables.sh && ./docker/substitute-env-variables.sh src/index.html PRODUCTION,API_URL,IRB_URL,HOME_ROUTE,BASE_HREF,PORT0",
"ci": "npm run lint && npm run test:coverage && sonar-scanner" "ci": "npm run lint && npm run test:coverage && sonar-scanner"
}, },
"private": true, "private": true,
@ -39,6 +35,7 @@
"@angular/router": "^9.0.7", "@angular/router": "^9.0.7",
"@ngx-formly/core": "^5.5.15", "@ngx-formly/core": "^5.5.15",
"@ngx-formly/material": "^5.5.15", "@ngx-formly/material": "^5.5.15",
"@sentry/browser": "^5.16.1",
"@yellowspot/ng-truncate": "^1.5.1", "@yellowspot/ng-truncate": "^1.5.1",
"bpmn-js": "^6.4.2", "bpmn-js": "^6.4.2",
"bpmn-js-properties-panel": "^0.33.2", "bpmn-js-properties-panel": "^0.33.2",
@ -54,7 +51,7 @@
"ngx-file-drop": "^8.0.8", "ngx-file-drop": "^8.0.8",
"ngx-markdown": "^9.0.0", "ngx-markdown": "^9.0.0",
"rxjs": "~6.5.4", "rxjs": "~6.5.4",
"sartography-workflow-lib": "0.0.213", "sartography-workflow-lib": "0.0.265",
"tslib": "^1.11.1", "tslib": "^1.11.1",
"uuid": "^7.0.2", "uuid": "^7.0.2",
"zone.js": "^0.10.3" "zone.js": "^0.10.3"

View File

@ -1,5 +1,4 @@
import {FileMeta, FileType, WorkflowSpec, WorkflowSpecCategory} from 'sartography-workflow-lib'; import {FileMeta, FileType, WorkflowSpec, WorkflowSpecCategory} from 'sartography-workflow-lib';
import {ApiError} from 'sartography-workflow-lib/lib/types/api';
export interface FileMetaDialogData { export interface FileMetaDialogData {
id?: number; id?: number;
@ -49,7 +48,3 @@ export interface DeleteWorkflowSpecCategoryDialogData {
confirm: boolean; confirm: boolean;
category: WorkflowSpecCategory; category: WorkflowSpecCategory;
} }
export interface ApiErrorsBottomSheetData {
apiErrors: ApiError[];
}

View File

@ -1,21 +0,0 @@
<div fxLayout="row">
<h2>Workflow Specification Errors</h2>
<span fxFlex></span>
<button mat-icon-button (click)="dismiss($event)"><mat-icon>close</mat-icon></button>
</div>
<mat-list>
<mat-list-item *ngFor="let e of apiErrors" class="api-error" [ngStyle]="{'height': 'auto'}">
<h3 mat-line *ngIf="e.status_code">{{e.code}}</h3>
<h4 mat-line *ngIf="e.code">{{e.status_code}}</h4>
<div mat-line *ngIf="e.task_name && e.task_id">{{e.task_name}} ({{e.task_id}})</div>
<div mat-line *ngIf="e.task_id && !e.task_name">Task ID: {{e.task_id}}</div>
<div mat-line *ngIf="!e.task_id && e.task_name">Task Name: {{e.task_name}}</div>
<div mat-line *ngIf="e.file_name">File: {{e.file_name}}</div>
<div mat-line *ngIf="e.tag">Tag: {{e.tag}}</div>
<ng-container *ngIf="e.message">
<div mat-line>
<code *ngIf="e.message">{{e.message}}</code>
</div>
</ng-container>
</mat-list-item>
</mat-list>

View File

@ -1,16 +0,0 @@
@import "../../config";
::ng-deep mat-list-item.api-error, mat-list-item.api-error:hover {
border-left: 4px solid $brand-warning;
background-color: $brand-warning-light;
cursor: default;
.mat-line {
text-overflow: initial;
height: auto;
code {
white-space: normal;
}
}
}

View File

@ -1,57 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {MAT_BOTTOM_SHEET_DATA, MatBottomSheetRef} from '@angular/material/bottom-sheet';
import {MatIconModule} from '@angular/material/icon';
import {MatListModule} from '@angular/material/list';
import { ApiErrorsComponent } from './api-errors.component';
describe('ApiErrorsComponent', () => {
let component: ApiErrorsComponent;
let fixture: ComponentFixture<ApiErrorsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
ApiErrorsComponent
],
imports: [
MatIconModule,
MatListModule,
],
providers: [
{
provide: MatBottomSheetRef,
useValue: {
dismiss: (dialogResult: any) => {
}
}
},
{provide: MAT_BOTTOM_SHEET_DATA, useValue: {apiErrors: [{
status_code: 400,
code: 'error_code'
}]}},
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ApiErrorsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
expect(component.data).toBeTruthy();
expect(component.apiErrors).toBeTruthy();
});
it('should dismiss', () => {
const dismissSpy = spyOn((component as any)._bottomSheetRef, 'dismiss').and.stub();
component.dismiss(new MouseEvent('click'));
expect(dismissSpy).toHaveBeenCalled();
});
});

View File

@ -1,30 +0,0 @@
import {Component, Inject, OnInit} from '@angular/core';
import {MAT_BOTTOM_SHEET_DATA, MatBottomSheetRef} from '@angular/material/bottom-sheet';
import {ApiError} from 'sartography-workflow-lib/lib/types/api';
import {ApiErrorsBottomSheetData} from '../_interfaces/dialog-data';
@Component({
selector: 'app-api-errors',
templateUrl: './api-errors.component.html',
styleUrls: ['./api-errors.component.scss']
})
export class ApiErrorsComponent implements OnInit {
apiErrors: ApiError[];
constructor(
@Inject(MAT_BOTTOM_SHEET_DATA) public data: ApiErrorsBottomSheetData,
private _bottomSheetRef: MatBottomSheetRef<ApiErrorsComponent>
) {
if (data && data.apiErrors && data.apiErrors.length > 0) {
this.apiErrors = data.apiErrors;
}
}
ngOnInit(): void {
}
dismiss(event: MouseEvent) {
this._bottomSheetRef.dismiss();
event.preventDefault();
}
}

View File

@ -15,6 +15,8 @@ export class ThisEnvironment implements AppEnvironment {
api = environment.api; api = environment.api;
irbUrl = environment.irbUrl; irbUrl = environment.irbUrl;
title = environment.title; title = environment.title;
googleAnalyticsKey = environment.googleAnalyticsKey;
sentryKey = environment.sentryKey;
} }
const routes: Routes = [ const routes: Routes = [

View File

@ -1,5 +1,5 @@
<div class="mat-typography"> <div class="mat-typography">
<app-navbar *ngIf="isSignedIn" class="mat-elevation-z6" id="globalHeader"></app-navbar> <app-navbar></app-navbar>
<router-outlet></router-outlet> <router-outlet></router-outlet>
<app-footer></app-footer> <app-footer></app-footer>
</div> </div>

View File

@ -1,7 +0,0 @@
#globalHeader {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 2;
}

View File

@ -1,61 +1,57 @@
import {APP_BASE_HREF} from '@angular/common'; import {APP_BASE_HREF} from '@angular/common';
import {HttpClient} from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
import {HttpClientTestingModule} from '@angular/common/http/testing'; import {HttpClientTestingModule} from '@angular/common/http/testing';
import {Component} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {MatIconModule} from '@angular/material/icon';
import {FakeMatIconRegistry} from '@angular/material/icon/testing';
import {MatMenuModule} from '@angular/material/menu';
import {RouterTestingModule} from '@angular/router/testing'; import {RouterTestingModule} from '@angular/router/testing';
import {ApiService, MockEnvironment} from 'sartography-workflow-lib'; import {ApiService, MockEnvironment} from 'sartography-workflow-lib';
import {AppComponent} from './app.component'; import {AppComponent} from './app.component';
import {FooterComponent} from './footer/footer.component';
import {NavbarComponent} from './navbar/navbar.component';
@Component({
selector: 'app-navbar',
template: ''
})
class MockNavbarComponent {
}
@Component({
selector: 'app-footer',
template: ''
})
class MockFooterComponent {
}
describe('AppComponent', () => { describe('AppComponent', () => {
let component: AppComponent; let component: AppComponent;
let fixture: ComponentFixture<AppComponent>; let fixture: ComponentFixture<AppComponent>;
const mockEnvironment = new MockEnvironment();
const mockTitle = `'Once,' said the Mock Title at last, with a deep sigh, 'I was a real Title.'`;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ declarations: [
AppComponent, AppComponent,
MockNavbarComponent, FooterComponent,
MockFooterComponent NavbarComponent,
], ],
imports: [ imports: [
HttpClientTestingModule, HttpClientTestingModule,
BrowserAnimationsModule, MatIconModule,
MatMenuModule,
RouterTestingModule, RouterTestingModule,
], ],
providers: [ providers: [
HttpClient, HttpClient,
FakeMatIconRegistry,
ApiService, ApiService,
{provide: 'APP_ENVIRONMENT', useClass: MockEnvironment}, {provide: 'APP_ENVIRONMENT', useValue: mockEnvironment},
{provide: APP_BASE_HREF, useValue: ''}, {provide: APP_BASE_HREF, useValue: ''},
], ]
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
mockEnvironment.title = mockTitle;
fixture = TestBed.createComponent(AppComponent); fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create the app', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
it(`should set the page title to match environment variable`, () => {
expect((component as any).titleService.getTitle()).toEqual(mockTitle);
});
}); });

View File

@ -1,5 +1,7 @@
import {Component} from '@angular/core'; import {Component, Inject} from '@angular/core';
import {ApiService} from 'sartography-workflow-lib'; import {MatIconRegistry} from '@angular/material/icon';
import {DomSanitizer, Title} from '@angular/platform-browser';
import {AppEnvironment, FileType, GoogleAnalyticsService} from 'sartography-workflow-lib';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@ -7,12 +9,19 @@ import {ApiService} from 'sartography-workflow-lib';
styleUrls: ['./app.component.scss'] styleUrls: ['./app.component.scss']
}) })
export class AppComponent { export class AppComponent {
title = 'CR Connect Configuration'; constructor(
@Inject('APP_ENVIRONMENT') private environment: AppEnvironment,
constructor(private apiService: ApiService) { private titleService: Title,
} private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer,
get isSignedIn() { private googleAnalyticsService: GoogleAnalyticsService,
return this.apiService.isSignedIn(); ) {
this.googleAnalyticsService.init(this.environment.googleAnalyticsKey);
const fileTypes = Object.values(FileType);
fileTypes.forEach(t => {
const url = this.domSanitizer.bypassSecurityTrustResourceUrl(`assets/icons/file_types/${t}.svg`);
this.matIconRegistry.addSvgIconInNamespace('crc', t, url);
});
this.titleService.setTitle(this.environment.title);
} }
} }

View File

@ -38,7 +38,6 @@ import {OpenFileDialogComponent} from './_dialogs/open-file-dialog/open-file-dia
import {WorkflowSpecCategoryDialogComponent} from './_dialogs/workflow-spec-category-dialog/workflow-spec-category-dialog.component'; import {WorkflowSpecCategoryDialogComponent} from './_dialogs/workflow-spec-category-dialog/workflow-spec-category-dialog.component';
import {WorkflowSpecDialogComponent} from './_dialogs/workflow-spec-dialog/workflow-spec-dialog.component'; import {WorkflowSpecDialogComponent} from './_dialogs/workflow-spec-dialog/workflow-spec-dialog.component';
import {GetIconCodePipe} from './_pipes/get-icon-code.pipe'; import {GetIconCodePipe} from './_pipes/get-icon-code.pipe';
import {ApiErrorsComponent} from './api-errors/api-errors.component';
import {AppRoutingModule} from './app-routing.module'; import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component'; import {AppComponent} from './app.component';
import {DiagramComponent} from './diagram/diagram.component'; import {DiagramComponent} from './diagram/diagram.component';
@ -59,6 +58,8 @@ export class ThisEnvironment implements AppEnvironment {
api = environment.api; api = environment.api;
irbUrl = environment.irbUrl; irbUrl = environment.irbUrl;
title = environment.title; title = environment.title;
googleAnalyticsKey = environment.googleAnalyticsKey;
sentryKey = environment.sentryKey;
} }
/** /**
@ -96,7 +97,6 @@ export function getBaseHref(platformLocation: PlatformLocation): string {
WorkflowSpecListComponent, WorkflowSpecListComponent,
HomeComponent, HomeComponent,
WorkflowSpecCardComponent, WorkflowSpecCardComponent,
ApiErrorsComponent,
ProtocolBuilderComponent, ProtocolBuilderComponent,
ReferenceFilesComponent, ReferenceFilesComponent,
], ],
@ -128,7 +128,6 @@ export function getBaseHref(platformLocation: PlatformLocation): string {
], ],
bootstrap: [AppComponent], bootstrap: [AppComponent],
entryComponents: [ entryComponents: [
ApiErrorsComponent,
DeleteFileDialogComponent, DeleteFileDialogComponent,
DeleteWorkflowSpecDialogComponent, DeleteWorkflowSpecDialogComponent,
DeleteWorkflowSpecCategoryDialogComponent, DeleteWorkflowSpecCategoryDialogComponent,

View File

@ -5,6 +5,7 @@ import {MatDialog} from '@angular/material/dialog';
import {MatSnackBar} from '@angular/material/snack-bar'; import {MatSnackBar} from '@angular/material/snack-bar';
import {ActivatedRoute, Params, Router} from '@angular/router'; import {ActivatedRoute, Params, Router} from '@angular/router';
import { import {
ApiErrorsComponent,
ApiService, ApiService,
FileMeta, FileMeta,
FileType, FileType,
@ -19,7 +20,6 @@ import {OpenFileDialogComponent} from '../_dialogs/open-file-dialog/open-file-di
import {BpmnWarning} from '../_interfaces/bpmn-warning'; import {BpmnWarning} from '../_interfaces/bpmn-warning';
import {FileMetaDialogData, NewFileDialogData, OpenFileDialogData} from '../_interfaces/dialog-data'; import {FileMetaDialogData, NewFileDialogData, OpenFileDialogData} from '../_interfaces/dialog-data';
import {ImportEvent} from '../_interfaces/import-event'; import {ImportEvent} from '../_interfaces/import-event';
import {ApiErrorsComponent} from '../api-errors/api-errors.component';
import {DiagramComponent} from '../diagram/diagram.component'; import {DiagramComponent} from '../diagram/diagram.component';
@Component({ @Component({

View File

@ -1,6 +1,6 @@
import {Component, Inject, OnInit} from '@angular/core'; import {Component, Inject} from '@angular/core';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {ApiService, AppEnvironment, isSignedIn, User, UserParams} from 'sartography-workflow-lib'; import {ApiService, AppEnvironment, GoogleAnalyticsService, isSignedIn, User} from 'sartography-workflow-lib';
interface NavItem { interface NavItem {
path?: string; path?: string;
@ -25,6 +25,7 @@ export class NavbarComponent {
private router: Router, private router: Router,
private api: ApiService, private api: ApiService,
@Inject('APP_ENVIRONMENT') private environment: AppEnvironment, @Inject('APP_ENVIRONMENT') private environment: AppEnvironment,
private googleAnalyticsService: GoogleAnalyticsService
) { ) {
this._loadUser(); this._loadUser();
this.title = environment.title; this.title = environment.title;
@ -38,6 +39,11 @@ export class NavbarComponent {
if (isSignedIn()) { if (isSignedIn()) {
this.api.getUser().subscribe(u => { this.api.getUser().subscribe(u => {
this.user = u; this.user = u;
if (this.user && this.user.uid) {
this.googleAnalyticsService.setUser(this.user.uid);
}
this._loadNavLinks(); this._loadNavLinks();
}, error => { }, error => {
localStorage.removeItem('token'); localStorage.removeItem('token');

View File

@ -13,6 +13,7 @@ import {RouterTestingModule} from '@angular/router/testing';
import createClone from 'rfdc'; import createClone from 'rfdc';
import {of} from 'rxjs'; import {of} from 'rxjs';
import { import {
ApiErrorsComponent,
ApiService, ApiService,
MockEnvironment, MockEnvironment,
mockWorkflowSpec0, mockWorkflowSpec0,
@ -34,7 +35,6 @@ import {
WorkflowSpecDialogData WorkflowSpecDialogData
} from '../_interfaces/dialog-data'; } from '../_interfaces/dialog-data';
import {GetIconCodePipe} from '../_pipes/get-icon-code.pipe'; import {GetIconCodePipe} from '../_pipes/get-icon-code.pipe';
import {ApiErrorsComponent} from '../api-errors/api-errors.component';
import {FileListComponent} from '../file-list/file-list.component'; import {FileListComponent} from '../file-list/file-list.component';
import {WorkflowSpecListComponent} from './workflow-spec-list.component'; import {WorkflowSpecListComponent} from './workflow-spec-list.component';

View File

@ -21,7 +21,7 @@ import {
WorkflowSpecCategoryDialogData, WorkflowSpecCategoryDialogData,
WorkflowSpecDialogData WorkflowSpecDialogData
} from '../_interfaces/dialog-data'; } from '../_interfaces/dialog-data';
import {ApiErrorsComponent} from '../api-errors/api-errors.component'; import {ApiErrorsComponent} from 'sartography-workflow-lib';
export interface WorkflowSpecCategoryGroup { export interface WorkflowSpecCategoryGroup {

View File

@ -10,4 +10,6 @@ export const environment: AppEnvironment = {
api: _has(ENV, 'api', '$API_URL') ? ENV.api : 'http://localhost:5000/v1.0', api: _has(ENV, 'api', '$API_URL') ? ENV.api : 'http://localhost:5000/v1.0',
irbUrl: _has(ENV, 'irbUrl', '$IRB_URL') ? ENV.irbUrl : 'http://localhost:5001', irbUrl: _has(ENV, 'irbUrl', '$IRB_URL') ? ENV.irbUrl : 'http://localhost:5001',
title: _has(ENV, 'title', '$TITLE') ? ENV.title : 'Research Ramp-Up Toolkit Configurator', title: _has(ENV, 'title', '$TITLE') ? ENV.title : 'Research Ramp-Up Toolkit Configurator',
googleAnalyticsKey: _has(ENV, 'googleAnalyticsKey', '$GOOGLE_ANALYTICS_KEY') ? ENV.googleAnalyticsKey : 'UA-168203235-5',
sentryKey: _has(ENV, 'sentryKey', '$SENTRY_KEY') ? ENV.sentryKey : undefined,
}; };

View File

@ -1,15 +1,17 @@
import {AppEnvironment} from 'sartography-workflow-lib';
import {_has, environment} from './environment.runtime'; import {_has, environment} from './environment.runtime';
declare var ENV; declare var ENV;
describe('Environments', () => { describe('Environments', () => {
it('should have settings for all the environments', () => { it('should have default values for all the environments', () => {
expect(environment).toBeDefined(); expect(environment).toBeDefined();
expect(environment.production).toEqual(false); expect(environment.production).toEqual(false);
expect(environment.api).toEqual('apiRoot'); expect(environment.api).toEqual('apiRoot');
expect(environment.irbUrl).toEqual('irbUrl'); expect(environment.irbUrl).toEqual('irbUrl');
expect(environment.homeRoute).toEqual('home'); expect(environment.homeRoute).toEqual('home');
expect(environment.title).toEqual('Research Ramp-Up Toolkit Configurator');
expect(environment.googleAnalyticsKey).toEqual('UA-168203235-5');
expect(environment.sentryKey).toEqual(undefined);
}); });
it('should check if environment variables are defined', () => { it('should check if environment variables are defined', () => {
@ -18,31 +20,44 @@ describe('Environments', () => {
production: '$PRODUCTION', production: '$PRODUCTION',
api: '$API_URL', api: '$API_URL',
irbUrl: '$IRB_URL', irbUrl: '$IRB_URL',
title: '$TITLE',
googleAnalyticsKey: '$GOOGLE_ANALYTICS_KEY',
sentryKey: '$SENTRY_KEY',
}; };
expect(_has(env, 'homeRoute', '$HOME_ROUTE')).toBeFalse(); expect(_has(env, 'homeRoute', '$HOME_ROUTE')).toBeFalse();
expect(_has(env, 'production', '$PRODUCTION')).toBeFalse(); expect(_has(env, 'production', '$PRODUCTION')).toBeFalse();
expect(_has(env, 'api', '$API_URL')).toBeFalse(); expect(_has(env, 'api', '$API_URL')).toBeFalse();
expect(_has(env, 'irbUrl', '$IRB_URL')).toBeFalse(); expect(_has(env, 'irbUrl', '$IRB_URL')).toBeFalse();
expect(_has(env, 'title', '$TITLE')).toBeFalse();
expect(_has(env, 'googleAnalyticsKey', '$GOOGLE_ANALYTICS_KEY')).toBeFalse();
env.homeRoute = undefined; env.homeRoute = undefined;
env.production = undefined; env.production = undefined;
env.api = undefined; env.api = undefined;
env.irbUrl = undefined; env.irbUrl = undefined;
env.title = undefined;
env.googleAnalyticsKey = undefined;
expect(_has(env, 'homeRoute', '$HOME_ROUTE')).toBeFalse(); expect(_has(env, 'homeRoute', '$HOME_ROUTE')).toBeFalse();
expect(_has(env, 'production', '$PRODUCTION')).toBeFalse(); expect(_has(env, 'production', '$PRODUCTION')).toBeFalse();
expect(_has(env, 'api', '$API_URL')).toBeFalse(); expect(_has(env, 'api', '$API_URL')).toBeFalse();
expect(_has(env, 'irbUrl', '$IRB_URL')).toBeFalse(); expect(_has(env, 'irbUrl', '$IRB_URL')).toBeFalse();
expect(_has(env, 'title', '$TITLE')).toBeFalse();
expect(_has(env, 'googleAnalyticsKey', '$GOOGLE_ANALYTICS_KEY')).toBeFalse();
env.homeRoute = 'something'; env.homeRoute = 'something';
env.production = 'something'; env.production = 'something';
env.api = 'something'; env.api = 'something';
env.irbUrl = 'something'; env.irbUrl = 'something';
env.title = 'something';
env.googleAnalyticsKey = 'something';
expect(_has(env, 'homeRoute', '$HOME_ROUTE')).toBeTrue(); expect(_has(env, 'homeRoute', '$HOME_ROUTE')).toBeTrue();
expect(_has(env, 'production', '$PRODUCTION')).toBeTrue(); expect(_has(env, 'production', '$PRODUCTION')).toBeTrue();
expect(_has(env, 'api', '$API_URL')).toBeTrue(); expect(_has(env, 'api', '$API_URL')).toBeTrue();
expect(_has(env, 'irbUrl', '$IRB_URL')).toBeTrue(); expect(_has(env, 'irbUrl', '$IRB_URL')).toBeTrue();
expect(_has(env, 'title', '$TITLE')).toBeTrue();
expect(_has(env, 'googleAnalyticsKey', '$GOOGLE_ANALYTICS_KEY')).toBeTrue();
}); });
}); });

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -10,11 +10,14 @@
production: '$PRODUCTION', production: '$PRODUCTION',
api: '$API_URL', api: '$API_URL',
irbUrl: '$IRB_URL', irbUrl: '$IRB_URL',
baseHref: '$BASE_HREF', title: '$TITLE',
googleAnalyticsKey: '$GOOGLE_ANALYTICS_KEY',
sentryKey: '$SENTRY_KEY',
}; };
</script> </script>
<meta content="width=device-width, initial-scale=1" name="viewport"> <meta content="width=device-width, initial-scale=1" name="viewport">
<link href="favicon.ico" rel="icon" type="image/x-icon"> <meta name="google-site-verification" content="KBn1RBc_UR6VF025kfjl_fRlIoLufSHL5JIkwE_xrOc" />
<link href="favicon.ico?v=1" rel="icon" type="image/x-icon">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://use.typekit.net/kwp6dli.css"> <link rel="stylesheet" href="https://use.typekit.net/kwp6dli.css">
<link href="assets/css/diagram-js.css" rel="stylesheet"> <link href="assets/css/diagram-js.css" rel="stylesheet">