[U] standup.service, huddle.comp: CRUD standups

This commit is contained in:
Jan 2020-10-29 23:13:22 +01:00
parent e1aa1342c2
commit 8509578c74
7 changed files with 186 additions and 11 deletions

View file

@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
import { StandUp } from './standup';
import { SupaService } from './supa.service';
@ -10,11 +10,17 @@ export class StandupService {
// standupMap: Map<number, StandUp> = new Map();
standupMap = {};
standups: BehaviorSubject<any> = new BehaviorSubject([]);
isListening: boolean = false;
constructor(
private supa: SupaService,
) { }
/**
* Get StandUps from local store.
* Requests data if store is emtpy.
* @returns Observable<StandUp[]>
*/
getStandUps(): Observable<StandUp[]> {
if (Object.values(this.standupMap).length === 0) {
console.log('getStandUps - REFRESH')
@ -25,31 +31,133 @@ export class StandupService {
}
}
/**
* Listen to realtime events from standup db.
*/
subscribeToStandups() {
if (!this.isListening) {
this.isListening = true;
this.supa.client.from<StandUp>('standup').on('*', payload => {
console.log('subscribeToStandups - REALTIME EVENT', payload);
if ((payload.eventType === 'INSERT') || (payload.eventType === 'UPDATE')) {
this.standupMap[payload.new.id] = payload.new;
} else {
delete this.standupMap[payload.old.id];
}
this.next();
}).subscribe();
}
}
/**
* Requests up to date data from API.
* Returns the local copy.
* @returns Observable<StandUp>
*/
refreshStandUps(): Observable<StandUp[]> {
this.supa.client.from<StandUp>('standup').select('id, name, description')
this.subscribeToStandups();
this.supa.client.from<StandUp>('standup').select()
.then(standups => this.updateStore(standups.body))
.catch(error => console.log('Error: ', error));
return this.standups.asObservable();
}
/**
* Update the local store with provided standups
* @param standups
*/
updateStore(standups: StandUp[]) {
standups.forEach(e => {
// this.standupMap.set(e.id, e);
this.standupMap[e.id] = e;
});
this.standups.next(Object.values(this.standupMap));
this.next();
}
updateOne(standup: StandUp) {
/**
* Emits local store.
*/
next = () => this.standups.next(Object.values(this.standupMap));
/**
* Retrieve standup from local store.
* @param id
*/
getOne(id: number) {
if (this.standupMap[id]) {
return of(this.standupMap[id]);
} else {
const subject: Subject<StandUp> = new Subject();
this.supa.client.from<StandUp>('standup').select('id, name, description')
.filter(<never>'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();
}
}
deleteOne(standup: StandUp) {
/**
*
* @param standup
*/
updateOne(standup: StandUp): Observable<StandUp> {
const subject: Subject<StandUp> = new Subject();
this.supa.client.from<StandUp>('standup').update(standup)
.match({ id: standup.id })
.then(data => {
subject.next(data.body[0]);
subject.complete();
})
.catch(error => {
subject.error(error);
subject.complete();
});
return subject.asObservable();
}
addOne(standup: StandUp) {
/**
* Removes one standup from db.
* @param standup
*/
deleteOne(standup: StandUp): Observable<StandUp> {
const subject: Subject<StandUp> = new Subject();
this.supa.client.from<StandUp>('standup').delete()
.match({ id: standup.id })
.then(data => {
subject.next(standup);
subject.complete();
})
.catch(error => {
subject.error(error);
subject.complete();
});
return subject.asObservable();
}
/**
* Creates a standup on the db.
* @param standup
*/
addOne(standup: StandUp): Observable<StandUp> {
const subject: Subject<StandUp> = new Subject();
this.supa.client.from<StandUp>('standup').insert(standup)
.then(data => {
subject.next(data.body[0]);
subject.complete();
})
.catch(error => {
subject.error(error);
subject.complete();
});
return subject.asObservable();
}
}

View file

@ -2,4 +2,9 @@ export class StandUp {
id: number;
name: string;
description: string;
constructor(name: string, description: string) {
this.name = name;
this.description = description;
}
}

View file

@ -4,7 +4,7 @@
</nav>
<div class="container-fluid p-0">
<div class="myContainer d-flex">
<div class="menu">
<div *ngIf="supa.user | async" class="menu">
<app-channel-list></app-channel-list>
</div>
<div class="container content">

View file

@ -1,5 +1,5 @@
<div class="list bg-dark text-white p-3">
<p><strong>Standup</strong> <strong class="newBtn">+</strong></p>
<p><strong>Standup</strong> <strong class="newBtn" (click)="createStandUp()">+</strong></p>
<ul class="list-unstyled">
<li *ngFor="let s of standups" [title]="s.description" [routerLink]="'/huddle/'+s.id">{{s.name}}</li>
</ul>

View file

@ -26,4 +26,11 @@ export class ChannelListComponent implements OnInit {
return this.standupSevice.getStandUps();
}
createStandUp() {
this.standupSevice.addOne(new StandUp('test', 'test')).subscribe(
data => console.log(data),
error => console.error(error)
)
}
}

View file

@ -1,4 +1,14 @@
<div class="row">
<div *ngIf="standup" class="row">
<div class="col-12 col-sm-9">
<legend #name contenteditable="true" (click)="dataUpdated=true">{{ standup.name }}</legend>
<p #desc contenteditable="true" (click)="dataUpdated=true">{{ standup.description }}</p>
</div>
<div class="col-12 col-sm-3">
<div class="float-right">
<button class="btn btn-primary ml-1 mr-1" [disabled]="!dataUpdated" (click)="updateStandUp(name.innerText, desc.innerText)">Save</button>
<button class="btn btn-danger ml-1 mr-1" (click)="deleteStandUp()">Delete</button>
</div>
</div>
<div class="col-12">
<ah-recorder></ah-recorder>
</div>

View file

@ -1,5 +1,8 @@
import { Component, OnInit, ViewChild } from "@angular/core";
import { ActivatedRoute } from '@angular/router';
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { StandUp } from '../api/supabase/standup';
import { StandupService } from '../api/supabase/standup.service';
import { SupaService } from '../api/supabase/supa.service';
@Component({
@ -33,13 +36,30 @@ export class HuddleComponent implements OnInit {
}
];
selectedUser;
standup: StandUp;
constructor(
private modalService: NgbModal,
public supa: SupaService,
private standupService: StandupService,
private route: ActivatedRoute,
) {}
ngOnInit() {
this.route.params.subscribe(
params => {
if (params.id) {
this.standupService.getOne(params.id).subscribe(
data => {
console.log(data);
this.standup = data;
},
error => {
console.error(error);
}
)
}
}
)
}
playStory(user) {
@ -91,4 +111,29 @@ export class HuddleComponent implements OnInit {
}
this.selectedUser = this.users[index + 1];
}
updateStandUp(name:string, desc:string) {
this.standup.name = name;
this.standup.description = desc;
this.standupService.updateOne(this.standup).subscribe(
data => {
console.log('Success', data);
},
error => {
console.error('Failed', error);
}
)
}
deleteStandUp() {
this.standupService.deleteOne(this.standup).subscribe(
data => {
console.log('Success', data);
},
error => {
console.error('Failed', error);
}
)
}
}