Commit 115d9ad9 authored by David Hardy's avatar David Hardy

Preparing for workshop

parent 5713c86f
......@@ -197,13 +197,20 @@ That's where **Functions** comes into play. We've already created one function,
Do the following from within the `/functions` folder:
- Start with obtaining the firebase dependencies, run `npm install firebase-functions@latest firebase-admin@latest --save`.
- Next replace the contents of `/functions/src` with the contents of `/functionsExample/src`.
- Now run `npm install @google-cloud/storage jimp rxjs --save` to get some app specific dependencies.
- Next replace the contents of `/functions/src` with the contents of `/functionsExample/src`.
- Run `npm run build`.
- In the file `firebase.json`, replace the contets of `functions` with
```
"ignore": [
"lib/model/**"
]
```
Now go back to the project root folder and:
- Run `npm run build`.
- Run `npm run deploy`.
- When asked for deletion of _hello world_ enter `yes`.
When this is done we should see in the Firebase console, under _Functions_ our 2 functions; _storageFinalizeFunctions_ and _deleteImages_.
Now upload an image with the App, either from http://localhost:4200 or, even better, from the just deployed public site
......@@ -266,9 +273,8 @@ So far we have already made a great App, we can register, sign up, log in. We ca
however were only getting started. We want to grow our App with new functionality. You know what would be great? Voting!
### Step 3.1: Naive voting
Let's start with the most easy way to have voting. Uncomment #TODO
- TODO 1
- TODO 2
Let's start with the most easy way to have voting.
- Uncomment the remaining code in `app/src/app/facade/image.service.ts`
Now we should be able to cast votes, and see the total. However there are at least 2 glaring problems with this naive solution.
......@@ -328,7 +334,11 @@ result in less reads, probably staying close to the free tier usage limits. Alar
This step is very important, but requires knowledge of TypeScript and Angular, so if you are not comfortable with Angular, feel free to skip to Part 4,
as long as you take to hart the above described problem.
In the class `app/src/app/facade/image.service.ts` you need to remove the method `getVoteScore$`. Instead you can use the fields `totalVotes` and `score` of `ImageData`.
- Start with some comment toggling, in `app/src/app/ui/thumbnail-card/thumbnail-card.component.html` toggle the comments.
- Next in `app/src/app/ui/thumbnail-card/thumbnail-card.component.ts` follow the comment.
- In the class `app/src/app/facade/image.service.ts` you need to remove the method `getVoteScore$`.
- Instead you can use the fields `totalVotes` and `score` of `ImageData`.
These fields do not contain any content yet, and it is your job to create an aggregation function. Open the file `functions/src/index.ts` and start with the code below.
Create a function that updates the fields `totalVotes` and `score`.
......
......@@ -11,10 +11,10 @@ import en from '@angular/common/locales/en';
import {ThumbnailListComponent} from './ui/thumbnail-list/thumbnail-list.component';
import {UploadImageComponent} from './ui/upload-image/upload-image.component';
import {ThumbnailCardComponent} from './ui/thumbnail-card/thumbnail-card.component';
// import {AngularFireModule} from 'angularfire2';
// import {AngularFirestoreModule} from 'angularfire2/firestore';
// import {AngularFireAuthModule} from 'angularfire2/auth';
// import {AngularFireStorageModule} from 'angularfire2/storage';
// import {AngularFireModule} from '@angular/fire';
// import {AngularFirestoreModule} from '@angular/fire/firestore';
// import {AngularFireAuthModule} from '@angular/fire/auth';
// import {AngularFireStorageModule} from '@angular/fire/storage';
// import {FirebaseUIModule} from 'firebaseui-angular';
// import {environment} from '../environments/environment';
// import * as firebaseui from 'firebaseui';
......
......@@ -47,12 +47,11 @@ export class ImageService {
* Also fix the constructor and the imports
*/
return of(this.myData);
// // ######################
// // Run once
// this.loginService.uid$().subscribe(uid => {
// this.myData.forEach(entry => {
// entry.user = uid
// this.db.doc(`images/${entry.id}`).set(entry);
// });
// });
......@@ -60,6 +59,8 @@ export class ImageService {
// return this.db.collection<ImageData>(`images`).valueChanges();
return of(this.myData);
}
delete(imageId: string): void {
......@@ -99,10 +100,9 @@ export class ImageService {
}
castVote$(imageId: string, vote: Vote): Observable<void> {
return of();
/**
* FixMe: Step TODO
* FixMe: Step 3.1
* Toggle the comments in this method
*/
......@@ -110,13 +110,14 @@ export class ImageService {
// take(1),
// switchMap(uid => this.db.doc<VoteContainer>(`images/${imageId}/votes/${uid}`).set({vote: vote}))
// );
return of();
}
getVoteScore$(imageId: string): Observable<number> {
return of(42);
/**
* FixMe: Step TODO
* FixMe: Step 3.1
* Toggle the comments in this method
*/
......@@ -127,21 +128,23 @@ export class ImageService {
// )),
// map(([upVotes, downVotes]) => (upVotes ? upVotes.length : 0) - (downVotes ? downVotes.length : 0))
// );
return of(42);
}
getMyVote$(imageId: string): Observable<Vote> {
/**
* FixMe: Step TODO
* FixMe: Step 3.1
* Toggle the comments in this method
*/
return of(Vote.BLANK);
// return this.loginService.uid$().pipe(
// take(1),
// switchMap(uid => this.db.doc<VoteContainer>(`images/${imageId}/votes/${uid}`).valueChanges()),
// map(vc => vc ? Vote[vc.vote] : Vote[Vote.BLANK])
// );
return of(Vote.BLANK);
}
}
......@@ -28,10 +28,10 @@ export class LoginService {
uid$(): Observable<string> {
return of('OfflineExample');
// return this.auth.authState.pipe(
// map(state => state ? state.uid : undefined)
// );
return of('OfflineExample');
}
// userInfo$(): Observable<UserInfo> {
......
......@@ -11,8 +11,11 @@
</ng-template>
<ng-template #description>
<p *ngIf="imageData.score != null">{{imageData.score}} / {{imageData.totalVotes}}</p>
<p *ngIf="imageData.score == null">0 / 0</p>
<!-- FixMe: Step 3.4: Uncomment the lines below -->
<!--<p *ngIf="imageData.score != null">{{imageData.score}} / {{imageData.totalVotes}}</p>-->
<!--<p *ngIf="imageData.score == null">0 / 0</p>-->
<!-- FixMe: Step 3.4: Remove the 1 line below -->
<p>{{score$ | async}}</p>
<p>{{imageData.username || imageData.user}}</p>
</ng-template>
......
import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';
import {Observable, Subscription} from 'rxjs';
import {merge, Observable, of, Subscription} from 'rxjs';
import {ImageService, Vote} from '../../facade/image.service';
import {ImageData} from '@apu/model';
import {LoginService} from '../../facade/login.service';
......@@ -21,6 +21,7 @@ export class ThumbnailCardComponent implements OnInit, OnDestroy {
myVote: Vote;
private subscription: Subscription;
private score$: Observable<number>;
constructor(private imageService: ImageService,
private loginService: LoginService) {
......@@ -31,6 +32,12 @@ export class ThumbnailCardComponent implements OnInit, OnDestroy {
this.subscription = this.imageService.getMyVote$(this.imageData.id)
.subscribe(vote => this.myVote = vote);
/**
* FixMe: Step 3.4
* Remove this line as well, and the score$ field.
*/
this.score$ = merge(of(0), this.imageService.getVoteScore$(this.imageData.id));
this.uid$ = this.loginService.uid$();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment