[New Feature] Add firestore to data layer
This commit is contained in:
@@ -1,7 +1,4 @@
|
||||
declare const process: any
|
||||
|
||||
import firebase from 'firebase'
|
||||
|
||||
try {
|
||||
let config = {
|
||||
apiKey: process.env.API_KEY,
|
||||
@@ -12,7 +9,6 @@ try {
|
||||
messagingSenderId: process.env.MESSAGING_SENDER_ID
|
||||
}
|
||||
|
||||
console.log(firebase)
|
||||
firebase.initializeApp(config)
|
||||
} catch (error) {
|
||||
console.log('=========Firebase initializer==============')
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import moment from 'moment'
|
||||
|
||||
import { Profile } from 'core/domain/users'
|
||||
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth } from 'data/firebaseClient'
|
||||
@@ -68,8 +71,8 @@ export class AuthorizeService implements IAuthorizeService {
|
||||
firebaseAuth()
|
||||
.createUserWithEmailAndPassword(user.email as string, user.password as string)
|
||||
.then((signupResult) => {
|
||||
const {uid, email, displayName, photoURL} = signupResult
|
||||
this.storeUserInformation(uid,email,displayName,photoURL).then(resolve)
|
||||
const {uid, email} = signupResult
|
||||
this.storeUserInformation(uid,email,user.fullName,'').then(resolve)
|
||||
})
|
||||
.catch((error: any) => reject(new SocialError(error.code, error.message)))
|
||||
})
|
||||
@@ -107,7 +110,7 @@ export class AuthorizeService implements IAuthorizeService {
|
||||
firebaseAuth().onAuthStateChanged( (user: any) => {
|
||||
let isVerifide = false
|
||||
if (user) {
|
||||
if (user.emailVerified) {
|
||||
if (user.emailVerified || user.providerData[0].providerId.trim() !== 'password') {
|
||||
isVerifide = true
|
||||
} else {
|
||||
isVerifide = false
|
||||
@@ -210,15 +213,17 @@ export class AuthorizeService implements IAuthorizeService {
|
||||
* @private
|
||||
* @memberof AuthorizeService
|
||||
*/
|
||||
private storeUserInformation = (userId: string, email: string, fullName: string, avatar?: string) => {
|
||||
private storeUserInformation = (userId: string, email: string, fullName: string, avatar: string) => {
|
||||
return new Promise<RegisterUserResult>((resolve,reject) => {
|
||||
firebaseRef.child(`users/${userId}/info`)
|
||||
.set({
|
||||
userId,
|
||||
.set(new Profile(
|
||||
avatar,
|
||||
email,
|
||||
fullName
|
||||
})
|
||||
fullName,
|
||||
'',
|
||||
'',
|
||||
moment().unix(),
|
||||
email
|
||||
))
|
||||
.then((result) => {
|
||||
resolve(new RegisterUserResult(userId))
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth } from 'data/firebaseClient'
|
||||
import { firebaseRef, firebaseAuth, db } from 'data/firebaseClient'
|
||||
|
||||
import { SocialError } from 'core/domain/common'
|
||||
import { ICircleService } from 'core/services/circles'
|
||||
@@ -18,13 +18,11 @@ export class CircleService implements ICircleService {
|
||||
public addCircle: (userId: string, circle: Circle)
|
||||
=> Promise<string> = (userId, circle) => {
|
||||
return new Promise<string>((resolve,reject) => {
|
||||
|
||||
let circleRef = firebaseRef.child(`users/${userId}/circles`).push(circle)
|
||||
circleRef.then(() => {
|
||||
resolve(circleRef.key as string)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth } from 'data/firebaseClient'
|
||||
import moment from 'moment'
|
||||
|
||||
import { SocialError } from 'core/domain/common'
|
||||
import { Profile, UserProvider } from 'core/domain/users'
|
||||
@@ -13,6 +14,7 @@ import { IUserService } from 'core/services/users'
|
||||
* @implements {IUserService}
|
||||
*/
|
||||
export class UserService implements IUserService {
|
||||
|
||||
public getUserProfile: (userId: string)
|
||||
=> Promise<Profile> = (userId) => {
|
||||
return new Promise<Profile>((resolve, reject) => {
|
||||
@@ -23,7 +25,7 @@ export class UserService implements IUserService {
|
||||
if (Object.keys(userProfile).length === 0 && userProfile.constructor === Object) {
|
||||
this.getUserProviderData(userId).then((providerData: UserProvider) => {
|
||||
const {avatar,fullName, email} = providerData
|
||||
const userProfile = new Profile(avatar,fullName,'','',email)
|
||||
const userProfile = new Profile(avatar,fullName,'','', moment().unix(),email)
|
||||
resolve(userProfile)
|
||||
this.updateUserProfile(userId,userProfile)
|
||||
})
|
||||
@@ -52,10 +54,16 @@ export class UserService implements IUserService {
|
||||
})
|
||||
})
|
||||
}
|
||||
public getUsersProfile: (userId: string)
|
||||
=> Promise<{ [userId: string]: Profile }> = (userId) => {
|
||||
public getUsersProfile: (userId: string, page?: number, lastKey?: string)
|
||||
=> Promise<{ [userId: string]: Profile }> = (userId, page, lastKey) => {
|
||||
return new Promise<{ [userId: string]: Profile }>((resolve, reject) => {
|
||||
let usersProfileRef: any = firebaseRef.child(`users`)
|
||||
let usersProfileRef: any
|
||||
if (page) {
|
||||
const numberOfItems = (page * 12) + 12
|
||||
usersProfileRef = firebaseRef.child(`users`).orderByKey().startAt(lastKey!).limitToFirst(numberOfItems)
|
||||
} else {
|
||||
usersProfileRef = firebaseRef.child(`users`).orderByKey()
|
||||
}
|
||||
|
||||
usersProfileRef.once('value').then((snapshot: any) => {
|
||||
let usersProfile: any = snapshot.val() || {}
|
||||
|
||||
31
src/data/firestoreClient/index.ts
Normal file
31
src/data/firestoreClient/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import firebase from 'firebase'
|
||||
import 'firebase/firestore'
|
||||
try {
|
||||
let config = {
|
||||
apiKey: process.env.API_KEY,
|
||||
authDomain: process.env.AUTH_DOMAIN,
|
||||
databaseURL: process.env.DATABASE_URL,
|
||||
projectId: process.env.PROJECT_ID,
|
||||
storageBucket: process.env.STORAGE_BUCKET,
|
||||
messagingSenderId: process.env.MESSAGING_SENDER_ID
|
||||
}
|
||||
|
||||
firebase.initializeApp(config)
|
||||
} catch (error) {
|
||||
console.log('=========Firebase firestore initializer==============')
|
||||
console.log(error)
|
||||
console.log('====================================')
|
||||
}
|
||||
|
||||
// - Storage reference
|
||||
export let storageRef = firebase.storage().ref()
|
||||
|
||||
// Initialize Cloud Firestore through Firebase
|
||||
export const db = firebase.firestore()
|
||||
|
||||
// - Database authorize
|
||||
export let firebaseAuth = firebase.auth
|
||||
export let firebaseRef = firebase.database().ref()
|
||||
|
||||
// - Firebase default
|
||||
export default firebase
|
||||
264
src/data/firestoreClient/services/authorize/AuthorizeService.ts
Normal file
264
src/data/firestoreClient/services/authorize/AuthorizeService.ts
Normal file
@@ -0,0 +1,264 @@
|
||||
import { Profile } from 'core/domain/users'
|
||||
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth, db } from 'data/firestoreClient'
|
||||
|
||||
import { IAuthorizeService } from 'core/services/authorize'
|
||||
import { User, UserProvider } from 'core/domain/users'
|
||||
import { LoginUser, RegisterUserResult } from 'core/domain/authorize'
|
||||
import { SocialError } from 'core/domain/common'
|
||||
|
||||
import { OAuthType } from 'core/domain/authorize/oauthType'
|
||||
import moment from 'moment'
|
||||
/**
|
||||
* Firbase authorize service
|
||||
*
|
||||
* @export
|
||||
* @class AuthorizeService
|
||||
* @implements {IAuthorizeService}
|
||||
*/
|
||||
export class AuthorizeService implements IAuthorizeService {
|
||||
|
||||
/**
|
||||
* Login the user
|
||||
*
|
||||
* @returns {Promise<LoginUser>}
|
||||
* @memberof IAuthorizeService
|
||||
*/
|
||||
public login: (email: string, password: string) => Promise<LoginUser> = (email, password) => {
|
||||
|
||||
return new Promise<LoginUser>((resolve, reject) => {
|
||||
firebaseAuth()
|
||||
.signInWithEmailAndPassword(email, password)
|
||||
.then((result) => {
|
||||
resolve(new LoginUser(result.uid, result.emailVerified))
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs out the user
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
* @memberof IAuthorizeService
|
||||
*/
|
||||
public logout: () => Promise<void> = () => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
firebaseAuth()
|
||||
.signOut()
|
||||
.then((result) => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => {
|
||||
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a user
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
* @memberof IAuthorizeService
|
||||
*/
|
||||
public registerUser: (user: User) => Promise<RegisterUserResult> = (user) => {
|
||||
return new Promise<RegisterUserResult>((resolve, reject) => {
|
||||
firebaseAuth()
|
||||
.createUserWithEmailAndPassword(user.email as string, user.password as string)
|
||||
.then((signupResult) => {
|
||||
const {uid, email} = signupResult
|
||||
this.storeUserInformation(uid,email,user.fullName,'').then(resolve)
|
||||
})
|
||||
.catch((error: any) => reject(new SocialError(error.code, error.message)))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user password
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
* @memberof IAuthorizeService
|
||||
*/
|
||||
public updatePassword: (newPassword: string) => Promise<void> = (newPassword) => {
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
let user = firebaseAuth().currentUser
|
||||
if (user) {
|
||||
user.updatePassword(newPassword).then(() => {
|
||||
// Update successful.
|
||||
resolve()
|
||||
}).catch((error: any) => {
|
||||
// An error happened.
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* On user authorization changed event
|
||||
*
|
||||
* @memberof IAuthorizeService
|
||||
*/
|
||||
public onAuthStateChanged: (callBack: (isVerifide: boolean, user: User) => void) => any = (callBack) => {
|
||||
firebaseAuth().onAuthStateChanged( (user: any) => {
|
||||
let isVerifide = false
|
||||
if (user) {
|
||||
if (user.emailVerified || user.providerData[0].providerId.trim() !== 'password') {
|
||||
isVerifide = true
|
||||
} else {
|
||||
isVerifide = false
|
||||
}
|
||||
}
|
||||
callBack(isVerifide,user)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset user password
|
||||
*
|
||||
* @memberof AuthorizeService
|
||||
*/
|
||||
public resetPassword: (email: string) => Promise<void> = (email) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
let auth = firebaseAuth()
|
||||
|
||||
auth.sendPasswordResetEmail(email).then(function () {
|
||||
resolve()
|
||||
}).catch((error: any) => {
|
||||
// An error happened.
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Send verfication email to user email
|
||||
*
|
||||
* @memberof AuthorizeService
|
||||
*/
|
||||
public sendEmailVerification: () => Promise<void> = () => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
let auth = firebaseAuth()
|
||||
const user = auth.currentUser
|
||||
|
||||
if (user) {
|
||||
user.sendEmailVerification().then(() => {
|
||||
resolve()
|
||||
}).catch((error: any) => {
|
||||
// An error happened.
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
} else {
|
||||
reject(new SocialError('authorizeService/nullException', 'User was null!'))
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
public loginWithOAuth: (type: OAuthType) => Promise<LoginUser> = (type) => {
|
||||
return new Promise<LoginUser>((resolve,reject) => {
|
||||
|
||||
let provider: any
|
||||
|
||||
switch (type) {
|
||||
case OAuthType.GITHUB:
|
||||
provider = new firebaseAuth.GithubAuthProvider()
|
||||
break
|
||||
case OAuthType.FACEBOOK:
|
||||
provider = new firebaseAuth.FacebookAuthProvider()
|
||||
break
|
||||
case OAuthType.GOOGLE:
|
||||
provider = new firebaseAuth.GoogleAuthProvider()
|
||||
break
|
||||
default:
|
||||
throw new SocialError('authorizeService/loginWithOAuth','None of OAuth type is matched!')
|
||||
}
|
||||
firebaseAuth().signInWithPopup(provider).then((result) => {
|
||||
// This gives you a GitHub Access Token. You can use it to access the GitHub API.
|
||||
let token = result.credential.accessToken
|
||||
// The signed-in user info.
|
||||
const {user} = result
|
||||
const {credential} = result
|
||||
const {uid, displayName, email, photoURL} = user
|
||||
const {accessToken, providerId} = credential
|
||||
this.storeUserProviderData(uid,email,displayName,photoURL,providerId,accessToken)
|
||||
// this.storeUserInformation(uid,email,displayName,photoURL).then(resolve)
|
||||
resolve(new LoginUser(user.uid,true,providerId,displayName,email,photoURL))
|
||||
|
||||
}).catch(function (error: any) {
|
||||
// Handle Errors here.
|
||||
let errorCode = error.code
|
||||
let errorMessage = error.message
|
||||
// The email of the user's account used.
|
||||
let email = error.email
|
||||
// The firebase.auth.AuthCredential type that was used.
|
||||
let credential = error.credential
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Store user information
|
||||
*
|
||||
* @private
|
||||
* @memberof AuthorizeService
|
||||
*/
|
||||
private storeUserInformation = (userId: string, email: string, fullName: string, avatar: string) => {
|
||||
return new Promise<RegisterUserResult>((resolve,reject) => {
|
||||
db.doc(`userInfo/${userId}`).set(
|
||||
{
|
||||
avatar,
|
||||
fullName,
|
||||
creationDate: moment().unix(),
|
||||
email
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
alert(userId)
|
||||
resolve(new RegisterUserResult(userId))
|
||||
})
|
||||
.catch((error: any) => reject(new SocialError(error.name, 'firestore/storeUserInformation : ' + error.message)))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Store user provider information
|
||||
*
|
||||
* @private
|
||||
* @memberof AuthorizeService
|
||||
*/
|
||||
private storeUserProviderData = (
|
||||
userId: string,
|
||||
email: string,
|
||||
fullName: string,
|
||||
avatar: string,
|
||||
providerId: string,
|
||||
accessToken: string
|
||||
) => {
|
||||
return new Promise<RegisterUserResult>((resolve,reject) => {
|
||||
db.doc(`userProviderInfo/${userId}`)
|
||||
.set(
|
||||
{
|
||||
userId,
|
||||
email,
|
||||
fullName,
|
||||
avatar,
|
||||
providerId,
|
||||
accessToken
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
resolve(new RegisterUserResult(userId))
|
||||
})
|
||||
.catch((error: any) => reject(new SocialError(error.name, error.message)))
|
||||
})
|
||||
}
|
||||
}
|
||||
5
src/data/firestoreClient/services/authorize/index.ts
Normal file
5
src/data/firestoreClient/services/authorize/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { AuthorizeService } from './AuthorizeService'
|
||||
|
||||
export {
|
||||
AuthorizeService
|
||||
}
|
||||
119
src/data/firestoreClient/services/circles/CircleService.ts
Normal file
119
src/data/firestoreClient/services/circles/CircleService.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth, db } from 'data/firestoreClient'
|
||||
|
||||
import { SocialError } from 'core/domain/common'
|
||||
import { ICircleService } from 'core/services/circles'
|
||||
import { Circle, UserFollower } from 'core/domain/circles'
|
||||
import { User } from 'core/domain/users'
|
||||
|
||||
/**
|
||||
* Firbase circle service
|
||||
*
|
||||
* @export
|
||||
* @class CircleService
|
||||
* @implements {ICircleService}
|
||||
*/
|
||||
export class CircleService implements ICircleService {
|
||||
|
||||
public addCircle: (userId: string, circle: Circle)
|
||||
=> Promise<string> = (userId, circle) => {
|
||||
return new Promise<string>((resolve,reject) => {
|
||||
let circleRef = db.doc(`users/${userId}`).collection(`circles`).add(circle)
|
||||
circleRef.then((result) => {
|
||||
resolve(result.id as string)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
public addFollowingUser: (userId: string, circleId: string, userCircle: User, userFollower: UserFollower, userFollowingId: string)
|
||||
=> Promise<void> = (userId, circleId, userCircle, userFollower, userFollowingId) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
const batch = db.batch()
|
||||
const followerRef = db.doc(`users/${userId}/circles/${circleId}/users/${userFollowingId}`)
|
||||
const followingRef = db.doc(`users/${userFollowingId}/circles/-Followers/users/${userId}`)
|
||||
|
||||
batch.update(followerRef, userCircle)
|
||||
batch.update(followingRef, userFollower)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
public deleteFollowingUser: (userId: string, circleId: string, userFollowingId: string)
|
||||
=> Promise<void> = (userId, circleId, userFollowingId) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
|
||||
const batch = db.batch()
|
||||
const followerRef = db.doc(`users/${userId}/circles/${circleId}/users/${userFollowingId}`)
|
||||
const followingRef = db.doc(`users/${userFollowingId}/circles/-Followers/users/${userId}`)
|
||||
|
||||
batch.delete(followerRef)
|
||||
batch.delete(followingRef)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
public updateCircle: (userId: string, circleId: string, circle: Circle)
|
||||
=> Promise<void> = (userId, circleId, circle) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
|
||||
const batch = db.batch()
|
||||
const circleRef = db.doc(`users/${userId}/circles/${circleId}`)
|
||||
|
||||
batch.update(circleRef,circle)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
public deleteCircle: (userId: string, circleId: string)
|
||||
=> Promise<void> = (userId, circleId) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
|
||||
const batch = db.batch()
|
||||
const circleRef = db.doc(`users/${userId}/circles/${circleId}`)
|
||||
|
||||
batch.delete(circleRef)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
public getCircles: (userId: string) => Promise<{ [circleId: string]: Circle }> = (userId) => {
|
||||
return new Promise<{ [circleId: string]: Circle }>((resolve,reject) => {
|
||||
let circlesRef = db.doc(`users/${userId}`).collection(`circles`)
|
||||
|
||||
circlesRef.onSnapshot((snapshot) => {
|
||||
let parsedData: { [circleId: string]: Circle } = {}
|
||||
snapshot.forEach((result) => {
|
||||
parsedData[result.id] = {
|
||||
id: result.id,
|
||||
...result.data() as Circle
|
||||
}
|
||||
})
|
||||
resolve(parsedData)
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
5
src/data/firestoreClient/services/circles/index.ts
Normal file
5
src/data/firestoreClient/services/circles/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { CircleService } from './CircleService'
|
||||
|
||||
export {
|
||||
CircleService
|
||||
}
|
||||
133
src/data/firestoreClient/services/comments/CommentService.ts
Normal file
133
src/data/firestoreClient/services/comments/CommentService.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth, db } from 'data/firestoreClient'
|
||||
import _ from 'lodash'
|
||||
|
||||
import { SocialError } from 'core/domain/common'
|
||||
import { ICommentService } from 'core/services/comments'
|
||||
import { Comment } from 'core/domain/comments'
|
||||
|
||||
/**
|
||||
* Firbase comment service
|
||||
*
|
||||
* @export
|
||||
* @class CommentService
|
||||
* @implements {ICommentService}
|
||||
*/
|
||||
export class CommentService implements ICommentService {
|
||||
public addComment: (comment: Comment)
|
||||
=> Promise<string> = (comment) => {
|
||||
return new Promise<string>((resolve,reject) => {
|
||||
const postRef = db.doc(`posts/${comment.postId}`)
|
||||
let commentRef = postRef.collection('comments')
|
||||
commentRef.add(comment).then((result) => {
|
||||
resolve(result.id)
|
||||
|
||||
/**
|
||||
* Add comment counter and three comments' slide preview
|
||||
*/
|
||||
db.runTransaction((transaction) => {
|
||||
return transaction.get(postRef).then((postDoc) => {
|
||||
if (postDoc.exists) {
|
||||
const commentCount = postDoc.data().commentCounter + 1
|
||||
transaction.update(postRef, { commentCounter: commentCount })
|
||||
let comments = postDoc.data()
|
||||
if (!comments) {
|
||||
comments = {}
|
||||
}
|
||||
if (commentCount < 4) {
|
||||
transaction.update(postRef, { comments: { ...comments, [result.id]: comment } })
|
||||
} else {
|
||||
let sortedObjects = comments
|
||||
// Sort posts with creation date
|
||||
sortedObjects.sort((a: any, b: any) => {
|
||||
return parseInt(b.creationDate,10) - parseInt(a.creationDate,10)
|
||||
})
|
||||
const lastCommentId = Object.keys(sortedObjects)[2]
|
||||
comments[lastCommentId] = {... comment}
|
||||
transaction.update(postRef, { comments: { ...comments} })
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code,error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public getComments: (postId: string, callback: (resultComments: { [postId: string]: { [commentId: string]: Comment } }) => void)
|
||||
=> void = (postId, callback) => {
|
||||
let commentsRef = db.doc(`posts/${postId}`).collection(`comments`)
|
||||
commentsRef.onSnapshot((snapshot) => {
|
||||
let parsedData: {[postId: string]: {[commentId: string]: Comment}} = {[postId]: {}}
|
||||
snapshot.forEach((result) => {
|
||||
parsedData[postId][result.id] = {
|
||||
id: result.id,
|
||||
...result.data() as Comment
|
||||
}
|
||||
})
|
||||
if (callback) {
|
||||
callback(parsedData)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public updateComment: (comment: Comment)
|
||||
=> Promise<void> = (comment) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
const batch = db.batch()
|
||||
const commentRef = db.doc(`posts/${comment.postId}/comments/${comment.id}`)
|
||||
|
||||
batch.update(commentRef, comment)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code,error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public deleteComment: (commentId: string, postId: string)
|
||||
=> Promise<void> = (commentId, postId) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
const batch = db.batch()
|
||||
const postRef = db.doc(`posts/${postId}`)
|
||||
const commentRef = postRef.collection(`comments`).doc(commentId)
|
||||
|
||||
batch.delete(commentRef)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
|
||||
/**
|
||||
* Delete comment counter and comments' slide preview
|
||||
*/
|
||||
db.runTransaction((transaction) => {
|
||||
return transaction.get(postRef).then((postDoc) => {
|
||||
if (postDoc.exists) {
|
||||
const commentCount = postDoc.data().commentCounter - 1
|
||||
transaction.update(postRef, { commentCounter: commentCount })
|
||||
if (commentCount > 3) {
|
||||
let comments = postDoc.data().comments
|
||||
if (!comments) {
|
||||
comments = {}
|
||||
}
|
||||
let parsedComments = {}
|
||||
Object.keys(postDoc.data().comments).map((id) => {
|
||||
if (id !== commentId) {
|
||||
_.merge(parsedComments, { [id]: { ...comments[id] } })
|
||||
}
|
||||
})
|
||||
transaction.update(postRef, { comments: { ...parsedComments}})
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code,error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
5
src/data/firestoreClient/services/comments/index.ts
Normal file
5
src/data/firestoreClient/services/comments/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { CommentService } from './CommentService'
|
||||
|
||||
export {
|
||||
CommentService
|
||||
}
|
||||
16
src/data/firestoreClient/services/common/CommonService.ts
Normal file
16
src/data/firestoreClient/services/common/CommonService.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth } from 'data/firebaseClient'
|
||||
|
||||
import { SocialError } from 'core/domain/common'
|
||||
import { ICommonService } from 'core/services/common'
|
||||
|
||||
/**
|
||||
* Firbase common service
|
||||
*
|
||||
* @export
|
||||
* @class CommonService
|
||||
* @implements {ICommonService}
|
||||
*/
|
||||
export class CommonService implements ICommonService {
|
||||
|
||||
}
|
||||
5
src/data/firestoreClient/services/common/index.ts
Normal file
5
src/data/firestoreClient/services/common/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { CommonService } from './CommonService'
|
||||
|
||||
export {
|
||||
CommonService
|
||||
}
|
||||
41
src/data/firestoreClient/services/files/StorageService.ts
Normal file
41
src/data/firestoreClient/services/files/StorageService.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { storageRef } from 'data/firestoreClient'
|
||||
import { IStorageService } from 'core/services/files'
|
||||
import { FileResult } from 'models/files/fileResult'
|
||||
|
||||
export class StorageService implements IStorageService {
|
||||
|
||||
/**
|
||||
* Upload image on the server
|
||||
* @param {file} file
|
||||
* @param {string} fileName
|
||||
*/
|
||||
public uploadFile = (file: any, fileName: string, progress: (percentage: number, status: boolean) => void) => {
|
||||
|
||||
return new Promise<FileResult>((resolve, reject) => {
|
||||
// Create a storage refrence
|
||||
let storegeFile = storageRef.child(`images/${fileName}`)
|
||||
|
||||
// Upload file
|
||||
let task = storegeFile.put(file)
|
||||
task.then((result) => {
|
||||
resolve(new FileResult(result.downloadURL!,result.metadata.fullPath))
|
||||
}).catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
|
||||
// Upload storage bar
|
||||
task.on('state_changed', (snapshot: any) => {
|
||||
let percentage: number = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
|
||||
progress(percentage, true)
|
||||
}, (error) => {
|
||||
console.log('========== Upload Image ============')
|
||||
console.log(error)
|
||||
console.log('====================================')
|
||||
|
||||
}, () => {
|
||||
progress(100, false)
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
5
src/data/firestoreClient/services/files/index.ts
Normal file
5
src/data/firestoreClient/services/files/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { StorageService } from './StorageService'
|
||||
|
||||
export {
|
||||
StorageService
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import { FileResult } from 'models/files/fileResult'
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth, storageRef, db } from 'data/firestoreClient'
|
||||
|
||||
import { SocialError } from 'core/domain/common'
|
||||
import { IImageGalleryService } from 'core/services/imageGallery'
|
||||
import { Image } from 'core/domain/imageGallery'
|
||||
import { IStorageService } from 'core/services/files'
|
||||
import { IServiceProvider, ServiceProvide } from 'core/factories'
|
||||
|
||||
/**
|
||||
* Firbase image gallery service
|
||||
*
|
||||
* @export
|
||||
* @class ImageGalleryService
|
||||
* @implements {IImageGalleryService}
|
||||
*/
|
||||
export class ImageGalleryService implements IImageGalleryService {
|
||||
|
||||
private readonly storageService: IStorageService
|
||||
private readonly serviceProvider: IServiceProvider
|
||||
|
||||
constructor () {
|
||||
this.serviceProvider = new ServiceProvide()
|
||||
this.storageService = this.serviceProvider.createStorageService()
|
||||
}
|
||||
|
||||
public getImageGallery: (userId: string)
|
||||
=> Promise<Image[]> = (userId) => {
|
||||
return new Promise<Image[]>((resolve,reject) => {
|
||||
let imagesRef = db.doc(`users/${userId}`).collection(`images`)
|
||||
|
||||
imagesRef.get().then((snapshot) => {
|
||||
let parsedData: Image[] = []
|
||||
snapshot.forEach((result) => {
|
||||
parsedData.push({
|
||||
id: result.id,
|
||||
...result.data() as Image
|
||||
})
|
||||
})
|
||||
resolve(parsedData)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
public saveImage: (userId: string, image: Image)
|
||||
=> Promise<string> = (userId, image) => {
|
||||
return new Promise<string>((resolve,reject) => {
|
||||
|
||||
let imageRef = db.doc(`users/${userId}`).collection(`images`).add(image)
|
||||
imageRef.then((result) => {
|
||||
resolve(result.id!)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
public deleteImage: (userId: string, imageId: string)
|
||||
=> Promise<void> = (userId, imageId) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
const batch = db.batch()
|
||||
const imageRef = db.doc(`users/${userId}/images/${imageId}`)
|
||||
|
||||
batch.delete(imageRef)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
public uploadImage: (image: any, imageName: string, progressCallback: (percentage: number, status: boolean) => void)
|
||||
=> Promise<FileResult> = (image, imageName, progressCallback) => {
|
||||
return new Promise<FileResult>((resolve,reject) => {
|
||||
this.storageService.uploadFile(image,imageName,progressCallback)
|
||||
.then((result: FileResult) => {
|
||||
resolve(result)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public downloadImage: (fileName: string)
|
||||
=> Promise<string> = (fileName) => {
|
||||
return new Promise<string>((resolve,reject) => {
|
||||
|
||||
// Create a reference to the file we want to download
|
||||
let starsRef: any = storageRef.child(`images/${fileName}`)
|
||||
|
||||
// Get the download URL
|
||||
starsRef.getDownloadURL().then((url: string) => {
|
||||
resolve(url)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
5
src/data/firestoreClient/services/imageGallery/index.ts
Normal file
5
src/data/firestoreClient/services/imageGallery/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { ImageGalleryService } from './ImageGalleryService'
|
||||
|
||||
export {
|
||||
ImageGalleryService
|
||||
}
|
||||
24
src/data/firestoreClient/services/index.ts
Normal file
24
src/data/firestoreClient/services/index.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { AuthorizeService } from './authorize'
|
||||
import { CircleService } from './circles'
|
||||
import { CommentService } from './comments'
|
||||
import { CommonService } from './common'
|
||||
import { ImageGalleryService } from './imageGallery'
|
||||
import { NotificationService } from './notifications'
|
||||
import { PostService } from './posts'
|
||||
import { UserService } from './users'
|
||||
import { VoteService } from './votes'
|
||||
import { StorageService } from './files'
|
||||
|
||||
export {
|
||||
AuthorizeService,
|
||||
CircleService,
|
||||
CommentService,
|
||||
CommonService,
|
||||
ImageGalleryService,
|
||||
NotificationService,
|
||||
PostService,
|
||||
UserService,
|
||||
VoteService,
|
||||
StorageService
|
||||
|
||||
}
|
||||
5
src/data/firestoreClient/services/notifications/index.ts
Normal file
5
src/data/firestoreClient/services/notifications/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { NotificationService } from './NotificationService'
|
||||
|
||||
export {
|
||||
NotificationService
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth, db } from 'data/firestoreClient'
|
||||
|
||||
import { SocialError } from 'core/domain/common'
|
||||
import { Notification } from 'core/domain/notifications'
|
||||
import { INotificationService } from 'core/services/notifications'
|
||||
|
||||
/**
|
||||
* Firbase notification service
|
||||
*
|
||||
* @export
|
||||
* @class NotificationService
|
||||
* @implements {INotificationService}
|
||||
*/
|
||||
export class NotificationService implements INotificationService {
|
||||
public addNotification: (notification: Notification)
|
||||
=> Promise<void> = (notification: Notification) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
db.doc(`users/${notification.notifyRecieverUserId}`).collection(`notifications`)
|
||||
.add(notification)
|
||||
.then(() => {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public getNotifications: (userId: string, callback: (resultNotifications: {[notifyId: string]: Notification}) => void)
|
||||
=> void = (userId,callback) => {
|
||||
let notificationsRef = db.doc(`users/${userId}`).collection('notifications')
|
||||
notificationsRef.onSnapshot((snapshot) => {
|
||||
let parsedData: { [notifyId: string]: Notification } = {}
|
||||
snapshot.forEach((result) => {
|
||||
parsedData[result.id] = {
|
||||
id: result.id,
|
||||
...result.data() as Notification
|
||||
}
|
||||
})
|
||||
callback(parsedData)
|
||||
})
|
||||
}
|
||||
|
||||
public deleteNotification: (notificationId: string, userId: string)
|
||||
=> Promise < void > = (notificationId, userId) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const batch = db.batch()
|
||||
const notificationRef = db.doc(`users/${userId}/notifications/${notificationId}`)
|
||||
|
||||
batch.delete(notificationRef)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public setSeenNotification: (notificationId: string, userId: string, notification: Notification)
|
||||
=> Promise <void> = (notificationId, userId, notification) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const batch = db.batch()
|
||||
const notificationRef = db.doc(`users/${userId}/notifications/${notificationId}`)
|
||||
|
||||
batch.update(notificationRef,notification)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
105
src/data/firestoreClient/services/posts/PostService.ts
Normal file
105
src/data/firestoreClient/services/posts/PostService.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth, db } from 'data/firestoreClient'
|
||||
|
||||
import { SocialError } from 'core/domain/common'
|
||||
import { Post } from 'core/domain/posts'
|
||||
import { IPostService } from 'core/services/posts'
|
||||
import { IServiceProvider } from 'core/factories'
|
||||
import { ICommentService } from 'core/services/comments'
|
||||
import { ServiceProvide } from 'core/factories/serviceProvide'
|
||||
|
||||
/**
|
||||
* Firbase post service
|
||||
*
|
||||
* @export
|
||||
* @class PostService
|
||||
* @implements {IPostService}
|
||||
*/
|
||||
export class PostService implements IPostService {
|
||||
|
||||
public addPost: (post: Post)
|
||||
=> Promise<string> = (post) => {
|
||||
return new Promise<string>((resolve,reject) => {
|
||||
let postRef = db.collection(`posts`).add(post)
|
||||
postRef.then((result) => {
|
||||
resolve(result.id)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code,error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public updatePost: (post: Post)
|
||||
=> Promise<void> = (post) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
const batch = db.batch()
|
||||
const notificationRef = db.doc(`posts/${post.id}`)
|
||||
|
||||
batch.update(notificationRef, post)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code,error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public deletePost: (postId: string)
|
||||
=> Promise<void> = (postId) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
const batch = db.batch()
|
||||
const notificationRef = db.doc(`posts/${postId}`)
|
||||
|
||||
batch.delete(notificationRef)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code,error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public getPosts: (userId: string)
|
||||
=> Promise<{ [postId: string]: Post }> = (userId) => {
|
||||
return new Promise<{ [postId: string]: Post }>((resolve,reject) => {
|
||||
|
||||
let postsRef = db.collection(`posts`).where('ownerUserId', '==', userId)
|
||||
postsRef.get().then((snapshot) => {
|
||||
let parsedData: { [postId: string]: Post } = {}
|
||||
snapshot.forEach((result) => {
|
||||
parsedData[result.id] = {
|
||||
id: result.id,
|
||||
...result.data() as Post
|
||||
}
|
||||
})
|
||||
resolve(parsedData)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code,error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public getPostById: (postId: string)
|
||||
=> Promise<Post> = (postId) => {
|
||||
return new Promise<Post>((resolve,reject) => {
|
||||
|
||||
let postsRef = db.doc(`posts/${postId}`)
|
||||
postsRef.get().then((snapshot) => {
|
||||
let newPost = snapshot.data() || {}
|
||||
let post: Post = {
|
||||
id: postId,
|
||||
...newPost
|
||||
}
|
||||
resolve(post)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code,error.message))
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
5
src/data/firestoreClient/services/posts/index.ts
Normal file
5
src/data/firestoreClient/services/posts/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { PostService } from './PostService'
|
||||
|
||||
export {
|
||||
PostService
|
||||
}
|
||||
92
src/data/firestoreClient/services/users/UserService.ts
Normal file
92
src/data/firestoreClient/services/users/UserService.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth, db } from 'data/firestoreClient'
|
||||
import firebase from 'firebase'
|
||||
import moment from 'moment'
|
||||
|
||||
import { SocialError } from 'core/domain/common'
|
||||
import { Profile, UserProvider } from 'core/domain/users'
|
||||
import { IUserService } from 'core/services/users'
|
||||
|
||||
/**
|
||||
* Firbase user service
|
||||
*
|
||||
* @export
|
||||
* @class UserService
|
||||
* @implements {IUserService}
|
||||
*/
|
||||
export class UserService implements IUserService {
|
||||
|
||||
public getUserProfile: (userId: string)
|
||||
=> Promise<Profile> = (userId) => {
|
||||
return new Promise<Profile>((resolve, reject) => {
|
||||
let userProfileRef = db.doc(`userInfo/${userId}`)
|
||||
userProfileRef.get().then((snapshot) => {
|
||||
if (!snapshot.exists) {
|
||||
this.getUserProviderData(userId).then((providerData: UserProvider) => {
|
||||
const {avatar,fullName, email} = providerData
|
||||
const userProfile = new Profile(avatar,fullName,'','',moment().unix(),email)
|
||||
resolve(userProfile)
|
||||
this.updateUserProfile(userId,userProfile)
|
||||
})
|
||||
} else {
|
||||
resolve(snapshot.data() as Profile)
|
||||
}
|
||||
|
||||
})
|
||||
.catch((error: any) => reject(new SocialError(error.code, 'firestore/getUserProfile :' + error.message)))
|
||||
})
|
||||
}
|
||||
|
||||
public updateUserProfile: (userId: string, profile: Profile)
|
||||
=> Promise<void> = (userId, profile) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const batch = db.batch()
|
||||
const profileRef = db.doc(`userInfo/${userId}`)
|
||||
|
||||
batch.set(profileRef,{...profile})
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
})
|
||||
.catch((error: any) => reject(new SocialError(error.code, 'firestore/updateUserProfile' + error.message)))
|
||||
})
|
||||
}
|
||||
public getUsersProfile: (userId: string, lastKey?: string, numberOfItems?: number)
|
||||
=> Promise<{ [userId: string]: Profile }> = (userId, lastKey, numberOfItems = 15) => {
|
||||
return new Promise<{ [userId: string]: Profile }>((resolve, reject) => {
|
||||
let usersProfileRef: firebase.firestore.Query
|
||||
if (lastKey) {
|
||||
usersProfileRef = db.collection(`userInfo`).orderBy('creationDate', 'desc').startAfter(lastKey!).limit(numberOfItems)
|
||||
} else {
|
||||
usersProfileRef = db.collection(`userInfo`).orderBy('creationDate', 'desc')
|
||||
}
|
||||
|
||||
usersProfileRef.get().then((snapshot) => {
|
||||
let parsedData: { [userId: string]: Profile } = {}
|
||||
snapshot.forEach((result) => {
|
||||
parsedData[result.id] = {
|
||||
...result.data() as Profile
|
||||
}
|
||||
})
|
||||
resolve(parsedData)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private getUserProviderData = (userId: string) => {
|
||||
return new Promise<UserProvider>((resolve,reject) => {
|
||||
let userProviderRef = db.doc(`userProviderInfo/${userId}`)
|
||||
userProviderRef.get().then((snapshot) => {
|
||||
let userProvider: UserProvider = snapshot.data() as UserProvider || {}
|
||||
resolve(userProvider)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code, 'firestore/getUserProviderData' + error.message))
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
5
src/data/firestoreClient/services/users/index.ts
Normal file
5
src/data/firestoreClient/services/users/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { UserService } from './UserService'
|
||||
|
||||
export {
|
||||
UserService
|
||||
}
|
||||
106
src/data/firestoreClient/services/votes/VoteService.ts
Normal file
106
src/data/firestoreClient/services/votes/VoteService.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
// - Import react components
|
||||
import { firebaseRef, firebaseAuth, db } from 'data/firestoreClient'
|
||||
|
||||
import { SocialError } from 'core/domain/common'
|
||||
import { Vote } from 'core/domain/votes'
|
||||
import { IVoteService } from 'core/services/votes'
|
||||
|
||||
/**
|
||||
* Firbase vote service
|
||||
*
|
||||
* @export
|
||||
* @class VoteService
|
||||
* @implements {IVoteService}
|
||||
*/
|
||||
export class VoteService implements IVoteService {
|
||||
|
||||
public addVote: (vote: Vote)
|
||||
=> Promise<string> = (vote) => {
|
||||
return new Promise<string>((resolve,reject) => {
|
||||
const postRef = db.doc(`posts/${vote.postId}`)
|
||||
let voteRef = postRef.collection(`votes`)
|
||||
.add(vote)
|
||||
voteRef.then((result) => {
|
||||
resolve(result.id)
|
||||
/**
|
||||
* Add score
|
||||
*/
|
||||
db.runTransaction((transaction) => {
|
||||
return transaction.get(postRef).then((postDoc) => {
|
||||
if (postDoc.exists) {
|
||||
const post = postDoc.data()
|
||||
let {votes, score} = post
|
||||
if (!votes) {
|
||||
votes = {}
|
||||
}
|
||||
if (!score) {
|
||||
score = 0
|
||||
}
|
||||
const newScore = score + 1
|
||||
votes[vote.userId] = true
|
||||
transaction.update(postRef, { votes: { ...votes}, score: newScore })
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(new SocialError(error.code,error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
public getVotes: (postId: string)
|
||||
=> Promise<{ [postId: string]: { [voteId: string]: Vote } }> = (postId) => {
|
||||
return new Promise<{ [postId: string]: { [voteId: string]: Vote } }>((resolve,reject) => {
|
||||
let votesRef = db.doc(`posts/${postId}`).collection(`votes`)
|
||||
|
||||
votesRef.onSnapshot((snapshot) => {
|
||||
let parsedData: {[postId: string]: {[voteId: string]: Vote}} = {[postId]: {}}
|
||||
snapshot.forEach((result) => {
|
||||
parsedData[postId][result.id] = {
|
||||
id: result.id,
|
||||
...result.data() as Vote
|
||||
}
|
||||
})
|
||||
resolve(parsedData)
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
public deleteVote: (vote: Vote)
|
||||
=> Promise<void> = (vote) => {
|
||||
return new Promise<void>((resolve,reject) => {
|
||||
const batch = db.batch()
|
||||
const postRef = db.doc(`posts/${vote.postId}`)
|
||||
let voteRef = postRef.collection(`votes`).doc(vote.id!)
|
||||
|
||||
batch.delete(voteRef)
|
||||
batch.commit().then(() => {
|
||||
resolve()
|
||||
/**
|
||||
* Remove score
|
||||
*/
|
||||
db.runTransaction((transaction) => {
|
||||
return transaction.get(postRef).then((postDoc) => {
|
||||
if (postDoc.exists) {
|
||||
const post = postDoc.data()
|
||||
let {votes, score} = post
|
||||
if (!votes) {
|
||||
votes = {}
|
||||
}
|
||||
if (!score) {
|
||||
score = 0
|
||||
}
|
||||
const newScore = score + 1
|
||||
votes[vote.userId] = true
|
||||
transaction.update(postRef, { votes: { ...votes}, score: newScore })
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(new SocialError(error.code,error.message))
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
5
src/data/firestoreClient/services/votes/index.ts
Normal file
5
src/data/firestoreClient/services/votes/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { VoteService } from './VoteService'
|
||||
|
||||
export {
|
||||
VoteService
|
||||
}
|
||||
Reference in New Issue
Block a user