diff --git a/ui/.eslintignore b/ui/.eslintignore index a4ba0955eb..fd5519665a 100644 --- a/ui/.eslintignore +++ b/ui/.eslintignore @@ -38,5 +38,4 @@ src/app/NS src/app/pipeline-details src/app/pipelines src/app/profile -src/app/services src/scss diff --git a/ui/.prettierignore b/ui/.prettierignore index e90ed933fe..78fd58ffd1 100644 --- a/ui/.prettierignore +++ b/ui/.prettierignore @@ -39,5 +39,4 @@ src/app/NS src/app/pipeline-details src/app/pipelines src/app/profile -src/app/services src/scss diff --git a/ui/src/app/services/auth.service.ts b/ui/src/app/services/auth.service.ts index feb406d657..9dee94a47e 100644 --- a/ui/src/app/services/auth.service.ts +++ b/ui/src/app/services/auth.service.ts @@ -30,21 +30,29 @@ import { RoleModel } from '../_models/auth.model'; @Injectable() export class AuthService { - - public authToken$: BehaviorSubject = new BehaviorSubject(undefined); - public user$: BehaviorSubject = new BehaviorSubject(undefined); - public isLoggedIn$: BehaviorSubject = new BehaviorSubject(false); - public darkMode$: BehaviorSubject = new BehaviorSubject(false); - - constructor(private restApi: RestApi, - private tokenStorage: JwtTokenStorageService, - private router: Router, - private loginService: LoginService) { + public authToken$: BehaviorSubject = new BehaviorSubject( + undefined, + ); + public user$: BehaviorSubject = new BehaviorSubject( + undefined, + ); + public isLoggedIn$: BehaviorSubject = new BehaviorSubject( + false, + ); + public darkMode$: BehaviorSubject = new BehaviorSubject( + false, + ); + + constructor( + private restApi: RestApi, + private tokenStorage: JwtTokenStorageService, + private router: Router, + private loginService: LoginService, + ) { if (this.authenticated()) { this.authToken$.next(tokenStorage.getToken()); this.user$.next(tokenStorage.getUser()); this.isLoggedIn$.next(true); - } else { this.logout(); } @@ -71,10 +79,15 @@ export class AuthService { } public authenticated(): boolean { - const token = this.authToken$.getValue() || this.tokenStorage.getToken(); + const token = + this.authToken$.getValue() || this.tokenStorage.getToken(); const jwtHelper: JwtHelperService = new JwtHelperService({}); - return token !== null && token !== undefined && !jwtHelper.isTokenExpired(token); + return ( + token !== null && + token !== undefined && + !jwtHelper.isTokenExpired(token) + ); } public decodeJwtToken(token: string): any { @@ -83,27 +96,38 @@ export class AuthService { } checkConfiguration(): Observable { - return Observable.create((observer) => this.restApi.configured().subscribe(response => { - if (response.configured) { - observer.next(true); - } else { - observer.next(false); - } - }, error => { - observer.error(); - })); + return Observable.create(observer => + this.restApi.configured().subscribe( + response => { + if (response.configured) { + observer.next(true); + } else { + observer.next(false); + } + }, + error => { + observer.error(); + }, + ), + ); } scheduleTokenRenew() { - this.authToken$.pipe( - filter((token: any) => !!token), - map((token: any) => new JwtHelperService({}).getTokenExpirationDate(token)), - switchMap((expiresIn: Date) => timer(expiresIn.getTime() - Date.now() - 60000)), - ).subscribe(() => { - if (this.authenticated()) { - this.updateTokenAndUserInfo(); - } - }); + this.authToken$ + .pipe( + filter((token: any) => !!token), + map((token: any) => + new JwtHelperService({}).getTokenExpirationDate(token), + ), + switchMap((expiresIn: Date) => + timer(expiresIn.getTime() - Date.now() - 60000), + ), + ) + .subscribe(() => { + if (this.authenticated()) { + this.updateTokenAndUserInfo(); + } + }); } updateTokenAndUserInfo() { @@ -113,14 +137,20 @@ export class AuthService { } watchTokenExpiration() { - this.authToken$.pipe( - filter((token: any) => !!token), - map((token: any) => new JwtHelperService({}).getTokenExpirationDate(token)), - switchMap((expiresIn: Date) => timer(expiresIn.getTime() - Date.now() + 1)) - ).subscribe(() => { - this.logout(); - this.router.navigate(['login']); - }); + this.authToken$ + .pipe( + filter((token: any) => !!token), + map((token: any) => + new JwtHelperService({}).getTokenExpirationDate(token), + ), + switchMap((expiresIn: Date) => + timer(expiresIn.getTime() - Date.now() + 1), + ), + ) + .subscribe(() => { + this.logout(); + this.router.navigate(['login']); + }); } getUserRoles(): string[] { @@ -128,24 +158,32 @@ export class AuthService { } public hasRole(role: RoleModel): boolean { - return this.getUserRoles().includes('ROLE_ADMIN') || this.getUserRoles().includes(role); + return ( + this.getUserRoles().includes('ROLE_ADMIN') || + this.getUserRoles().includes(role) + ); } public hasAnyRole(roles: RoleModel[]): boolean { if (Array.isArray(roles)) { - return roles.reduce((aggregator: false, role: RoleModel) => aggregator || this.hasRole(role), false); + return roles.reduce( + (aggregator: false, role: RoleModel) => + aggregator || this.hasRole(role), + false, + ); } return false; } - isAnyAccessGranted(pageNames: PageName[], - redirect?: boolean): boolean { + isAnyAccessGranted(pageNames: PageName[], redirect?: boolean): boolean { if (!pageNames || pageNames.length === 0) { return true; } - const result = pageNames.some(pageName => this.isAccessGranted(pageName)); + const result = pageNames.some(pageName => + this.isAccessGranted(pageName), + ); if (!result && redirect) { this.router.navigate(['']); } @@ -162,17 +200,29 @@ export class AuthService { case PageName.PIPELINE_EDITOR: return this.hasAnyRole(['ROLE_PIPELINE_ADMIN']); case PageName.PIPELINE_OVERVIEW: - return this.hasAnyRole(['ROLE_PIPELINE_ADMIN', 'ROLE_PIPELINE_USER']); + return this.hasAnyRole([ + 'ROLE_PIPELINE_ADMIN', + 'ROLE_PIPELINE_USER', + ]); case PageName.CONNECT: return this.hasAnyRole(['ROLE_CONNECT_ADMIN']); case PageName.DASHBOARD: - return this.hasAnyRole(['ROLE_DASHBOARD_USER', 'ROLE_DASHBOARD_ADMIN']); + return this.hasAnyRole([ + 'ROLE_DASHBOARD_USER', + 'ROLE_DASHBOARD_ADMIN', + ]); case PageName.DATA_EXPLORER: - return this.hasAnyRole(['ROLE_DATA_EXPLORER_ADMIN', 'ROLE_DATA_EXPLORER_USER']); + return this.hasAnyRole([ + 'ROLE_DATA_EXPLORER_ADMIN', + 'ROLE_DATA_EXPLORER_USER', + ]); case PageName.APPS: return this.hasAnyRole(['ROLE_APP_USER']); case PageName.FILE_UPLOAD: - return this.hasAnyRole(['ROLE_CONNECT_ADMIN', 'ROLE_PIPELINE_ADMIN']); + return this.hasAnyRole([ + 'ROLE_CONNECT_ADMIN', + 'ROLE_PIPELINE_ADMIN', + ]); case PageName.INSTALL_PIPELINE_ELEMENTS: return this.hasAnyRole(['ROLE_ADMIN']); case PageName.NOTIFICATIONS: diff --git a/ui/src/app/services/available-roles.service.ts b/ui/src/app/services/available-roles.service.ts index 64893d7e93..4d7c302412 100644 --- a/ui/src/app/services/available-roles.service.ts +++ b/ui/src/app/services/available-roles.service.ts @@ -22,24 +22,66 @@ import { UserRole } from '../_enums/user-role.enum'; @Injectable() export class AvailableRolesService { + availableRoles: RoleDescription[] = [ + { role: UserRole.ROLE_ADMIN, roleTitle: 'Admin', roleDescription: '' }, + { + role: UserRole.ROLE_SERVICE_ADMIN, + roleTitle: 'Service Admin', + roleDescription: '', + }, + { + role: UserRole.ROLE_APP_USER, + roleTitle: 'App User', + roleDescription: '', + }, + { + role: UserRole.ROLE_DASHBOARD_USER, + roleTitle: 'Dashboard User', + roleDescription: '', + }, + { + role: UserRole.ROLE_DASHBOARD_ADMIN, + roleTitle: 'Dashboard Admin', + roleDescription: '', + }, + { + role: UserRole.ROLE_DATA_EXPLORER_USER, + roleTitle: 'Data Explorer User', + roleDescription: '', + }, + { + role: UserRole.ROLE_DATA_EXPLORER_ADMIN, + roleTitle: 'Data Explorer Admin', + roleDescription: '', + }, + { + role: UserRole.ROLE_CONNECT_ADMIN, + roleTitle: 'Connect Admin', + roleDescription: '', + }, + { + role: UserRole.ROLE_PIPELINE_USER, + roleTitle: 'Pipeline User', + roleDescription: '', + }, + { + role: UserRole.ROLE_PIPELINE_ADMIN, + roleTitle: 'Pipeline Admin', + roleDescription: '', + }, + { + role: UserRole.ROLE_ASSET_USER, + roleTitle: 'Asset User', + roleDescription: '', + }, + { + role: UserRole.ROLE_ASSET_ADMIN, + roleTitle: 'Asset Admin', + roleDescription: '', + }, + ]; - availableRoles: RoleDescription[] = [ - {role: UserRole.ROLE_ADMIN, roleTitle: 'Admin', roleDescription: ''}, - {role: UserRole.ROLE_SERVICE_ADMIN, roleTitle: 'Service Admin', roleDescription: ''}, - {role: UserRole.ROLE_APP_USER, roleTitle: 'App User', roleDescription: ''}, - {role: UserRole.ROLE_DASHBOARD_USER, roleTitle: 'Dashboard User', roleDescription: ''}, - {role: UserRole.ROLE_DASHBOARD_ADMIN, roleTitle: 'Dashboard Admin', roleDescription: ''}, - {role: UserRole.ROLE_DATA_EXPLORER_USER, roleTitle: 'Data Explorer User', roleDescription: ''}, - {role: UserRole.ROLE_DATA_EXPLORER_ADMIN, roleTitle: 'Data Explorer Admin', roleDescription: ''}, - {role: UserRole.ROLE_CONNECT_ADMIN, roleTitle: 'Connect Admin', roleDescription: ''}, - {role: UserRole.ROLE_PIPELINE_USER, roleTitle: 'Pipeline User', roleDescription: ''}, - {role: UserRole.ROLE_PIPELINE_ADMIN, roleTitle: 'Pipeline Admin', roleDescription: ''}, - {role: UserRole.ROLE_ASSET_USER, roleTitle: 'Asset User', roleDescription: ''}, - {role: UserRole.ROLE_ASSET_ADMIN, roleTitle: 'Asset Admin', roleDescription: ''}, - ]; - - - public getAvailableRoles(): RoleDescription[] { - return this.availableRoles; - } + public getAvailableRoles(): RoleDescription[] { + return this.availableRoles; + } } diff --git a/ui/src/app/services/get-element-icon-text.service.ts b/ui/src/app/services/get-element-icon-text.service.ts index eeff6a657c..2bc2960451 100644 --- a/ui/src/app/services/get-element-icon-text.service.ts +++ b/ui/src/app/services/get-element-icon-text.service.ts @@ -20,7 +20,6 @@ import { Injectable } from '@angular/core'; @Injectable() export class ElementIconText { - constructor() {} getElementIconText(s) { diff --git a/ui/src/app/services/jwt-token-storage.service.ts b/ui/src/app/services/jwt-token-storage.service.ts index 3d535c1217..ee696bb070 100644 --- a/ui/src/app/services/jwt-token-storage.service.ts +++ b/ui/src/app/services/jwt-token-storage.service.ts @@ -22,28 +22,27 @@ const TOKEN_KEY = 'auth-token'; const USER_KEY = 'auth-user'; export class JwtTokenStorageService { + constructor() {} - constructor() { } + clearTokens(): void { + window.localStorage.clear(); + } - clearTokens(): void { - window.localStorage.clear(); - } + public saveToken(token: string): void { + window.localStorage.removeItem(TOKEN_KEY); + window.localStorage.setItem(TOKEN_KEY, token); + } - public saveToken(token: string): void { - window.localStorage.removeItem(TOKEN_KEY); - window.localStorage.setItem(TOKEN_KEY, token); - } + public getToken(): string { + return localStorage.getItem(TOKEN_KEY); + } - public getToken(): string { - return localStorage.getItem(TOKEN_KEY); - } + public saveUser(user: UserInfo): void { + window.localStorage.removeItem(USER_KEY); + window.localStorage.setItem(USER_KEY, JSON.stringify(user)); + } - public saveUser(user: UserInfo): void { - window.localStorage.removeItem(USER_KEY); - window.localStorage.setItem(USER_KEY, JSON.stringify(user)); - } - - public getUser(): UserInfo { - return JSON.parse(localStorage.getItem(USER_KEY)); - } + public getUser(): UserInfo { + return JSON.parse(localStorage.getItem(USER_KEY)); + } } diff --git a/ui/src/app/services/notification-count-service.ts b/ui/src/app/services/notification-count-service.ts index bc8a8ecbdd..6ee91da260 100644 --- a/ui/src/app/services/notification-count-service.ts +++ b/ui/src/app/services/notification-count-service.ts @@ -21,19 +21,16 @@ import { BehaviorSubject } from 'rxjs'; @Injectable() export class NotificationCountService { - public unreadNotificationCount$ = new BehaviorSubject(0); lockNotificationId: string; lockActive = false; - constructor(private restApi: RestApi) { - } + constructor(private restApi: RestApi) {} loadUnreadNotifications() { - this.restApi.getUnreadNotificationsCount() - .subscribe(response => { - this.unreadNotificationCount$.next(response.count); - }); + this.restApi.getUnreadNotificationsCount().subscribe(response => { + this.unreadNotificationCount$.next(response.count); + }); } decreaseNotificationCount() { diff --git a/ui/src/app/services/property-selector.service.ts b/ui/src/app/services/property-selector.service.ts index 87d1a0f100..7fbad83989 100644 --- a/ui/src/app/services/property-selector.service.ts +++ b/ui/src/app/services/property-selector.service.ts @@ -17,31 +17,38 @@ */ import { Injectable } from '@angular/core'; -import { EventPropertyNested, EventPropertyUnion } from '@streampipes/platform-services'; +import { + EventPropertyNested, + EventPropertyUnion, +} from '@streampipes/platform-services'; @Injectable() export class PropertySelectorService { - firstStreamPrefix = 's0'; secondStreamPrefix = 's1'; propertyDelimiter = '::'; - constructor() { - - } + constructor() {} - makeProperties(eventProperties: any[], availablePropertyKeys: string[], currentPointer) { + makeProperties( + eventProperties: any[], + availablePropertyKeys: string[], + currentPointer, + ) { const outputProperties = []; eventProperties.forEach(ep => { availablePropertyKeys.forEach(apk => { if (this.isInSelection(ep, apk, currentPointer)) { - ep.runtimeId = this.makeSelector(currentPointer, ep.runtimeName); + ep.runtimeId = this.makeSelector( + currentPointer, + ep.runtimeName, + ); if (this.isNested(ep)) { - ep.eventProperties = - this.makeProperties( - ep.eventProperties, - availablePropertyKeys, - this.makeSelector(currentPointer, ep.runtimeName)); + ep.eventProperties = this.makeProperties( + ep.eventProperties, + availablePropertyKeys, + this.makeSelector(currentPointer, ep.runtimeName), + ); } outputProperties.push(ep); } @@ -50,13 +57,18 @@ export class PropertySelectorService { return outputProperties; } - makeFlatProperties(eventProperties: EventPropertyUnion[], availablePropertyKeys: string[]) { + makeFlatProperties( + eventProperties: EventPropertyUnion[], + availablePropertyKeys: string[], + ) { const outputProperties = []; availablePropertyKeys.forEach(apk => { const keyArray = apk.split('::'); keyArray.shift(); - outputProperties.push(this.makeProperty(eventProperties, keyArray, apk)); + outputProperties.push( + this.makeProperty(eventProperties, keyArray, apk), + ); }); return outputProperties; } @@ -67,11 +79,16 @@ export class PropertySelectorService { if (ep.runtimeName === propertySelector[0]) { if (this.isNested(ep)) { propertySelector.shift(); - outputProperty = this.makeProperty(ep.eventProperties, propertySelector, originalSelector); + outputProperty = this.makeProperty( + ep.eventProperties, + propertySelector, + originalSelector, + ); } else { ep.runtimeId = originalSelector; outputProperty = ep; - outputProperty.properties.niceLabel = this.makeNiceLabel(originalSelector); + outputProperty.properties.niceLabel = + this.makeNiceLabel(originalSelector); } } }); @@ -86,11 +103,17 @@ export class PropertySelectorService { return ep instanceof EventPropertyNested; } - isInSelection(inputProperty: EventPropertyUnion, propertySelector, currentPropertyPointer) { - return (currentPropertyPointer - + this.propertyDelimiter - + inputProperty.runtimeName) === propertySelector; - + isInSelection( + inputProperty: EventPropertyUnion, + propertySelector, + currentPropertyPointer, + ) { + return ( + currentPropertyPointer + + this.propertyDelimiter + + inputProperty.runtimeName === + propertySelector + ); } makeSelector(prefix, current) { diff --git a/ui/src/app/services/rest-api.service.ts b/ui/src/app/services/rest-api.service.ts index 23eae54e41..62a2d46ff2 100644 --- a/ui/src/app/services/rest-api.service.ts +++ b/ui/src/app/services/rest-api.service.ts @@ -23,12 +23,12 @@ import { Observable } from 'rxjs'; @Injectable() export class RestApi { - encodeURIComponent: any; - constructor (private platformServicesCommons: PlatformServicesCommons, - private $http: HttpClient) { - } + constructor( + private platformServicesCommons: PlatformServicesCommons, + private $http: HttpClient, + ) {} getServerUrl() { return this.platformServicesCommons.apiBasePath; @@ -44,16 +44,21 @@ export class RestApi { configured(): Observable { return this.$http.get(this.getServerUrl() + '/setup/configured', { - headers: { ignoreLoadingBar: '' } + headers: { ignoreLoadingBar: '' }, }); } getUnreadNotificationsCount(): Observable { - return this.$http.get(this.urlApiBase() + '/notifications/count', { headers: { ignoreLoadingBar: '' }}); + return this.$http.get(this.urlApiBase() + '/notifications/count', { + headers: { ignoreLoadingBar: '' }, + }); } getDomainKnowledgeItems(query) { - return this.$http.post(this.getServerUrl() + '/autocomplete/domain', query); + return this.$http.post( + this.getServerUrl() + '/autocomplete/domain', + query, + ); } getAllUnits() { @@ -65,7 +70,11 @@ export class RestApi { } getUnit(resource) { - return this.$http.get(this.getServerUrl() + '/units/instances/' + encodeURIComponent(resource)); + return this.$http.get( + this.getServerUrl() + + '/units/instances/' + + encodeURIComponent(resource), + ); } getEpaCategories() { @@ -89,7 +98,10 @@ export class RestApi { } updateCachedPipeline(rawPipelineModel: any) { - return this.$http.post(this.urlApiBase() + '/pipeline-cache', rawPipelineModel); + return this.$http.post( + this.urlApiBase() + '/pipeline-cache', + rawPipelineModel, + ); } removePipelineFromCache() { diff --git a/ui/src/app/services/secure.pipe.ts b/ui/src/app/services/secure.pipe.ts index 11538bd496..5027e7359d 100644 --- a/ui/src/app/services/secure.pipe.ts +++ b/ui/src/app/services/secure.pipe.ts @@ -16,7 +16,6 @@ * */ - import { Pipe, PipeTransform } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; @@ -25,18 +24,30 @@ import { map } from 'rxjs/operators'; import { Observable } from 'rxjs'; @Pipe({ - name: 'secure' + name: 'secure', }) export class SecurePipe implements PipeTransform { + constructor( + private http: HttpClient, + private sanitizer: DomSanitizer, + private authService: AuthService, + ) {} - constructor(private http: HttpClient, - private sanitizer: DomSanitizer, - private authService: AuthService) { } - - transform(url): Observable { - return this.http - .get(url, { responseType: 'blob', headers: {'Authorization': 'Bearer ' + this.authService.authToken$.value}}) - .pipe(map(val => this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(val)))); - } - + transform(url): Observable { + return this.http + .get(url, { + responseType: 'blob', + headers: { + Authorization: + 'Bearer ' + this.authService.authToken$.value, + }, + }) + .pipe( + map(val => + this.sanitizer.bypassSecurityTrustUrl( + URL.createObjectURL(val), + ), + ), + ); + } } diff --git a/ui/src/app/services/services.module.ts b/ui/src/app/services/services.module.ts index c27c7de91f..5e597d1f97 100644 --- a/ui/src/app/services/services.module.ts +++ b/ui/src/app/services/services.module.ts @@ -27,7 +27,7 @@ import { ElementIconText } from './get-element-icon-text.service'; import { AppConstants } from './app.constants'; import { JwtTokenStorageService } from './jwt-token-storage.service'; import { PlatformServicesModule } from '@streampipes/platform-services'; -import { SecurePipe } from "./secure.pipe"; +import { SecurePipe } from './secure.pipe'; @NgModule({ imports: [], @@ -45,7 +45,6 @@ import { SecurePipe } from "./secure.pipe"; PlatformServicesModule, SecurePipe, ], - exports: [SecurePipe] + exports: [SecurePipe], }) -export class ServicesModule { -} +export class ServicesModule {} diff --git a/ui/src/app/services/tour/adapter-tour-2.constants.ts b/ui/src/app/services/tour/adapter-tour-2.constants.ts index aff1698994..8a9e520040 100644 --- a/ui/src/app/services/tour/adapter-tour-2.constants.ts +++ b/ui/src/app/services/tour/adapter-tour-2.constants.ts @@ -19,51 +19,47 @@ export default { adapterTour: { id: 'adapter2', - steps: [{ - stepId: 'step-1', - title: 'Welcome to the Second Adapter Tutorial', - text: '

In this tutorial you will learn how to get official environment data from the \'Landesamt für Umwelt Baden-Württemberg\' LUBW.' + - '

Click next to continue.', - classes: 'shepherd shepherd-welcome', - buttons: [ - 'cancel', - 'next' - ] - }, + steps: [ + { + stepId: 'step-1', + title: 'Welcome to the Second Adapter Tutorial', + text: + "

In this tutorial you will learn how to get official environment data from the 'Landesamt für Umwelt Baden-Württemberg' LUBW." + + '

Click next to continue.', + classes: 'shepherd shepherd-welcome', + buttons: ['cancel', 'next'], + }, { stepId: 'step-2', title: 'Select a new adapter', - text: '

Let\'s start!

' + - '

Select the Http Stream adapter to get the data from the LUBW

' + - '
Sensebox
' + - 'The image shows a measuring station. Those stations are distributed all over Baden-Württemberg', + text: + "

Let's start!

" + + '

Select the Http Stream adapter to get the data from the LUBW

' + + '
Sensebox
' + + 'The image shows a measuring station. Those stations are distributed all over Baden-Württemberg', attachToElement: '#HTTP_Stream', attachPosition: 'bottom', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-3', title: 'Configure the protocol', - text: 'The data is provided through a REST endpoint, which has to be polled regularly. To do this set the Interval [Sec] to 60. This means the endpoint is accessed every minute.' + - 'The URL of the endpoint is: restendpoint:3001/lubw, copy this URL into the URL field', + text: + 'The data is provided through a REST endpoint, which has to be polled regularly. To do this set the Interval [Sec] to 60. This means the endpoint is accessed every minute.' + + 'The URL of the endpoint is: restendpoint:3001/lubw, copy this URL into the URL field', attachToElement: '#formWrapper:last-of-type', attachPosition: 'top', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-4', title: 'Select the format geo Json', - text: 'The data is provided in the form of geo Json. This is a Json format optimized for geospatiol data. To process this data select the GeoJson format. This format needs no further configuration.' + - ' Go to the next step', + text: + 'The data is provided in the form of geo Json. This is a Json format optimized for geospatiol data. To process this data select the GeoJson format. This format needs no further configuration.' + + ' Go to the next step', attachToElement: '#GeoJSON', attachPosition: 'right', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-5', @@ -71,15 +67,14 @@ export default { text: 'After selecting GeoJson as a format go to the next step', attachPosition: 'top', attachToElement: '#format-selection-next-button', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-6.0', title: 'Change the schema of the data', - text: 'The data source of LUWB provices a lot of information and we do not need all of this. Therefore first delete all properties, except the following.' + - '
    ' + + text: + 'The data source of LUWB provices a lot of information and we do not need all of this. Therefore first delete all properties, except the following.' + + '
      ' + '
    • no2kont (NO2)
    • ' + '
    • ozon (Ozon)
    • ' + '
    • pm10grav (Particulate Matter)
    • ' + @@ -87,15 +82,11 @@ export default { '
    • longitude (Location Longitude)
    • ' + '
    • timestamp (Timestemp of data point)
    • ' + '
    • id (Id of the station)
    • ' + - '
    ' + - 'When you make any errors during the editing you can reset the the schema on the reload button.', + '
' + + 'When you make any errors during the editing you can reset the the schema on the reload button.', attachToElement: '#schema_reload_button', attachPosition: 'top', - buttons: [ - 'cancel', - 'next' - - ] + buttons: ['cancel', 'next'], }, { stepId: 'step-6.1', @@ -103,9 +94,7 @@ export default { text: 'Finish the modelling and go to next step to start the adapter', attachToElement: '#event-schema-next-button', attachPosition: 'bottom', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-7', @@ -113,9 +102,7 @@ export default { text: 'Change the name of the adapter to LUBW and click on button Start Adapter', attachToElement: '#input-AdapterName', attachPosition: 'top', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-8', @@ -123,30 +110,32 @@ export default { text: 'Wait for the data! Then finish the creation process by clicking on this button.', attachToElement: '#confirm_adapter_started_button', attachPosition: 'right', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-9', title: 'Congratulation', text: 'Congratulation you have created your first adapter and finished the tutorial. Go to the pipeline editor to see the new data source', classes: 'shepherd shepherd-welcome', - buttons: [ - 'cancel' - ] - } + buttons: ['cancel'], + }, ], matchingSteps: [ - {actionId: 'select-adapter', currentStep: 'step-2'}, - {actionId: 'specific-settings-next-button', currentStep: 'step-3'}, - {actionId: 'select-format', currentStep: 'step-4'}, - {actionId: 'format-selection-next-button', currentStep: 'step-5'}, + { actionId: 'select-adapter', currentStep: 'step-2' }, + { + actionId: 'specific-settings-next-button', + currentStep: 'step-3', + }, + { actionId: 'select-format', currentStep: 'step-4' }, + { actionId: 'format-selection-next-button', currentStep: 'step-5' }, - {actionId: 'event-schema-next-button', currentStep: 'step-6.1'}, + { actionId: 'event-schema-next-button', currentStep: 'step-6.1' }, - {actionId: 'button-startAdapter', currentStep: 'step-7'}, - {actionId: 'confirm_adapter_started_button', currentStep: 'step-8'}, - ] - } + { actionId: 'button-startAdapter', currentStep: 'step-7' }, + { + actionId: 'confirm_adapter_started_button', + currentStep: 'step-8', + }, + ], + }, }; diff --git a/ui/src/app/services/tour/adapter-tour-3.constants.ts b/ui/src/app/services/tour/adapter-tour-3.constants.ts index 2f8e00a932..dc26631ed5 100644 --- a/ui/src/app/services/tour/adapter-tour-3.constants.ts +++ b/ui/src/app/services/tour/adapter-tour-3.constants.ts @@ -19,63 +19,57 @@ export default { adapterTour: { id: 'adapter3', - steps: [{ - stepId: 'step-1', - title: 'Welcome to the Second Adapter Tutorial', - text: '

In this tutorial we connect the live data form parking lots of the LAX airport.

' + - '

Link to data description: https://goo.gl/48y2xv

' + - 'Click next to continue.', - classes: 'shepherd shepherd-welcome', - buttons: [ - 'cancel', - 'next' - ] - }, + steps: [ + { + stepId: 'step-1', + title: 'Welcome to the Second Adapter Tutorial', + text: + '

In this tutorial we connect the live data form parking lots of the LAX airport.

' + + '

Link to data description: https://goo.gl/48y2xv

' + + 'Click next to continue.', + classes: 'shepherd shepherd-welcome', + buttons: ['cancel', 'next'], + }, { stepId: 'step-2', title: 'Select a new adapter', - text: '

Let\'s start!

' + - '

First select the Http Stream adapter

', + text: + "

Let's start!

" + + '

First select the Http Stream adapter

', attachToElement: '#HTTP_Stream', attachPosition: 'bottom', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-3', title: 'Configure the protocol', - text: 'The data is provided through a REST endpoint, which has to be polled regularly. To do this set the Interval to 60. This configuration will poll the data every minute' + - 'The URL of the endpoint is: https://data.lacity.org/resource/xzkr-5anj.json, copy this URL into the URL field' + - '

After setting the configuration, click on next to go to the next step

', + text: + 'The data is provided through a REST endpoint, which has to be polled regularly. To do this set the Interval to 60. This configuration will poll the data every minute' + + 'The URL of the endpoint is: https://data.lacity.org/resource/xzkr-5anj.json, copy this URL into the URL field' + + '

After setting the configuration, click on next to go to the next step

', attachToElement: '#formWrapper:last-of-type', attachPosition: 'top', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-4', title: 'Select the format Json Array No Key', - text: 'Click on Json Array No Key format. The data is provided in an array and no further configurations are required' + - 'Go to the next step', + text: + 'Click on Json Array No Key format. The data is provided in an array and no further configurations are required' + + 'Go to the next step', attachToElement: '#json_array_no_key', attachPosition: 'left', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-6.0', title: 'Change the schema of the data', - text: 'In this view you can see the schema of each data entry. You can use the schema editor to change the schema, add more information and have a look at the data' + - '

When you understand the schema of the data go to the next step by clicking on the next button!', + text: + 'In this view you can see the schema of each data entry. You can use the schema editor to change the schema, add more information and have a look at the data' + + '

When you understand the schema of the data go to the next step by clicking on the next button!', attachToElement: '#schema_reload_button', attachPosition: 'top', - buttons: [ - 'cancel', - - ] + buttons: ['cancel'], }, { stepId: 'step-7', @@ -83,9 +77,7 @@ export default { text: 'Change the name of the adapter to LAX and click on button Start Adapter', attachToElement: '#input-AdapterName', attachPosition: 'top', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-8', @@ -93,29 +85,31 @@ export default { text: 'Wait for the data! Then finish the creation process by clicking on this button.', attachToElement: '#confirm_adapter_started_button', attachPosition: 'right', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-9', title: 'Congratulation', text: 'Congratulation you have created your second adapter and finished the tutorial. Go to the pipeline editor to see the new data source', classes: 'shepherd shepherd-welcome', - buttons: [ - 'cancel' - ] - } + buttons: ['cancel'], + }, ], matchingSteps: [ - {actionId: 'select-adapter', currentStep: 'step-2'}, - {actionId: 'specific-settings-next-button', currentStep: 'step-3'}, - {actionId: 'format-selection-next-button', currentStep: 'step-4'}, + { actionId: 'select-adapter', currentStep: 'step-2' }, + { + actionId: 'specific-settings-next-button', + currentStep: 'step-3', + }, + { actionId: 'format-selection-next-button', currentStep: 'step-4' }, - {actionId: 'event-schema-next-button', currentStep: 'step-6.0'}, + { actionId: 'event-schema-next-button', currentStep: 'step-6.0' }, - {actionId: 'button-startAdapter', currentStep: 'step-7'}, - {actionId: 'confirm_adapter_started_button', currentStep: 'step-8'}, - ] - } + { actionId: 'button-startAdapter', currentStep: 'step-7' }, + { + actionId: 'confirm_adapter_started_button', + currentStep: 'step-8', + }, + ], + }, }; diff --git a/ui/src/app/services/tour/adapter-tour.constants.ts b/ui/src/app/services/tour/adapter-tour.constants.ts index ece3c5273c..eea1b7d19a 100644 --- a/ui/src/app/services/tour/adapter-tour.constants.ts +++ b/ui/src/app/services/tour/adapter-tour.constants.ts @@ -19,112 +19,104 @@ export default { adapterTour: { id: 'adapter', - steps: [{ - stepId: 'step-1', - title: 'Welcome to the Adapter Tutorial', - text: '

In this tour you will learn how to create a new adapter, which then can be used as a source in the pipeline editor.

Click next to continue.', - classes: 'shepherd shepherd-welcome', - buttons: [ - 'cancel', - 'next' - ] - }, + steps: [ + { + stepId: 'step-1', + title: 'Welcome to the Adapter Tutorial', + text: '

In this tour you will learn how to create a new adapter, which then can be used as a source in the pipeline editor.

Click next to continue.', + classes: 'shepherd shepherd-welcome', + buttons: ['cancel', 'next'], + }, { stepId: 'step-2', title: 'Select a new adapter', - text: '

Let\'s start!

' + - '

This is the OpenSenseMap adapter. OpenSenseMap is an online service where everybody can publish environment data.

' + - '
Sensebox
' + - 'Click on OpenSenseMap Adapter to continue.', + text: + "

Let's start!

" + + '

This is the OpenSenseMap adapter. OpenSenseMap is an online service where everybody can publish environment data.

' + + '
Sensebox
' + + 'Click on OpenSenseMap Adapter to continue.', attachToElement: '#OpenSenseMap', attachPosition: 'bottom', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-3', title: 'Select the sensors you are interested in', - text: '

Select all sensors in the menu on the left. With the selection you just get the values of the sensor boxes containing all sensors.

' + - 'After selecting all Sensors click on next to continue.', + text: + '

Select all sensors in the menu on the left. With the selection you just get the values of the sensor boxes containing all sensors.

' + + 'After selecting all Sensors click on next to continue.', attachToElement: '#specific-settings-next-button', attachPosition: 'top', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-4', title: 'Configure the schema of the data', - text: 'In this editor it is possible to change the schema of the sensebox data. Each entry describes a property. For example the id property contains the unique id of the sensebox. ' + - 'Open the configuration menu by clicking on the arrow!', + text: + 'In this editor it is possible to change the schema of the sensebox data. Each entry describes a property. For example the id property contains the unique id of the sensebox. ' + + 'Open the configuration menu by clicking on the arrow!', attachToElement: '#id button:last-of-type', attachPosition: 'top', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-5', title: 'Change the id runtime name', - text: 'The runtime name represents the key in our Json data objects. Change the value of the runtime name to new_id. This will also change all the keys later in the real data stream. ' + - 'Then click the next button of the user guide.', + text: + 'The runtime name represents the key in our Json data objects. Change the value of the runtime name to new_id. This will also change all the keys later in the real data stream. ' + + 'Then click the next button of the user guide.', attachToElement: '#input-runtime-name-Id', attachPosition: 'bottom', - buttons: [ - 'cancel', - 'next' - ] + buttons: ['cancel', 'next'], }, - { + { stepId: 'step-6', title: 'Go to next Step', text: 'Finish the modelling and go to next step to start the adapter. Click next to continue.', attachToElement: '#event-schema-next-button', attachPosition: 'bottom', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-7', title: 'Start Adapter', - text: 'Change the name of the adapter to OpenSenseMap and click on button \'Start Adapter\'', + text: "Change the name of the adapter to OpenSenseMap and click on button 'Start Adapter'", attachToElement: '#input-AdapterName', attachPosition: 'top', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-8', title: 'Adapter was started successfully', - text: '

The adpater is now deployed in the background and the data is fetched and processed from the OpenSenseMap endpoint. Here you will see some example data, which is coming directly ' + - 'the data source. This might take a minute. On the left you can see the runtime names of the properties you defined before. On the right side the values are shown. After having a look at ' + - 'the data click on Close to continue.

', + text: + '

The adpater is now deployed in the background and the data is fetched and processed from the OpenSenseMap endpoint. Here you will see some example data, which is coming directly ' + + 'the data source. This might take a minute. On the left you can see the runtime names of the properties you defined before. On the right side the values are shown. After having a look at ' + + 'the data click on Close to continue.

', attachToElement: '#confirm_adapter_started_button', attachPosition: 'bottom', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-9', title: 'Congratulation', text: 'Congratulation! You have created your first adapter and finished the tutorial. Go to the pipeline editor to see the new data source', classes: 'shepherd shepherd-welcome', - buttons: [ - 'cancel' - ] - } + buttons: ['cancel'], + }, ], matchingSteps: [ - {actionId: 'select-adapter', currentStep: 'step-2'}, - {actionId: 'specific-settings-next-button', currentStep: 'step-3'}, - {actionId: 'open-event-property-primitve', currentStep: 'step-4'}, - {actionId: 'event-schema-next-button', currentStep: 'step-6'}, - {actionId: 'button-startAdapter', currentStep: 'step-7'}, - {actionId: 'confirm_adapter_started_button', currentStep: 'step-8'}, - ] - } + { actionId: 'select-adapter', currentStep: 'step-2' }, + { + actionId: 'specific-settings-next-button', + currentStep: 'step-3', + }, + { actionId: 'open-event-property-primitve', currentStep: 'step-4' }, + { actionId: 'event-schema-next-button', currentStep: 'step-6' }, + { actionId: 'button-startAdapter', currentStep: 'step-7' }, + { + actionId: 'confirm_adapter_started_button', + currentStep: 'step-8', + }, + ], + }, }; diff --git a/ui/src/app/services/tour/create-pipeline-tour.constants.ts b/ui/src/app/services/tour/create-pipeline-tour.constants.ts index b9bbacea82..ed09e30daa 100644 --- a/ui/src/app/services/tour/create-pipeline-tour.constants.ts +++ b/ui/src/app/services/tour/create-pipeline-tour.constants.ts @@ -25,31 +25,24 @@ export default { title: 'Welcome!', classes: 'shepherd shepherd-welcome', text: '

This tour will teach you how to create your first pipeline. You will learn how to select streams, how to connect data processors and sinks and how to start a pipeline.

Click next to continue.', - buttons: [ - 'cancel', - 'next' - ] + buttons: ['cancel', 'next'], }, { stepId: 'step-2', title: 'Pipeline Element Selection', - text: '

Let\'s start!

This is the Pipeline Element Selection panel. Here you can select and use all available pipeline elements.

', + text: "

Let's start!

This is the Pipeline Element Selection panel. Here you can select and use all available pipeline elements.

", attachToElement: '#editor-icon-stand', attachPosition: 'left', - buttons: [ - 'cancel', - 'next' - ] + buttons: ['cancel', 'next'], }, { stepId: 'step-3', title: 'Selecting data streams', - text: 'The first element of a pipeline is a data stream, which produces data you\'d like to transform.

To select a stream, drag and drop the stream named Flow Rate 1 to the assembly area on the right.

', - attachToElement: '#org\\.apache\\.streampipes\\.sources\\.simulator\\.flowrate1', + text: "The first element of a pipeline is a data stream, which produces data you'd like to transform.

To select a stream, drag and drop the stream named Flow Rate 1 to the assembly area on the right.

", + attachToElement: + '#org\\.apache\\.streampipes\\.sources\\.simulator\\.flowrate1', attachPosition: 'left', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-4', @@ -57,10 +50,7 @@ export default { text: '

Cool!

Dragging and dropping elements is the basic principle you need to know to create pipelines. You only need to select a pipeline element and drop it to the assembly area.

Click Next to continue.

', attachToElement: '#assembly>pipeline .stream:nth-child(1)', attachPosition: 'left', - buttons: [ - 'cancel', - 'next' - ] + buttons: ['cancel', 'next'], }, { stepId: 'step-5', @@ -68,30 +58,25 @@ export default { text: 'No we will add a data processor. This is the data processor list which shows all currently available data processors.

Click Next to continue.

', attachToElement: '#panel-2', attachPosition: 'left', - buttons: [ - 'cancel', - 'next' - ] + buttons: ['cancel', 'next'], }, { stepId: 'step-6', title: 'Selecting data processors', text: '

Processors can provide simple capabilities such as filters or aggregations, but can also provide more advanced capabilities such as trend and pattern detection or even pre-trained neural networks.

Select the processor called Numerical Filter and move it to the assembly area.

', - attachToElement: '#org\\.apache\\.streampipes\\.processors\\.filters\\.jvm\\.numericalfilter', + attachToElement: + '#org\\.apache\\.streampipes\\.processors\\.filters\\.jvm\\.numericalfilter', attachPosition: 'right', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-7', title: 'Connecting elements', - text: '

Now it\'s time to connect the first elements of your pipeline!

Click the gray output port of the stream and connect it with the Numerical Filter component.

', - attachToElement: '#assembly>div.jsplumb-endpoint:nth-of-type(1)', + text: "

Now it's time to connect the first elements of your pipeline!

Click the gray output port of the stream and connect it with the Numerical Filter component.

", + attachToElement: + '#assembly>div.jsplumb-endpoint:nth-of-type(1)', attachPosition: 'bottom', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-8', @@ -99,40 +84,33 @@ export default { text: '

Most pipeline elements can be customized according to your needs. Whenever you connect two elements with each other, a configuration dialog pops up.

Select Mass Flow as the field to filter, select greater than (>) as operation, select 2 as the threshold value and click Save.

', attachToElement: 'div .dialog-panel-content', attachPosition: 'right', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-9', title: 'Selecting data sinks', - text: '

What\'s missing?

Every pipeline needs a data sink. Sinks define what to do with the output of your pipeline and can be visualizations, notifications, or can trigger third party components or even actuators.

Click Next to continue.

', + text: "

What's missing?

Every pipeline needs a data sink. Sinks define what to do with the output of your pipeline and can be visualizations, notifications, or can trigger third party components or even actuators.

Click Next to continue.

", attachToElement: '#panel-3', attachPosition: 'left', - buttons: [ - 'cancel', - 'next' - ] + buttons: ['cancel', 'next'], }, { stepId: 'step-10', title: 'Finish Pipeline', text: '

Almost there!

Select the Data Lake sink and connect the Numerical Filter to the Data Lake sink. Enter any storage name in the configuration menu.

', - attachToElement: '#org\\.apache\\.streampipes\\.sinks\\.internal\\.jvm\\.datalake', + attachToElement: + '#org\\.apache\\.streampipes\\.sinks\\.internal\\.jvm\\.datalake', attachPosition: 'left', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-11', title: 'Save Pipeline', - text: '

Great!

Your first pipeline is complete. No we\'re ready to start the pipeline.

Click the Save icon to open the save dialog.

', - attachToElement: '.pipeline-assembly-options>div>button:nth-of-type(1)', + text: "

Great!

Your first pipeline is complete. No we're ready to start the pipeline.

Click the Save icon to open the save dialog.

", + attachToElement: + '.pipeline-assembly-options>div>button:nth-of-type(1)', attachPosition: 'left', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-12', @@ -140,42 +118,38 @@ export default { text: '

Enter a name and an optional description of your pipeline.

Afterwards, make sure that Start pipeline immediately is checked.

', attachToElement: 'div .dialog-panel-content', attachPosition: 'right', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-13', title: 'Save Pipeline Dialog', text: '

Click on Save and go to pipeline view to start the pipeline.

', - attachToElement: 'save-pipeline .sp-dialog-actions>button:nth-of-type(2)', + attachToElement: + 'save-pipeline .sp-dialog-actions>button:nth-of-type(2)', attachPosition: 'top', - buttons: [ - 'cancel' - ] + buttons: ['cancel'], }, { stepId: 'step-14', title: 'Pipeline Started', - text: '

Congratulations!

You\'ve completed the first tutorial. The next step would be to add a visualization in the Dashboard. If you wish to see how it works, start the second tutorial.

', - attachToElement: 'md-dialog>form>md-dialog-actions>button:nth-of-type(1)', + text: "

Congratulations!

You've completed the first tutorial. The next step would be to add a visualization in the Dashboard. If you wish to see how it works, start the second tutorial.

", + attachToElement: + 'md-dialog>form>md-dialog-actions>button:nth-of-type(1)', attachPosition: 'bottom', - buttons: [ - 'cancel' - ] - } + buttons: ['cancel'], + }, ], matchingSteps: [ - {actionId: 'drop-stream', currentStep: 'step-3'}, - {actionId: 'select-sepa', currentStep: 'step-5'}, - {actionId: 'drop-sepa', currentStep: 'step-6'}, - {actionId: 'customize-sepa', currentStep: 'step-7'}, - {actionId: 'save-sepa', currentStep: 'step-8'}, - {actionId: 'select-action', currentStep: 'step-9'}, - {actionId: 'save-action', currentStep: 'step-10'}, - {actionId: 'enter-pipeline-name', currentStep: 'step-11'}, - {actionId: 'save-pipeline-dialog', currentStep: 'step-12'}, - {actionId: 'pipeline-started', currentStep: 'step-13'}, - ] - } + { actionId: 'drop-stream', currentStep: 'step-3' }, + { actionId: 'select-sepa', currentStep: 'step-5' }, + { actionId: 'drop-sepa', currentStep: 'step-6' }, + { actionId: 'customize-sepa', currentStep: 'step-7' }, + { actionId: 'save-sepa', currentStep: 'step-8' }, + { actionId: 'select-action', currentStep: 'step-9' }, + { actionId: 'save-action', currentStep: 'step-10' }, + { actionId: 'enter-pipeline-name', currentStep: 'step-11' }, + { actionId: 'save-pipeline-dialog', currentStep: 'step-12' }, + { actionId: 'pipeline-started', currentStep: 'step-13' }, + ], + }, }; diff --git a/ui/src/app/services/tour/dashboard-tour.constants.ts b/ui/src/app/services/tour/dashboard-tour.constants.ts index 4439c684f7..095d3c0610 100644 --- a/ui/src/app/services/tour/dashboard-tour.constants.ts +++ b/ui/src/app/services/tour/dashboard-tour.constants.ts @@ -19,25 +19,21 @@ export default { dashboardTour: { id: 'dashboard', - steps: [{ - stepId: 'step-1', - title: 'Welcome to the Dashboard Tutorial!', - classes: 'shepherd shepherd-welcome', - text: '

In this tutorial, you\'ll learn how to create a live dashboard that shows data from a running pipeline.

Note:This tutorial requires a running pipeline that makes use of the Dashboard Sink. If you don\'t have such a pipeine started yet, go to the pipeline editor and create one.

Press Next to start the tutorial!

', - buttons: [ - 'cancel', - 'next' - ] - }, + steps: [ + { + stepId: 'step-1', + title: 'Welcome to the Dashboard Tutorial!', + classes: 'shepherd shepherd-welcome', + text: "

In this tutorial, you'll learn how to create a live dashboard that shows data from a running pipeline.

Note:This tutorial requires a running pipeline that makes use of the Dashboard Sink. If you don't have such a pipeine started yet, go to the pipeline editor and create one.

Press Next to start the tutorial!

", + buttons: ['cancel', 'next'], + }, { stepId: 'step-2', title: 'Add visualization', - text: '

Let\'s start!

To create a new visulization, click the Add visualization button.

', + text: "

Let's start!

To create a new visulization, click the Add visualization button.

", attachToElement: '#add-viz-button', attachPosition: 'bottom', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-3', @@ -45,19 +41,15 @@ export default { text: '

This wizard allows to configure visualizations. The first step is to select a currently running pipeline.

Click the pipeline shown on the left.

', attachToElement: 'md-grid-tile:nth-of-type(1)', attachPosition: 'right', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-4', title: 'Select visualization', - text: '

The second step requires the selection of a visulization. You can select from tables, gauges, maps or charts.

In this tutorial, we\'ll create a table visualization, so click the Table visualization on the left.

', + text: "

The second step requires the selection of a visulization. You can select from tables, gauges, maps or charts.

In this tutorial, we'll create a table visualization, so click the Table visualization on the left.

", attachToElement: 'md-grid-tile:nth-of-type(1)', attachPosition: 'right', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-5', @@ -65,9 +57,7 @@ export default { text: '

Some visualizations can be customized according to your needs.

For instance, the table visualization provides a dialog to filter columns. Click the Select all button on the left to select all fields from the incoming event.

', attachToElement: '#select-all-button', attachPosition: 'right', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-6', @@ -75,9 +65,7 @@ export default { text: 'Now you are ready to save your visualization. Click Save to create a new visualization in your dashboard.', attachToElement: '#save-viz-button', attachPosition: 'bottom', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, { stepId: 'step-7', @@ -85,17 +73,15 @@ export default { text: '

Now you should see live data coming in. There are many more visualization types you can try.

Press Exit to finish the tour.', attachToElement: '.widget-container:nth-of-type(1)', attachPosition: 'right', - buttons: [ - 'cancel', - ] + buttons: ['cancel'], }, ], matchingSteps: [ - {actionId: 'add-viz', currentStep: 'step-2'}, - {actionId: 'select-pipeline', currentStep: 'step-3'}, - {actionId: 'select-viz', currentStep: 'step-4'}, - {actionId: 'customize-viz', currentStep: 'step-5'}, - {actionId: 'save-viz', currentStep: 'step-6'}, - ] - } + { actionId: 'add-viz', currentStep: 'step-2' }, + { actionId: 'select-pipeline', currentStep: 'step-3' }, + { actionId: 'select-viz', currentStep: 'step-4' }, + { actionId: 'customize-viz', currentStep: 'step-5' }, + { actionId: 'save-viz', currentStep: 'step-6' }, + ], + }, }; diff --git a/ui/src/app/services/tour/shepherd.service.ts b/ui/src/app/services/tour/shepherd.service.ts index 9d820fdc45..c5c87f09f8 100644 --- a/ui/src/app/services/tour/shepherd.service.ts +++ b/ui/src/app/services/tour/shepherd.service.ts @@ -25,13 +25,14 @@ import StepOptions = Step.StepOptions; @Injectable() export class ShepherdService { - currentTour: any; currentTourSettings: any; timeWaitMillis: number; - constructor(private router: Router, - private tourProviderService: TourProviderService) { + constructor( + private router: Router, + private tourProviderService: TourProviderService, + ) { this.timeWaitMillis = tourProviderService.getTime(); } @@ -41,9 +42,9 @@ export class ShepherdService { confirmCancelMessage: 'Do you really want to cancel the tour?', defaultStepOptions: { classes: 'shadow-md bg-purple-dark', - scrollTo: true + scrollTo: true, // showCancelLink: true - } + }, }); currentTourSettings.steps.forEach(step => { @@ -59,7 +60,7 @@ export class ShepherdService { text: step.text, classes: step.classes, id: step.stepId, - buttons: this.generateButtons(tour, step.buttons) + buttons: this.generateButtons(tour, step.buttons), }; if (step.attachToElement) { @@ -67,7 +68,7 @@ export class ShepherdService { attachTo: { element: step.attachToElement, on: step.attachPosition, - } + }, }); } @@ -100,19 +101,18 @@ export class ShepherdService { this.currentTour.start(); } - makeCancelButton(tour) { return { action: tour.cancel, classes: 'shepherd-button-secondary', - text: 'Exit Tour' + text: 'Exit Tour', }; } makeNextButton(tour) { return { action: tour.next, - text: 'Next' + text: 'Next', }; } @@ -120,28 +120,36 @@ export class ShepherdService { return { action: tour.back, classes: 'shepherd-button-secondary', - text: 'Back' + text: 'Back', }; } makeStartDashboardTutorialButton() { return { action: this.switchAndStartDashboardTour(), - text: 'Dashboard Tutorial' + text: 'Dashboard Tutorial', }; } trigger(actionId) { if (Shepherd.activeTour) { - if (this.shouldTrigger(actionId, this.currentTour.getCurrentStep().id)) { - setTimeout(() => this.currentTour.next(), this.tourProviderService.getTime()); + if ( + this.shouldTrigger( + actionId, + this.currentTour.getCurrentStep().id, + ) + ) { + setTimeout( + () => this.currentTour.next(), + this.tourProviderService.getTime(), + ); } } } shouldTrigger(actionId, currentStep) { return this.currentTourSettings.matchingSteps.some(el => { - return (el.actionId === actionId) && (el.currentStep === currentStep); + return el.actionId === actionId && el.currentStep === currentStep; }); } @@ -182,6 +190,6 @@ export class ShepherdService { } getTimeWaitMillies() { - return this.tourProviderService.getTime(); + return this.tourProviderService.getTime(); } } diff --git a/ui/src/app/services/tour/tour-provider.service.ts b/ui/src/app/services/tour/tour-provider.service.ts index c2094a4c98..6e4520106c 100644 --- a/ui/src/app/services/tour/tour-provider.service.ts +++ b/ui/src/app/services/tour/tour-provider.service.ts @@ -1,4 +1,3 @@ - /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -26,7 +25,6 @@ import { Injectable } from '@angular/core'; @Injectable() export class TourProviderService { - guidedTours: any; // This is needed to configure the time in cypress test cases @@ -48,7 +46,7 @@ export class TourProviderService { getTourById(tourId) { return this.guidedTours.find(tour => { - return tour.id === tourId; + return tour.id === tourId; }); }