From 0e5142746ec1999e3f86ba9163552ce5d4818f72 Mon Sep 17 00:00:00 2001 From: RINO767 Date: Tue, 18 Jun 2019 10:49:49 +0200 Subject: [PATCH 1/9] added loading animation for cloud/hardware overview --- src/app/app.module.ts | 6 +- .../cloud-overview.component.html | 37 +++--- .../cloud-overview.component.ts | 5 +- .../hardware-overview.component.html | 119 ++++++++++-------- .../hardware-overview.component.scss | 74 ++++++++++- .../hardware-overview.component.ts | 2 + .../schedules-overview.component.html | 2 +- src/app/guards/http-auth.interceptor.ts | 3 +- .../root-store/cloud-data-store/actions.ts | 46 ++++++- .../root-store/cloud-data-store/reducer.ts | 20 +++ .../root-store/cloud-data-store/selectors.ts | 12 ++ src/app/root-store/cloud-data-store/state.ts | 12 +- src/app/services/cloud-data.service.ts | 71 +++++++++-- src/styles.scss | 42 ++++++- 14 files changed, 364 insertions(+), 87 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index e94ae42..b4bc2bb 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -31,6 +31,8 @@ import { ServiceWorkerModule } from '@angular/service-worker'; import { SchedulesBottomSheetComponent } from './components/schedules/schedules-bottom-sheet/schedules-bottom-sheet.component'; import {environment} from '../environments/environment'; import {FlexLayoutModule} from '@angular/flex-layout'; +import {ScrollingModule} from '@angular/cdk/scrolling'; +import { OverviewTableComponent } from './components/overview-table/overview-table.component'; /** * Default configuration required by the swagger API Module. @@ -77,6 +79,7 @@ export class BottomSheetHammerConfig extends HammerGestureConfig { SchedulesOverviewComponent, SchedulesViewComponent, SchedulesBottomSheetComponent, + OverviewTableComponent, ], imports: [ BrowserModule, @@ -90,7 +93,8 @@ export class BottomSheetHammerConfig extends HammerGestureConfig { CdkTableModule, AppDialogModule, FlexLayoutModule, - ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }) + ServiceWorkerModule.register('ngsw-worker.js', {enabled: environment.production}), + ScrollingModule ], providers: [ { diff --git a/src/app/components/clouds/cloud-overview/cloud-overview.component.html b/src/app/components/clouds/cloud-overview/cloud-overview.component.html index 30155e2..73a29df 100644 --- a/src/app/components/clouds/cloud-overview/cloud-overview.component.html +++ b/src/app/components/clouds/cloud-overview/cloud-overview.component.html @@ -1,24 +1,33 @@
-
-
-
-

Clouds

+
+
+
+

Clouds

+
-
-
-
+
+
- + + + + +
+
+
+
+
- - + + - -
-
+ +
+
diff --git a/src/app/components/clouds/cloud-overview/cloud-overview.component.ts b/src/app/components/clouds/cloud-overview/cloud-overview.component.ts index c5fc0d8..0f34898 100644 --- a/src/app/components/clouds/cloud-overview/cloud-overview.component.ts +++ b/src/app/components/clouds/cloud-overview/cloud-overview.component.ts @@ -1,7 +1,8 @@ import {Component, OnDestroy, OnInit} from '@angular/core'; import {CloudDataService} from '../../../services/cloud-data.service'; import {Cloud} from 'cloudiator-rest-api'; -import {Subscription} from 'rxjs'; +import {Observable, Subscription} from 'rxjs'; +import {map, tap} from 'rxjs/operators'; /** * Overview of all clouds given as a set of horizontally flowing cards. @@ -19,6 +20,8 @@ export class CloudOverviewComponent implements OnInit, OnDestroy { */ public clouds: Cloud[] = []; + public cloudIsLoading$: Observable = this.cloudDataService.cloudIsLoading(); + /** * All Subscriptions of this Component. * @type {any[]} diff --git a/src/app/components/hardware/hardware-overview/hardware-overview.component.html b/src/app/components/hardware/hardware-overview/hardware-overview.component.html index 616fba1..86ecce9 100644 --- a/src/app/components/hardware/hardware-overview/hardware-overview.component.html +++ b/src/app/components/hardware/hardware-overview/hardware-overview.component.html @@ -1,73 +1,88 @@ -
-
-
-

Hardware

+
+
+
+
+

Hardware

+
-
-
-
+
+
+ - -

- - + + +

+

- +
+ +
- - - - - + + + - - - - - + + + - - - - - + + + - - - - - + + + - - - -
- Name - + + + + Name + - {{row.name}} {{row.name}} - Ram - + + + + Ram + - {{row.ram}} {{row.ram}} - Cores - + + + + Cores + - {{row.cores}} {{row.cores}} - Disk - + + + + Disk + - {{row.disk}} {{row.disk}}
-
-
+ + + + + +
+ + +
+
+
+
+
+ +
diff --git a/src/app/components/hardware/hardware-overview/hardware-overview.component.scss b/src/app/components/hardware/hardware-overview/hardware-overview.component.scss index 4e6fb98..e7d50e9 100644 --- a/src/app/components/hardware/hardware-overview/hardware-overview.component.scss +++ b/src/app/components/hardware/hardware-overview/hardware-overview.component.scss @@ -1,3 +1,75 @@ +@import "../../../../styles"; +@import "~bulma/sass/utilities/mixins"; + +.view { + display: flex; + flex-direction: column; + height: 100%; +} + +.table-section { + flex: 2; + display: flex +} + +.searchbar { + max-width: 500px +} + +.table-viewport { + height: 100%; + border: 1px $grey-lighter solid; + border-radius: 5px; + scroll-margin: 5px 10px 0 10px; + //overflow: hidden; +} + .table { - margin: 5px 0 0 0; + width: calc(100%); +} + +th { + background: white; + border: none; +} + +th:after { + content: ''; + position: absolute; + left: 0; + bottom: 0; + width: 100%; + border-bottom: 3px solid $grey-lighter; +} + +tr { + border: none; +} + +.loading-placeholder { + height: 100%; + width: 100%; + border-radius: 5px; + + > div { + height: 100%; + width: 100%; + } +} + +@include mobile { + .section { + padding: 0; + } + + .searchbar { + width: 100%; + max-width: none; + } + + .loading-placeholder { + border-top: 1px solid $grey-lighter; + border-radius: 0; + } } + diff --git a/src/app/components/hardware/hardware-overview/hardware-overview.component.ts b/src/app/components/hardware/hardware-overview/hardware-overview.component.ts index 8e30c63..1b8e512 100644 --- a/src/app/components/hardware/hardware-overview/hardware-overview.component.ts +++ b/src/app/components/hardware/hardware-overview/hardware-overview.component.ts @@ -15,6 +15,8 @@ import {ActivatedRoute} from '@angular/router'; }) export class HardwareOverviewComponent implements OnInit, OnDestroy { + isLoading$ = this.cloudDataService.hardwareIsLoading(); + /** * Datasource for table. * @type {BehaviorSubject} diff --git a/src/app/components/schedules/schedules-overview/schedules-overview.component.html b/src/app/components/schedules/schedules-overview/schedules-overview.component.html index 1ca0f1a..466beae 100644 --- a/src/app/components/schedules/schedules-overview/schedules-overview.component.html +++ b/src/app/components/schedules/schedules-overview/schedules-overview.component.html @@ -25,7 +25,7 @@

Schedules

-
+
diff --git a/src/app/guards/http-auth.interceptor.ts b/src/app/guards/http-auth.interceptor.ts index 5d53a94..a03d7c6 100644 --- a/src/app/guards/http-auth.interceptor.ts +++ b/src/app/guards/http-auth.interceptor.ts @@ -4,7 +4,7 @@ import {Observable, Subscription} from 'rxjs'; import {AuthService} from '../services/auth.service'; import {RuntimeConfigService} from '../services/runtime-config.service'; import {AuthMode} from '../model/RuntimeConfig'; -import {mergeMap, tap} from 'rxjs/operators'; +import {mergeMap, take, tap} from 'rxjs/operators'; /** * sets correct api path and authentication headers for all requests. @@ -60,6 +60,7 @@ export class HttpAuthInterceptor implements HttpInterceptor, OnDestroy { return new Observable(subscriber => { this.runtimeConfigService.awaitConfigLoad().then(() => subscriber.next()); }).pipe( + take(1), mergeMap(() => next.handle(this.changeRequest(request))) ); } diff --git a/src/app/root-store/cloud-data-store/actions.ts b/src/app/root-store/cloud-data-store/actions.ts index 0c1d887..fb6a0aa 100644 --- a/src/app/root-store/cloud-data-store/actions.ts +++ b/src/app/root-store/cloud-data-store/actions.ts @@ -2,9 +2,13 @@ import {Action} from '@ngrx/store'; import {Cloud, Hardware, Image, Location} from 'cloudiator-rest-api'; export const SET_CLOUDS = '[Clouddata] set Cloud'; +export const SET_CLOUD_IS_LOADING = '[Clouddata] set Cloud isLoading'; export const SET_HARDWARE = '[Clouddata] set Hardware'; +export const SET_HARDWARE_IS_LOADING = '[Clouddata] set HARDWARE isLoading'; export const SET_IMAGES = '[Clouddata] set Images'; +export const SET_IMAGE_IS_LOADING = '[Clouddata] set Image isLoading'; export const SET_LOCATIONS = '[Clouddata] set Locations'; +export const SET_LOCATION_IS_LOADING = '[Clouddata] set Location isLoading'; export class SetCloudsAction implements Action { readonly type = SET_CLOUDS; @@ -12,6 +16,14 @@ export class SetCloudsAction implements Action { constructor(public clouds: Cloud[]) { } } + +export class SetCloudIsLoading implements Action { + readonly type = SET_CLOUD_IS_LOADING; + + constructor(public isLoading: boolean) { + } +} + export class SetHardwareAction implements Action { readonly type = SET_HARDWARE; @@ -19,6 +31,14 @@ export class SetHardwareAction implements Action { } } + +export class SetHardwareIsLoading implements Action { + readonly type = SET_HARDWARE_IS_LOADING; + + constructor(public isLoading: boolean) { + } +} + export class SetImagesAction implements Action { readonly type = SET_IMAGES; @@ -26,6 +46,14 @@ export class SetImagesAction implements Action { } } + +export class SetImageIsLoading implements Action { + readonly type = SET_IMAGE_IS_LOADING; + + constructor(public isLoading: boolean) { + } +} + export class SetLocationsAction implements Action { readonly type = SET_LOCATIONS; @@ -34,4 +62,20 @@ export class SetLocationsAction implements Action { } -export type All = SetCloudsAction | SetHardwareAction | SetImagesAction | SetLocationsAction; +export class SetLocationIsLoading implements Action { + readonly type = SET_LOCATION_IS_LOADING; + + constructor(public isLoading: boolean) { + } +} + + +export type All = + SetCloudsAction + | SetCloudIsLoading + | SetHardwareAction + | SetHardwareIsLoading + | SetImagesAction + | SetImageIsLoading + | SetLocationsAction + | SetLocationIsLoading; diff --git a/src/app/root-store/cloud-data-store/reducer.ts b/src/app/root-store/cloud-data-store/reducer.ts index 4a7bb2e..8553120 100644 --- a/src/app/root-store/cloud-data-store/reducer.ts +++ b/src/app/root-store/cloud-data-store/reducer.ts @@ -8,21 +8,41 @@ export function cloudDataReducer(state = initialState, action: cloudActions.All) ...state, clouds: action.clouds }; + case cloudActions.SET_CLOUD_IS_LOADING: + return { + ...state, + cloudIsLoading: action.isLoading + }; case cloudActions.SET_HARDWARE: return { ...state, hardware: action.hardware }; + case cloudActions.SET_HARDWARE_IS_LOADING: + return { + ...state, + hardwareIsLoading: action.isLoading + }; case cloudActions.SET_IMAGES: return { ...state, images: action.images }; + case cloudActions.SET_IMAGE_IS_LOADING: + return { + ...state, + imageIsLoading: action.isLoading + }; case cloudActions.SET_LOCATIONS: return { ...state, locations: action.locations }; + case cloudActions.SET_LOCATION_IS_LOADING: + return { + ...state, + locationIsLoading: action.isLoading + }; default: return initialState; } diff --git a/src/app/root-store/cloud-data-store/selectors.ts b/src/app/root-store/cloud-data-store/selectors.ts index 5872438..6b6521f 100644 --- a/src/app/root-store/cloud-data-store/selectors.ts +++ b/src/app/root-store/cloud-data-store/selectors.ts @@ -4,18 +4,30 @@ import {createFeatureSelector, createSelector, MemoizedSelector} from '@ngrx/sto const getClouds = (state: State): Cloud[] => state.clouds; +const getCloudIsLoading = (state: State): boolean => state.cloudIsLoading; const getHardware = (state: State): Hardware[] => state.hardware; +const getHardwareIsLoading = (state: State): boolean => state.hardwareIsLoading; const getImages = (state: State): Image[] => state.images; +const getImageIsLoading = (state: State): boolean => state.imageIsLoading; const getLocations = (state: State): Location[] => state.locations; +const getLocationIsLoading = (state: State): boolean => state.locationIsLoading; export const selectCloudDataState: MemoizedSelector = createFeatureSelector('cloudData'); export const selectClouds: MemoizedSelector = createSelector(selectCloudDataState, getClouds); +export const selectCloudIsLoading: MemoizedSelector + = createSelector(selectCloudDataState, getCloudIsLoading); export const selectHardware: MemoizedSelector = createSelector(selectCloudDataState, getHardware); +export const selectHardwareIsLoading: MemoizedSelector + = createSelector(selectCloudDataState, getHardwareIsLoading); export const selectImages: MemoizedSelector = createSelector(selectCloudDataState, getImages); +export const selectImageIsLoading: MemoizedSelector + = createSelector(selectCloudDataState, getImageIsLoading); export const selectLocations: MemoizedSelector = createSelector(selectCloudDataState, getLocations); +export const selectLocationIsLoading: MemoizedSelector + = createSelector(selectCloudDataState, getLocationIsLoading); diff --git a/src/app/root-store/cloud-data-store/state.ts b/src/app/root-store/cloud-data-store/state.ts index 192f501..61e2cc0 100644 --- a/src/app/root-store/cloud-data-store/state.ts +++ b/src/app/root-store/cloud-data-store/state.ts @@ -2,14 +2,22 @@ import {Cloud, Hardware, Image, Location} from 'cloudiator-rest-api'; export interface State { clouds: Cloud[]; + cloudIsLoading: boolean; hardware: Hardware[]; + hardwareIsLoading: boolean; images: Image[]; + imageIsLoading: boolean; locations: Location[]; + locationIsLoading: boolean; } -export const initialState = { +export const initialState: State = { clouds: [], + cloudIsLoading: false, hardware: [], + hardwareIsLoading: false, images: [], - locations: [] + imageIsLoading: false, + locations: [], + locationIsLoading: false }; diff --git a/src/app/services/cloud-data.service.ts b/src/app/services/cloud-data.service.ts index 12044a2..b32d601 100644 --- a/src/app/services/cloud-data.service.ts +++ b/src/app/services/cloud-data.service.ts @@ -1,8 +1,8 @@ import {Injectable} from '@angular/core'; import {Cloud, CloudService, Hardware, Image, NewCloud, Location} from 'cloudiator-rest-api'; -import {Observable, pipe} from 'rxjs'; +import {Observable, of, pipe} from 'rxjs'; import {select, Store} from '@ngrx/store'; -import {map, take, timeout} from 'rxjs/operators'; +import {finalize, map, take, timeout} from 'rxjs/operators'; import {HttpResponse} from '@angular/common/http'; import {RuntimeConfigService} from './runtime-config.service'; import {ToastService} from '../app-dialog/services/toast.service'; @@ -66,6 +66,10 @@ export class CloudDataService { ); } + public cloudIsLoading(): Observable { + return this.store.pipe(select(CloudDataSelectors.selectCloudIsLoading)); + } + /* HARDWARE */ /** * Searches for all Hardware containing the given id string. @@ -81,6 +85,24 @@ export class CloudDataService { map(hardware => hardware.filter(hw => hw.id.includes(id)))); } return this.store.pipe(select(CloudDataSelectors.selectHardware)); + // const lst = []; + // let i = 0 + // while (i < 65000) { + // lst.push({ + // id: 's', + // name: 'test', + // cores: 3, + // ram: 20, + // disk: 100 + // }); + // i++; + // } + // console.log(lst) + // return of(lst); + } + + public hardwareIsLoading(): Observable { + return this.store.pipe(select(CloudDataSelectors.selectHardwareIsLoading)); } /* IMAGES */ @@ -102,6 +124,10 @@ export class CloudDataService { select(CloudDataSelectors.selectImages)); } + public imageIsLoading(): Observable { + return this.store.pipe(select(CloudDataSelectors.selectImageIsLoading)); + } + /** * Searches for all Locations containing the fiven id string. * @param {string} id Id to be searched for. @@ -118,6 +144,10 @@ export class CloudDataService { return this.store.pipe(select(CloudDataSelectors.selectLocations)); } + public locationIsLoading(): Observable { + return this.store.pipe(select(CloudDataSelectors.selectLocationIsLoading)); + } + /** * Fetches all clouds from the Server and saves them in the Redux store. * before sending the request, the config file must be loaded to grant the correct api url @@ -125,14 +155,20 @@ export class CloudDataService { private fetchClouds() { // fetch Clouds + this.store.dispatch(new CloudDataActions.SetCloudIsLoading(true)); this.cloudApiService.findClouds() - .subscribe(clouds => { + .subscribe( + clouds => { this.store.dispatch(new CloudDataActions.SetCloudsAction(clouds)); }, err => { console.error('could not fetch clouds', err); this.toastService.show({text: 'could not fetch clouds', type: ToastType.DANGER}, false); - }); + }, + () => { + this.store.dispatch(new CloudDataActions.SetCloudIsLoading(false)); + } + ); } /** @@ -140,14 +176,19 @@ export class CloudDataService { */ private fetchHardware() { // fetch Hardware + this.store.dispatch(new CloudDataActions.SetHardwareIsLoading(true)); this.cloudApiService.findHardware() - .subscribe(hardware => { + .subscribe( + hardware => { this.store.dispatch(new CloudDataActions.SetHardwareAction(hardware)); }, () => { console.error('could not fetch Hardware'); this.toastService.show({text: 'could not fetch Hardware', type: ToastType.DANGER}, false); - }); + }, + () => + this.store.dispatch(new CloudDataActions.SetHardwareIsLoading(false)) + ); } /** @@ -155,14 +196,19 @@ export class CloudDataService { */ private fetchImages() { // fetch Images + this.store.dispatch(new CloudDataActions.SetImageIsLoading(true)); this.cloudApiService.findImages() - .subscribe(images => { + .subscribe( + images => { this.store.dispatch(new CloudDataActions.SetImagesAction(images)); }, () => { console.error('could not fetch Images'); this.toastService.show({text: 'could not fetch Images', type: ToastType.DANGER}, false); - }); + }, + () => + this.store.dispatch(new CloudDataActions.SetImageIsLoading(false)) + ); } /** @@ -170,15 +216,18 @@ export class CloudDataService { */ private fetchLocations() { // fetch Images + this.store.dispatch(new CloudDataActions.SetLocationIsLoading(true)); this.cloudApiService.findLocations() - .pipe(take(1)) - .subscribe(locations => { + .subscribe( + locations => { this.store.dispatch(new CloudDataActions.SetLocationsAction(locations)); }, () => { console.error('could not fetch Images'); this.toastService.show({text: 'could not fetch Images', type: ToastType.DANGER}, false); - }); + }, + () => this.store.dispatch(new CloudDataActions.SetLocationIsLoading(false)) + ); } /** diff --git a/src/styles.scss b/src/styles.scss index c41475a..9a689c5 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -45,6 +45,21 @@ html { overflow-y: auto; } + +//::-webkit-scrollbar { +// width: 12px; +//} +// +//::-webkit-scrollbar-track { +// border-radius: 5px; +//} +// +//::-webkit-scrollbar-thumb { +// border-radius: 4px; +// //border-top-right-radius: 4px; +// background: $grey-light; +//} + $app-container-height: calc(100% - #{$navbar-height}); // notification z-index @@ -100,10 +115,10 @@ $app-container-height: calc(100% - #{$navbar-height}); // text placeholder @keyframes placeHolderShimmer{ 0%{ - background-position: -468px 0 + background-position: 50% 0 } 100%{ - background-position: 468px 0 + background-position: -50% 0 } } @@ -120,3 +135,26 @@ $app-container-height: calc(100% - #{$navbar-height}); //height: 96px; position: relative; } +.text-loading-animation { + animation-duration: 1s; + animation-fill-mode: forwards; + animation-iteration-count: infinite; + animation-name: placeHolderShimmer; + animation-timing-function: linear; + background: $secondary; + background: linear-gradient(to right, rgba(238,238,238,0.3) 8%, rgba(255,255,255,0.1) 18%, rgba(238,238,238,0.3) 33%); + background-size: 800px 104px; + border-radius: 3rem; + //height: 96px; + position: relative; +} + +.big-loading-animation { + animation-duration: 1s; + animation-fill-mode: forwards; + animation-iteration-count: infinite; + animation-name: placeHolderShimmer; + animation-timing-function: linear; + background: linear-gradient(to right, rgba(255,255,255,0.9) 8%, rgba(255,255,255,0.1) 18%, rgba(255,255,255,0.9) 33%); + background-size: 500%; +} From 82ea2ffec90c2926e9e00b9012ae9c1a3c786058 Mon Sep 17 00:00:00 2001 From: RINO767 Date: Tue, 18 Jun 2019 15:13:39 +0200 Subject: [PATCH 2/9] abstracted overview table components to let them share nearly the same code --- src/app/app-routing.module.ts | 6 +- src/app/app.module.ts | 8 +- src/app/components/app/app.component.spec.ts | 10 +- .../cloud-overview.component.spec.ts | 3 +- .../hardware-overview.component.html | 88 ------------- .../images-overview.component.html | 62 --------- .../images-overview.component.scss | 3 - .../images-overview.component.ts | 118 ------------------ .../locations-overview.component.html | 51 -------- .../locations-overview.component.scss | 3 - .../locations-overview.component.ts | 93 -------------- .../hardware-overview.component.spec.ts | 4 +- .../hardware-overview.component.ts | 37 ++++++ .../images-overview.component.spec.ts | 4 +- .../images-overview.component.ts | 33 +++++ .../locations-overview.component.spec.ts | 4 +- .../locations-overview.component.ts | 40 ++++++ .../overview-table.component.html | 60 +++++++++ .../overview-table.component.scss} | 2 +- .../overview-table.component.spec.ts | 57 +++++++++ .../overview-table.component.ts} | 62 +++++---- src/app/model/TableColumns.ts | 6 + src/app/services/cloud-data.service.ts | 10 +- 23 files changed, 302 insertions(+), 462 deletions(-) delete mode 100644 src/app/components/hardware/hardware-overview/hardware-overview.component.html delete mode 100644 src/app/components/images/images-overview/images-overview.component.html delete mode 100644 src/app/components/images/images-overview/images-overview.component.scss delete mode 100644 src/app/components/images/images-overview/images-overview.component.ts delete mode 100644 src/app/components/locations/locations-overview/locations-overview.component.html delete mode 100644 src/app/components/locations/locations-overview/locations-overview.component.scss delete mode 100644 src/app/components/locations/locations-overview/locations-overview.component.ts rename src/app/components/{hardware => overview-tables}/hardware-overview/hardware-overview.component.spec.ts (94%) create mode 100644 src/app/components/overview-tables/hardware-overview/hardware-overview.component.ts rename src/app/components/{images => overview-tables}/images-overview/images-overview.component.spec.ts (94%) create mode 100644 src/app/components/overview-tables/images-overview/images-overview.component.ts rename src/app/components/{locations => overview-tables}/locations-overview/locations-overview.component.spec.ts (94%) create mode 100644 src/app/components/overview-tables/locations-overview/locations-overview.component.ts create mode 100644 src/app/components/overview-tables/overview-table.component.html rename src/app/components/{hardware/hardware-overview/hardware-overview.component.scss => overview-tables/overview-table.component.scss} (96%) create mode 100644 src/app/components/overview-tables/overview-table.component.spec.ts rename src/app/components/{hardware/hardware-overview/hardware-overview.component.ts => overview-tables/overview-table.component.ts} (55%) create mode 100644 src/app/model/TableColumns.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 6c7e488..f274004 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -3,9 +3,9 @@ import {NgModule} from '@angular/core'; import {CloudOverviewComponent} from './components/clouds/cloud-overview/cloud-overview.component'; import {NewCloudComponent} from './components/clouds/new-cloud/new-cloud.component'; import {CloudViewComponent} from './components/clouds/cloud-view/cloud-view.component'; -import {HardwareOverviewComponent} from './components/hardware/hardware-overview/hardware-overview.component'; -import {ImagesOverviewComponent} from './components/images/images-overview/images-overview.component'; -import {LocationsOverviewComponent} from './components/locations/locations-overview/locations-overview.component'; +import {HardwareOverviewComponent} from './components/overview-tables/hardware-overview/hardware-overview.component'; +import {ImagesOverviewComponent} from './components/overview-tables/images-overview/images-overview.component'; +import {LocationsOverviewComponent} from './components/overview-tables/locations-overview/locations-overview.component'; import {YamlEditorComponent} from './components/editor/yaml-editor/yaml-editor.component'; import {LoginComponent} from './components/login/login.component'; import {AuthGuard} from './guards/auth.guard'; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b4bc2bb..ade6dbe 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -11,10 +11,10 @@ import {NewCloudComponent} from './components/clouds/new-cloud/new-cloud.compone import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {CloudViewComponent} from './components/clouds/cloud-view/cloud-view.component'; import {CloudCardComponent} from './components/clouds/cloud-card/cloud-card.component'; -import {HardwareOverviewComponent} from './components/hardware/hardware-overview/hardware-overview.component'; +import {HardwareOverviewComponent} from './components/overview-tables/hardware-overview/hardware-overview.component'; import {CdkTableModule} from '@angular/cdk/table'; -import {ImagesOverviewComponent} from './components/images/images-overview/images-overview.component'; -import {LocationsOverviewComponent} from './components/locations/locations-overview/locations-overview.component'; +import {ImagesOverviewComponent} from './components/overview-tables/images-overview/images-overview.component'; +import {LocationsOverviewComponent} from './components/overview-tables/locations-overview/locations-overview.component'; import {YamlEditorComponent} from './components/editor/yaml-editor/yaml-editor.component'; import {YamlGraphComponent} from './components/editor/yaml-graph/yaml-graph.component'; import {AppDialogModule} from './app-dialog/app-dialog.module'; @@ -32,7 +32,7 @@ import { SchedulesBottomSheetComponent } from './components/schedules/schedules- import {environment} from '../environments/environment'; import {FlexLayoutModule} from '@angular/flex-layout'; import {ScrollingModule} from '@angular/cdk/scrolling'; -import { OverviewTableComponent } from './components/overview-table/overview-table.component'; +import { OverviewTableComponent } from './components/overview-tables/overview-table.component'; /** * Default configuration required by the swagger API Module. diff --git a/src/app/components/app/app.component.spec.ts b/src/app/components/app/app.component.spec.ts index 3422813..4904846 100644 --- a/src/app/components/app/app.component.spec.ts +++ b/src/app/components/app/app.component.spec.ts @@ -6,10 +6,10 @@ import {NewCloudComponent} from '../clouds/new-cloud/new-cloud.component'; import {CloudOverviewComponent} from '../clouds/cloud-overview/cloud-overview.component'; import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {CloudCardComponent} from '../clouds/cloud-card/cloud-card.component'; -import {HardwareOverviewComponent} from '../hardware/hardware-overview/hardware-overview.component'; +import {HardwareOverviewComponent} from '../overview-tables/hardware-overview/hardware-overview.component'; import {CdkTableModule} from '@angular/cdk/table'; -import {ImagesOverviewComponent} from '../images/images-overview/images-overview.component'; -import {LocationsOverviewComponent} from '../locations/locations-overview/locations-overview.component'; +import {ImagesOverviewComponent} from '../overview-tables/images-overview/images-overview.component'; +import {LocationsOverviewComponent} from '../overview-tables/locations-overview/locations-overview.component'; import {YamlEditorComponent} from '../editor/yaml-editor/yaml-editor.component'; import {YamlGraphComponent} from '../editor/yaml-graph/yaml-graph.component'; import {RootStoreModule} from '../../root-store'; @@ -25,6 +25,7 @@ import {HttpClientTestingModule} from '@angular/common/http/testing'; import {AuthService} from '../../services/auth.service'; import {of} from 'rxjs'; import * as testData from 'testing/test-data'; +import {ScrollingModule} from '@angular/cdk/scrolling'; describe('AppComponent', () => { beforeEach(async(() => { @@ -55,7 +56,8 @@ describe('AppComponent', () => { CdkTableModule, ApiModule.forRoot(testData.testApiFactory), HttpClientTestingModule, - AppDialogModule + AppDialogModule, + ScrollingModule ], providers: [] }).compileComponents(); diff --git a/src/app/components/clouds/cloud-overview/cloud-overview.component.spec.ts b/src/app/components/clouds/cloud-overview/cloud-overview.component.spec.ts index 6f157da..1deb913 100644 --- a/src/app/components/clouds/cloud-overview/cloud-overview.component.spec.ts +++ b/src/app/components/clouds/cloud-overview/cloud-overview.component.spec.ts @@ -12,7 +12,8 @@ describe('CloudOverviewComponent', () => { let fixture: ComponentFixture; const mockCloudDataService = jasmine.createSpyObj('CloudDataService', { - 'findClouds': of([]) + 'findClouds': of([]), + 'cloudIsLoading': of(false) }); beforeEach(async(() => { diff --git a/src/app/components/hardware/hardware-overview/hardware-overview.component.html b/src/app/components/hardware/hardware-overview/hardware-overview.component.html deleted file mode 100644 index 86ecce9..0000000 --- a/src/app/components/hardware/hardware-overview/hardware-overview.component.html +++ /dev/null @@ -1,88 +0,0 @@ -
-
-
-
-

Hardware

-
-
-
- - -
-
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Name - - - - {{row.name}} - Ram - - - - {{row.ram}} - Cores - - - - {{row.cores}} - Disk - - - - {{row.disk}}
-
-
-
- -
-
-
-
-
-
-
diff --git a/src/app/components/images/images-overview/images-overview.component.html b/src/app/components/images/images-overview/images-overview.component.html deleted file mode 100644 index 08ba13d..0000000 --- a/src/app/components/images/images-overview/images-overview.component.html +++ /dev/null @@ -1,62 +0,0 @@ -
-
-
-

Images

-
-
-
- - -
-
- - - -
- - -
- - -

- - - - -

- - - - - - - - - - - - - - - - - - -
- Name - - - - {{row.name}} - OS - - - - {{row.operatingSystem ? row.operatingSystem.operatingSystemFamily : ''}}
-
-
-
diff --git a/src/app/components/images/images-overview/images-overview.component.scss b/src/app/components/images/images-overview/images-overview.component.scss deleted file mode 100644 index 4e6fb98..0000000 --- a/src/app/components/images/images-overview/images-overview.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.table { - margin: 5px 0 0 0; -} diff --git a/src/app/components/images/images-overview/images-overview.component.ts b/src/app/components/images/images-overview/images-overview.component.ts deleted file mode 100644 index 8f5e228..0000000 --- a/src/app/components/images/images-overview/images-overview.component.ts +++ /dev/null @@ -1,118 +0,0 @@ -import {Component, OnInit} from '@angular/core'; -import {FormControl} from '@angular/forms'; -import {Image} from 'cloudiator-rest-api'; -import {BehaviorSubject, combineLatest} from 'rxjs'; -import {CloudDataService} from '../../../services/cloud-data.service'; -import {ActivatedRoute} from '@angular/router'; -import {tap} from 'rxjs/operators'; - -/** - * Overview of all Images available. - */ -@Component({ - selector: 'app-images-overview', - templateUrl: './images-overview.component.html', - styleUrls: ['./images-overview.component.scss'] -}) -export class ImagesOverviewComponent implements OnInit { - - /** - * Datasource for table. - * @type {BehaviorSubject} - */ - dataSource = new BehaviorSubject([]); - - /** - * Searchbar object. - * @type {FormControl} - */ - searchFormControl = new FormControl(); - - /** - * Key That is sorted by. - * @type {BehaviorSubject} - */ - sortKey = new BehaviorSubject(''); - /** - * Sort direction. - * @type {BehaviorSubject} - */ - sortDirection = new BehaviorSubject(''); - - /** - * indicates if data is being loaded right now. - * @type {boolean} - */ - isLoading = true; - - /** @ignore */ - constructor(private activatedRoute: ActivatedRoute, - public cloudDataService: CloudDataService) { - } - - /** @ignore */ - ngOnInit() { - - this.adjustSort('name'); - - combineLatest( - this.cloudDataService.findImages().pipe(tap(() => this.isLoading = false)), - this.searchFormControl.valueChanges, - this.sortKey, - this.sortDirection - ) - .subscribe(([changedHardwareData, searchTerm, sortKey, sortDirection]) => { - const imagesArray = Object.values(changedHardwareData); - - let filteredImages = []; - - if (!searchTerm) { - filteredImages = imagesArray; - } else { - filteredImages = this.cloudDataService.filterImages(imagesArray, searchTerm); - } - - const sortedImages = filteredImages.sort((a, b) => { - if (a[sortKey] > b[sortKey]) { - return sortDirection === 'asc' ? 1 : -1; - } - if (a[sortKey] < b[sortKey]) { - return sortDirection === 'asc' ? -1 : 1; - } - return 0; - }); - - this.dataSource.next(sortedImages); - }); - - - this.searchFormControl.setValue(''); - - this.activatedRoute.queryParams.subscribe(params => { - if (params.id) { - this.searchFormControl.patchValue(`id=${params.id}`); - } else if (params.cloud) { - this.searchFormControl.patchValue(`cloud=${params.cloud}`); - } - }); - } - - /** - * Adjusts sort key and direction. - * @param {string} key - */ - adjustSort(key: string) { - if (this.sortKey.value === key) { - if (this.sortDirection.value === 'asc') { - this.sortDirection.next('desc'); - } else { - this.sortDirection.next('asc'); - } - return; - } - - this.sortKey.next(key); - this.sortDirection.next('asc'); - } - -} diff --git a/src/app/components/locations/locations-overview/locations-overview.component.html b/src/app/components/locations/locations-overview/locations-overview.component.html deleted file mode 100644 index 7bf883c..0000000 --- a/src/app/components/locations/locations-overview/locations-overview.component.html +++ /dev/null @@ -1,51 +0,0 @@ -
-
-
-

Locations

-
-
-
- - -
-
- - -

- - - - -

- - - - - - - - - - - - - - - - - - -
- Name - - - - {{row.name}} - Country - - - - {{row.geolocation ? row.geolocation : ''}}
-
-
diff --git a/src/app/components/locations/locations-overview/locations-overview.component.scss b/src/app/components/locations/locations-overview/locations-overview.component.scss deleted file mode 100644 index 4e6fb98..0000000 --- a/src/app/components/locations/locations-overview/locations-overview.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.table { - margin: 5px 0 0 0; -} diff --git a/src/app/components/locations/locations-overview/locations-overview.component.ts b/src/app/components/locations/locations-overview/locations-overview.component.ts deleted file mode 100644 index 7ccf85d..0000000 --- a/src/app/components/locations/locations-overview/locations-overview.component.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import {BehaviorSubject, combineLatest} from 'rxjs'; -import {Location} from 'cloudiator-rest-api'; -import {FormControl} from '@angular/forms'; -import {CloudDataService} from '../../../services/cloud-data.service'; - -/** - * Overview of all Locations available. - */ -@Component({ - selector: 'app-locations-overview', - templateUrl: './locations-overview.component.html', - styleUrls: ['./locations-overview.component.scss'] -}) -export class LocationsOverviewComponent implements OnInit { - - /** - * Datasource for table. - * @type {BehaviorSubject} - */ - dataSource = new BehaviorSubject([]); - - /** - * Search bar Object. - * @type {FormControl} - */ - searchFormControl = new FormControl(); - - /** - * Key the table is sorted by. - * @type {BehaviorSubject} - */ - sortKey = new BehaviorSubject(''); - /** - * Direction of table sort. - * @type {BehaviorSubject} - */ - sortDirection = new BehaviorSubject(''); - - /** @ignore */ - constructor(public cloudDataService: CloudDataService) { - } - - /** @ignore */ - ngOnInit() { - this.adjustSort('name'); - - combineLatest(this.cloudDataService.findLocations(), this.searchFormControl.valueChanges, this.sortKey, this.sortDirection) - .subscribe(([changedHardwareData, searchTerm, sortKey, sortDirection]) => { - const locationsArray = Object.values(changedHardwareData); - - let filteredLocations = []; - - if (!searchTerm) { - filteredLocations = locationsArray; - } else { - filteredLocations = this.cloudDataService.filterLocations(locationsArray, searchTerm); - } - - const sortedLocations = filteredLocations.sort((a, b) => { - if (a[sortKey] > b[sortKey]) { - return sortDirection === 'asc' ? 1 : -1; - } - if (a[sortKey] < b[sortKey]) { - return sortDirection === 'asc' ? -1 : 1; - } - return 0; - }); - - this.dataSource.next(sortedLocations); - }); - - this.searchFormControl.setValue(''); - } - - /** - * adjusts Sort key and direction. - * @param {string} key - */ - adjustSort(key: string) { - if (this.sortKey.value === key) { - if (this.sortDirection.value === 'asc') { - this.sortDirection.next('desc'); - } else { - this.sortDirection.next('asc'); - } - return; - } - - this.sortKey.next(key); - this.sortDirection.next('asc'); - } -} diff --git a/src/app/components/hardware/hardware-overview/hardware-overview.component.spec.ts b/src/app/components/overview-tables/hardware-overview/hardware-overview.component.spec.ts similarity index 94% rename from src/app/components/hardware/hardware-overview/hardware-overview.component.spec.ts rename to src/app/components/overview-tables/hardware-overview/hardware-overview.component.spec.ts index 108c2a8..8add255 100644 --- a/src/app/components/hardware/hardware-overview/hardware-overview.component.spec.ts +++ b/src/app/components/overview-tables/hardware-overview/hardware-overview.component.spec.ts @@ -11,6 +11,7 @@ import {ActivatedRoute, Router, RouterModule} from '@angular/router'; import {of} from 'rxjs'; import {AppDialogModule} from '../../../app-dialog/app-dialog.module'; import {RootStoreModule} from '../../../root-store'; +import {ScrollingModule} from '@angular/cdk/scrolling'; describe('HardwareOverviewComponent', () => { let component: HardwareOverviewComponent; @@ -29,7 +30,8 @@ describe('HardwareOverviewComponent', () => { HttpClientModule, ApiModule.forRoot(apiConfigFactory), RouterModule, - AppDialogModule + AppDialogModule, + ScrollingModule ], providers: [ {provide: Router, useValue: router}, diff --git a/src/app/components/overview-tables/hardware-overview/hardware-overview.component.ts b/src/app/components/overview-tables/hardware-overview/hardware-overview.component.ts new file mode 100644 index 0000000..b531177 --- /dev/null +++ b/src/app/components/overview-tables/hardware-overview/hardware-overview.component.ts @@ -0,0 +1,37 @@ +import {Component, OnDestroy, OnInit} from '@angular/core'; +import {BehaviorSubject, combineLatest, Subscription} from 'rxjs'; +import {Hardware} from 'cloudiator-rest-api'; +import {CloudDataService} from '../../../services/cloud-data.service'; +import {FormControl} from '@angular/forms'; +import {ActivatedRoute} from '@angular/router'; +import {OverviewTableComponent} from '../overview-table.component'; + +/** + * Overview Component showing available Hardware. + */ +@Component({ + selector: 'app-hardware-overview', + templateUrl: '../overview-table.component.html', + styleUrls: ['../overview-table.component.scss'] +}) +export class HardwareOverviewComponent extends OverviewTableComponent implements OnInit, OnDestroy { + constructor(activatedRoute: ActivatedRoute, + cloudDataService: CloudDataService) { + super(activatedRoute, cloudDataService); + this.title = 'Hardware'; + this.columns = { + name: {value: 'Name'}, + cores: {value: 'Cores'}, + ram: {value: 'Ram'}, + disk: {value: 'Disk'} + }; + this.initialSortKey = 'cores'; + this.isLoading$ = cloudDataService.hardwareIsLoading(); + this.filter = (v, t) => cloudDataService.filterHardware(v, t); + + this.data = cloudDataService.findHardware(); + } +} + + + diff --git a/src/app/components/images/images-overview/images-overview.component.spec.ts b/src/app/components/overview-tables/images-overview/images-overview.component.spec.ts similarity index 94% rename from src/app/components/images/images-overview/images-overview.component.spec.ts rename to src/app/components/overview-tables/images-overview/images-overview.component.spec.ts index 6892138..8ae711d 100644 --- a/src/app/components/images/images-overview/images-overview.component.spec.ts +++ b/src/app/components/overview-tables/images-overview/images-overview.component.spec.ts @@ -11,6 +11,7 @@ import {ActivatedRoute, Router, RouterModule} from '@angular/router'; import {of} from 'rxjs'; import {AppDialogModule} from '../../../app-dialog/app-dialog.module'; import {RootStoreModule} from '../../../root-store'; +import {ScrollingModule} from '@angular/cdk/scrolling'; describe('ImagesOverviewComponent', () => { let component: ImagesOverviewComponent; @@ -29,7 +30,8 @@ describe('ImagesOverviewComponent', () => { HttpClientModule, ApiModule.forRoot(apiConfigFactory), RouterModule, - AppDialogModule + AppDialogModule, + ScrollingModule ], providers: [ { provide: Router, useValue: router }, diff --git a/src/app/components/overview-tables/images-overview/images-overview.component.ts b/src/app/components/overview-tables/images-overview/images-overview.component.ts new file mode 100644 index 0000000..33aa9fd --- /dev/null +++ b/src/app/components/overview-tables/images-overview/images-overview.component.ts @@ -0,0 +1,33 @@ +import {Component, OnDestroy, OnInit} from '@angular/core'; +import {Hardware, Image} from 'cloudiator-rest-api'; +import {CloudDataService} from '../../../services/cloud-data.service'; +import {ActivatedRoute} from '@angular/router'; +import {OverviewTableComponent} from '../overview-table.component'; + +/** + * Overview of all Images available. + */ +@Component({ + selector: 'app-images-overview', + templateUrl: '../overview-table.component.html', + styleUrls: ['../overview-table.component.scss'] +}) +export class ImagesOverviewComponent extends OverviewTableComponent implements OnInit, OnDestroy { + constructor(activatedRoute: ActivatedRoute, + cloudDataService: CloudDataService) { + super(activatedRoute, cloudDataService); + this.title = 'Images'; + this.columns = { + providerId: {value: 'provider ID'}, + name: {value: 'Name'}, + os: { + value: 'OS', + selectionFn: (v: Image) => v.operatingSystem ? v.operatingSystem.operatingSystemFamily : '' + } + }; + this.initialSortKey = ''; + this.isLoading$ = cloudDataService.imageIsLoading(); + this.filter = (v, t) => cloudDataService.filterImages(v, t); + this.data = cloudDataService.findImages(); + } +} diff --git a/src/app/components/locations/locations-overview/locations-overview.component.spec.ts b/src/app/components/overview-tables/locations-overview/locations-overview.component.spec.ts similarity index 94% rename from src/app/components/locations/locations-overview/locations-overview.component.spec.ts rename to src/app/components/overview-tables/locations-overview/locations-overview.component.spec.ts index e510698..e8ec229 100644 --- a/src/app/components/locations/locations-overview/locations-overview.component.spec.ts +++ b/src/app/components/overview-tables/locations-overview/locations-overview.component.spec.ts @@ -11,6 +11,7 @@ import {CloudDataService} from '../../../services/cloud-data.service'; import {of} from 'rxjs'; import {AppDialogModule} from '../../../app-dialog/app-dialog.module'; import {RootStoreModule} from '../../../root-store'; +import {ScrollingModule} from '@angular/cdk/scrolling'; describe('LocationsOverviewComponent', () => { let component: LocationsOverviewComponent; @@ -30,7 +31,8 @@ describe('LocationsOverviewComponent', () => { HttpClientModule, ApiModule.forRoot(apiConfigFactory), RouterModule, - AppDialogModule + AppDialogModule, + ScrollingModule ], providers: [ {provide: Router, useValue: router}, diff --git a/src/app/components/overview-tables/locations-overview/locations-overview.component.ts b/src/app/components/overview-tables/locations-overview/locations-overview.component.ts new file mode 100644 index 0000000..f206338 --- /dev/null +++ b/src/app/components/overview-tables/locations-overview/locations-overview.component.ts @@ -0,0 +1,40 @@ +import {Component, OnDestroy, OnInit} from '@angular/core'; +import {BehaviorSubject, combineLatest} from 'rxjs'; +import {Image, Location} from 'cloudiator-rest-api'; +import {FormControl} from '@angular/forms'; +import {CloudDataService} from '../../../services/cloud-data.service'; +import {OverviewTableComponent} from '../overview-table.component'; +import {ActivatedRoute} from '@angular/router'; + +/** + * Overview of all Locations available. + */ +@Component({ + selector: 'app-locations-overview', + templateUrl: '../overview-table.component.html', + styleUrls: ['../overview-table.component.scss'] +}) +export class LocationsOverviewComponent extends OverviewTableComponent implements OnInit, OnDestroy { + constructor(activatedRoute: ActivatedRoute, + cloudDataService: CloudDataService) { + super(activatedRoute, cloudDataService); + this.title = 'Locations'; + this.columns = { + name: { + value: 'Name' + }, + country: { + value: 'Country', + selectionFn: (v: Location) => v.geoLocation ? v.geoLocation.country : '' + }, + city: { + value: 'City', + selectionFn: (v: Location) => v.geoLocation ? v.geoLocation.city : '' + } + }; + this.initialSortKey = ''; + this.isLoading$ = cloudDataService.locationIsLoading(); + this.filter = (v, t) => cloudDataService.filterLocations(v, t); + this.data = cloudDataService.findLocations(); + } +} diff --git a/src/app/components/overview-tables/overview-table.component.html b/src/app/components/overview-tables/overview-table.component.html new file mode 100644 index 0000000..d5efee0 --- /dev/null +++ b/src/app/components/overview-tables/overview-table.component.html @@ -0,0 +1,60 @@ +
+
+
+
+

{{title}}

+
+
+
+ + +
+
+ + + + + + +
+ + + + + + + + + + + + + +
+ {{columns[field].value}} + + + + + {{columns[field].selectionFn + ? columns[field].selectionFn(row) + : row[field]}} +
+
+
+
+ +
+
+
+
+
+
+
diff --git a/src/app/components/hardware/hardware-overview/hardware-overview.component.scss b/src/app/components/overview-tables/overview-table.component.scss similarity index 96% rename from src/app/components/hardware/hardware-overview/hardware-overview.component.scss rename to src/app/components/overview-tables/overview-table.component.scss index e7d50e9..5c36817 100644 --- a/src/app/components/hardware/hardware-overview/hardware-overview.component.scss +++ b/src/app/components/overview-tables/overview-table.component.scss @@ -1,4 +1,4 @@ -@import "../../../../styles"; +@import "../../../styles"; @import "~bulma/sass/utilities/mixins"; .view { diff --git a/src/app/components/overview-tables/overview-table.component.spec.ts b/src/app/components/overview-tables/overview-table.component.spec.ts new file mode 100644 index 0000000..7563852 --- /dev/null +++ b/src/app/components/overview-tables/overview-table.component.spec.ts @@ -0,0 +1,57 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { OverviewTableComponent } from './overview-table.component'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {CdkTableModule} from '@angular/cdk/table'; +import {RouterTestingModule} from '@angular/router/testing'; +import {ScrollingModule} from '@angular/cdk/scrolling'; +import {HttpClientModule} from '@angular/common/http'; +import {ApiModule} from 'cloudiator-rest-api'; +import {apiConfigFactory} from '../../app.module'; +import {CloudDataService} from '../../services/cloud-data.service'; +import {RootStoreModule} from '../../root-store'; +import {AppDialogModule} from '../../app-dialog/app-dialog.module'; +import {ActivatedRoute} from '@angular/router'; +import {of} from 'rxjs'; + +describe('OverviewTableComponent', () => { + let component: OverviewTableComponent; + let fixture: ComponentFixture>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ OverviewTableComponent ], + imports: [ + RootStoreModule, + FormsModule, + ReactiveFormsModule, + CdkTableModule, + RouterTestingModule, + ScrollingModule, + HttpClientModule, + ApiModule.forRoot(apiConfigFactory), + AppDialogModule + ], + providers: [ + CloudDataService, + { + provide: ActivatedRoute, + useValue: { + queryParams: of({id: null}) + } + } + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(OverviewTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/hardware/hardware-overview/hardware-overview.component.ts b/src/app/components/overview-tables/overview-table.component.ts similarity index 55% rename from src/app/components/hardware/hardware-overview/hardware-overview.component.ts rename to src/app/components/overview-tables/overview-table.component.ts index 1b8e512..93c517c 100644 --- a/src/app/components/hardware/hardware-overview/hardware-overview.component.ts +++ b/src/app/components/overview-tables/overview-table.component.ts @@ -1,50 +1,57 @@ import {Component, OnDestroy, OnInit} from '@angular/core'; -import {BehaviorSubject, combineLatest, Subscription} from 'rxjs'; +import {BehaviorSubject, combineLatest, Observable, of, Subscription} from 'rxjs'; import {Hardware} from 'cloudiator-rest-api'; -import {CloudDataService} from '../../../services/cloud-data.service'; import {FormControl} from '@angular/forms'; import {ActivatedRoute} from '@angular/router'; +import {CloudDataService} from '../../services/cloud-data.service'; -/** - * Overview Component showing available Hardware. - */ @Component({ - selector: 'app-hardware-overview', - templateUrl: './hardware-overview.component.html', - styleUrls: ['./hardware-overview.component.scss'] + selector: 'app-overview-table', + templateUrl: './overview-table.component.html', + styleUrls: ['./overview-table.component.scss'] }) -export class HardwareOverviewComponent implements OnInit, OnDestroy { +export class OverviewTableComponent implements OnInit, OnDestroy { + title = ''; - isLoading$ = this.cloudDataService.hardwareIsLoading(); + columns: TableColumns; + columnFields: string[]; + + initialSortKey: string; + + isLoading$: Observable = of(false); + + filter: (data: T[], searchTerm: string) => T[]; + + data: Observable = of([]); /** * Datasource for table. * @type {BehaviorSubject} */ - dataSource = new BehaviorSubject([]); + protected dataSource = new BehaviorSubject([]); /** * Search bar Object. * @type {FormControl} */ - searchFormControl = new FormControl(); + protected searchFormControl = new FormControl(); /** * Key the table is sorted by. * @type {BehaviorSubject} */ - sortKey = new BehaviorSubject(''); + protected sortKey = new BehaviorSubject(''); /** * Sort Direction. * @type {BehaviorSubject} */ - sortDirection = new BehaviorSubject(''); + protected sortDirection = new BehaviorSubject(''); /** * Subscriptions of this Components. * @type {any[]} */ - subscriptions: Subscription[] = []; + protected subscriptions: Subscription[] = []; /** @ignore */ constructor(private activatedRoute: ActivatedRoute, @@ -53,21 +60,23 @@ export class HardwareOverviewComponent implements OnInit, OnDestroy { /** @ignore */ ngOnInit() { - this.adjustSort('cores'); + this.columnFields = this.columns ? Object.keys(this.columns) : []; + + this.adjustSort(this.initialSortKey); - combineLatest(this.cloudDataService.findHardware(), this.searchFormControl.valueChanges, this.sortKey, this.sortDirection) - .subscribe(([changedHardwareData, searchTerm, sortKey, sortDirection]) => { - const hardwareArray = Object.values(changedHardwareData); + combineLatest(this.data, this.searchFormControl.valueChanges, this.sortKey, this.sortDirection) + .subscribe(([changedData, searchTerm, sortKey, sortDirection]) => { + const dataArray = Object.values(changedData); - let filteredHardware = []; + let filteredData = []; if (!searchTerm) { - filteredHardware = hardwareArray; + filteredData = dataArray; } else { - filteredHardware = this.cloudDataService.filterHardware(hardwareArray, searchTerm); + filteredData = this.filter(dataArray, searchTerm); } - const sortedHardware = filteredHardware.sort((a, b) => { + const sortedData = filteredData.sort((a, b) => { if (a[sortKey] > b[sortKey]) { return sortDirection === 'asc' ? 1 : -1; } @@ -77,7 +86,7 @@ export class HardwareOverviewComponent implements OnInit, OnDestroy { return 0; }); - this.dataSource.next(sortedHardware); + this.dataSource.next(sortedData); }); this.searchFormControl.setValue(''); @@ -88,6 +97,8 @@ export class HardwareOverviewComponent implements OnInit, OnDestroy { this.searchFormControl.patchValue(`id=${params.id}`); } else if (params.cloud) { this.searchFormControl.patchValue(`cloud=${params.cloud}`); + } else { + this.searchFormControl.patchValue(''); } }); } @@ -116,6 +127,3 @@ export class HardwareOverviewComponent implements OnInit, OnDestroy { } } - - - diff --git a/src/app/model/TableColumns.ts b/src/app/model/TableColumns.ts new file mode 100644 index 0000000..366e019 --- /dev/null +++ b/src/app/model/TableColumns.ts @@ -0,0 +1,6 @@ +interface TableColumns { + [key: string]: { + value: string; + selectionFn?: (any) => string; + }; +} diff --git a/src/app/services/cloud-data.service.ts b/src/app/services/cloud-data.service.ts index b32d601..7bab40c 100644 --- a/src/app/services/cloud-data.service.ts +++ b/src/app/services/cloud-data.service.ts @@ -319,9 +319,17 @@ export class CloudDataService { curr.geoLocation.country && operator === '=' && curr.geoLocation.country.toLowerCase() === term.toLowerCase(); + case 'city': + return (curr: Location) => + curr.geoLocation && + curr.geoLocation.city && + operator === '=' && + curr.geoLocation.city.toLowerCase() === term.toLowerCase(); default: return (curr: Location) => { - return curr.name.toLowerCase().includes(term.toLowerCase()); + return curr.name.toLowerCase().includes(term.toLowerCase()) || + (curr.geoLocation && curr.geoLocation.country.toLowerCase().includes(term.toLowerCase())) || + (curr.geoLocation && curr.geoLocation.city.toLowerCase().includes(term.toLowerCase())); }; } }; From 8ee3d3dcc9dd049cc139a2f53c17c25b74099cf8 Mon Sep 17 00:00:00 2001 From: RINO767 Date: Tue, 18 Jun 2019 15:32:04 +0200 Subject: [PATCH 3/9] fixed broken table column --- src/app/components/overview-tables/overview-table.component.ts | 1 + src/app/model/TableColumns.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/components/overview-tables/overview-table.component.ts b/src/app/components/overview-tables/overview-table.component.ts index 93c517c..0e2a22a 100644 --- a/src/app/components/overview-tables/overview-table.component.ts +++ b/src/app/components/overview-tables/overview-table.component.ts @@ -4,6 +4,7 @@ import {Hardware} from 'cloudiator-rest-api'; import {FormControl} from '@angular/forms'; import {ActivatedRoute} from '@angular/router'; import {CloudDataService} from '../../services/cloud-data.service'; +import {TableColumns} from '../../model/TableColumns'; @Component({ selector: 'app-overview-table', diff --git a/src/app/model/TableColumns.ts b/src/app/model/TableColumns.ts index 366e019..c9ba3c7 100644 --- a/src/app/model/TableColumns.ts +++ b/src/app/model/TableColumns.ts @@ -1,4 +1,4 @@ -interface TableColumns { +export interface TableColumns { [key: string]: { value: string; selectionFn?: (any) => string; From d8e489b257e5ae719a37ab88b93add2d5ba08894 Mon Sep 17 00:00:00 2001 From: RINO767 Date: Tue, 18 Jun 2019 16:58:36 +0200 Subject: [PATCH 4/9] small overview table design fixes --- .../hardware-overview.component.ts | 1 + .../overview-table.component.html | 82 +++++++++---------- .../overview-table.component.scss | 12 ++- 3 files changed, 49 insertions(+), 46 deletions(-) diff --git a/src/app/components/overview-tables/hardware-overview/hardware-overview.component.ts b/src/app/components/overview-tables/hardware-overview/hardware-overview.component.ts index b531177..19a1310 100644 --- a/src/app/components/overview-tables/hardware-overview/hardware-overview.component.ts +++ b/src/app/components/overview-tables/hardware-overview/hardware-overview.component.ts @@ -5,6 +5,7 @@ import {CloudDataService} from '../../../services/cloud-data.service'; import {FormControl} from '@angular/forms'; import {ActivatedRoute} from '@angular/router'; import {OverviewTableComponent} from '../overview-table.component'; +import {map} from 'rxjs/operators'; /** * Overview Component showing available Hardware. diff --git a/src/app/components/overview-tables/overview-table.component.html b/src/app/components/overview-tables/overview-table.component.html index d5efee0..00d8cfb 100644 --- a/src/app/components/overview-tables/overview-table.component.html +++ b/src/app/components/overview-tables/overview-table.component.html @@ -1,5 +1,5 @@
-
+

{{title}}

@@ -8,53 +8,49 @@

{{title}}

-
-
+
- - - - -
- - - - - - + + + + + + + +
- {{columns[field].value}} - +

+ + + + + + - - - - - - - -
+ {{columns[field].value}} + - - {{columns[field].selectionFn - ? columns[field].selectionFn(row) - : row[field]}} -
-
- - - -
-
-
-
- +
+ {{columns[field].selectionFn + ? columns[field].selectionFn(row) + : row[field]}} +
+
+ + +
+
+
+
diff --git a/src/app/components/overview-tables/overview-table.component.scss b/src/app/components/overview-tables/overview-table.component.scss index 5c36817..9ef71d6 100644 --- a/src/app/components/overview-tables/overview-table.component.scss +++ b/src/app/components/overview-tables/overview-table.component.scss @@ -8,8 +8,10 @@ } .table-section { + width: 100%; flex: 2; - display: flex + display: flex; + flex-direction: column; } .searchbar { @@ -17,7 +19,7 @@ } .table-viewport { - height: 100%; + flex: 2; border: 1px $grey-lighter solid; border-radius: 5px; scroll-margin: 5px 10px 0 10px; @@ -25,7 +27,7 @@ } .table { - width: calc(100%); + width: 100%; } th { @@ -67,6 +69,10 @@ tr { max-width: none; } + .table-viewport { + border-radius: 0; + } + .loading-placeholder { border-top: 1px solid $grey-lighter; border-radius: 0; From 69ddb0394504cc7391a30643d1f7aa3f18c91bc1 Mon Sep 17 00:00:00 2001 From: RINO767 Date: Wed, 26 Jun 2019 10:18:20 +0200 Subject: [PATCH 5/9] implemented loading indicator for schedules list --- .../schedules-overview.component.html | 6 ++-- .../schedules-overview.component.ts | 10 +++--- .../schedules-view.component.ts | 4 +-- .../root-store/process-data-store/actions.ts | 10 +++++- .../root-store/process-data-store/reducer.ts | 5 +++ .../process-data-store/selectors.ts | 3 ++ .../root-store/process-data-store/state.ts | 4 ++- src/app/services/process-data.service.ts | 34 ++++++++++++------- 8 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/app/components/schedules/schedules-overview/schedules-overview.component.html b/src/app/components/schedules/schedules-overview/schedules-overview.component.html index 466beae..71ebc83 100644 --- a/src/app/components/schedules/schedules-overview/schedules-overview.component.html +++ b/src/app/components/schedules/schedules-overview/schedules-overview.component.html @@ -10,7 +10,7 @@

Schedules

-
+
@@ -31,8 +31,8 @@

Schedules

+ [routerLink]="['/schedules', view.schedule.id]" + [class.is-active]="view.schedule.id === activeViewId"> {{view.job?.name}}
diff --git a/src/app/components/schedules/schedules-overview/schedules-overview.component.ts b/src/app/components/schedules/schedules-overview/schedules-overview.component.ts index 39bc3e5..72246d8 100644 --- a/src/app/components/schedules/schedules-overview/schedules-overview.component.ts +++ b/src/app/components/schedules/schedules-overview/schedules-overview.component.ts @@ -1,10 +1,12 @@ import {Component, OnDestroy, OnInit} from '@angular/core'; import {ProcessDataService} from '../../../services/process-data.service'; -import {Subscription} from 'rxjs'; +import {merge, Observable, of, Subscription, zip} from 'rxjs'; import {ScheduleView} from '../../../model/ScheduleView'; import {JobDataService} from '../../../services/job-data.service'; -import {map} from 'rxjs/operators'; +import {delay, flatMap, map, mergeAll, mergeMap, tap, zipAll} from 'rxjs/operators'; import {ActivatedRoute, Router} from '@angular/router'; +import * as testData from 'testing/test-data'; +import {flatten} from '@angular/compiler'; /** * Overview of Schedules. Hosts a list containing all Schedules and the SchedulesView. @@ -46,9 +48,9 @@ export class SchedulesOverviewComponent implements OnInit, OnDestroy { /** * indicates load state of Schedules - * @type {boolean} + * @type {Observable} */ - isLoading = false; + isLoading = this.processDataService.getScheduleIsLoading(); /** @ignore */ jobLoad = false; diff --git a/src/app/components/schedules/schedules-view/schedules-view.component.ts b/src/app/components/schedules/schedules-view/schedules-view.component.ts index 8c06084..9be58d0 100644 --- a/src/app/components/schedules/schedules-view/schedules-view.component.ts +++ b/src/app/components/schedules/schedules-view/schedules-view.component.ts @@ -8,7 +8,8 @@ import { import {ScheduleView} from '../../../model/ScheduleView'; import * as cytoscape from 'cytoscape'; import {ProcessDataService} from '../../../services/process-data.service'; -import {take} from 'rxjs/operators'; +import {map, take} from 'rxjs/operators'; +import * as testData from 'testing/test-data'; /** * View of a selected Schedule, containing a Cytoscape and a bottomsheet for further information @@ -197,7 +198,6 @@ export class SchedulesViewComponent implements OnInit, OnChanges { updategraph() { this.isLoading = true; this.processDataService.scheduleGraph(this.scheduleView.schedule.id) - .pipe(take(1)) .subscribe(graph => { // timeout as hack to fix wrong positioning of graph when data arrives to early in mobile view setTimeout(() => { diff --git a/src/app/root-store/process-data-store/actions.ts b/src/app/root-store/process-data-store/actions.ts index e358b6f..1365362 100644 --- a/src/app/root-store/process-data-store/actions.ts +++ b/src/app/root-store/process-data-store/actions.ts @@ -2,6 +2,7 @@ import {Action} from '@ngrx/store'; import {Schedule} from 'cloudiator-rest-api'; export const SET_SCHEDULES = '[Processdata] set schedules'; +export const SET_SCHEDULE_IS_LOADING = '[Processdata] set Schedule is loading'; export class SetSchedulesAction implements Action { readonly type = SET_SCHEDULES; @@ -10,5 +11,12 @@ export class SetSchedulesAction implements Action { } } +export class SetScheduleIsLoading implements Action { + readonly type = SET_SCHEDULE_IS_LOADING; -export type All = SetSchedulesAction; + constructor(public isLoading: boolean) { + } +} + + +export type All = SetSchedulesAction | SetScheduleIsLoading; diff --git a/src/app/root-store/process-data-store/reducer.ts b/src/app/root-store/process-data-store/reducer.ts index 68cb40f..8d18672 100644 --- a/src/app/root-store/process-data-store/reducer.ts +++ b/src/app/root-store/process-data-store/reducer.ts @@ -8,6 +8,11 @@ export function processDatareducer(state = initialState, action: processActions. ...state, schedules: action.schedules }; + case processActions.SET_SCHEDULE_IS_LOADING: + return { + ...state, + scheduleIsLoading: action.isLoading + }; default: return state; } diff --git a/src/app/root-store/process-data-store/selectors.ts b/src/app/root-store/process-data-store/selectors.ts index 3a6eeaa..836428c 100644 --- a/src/app/root-store/process-data-store/selectors.ts +++ b/src/app/root-store/process-data-store/selectors.ts @@ -3,9 +3,12 @@ import {Schedule} from 'cloudiator-rest-api'; import {createFeatureSelector, createSelector, MemoizedSelector} from '@ngrx/store'; const getSchedules = (state: State): Schedule[] => state.schedules; +const getScheduleIsLoading = (state: State): boolean => state.scheduleIsLoading; export const selectProcessDataState: MemoizedSelector = createFeatureSelector('processData'); export const selectSchedules: MemoizedSelector = createSelector(selectProcessDataState, getSchedules); +export const selectScheduleIsLoading: MemoizedSelector + = createSelector(selectProcessDataState, getScheduleIsLoading); diff --git a/src/app/root-store/process-data-store/state.ts b/src/app/root-store/process-data-store/state.ts index ad0ea87..805792b 100644 --- a/src/app/root-store/process-data-store/state.ts +++ b/src/app/root-store/process-data-store/state.ts @@ -2,8 +2,10 @@ import {Schedule} from 'cloudiator-rest-api'; export interface State { schedules: Schedule[]; + scheduleIsLoading: boolean; } export const initialState = { - schedules: [] + schedules: [], + scheduleIsLoading: false }; diff --git a/src/app/services/process-data.service.ts b/src/app/services/process-data.service.ts index 523c26d..bf314d8 100644 --- a/src/app/services/process-data.service.ts +++ b/src/app/services/process-data.service.ts @@ -1,5 +1,5 @@ import {Injectable} from '@angular/core'; -import {forkJoin, Observable} from 'rxjs'; +import {forkJoin, Observable, of} from 'rxjs'; import {Job, ProcessService, Queue, Schedule} from 'cloudiator-rest-api'; import {select, Store} from '@ngrx/store'; import {EditorSelectors} from '../root-store/editor-store'; @@ -11,6 +11,7 @@ import {ScheduleView} from '../model/ScheduleView'; import {RootStoreState} from '../root-store'; import {ToastService} from '../app-dialog/services/toast.service'; import {ToastType} from '../app-dialog/model/toast'; +import * as testData from '../../../testing/test-data'; /** * Service handling the Process api. @@ -47,6 +48,11 @@ export class ProcessDataService { return this.store.pipe(select(ProcessDataSelectors.selectSchedules)); } + public getScheduleIsLoading(): Observable { + return this.store.pipe(select(ProcessDataSelectors.selectScheduleIsLoading)); + } + + /** * Fetches Graph of the given id and maps it to Cytoscape data. * @param {string} id @@ -66,17 +72,19 @@ export class ProcessDataService { * Fetches schedules from api. */ private fetchSchedules() { - this.runtimeConfigService.awaitConfigLoad() - .then(() => { - this.processApiService.getSchedules() - .subscribe( - schedules => { - this.store.dispatch(new ProcessDataActions.SetSchedulesAction(schedules)); - }, - () => { - this.toastService.show({text: 'Could not fetch Schedules', type: ToastType.DANGER}); - console.error('could not fetch Schedules'); - }); - }); + this.store.dispatch(new ProcessDataActions.SetScheduleIsLoading(true)); + this.processApiService.getSchedules() + .subscribe( + schedules => { + this.store.dispatch(new ProcessDataActions.SetSchedulesAction(schedules)); + }, + () => { + this.toastService.show({text: 'Could not fetch Schedules', type: ToastType.DANGER}); + console.error('could not fetch Schedules'); + }, + () => { + this.store.dispatch(new ProcessDataActions.SetScheduleIsLoading(false)); + } + ); } } From 8ff4b35ea60982337360695b643c2ab238de83c5 Mon Sep 17 00:00:00 2001 From: RINO767 Date: Wed, 26 Jun 2019 12:47:27 +0200 Subject: [PATCH 6/9] fixed loading animation bug in schedule view --- src/app/app-routing.module.ts | 1 - .../schedules-overview/schedules-overview.component.html | 3 ++- .../schedules-overview/schedules-overview.component.ts | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index f274004..c9a5163 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -29,7 +29,6 @@ const routes: Routes = [ {path: 'editor', component: YamlEditorComponent, canActivate: [AuthGuard]}, {path: 'schedules', component: SchedulesOverviewComponent}, - {path: 'schedules/:id', component: SchedulesOverviewComponent}, {path: 'clouds', component: CloudOverviewComponent, canActivate: [AuthGuard]}, {path: '', component: CloudOverviewComponent, canActivate: [AuthGuard]}, diff --git a/src/app/components/schedules/schedules-overview/schedules-overview.component.html b/src/app/components/schedules/schedules-overview/schedules-overview.component.html index 71ebc83..246f23e 100644 --- a/src/app/components/schedules/schedules-overview/schedules-overview.component.html +++ b/src/app/components/schedules/schedules-overview/schedules-overview.component.html @@ -31,7 +31,8 @@

Schedules

{{view.job?.name}}
diff --git a/src/app/components/schedules/schedules-overview/schedules-overview.component.ts b/src/app/components/schedules/schedules-overview/schedules-overview.component.ts index 72246d8..1127534 100644 --- a/src/app/components/schedules/schedules-overview/schedules-overview.component.ts +++ b/src/app/components/schedules/schedules-overview/schedules-overview.component.ts @@ -1,4 +1,4 @@ -import {Component, OnDestroy, OnInit} from '@angular/core'; +import {Component, OnChanges, OnDestroy, OnInit, SimpleChanges} from '@angular/core'; import {ProcessDataService} from '../../../services/process-data.service'; import {merge, Observable, of, Subscription, zip} from 'rxjs'; import {ScheduleView} from '../../../model/ScheduleView'; @@ -60,13 +60,15 @@ export class SchedulesOverviewComponent implements OnInit, OnDestroy { public jobDataService: JobDataService, public processDataService: ProcessDataService, private router: Router) { + console.log('construct'); } /** @ignore */ ngOnInit() { + console.log('init'); this.subscriptions.push( - this.route.paramMap + this.route.queryParamMap .pipe( map(paramsMap => paramsMap.get('id')) ) @@ -118,4 +120,5 @@ export class SchedulesOverviewComponent implements OnInit, OnDestroy { this.activeScheduleView = this.scheduleViews.find(sv => sv.schedule.id === this.activeViewId); } } + } From 41184c13fff12c295b6942d7a99fa358d8899138 Mon Sep 17 00:00:00 2001 From: RINO767 Date: Wed, 26 Jun 2019 12:58:23 +0200 Subject: [PATCH 7/9] navigate from specific schedule to overal scheduleview will now correctly reset view --- .../schedules-overview/schedules-overview.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/components/schedules/schedules-overview/schedules-overview.component.ts b/src/app/components/schedules/schedules-overview/schedules-overview.component.ts index 1127534..241d068 100644 --- a/src/app/components/schedules/schedules-overview/schedules-overview.component.ts +++ b/src/app/components/schedules/schedules-overview/schedules-overview.component.ts @@ -70,7 +70,7 @@ export class SchedulesOverviewComponent implements OnInit, OnDestroy { this.subscriptions.push( this.route.queryParamMap .pipe( - map(paramsMap => paramsMap.get('id')) + map(paramsMap => paramsMap.get('id') || undefined) ) .subscribe(id => { this.activeViewId = id; @@ -118,6 +118,8 @@ export class SchedulesOverviewComponent implements OnInit, OnDestroy { private updateActiveScheduleView() { if (this.activeViewId) { this.activeScheduleView = this.scheduleViews.find(sv => sv.schedule.id === this.activeViewId); + } else { + this.activeScheduleView = null; } } From e46b65112f4c55635edecf82d7df3feb303fed1d Mon Sep 17 00:00:00 2001 From: RINO767 Date: Wed, 26 Jun 2019 13:00:06 +0200 Subject: [PATCH 8/9] removed unnecessary console.logs --- .../schedules-overview/schedules-overview.component.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app/components/schedules/schedules-overview/schedules-overview.component.ts b/src/app/components/schedules/schedules-overview/schedules-overview.component.ts index 241d068..4da1923 100644 --- a/src/app/components/schedules/schedules-overview/schedules-overview.component.ts +++ b/src/app/components/schedules/schedules-overview/schedules-overview.component.ts @@ -60,12 +60,10 @@ export class SchedulesOverviewComponent implements OnInit, OnDestroy { public jobDataService: JobDataService, public processDataService: ProcessDataService, private router: Router) { - console.log('construct'); } /** @ignore */ ngOnInit() { - console.log('init'); this.subscriptions.push( this.route.queryParamMap From ac525a7206feb0ee8c6242612b7b8fb752e46c67 Mon Sep 17 00:00:00 2001 From: Florian Lappe Date: Mon, 15 Jul 2019 13:48:37 +0200 Subject: [PATCH 9/9] fixed vurnerabilities and upgraded to angular 8 --- package.json | 52 +++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 9c44404..ac469bc 100644 --- a/package.json +++ b/package.json @@ -15,46 +15,44 @@ }, "private": true, "dependencies": { - "@angular/animations": "^7.2.12", - "@angular/cdk": "^7.3.6", - "@angular/common": "^7.2.12", - "@angular/compiler": "^7.2.12", - "@angular/core": "^7.2.12", - "@angular/flex-layout": "^7.0.0-beta.24", - "@angular/forms": "^7.2.12", - "@angular/http": "^7.2.12", - "@angular/platform-browser": "^7.2.12", - "@angular/platform-browser-dynamic": "^7.2.12", - "@angular/pwa": "^0.12.4", - "@angular/router": "^7.2.12", - "@angular/service-worker": "^7.2.6", - "@ngrx/store": "^7.2.0", + "@angular/animations": "^8.1.1", + "@angular/cdk": "^8.0.2", + "@angular/common": "^8.1.1", + "@angular/compiler": "^8.1.1", + "@angular/core": "^8.1.1", + "@angular/flex-layout": "^8.0.0-beta.26", + "@angular/forms": "^8.1.1", + "@angular/http": "*", + "@angular/platform-browser": "^8.1.1", + "@angular/platform-browser-dynamic": "^8.1.1", + "@angular/pwa": "^0.801.1", + "@angular/router": "^8.1.1", + "@angular/service-worker": "^8.1.1", + "@ngrx/store": "^8.1.0", "brace": "^0.11.1", "bulma-badge": "^2.0.0", - "bulma-checkradio": "^2.1.0", + "bulma-checkradio": "^2.1.1", "bulma-divider": "^2.0.1", "cloudiator-rest-api": "1.4.0", "core-js": "^2.6.5", - "cytoscape": "^3.5.2", + "cytoscape": "^3.8.1", "file-saver": "^2.0.1", "hammerjs": "^2.0.8", - "lodash": "^4.17.11", "node-sass": "^4.12.0", "rxjs": "^6.4.0", "sass-loader": "^7.1.0", - "webpack": "^4.29.6", + "webpack": "^4.35.3", "zone.js": "^0.8.29" }, "devDependencies": { - "@angular-devkit/build-angular": "^0.13.3", - "@angular/cli": "^7.3.8", - "@angular/compiler-cli": "^7.2.12", - "@angular/language-service": "^7.2.12", - "@compodoc/compodoc": "^1.1.8", + "@angular-devkit/build-angular": "^0.801.1", + "@angular/cli": "^8.1.1", + "@angular/compiler-cli": "^8.1.1", + "@angular/language-service": "^8.1.1", + "@compodoc/compodoc": "^1.1.10", "@types/jasmine": "^2.8.16", "@types/jasminewd2": "^2.0.6", - "@types/lodash": "^4.14.121", - "@types/node": "^10.14.4", + "@types/node": "^10.14.12", "bulma": "^0.7.4", "codelyzer": "^4.5.0", "hoek": "^6.1.2", @@ -69,7 +67,7 @@ "karma-teamcity-reporter": "^1.1.0", "protractor": "^5.4.2", "ts-node": "^7.0.1", - "tslint": "^5.15.0", - "typescript": "^3.1.6" + "tslint": "^5.18.0", + "typescript": "<3.5.0" } }