async-huddle/src/app/api/supabase/story.service.ts

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();
}
}