Image gallery has been resolved

This commit is contained in:
Qolzam
2017-11-11 11:02:37 +07:00
parent 7bbb1679ad
commit 9ffd6a1e40
23 changed files with 186 additions and 103 deletions

4
.gitignore vendored
View File

@@ -3,4 +3,6 @@ public/bundle.js
config/ config/
.vscode/ .vscode/
src/data/awsClient src/data/awsClient
src/components/AWS.tsx src/components/AWS.tsx
.firebaserc
firebase.json

View File

@@ -1,3 +1,4 @@
import { IStorageService } from 'core/services/files'
// - Import react componetns // - Import react componetns
import moment from 'moment' import moment from 'moment'
@@ -16,9 +17,11 @@ import FileAPI from 'api/FileAPI'
import { IServiceProvider, ServiceProvide } from 'core/factories' import { IServiceProvider, ServiceProvide } from 'core/factories'
import { IImageGalleryService } from 'core/services/imageGallery' import { IImageGalleryService } from 'core/services/imageGallery'
import { FileResult } from 'models/files/fileResult'
const serviceProvider: IServiceProvider = new ServiceProvide() const serviceProvider: IServiceProvider = new ServiceProvide()
const imageGalleryService: IImageGalleryService = serviceProvider.createImageGalleryService() const imageGalleryService: IImageGalleryService = serviceProvider.createImageGalleryService()
const storageService: IStorageService = serviceProvider.createStorageService()
/* _____________ UI Actions _____________ */ /* _____________ UI Actions _____________ */
@@ -101,16 +104,16 @@ export const dbDeleteImage = (id: string) => {
* @param {file} file * @param {file} file
* @param {string} fileName * @param {string} fileName
*/ */
export const dbUploadImage = (file: any, fileName: string) => { export const dbUploadImage = (image: any, imageName: string) => {
return (dispatch: any, getState: Function) => { return (dispatch: any, getState: Function) => {
return imageGalleryService return imageGalleryService
.uploadImage(file,fileName, (percentage: number) => { .uploadImage(image,imageName, (percentage: number) => {
dispatch(globalActions.progressChange(percentage, true)) dispatch(globalActions.progressChange(percentage, true))
}) })
.then(() => { .then((result: FileResult) => {
dispatch(globalActions.progressChange(100, false)) dispatch(globalActions.progressChange(100, false))
dispatch(dbSaveImage(fileName,'')) dispatch(dbSaveImage(result.fileURL,result.fileFullPath))
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {

View File

@@ -1,6 +1,3 @@
// - Import react component
import { storageRef } from 'data/firebaseClient'
// - Import actions // - Import actions
const isValidEmail = (email: string) => { const isValidEmail = (email: string) => {

View File

@@ -8,7 +8,7 @@ export interface IImageGalleryComponentProps {
* @type {(URL: string,fullPath: string)} * @type {(URL: string,fullPath: string)}
* @memberof IImageGalleryComponentProps * @memberof IImageGalleryComponentProps
*/ */
set?: (URL: string,fullPath: string) => void set: (URL: string,fullPath: string) => void
/** /**
* Delete an image * Delete an image
@@ -18,25 +18,18 @@ export interface IImageGalleryComponentProps {
deleteImage?: (imageId: string) => void deleteImage?: (imageId: string) => void
/** /**
* Save image in image gallery * Upload image to the server
* *
* @memberof IImageGalleryComponentProps * @memberof IImageGalleryComponentProps
*/ */
saveImageGallery?: (URL: string,fullPath: string) => void uploadImage?: (image: any, imageName: string) => any
/**
* Change progress state
*
* @memberof IImageGalleryComponentProps
*/
progressChange?: (percentage: number, status: boolean) => void
/** /**
* Close image gallery * Close image gallery
* *
* @memberof IImageGalleryComponentProps * @memberof IImageGalleryComponentProps
*/ */
close?: () => void close: () => void
/** /**
* List of image in image gallery * List of image in image gallery

View File

@@ -124,16 +124,8 @@ export class ImageGalleryComponent extends Component<IImageGalleryComponentProps
handleSendResizedImage = (event: any) => { handleSendResizedImage = (event: any) => {
const { resizedImage, fileName } = event.detail const { resizedImage, fileName } = event.detail
const {saveImageGallery, progressChange} = this.props const {uploadImage} = this.props
uploadImage(resizedImage,fileName)
FileAPI.uploadImage(resizedImage, fileName, (percent: number, status: boolean) => {
progressChange!(percent,status)
}).then((result) => {
/* Add image to image gallery */
saveImageGallery!(result.downloadURL,result.metadata.fullPath)
})
} }
/** /**
@@ -231,7 +223,7 @@ export class ImageGalleryComponent extends Component<IImageGalleryComponentProps
*/ */
const mapDispatchToProps = (dispatch: any, ownProps: IImageGalleryComponentProps) => { const mapDispatchToProps = (dispatch: any, ownProps: IImageGalleryComponentProps) => {
return { return {
saveImageGallery: (imageURL: string,imageFullPath: string) => dispatch(imageGalleryActions.dbSaveImage(imageURL,imageFullPath)), uploadImage: (image: any, imageName: string) => dispatch(imageGalleryActions.dbUploadImage(image,imageName)),
deleteImage: (id: string) => dispatch(imageGalleryActions.dbDeleteImage(id)), deleteImage: (id: string) => dispatch(imageGalleryActions.dbDeleteImage(id)),
progressChange : (percent: number,status: boolean) => dispatch(globalActions.progressChange(percent, status)) progressChange : (percent: number,status: boolean) => dispatch(globalActions.progressChange(percent, status))

View File

@@ -3,7 +3,6 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { Route, Switch, NavLink, withRouter, Redirect } from 'react-router-dom' import { Route, Switch, NavLink, withRouter, Redirect } from 'react-router-dom'
import { firebaseAuth, firebaseRef } from 'data/firebaseClient'
import { push } from 'react-router-redux' import { push } from 'react-router-redux'
import Snackbar from 'material-ui/Snackbar' import Snackbar from 'material-ui/Snackbar'
import LinearProgress from 'material-ui/LinearProgress' import LinearProgress from 'material-ui/LinearProgress'
@@ -16,6 +15,8 @@ import Setting from 'components/setting'
import MasterLoading from 'components/masterLoading' import MasterLoading from 'components/masterLoading'
import { IMasterComponentProps } from './IMasterComponentProps' import { IMasterComponentProps } from './IMasterComponentProps'
import { IMasterComponentState } from './IMasterComponentState' import { IMasterComponentState } from './IMasterComponentState'
import { ServiceProvide, IServiceProvider } from 'core/factories'
import { IAuthorizeService } from 'core/services/authorize'
// - Import actions // - Import actions
import { import {
@@ -36,9 +37,15 @@ import {
export class MasterComponent extends Component<IMasterComponentProps, IMasterComponentState> { export class MasterComponent extends Component<IMasterComponentProps, IMasterComponentState> {
static isPrivate = true static isPrivate = true
private readonly _serviceProvider: IServiceProvider
private readonly _authourizeService: IAuthorizeService
// Constructor // Constructor
constructor (props: IMasterComponentProps) { constructor (props: IMasterComponentProps) {
super(props) super(props)
this._serviceProvider = new ServiceProvide()
this._authourizeService = this._serviceProvider.createAuthorizeService()
this.state = { this.state = {
loading: true, loading: true,
authed: false, authed: false,
@@ -73,7 +80,7 @@ export class MasterComponent extends Component<IMasterComponentProps, IMasterCom
componentWillMount () { componentWillMount () {
firebaseAuth().onAuthStateChanged((user: any) => { this._authourizeService.onAuthStateChanged((user: any) => {
if (user) { if (user) {
this.props.login(user) this.props.login(user)

View File

@@ -27,6 +27,7 @@ import Dialog from 'material-ui/Dialog'
import IconButton from 'material-ui/IconButton' import IconButton from 'material-ui/IconButton'
import MoreVertIcon from 'material-ui/svg-icons/navigation/more-vert' import MoreVertIcon from 'material-ui/svg-icons/navigation/more-vert'
import IconMenu from 'material-ui/IconMenu' import IconMenu from 'material-ui/IconMenu'
import reactStringReplace from 'react-string-replace' import reactStringReplace from 'react-string-replace'
// - Import app components // - Import app components

View File

@@ -1,12 +1,15 @@
import { IAuthorizeService } from 'services/authorize/IAuthorizeService' import {
import { ICircleService } from 'services/circles' IAuthorizeService,
import { ICommentService } from 'core/services/comments' ICircleService,
import { ICommonService } from 'services/common' ICommentService,
import { IImageGalleryService } from 'services/imageGallery' ICommonService,
import { INotificationService } from 'services/notifications' IImageGalleryService,
import { IPostService } from 'services/posts' INotificationService,
import { IUserService } from 'services/users' IPostService,
import { IVoteService } from 'services/votes' IUserService,
IVoteService,
IStorageService
} from 'core/services'
export interface IServiceProvider { export interface IServiceProvider {
@@ -73,4 +76,11 @@ export interface IServiceProvider {
*/ */
createVoteService: () => IVoteService createVoteService: () => IVoteService
/**
* Create instant for Vote Service
*
* @memberof ServiceProvide
*/
createStorageService: () => IStorageService
} }

View File

@@ -10,7 +10,8 @@ import {
INotificationService, INotificationService,
IPostService, IPostService,
IUserService, IUserService,
IVoteService IVoteService,
IStorageService
} from 'core/services' } from 'core/services'
//#endregion //#endregion
@@ -27,7 +28,8 @@ import {
NotificationService, NotificationService,
PostService, PostService,
UserService, UserService,
VoteService VoteService,
StorageService
} from 'data/firebaseClient/services' } from 'data/firebaseClient/services'
//#endregion //#endregion
@@ -115,4 +117,13 @@ export class ServiceProvide implements IServiceProvider {
return new VoteService() return new VoteService()
} }
/**
* Create instant for Vote Service
*
* @memberof ServiceProvide
*/
createStorageService: () => IStorageService = () => {
return new StorageService()
}
} }

View File

@@ -35,4 +35,10 @@ export interface IAuthorizeService {
*/ */
registerUser: (user: User) => Promise<RegisterUserResult> registerUser: (user: User) => Promise<RegisterUserResult>
} /**
* On user authorization changed event
*
* @memberof IAuthorizeService
*/
onAuthStateChanged: (callBack: (user: User) => void)
}

View File

@@ -0,0 +1,11 @@
import { FileResult } from 'models/files/fileResult'
export interface IStorageService {
/**
* Storage file service
*
* @memberof IStorageService
*/
uploadFile: (file: any, fileName: string, progress: (percentage: number, status: boolean) => void) => Promise<FileResult>
}

View File

@@ -0,0 +1,5 @@
import { IStorageService } from './IStorageService'
export {
IStorageService
}

View File

@@ -1,3 +1,4 @@
import { FileResult } from 'models/files/fileResult'
import { User } from 'core/domain/users' import { User } from 'core/domain/users'
import { Image } from 'core/domain/imageGallery' import { Image } from 'core/domain/imageGallery'
@@ -11,6 +12,6 @@ export interface IImageGalleryService {
getImageGallery: (userId: string) => Promise<Image[]> getImageGallery: (userId: string) => Promise<Image[]>
saveImage: (userId: string, image: Image) => Promise<string> saveImage: (userId: string, image: Image) => Promise<string>
deleteImage: (userId: string, imageId: string) => Promise<void> deleteImage: (userId: string, imageId: string) => Promise<void>
uploadImage: (file: any, fileName: string, progressCallback: Function) => Promise<void> uploadImage: (file: any, fileName: string, progressCallback: (percentage: number, status: boolean) => void) => Promise<FileResult>
downloadImage: (fileName: string) => Promise<string> downloadImage: (fileName: string) => Promise<string>
} }

View File

@@ -7,6 +7,7 @@ import { INotificationService } from './notifications'
import { IPostService } from './posts' import { IPostService } from './posts'
import { IUserService } from './users' import { IUserService } from './users'
import { IVoteService } from './votes' import { IVoteService } from './votes'
import { IStorageService } from './files'
export { export {
IAuthorizeService, IAuthorizeService,
@@ -17,5 +18,6 @@ export {
INotificationService, INotificationService,
IPostService, IPostService,
IUserService, IUserService,
IVoteService IVoteService,
IStorageService
} }

View File

@@ -103,4 +103,13 @@ export class AuthorizeService implements IAuthorizeService {
}) })
} }
/**
* On user authorization changed event
*
* @memberof IAuthorizeService
*/
onAuthStateChanged: (callBack: (user: User) => void) => any = (callBack) => {
firebaseAuth().onAuthStateChanged(callBack)
}
} }

View File

@@ -0,0 +1,41 @@
import { storageRef } from 'data/firebaseClient'
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)
})
})
}
}

View File

@@ -0,0 +1,5 @@
import { StorageService } from './StorageService'
export {
StorageService
}

View File

@@ -1,9 +1,12 @@
import { FileResult } from 'models/files/fileResult'
// - Import react components // - Import react components
import { firebaseRef, firebaseAuth, storageRef } from 'data/firebaseClient' import { firebaseRef, firebaseAuth, storageRef } from 'data/firebaseClient'
import { SocialError } from 'core/domain/common' import { SocialError } from 'core/domain/common'
import { IImageGalleryService } from 'core/services/imageGallery' import { IImageGalleryService } from 'core/services/imageGallery'
import { Image } from 'core/domain/imageGallery' import { Image } from 'core/domain/imageGallery'
import { IStorageService } from 'core/services/files'
import { IServiceProvider, ServiceProvide } from 'core/factories'
/** /**
* Firbase image gallery service * Firbase image gallery service
@@ -14,6 +17,14 @@ import { Image } from 'core/domain/imageGallery'
*/ */
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) public getImageGallery: (userId: string)
=> Promise<Image[]> = (userId) => { => Promise<Image[]> = (userId) => {
return new Promise<Image[]>((resolve,reject) => { return new Promise<Image[]>((resolve,reject) => {
@@ -69,24 +80,15 @@ export class ImageGalleryService implements IImageGalleryService {
}) })
} }
public uploadImage: (file: any, fileName: string, progressCallback: Function) public uploadImage: (image: any, imageName: string, progressCallback: (percentage: number, status: boolean) => void)
=> Promise<void> = (file, fileName, progressCallback) => { => Promise<FileResult> = (image, imageName, progressCallback) => {
return new Promise<void>((resolve,reject) => { return new Promise<FileResult>((resolve,reject) => {
this.storageService.uploadFile(image,imageName,progressCallback)
let storegeFile = storageRef.child(`images/${fileName}`) .then((result: FileResult) => {
resolve(result)
// Upload file })
let task = storegeFile.put(file) .catch((error: any) => {
// Upload storage bar
task.on('state_changed', (snapshot: any) => {
let percentage = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
progressCallback(percentage)
}, (error: any) => {
reject(new SocialError(error.code, error.message)) reject(new SocialError(error.code, error.message))
}, () => {
resolve()
}) })
}) })
} }

View File

@@ -7,6 +7,7 @@ import { NotificationService } from './notifications'
import { PostService } from './posts' import { PostService } from './posts'
import { UserService } from './users' import { UserService } from './users'
import { VoteService } from './votes' import { VoteService } from './votes'
import { StorageService } from './files'
export { export {
AuthorizeService, AuthorizeService,
@@ -17,5 +18,7 @@ export {
NotificationService, NotificationService,
PostService, PostService,
UserService, UserService,
VoteService VoteService,
StorageService
} }

View File

@@ -17,7 +17,7 @@ export class PostService implements IPostService {
public addPost: (userId: string, post: Post) public addPost: (userId: string, post: Post)
=> Promise<string> = (userId, post) => { => Promise<string> = (userId, post) => {
return new Promise<string>((resolve,reject) => { return new Promise<string>((resolve,reject) => {
let postRef: any = firebaseRef.child(`userPosts/${userId}/posts`).push(post) let postRef: any = firebaseRef.child(`users/${userId}/posts`).push(post)
postRef.then(() => { postRef.then(() => {
resolve(postRef.key) resolve(postRef.key)
}) })
@@ -31,7 +31,7 @@ export class PostService implements IPostService {
=> Promise<void> = (userId, postId, post) => { => Promise<void> = (userId, postId, post) => {
return new Promise<void>((resolve,reject) => { return new Promise<void>((resolve,reject) => {
let updates: any = {} let updates: any = {}
updates[`userPosts/${userId}/posts/${postId}`] = post updates[`users/${userId}/posts/${postId}`] = post
firebaseRef.update(updates).then(() => { firebaseRef.update(updates).then(() => {
resolve() resolve()
}) })
@@ -45,7 +45,7 @@ export class PostService implements IPostService {
=> Promise<void> = (userId, postId) => { => Promise<void> = (userId, postId) => {
return new Promise<void>((resolve,reject) => { return new Promise<void>((resolve,reject) => {
let updates: any = {} let updates: any = {}
updates[`userPosts/${userId}/posts/${postId}`] = null updates[`users/${userId}/posts/${postId}`] = null
firebaseRef.update(updates).then(() => { firebaseRef.update(updates).then(() => {
resolve() resolve()
}) })
@@ -59,7 +59,7 @@ export class PostService implements IPostService {
=> Promise<{ [postId: string]: Post }> = (userId) => { => Promise<{ [postId: string]: Post }> = (userId) => {
return new Promise<{ [postId: string]: Post }>((resolve,reject) => { return new Promise<{ [postId: string]: Post }>((resolve,reject) => {
let postsRef: any = firebaseRef.child(`userPosts/${userId}/posts`) let postsRef: any = firebaseRef.child(`users/${userId}/posts`)
postsRef.once('value').then((snapshot: any) => { postsRef.once('value').then((snapshot: any) => {
let posts: any = snapshot.val() || {} let posts: any = snapshot.val() || {}
let parsedPosts: { [postId: string]: Post } = {} let parsedPosts: { [postId: string]: Post } = {}
@@ -82,7 +82,7 @@ export class PostService implements IPostService {
=> Promise<Post> = (userId, postId) => { => Promise<Post> = (userId, postId) => {
return new Promise<Post>((resolve,reject) => { return new Promise<Post>((resolve,reject) => {
let postsRef: any = firebaseRef.child(`userPosts/${userId}/posts/${postId}`) let postsRef: any = firebaseRef.child(`users/${userId}/posts/${postId}`)
postsRef.once('value').then((snapshot: any) => { postsRef.once('value').then((snapshot: any) => {
let newPost = snapshot.val() || {} let newPost = snapshot.val() || {}

View File

@@ -0,0 +1,15 @@
export class FileResult {
constructor (private _fileURL: string, private _fileFullPath: string) {
}
public get fileURL (): string {
return this._fileURL
}
public get fileFullPath (): string {
return this._fileFullPath
}
}

View File

@@ -0,0 +1 @@
export { FileResult } from './fileResult'

View File

@@ -1,34 +0,0 @@
// - Import react components
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
let expect = require('expect')
import firebase, {firebaseRef} from 'src/firebaseClient'
let authorizeActions = require('authorizeActions')
import * as types from 'actionTypes'
let createMockStore = configureMockStore([thunk])
describe('AuthorizeActions', () => {
it('should generate login action', () => {
const uid = 'UID123456'
let action = {
type: types.LOGIN,
authed: true,
uid
}
let res = authorizeActions.login(action.uid)
expect(res).toEqual(action)
})
it('should generate logout action', () => {
let action = {
type: types.LOGOUT
}
let res = authorizeActions.logout()
expect(res).toEqual(action)
})
})