diff --git a/README.md b/README.md index 6dfe9c06..55069053 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ AWS_ACCESS_KEY_ID=aws_key AWS_SECRET_ACCESS_KEY=aws_secret DEMO_PASSWORD=ibl_navigator_password JWT_SECRET=secret +API_MODE=[public | private] # utilized for remote deployment SUBDOMAINS=sub URL=example.com @@ -108,4 +109,4 @@ make sure to move over to the `master` branch by `git checkout master` `docker-compose -f docker-compose-deploy.yml pull` to get the ibl-navigator container `docker-compose -f docker-compose-deploy.yml up -d` -------------------------------------- \ No newline at end of file +------------------------------------- diff --git a/backend/iblapi.py b/backend/iblapi.py index 0449bd06..391d13d3 100644 --- a/backend/iblapi.py +++ b/backend/iblapi.py @@ -172,10 +172,12 @@ def do_req(subpath): # construct kwargs kwargs = {'as_dict': True} limit = int(request.values['__limit']) if '__limit' in values else None - order = request.values['__order'] if '__order' in values else None + order = request.values['__order'] if '__order' in values else 'KEY ASC' + page = int(request.values['__page']) if '__page' in values else 1 proj = json.loads(request.values['__proj']) if '__proj' in values else None - special_fields = ['__json', '__limit', '__order', '__proj', '__json_kwargs'] - for a in (v for v in values if v not in special_fields): + special_fields = ['__json', '__limit', '__order', '__proj', '__json_kwargs', + '__page'] + for a in (k for k, v in values.items() if k not in special_fields and v): # HACK: 'uuid' attrs -> UUID type (see also: datajoint-python #594) postargs[a] = UUID(values[a]) if 'uuid' in a else values[a] args = [postargs] if len(postargs) else [] @@ -186,9 +188,14 @@ def do_req(subpath): if '__json_kwargs' in values: json_kwargs = json.loads(request.values['__json_kwargs']) args = {} if not args else dj.AndList(args) - kwargs = {k: v for k, v in (('as_dict', True,), - ('limit', limit,), - ('order_by', order,)) if v is not None} + if limit == None: + kwargs = {k: v for k, v in (('as_dict', True,), + ('order_by', order,)) if v is not None} + else: + kwargs = {k: v for k, v in (('as_dict', True,), + ('limit', limit,), + ('order_by', order,), + ('offset', (page-1)*limit)) if v is not None} # 2) and dispatch app.logger.debug("args: '{}', kwargs: {}".format(args, kwargs)) if obj not in reqmap: @@ -216,8 +223,7 @@ def handle_q(subpath, args, proj, fetch_args=None, **kwargs): ((session * subject * lab * user) & arg).proj(flist) ''' app.logger.info("handle_q: subpath: '{}', args: {}".format(subpath, args)) - app.logger.info('key words: {}'.format(kwargs)) - + fetch_args = {} if fetch_args is None else fetch_args ret = [] post_process = None @@ -266,10 +272,12 @@ def handle_q(subpath, args, proj, fetch_args=None, **kwargs): q = ((acquisition.Session() * sess_proj * psych_curve * ephys_data * subject.Subject() * subject.SubjectLab() * subject.SubjectUser() * trainingStatus) & args & brain_restriction) - + q = q.proj(*proj) if proj else q dj.conn().query("SET SESSION max_join_size={}".format('18446744073709551615')) - q = q.proj(*proj).fetch(**fetch_args) if proj else q.fetch(**fetch_args) + ret_count = len(q) + ret = q.fetch(**fetch_args) dj.conn().query("SET SESSION max_join_size={}".format(original_max_join_size)) + return dumps({"records_count": ret_count, "records": ret}) elif subpath == 'subjpage': proj_restr = None for e in args: diff --git a/docker-compose-base.yml b/docker-compose-base.yml index 0e39fdce..ac65b847 100644 --- a/docker-compose-base.yml +++ b/docker-compose-base.yml @@ -8,7 +8,7 @@ x-net: &net services: iblapi: <<: *net - image: registry.vathes.com/ibl-navigator/iblapi:v0.5.3 # for internal demo + image: registry.vathes.com/ibl-navigator/iblapi:v0.6.0 # for internal demo # image: registry.vathes.com/ibl-navigator/iblapi:v0.1.0-public # for public demo environment: - DJ_USER=maho @@ -31,7 +31,7 @@ services: #cpu_period: 100ms ibl-navigator: <<: *net - image: registry.vathes.com/ibl-navigator/frontend:v0.4.2 # for internal demo + image: registry.vathes.com/ibl-navigator/frontend:v0.5.0 # for internal demo # image: registry.vathes.com/ibl-navigator/frontend:v0.1.0-public # for public demo healthcheck: test: curl --fail http://localhost:9000 || exit 1 @@ -39,7 +39,8 @@ services: retries: 20 ibl-node-server: <<: *net - image: registry.vathes.com/ibl-navigator/node-server:v0.3.0 # for internal demo + platform: linux/amd64 + image: registry.vathes.com/ibl-navigator/node-server:v0.4.0 # for internal demo # image: registry.vathes.com/ibl-navigator/node-server:v0.1.0-public # for public demo environment: - NODE_ENV=development @@ -71,7 +72,7 @@ services: # condition: service_healthy nginx: <<: *net - image: datajoint/nginx:v0.0.16 + image: datajoint/nginx:v0.0.18 environment: - ADD_zfrontend_TYPE=REST - ADD_zfrontend_ENDPOINT=ibl-navigator:9000 diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 58f2651e..471bb22b 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -35,6 +35,9 @@ services: service: ibl-node-server image: ibl-node-server:v0.0.0 # command: nodemon /src/server.js + # command: npm test + ports: + - "9222:9222" volumes: - ./node_server/app.js:/src/app.js <<: *net diff --git a/ibl-frontend/Dockerfile b/ibl-frontend/Dockerfile index 80462af8..953b003e 100644 --- a/ibl-frontend/Dockerfile +++ b/ibl-frontend/Dockerfile @@ -1,4 +1,10 @@ -FROM vathes/angulardev:angcli7.1.4-angbuild0.11.4 +# FROM vathes/angulardev:angcli7.1.4-angbuild0.11.4 + +FROM node:12-bullseye + +RUN \ + apt update && \ + apt install nginx -y WORKDIR /app/dist/pipeline-viewer @@ -10,10 +16,9 @@ COPY ./app.conf /etc/nginx/conf.d/default.conf CMD ["nginx", "-g", "daemon off;"] ADD ./frontend-content/package.json /app/ -ADD ./frontend-content/package-lock.json /app/ RUN \ cd /app && \ - npm install --save-dev @angular-devkit/build-angular > /dev/null + npm install ADD ./frontend-content /app @@ -23,7 +28,7 @@ COPY ./frontend-content/src/assets/addons/plotly.js /app/node_modules/plotly.js- RUN \ cd /app && \ - node --max_old_space_size=8192 /usr/local/lib/node_modules/@angular/cli/bin/ng build --prod + node --max_old_space_size=5120 /app/node_modules/@angular/cli/bin/ng build --configuration production # CMD ["http-server","-p", "8080" ,"-a","0.0.0.0"] diff --git a/ibl-frontend/dev.dockerfile b/ibl-frontend/dev.dockerfile index c3ff43e7..fe147890 100644 --- a/ibl-frontend/dev.dockerfile +++ b/ibl-frontend/dev.dockerfile @@ -1,5 +1,7 @@ # don't build -FROM vathes/angulardev:angcli7.1.4-angbuild0.11.4 +# FROM vathes/angulardev:angcli7.1.4-angbuild0.11.4 + +FROM node:12-bullseye HEALTHCHECK \ --timeout=3s \ @@ -10,12 +12,10 @@ HEALTHCHECK \ COPY ./entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] -CMD ["ng","serve","--host","0.0.0.0","--port","9000","--disable-host-check"] WORKDIR /app ADD ./frontend-content/package.json /app/ -ADD ./frontend-content/package-lock.json /app/ RUN \ npm install && \ npm install --only=dev @@ -24,5 +24,6 @@ ADD ./frontend-content /app COPY ./frontend-content/src/assets/addons/indigo-pink-ibl.css /app/node_modules/\@angular/material/prebuilt-themes/ COPY ./frontend-content/src/assets/addons/plotly.js /app/node_modules/plotly.js-dist/ +CMD ["node", "--max_old_space_size=5120", "/app/node_modules/@angular/cli/bin/ng", "serve", "--host", "0.0.0.0", "--port", "9000", "--disable-host-check"] - +# node --max_old_space_size=5120 /app/node_modules/@angular/cli/bin/ng serve --host 0.0.0.0 --port 9000 --disable-host-check 1> /app/src/output.log 2> /app/src/error.log diff --git a/ibl-frontend/frontend-content/angular.json b/ibl-frontend/frontend-content/angular.json index 763b0a3c..9521a3e7 100644 --- a/ibl-frontend/frontend-content/angular.json +++ b/ibl-frontend/frontend-content/angular.json @@ -23,16 +23,25 @@ "src/assets" ], "styles": [ - "node_modules/bootstrap/dist/css/bootstrap.min.css", + { + "input": "node_modules/@angular/material/prebuilt-themes/indigo-pink-ibl.css", + "inject": true + }, + { + "input": "src/assets/fonts/css/open-iconic-bootstrap.min.css", + "inject": true + }, "src/styles.css" ], "scripts": [ - // "node_modules/mathjax/MathJax.js", - // "node_modules/mathjax/jax/output/SVG/config.js", - // "node_modules/mathjax/extensions/MathMenu.js", - // "node_modules/mathjax/extensions/MathZoom.js", "node_modules/plotly.js-dist/plotly.js" - ] + ], + "vendorChunk": true, + "extractLicenses": false, + "buildOptimizer": false, + "sourceMap": true, + "optimization": false, + "namedChunks": true }, "configurations": { "production": { @@ -45,9 +54,7 @@ "optimization": true, "outputHashing": "all", "sourceMap": false, - "extractCss": true, "namedChunks": false, - "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, @@ -55,11 +62,16 @@ { "type": "initial", "maximumWarning": "2mb", - "maximumError": "7mb" + "maximumError": "10mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb" } ] } - } + }, + "defaultConfiguration": "" }, "serve": { "builder": "@angular-devkit/build-angular:dev-server", diff --git a/ibl-frontend/frontend-content/package.json b/ibl-frontend/frontend-content/package.json index b664f5c3..2cdbd7f1 100644 --- a/ibl-frontend/frontend-content/package.json +++ b/ibl-frontend/frontend-content/package.json @@ -11,56 +11,30 @@ }, "private": true, "dependencies": { - "@angular/animations": "^7.1.4", - "@angular/cdk": "^7.3.7", - "@angular/common": "~7.1.0", - "@angular/compiler": "~7.1.0", - "@angular/core": "~7.1.0", - "@angular/flex-layout": "^7.0.0-beta.24", - "@angular/forms": "~7.1.0", - "@angular/material": "^7.3.3", - "@angular/material-moment-adapter": "^8.1.2", - "@angular/platform-browser": "~7.1.0", - "@angular/platform-browser-dynamic": "~7.1.0", - "@angular/router": "~7.1.0", - "@types/mathjax": "0.0.35", + "@angular/animations": "^12.0.0", + "@angular/cdk": "^12.0.0", + "@angular/common": "^12.0.0", + "@angular/compiler": "^12.0.0", + "@angular/core": "^12.0.0", + "@angular/flex-layout": "^12.0.0-beta.35", + "@angular/forms": "^12.0.0", + "@angular/material": "^12.0.0", + "@angular/material-moment-adapter": "^12.0.0", + "@angular/platform-browser": "^12.0.0", + "@angular/platform-browser-dynamic": "^12.0.0", + "@angular/router": "^12.0.0", "@wizpanda/super-gif": "0.0.5", - "angular-plotly.js": "^1.3.2", - "body-parser": "^1.18.3", + "angular-plotly.js": "^4.0.4", "bootstrap": "^4.2.1", - "core-js": "^2.5.4", - "dotenv": "^8.0.0", - "express": "^4.16.4", - "jsonwebtoken": "^8.5.1", - "mathjax": "^2.7.5", - "moment": "^2.24.0", - "plotly.js": "^1.49.0", - "plotly.js-dist": "^1.44.4", - "request": "^2.88.0", - "rxjs": "~6.3.3", - "rxjs-compat": "^6.3.3", - "tslib": "^1.9.0", - "zone.js": "~0.8.26" + "moment": "^2.29.1", + "plotly.js": "^2.5.1", + "rxjs": "^7.4.0", + "rxjs-compat": "^6.6.7", + "zone.js": "^0.11.4" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.11.0", - "@angular/cli": "~7.1.3", - "@angular/compiler-cli": "~7.1.0", - "@angular/language-service": "~7.1.0", - "@types/node": "~8.9.4", - "@types/jasmine": "~2.8.8", - "@types/jasminewd2": "~2.0.3", - "codelyzer": "~4.5.0", - "jasmine-core": "~2.99.1", - "jasmine-spec-reporter": "~4.2.1", - "karma": "~3.1.1", - "karma-chrome-launcher": "~2.2.0", - "karma-coverage-istanbul-reporter": "~2.0.1", - "karma-jasmine": "~1.1.2", - "karma-jasmine-html-reporter": "^0.2.2", - "protractor": "~5.4.0", - "ts-node": "~7.0.0", - "tslint": "~5.11.0", - "typescript": "~3.1.6" + "@angular-devkit/build-angular": "^12.0.0", + "@angular/cli": "^12.0.0", + "@angular/compiler-cli": "^12.0.0" } } diff --git a/ibl-frontend/frontend-content/src/app/app.module.ts b/ibl-frontend/frontend-content/src/app/app.module.ts index 470bd5c7..2b259c63 100644 --- a/ibl-frontend/frontend-content/src/app/app.module.ts +++ b/ibl-frontend/frontend-content/src/app/app.module.ts @@ -6,30 +6,28 @@ import { PlotlyModule } from 'angular-plotly.js'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { Routes, RouterModule } from '@angular/router'; -import { MatSelectModule, - MatAutocompleteModule, - MatIconModule, - MatInputModule, - MatCheckboxModule, - MatRadioModule, - MatNativeDateModule, - MatDatepickerModule, - MatSlideToggleModule, - MatCardModule, - MatButtonModule, - MatTableModule, - MatPaginatorModule, - MatSortModule, - MatSliderModule, - MatExpansionModule, - MatDialogModule, - MatTreeModule, - MatFormFieldModule } from '@angular/material'; import { MatMomentDateModule, MAT_MOMENT_DATE_ADAPTER_OPTIONS } from '@angular/material-moment-adapter'; +import { MatNativeDateModule } from '@angular/material/core'; import { FlexLayoutModule } from '@angular/flex-layout'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; - - +import {MatSelectModule} from '@angular/material/select'; +import {MatAutocompleteModule} from '@angular/material/autocomplete'; +import {MatIconModule} from '@angular/material/icon'; +import {MatInputModule} from '@angular/material/input'; +import {MatCheckboxModule} from '@angular/material/checkbox'; +import {MatRadioModule} from '@angular/material/radio'; +import {MatDatepickerModule} from '@angular/material/datepicker'; +import {MatSlideToggleModule} from '@angular/material/slide-toggle'; +import {MatCardModule} from '@angular/material/card'; +import {MatButtonModule} from '@angular/material/button'; +import {MatTableModule} from '@angular/material/table'; +import {MatPaginatorModule} from '@angular/material/paginator'; +import {MatSortModule} from '@angular/material/sort'; +import {MatSliderModule} from '@angular/material/slider'; +import {MatExpansionModule} from '@angular/material/expansion'; +import {MatDialogModule} from '@angular/material/dialog'; +import {MatTreeModule} from '@angular/material/tree'; +import {MatFormFieldModule} from '@angular/material/form-field'; import { AuthGuard } from './auth/auth-guard.service'; import { AppComponent } from './app.component'; import { EachBatchComponent } from './each-batch/each-batch.component'; @@ -64,6 +62,7 @@ import { PsthPlotsComponent } from './cell-list/cell/psth-plots/psth-plots.compo import { QualityControlComponent } from './quality-control/quality-control.component'; import { DriftmapComponent } from './quality-control/driftmap/driftmap.component'; import { SpinningBrainComponent } from './mouse-list/mouse/spinning-brain/spinning-brain.component'; +import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; PlotlyModule.plotlyjs = PlotlyJS; @@ -170,6 +169,7 @@ const appRoutes: Routes = [ FormsModule, HttpClientModule, RouterModule.forRoot(appRoutes), + MatProgressSpinnerModule, MatSelectModule, MatAutocompleteModule, MatIconModule, MatInputModule, MatCheckboxModule, MatRadioModule, MatNativeDateModule, MatDatepickerModule, MatMomentDateModule, MatSlideToggleModule, MatCardModule, MatButtonModule, MatTableModule, MatPaginatorModule, MatSortModule, MatSliderModule, MatExpansionModule, diff --git a/ibl-frontend/frontend-content/src/app/auth/auth-guard.service.ts b/ibl-frontend/frontend-content/src/app/auth/auth-guard.service.ts index ae23c2dc..564d1362 100644 --- a/ibl-frontend/frontend-content/src/app/auth/auth-guard.service.ts +++ b/ibl-frontend/frontend-content/src/app/auth/auth-guard.service.ts @@ -1,5 +1,5 @@ import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, CanActivateChild } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; import { AuthService } from './auth.service'; diff --git a/ibl-frontend/frontend-content/src/app/cell-list/cell-list.component.html b/ibl-frontend/frontend-content/src/app/cell-list/cell-list.component.html index 175303a8..08ed09a6 100644 --- a/ibl-frontend/frontend-content/src/app/cell-list/cell-list.component.html +++ b/ibl-frontend/frontend-content/src/app/cell-list/cell-list.component.html @@ -85,9 +85,9 @@
(Total clusters for probe {{probeIndex}}: {{cellsByProbeIns.length}})
- + - +
diff --git a/ibl-frontend/frontend-content/src/app/cell-list/cell-list.component.ts b/ibl-frontend/frontend-content/src/app/cell-list/cell-list.component.ts index ecfc93b8..53402d39 100644 --- a/ibl-frontend/frontend-content/src/app/cell-list/cell-list.component.ts +++ b/ibl-frontend/frontend-content/src/app/cell-list/cell-list.component.ts @@ -277,7 +277,7 @@ export class CellListComponent implements OnInit, OnDestroy, DoCheck { private fullPSTHLoaded = new Subject(); private fullRasterPSTHLoaded = new Subject(); @Input() sessionInfo: Object; - @ViewChild('navTable') el_nav: ElementRef; + @ViewChild('navTable', {static: true}) el_nav: ElementRef; // @ViewChild('brainGIF') brain_gif: ElementRef; // spinningBrain; @@ -1968,68 +1968,68 @@ export class CellListComponent implements OnInit, OnDestroy, DoCheck { for (let templateType of Object.entries(this.psthLookup[psth['cluster_id']]['data'])) { // console.log('templateType: ', templateType); if (psth['psth_time']) { - this.psthLookup[psth['cluster_id']]['data'][parseInt(templateType[0], 10)]['x'] = psth['psth_time'].split(','); + this.psthLookup[psth['cluster_id']]['data'][parseInt(templateType[0], 10)]['x'] = (psth['psth_time'].split(',')).map(Number);; } switch (templateType[0]) { case '0': if (psth['psth_left_upper']) { - this.psthLookup[psth['cluster_id']]['data'][0]['y'] = psth['psth_left_upper'].split(','); + this.psthLookup[psth['cluster_id']]['data'][0]['y'] = (psth['psth_left_upper'].split(',')).map(Number); } break; case '1': if (psth['psth_left']) { - this.psthLookup[psth['cluster_id']]['data'][1]['y'] = psth['psth_left'].split(','); + this.psthLookup[psth['cluster_id']]['data'][1]['y'] = (psth['psth_left'].split(',')).map(Number); } break; case '2': if (psth['psth_left_lower']) { - this.psthLookup[psth['cluster_id']]['data'][2]['y'] = psth['psth_left_lower'].split(','); + this.psthLookup[psth['cluster_id']]['data'][2]['y'] = (psth['psth_left_lower'].split(',')).map(Number); } break; case '3': if (psth['psth_right_upper']) { - this.psthLookup[psth['cluster_id']]['data'][3]['y'] = psth['psth_right_upper'].split(','); + this.psthLookup[psth['cluster_id']]['data'][3]['y'] = (psth['psth_right_upper'].split(',')).map(Number); } break; case '4': if (psth['psth_right']) { - this.psthLookup[psth['cluster_id']]['data'][4]['y'] = psth['psth_right'].split(','); + this.psthLookup[psth['cluster_id']]['data'][4]['y'] = (psth['psth_right'].split(',')).map(Number); } break; case '5': if (psth['psth_right_lower']) { - this.psthLookup[psth['cluster_id']]['data'][5]['y'] = psth['psth_right_lower'].split(','); + this.psthLookup[psth['cluster_id']]['data'][5]['y'] = (psth['psth_right_lower'].split(',')).map(Number); } break; case '6': if (psth['psth_incorrect_upper']) { - this.psthLookup[psth['cluster_id']]['data'][6]['y'] = psth['psth_incorrect_upper'].split(','); + this.psthLookup[psth['cluster_id']]['data'][6]['y'] = (psth['psth_incorrect_upper'].split(',')).map(Number); } break; case '7': if (psth['psth_incorrect']) { - this.psthLookup[psth['cluster_id']]['data'][7]['y'] = psth['psth_incorrect'].split(','); + this.psthLookup[psth['cluster_id']]['data'][7]['y'] = (psth['psth_incorrect'].split(',')).map(Number); } break; case '8': if (psth['psth_incorrect_lower']) { - this.psthLookup[psth['cluster_id']]['data'][8]['y'] = psth['psth_incorrect_lower'].split(','); + this.psthLookup[psth['cluster_id']]['data'][8]['y'] = (psth['psth_incorrect_lower'].split(',')).map(Number); } break; case '9': if (psth['psth_all_upper']) { - this.psthLookup[psth['cluster_id']]['data'][9]['y'] = psth['psth_all_upper'].split(','); + this.psthLookup[psth['cluster_id']]['data'][9]['y'] = (psth['psth_all_upper'].split(',')).map(Number); } break; case '10': if (psth['psth_all']) { - this.psthLookup[psth['cluster_id']]['data'][10]['y'] = psth['psth_all'].split(','); + this.psthLookup[psth['cluster_id']]['data'][10]['y'] = (psth['psth_all'].split(',')).map(Number); } break; case '11': if (psth['psth_all_lower']) { - this.psthLookup[psth['cluster_id']]['data'][11]['y'] = psth['psth_all_lower'].split(','); + this.psthLookup[psth['cluster_id']]['data'][11]['y'] = (psth['psth_all_lower'].split(',')).map(Number); } break; } @@ -2037,7 +2037,7 @@ export class CellListComponent implements OnInit, OnDestroy, DoCheck { this.psthLookup[psth['cluster_id']]['layout']['title']['text'] = `PSTH, aligned to ${psth['event']} time`; - this.psthLookup[psth['cluster_id']]['layout']['xaxis']['range'] = psth['psth_x_lim'] ? psth['psth_x_lim'].split(',') : []; + this.psthLookup[psth['cluster_id']]['layout']['xaxis']['range'] = psth['psth_x_lim'] ? (psth['psth_x_lim'].split(',')).map(Number) : []; this.psthLookup[psth['cluster_id']]['layout']['width'] = 770; this.psthLookup[psth['cluster_id']]['layout']['height'] = 420; @@ -2395,7 +2395,7 @@ export class CellListComponent implements OnInit, OnDestroy, DoCheck { } // console.log('xAcgArray: ', xAcgArray); this.autocorrelogramLookup[acg['cluster_id']]['data'][0]['x'] = xAcgArray; - this.autocorrelogramLookup[acg['cluster_id']]['data'][0]['y'] = acg['acg'].split(','); + this.autocorrelogramLookup[acg['cluster_id']]['data'][0]['y'] = (acg['acg'].split(',')).map(Number); this.autocorrelogramLookup[acg['cluster_id']]['layout']['yaxis']['range'] = acg['plot_ylim'] // original sizing : 400 height / 580 width diff --git a/ibl-frontend/frontend-content/src/app/cell-list/cell/psth-plots/psth-plots.component.ts b/ibl-frontend/frontend-content/src/app/cell-list/cell/psth-plots/psth-plots.component.ts index ca0cb90c..d6a08fc0 100644 --- a/ibl-frontend/frontend-content/src/app/cell-list/cell/psth-plots/psth-plots.component.ts +++ b/ibl-frontend/frontend-content/src/app/cell-list/cell/psth-plots/psth-plots.component.ts @@ -51,7 +51,7 @@ export class PsthPlotsComponent implements OnInit, OnDestroy, OnChanges { @Input() clusterInfo: Object; @Input() selectedEvent: String; - @ViewChild('PSTH_plot') el: ElementRef; + @ViewChild('PSTH_plot', {static: true}) el: ElementRef; constructor(public cellPlotsService: CellPlotsService) { } ngOnInit() { diff --git a/ibl-frontend/frontend-content/src/app/cell-list/cell/raster-plots/raster-plots.component.ts b/ibl-frontend/frontend-content/src/app/cell-list/cell/raster-plots/raster-plots.component.ts index 79f30ce1..42218634 100644 --- a/ibl-frontend/frontend-content/src/app/cell-list/cell/raster-plots/raster-plots.component.ts +++ b/ibl-frontend/frontend-content/src/app/cell-list/cell/raster-plots/raster-plots.component.ts @@ -55,7 +55,7 @@ export class RasterPlotsComponent implements OnInit, OnDestroy { @Input() clusterInfo: Object; - @ViewChild('raster_plots') el: ElementRef; + @ViewChild('raster_plots', {static: true}) el: ElementRef; @Output() eventSelected: EventEmitter = new EventEmitter(); constructor(public cellPlotsService: CellPlotsService) { } diff --git a/ibl-frontend/frontend-content/src/app/daily-summary/daily-summary.component.ts b/ibl-frontend/frontend-content/src/app/daily-summary/daily-summary.component.ts index 1be5c42e..8b03a1af 100644 --- a/ibl-frontend/frontend-content/src/app/daily-summary/daily-summary.component.ts +++ b/ibl-frontend/frontend-content/src/app/daily-summary/daily-summary.component.ts @@ -2,7 +2,9 @@ import { Component, OnInit, OnDestroy, ElementRef, ViewChild } from '@angular/co import { Subscription, Observable, Subject } from 'rxjs'; import { FormControl, FormGroup, FormArray } from '@angular/forms'; import { map, startWith } from 'rxjs/operators'; -import { MatPaginator, MatTableDataSource, MatSort } from '@angular/material'; +import { MatPaginator} from '@angular/material/paginator'; +import { MatTableDataSource } from '@angular/material/table'; +import { MatSort } from '@angular/material/sort'; import { trigger, state, style, animate, transition } from '@angular/animations'; import { DailySummaryService } from './daily-summary.service'; import { FilterStoreService } from '../filter-store.service'; diff --git a/ibl-frontend/frontend-content/src/app/daily-summary/summary-plots/summary-plots.component.ts b/ibl-frontend/frontend-content/src/app/daily-summary/summary-plots/summary-plots.component.ts index d68ea5c2..04d33602 100644 --- a/ibl-frontend/frontend-content/src/app/daily-summary/summary-plots/summary-plots.component.ts +++ b/ibl-frontend/frontend-content/src/app/daily-summary/summary-plots/summary-plots.component.ts @@ -59,10 +59,10 @@ export class SummaryPlotsComponent implements OnInit, OnDestroy { @Input() plotsCollapsed: {}; constructor(public dailySummaryService: DailySummaryService) { } - @ViewChild('waterWeightPlot') WWIplot: ElementRef; - @ViewChild('trialCountsSessionDurationPlot') TCSDplot: ElementRef; - @ViewChild('performanceReactionTimePlot') PRTplot: ElementRef; - @ViewChild('contrastHeatmapPlot') CHplot: ElementRef; + @ViewChild('waterWeightPlot', {static: true}) WWIplot: ElementRef; + @ViewChild('trialCountsSessionDurationPlot', {static: true}) TCSDplot: ElementRef; + @ViewChild('performanceReactionTimePlot', {static: true}) PRTplot: ElementRef; + @ViewChild('contrastHeatmapPlot', {static: true}) CHplot: ElementRef; ngOnInit() { const WWIplotElem = this.WWIplot.nativeElement; const TCSDplotElem = this.TCSDplot.nativeElement; diff --git a/ibl-frontend/frontend-content/src/app/mouse-list/mouse-list.component.html b/ibl-frontend/frontend-content/src/app/mouse-list/mouse-list.component.html index ebbccdce..472e856b 100644 --- a/ibl-frontend/frontend-content/src/app/mouse-list/mouse-list.component.html +++ b/ibl-frontend/frontend-content/src/app/mouse-list/mouse-list.component.html @@ -102,11 +102,6 @@

Only show mice with ready for delay training status

-
- - Only show mice with resolved probe trajectories. - -
diff --git a/ibl-frontend/frontend-content/src/app/mouse-list/mouse-list.component.ts b/ibl-frontend/frontend-content/src/app/mouse-list/mouse-list.component.ts index 794a1a87..f793f860 100644 --- a/ibl-frontend/frontend-content/src/app/mouse-list/mouse-list.component.ts +++ b/ibl-frontend/frontend-content/src/app/mouse-list/mouse-list.component.ts @@ -2,7 +2,9 @@ import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'; import { Subscription, Observable } from 'rxjs'; import { FormControl, FormGroup, FormArray } from '@angular/forms'; import { map, startWith } from 'rxjs/operators'; -import { MatPaginator, MatTableDataSource, MatSort } from '@angular/material'; +import { MatPaginator} from '@angular/material/paginator'; +import { MatTableDataSource } from '@angular/material/table'; +import { MatSort } from '@angular/material/sort'; import { AllMiceService } from './all-mice.service'; import { FilterStoreService } from '../filter-store.service'; import * as moment from 'moment'; @@ -249,7 +251,7 @@ export class MouseListComponent implements OnInit, OnDestroy { for (const date of this.mice_menu['subject_birth_date']) { birthDates.push(date); } - return birthDates.includes(d.toISOString().split('T')[0]); + return (d == null ? true : birthDates.includes(d.toISOString().split('T')[0])); }; } @@ -324,7 +326,7 @@ export class MouseListComponent implements OnInit, OnDestroy { filterRequests(focusedField?: string) { const filterList = Object.entries(this.mouse_filter_form.getRawValue()); const requestFilter = {}; - filterList.forEach(filter => { + filterList.forEach((filter: Array) => { // filter is [["lab_name_control", "somelab"], ["subject_nickname_control", null]...] const filterKey = filter[0].split('_control')[0]; // filter[0] is control name like 'lab_name_control' if (filter[1] && filterKey !== focusedField) { diff --git a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/animated-psych-curve-plot/animated-psych-curve-plot.component.ts b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/animated-psych-curve-plot/animated-psych-curve-plot.component.ts index 737c0395..98d9d0ee 100644 --- a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/animated-psych-curve-plot/animated-psych-curve-plot.component.ts +++ b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/animated-psych-curve-plot/animated-psych-curve-plot.component.ts @@ -20,7 +20,7 @@ export class AnimatedPsychCurvePlotComponent implements OnInit { private sessionQuerySubscription: Subscription; constructor(public mousePlotsService: MousePlotsService, public allSessionsService: AllSessionsService) { } @Input() mouseInfo: Object; - @ViewChild('animatedPsychCurvePlot') element: ElementRef; + @ViewChild('animatedPsychCurvePlot', {static: true}) element: ElementRef; ngOnInit() { this.showInfo = false; const initialScreenSize = window.innerWidth; diff --git a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/by-date-result-plots/by-date-result-plots.component.ts b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/by-date-result-plots/by-date-result-plots.component.ts index 06be19b5..f68d4a48 100644 --- a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/by-date-result-plots/by-date-result-plots.component.ts +++ b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/by-date-result-plots/by-date-result-plots.component.ts @@ -174,18 +174,15 @@ export class ByDateResultPlotsComponent implements OnInit, OnDestroy { @Output() byDateResultPlotsAvailability: EventEmitter = new EventEmitter(); @Input() mouseInfo: Object; constructor(public mousePlotsService: MousePlotsService) { } - // @ViewChild('datePsychCurvePlot') elPsych: ElementRef; - // @ViewChild('dateRTContrastPlot') elRTContrast: ElementRef; - // @ViewChild('dateRTTrialNumPlot') elRTTrialNum: ElementRef; - @ViewChild('datePsychCurvePlot1') elPsych1: ElementRef; - @ViewChild('dateRTContrastPlot1') elRTContrast1: ElementRef; - @ViewChild('dateRTTrialNumPlot1') elRTTrialNum1: ElementRef; - @ViewChild('datePsychCurvePlot2') elPsych2: ElementRef; - @ViewChild('dateRTContrastPlot2') elRTContrast2: ElementRef; - @ViewChild('dateRTTrialNumPlot2') elRTTrialNum2: ElementRef; - @ViewChild('datePsychCurvePlot3') elPsych3: ElementRef; - @ViewChild('dateRTContrastPlot3') elRTContrast3: ElementRef; - @ViewChild('dateRTTrialNumPlot3') elRTTrialNum3: ElementRef; + @ViewChild('datePsychCurvePlot1', {static: true}) elPsych1: ElementRef; + @ViewChild('dateRTContrastPlot1', {static: true}) elRTContrast1: ElementRef; + @ViewChild('dateRTTrialNumPlot1', {static: true}) elRTTrialNum1: ElementRef; + @ViewChild('datePsychCurvePlot2', {static: true}) elPsych2: ElementRef; + @ViewChild('dateRTContrastPlot2', {static: true}) elRTContrast2: ElementRef; + @ViewChild('dateRTTrialNumPlot2', {static: true}) elRTTrialNum2: ElementRef; + @ViewChild('datePsychCurvePlot3', {static: true}) elPsych3: ElementRef; + @ViewChild('dateRTContrastPlot3', {static: true}) elRTContrast3: ElementRef; + @ViewChild('dateRTTrialNumPlot3', {static: true}) elRTTrialNum3: ElementRef; @HostListener('window:resize', ['$event.target']) onresize(event) { this.newScreenWidth = event.innerWidth; diff --git a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/contrast-heatmap-plot/contrast-heatmap-plot.component.ts b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/contrast-heatmap-plot/contrast-heatmap-plot.component.ts index daa0aa4f..d78ea57a 100644 --- a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/contrast-heatmap-plot/contrast-heatmap-plot.component.ts +++ b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/contrast-heatmap-plot/contrast-heatmap-plot.component.ts @@ -98,7 +98,7 @@ export class ContrastHeatmapPlotComponent implements OnInit, OnDestroy { @Output() contrastHeatmapPlotAvailability: EventEmitter = new EventEmitter(); @Input() mouseInfo: Object; - @ViewChild('contrastHeatmapPlot') elem: ElementRef; + @ViewChild('contrastHeatmapPlot', {static: true}) elem: ElementRef; constructor(public mousePlotsService: MousePlotsService) { } @HostListener('window:resize', ['$event.target']) onresize(event) { diff --git a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/fit-par-plots/fit-par-plots.component.ts b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/fit-par-plots/fit-par-plots.component.ts index 621d038c..65b3a28b 100644 --- a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/fit-par-plots/fit-par-plots.component.ts +++ b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/fit-par-plots/fit-par-plots.component.ts @@ -57,7 +57,7 @@ export class FitParPlotsComponent implements OnInit, OnDestroy { @Input() mouseInfo: Object; constructor(public mousePlotsService: MousePlotsService) { } - @ViewChild('fitParPlots') elem: ElementRef; + @ViewChild('fitParPlots', {static: true}) elem: ElementRef; smallScreenLayout = { 'font.size': '10', width: '516', diff --git a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/performance-reaction-time-plot/performance-reaction-time-plot.component.ts b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/performance-reaction-time-plot/performance-reaction-time-plot.component.ts index 8abab434..218d3e0f 100644 --- a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/performance-reaction-time-plot/performance-reaction-time-plot.component.ts +++ b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/performance-reaction-time-plot/performance-reaction-time-plot.component.ts @@ -105,7 +105,7 @@ export class PerformanceReactionTimePlotComponent implements OnInit, OnDestroy { @Output() PRPPlotAvailability: EventEmitter = new EventEmitter(); constructor(public mousePlotsService: MousePlotsService) { } - @ViewChild('performanceReactionTimePlot') el: ElementRef; + @ViewChild('performanceReactionTimePlot', {static: true}) el: ElementRef; @HostListener('window:resize', ['$event.target']) onresize(event) { this.newScreenWidth = event.innerWidth; const responsivePRTplot = this.d3.select(this.el.nativeElement).node(); diff --git a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/spinning-brain/spinning-brain.component.ts b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/spinning-brain/spinning-brain.component.ts index 7c3f0a03..d3fc7dde 100644 --- a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/spinning-brain/spinning-brain.component.ts +++ b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/spinning-brain/spinning-brain.component.ts @@ -14,7 +14,7 @@ export class SpinningBrainComponent implements OnInit, OnDestroy { private spinningBrainSubscription: Subscription; @Input() mouseInfo: Object; - @ViewChild('brainGIF') brain_gif: ElementRef; + @ViewChild('brainGIF', {static: true}) brain_gif: ElementRef; spinningBrain: any; spinningBrainSrc: string = ''; base64GIFsrc = ''; diff --git a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/trial-counts-session-duration/trial-counts-session-duration.component.ts b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/trial-counts-session-duration/trial-counts-session-duration.component.ts index 37d4e649..bb34c843 100644 --- a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/trial-counts-session-duration/trial-counts-session-duration.component.ts +++ b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/trial-counts-session-duration/trial-counts-session-duration.component.ts @@ -107,7 +107,7 @@ export class TrialCountsSessionDurationComponent implements OnInit, OnDestroy { @Input() mouseInfo: Object; constructor(public mousePlotsService: MousePlotsService) { } - @ViewChild('trialCountsSessionDurationPlot') el: ElementRef; + @ViewChild('trialCountsSessionDurationPlot', {static: true}) el: ElementRef; @HostListener('window:resize', ['$event.target']) onresize(event) { this.newScreenWidth = event.innerWidth; diff --git a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/water-weight-plot/water-weight-plot.component.ts b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/water-weight-plot/water-weight-plot.component.ts index 1e7c3dc8..18658601 100644 --- a/ibl-frontend/frontend-content/src/app/mouse-list/mouse/water-weight-plot/water-weight-plot.component.ts +++ b/ibl-frontend/frontend-content/src/app/mouse-list/mouse/water-weight-plot/water-weight-plot.component.ts @@ -122,7 +122,7 @@ export class WaterWeightPlotComponent implements OnInit, OnDestroy { @Output() WIWPlotAvailability: EventEmitter = new EventEmitter(); constructor(public mousePlotsService: MousePlotsService) { } - @ViewChild('waterIntake_weight_plot') el: ElementRef; + @ViewChild('waterIntake_weight_plot', {static: true}) el: ElementRef; @HostListener('window:resize', ['$event.target']) onresize(event) { this.newScreenWidth = event.innerWidth; // console.log('new screenwidth: ', this.newScreenWidth); diff --git a/ibl-frontend/frontend-content/src/app/overview/overview.component.html b/ibl-frontend/frontend-content/src/app/overview/overview.component.html index b1075c84..ddec10c5 100644 --- a/ibl-frontend/frontend-content/src/app/overview/overview.component.html +++ b/ibl-frontend/frontend-content/src/app/overview/overview.component.html @@ -1,5 +1,5 @@
-

User Guide

- +

User Guide

+
\ No newline at end of file diff --git a/ibl-frontend/frontend-content/src/app/plots/view-sample-plots/sample-plot/sample-plot.component.ts b/ibl-frontend/frontend-content/src/app/plots/view-sample-plots/sample-plot/sample-plot.component.ts index e3502dc3..6b2996de 100644 --- a/ibl-frontend/frontend-content/src/app/plots/view-sample-plots/sample-plot/sample-plot.component.ts +++ b/ibl-frontend/frontend-content/src/app/plots/view-sample-plots/sample-plot/sample-plot.component.ts @@ -18,7 +18,7 @@ export class SamplePlotComponent implements OnInit, OnChanges, OnDestroy { private plotsSubscription: Subscription; - @ViewChild('samplePlot') el: ElementRef; + @ViewChild('samplePlot', {static: true}) el: ElementRef; constructor(public plotsService: PlotsService, @Inject(ViewSamplePlotsComponent) public VSPComp: ViewSamplePlotsComponent) {} ngOnInit() { diff --git a/ibl-frontend/frontend-content/src/app/plots/view-sample-plots/view-sample-plots.component.ts b/ibl-frontend/frontend-content/src/app/plots/view-sample-plots/view-sample-plots.component.ts index 27790562..5dd08493 100644 --- a/ibl-frontend/frontend-content/src/app/plots/view-sample-plots/view-sample-plots.component.ts +++ b/ibl-frontend/frontend-content/src/app/plots/view-sample-plots/view-sample-plots.component.ts @@ -26,10 +26,10 @@ export class ViewSamplePlotsComponent implements OnInit, OnDestroy { private somePostSubscription: Subscription; - @ViewChild('samplePlot2') el: ElementRef; - @ViewChild('samplePlot_psych') el2: ElementRef; + @ViewChild('samplePlot2', {static: true}) el: ElementRef; + @ViewChild('samplePlot_psych', {static: true}) el2: ElementRef; - @ViewChild(PlotMenuToggleComponent) PMTComp: PlotMenuToggleComponent; + @ViewChild('PlotMenuToggleComponent', {static: true}) PMTComp: PlotMenuToggleComponent; @Input() selectedPlotChange: PlotMenuToggleComponent; constructor(public plotsService: PlotsService) { } diff --git a/ibl-frontend/frontend-content/src/app/session-list/all-sessions.service.ts b/ibl-frontend/frontend-content/src/app/session-list/all-sessions.service.ts index 167183d8..c90d911f 100644 --- a/ibl-frontend/frontend-content/src/app/session-list/all-sessions.service.ts +++ b/ibl-frontend/frontend-content/src/app/session-list/all-sessions.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Subject } from 'rxjs'; +import { Subject, Observable } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { environment } from '../../environments/environment'; @@ -7,6 +7,30 @@ import { environment } from '../../environments/environment'; const BACKEND_API_URL = environment.backend_url; +export interface SessionRecord { + mouse_id: number; + session_date: string; + session_lab: string; + subject_nickname: string; + subject_birth_date: string; + session_start_time: string; + task_protocol: string; + subject_line: string; + responsible_user: string; + session_uuid: string; + sex: string; + subject_uuid: string; + nplot: string; + nprobe: string; + session_project: string; + good4bmap: string; +} + +interface SessionApi { + records: SessionRecord[]; + records_count: number; +} + @Injectable({ providedIn: 'root' }) @@ -36,6 +60,11 @@ export class AllSessionsService { return this.http.post(BACKEND_API_URL + '/sessions/', sessionFilters, { responseType: 'json'}) } + getSessions(body: Object): Observable { + const requestUrl = BACKEND_API_URL + '/sessions'; + return this.http.post(requestUrl, body, { responseType: 'json' }); + } + getAllSessions() { let start = new Date(); this.http.get(BACKEND_API_URL + `/sessions`) @@ -88,7 +117,7 @@ export class AllSessionsService { (filteredSessionsData) => { let end = new Date(); // console.log(`It took ${Number(end) - Number(start)}ms to retrieve the session list information`) - this.retrievedSessions = filteredSessionsData; + this.retrievedSessions = filteredSessionsData['records']; // console.log('retrievedSessions data are: '); // console.log(this.retrievedSessions); this.newSessionsLoaded.next(this.retrievedSessions); diff --git a/ibl-frontend/frontend-content/src/app/session-list/session-list.component.css b/ibl-frontend/frontend-content/src/app/session-list/session-list.component.css index 690ed97c..7fadc72d 100644 --- a/ibl-frontend/frontend-content/src/app/session-list/session-list.component.css +++ b/ibl-frontend/frontend-content/src/app/session-list/session-list.component.css @@ -105,6 +105,20 @@ label { display: block; } +.session-list-loading-shade { + position: absolute; + /* top: 0; */ + left: 0; + /* bottom: 56px; */ + right: 0; + background: rgba(0, 0, 0, 0.15); + z-index: 9; + display: flex; + align-items: center; + justify-content: center; + height: 100%; +} + .loading-icon.loading.initial { border: 1px solid gray; padding: 36px 24px; @@ -118,6 +132,7 @@ label { .table-container { width: 100%; + position: relative; overflow-x: auto; } td.mat-cell, @@ -229,7 +244,7 @@ mat-checkbox.mouse_sex_menu_chbox { .form-submit-button-area { display: flex; - flex-direction: row; + flex-direction: column; } .nplot_status_filter { diff --git a/ibl-frontend/frontend-content/src/app/session-list/session-list.component.html b/ibl-frontend/frontend-content/src/app/session-list/session-list.component.html index a661b194..4b558455 100644 --- a/ibl-frontend/frontend-content/src/app/session-list/session-list.component.html +++ b/ibl-frontend/frontend-content/src/app/session-list/session-list.component.html @@ -1,5 +1,6 @@ -
+
+

List of Sessions

@@ -31,6 +32,15 @@

+ + + + + + +
+ +

@@ -153,7 +163,7 @@

-
Selected Brain Region: + + // This is the tree node template for leaf nodes
  • - + // use a disabled button to provide padding for tree leaf {{node.display}}
  • - + // This is the tree node template for expandable nodes
  • @@ -193,24 +203,24 @@

  • -
    +

    -->
    -

    - -
    -
    - -
    -
    - +
    + +
    +
    + +
    +
    + +
    -
    -
    +
    -

    - Loading time for the sessions may take a while depending on your internet connection. We appreciate your patience as we load the full list of sessions. -

    +

    - +
    + +
    +
    @@ -334,7 +345,9 @@

    Lab
    - +
    diff --git a/ibl-frontend/frontend-content/src/app/session-list/session-list.component.ts b/ibl-frontend/frontend-content/src/app/session-list/session-list.component.ts index d64b8c16..8e36f544 100644 --- a/ibl-frontend/frontend-content/src/app/session-list/session-list.component.ts +++ b/ibl-frontend/frontend-content/src/app/session-list/session-list.component.ts @@ -1,10 +1,14 @@ import { Component, OnInit, OnDestroy, ViewChild, Input } from '@angular/core'; +import {HttpClient} from '@angular/common/http'; import { FormControl, FormGroup, FormArray, AbstractControl} from '@angular/forms'; +import { Subscription, Observable, merge, of as observableOf } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; -import { Subscription, Observable } from 'rxjs'; -import { map, startWith } from 'rxjs/operators'; -import { MatPaginator, MatTableDataSource, MatSort, MatTreeNestedDataSource } from '@angular/material'; -import { AllSessionsService } from './all-sessions.service'; +import { map, startWith, catchError, switchMap } from 'rxjs/operators'; +import { MatTreeNestedDataSource } from '@angular/material/tree'; +import { MatPaginator} from '@angular/material/paginator'; +import { MatTableDataSource } from '@angular/material/table'; +import { MatSort } from '@angular/material/sort'; +import { AllSessionsService, SessionRecord } from './all-sessions.service'; import { FilterStoreService } from '../filter-store.service'; import * as moment from 'moment'; import * as _ from 'lodash'; @@ -50,6 +54,7 @@ export class SessionListComponent implements OnInit, OnDestroy { responsible_user: new FormControl() }); isLoading; + isLoadingTable = true; initialLoad; filterExpanded; allSessions; @@ -109,12 +114,18 @@ export class SessionListComponent implements OnInit, OnDestroy { selectedSession = {}; + sessionService: AllSessionsService | null; + sessionRecords: SessionRecord[] = []; + sessionRecordLength = 0; + isLoadingResults = true; + private sessionsSubscription: Subscription; private sessionMenuSubscription: Subscription; private allSessionMenuSubscription: Subscription; private reqSessionsSubscription: Subscription; - constructor(private route: ActivatedRoute, private router: Router, public allSessionsService: AllSessionsService, public filterStoreService: FilterStoreService) { + constructor(private route: ActivatedRoute, private router: Router, public allSessionsService: AllSessionsService, public filterStoreService: FilterStoreService, + private _httpClient: HttpClient) { this.treeDataSource.data = this.brainRegionTree // Initalized the material table this.dataSource = new MatTableDataSource(); @@ -240,7 +251,6 @@ export class SessionListComponent implements OnInit, OnDestroy { } } } - // Check storage to see if there is anything there // Check for paginator if (this.filterStoreService.sessionPaginator) { @@ -280,7 +290,7 @@ export class SessionListComponent implements OnInit, OnDestroy { } else { // Else fetch from database - await this.fetchSessions(); + // await this.fetchSessions(); this.initialLoad = false; } @@ -297,7 +307,7 @@ export class SessionListComponent implements OnInit, OnDestroy { // Create Menu, Update table view and set loading to false this.createMenu(this.restrictedSessions); - this.updateTableView(this.restrictedSessions); + //this.updateTableView(this.restrictedSessions); this.isLoading = false; if (this.filterStoreService.sessionPaginator) { @@ -319,6 +329,83 @@ export class SessionListComponent implements OnInit, OnDestroy { this.buildLookup(); }) } + + ngAfterViewInit() { + this.isLoading = false; + this.sessionService = new AllSessionsService(this._httpClient); + // If the user changes the sort order, reset back to the first page. + this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); + let newObject = {}; + merge(this.sort.sortChange, this.paginator.page) + .pipe( + startWith({}), + switchMap(() => { + this.isLoadingTable = true; + if(this.sort.direction == ''){ + this.sort.active = 'session_start_time'; + this.sort.direction = 'desc' + } + let filter = Object.assign({}, this.session_filter_form.getRawValue()); + let newFilter = JSON.stringify(filter) + + for (const [key, value] of Object.entries(filter)) { + if(key == 'sex'){ + if(value[0] == true){ + newObject[key] = 'F' + //female + continue + } + else if (value[1] == true){ + newObject[key] = 'M' + //male + continue + } + else if (value[2] == true){ + newObject[key] = 'U' + //undefined + continue + } + else{ + continue + } + } + if(key == 'session_range_filter'){ + for( const [key2, val] of Object.entries(value)){ + if(val !== null){ + newObject[key2] = val + } + continue + } + } + if(value !== null){ + newObject[key] = value + } + } + this.isLoadingResults = true; + + newObject["__page"] = this.paginator.pageIndex + 1; + newObject["__limit"] = this.paginator.pageSize; + newObject["__order"] = this.sort.active + ' ' + this.sort.direction + return this.sessionService!.getSessions( + newObject) + .pipe(catchError(() => observableOf(null))); + }), + map(sessionRecords => { + this.isLoadingTable = false; + // Flip flag to show that loading has finished. + this.isLoadingResults = false; + + if (sessionRecords === null) { + return []; + } + // Only refresh the result length if there is new data. In case of rate + // limit errors, we do not want to reset the paginator to zero, as that + // would prevent users from re-triggering requests. + this.sessionRecordLength = sessionRecords.records_count; + return sessionRecords.records; + }) + ).subscribe(sessionRecords => this.sessionRecords = sessionRecords); + } ngOnDestroy() { // Store paginator, sort, buttons, and sessions @@ -362,6 +449,7 @@ export class SessionListComponent implements OnInit, OnDestroy { filters['__order'] = 'session_start_time DESC'; this.allSessions = await this.allSessionsService.fetchSessions(filters).toPromise(); + this.allSessions = this.allSessions['records']; } setDropDownFormOptions(dropDownMenuOptionKey, formControl: AbstractControl, key: string) { @@ -394,56 +482,62 @@ export class SessionListComponent implements OnInit, OnDestroy { this.uniqueValuesForEachAttribute[key] = new Set(); }) - // Loop through each tuple - restrictedSessions.forEach(tuple => { - keys.forEach(key => { - if (tuple[key] !== null && !this.uniqueValuesForEachAttribute[key].has(tuple[key])) { - // Add it to the uniqueValuesForColumns if it doesn't already exist in there - this.uniqueValuesForEachAttribute[key].add(tuple[key]) - } - }) - }); - - // Deal with specific case for - this.patchSexMaterial(Sex.FEMALE, this.uniqueValuesForEachAttribute['sex'].has('F')); - this.patchSexMaterial(Sex.MALE, this.uniqueValuesForEachAttribute['sex'].has('M')); - this.patchSexMaterial(Sex.UNDEFINED, this.uniqueValuesForEachAttribute['sex'].has('U')); - - // This is for selected or not for sex, don't know why this is here blame Maho this.uniqueValuesForEachAttribute['sex'] = { F: false, M: false, U: false } - // Deal with figureing out the range of dates - const sessionSeconds = []; - this.uniqueValuesForEachAttribute['session_start_time'].forEach(date => { - sessionSeconds.push(new Date(date).getTime()); - }); - - this.sessionMinDate = new Date(Math.min(...sessionSeconds)); - this.sessionMaxDate = new Date(Math.max(...sessionSeconds)); - - // Figure out what dates are valid and assign it to this.sessionDateFilter for the material table to highlight those date - this.sessionDateFilter = (date: Date): boolean => { - let sessionDates = []; - this.uniqueValuesForEachAttribute['session_start_time'].forEach(date => { - sessionDates.push(date.toString().substring(0, 10)); // Split it at T and only take the first half - }); - - // filter out dates without any session - return sessionDates.includes(date.toISOString().substring(0, 10)); - }; - - // Figure out what dates for the mouse Birthday Filter are valid and assign it to this.sessionDateFilter for the material table to highlight those date - this.miceBirthdayFilter = (calendarDate: Date): boolean => { - let birthDates = []; - this.uniqueValuesForEachAttribute['subject_birth_date'].forEach(date => { - birthDates.push(date); - }); - return birthDates.includes(calendarDate.toISOString().substring(0, 10)); - }; + // Loop through each tuple + // restrictedSessions.forEach(tuple => { + // keys.forEach(key => { + // if (tuple[key] !== null && !this.uniqueValuesForEachAttribute[key].has(tuple[key])) { + // // Add it to the uniqueValuesForColumns if it doesn't already exist in there + // this.uniqueValuesForEachAttribute[key].add(tuple[key]) + // } + // }) + // }); + + // // Deal with specific case for + // this.patchSexMaterial(Sex.FEMALE, this.uniqueValuesForEachAttribute['sex'].has('F')); + // this.patchSexMaterial(Sex.MALE, this.uniqueValuesForEachAttribute['sex'].has('M')); + // this.patchSexMaterial(Sex.UNDEFINED, this.uniqueValuesForEachAttribute['sex'].has('U')); + + // // This is for selected or not for sex, don't know why this is here blame Maho + // this.uniqueValuesForEachAttribute['sex'] = { + // F: false, + // M: false, + // U: false + // } + + // // Deal with figureing out the range of dates + // const sessionSeconds = []; + // this.uniqueValuesForEachAttribute['session_start_time'].forEach(date => { + // sessionSeconds.push(new Date(date).getTime()); + // }); + + // this.sessionMinDate = new Date(Math.min(...sessionSeconds)); + // this.sessionMaxDate = new Date(Math.max(...sessionSeconds)); + + // // Figure out what dates are valid and assign it to this.sessionDateFilter for the material table to highlight those date + // this.sessionDateFilter = (date: Date): boolean => { + // let sessionDates = []; + // this.uniqueValuesForEachAttribute['session_start_time'].forEach(date => { + // sessionDates.push(date.toString().substring(0, 10)); // Split it at T and only take the first half + // }); + + // // filter out dates without any session + // return sessionDates.includes(date.toISOString().substring(0, 10)); + // }; + + // // Figure out what dates for the mouse Birthday Filter are valid and assign it to this.sessionDateFilter for the material table to highlight those date + // this.miceBirthdayFilter = (calendarDate: Date): boolean => { + // let birthDates = []; + // this.uniqueValuesForEachAttribute['subject_birth_date'].forEach(date => { + // birthDates.push(date); + // }); + // return birthDates.includes(calendarDate.toISOString().substring(0, 10)); + // }; // Set material from drop down this.setDropDownFormOptions('filteredSessionLabOptions', this.session_filter_form.controls.session_lab, 'session_lab'); @@ -554,7 +648,7 @@ export class SessionListComponent implements OnInit, OnDestroy { const requestFilter = {}; let requestJSONstring = ''; - filterList.forEach(filter => { + filterList.forEach((filter: Array) => { // filter is [["session_lab", "somelab"], ["subject_nickname", null]...] const filterKey = filter[0].split('')[0]; // filter[0] is control name like 'session_lab' if (filter[1] && filterKey !== focusedField) { @@ -792,8 +886,10 @@ export class SessionListComponent implements OnInit, OnDestroy { this.restrictedSessions = await this.applyFilter(); this.createMenu(this.restrictedSessions); - await this.updateTableView(this.restrictedSessions); + //await this.updateTableView(this.restrictedSessions); this.isLoading = false; + this.paginator.pageIndex = 0; + this.ngAfterViewInit(); } /** @@ -801,65 +897,69 @@ export class SessionListComponent implements OnInit, OnDestroy { * @returns */ async applyFilter(focusFieldKey?: string) { - if (!this.allSessions) { - return []; - } - - // Hide certain checkboxes - this.hideMissingPlots = false; - this.hideMissingEphys = false; - this.hideNG4BrainMap = false; - this.hideNotReady4Delay = false; - - let tupleToRestrict = this.allSessions // By default this should be all sessions - - // Check if there is a brain region request, if so override the tupleToRestrict reference - const brainRegionRequest = this.requested_BR; - if (brainRegionRequest.length !== 0) { - // BrainRegionRequest is not empty, thus query the backend for it - let requestFilter = {} - let BR_JSONstring = ''; - if (brainRegionRequest.length > 0) { - BR_JSONstring = ''; - brainRegionRequest.filter(function(selection, index) { - if (index > 0) { - BR_JSONstring += `, "${selection}"` - } else { - BR_JSONstring += `"${selection}"` - } - }) - BR_JSONstring = '[' + BR_JSONstring + ']' - } - - // Add it it to the requestFilter object - if (brainRegionRequest.length > 0) { - requestFilter['__json_kwargs'] = '{ "brain_regions": ' + BR_JSONstring + '}'; - } - - // Add the default sorting for the api request - requestFilter['__order'] = 'session_start_time DESC'; - - // Query back end - tupleToRestrict = await this.allSessionsService.fetchSessions(requestFilter).toPromise(); - } - - // Filter based on what the user requested - let restrictionObjectFromForm = this.session_filter_form.getRawValue(); - - // if user is focusing on a specific field, then remove the currently focused field's restriction value from menu creation - if (focusFieldKey) { - restrictionObjectFromForm[focusFieldKey] = null; - } - - // Iterate through the tuples and restrict accordingly - // This is kind of stupid cause it doesn't check if the restrictionObjectFromForm even have a valid restriction - let restrictedSessions = []; - for (let tuple of tupleToRestrict) { - if (this.doesTupleMatchRestriction(tuple, restrictionObjectFromForm)) { - restrictedSessions.push(tuple); - } - } - return restrictedSessions; + return []; + // if (!this.allSessions) { + // return []; + // } + + // // Hide certain checkboxes + // this.hideMissingPlots = false; + // this.hideMissingEphys = false; + // this.hideNG4BrainMap = false; + // this.hideNotReady4Delay = false; + + // let tupleToRestrict = this.allSessions // By default this should be all sessions + + // // Check if there is a brain region request, if so override the tupleToRestrict reference + // const brainRegionRequest = this.requested_BR; + // if (brainRegionRequest.length !== 0) { + // // BrainRegionRequest is not empty, thus query the backend for it + // let requestFilter = {} + // let BR_JSONstring = ''; + // if (brainRegionRequest.length > 0) { + // BR_JSONstring = ''; + // brainRegionRequest.filter(function(selection, index) { + // if (index > 0) { + // BR_JSONstring += `, "${selection}"` + // } else { + // BR_JSONstring += `"${selection}"` + // } + // }) + // BR_JSONstring = '[' + BR_JSONstring + ']' + // } + + // // Add it it to the requestFilter object + // if (brainRegionRequest.length > 0) { + // requestFilter['__json_kwargs'] = '{ "brain_regions": ' + BR_JSONstring + '}'; + // } + + // // Add the default sorting for the api request + // requestFilter['__order'] = 'session_start_time DESC'; + + // console.log(requestFilter) + + // // Query back end + // tupleToRestrict = await this.allSessionsService.fetchSessions(requestFilter).toPromise(); + // } + + // // Filter based on what the user requested + // let restrictionObjectFromForm = this.session_filter_form.getRawValue(); + + // // if user is focusing on a specific field, then remove the currently focused field's restriction value from menu creation + // if (focusFieldKey) { + // restrictionObjectFromForm[focusFieldKey] = null; + // } + + // // Iterate through the tuples and restrict accordingly + // // This is kind of stupid cause it doesn't check if the restrictionObjectFromForm even have a valid restriction + // let restrictedSessions = []; + // for (let tuple of tupleToRestrict) { + // if (this.doesTupleMatchRestriction(tuple, restrictionObjectFromForm)) { + // restrictedSessions.push(tuple); + // } + // } + // console.log(restrictedSessions) + // return restrictedSessions; } /** @@ -868,10 +968,11 @@ export class SessionListComponent implements OnInit, OnDestroy { async refreshData() { this.isLoading = true; this.filterStoreService.refreshSessionTableState(); - await this.fetchSessions(); + // await this.fetchSessions(); this.restrictedSessions = await this.applyFilter(); this.createMenu(this.restrictedSessions); - await this.updateTableView(this.restrictedSessions); + //await this.updateTableView(this.restrictedSessions); + this.ngAfterViewInit(); this.isLoading = false; } @@ -880,36 +981,38 @@ export class SessionListComponent implements OnInit, OnDestroy { */ async handleResetFilterButtonPress() { this.isLoading = true; - for (const control in this.session_filter_form.controls) { - const toReset = {} + // for (const control in this.session_filter_form.controls) { + // const toReset = {} - if (control === 'session_range_filter') { - toReset[control] = { 'session_range_start': null, 'session_range_end': null} + // if (control === 'session_range_filter') { + // toReset[control] = { 'session_range_start': null, 'session_range_end': null} - } else if (control === 'sex') { - toReset[control] = [false, false, false]; - for (const index in this.session_filter_form.get(control)['controls']) { - this.session_filter_form.get(control).get([index]).enable(); - } - } else { - toReset[control] = null; - } - this.session_filter_form.patchValue(toReset); - } + // } else if (control === 'sex') { + // toReset[control] = [false, false, false]; + // for (const index in this.session_filter_form.get(control)['controls']) { + // this.session_filter_form.get(control).get([index]).enable(); + // } + // } else { + // toReset[control] = null; + // } + // this.session_filter_form.patchValue(toReset); + // } + + // this.route.queryParams.subscribe(async param => { + // if (Object.keys(param).length > 0) { + // // Clear all URL params, and do a fresh fetch + // this.router.navigate( + // [], + // { + // relativeTo: this.route, + // queryParams: null + // }); + // } + // }) + + //all of the above code can just be done with this.session_filter_form.reset() + this.session_filter_form.reset() - this.route.queryParams.subscribe(async param => { - if (Object.keys(param).length > 0) { - // Clear all URL params, and do a fresh fetch - this.router.navigate( - [], - { - relativeTo: this.route, - queryParams: null - }); - } - }) - - // clear the filter in storage before applying filter this.filterStoreService.clearSessionFilter(); this.restrictedSessions = await this.applyFilter(); @@ -919,13 +1022,14 @@ export class SessionListComponent implements OnInit, OnDestroy { this.paginator.pageIndex = 0; this.paginator.pageSize = 25; // the below is to remove the arrow UI that doesn't go away after this.sort.active = '' - this.sort.sortables.forEach(sortItem => { - this.sort.sort(sortItem); - }); - this.sort.active = ''; + // this.sort.sortables.forEach(sortItem => { + // this.sort.sort(sortItem); + // }); + // this.sort.active = ''; - await this.updateTableView(this.restrictedSessions); + //await this.updateTableView(this.restrictedSessions); this.isLoading = false; + this.ngAfterViewInit(); return; } diff --git a/ibl-frontend/frontend-content/src/app/session-list/session/session-psych-plot/session-psych-plot.component.html b/ibl-frontend/frontend-content/src/app/session-list/session/session-psych-plot/session-psych-plot.component.html index 90739a4f..8d81686b 100644 --- a/ibl-frontend/frontend-content/src/app/session-list/session/session-psych-plot/session-psych-plot.component.html +++ b/ibl-frontend/frontend-content/src/app/session-list/session/session-psych-plot/session-psych-plot.component.html @@ -2,7 +2,7 @@
    - +

    plot loading...

    diff --git a/ibl-frontend/frontend-content/src/app/session-list/session/session-psych-plot/session-psych-plot.component.ts b/ibl-frontend/frontend-content/src/app/session-list/session/session-psych-plot/session-psych-plot.component.ts index 7ed0f2e9..5e538a4f 100644 --- a/ibl-frontend/frontend-content/src/app/session-list/session/session-psych-plot/session-psych-plot.component.ts +++ b/ibl-frontend/frontend-content/src/app/session-list/session/session-psych-plot/session-psych-plot.component.ts @@ -117,7 +117,7 @@ export class SessionPsychPlotComponent implements OnInit, OnDestroy { @Output() psychCurveFitPars: EventEmitter = new EventEmitter(); constructor(public sessionPlotsService: SessionPlotsService) { } - @ViewChild('session_psych_plot') el: ElementRef; + @ViewChild('session_psych_plot', {static: true}) el: ElementRef; @HostListener('window:resize', ['$event.target']) onresize(event) { this.newScreenWidth = event.innerWidth; // console.log('screensize change: ', this.newScreenWidth); diff --git a/ibl-frontend/frontend-content/src/app/session-list/session/session-rtc-plot/session-rtc-plot.component.html b/ibl-frontend/frontend-content/src/app/session-list/session/session-rtc-plot/session-rtc-plot.component.html index 6b905243..7369e7e9 100644 --- a/ibl-frontend/frontend-content/src/app/session-list/session/session-rtc-plot/session-rtc-plot.component.html +++ b/ibl-frontend/frontend-content/src/app/session-list/session/session-rtc-plot/session-rtc-plot.component.html @@ -1,7 +1,7 @@
    - +

    plot loading...

    diff --git a/ibl-frontend/frontend-content/src/app/session-list/session/session-rtc-plot/session-rtc-plot.component.ts b/ibl-frontend/frontend-content/src/app/session-list/session/session-rtc-plot/session-rtc-plot.component.ts index dcb472ab..2895b4dd 100644 --- a/ibl-frontend/frontend-content/src/app/session-list/session/session-rtc-plot/session-rtc-plot.component.ts +++ b/ibl-frontend/frontend-content/src/app/session-list/session/session-rtc-plot/session-rtc-plot.component.ts @@ -102,7 +102,7 @@ export class SessionRTCPlotComponent implements OnInit, OnDestroy { @Output() openSRTCplot: EventEmitter = new EventEmitter(); constructor(public sessionPlotsService: SessionPlotsService) { } - @ViewChild('session_RTC_plot') el: ElementRef; + @ViewChild('session_RTC_plot', {static: true}) el: ElementRef; @HostListener('window:resize', ['$event.target']) onresize(event) { this.newScreenWidth = event.innerWidth; // console.log('screensize change: ', this.newScreenWidth); diff --git a/ibl-frontend/frontend-content/src/app/session-list/session/session-rttn-plot/session-rttn-plot.component.html b/ibl-frontend/frontend-content/src/app/session-list/session/session-rttn-plot/session-rttn-plot.component.html index 7941a6a8..225adec7 100644 --- a/ibl-frontend/frontend-content/src/app/session-list/session/session-rttn-plot/session-rttn-plot.component.html +++ b/ibl-frontend/frontend-content/src/app/session-list/session/session-rttn-plot/session-rttn-plot.component.html @@ -1,7 +1,7 @@
    - +

    plot loading...

    diff --git a/ibl-frontend/frontend-content/src/app/session-list/session/session-rttn-plot/session-rttn-plot.component.ts b/ibl-frontend/frontend-content/src/app/session-list/session/session-rttn-plot/session-rttn-plot.component.ts index 15f02c13..118c6bde 100644 --- a/ibl-frontend/frontend-content/src/app/session-list/session/session-rttn-plot/session-rttn-plot.component.ts +++ b/ibl-frontend/frontend-content/src/app/session-list/session/session-rttn-plot/session-rttn-plot.component.ts @@ -99,7 +99,7 @@ export class SessionRTTNPlotComponent implements OnInit, OnDestroy { @Output() openSRTTNplot: EventEmitter = new EventEmitter(); constructor(public sessionPlotsService: SessionPlotsService) { } - @ViewChild('session_RTTN_plot') el: ElementRef; + @ViewChild('session_RTTN_plot', {static: true}) el: ElementRef; @HostListener('window:resize', ['$event.target']) onresize(event) { this.newScreenWidth = event.innerWidth; // console.log('screensize change: ', this.newScreenWidth); diff --git a/ibl-frontend/frontend-content/src/environments/environment.ts b/ibl-frontend/frontend-content/src/environments/environment.ts index ab9baa1f..3ca14dfd 100644 --- a/ibl-frontend/frontend-content/src/environments/environment.ts +++ b/ibl-frontend/frontend-content/src/environments/environment.ts @@ -21,4 +21,4 @@ export const environment = { * This import should be commented out in production mode because it will have a negative impact * on performance if an error is thrown. */ -// import 'zone.js/dist/zone-error'; // Included with Angular CLI. +// import 'zone.js/plugins/zone-error'; // Included with Angular CLI. diff --git a/ibl-frontend/frontend-content/src/index.html b/ibl-frontend/frontend-content/src/index.html index 26a1977c..f4e521c9 100644 --- a/ibl-frontend/frontend-content/src/index.html +++ b/ibl-frontend/frontend-content/src/index.html @@ -8,7 +8,6 @@ - diff --git a/ibl-frontend/frontend-content/src/polyfills.ts b/ibl-frontend/frontend-content/src/polyfills.ts index a5b8c7f6..60354026 100644 --- a/ibl-frontend/frontend-content/src/polyfills.ts +++ b/ibl-frontend/frontend-content/src/polyfills.ts @@ -81,7 +81,7 @@ /*************************************************************************************************** * Zone JS is required by default for Angular itself. */ -import 'zone.js/dist/zone'; // Included with Angular CLI. +import 'zone.js'; // Included with Angular CLI. /*************************************************************************************************** diff --git a/ibl-frontend/frontend-content/src/styles.css b/ibl-frontend/frontend-content/src/styles.css index 5ad556d6..fc6323de 100644 --- a/ibl-frontend/frontend-content/src/styles.css +++ b/ibl-frontend/frontend-content/src/styles.css @@ -1,6 +1,8 @@ /* You can add global styles to this file, and also import other style files */ -@import "~@angular/material/prebuilt-themes/indigo-pink-ibl.css"; +@import '../node_modules/bootstrap/dist/css/bootstrap.min.css'; +@import '../node_modules/@angular/material/prebuilt-themes/indigo-pink-ibl.css'; @import url('https://fonts.googleapis.com/css?family=Roboto+Condensed:300, 300i ,400, 400i, 700, 700i&subset=greek,greek-ext'); +@import './assets/fonts/css/open-iconic-bootstrap.min.css'; /* *:not(mat-icon) { font-family: 'Roboto Condensed', sans-serif; diff --git a/ibl-frontend/frontend-content/src/test.ts b/ibl-frontend/frontend-content/src/test.ts index 16317897..a6f15af3 100644 --- a/ibl-frontend/frontend-content/src/test.ts +++ b/ibl-frontend/frontend-content/src/test.ts @@ -1,6 +1,6 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files -import 'zone.js/dist/zone-testing'; +import 'zone.js/testing'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, diff --git a/ibl-frontend/frontend-content/src/tsconfig.app.json b/ibl-frontend/frontend-content/src/tsconfig.app.json index 190fd300..f3a1b801 100644 --- a/ibl-frontend/frontend-content/src/tsconfig.app.json +++ b/ibl-frontend/frontend-content/src/tsconfig.app.json @@ -4,8 +4,11 @@ "outDir": "../out-tsc/app", "types": [] }, - "exclude": [ - "test.ts", - "**/*.spec.ts" + "files": [ + "main.ts", + "polyfills.ts" + ], + "include": [ + "src/**/*.d.ts" ] } diff --git a/node_server/Dockerfile b/node_server/Dockerfile index b1ff07e8..20729d47 100644 --- a/node_server/Dockerfile +++ b/node_server/Dockerfile @@ -20,6 +20,9 @@ COPY ./ /src/ # RUN \ # mv /src/check-auth.js /src/middleware/ -CMD node --max_old_space_size=8192 /src/server.js +WORKDIR /src +CMD npm start + +# CMD node --max_old_space_size=8192 /src/server.js # CMD nodemon /src/server.js # CMD tail -f /dev/null \ No newline at end of file diff --git a/node_server/app.js b/node_server/app.js index 9a24f998..beac3489 100644 --- a/node_server/app.js +++ b/node_server/app.js @@ -190,7 +190,7 @@ app.get('/sessions', checkAuth, (req, res) => { }) app.post('/sessions', checkAuth, cacheMiddleware(15*60), (req, res) => { - // console.log('posting to filter session page'); + console.log('req.body: ', req.body) console.log('type: ', typeof req.body) request.post(flask_backend + '/v0/_q/sessionpage', { form: req.body }, function (error, httpResponse, body) { @@ -199,13 +199,11 @@ app.post('/sessions', checkAuth, cacheMiddleware(15*60), (req, res) => { res.status(500).end(); return; } - // console.log(body); + res.send(body); }) }) - - app.get('/mice', checkAuth, (req, res) => { // setup for proxy server var options = { diff --git a/node_server/package.json b/node_server/package.json index 46421eb8..843763b5 100644 --- a/node_server/package.json +++ b/node_server/package.json @@ -28,5 +28,9 @@ "karma-jasmine": "~1.1.2", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.4.0" + }, + "scripts": { + "start": "node --max_old_space_size=8192 /src/server.js", + "test": "node --max_old_space_size=8192 --inspect-brk=0.0.0.0:9222 /src/server.js" } }