diff --git a/workbench/backend/src/app/booking/booking.controller.ts b/workbench/backend/src/app/booking/booking.controller.ts index 45aa739..f8cce01 100644 --- a/workbench/backend/src/app/booking/booking.controller.ts +++ b/workbench/backend/src/app/booking/booking.controller.ts @@ -96,7 +96,7 @@ export class BookingController { .json({ activityId: e.message }); } - let axiosError: AxiosError = e?.error; + const axiosError: AxiosError = e?.error; return res .status(axiosError?.response?.status || 500) .json(axiosError?.response?.data); diff --git a/workbench/backend/src/app/re-optimize/re-optimize.controller.ts b/workbench/backend/src/app/re-optimize/re-optimize.controller.ts index 2672f60..eb940b5 100644 --- a/workbench/backend/src/app/re-optimize/re-optimize.controller.ts +++ b/workbench/backend/src/app/re-optimize/re-optimize.controller.ts @@ -18,7 +18,7 @@ export class ReOptimizeController { const { data } = await this.dao.reOptimize('sync', ctx, body).toPromise(); return res.json(data); } catch (e) { - let axiosError: AxiosError = e?.error; + const axiosError: AxiosError = e?.error; return res .status(axiosError?.response?.status || 500) .json(axiosError?.response?.data); @@ -30,7 +30,7 @@ export class ReOptimizeController { const { data } = await this.dao.reOptimize('async', ctx, body).toPromise(); return res.json(data); } catch (e) { - let axiosError: AxiosError = e?.error; + const axiosError: AxiosError = e?.error; return res .status(axiosError?.response?.status || 500) .json(axiosError?.response?.data); diff --git a/workbench/frontend/src/app/common/services/auth.service.ts b/workbench/frontend/src/app/common/services/auth.service.ts index 725d64d..f09d30c 100644 --- a/workbench/frontend/src/app/common/services/auth.service.ts +++ b/workbench/frontend/src/app/common/services/auth.service.ts @@ -27,7 +27,7 @@ const DEFAULT_CTX = { selectedLocale: 'en-us', user: '', userId: 0 -} +}; @Injectable({ providedIn: 'root' @@ -42,14 +42,14 @@ export class AuthService { public globalContext$ = new BehaviorSubject(DEFAULT_CTX); public globalContextWithAuth$ = this.globalContext$.pipe(filter((it) => it !== DEFAULT_CTX)); - public isLoggedIn$ = this.globalContext$.pipe(map(it => it !== DEFAULT_CTX)) + public isLoggedIn$ = this.globalContext$.pipe(map(it => it !== DEFAULT_CTX)); - public logout() { + public logout(): void { this.clearContext(); this.onContextReady(DEFAULT_CTX); } - public openLoginDialog() { + public openLoginDialog(): void { const dialogRef = this.dialog.open(LoginDialogComponent, LoginDialogComponent.CONFIG ); @@ -66,14 +66,14 @@ export class AuthService { }); } - public tryRestoreSession() { + public tryRestoreSession(): void { const ctx = this.restoreContext(); if (ctx) { this.infoMessage( '[✅ INFO ✅] session loaded from sessionStorage', 'logout', () => this.logout() ); - setTimeout(() => this.onContextReady(ctx), 1) + setTimeout(() => this.onContextReady(ctx), 1); } else { this.infoMessage( '[❌ WARN ❌ ] no session found', @@ -83,18 +83,18 @@ export class AuthService { } } - private onContextReady(ctx: GlobalContext) { + private onContextReady(ctx: GlobalContext): void { this.globalContext$.next(ctx); } - private clearContext() { + private clearContext(): void { this.infoMessage('[✅ INFO ✅] session cleared from sessionStorage', 'login', () => this.openLoginDialog()); sessionStorage.removeItem(this.AUTH_KEY); } - private storeContext(ctx: GlobalContext) { + private storeContext(ctx: GlobalContext): void { this.infoMessage('[✅ INFO ✅] session stored in sessionStorage'); - sessionStorage.setItem(this.AUTH_KEY, JSON.stringify(ctx)) + sessionStorage.setItem(this.AUTH_KEY, JSON.stringify(ctx)); } private restoreContext(): GlobalContext | null { @@ -104,7 +104,7 @@ export class AuthService { : null; } - private infoMessage(msg: string, btnText = 'ok', action: () => void | null = null) { + private infoMessage(msg: string, btnText = 'ok', action: () => void | null = null): void { const snackBarRef = this.snackBar.open(msg, btnText, { duration: 5000 }); if (action) { snackBarRef.onAction().subscribe(() => { diff --git a/workbench/frontend/src/app/common/services/config.service.ts b/workbench/frontend/src/app/common/services/config.service.ts index 8aedbfa..8f6a342 100644 --- a/workbench/frontend/src/app/common/services/config.service.ts +++ b/workbench/frontend/src/app/common/services/config.service.ts @@ -5,14 +5,14 @@ import { Injectable } from '@angular/core'; export class ConfigService { constructor() { } - private getHost() { + private getHost(): 'http://localhost:8000' | '' { return location.origin === 'http://localhost:4200' ? 'http://localhost:8000' : ''; } - public getApiUri() { - return `${this.getHost()}/api` + public getApiUri(): string { + return `${this.getHost()}/api`; } -} \ No newline at end of file +} diff --git a/workbench/frontend/src/app/common/services/plugin.service.ts b/workbench/frontend/src/app/common/services/plugin.service.ts index e7227da..79398f4 100644 --- a/workbench/frontend/src/app/common/services/plugin.service.ts +++ b/workbench/frontend/src/app/common/services/plugin.service.ts @@ -1,6 +1,6 @@ import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { of, throwError } from 'rxjs'; +import { Observable, ObservedValueOf, of, throwError } from 'rxjs'; import { catchError, map, mergeMap } from 'rxjs/operators'; import { ConfigService } from './config.service'; import { CLIENT_IDENTIFIER } from '../contants'; @@ -39,10 +39,10 @@ export type PolicyObjectiveDto = { }) export class PluginService { - private getHeaders(ctx: GlobalContext) { + private getHeaders(ctx: GlobalContext): HttpHeaders { return new HttpHeaders({ 'Content-Type': 'application/json', - 'Authorization': `${ctx.authToken}`, + Authorization: `${ctx.authToken}`, 'x-cloud-host': `${ctx.cloudHost}`, 'x-account-name': `${ctx.account}`, 'x-account-id': `${ctx.accountId}`, @@ -70,14 +70,13 @@ export class PluginService { } - // tslint:disable-next-line:typedef - fetchAll() { + fetchAll(): Observable { return this.auth.globalContextWithAuth$.pipe( mergeMap(ctx => this.http.get(`${this.config.getApiUri()}/plugin`, { headers: this.getHeaders(ctx) })), ); } - fetchById(id: string) { + fetchById(id: string): Observable>> { return this.auth.globalContextWithAuth$.pipe( mergeMap(ctx => this.http.get(`${this.config.getApiUri()}/plugin/by-id/${id}`, { headers: this.getHeaders(ctx) })) ); @@ -91,6 +90,7 @@ export class PluginService { ); } + // tslint:disable-next-line:typedef create(plugin: Partial) { return this.auth.globalContextWithAuth$.pipe( mergeMap(ctx => this.http.post(`${this.config.getApiUri()}/plugin`, plugin, { headers: this.getHeaders(ctx) })), @@ -106,13 +106,13 @@ export class PluginService { ); } - update(plugin: Partial) { + update(plugin: Partial): Observable>> { return this.auth.globalContextWithAuth$.pipe( mergeMap(ctx => this.http.put(`${this.config.getApiUri()}/plugin/${plugin.id}`, plugin, { headers: this.getHeaders(ctx) })) ); } - delete(pluginId: string) { + delete(pluginId: string): Observable>> { return this.auth.globalContextWithAuth$.pipe( mergeMap(ctx => this.http.delete(`${this.config.getApiUri()}/plugin/${pluginId}`, { headers: this.getHeaders(ctx) })) ); diff --git a/workbench/frontend/src/app/slot-booking/services/booking.service.ts b/workbench/frontend/src/app/slot-booking/services/booking.service.ts index 7dba6fb..fcaaef3 100644 --- a/workbench/frontend/src/app/slot-booking/services/booking.service.ts +++ b/workbench/frontend/src/app/slot-booking/services/booking.service.ts @@ -30,10 +30,10 @@ export class BookingService { private query: QueryService ) { } - private getHeaders(ctx: GlobalContext) { + private getHeaders(ctx: GlobalContext): HttpHeaders { return new HttpHeaders({ 'Content-Type': 'application/json', - 'Authorization': `${ctx.authToken}`, + Authorization: `${ctx.authToken}`, 'x-cloud-host': `${ctx.cloudHost}`, 'x-account-name': `${ctx.account}`, 'x-account-id': `${ctx.accountId}`, @@ -44,17 +44,19 @@ export class BookingService { 'x-client-id': CLIENT_IDENTIFIER, 'x-client-version': '0.0.0', 'x-request-id': `${Date.now()}`, - }) + }); } + // tslint:disable-next-line:typedef private book(bookable: SearchResponseItem, job: Job, activityId: string = 'create-activity') { return this.auth.globalContextWithAuth$.pipe( - mergeMap(ctx => this.http.post<{}>(`${this.config.getApiUri()}/booking/actions/book/${activityId}`, { job, bookable }, { headers: this.getHeaders(ctx) })) + mergeMap(ctx => this.http.post<{}>(`${this.config.getApiUri()}/booking/actions/book/${activityId}`, + { job, bookable }, { headers: this.getHeaders(ctx) })) ); } - public tryBookAll(list: SearchResponseItem[], job: Job) { + public tryBookAll(list: SearchResponseItem[], job: Job): Observable { return new Observable((op) => { @@ -68,7 +70,7 @@ export class BookingService { current: (idx + 1), result: null, activityId, - } + }; const person = this.query.getResourceFromCache(bookable.resource); @@ -83,25 +85,26 @@ export class BookingService { success: true, message: `🎉🎉 we booked a slot with ${person.firstName} ${person.lastName} from ${moment(bookable.start).format('HH:mm')} to ${moment(bookable.end).format('HH:mm')} `, result - }) + }); }) .catch(errorRep => { + // tslint:disable-next-line:no-shadowed-variable let activityId: string; // if the backend returns a 422 - creation of temp data was okay but booking failed. - // use [activityId] for next try to not recreate data + // use [activityId] for next try to not recreate data if (errorRep instanceof HttpErrorResponse && errorRep.status === 422 && errorRep.error) { - activityId = errorRep.error.activityId || '' + activityId = errorRep.error.activityId || ''; } throw { ...progress, activityId: activityId ? activityId : '' }; }); - } + }; - // setup chain + // setup chain const work = list.reduce( (promise, it, idx) => promise.catch((progress: Progress) => tryBook(idx, it, progress.blockedList, progress.activityId)), Promise.reject({ message: `init`, blockedList: [], success: false, total: list.length, current: -1 }) - ) + ); // run chain work @@ -110,15 +113,15 @@ export class BookingService { op.complete(); }) .catch((error: Progress) => { - op.next({ ...error, message: '❌ slot booking failed, all technicains are booked already ...' }); + op.next({ ...error, message: '❌ slot booking failed, all technicians are booked already ...' }); op.error(error); }); return () => { - // clean ups - } - }) + // clean-ups + }; + }); - }; + } -} \ No newline at end of file +} diff --git a/workbench/frontend/src/app/slot-booking/services/job.service.ts b/workbench/frontend/src/app/slot-booking/services/job.service.ts index 79e8638..1002b3e 100644 --- a/workbench/frontend/src/app/slot-booking/services/job.service.ts +++ b/workbench/frontend/src/app/slot-booking/services/job.service.ts @@ -4,6 +4,7 @@ import { mergeMap } from 'rxjs/operators'; import { ConfigService } from '../../common/services/config.service'; import { CLIENT_IDENTIFIER } from '../../common/contants'; import { GlobalContext, AuthService } from '../../common/services/auth.service'; +import { Observable } from 'rxjs'; export type Job = { durationMinutes: number, @@ -13,7 +14,7 @@ export type Job = { } | null, mandatorySkills: string[], optionalSkills: string[] -} +}; export type TagDTO = { branches: null @@ -33,7 +34,7 @@ export type TagDTO = { syncStatus: 'IN_CLOUD' udfMetaGroups: null udfValues: null -} +}; export type AddressDTO = { block: null @@ -69,16 +70,16 @@ export type AddressDTO = { udfMetaGroups: null udfValues: null zipCode: string -} +}; @Injectable({ providedIn: 'root' }) export class JobService { - private getHeaders(ctx: GlobalContext) { + private getHeaders(ctx: GlobalContext): HttpHeaders { return new HttpHeaders({ 'Content-Type': 'application/json', - 'Authorization': `${ctx.authToken}`, + Authorization: `${ctx.authToken}`, 'x-cloud-host': `${ctx.cloudHost}`, 'x-account-name': `${ctx.account}`, 'x-account-id': `${ctx.accountId}`, @@ -98,21 +99,24 @@ export class JobService { private http: HttpClient, ) { } - fetchAllTags() { + fetchAllTags(): Observable> { return this.auth.globalContextWithAuth$.pipe( - mergeMap(ctx => this.http.get>(`${this.config.getApiUri()}/query/tags`, { headers: this.getHeaders(ctx) })) + mergeMap(ctx => this.http.get>(`${this.config.getApiUri()}/query/tags`, + { headers: this.getHeaders(ctx) })) ); } - fetchAllAddress() { + fetchAllAddress(): Observable { return this.auth.globalContextWithAuth$.pipe( - mergeMap(ctx => this.http.get(`${this.config.getApiUri()}/query/address`, { headers: this.getHeaders(ctx) })), + mergeMap(ctx => this.http.get(`${this.config.getApiUri()}/query/address`, + { headers: this.getHeaders(ctx) })), ); } - personByTag(tagId: string) { + personByTag(tagId: string): Observable<{ person: string; tag: string }[]> { return this.auth.globalContextWithAuth$.pipe( - mergeMap(ctx => this.http.get<{ person: string, tag: string }[]>(`${this.config.getApiUri()}/query/person/by-tag/${tagId}`, { headers: this.getHeaders(ctx) })), + mergeMap(ctx => this.http.get<{ person: string, tag: string }[]>(`${this.config.getApiUri()}/query/person/by-tag/${tagId}`, + { headers: this.getHeaders(ctx) })), ); } } diff --git a/workbench/frontend/src/app/slot-booking/services/slot-booking.service.ts b/workbench/frontend/src/app/slot-booking/services/slot-booking.service.ts index e8a3b6d..28e039f 100644 --- a/workbench/frontend/src/app/slot-booking/services/slot-booking.service.ts +++ b/workbench/frontend/src/app/slot-booking/services/slot-booking.service.ts @@ -16,7 +16,7 @@ export type GroupedSearchResponse = { hash: string, maxScore: number, sumScore: number -} +}; export type SearchResponseWrapper = SearchResponse & { isError: boolean, @@ -25,9 +25,9 @@ export type SearchResponseWrapper = SearchResponse & { grouped: GroupedSearchResponse[] }; -type SearchResponseItemExteded = SearchResponseItem & { +type SearchResponseItemExtended = SearchResponseItem & { resourceVm: { id: string, firstName: string, lastName: string } | undefined | null -} +}; export type SearchResponseItem = { slot: { start: string; end: string; }, @@ -39,10 +39,10 @@ export type SearchResponseItem = { distanceInMeters: number; } score: number -} +}; type SearchResponse = { results: SearchResponseItem[] -} +}; type ISearchRequestSlot = Readonly<{ start: string; end: string; @@ -66,11 +66,11 @@ export type SearchRequest = Readonly<{ maxResultsPerSlot: number; }>; optimizationPlugin: null | string; -}> +}>; type ILocation = { latitude: number; longitude: number; -} +}; @Injectable({ @@ -78,10 +78,10 @@ type ILocation = { }) export class SlotSearchService { - private getHeaders(ctx: GlobalContext) { + private getHeaders(ctx: GlobalContext): HttpHeaders { return new HttpHeaders({ 'Content-Type': 'application/json', - 'Authorization': `${ctx.authToken}`, + Authorization: `${ctx.authToken}`, 'x-cloud-host': `${ctx.cloudHost}`, 'x-account-name': `${ctx.account}`, 'x-account-id': `${ctx.accountId}`, @@ -92,7 +92,7 @@ export class SlotSearchService { 'x-client-id': CLIENT_IDENTIFIER, 'x-client-version': '0.0.0', 'x-request-id': `${Date.now()}`, - }) + }); } constructor( @@ -108,7 +108,8 @@ export class SlotSearchService { return this.auth.globalContextWithAuth$.pipe( - mergeMap(ctx => this.http.post(`${this.config.getApiUri()}/job-slots/actions/search`, body, { headers: this.getHeaders(ctx) })), + mergeMap(ctx => this.http.post(`${this.config.getApiUri()}/job-slots/actions/search`, + body, { headers: this.getHeaders(ctx) })), map(resp => { return { ...resp, @@ -119,7 +120,7 @@ export class SlotSearchService { const hash = `${it.slot.start}-${it.slot.end}`; - const extendedItem: SearchResponseItemExteded = { + const extendedItem: SearchResponseItemExtended = { ...it, resourceVm: this.queryService.getResourceFromCache(it.resource) }; @@ -128,18 +129,20 @@ export class SlotSearchService { const group = theMap.get(hash); group.items = [...group.items, extendedItem].sort((a, b) => b.score - a.score); - group.maxScore = group.maxScore > it.score ? group.maxScore : it.score + group.maxScore = group.maxScore > it.score ? group.maxScore : it.score; group.sumScore += it.score; } else { - theMap.set(hash, { items: [extendedItem], hash, maxScore: it.score, sumScore: it.score, slot: it.slot }) + theMap.set(hash, { items: [extendedItem], hash, maxScore: it.score, sumScore: it.score, slot: it.slot }); } return theMap; - }, new Map())) + }, + new Map())) .map(([, v]) => v) .sort((a, b) => b.maxScore - a.maxScore) - } + }; }) ); }