191 lines
4.8 KiB
TypeScript
191 lines
4.8 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
|
|
import { map } from 'rxjs/operators';
|
|
import { Story } from './story';
|
|
import { SupaService } from './supa.service';
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class StoryService {
|
|
// storyMap: Map<number, Story> = new Map();
|
|
storyMap = {};
|
|
stories: BehaviorSubject<any> = new BehaviorSubject([]);
|
|
subscribedStandUpIds: number[] = [];
|
|
isListening: boolean = false;
|
|
|
|
constructor(
|
|
private supa: SupaService,
|
|
) { }
|
|
|
|
/**
|
|
* Get Storys from local store.
|
|
* Requests data if store is emtpy.
|
|
* @param standup_id
|
|
* @returns Observable<Story[]>
|
|
*/
|
|
getStories(standup_id: number): Observable<Story[]> {
|
|
if (!this.subscribedStandUpIds.includes(standup_id)) {
|
|
this.subscribeToStories(standup_id);
|
|
console.log('getStories - REFRESH', standup_id)
|
|
this.supa.client.from<Story>('story').select()
|
|
.filter(<never>'standup_id', 'eq', standup_id)
|
|
.then(
|
|
data => {
|
|
this.updateStore(data.body);
|
|
},
|
|
error => {
|
|
console.error(error);
|
|
}
|
|
);
|
|
} else {
|
|
console.log('getStories - LOCAL', standup_id)
|
|
}
|
|
return this.stories.asObservable().pipe(
|
|
map(stories => stories.filter(e => e.standup_id === standup_id))
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Listen to realtime events from story db.
|
|
*/
|
|
subscribeToStories(standup_id: number) {
|
|
// TODO check for this.subscribedStandUpIds.includes(standup_id)
|
|
if (!this.isListening) {
|
|
this.subscribedStandUpIds.push(standup_id);
|
|
this.supa.client.from<Story>('story').on('*', payload => {
|
|
console.log('subscribeToStories - REALTIME EVENT', payload)
|
|
if ((payload.eventType === 'INSERT') || (payload.eventType === 'UPDATE')) {
|
|
this.storyMap[payload.new.id] = payload.new;
|
|
} else {
|
|
delete this.storyMap[payload.old.id];
|
|
}
|
|
this.next();
|
|
}).subscribe();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Requests up to date data from API.
|
|
* Returns the local copy.
|
|
* @returns Observable<Story>
|
|
*/
|
|
// refreshStorys(): Observable<Story[]> {
|
|
// this.subscribeToStories();
|
|
// this.supa.client.from<Story>('story').select()
|
|
// .then(stories => this.updateStore(stories.body))
|
|
// .catch(error => console.log('Error: ', error));
|
|
// return this.stories.asObservable();
|
|
// }
|
|
|
|
/**
|
|
* Update the local store with provided stories
|
|
* @param stories
|
|
*/
|
|
updateStore(stories: Story[]) {
|
|
stories.forEach(e => {
|
|
// this.storyMap.set(e.id, e);
|
|
this.storyMap[e.id] = e;
|
|
});
|
|
console.log('update stories', this.storyMap)
|
|
this.next();
|
|
}
|
|
|
|
/**
|
|
* Emits local store.
|
|
*/
|
|
next = () => {
|
|
console.log('next', Object.values(this.storyMap))
|
|
this.stories.next(Object.values(this.storyMap))
|
|
};
|
|
|
|
/**
|
|
* Retrieve story from local store.
|
|
* @param id
|
|
*/
|
|
getOne(id: number) {
|
|
if (this.storyMap[id]) {
|
|
return of(this.storyMap[id]);
|
|
} else {
|
|
const subject: Subject<Story> = new Subject();
|
|
this.supa.client.from<Story>('story').select('id, name, description')
|
|
.filter(<never>'id', 'eq', id)
|
|
.then(
|
|
data => {
|
|
this.updateStore([data.body[0]]);
|
|
subject.next(data.body[0]);
|
|
subject.complete();
|
|
},
|
|
error => {
|
|
subject.error(error);
|
|
subject.complete();
|
|
}
|
|
);
|
|
return subject.asObservable();
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param story
|
|
*/
|
|
updateOne(story: Story): Observable<Story> {
|
|
const subject: Subject<Story> = new Subject();
|
|
this.supa.client.from<Story>('story').update(story)
|
|
.match({ id: story.id })
|
|
.then(
|
|
data => {
|
|
subject.next(data.body[0]);
|
|
subject.complete();
|
|
},
|
|
error => {
|
|
subject.error(error);
|
|
subject.complete();
|
|
}
|
|
);
|
|
return subject.asObservable();
|
|
}
|
|
|
|
|
|
/**
|
|
* Removes one story from db.
|
|
* @param story
|
|
*/
|
|
deleteOne(story: Story): Observable<Story> {
|
|
const subject: Subject<Story> = new Subject();
|
|
this.supa.client.from<Story>('story').delete()
|
|
.match({ id: story.id })
|
|
.then(
|
|
data => {
|
|
subject.next(story);
|
|
subject.complete();
|
|
},
|
|
error => {
|
|
subject.error(error);
|
|
subject.complete();
|
|
}
|
|
);
|
|
return subject.asObservable();
|
|
}
|
|
|
|
/**
|
|
* Creates a story on the db.
|
|
* @param story
|
|
*/
|
|
addOne(story: Story): Observable<Story> {
|
|
const subject: Subject<Story> = new Subject();
|
|
this.supa.client.from<Story>('story').insert(story)
|
|
.then(
|
|
data => {
|
|
subject.next(data.body[0]);
|
|
subject.complete();
|
|
},
|
|
error => {
|
|
subject.error(error);
|
|
subject.complete();
|
|
}
|
|
);
|
|
return subject.asObservable();
|
|
}
|
|
|
|
}
|