File: /var/dev/nowruzgan/travelogue/src/app/services/endpoint.service.ts
import { inject, Injectable } from '@angular/core';
import { Dataset, Source, Note, Poi, PoiRel, Tag } from '../data.types';
import { environment } from '../../environments/environment';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { firstValueFrom } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class EndpointService {
readonly http = inject(HttpClient);
dataset: Dataset = {
sources: [],
notes: [],
pois: [],
tags: [],
timestamp: 0
};
datasetCallbacks: Function[] = [];
loadingData: boolean = false;
static calendar: string = 'gregorian';
raw: any = {};
async getSummary(): Promise<Dataset> {
if(this.dataset.timestamp) return this.dataset;
let result = await firstValueFrom(this.http.get(`${environment.apiBase}/travelogue/public/summary`)).catch(error => error);
if(result instanceof HttpErrorResponse)
return this.dataset;
this.raw = result;
await this.normlize();
return this.dataset;
/*return new Promise((resolve, reject) => {
if(this.dataset.timestamp) return resolve(this.dataset);
if(this.loadingData) {
this.datasetCallbacks.push(() => resolve(this.dataset));
}else {
this.loadingData = true;
this.http
.get(`${environment.apiBase}/travelogue/public/summary`)
.subscribe({
next: async data => {
await this.normlize(data);
resolve(this.dataset);
this.datasetCallbacks.forEach(callback => callback());
},
error: error => {
console.log('http error', {status: error.status, text: error.statusText});
resolve(this.dataset);
this.datasetCallbacks.forEach(callback => callback());
}
});
}
// this.normlize(result)
// return this.dataset;
});*/
}
async normlize() {
let data = this.raw;
data.sources = this.convertObject(data.sources);
data.notes = this.convertObject(data.notes);
data.pois = this.convertObject(data.pois);
data.notePois = this.convertObject(data.notePois);
data.noteTags = this.convertObject(data.noteTags);
data.tags = this.convertObject(data.tags);
this.dataset.sources = data.sources.map((source: any) => new Source(source));
this.dataset.notes = data.notes.map((note: any) => {
let result: Note = new Note(note);
result.source = this.dataset.sources.find(source => source.id == note.source) || new Source();
result.source.notes.push(result);
return result;
});
this.dataset.pois = data.pois.map((poi: any) => new Poi(poi));
for (let rel of data.notePois) {
let poi = this.dataset.pois.find(poi => poi.id == rel.poi);
if(!poi) continue;
let note = this.dataset.notes.find(note => note.id == rel.note);
if(!note) continue;
rel.poi = poi;
poi.notes.push(note);
if(!poi.sources.includes(note.source))
poi.sources.push(note.source);
poi.meta.waypointSources = poi.meta.waypointSources || [];
if(poi.granularity == 40 && !rel.flagMilestone && !rel.flagNoway) {
poi.meta.waypointSources[note.source.id] = true;
if(!note.source.borderBox) {
note.source.borderBox = {minLat: poi.lat, maxLat: poi.lat, minLon: poi.lon, maxLon: poi.lon};
}else {
note.source.borderBox.minLat = Math.min(note.source.borderBox.minLat, poi.lat);
note.source.borderBox.maxLat = Math.max(note.source.borderBox.maxLat, poi.lat);
note.source.borderBox.minLon = Math.min(note.source.borderBox.minLon, poi.lon);
note.source.borderBox.maxLon = Math.max(note.source.borderBox.maxLon, poi.lon);
}
}
delete rel.note;
note.poiRels.push(rel);
}
this.dataset.notes.forEach(note => {
note.poiRels = note.poiRels.sort((a: PoiRel, b: PoiRel) => a.order - b.order);
});
this.dataset.tags = data.tags
.map((tag: any) => new Tag(tag));
for(let source of this.dataset.sources)
source.tags = this.dataset.tags.filter(tag => tag.meta.sources.includes(source.id));
for(let rel of data.noteTags) {
let note = this.dataset.notes.find(note => note.id == rel.note);
if(!note) continue;
let tag = this.dataset.tags.find(tag => tag.id == rel.tag);
if(!tag) continue;
tag.notes.push(note);
if(tag.taxonomy == 'travelogue-note-tag')
note.tags.push(tag);
if(tag.taxonomy == 'travelogue-note-index-place')
note.indexPlace.push(tag);
if(tag.taxonomy == 'travelogue-note-index-person')
note.indexPerson.push(tag);
if(tag.taxonomy == 'travelogue-note-index-other')
note.indexOther.push(tag);
}
this.dataset.sources.forEach(source => source.notes = source.notes.sort((a, b) => a.order - b.order));
for(let source of this.dataset.sources) {
if(!source.borderBox) continue;
let offsetLon = (source.borderBox.maxLon - source.borderBox.minLon)*.1;
source.borderBox.minLon -= offsetLon ;
source.borderBox.maxLon += offsetLon ;
let offsetLat = (source.borderBox.maxLat - source.borderBox.minLat)*.1;
source.borderBox.minLat -= offsetLat ;
source.borderBox.maxLat += offsetLat ;
}
this.dataset.timestamp = Date.now();
}
convertObject(data: any[]) {
let cols = data.shift();
return data.map(record => {
let obj: any = {};
for(let i=0; i<cols.length; i++)
obj[cols[i]] = record[i];
return obj;
})
}
}