diff --git a/Dockerfile b/Dockerfile
index 1cedae5..ef32b0c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -32,6 +32,6 @@ RUN echo "pushstate: enabled" > /etc/nginx/html/Staticfile
# then starts/reloads nginx.
ENTRYPOINT ["./entrypoint.sh", \
"/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", \
"true"]
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
index 4fb688f..6a5c4e7 100644
--- a/docker/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -1,14 +1,20 @@
version: "3.3"
services:
+ ldap:
+ container_name: ldap
+ image: tuxmonteiro/ldap-mock
+ ports:
+ - "3890:3890"
+
db:
container_name: db
- image: sartography/cr-connect-db:dev
+ image: sartography/cr-connect-db:$E2E_TAG
ports:
- "5432:5432"
environment:
- - POSTGRES_USER=rrt_user
- - POSTGRES_PASSWORD=rrt_pass
- - POSTGRES_MULTIPLE_DATABASES=rrt
+ - POSTGRES_USER=crc_user
+ - POSTGRES_PASSWORD=crc_pass
+ - POSTGRES_MULTIPLE_DATABASES=crc_test,pb_test
healthcheck:
test: ["CMD", "pg_isready"]
timeout: 20s
@@ -18,52 +24,73 @@ services:
container_name: backend
depends_on:
- db
- image: sartography/cr-connect-workflow:dev
+ image: sartography/cr-connect-workflow:$E2E_TAG
environment:
- - APPLICATION_ROOT=/api
+ - APPLICATION_ROOT=/
- CORS_ALLOW_ORIGINS=localhost:5002,bpmn:5002,localhost:4200,frontend:4200
- DB_HOST=db
- - DB_NAME=rrt
- - DB_PASSWORD=rrt_pass
+ - DB_NAME=crc_test
+ - DB_PASSWORD=crc_pass
- DB_PORT=5432
- - DB_USER=rrt_user
- - LDAP_URL=ldap.virginia.edu
- - PB_ENABLED=false
+ - DB_USER=crc_user
+ - LDAP_URL=ldap
+ - PB_ENABLED=true
+ - PB_BASE_URL=http://pb:5001/v2.0/
- PORT0=5000
- RESET_DB=true
- UPGRADE_DB=true
+ - TESTING=true
ports:
- "5000:5000"
command: ./wait-for-it.sh db:5432 -t 0 -- ./docker_run.sh
- bpmn:
- container_name: bpmn
+ pb:
+ container_name: pb
depends_on:
- db
- - backend
- image: sartography/cr-connect-bpmn:dev
+ image: sartography/protocol-builder-mock:$E2E_TAG
environment:
- - API_URL=http://localhost:5000/api/v1.0
- - BASE_HREF=/bpmn/
- - DEPLOY_URL=/bpmn/
- - HOME_ROUTE=home
- - PORT0=5002
- - PRODUCTION=false
+ - APPLICATION_ROOT=/
+ - CORS_ALLOW_ORIGINS=localhost:5000,backend:5000,localhost:5002,bpmn:5002,localhost:4200,frontend:4200
+ - DB_HOST=db
+ - DB_NAME=pb_test
+ - DB_PASSWORD=crc_pass
+ - DB_PORT=5432
+ - DB_USER=crc_user
+ - PORT0=5001
+ - UPGRADE_DB=true
ports:
- - "5002:5002"
+ - "5001:5001"
+ command: ./wait-for-it.sh db:5432 -t 0 -- ./docker_run.sh
- 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"
+# bpmn:
+# container_name: bpmn
+# depends_on:
+# - db
+# - backend
+# image: sartography/cr-connect-bpmn:dev
+# environment:
+# - API_URL=http://localhost:5000/api/v1.0
+# - BASE_HREF=/bpmn/
+# - DEPLOY_URL=/bpmn/
+# - HOME_ROUTE=home
+# - PORT0=5002
+# - PRODUCTION=false
+# ports:
+# - "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"
diff --git a/package-lock.json b/package-lock.json
index e6b4544..15db4d5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -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": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
@@ -12299,9 +12356,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sartography-workflow-lib": {
- "version": "0.0.213",
- "resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.213.tgz",
- "integrity": "sha512-2y4UQk3zYeY0Xu3wqq3UptORxVN/Dp8MPyr7JMNBjM9XCdoDL+nIyhpOA7pS+VfraoEzbm9m4CQamQ9YSGRu6w=="
+ "version": "0.0.265",
+ "resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.265.tgz",
+ "integrity": "sha512-cb1Wc09m83hgpjz7d60KHGDjHvrpq6oZns8lL+kgjFUrGwsL8lRxwsjt1cOGMnCTzi48icybEogvSsluhU7RhA=="
},
"sass": {
"version": "1.23.3",
diff --git a/package.json b/package.json
index e33ae8c..de3ad60 100644
--- a/package.json
+++ b/package.json
@@ -12,16 +12,12 @@
"test:coverage": "ng test --codeCoverage=true --watch=false --browsers=ChromeHeadless",
"lint": "ng lint",
"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-wf:stop": "docker stop db || true && docker stop backend || true && docker stop pb || true",
- "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 --no-cache && cd ..",
- "e2e-wf:start": "cd docker && docker-compose up -d && cd ..",
- "e2e-wf:db-upgrade": "docker exec -it backend pipenv run flask db upgrade",
- "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",
+ "e2e:with-wf": "npm run e2e-wf && ng e2e && npm run e2e-wf:stop",
+ "e2e-wf:stop": "cd docker && docker-compose down && cd ..",
+ "e2e-wf:build": "cd docker && docker-compose pull && docker-compose build && cd ..",
+ "e2e-wf:start": "cd docker && docker-compose up -d --force-recreate && cd ..",
+ "e2e-wf": "npm run e2e-wf:stop && npm run e2e-wf:build && npm run e2e-wf:start",
+ "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",
"ci": "npm run lint && npm run test:coverage && sonar-scanner"
},
"private": true,
@@ -39,6 +35,7 @@
"@angular/router": "^9.0.7",
"@ngx-formly/core": "^5.5.15",
"@ngx-formly/material": "^5.5.15",
+ "@sentry/browser": "^5.16.1",
"@yellowspot/ng-truncate": "^1.5.1",
"bpmn-js": "^6.4.2",
"bpmn-js-properties-panel": "^0.33.2",
@@ -54,7 +51,7 @@
"ngx-file-drop": "^8.0.8",
"ngx-markdown": "^9.0.0",
"rxjs": "~6.5.4",
- "sartography-workflow-lib": "0.0.213",
+ "sartography-workflow-lib": "0.0.265",
"tslib": "^1.11.1",
"uuid": "^7.0.2",
"zone.js": "^0.10.3"
diff --git a/src/app/_interfaces/dialog-data.ts b/src/app/_interfaces/dialog-data.ts
index cd0dea0..48ce9db 100644
--- a/src/app/_interfaces/dialog-data.ts
+++ b/src/app/_interfaces/dialog-data.ts
@@ -1,5 +1,4 @@
import {FileMeta, FileType, WorkflowSpec, WorkflowSpecCategory} from 'sartography-workflow-lib';
-import {ApiError} from 'sartography-workflow-lib/lib/types/api';
export interface FileMetaDialogData {
id?: number;
@@ -49,7 +48,3 @@ export interface DeleteWorkflowSpecCategoryDialogData {
confirm: boolean;
category: WorkflowSpecCategory;
}
-
-export interface ApiErrorsBottomSheetData {
- apiErrors: ApiError[];
-}
diff --git a/src/app/api-errors/api-errors.component.html b/src/app/api-errors/api-errors.component.html
deleted file mode 100644
index f51de56..0000000
--- a/src/app/api-errors/api-errors.component.html
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
Workflow Specification Errors
-
-
-
-
-
- {{e.code}}
- {{e.status_code}}
- {{e.task_name}} ({{e.task_id}})
- Task ID: {{e.task_id}}
- Task Name: {{e.task_name}}
- File: {{e.file_name}}
- Tag: {{e.tag}}
-
-
- {{e.message}}
-
-
-
-
diff --git a/src/app/api-errors/api-errors.component.scss b/src/app/api-errors/api-errors.component.scss
deleted file mode 100644
index eda4773..0000000
--- a/src/app/api-errors/api-errors.component.scss
+++ /dev/null
@@ -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;
- }
- }
-}
diff --git a/src/app/api-errors/api-errors.component.spec.ts b/src/app/api-errors/api-errors.component.spec.ts
deleted file mode 100644
index 73864c4..0000000
--- a/src/app/api-errors/api-errors.component.spec.ts
+++ /dev/null
@@ -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;
-
- 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();
- });
-
-});
diff --git a/src/app/api-errors/api-errors.component.ts b/src/app/api-errors/api-errors.component.ts
deleted file mode 100644
index af16458..0000000
--- a/src/app/api-errors/api-errors.component.ts
+++ /dev/null
@@ -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
- ) {
- if (data && data.apiErrors && data.apiErrors.length > 0) {
- this.apiErrors = data.apiErrors;
- }
- }
-
- ngOnInit(): void {
- }
-
- dismiss(event: MouseEvent) {
- this._bottomSheetRef.dismiss();
- event.preventDefault();
- }
-}
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 2f759e1..ca7543e 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -15,6 +15,8 @@ export class ThisEnvironment implements AppEnvironment {
api = environment.api;
irbUrl = environment.irbUrl;
title = environment.title;
+ googleAnalyticsKey = environment.googleAnalyticsKey;
+ sentryKey = environment.sentryKey;
}
const routes: Routes = [
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 80ac792..aafc157 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,5 +1,5 @@
diff --git a/src/app/app.component.scss b/src/app/app.component.scss
index e25ee2c..e69de29 100644
--- a/src/app/app.component.scss
+++ b/src/app/app.component.scss
@@ -1,7 +0,0 @@
-#globalHeader {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- z-index: 2;
-}
diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts
index e619fbd..b583860 100644
--- a/src/app/app.component.spec.ts
+++ b/src/app/app.component.spec.ts
@@ -1,61 +1,57 @@
import {APP_BASE_HREF} from '@angular/common';
import {HttpClient} from '@angular/common/http';
import {HttpClientTestingModule} from '@angular/common/http/testing';
-import {Component} from '@angular/core';
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 {ApiService, MockEnvironment} from 'sartography-workflow-lib';
import {AppComponent} from './app.component';
-
-
-@Component({
- selector: 'app-navbar',
- template: ''
-})
-class MockNavbarComponent {
-}
-
-@Component({
- selector: 'app-footer',
- template: ''
-})
-class MockFooterComponent {
-}
+import {FooterComponent} from './footer/footer.component';
+import {NavbarComponent} from './navbar/navbar.component';
describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture;
+ const mockEnvironment = new MockEnvironment();
+ const mockTitle = `'Once,' said the Mock Title at last, with a deep sigh, 'I was a real Title.'`;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent,
- MockNavbarComponent,
- MockFooterComponent
+ FooterComponent,
+ NavbarComponent,
],
imports: [
HttpClientTestingModule,
- BrowserAnimationsModule,
+ MatIconModule,
+ MatMenuModule,
RouterTestingModule,
],
providers: [
HttpClient,
+ FakeMatIconRegistry,
ApiService,
- {provide: 'APP_ENVIRONMENT', useClass: MockEnvironment},
+ {provide: 'APP_ENVIRONMENT', useValue: mockEnvironment},
{provide: APP_BASE_HREF, useValue: ''},
- ],
- })
- .compileComponents();
+ ]
+ }).compileComponents();
}));
beforeEach(() => {
+ mockEnvironment.title = mockTitle;
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
- it('should create', () => {
+ it('should create the app', () => {
expect(component).toBeTruthy();
});
+
+ it(`should set the page title to match environment variable`, () => {
+ expect((component as any).titleService.getTitle()).toEqual(mockTitle);
+ });
});
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index a1d377a..80ba960 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,5 +1,7 @@
-import {Component} from '@angular/core';
-import {ApiService} from 'sartography-workflow-lib';
+import {Component, Inject} from '@angular/core';
+import {MatIconRegistry} from '@angular/material/icon';
+import {DomSanitizer, Title} from '@angular/platform-browser';
+import {AppEnvironment, FileType, GoogleAnalyticsService} from 'sartography-workflow-lib';
@Component({
selector: 'app-root',
@@ -7,12 +9,19 @@ import {ApiService} from 'sartography-workflow-lib';
styleUrls: ['./app.component.scss']
})
export class AppComponent {
- title = 'CR Connect Configuration';
-
- constructor(private apiService: ApiService) {
- }
-
- get isSignedIn() {
- return this.apiService.isSignedIn();
+ constructor(
+ @Inject('APP_ENVIRONMENT') private environment: AppEnvironment,
+ private titleService: Title,
+ private matIconRegistry: MatIconRegistry,
+ private domSanitizer: DomSanitizer,
+ private googleAnalyticsService: GoogleAnalyticsService,
+ ) {
+ 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);
}
}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 7521467..e890441 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -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 {WorkflowSpecDialogComponent} from './_dialogs/workflow-spec-dialog/workflow-spec-dialog.component';
import {GetIconCodePipe} from './_pipes/get-icon-code.pipe';
-import {ApiErrorsComponent} from './api-errors/api-errors.component';
import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component';
import {DiagramComponent} from './diagram/diagram.component';
@@ -59,6 +58,8 @@ export class ThisEnvironment implements AppEnvironment {
api = environment.api;
irbUrl = environment.irbUrl;
title = environment.title;
+ googleAnalyticsKey = environment.googleAnalyticsKey;
+ sentryKey = environment.sentryKey;
}
/**
@@ -96,7 +97,6 @@ export function getBaseHref(platformLocation: PlatformLocation): string {
WorkflowSpecListComponent,
HomeComponent,
WorkflowSpecCardComponent,
- ApiErrorsComponent,
ProtocolBuilderComponent,
ReferenceFilesComponent,
],
@@ -128,7 +128,6 @@ export function getBaseHref(platformLocation: PlatformLocation): string {
],
bootstrap: [AppComponent],
entryComponents: [
- ApiErrorsComponent,
DeleteFileDialogComponent,
DeleteWorkflowSpecDialogComponent,
DeleteWorkflowSpecCategoryDialogComponent,
diff --git a/src/app/modeler/modeler.component.ts b/src/app/modeler/modeler.component.ts
index 6d53c8a..60b9914 100644
--- a/src/app/modeler/modeler.component.ts
+++ b/src/app/modeler/modeler.component.ts
@@ -5,6 +5,7 @@ import {MatDialog} from '@angular/material/dialog';
import {MatSnackBar} from '@angular/material/snack-bar';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {
+ ApiErrorsComponent,
ApiService,
FileMeta,
FileType,
@@ -19,7 +20,6 @@ import {OpenFileDialogComponent} from '../_dialogs/open-file-dialog/open-file-di
import {BpmnWarning} from '../_interfaces/bpmn-warning';
import {FileMetaDialogData, NewFileDialogData, OpenFileDialogData} from '../_interfaces/dialog-data';
import {ImportEvent} from '../_interfaces/import-event';
-import {ApiErrorsComponent} from '../api-errors/api-errors.component';
import {DiagramComponent} from '../diagram/diagram.component';
@Component({
diff --git a/src/app/navbar/navbar.component.ts b/src/app/navbar/navbar.component.ts
index 7e1af1c..288ba4c 100644
--- a/src/app/navbar/navbar.component.ts
+++ b/src/app/navbar/navbar.component.ts
@@ -1,6 +1,6 @@
-import {Component, Inject, OnInit} from '@angular/core';
+import {Component, Inject} from '@angular/core';
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 {
path?: string;
@@ -25,6 +25,7 @@ export class NavbarComponent {
private router: Router,
private api: ApiService,
@Inject('APP_ENVIRONMENT') private environment: AppEnvironment,
+ private googleAnalyticsService: GoogleAnalyticsService
) {
this._loadUser();
this.title = environment.title;
@@ -38,6 +39,11 @@ export class NavbarComponent {
if (isSignedIn()) {
this.api.getUser().subscribe(u => {
this.user = u;
+
+ if (this.user && this.user.uid) {
+ this.googleAnalyticsService.setUser(this.user.uid);
+ }
+
this._loadNavLinks();
}, error => {
localStorage.removeItem('token');
diff --git a/src/app/workflow-spec-list/workflow-spec-list.component.spec.ts b/src/app/workflow-spec-list/workflow-spec-list.component.spec.ts
index fd65069..f9fe120 100644
--- a/src/app/workflow-spec-list/workflow-spec-list.component.spec.ts
+++ b/src/app/workflow-spec-list/workflow-spec-list.component.spec.ts
@@ -13,6 +13,7 @@ import {RouterTestingModule} from '@angular/router/testing';
import createClone from 'rfdc';
import {of} from 'rxjs';
import {
+ ApiErrorsComponent,
ApiService,
MockEnvironment,
mockWorkflowSpec0,
@@ -34,7 +35,6 @@ import {
WorkflowSpecDialogData
} from '../_interfaces/dialog-data';
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 {WorkflowSpecListComponent} from './workflow-spec-list.component';
diff --git a/src/app/workflow-spec-list/workflow-spec-list.component.ts b/src/app/workflow-spec-list/workflow-spec-list.component.ts
index 0f5770b..39c5f71 100644
--- a/src/app/workflow-spec-list/workflow-spec-list.component.ts
+++ b/src/app/workflow-spec-list/workflow-spec-list.component.ts
@@ -21,7 +21,7 @@ import {
WorkflowSpecCategoryDialogData,
WorkflowSpecDialogData
} from '../_interfaces/dialog-data';
-import {ApiErrorsComponent} from '../api-errors/api-errors.component';
+import {ApiErrorsComponent} from 'sartography-workflow-lib';
export interface WorkflowSpecCategoryGroup {
diff --git a/src/environments/environment.runtime.ts b/src/environments/environment.runtime.ts
index c40401d..d49a424 100644
--- a/src/environments/environment.runtime.ts
+++ b/src/environments/environment.runtime.ts
@@ -10,4 +10,6 @@ export const environment: AppEnvironment = {
api: _has(ENV, 'api', '$API_URL') ? ENV.api : 'http://localhost:5000/v1.0',
irbUrl: _has(ENV, 'irbUrl', '$IRB_URL') ? ENV.irbUrl : 'http://localhost:5001',
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,
};
diff --git a/src/environments/environment.spec.ts b/src/environments/environment.spec.ts
index f5ffbe4..ce06af4 100644
--- a/src/environments/environment.spec.ts
+++ b/src/environments/environment.spec.ts
@@ -1,15 +1,17 @@
-import {AppEnvironment} from 'sartography-workflow-lib';
import {_has, environment} from './environment.runtime';
declare var ENV;
describe('Environments', () => {
- it('should have settings for all the environments', () => {
+ it('should have default values for all the environments', () => {
expect(environment).toBeDefined();
expect(environment.production).toEqual(false);
expect(environment.api).toEqual('apiRoot');
expect(environment.irbUrl).toEqual('irbUrl');
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', () => {
@@ -18,31 +20,44 @@ describe('Environments', () => {
production: '$PRODUCTION',
api: '$API_URL',
irbUrl: '$IRB_URL',
+ title: '$TITLE',
+ googleAnalyticsKey: '$GOOGLE_ANALYTICS_KEY',
+ sentryKey: '$SENTRY_KEY',
};
expect(_has(env, 'homeRoute', '$HOME_ROUTE')).toBeFalse();
expect(_has(env, 'production', '$PRODUCTION')).toBeFalse();
expect(_has(env, 'api', '$API_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.production = undefined;
env.api = undefined;
env.irbUrl = undefined;
+ env.title = undefined;
+ env.googleAnalyticsKey = undefined;
expect(_has(env, 'homeRoute', '$HOME_ROUTE')).toBeFalse();
expect(_has(env, 'production', '$PRODUCTION')).toBeFalse();
expect(_has(env, 'api', '$API_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.production = 'something';
env.api = 'something';
env.irbUrl = 'something';
+ env.title = 'something';
+ env.googleAnalyticsKey = 'something';
expect(_has(env, 'homeRoute', '$HOME_ROUTE')).toBeTrue();
expect(_has(env, 'production', '$PRODUCTION')).toBeTrue();
expect(_has(env, 'api', '$API_URL')).toBeTrue();
expect(_has(env, 'irbUrl', '$IRB_URL')).toBeTrue();
+ expect(_has(env, 'title', '$TITLE')).toBeTrue();
+ expect(_has(env, 'googleAnalyticsKey', '$GOOGLE_ANALYTICS_KEY')).toBeTrue();
});
});
diff --git a/src/favicon.ico b/src/favicon.ico
index 8081c7c..df273c3 100644
Binary files a/src/favicon.ico and b/src/favicon.ico differ
diff --git a/src/index.html b/src/index.html
index 124a135..a5136bc 100644
--- a/src/index.html
+++ b/src/index.html
@@ -10,11 +10,14 @@
production: '$PRODUCTION',
api: '$API_URL',
irbUrl: '$IRB_URL',
- baseHref: '$BASE_HREF',
+ title: '$TITLE',
+ googleAnalyticsKey: '$GOOGLE_ANALYTICS_KEY',
+ sentryKey: '$SENTRY_KEY',
};
-
+
+