From 1da9c1e81ac15e83a5a897c9b422413f9eb9f983 Mon Sep 17 00:00:00 2001 From: jgerstbe Date: Sat, 31 Oct 2020 00:07:55 +0100 Subject: [PATCH] [A] channel.service functionality, create channel from sidebar --- src/app/api/supabase/channel.service.ts | 153 +++++++++++++++++++++++- src/app/api/supabase/channel.ts | 13 ++ src/app/api/supabase/standup.service.ts | 2 - src/app/sidebar/sidebar.component.html | 9 +- src/app/sidebar/sidebar.component.ts | 25 ++++ 5 files changed, 194 insertions(+), 8 deletions(-) create mode 100644 src/app/api/supabase/channel.ts diff --git a/src/app/api/supabase/channel.service.ts b/src/app/api/supabase/channel.service.ts index 0d73e6c..93ee5be 100644 --- a/src/app/api/supabase/channel.service.ts +++ b/src/app/api/supabase/channel.service.ts @@ -1,9 +1,160 @@ import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable, of, Subject } from 'rxjs'; +import { Channel } from './channel'; +import { SupaService } from './supa.service'; @Injectable({ providedIn: 'root' }) export class ChannelService { + channelMap = {}; + channels: BehaviorSubject = new BehaviorSubject([]); + isListening: boolean = false; - constructor() { } + constructor( + private supa: SupaService, + ) { } + + /** + * Get Channels from local store. + * Requests data if store is emtpy. + * @returns Observable + */ + getChannels(): Observable { + if (Object.values(this.channelMap).length === 0) { + console.log('getChannels - REFRESH') + return this.refreshChannels(); + } else { + console.log('getChannels - LOCAL') + return this.channels.asObservable(); + } + } + + /** + * Listen to realtime events from channel db. + */ + subscribeToChannels() { + if (!this.isListening) { + this.isListening = true; + this.supa.client.from('channel').on('*', payload => { + console.log('subscribeToChannels - REALTIME EVENT', payload); + if ((payload.eventType === 'INSERT') || (payload.eventType === 'UPDATE')) { + this.channelMap[payload.new.id] = payload.new; + } else { + delete this.channelMap[payload.old.id]; + } + this.next(); + }).subscribe(); + } + } + + /** + * Requests up to date data from API. + * Returns the local copy. + * @returns Observable + */ + refreshChannels(): Observable { + this.subscribeToChannels(); + this.supa.client.from('channel').select() + .then(channels => this.updateStore(channels.body)) + .catch(error => console.log('Error: ', error)); + return this.channels.asObservable(); + } + + /** + * Update the local store with provided channels + * @param channels + */ + updateStore(channels: Channel[]) { + channels.forEach(e => { + this.channelMap[e.id] = e; + }); + this.next(); + } + + /** + * Emits local store. + */ + next = () => this.channels.next(Object.values(this.channelMap)); + + /** + * Retrieve channel from local store. + * @param id + */ + getOne(id: number) { + if (this.channelMap[id]) { + return of(this.channelMap[id]); + } else { + const subject: Subject = new Subject(); + this.supa.client.from('channel').select('id, name, description') + .filter('id', 'eq', id) + .then(data => { + this.updateStore([data.body[0]]); + subject.next(data.body[0]); + subject.complete(); + }) + .catch(error => { + subject.error(error); + subject.complete(); + }); + return subject.asObservable(); + } + } + + /** + * + * @param channel + */ + updateOne(channel: Channel): Observable { + const subject: Subject = new Subject(); + this.supa.client.from('channel').update(channel) + .match({ id: channel.id }) + .then(data => { + subject.next(data.body[0]); + subject.complete(); + }) + .catch(error => { + subject.error(error); + subject.complete(); + }); + return subject.asObservable(); + } + + + /** + * Removes one channel from db. + * @param channel + */ + deleteOne(channel: Channel): Observable { + const subject: Subject = new Subject(); + this.supa.client.from('channel').delete() + .match({ id: channel.id }) + .then(data => { + subject.next(channel); + subject.complete(); + }) + .catch(error => { + subject.error(error); + subject.complete(); + }); + return subject.asObservable(); + } + + /** + * Creates a channel on the db. + * @param channel + */ + addOne(channel: Channel): Observable { + const subject: Subject = new Subject(); + this.supa.client.from('channel').insert(channel) + .then(data => { + subject.next(data.body[0]); + subject.complete(); + }) + .catch(error => { + subject.error(error); + subject.complete(); + }); + return subject.asObservable(); + } } diff --git a/src/app/api/supabase/channel.ts b/src/app/api/supabase/channel.ts new file mode 100644 index 0000000..33ac54a --- /dev/null +++ b/src/app/api/supabase/channel.ts @@ -0,0 +1,13 @@ +export class Channel { + id: number; + name: string; + description: string; + inserted_at: string | Date; + created_by: string; + + constructor(created_by: string, name: string, description?: string) { + this.name = name; + this.description = description; + this.created_by = created_by; + } +} \ No newline at end of file diff --git a/src/app/api/supabase/standup.service.ts b/src/app/api/supabase/standup.service.ts index f67c401..966cdbe 100644 --- a/src/app/api/supabase/standup.service.ts +++ b/src/app/api/supabase/standup.service.ts @@ -7,7 +7,6 @@ import { SupaService } from './supa.service'; providedIn: 'root' }) export class StandupService { - // standupMap: Map = new Map(); standupMap = {}; standups: BehaviorSubject = new BehaviorSubject([]); isListening: boolean = false; @@ -68,7 +67,6 @@ export class StandupService { */ updateStore(standups: StandUp[]) { standups.forEach(e => { - // this.standupMap.set(e.id, e); this.standupMap[e.id] = e; }); this.next(); diff --git a/src/app/sidebar/sidebar.component.html b/src/app/sidebar/sidebar.component.html index 1d858bd..d835f33 100644 --- a/src/app/sidebar/sidebar.component.html +++ b/src/app/sidebar/sidebar.component.html @@ -2,13 +2,12 @@

Standup +

  • {{s.name}}
  • +
  • There are no standups yet.
-

Channel +

+

Channel +

    -
  • ...
  • -
  • ...
  • -
  • ...
  • -
  • ...
  • +
  • {{c.name}}
  • +
  • There are no channels yet.

Settings

    diff --git a/src/app/sidebar/sidebar.component.ts b/src/app/sidebar/sidebar.component.ts index 74ecec7..4bb6503 100644 --- a/src/app/sidebar/sidebar.component.ts +++ b/src/app/sidebar/sidebar.component.ts @@ -3,6 +3,10 @@ import { Observable, throwError } from 'rxjs'; import { StandUp } from '../api/supabase/standup'; import { StandupService } from '../api/supabase/standup.service'; import { environment } from '../../environments/environment'; +import { Channel } from '../api/supabase/channel'; +import { ChannelService } from '../api/supabase/channel.service'; +import { SupaService } from '../api/supabase/supa.service'; +import { User } from '../api/supabase/user'; @Component({ selector: 'app-sidebar', @@ -11,10 +15,13 @@ import { environment } from '../../environments/environment'; }) export class SidebarComponent implements OnInit { standups: StandUp[] = []; + channels: Channel[] = []; environment = environment; constructor( + private supaService: SupaService, private standupSevice: StandupService, + private channelService: ChannelService, ) { } ngOnInit() { @@ -22,12 +29,20 @@ export class SidebarComponent implements OnInit { console.log('ChannelListComponent - StandUps', standups); this.standups = standups; }); + this.loadChannels().subscribe(channels => { + console.log('ChannelListComponent - Channels', channels); + this.channels = channels; + }); } loadStandUps(): Observable { return this.standupSevice.getStandUps(); } + loadChannels(): Observable { + return this.channelService.getChannels(); + } + createStandUp() { this.standupSevice.addOne(new StandUp('test', 'test')).subscribe( data => console.log(data), @@ -35,4 +50,14 @@ export class SidebarComponent implements OnInit { ) } + createChannel() { + if (!this.supaService.userProfile.id) { + return; + } + this.channelService.addOne(new Channel(this.supaService.userProfile.id, 'test', 'test')).subscribe( + data => console.log(data), + error => console.error(error) + ) + } + }