Read
Readings docs is pretty straightforward. Get the object from firestore, convert it to our model and encapsulate it in an Entity with the firestore id.
getResume(resumeId: string): Observable<Entity<Resume>> {
console.log('getResume called');
return this.afs
.doc(`/users/${this.uid}/resumes/${resumeId}`)
.snapshotChanges()
.pipe(
map(action => {
const resume = this.convertFromFirestore(action.payload.data());
const id = action.payload.id;
return new Entity<Resume>(id, resume);
}),
tap(next => console.log(`getResumes returned ${JSON.stringify(next)}`))
);
}
getResumes(limit: number, startAfter?: Resume) {
console.log('getResumes called');
return this.afs
.collection(`/users/${this.uid}/resumes`, queryFn => {
let paginatedQuery = queryFn.orderBy('name').limit(limit);
if (startAfter) {
paginatedQuery = paginatedQuery.startAt(startAfter);
}
return paginatedQuery;
})
.snapshotChanges()
.pipe(
map(actions => {
return actions.map(action => {
const resume = this.convertFromFirestore(action.payload.doc.data());
const id = action.payload.doc.id;
return new Entity<Resume>(id, resume);
});
}),
tap(next => console.log(`getResumes data length ${next.length}`))
);
}
The conversion is necessary because Firestore changes the Dates to a Timestamp object.
convertFromFirestore(rawResume: any): Resume {
const versions = rawResume.versions.map(
rawversion =>
<ResumeVersion>{
version: rawversion.version,
// Convert Timestamp to Date
createdAt: rawversion.createdAt.toDate(),
archived: rawversion.archived,
filename: rawversion.filename
}
);
const resume: Resume = {
name: rawResume.name,
versions: versions
};
return resume;
}
Creation
Creating a Resume is a two step process, first we create the firestore document, then we upload a File to Firebase Storage
createResume(name: string, file: File): Observable<UploadTaskSnapshot> {
const newVersionNumber = 1;
const resume = <Resume>{
name: name,
versions: [
<ResumeVersion>{
version: newVersionNumber,
createdAt: new Date(),
filename: file.name,
archived: false
}
]
};
console.log({ resume });
const uploadTask = this.afs
.collection(`users/${this.uid}/resumes/`)
.add(resume)
.then(function(docRef) {
console.log('Resource document written with ID: ', docRef.id);
return new Entity<Resume>(docRef.id, resume);
})
.then(resumeEntity => {
const path = this.storagePath(resumeEntity, newVersionNumber);
const sorageRef = this.storage.ref(path);
const task = sorageRef.put(file);
return task;
});
return from(uploadTask);
}
Update
Updating is divided in two part
- changing the name of the resume
- adding a new version by uploading a new file
Uploading a new file requires to update the document and then do the upload.
updateResume(resumeId: string, name: string) {
return this.afs
.doc(`/users/${this.uid}/resumes/${resumeId}`)
.update({ name: name });
}
addResumeVersion(resumeEntity: Entity<Resume>, file?: File) {
const resume = resumeEntity.value;
// Not sure about this, maybe the array can be reordered some way
const newVersionNumber =
resume.versions[resume.versions.length - 1].version + 1;
resume.versions.push(<ResumeVersion>{
version: newVersionNumber,
createdAt: new Date(),
filename: file.name,
archived: false
});
const uploadTask = this.afs
.doc(`/users/${this.uid}/resumes/${resumeEntity.id}`)
.update(resume)
.then(_ => {
const path = this.storagePath(resumeEntity, newVersionNumber);
const sorageRef = this.storage.ref(path);
const task = sorageRef.put(file);
return task;
});
return from(uploadTask);
}