Skip to content

Commit

Permalink
Fix event service subscription for fetch completion
Browse files Browse the repository at this point in the history
  • Loading branch information
newmanw committed Aug 30, 2024
1 parent fc29abc commit 2135c52
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 125 deletions.
189 changes: 94 additions & 95 deletions web-app/src/app/event/event.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Injectable } from "@angular/core";
import { Observable, ObservableInput, catchError, finalize, forkJoin, of, tap, zip } from "rxjs";
import * as moment from 'moment'
import { Observable, Subject, catchError, combineLatest, finalize, forkJoin, map, of, take, tap } from "rxjs";
import { FilterService } from "../filter/filter.service";
import { PollingService } from "./polling.service";
import { ObservationService } from "../observation/observation.service";
Expand All @@ -10,6 +9,7 @@ import { FeedService } from "core-lib-src/feed";
import { LocationService } from "../user/location/location.service";
import { LocalStorageService } from "../http/local-storage.service";
import * as _ from 'lodash'
import * as moment from 'moment'

@Injectable({
providedIn: 'root'
Expand Down Expand Up @@ -70,13 +70,13 @@ export class EventService {
}

if (filter.event || filter.timeInterval) { // requery server
this.fetch();
this.fetch()
} else if (filter.teams) { // filter in memory
this.onTeamsChanged();
this.onTeamsChanged()
}

if (filter.actionFilter) {
this.onActionFilterChanged();
this.onActionFilterChanged()
}
}

Expand Down Expand Up @@ -470,10 +470,20 @@ export class EventService {
parameters.interval = time;
}

return forkJoin({
locations: this.fetchLocations(event, parameters),
observations: this.fetchObservations(event, parameters)
})
return combineLatest([
this.locationService
.getUserLocationsForEvent(event, parameters)
.pipe(map((locations: any) => {
this.parseLocations(event, locations)
})),
this.observationService
.getObservationsForEvent(event, parameters)
.pipe(map((observations: any) => {
this.parseObservations(event, observations)
}))
]).pipe(
take(1)
)
}

fetchLayers(event) {
Expand Down Expand Up @@ -514,113 +524,102 @@ export class EventService {
});
}

fetchObservations(event, parameters): Observable<any> {
const observable = this.observationService.getObservationsForEvent(event, parameters)
observable.subscribe((observations: any) => {
var added = [];
var updated = [];
var removed = [];

var observationsById = {};
var filteredObservationsById = this.eventsById[event.id].filteredObservationsById;
observations.forEach((observation: any) => {
// Check if this observation passes the current filter
if (this.filterService.observationInFilter(observation)) {
// Check if we already have this observation, if so update, otherwise add
var localObservation = filteredObservationsById[observation.id];
if (localObservation) {
if (localObservation.lastModified !== observation.lastModified) {
updated.push(observation);
} else if (observation.attachments) {
var some = _.some(observation.attachments, function (attachment) {
var localAttachment = _.find(localObservation.attachments, function (a) { return a.id === attachment.id; });
return !localAttachment || localAttachment.lastModified !== attachment.lastModified;
});

if (some) updated.push(observation);
}
} else {
added.push(observation);
}
parseObservations(event: any, observations: any): any {
var added = [];
var updated = [];
var removed = [];

// remove from list of observations if it came back from server
// remaining elements in this list will be removed
delete filteredObservationsById[observation.id];

observationsById[observation.id] = observation;
var observationsById = {};
var filteredObservationsById = this.eventsById[event.id].filteredObservationsById;
observations.forEach((observation: any) => {
// Check if this observation passes the current filter
if (this.filterService.observationInFilter(observation)) {
// Check if we already have this observation, if so update, otherwise add
var localObservation = filteredObservationsById[observation.id];
if (localObservation) {
if (localObservation.lastModified !== observation.lastModified) {
updated.push(observation);
} else if (observation.attachments) {
var some = _.some(observation.attachments, function (attachment) {
var localAttachment = _.find(localObservation.attachments, function (a) { return a.id === attachment.id; });
return !localAttachment || localAttachment.lastModified !== attachment.lastModified;
});

if (some) updated.push(observation);
}
} else {
added.push(observation);
}
});

// remaining elements were not pulled from the server, hence we should remove them
removed = Object.values(filteredObservationsById);

this.eventsById[event.id].observationsById = _.keyBy(observations, 'id');
this.eventsById[event.id].filteredObservationsById = observationsById;
// remove from list of observations if it came back from server
// remaining elements in this list will be removed
delete filteredObservationsById[observation.id];

this.observationsChanged({ added: added, updated: updated, removed: removed });
observationsById[observation.id] = observation;
}
});

return observable
}
// remaining elements were not pulled from the server, hence we should remove them
removed = Object.values(filteredObservationsById);

fetchLocations(event, parameters): Observable<any> {
const observable = this.locationService.getUserLocationsForEvent(event, parameters)
this.eventsById[event.id].observationsById = _.keyBy(observations, 'id');
this.eventsById[event.id].filteredObservationsById = observationsById;

observable.subscribe((userLocations: any) => {
const added = [];
const updated = [];
this.observationsChanged({ added: added, updated: updated, removed: removed });
}

const usersById = {};
const filteredUsersById = this.eventsById[event.id].filteredUsersById;
userLocations.forEach((userLocation: any) => {
// Track each location feature by users id,
// so update the locations id to match the usersId
const location = userLocation.locations[0];
location.id = userLocation.id;
parseLocations(event, userLocations: any) {
const added = [];
const updated = [];

userLocation.location = location;
delete userLocation.locations;
const usersById = {};
const filteredUsersById = this.eventsById[event.id].filteredUsersById;
userLocations.forEach((userLocation: any) => {
// Track each location feature by users id,
// so update the locations id to match the usersId
const location = userLocation.locations[0];
location.id = userLocation.id;

if (userLocation.user.iconUrl) {
var params = new HttpParams();
params = params.append('access_token', this.localStorageService.getToken())
params = params.append('_dc', userLocation.user.lastUpdated)
userLocation.location = location;
delete userLocation.locations;

location.style = {
iconUrl: `${userLocation.user.iconUrl}?${params.toString()}`
}
if (userLocation.user.iconUrl) {
var params = new HttpParams();
params = params.append('access_token', this.localStorageService.getToken())
params = params.append('_dc', userLocation.user.lastUpdated)

location.style = {
iconUrl: `${userLocation.user.iconUrl}?${params.toString()}`
}
}

if (this.filterService.isUserInTeamFilter(userLocation.id)) {
// Check if we already have this user, if so update, otherwise add
const localUser = filteredUsersById[userLocation.id];
if (localUser) {
if (this.filterService.isUserInTeamFilter(userLocation.id)) {
// Check if we already have this user, if so update, otherwise add
const localUser = filteredUsersById[userLocation.id];
if (localUser) {

if (userLocation.location.properties.timestamp !== localUser.location.properties.timestamp) {
updated.push(userLocation);
}
} else {
added.push(userLocation);
if (userLocation.location.properties.timestamp !== localUser.location.properties.timestamp) {
updated.push(userLocation);
}

// remove from list of observations if it came back from server
// remaining elements in this list will be removed
delete filteredUsersById[userLocation.id];

usersById[userLocation.id] = userLocation;
} else {
added.push(userLocation);
}
});

// remaining elements were not pulled from the server, hence we should remove them
const removed = _.values(filteredUsersById);

this.eventsById[event.id].usersById = _.keyBy(userLocations, 'id');
this.eventsById[event.id].filteredUsersById = usersById;
// remove from list of observations if it came back from server
// remaining elements in this list will be removed
delete filteredUsersById[userLocation.id];

this.usersChanged({ added: added, updated: updated, removed: removed });
usersById[userLocation.id] = userLocation;
}
});

return observable
// remaining elements were not pulled from the server, hence we should remove them
const removed = _.values(filteredUsersById);

this.eventsById[event.id].usersById = _.keyBy(userLocations, 'id');
this.eventsById[event.id].filteredUsersById = usersById;

this.usersChanged({ added: added, updated: updated, removed: removed });
}

poll(interval) {
Expand Down
2 changes: 2 additions & 0 deletions web-app/src/app/home/home.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ import { HomeComponent } from '..//home/home.component';
import { RouterModule, Routes } from '@angular/router';
import { UserResolver } from '../ingress/user.resolver';
import { UserAvatarModule } from '../user/user-avatar/user-avatar.module';
import { IngressModule } from '../ingress/ingress.module';

const routes: Routes = [{
path: '',
Expand Down Expand Up @@ -228,6 +229,7 @@ const routes: Routes = [{
ContactDialogComponent
],
imports: [
IngressModule,
UserAvatarModule,
FeedItemSummaryModule,
StaticIconModule,
Expand Down
11 changes: 4 additions & 7 deletions web-app/src/app/http/token.interceptor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpContextToken, HttpStatusCode, HttpErrorResponse, HttpClient } from '@angular/common/http';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpContextToken, HttpStatusCode, HttpErrorResponse } from '@angular/common/http';
import { catchError, Observable, Subject, switchMap, throwError } from 'rxjs';
import { LocalStorageService } from './local-storage.service';
import { AuthenticationDialogComponent } from '../ingress/authentication/authentication-dialog.component';
Expand Down Expand Up @@ -34,7 +34,6 @@ export class TokenInterceptorService implements HttpInterceptor {
this.isRefreshingToken = true
this.dialog.open(AuthenticationDialogComponent, {
width: '600px',
height: '400px',
disableClose: true,
autoFocus: false
}).afterClosed().subscribe(() => {
Expand All @@ -44,9 +43,7 @@ export class TokenInterceptorService implements HttpInterceptor {
}

return this.tokenSubject.pipe(
switchMap(() => {
return next.handle(this.tokenRequest(req))
})
switchMap(() => next.handle(this.tokenRequest(req)))
)
}
}
Expand All @@ -60,7 +57,7 @@ export class TokenInterceptorService implements HttpInterceptor {
}

tokenRequest(req: HttpRequest<any>): HttpRequest<any> {
const token = this.localStorageService.getToken();
return req.clone({ headers: req.headers.set('Authorization', `Bearer ${token}`) });
const token = this.localStorageService.getToken()
return req.clone({ headers: req.headers.set('Authorization', `Bearer ${token}`) })
}
}
30 changes: 7 additions & 23 deletions web-app/src/app/ingress/ingress.component.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'
import { Api, AuthenticationStrategy } from '../api/api.entity'
import { ActivatedRoute } from '@angular/router'
import { UserService } from '../user/user.service'
import { AuthorizationEvent } from './authorization/authorization.component'
import { LocalStorageService } from '../http/local-storage.service'
import { DiscalimeCloseEvent, DiscalimerCloseReason } from './disclaimer/disclaimer.component'
import { animate, style, transition, trigger } from '@angular/animations'
import { SignupEvent } from './authentication/local/signup.component'
import * as _ from 'underscore'
import { User } from 'core-lib-src/user'
import { InitializedEvent } from './intialize/initialize.component'
import * as _ from 'underscore'

enum IngressState {
Initialize,
Expand Down Expand Up @@ -85,7 +84,7 @@ class Initialize extends Ingress {
])
]
})
export class IngressComponent implements OnInit {
export class IngressComponent implements OnChanges {
@Input() api: Api
@Input() landing: boolean
@Output() complete = new EventEmitter<void>()
Expand All @@ -98,29 +97,14 @@ export class IngressComponent implements OnInit {
localAuthenticationStrategy: any

constructor(
private route: ActivatedRoute,
private userService: UserService,
private localStorageService: LocalStorageService
) { }

ngOnInit(): void {
this.route.data.subscribe(({ api }) => {
this.api = api

if (this.api.initial) {
this.ingress = new Initialize()
}

this.localAuthenticationStrategy = this.api?.authenticationStrategies['local'];
if (this.localAuthenticationStrategy) {
this.localAuthenticationStrategy.name = 'local';
}

this.thirdPartyStrategies = _.map(_.omit(this.api?.authenticationStrategies, this.localStrategyFilter), function (strategy: AuthenticationStrategy, name: string) {
strategy.name = name;
return strategy;
});
})
ngOnChanges(changes: SimpleChanges): void {
if (changes.api.currentValue === true) {
this.ingress = new Initialize()
}
}

localStrategyFilter(_strategy: AuthenticationStrategy, name: string) {
Expand Down

0 comments on commit 2135c52

Please sign in to comment.