Skip to content

Commit 07315a1

Browse files
TWHousexta13
authored andcommitted
Feature/#154115334 (#206)
* feature: use FormData to send file to api [#154115334] * feature: use multer to save upload picture [#154115334] * Minio-server and upload project image * feature: upload picture to s3 [#154115334] * feature: add timestamp to filename [#154115334] * feature: save imageUrl to database [#154115334] * feature: use project.imageUrl for project image [#154115334] * fix: allow reading image from s3 without credentials [#154115334] * style: replace require with import [#154115334]
1 parent c4f9c7c commit 07315a1

File tree

9 files changed

+306
-260
lines changed

9 files changed

+306
-260
lines changed

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ export DB_USER=user
22
export DB_PASS=pass
33
export NODE_ENV=dev
44
export DB_URL=127.0.0.1
5-
export DEBUG=Rollbar:*
5+
export DEBUG=Rollbar:*

client/actions/project/index.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ export default class ProjectActionCreator {
8080
}
8181

8282
static async uploadImage (file, apiOptions) {
83-
const url = await projectsApiClient.getPresignedUrlForProjectImage(apiOptions, file.name)
83+
const filename = file.name.replace(/(\.[\w\d_-]+)$/i, Date.now() + '$1')
84+
const url = await projectsApiClient.getPresignedUrlForProjectImage(apiOptions, filename)
8485
await projectsApiClient.uploadImage(apiOptions, url, file)
86+
return filename
8587
}
8688

8789
static createProject (projectName, causes, technologies, organization, file) {
@@ -91,9 +93,9 @@ export default class ProjectActionCreator {
9193
try {
9294
const state = getState()
9395
const apiOptions = apiOptionsFromState(state)
94-
await ProjectActionCreator.uploadImage(file, apiOptions)
96+
const filename = await ProjectActionCreator.uploadImage(file, apiOptions)
9597
await projectsApiClient.createProject(apiOptions, projectName, causes,
96-
technologies, organization)
98+
technologies, organization, filename)
9799
dispatch({type: actionTypes.CREATE_PROJECT_SUCCESS})
98100
dispatch(push('/'))
99101
} catch (e) {

client/api/projects.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ const projectsApiClient = {
1515
return apiRequest.get('/projects', apiOptions, query)
1616
},
1717

18-
async createProject (apiOptions, name, causes, technologies, organization) {
18+
async createProject (apiOptions, name, causes, technologies, organization, imageUrl) {
1919
const options = {
2020
method: 'POST',
2121
headers: {
2222
'Content-Type': 'application/json'
2323
},
24-
body: JSON.stringify({ name, causes, technologies, organization })
24+
body: JSON.stringify({ name, causes, technologies, organization, imageUrl })
2525
}
2626
return fetch('/api/projects/', options)
2727
},

client/components/Project/Project.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types'
44
import Chip from 'material-ui/Chip'
55
import {Link} from 'react-router-dom'
66
import styles from './Project.scss'
7+
import logo from '../../images/logo.png'
78

89
class Project extends Component {
910
constructor (props) {
@@ -61,7 +62,7 @@ class Project extends Component {
6162
return (
6263
<div className={projectClasses}
6364
onClick={this.handleClick.bind(this)}>
64-
<img className={styles.image} src={project.image || require('../../images/logo.png')} />
65+
<img className={styles.image} src={project.imageUrl || logo }/>
6566
<div className={styles.projectContent}>
6667
<div className={styles.projectTitle}>
6768
<Link to={`/projects/${project.id}`}>{project.name}</Link>

client/components/UploadDropzone/UploadDropzone.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import '../../scss/partials/partials';
1+
@import '../../scss/partials/_partials';
22

33
.dropzone {
44
@extend %hover;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,4 @@
115115
],
116116
"babel": "inherit"
117117
}
118-
}
118+
}

server/database/models/Project.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const ProjectSchema = mongoose.Schema({
88
name: String,
99
role: String,
1010
email: String,
11+
imageUrl: String,
1112
causes: [{
1213
type: String,
1314
enum: ['Animal', 'Environment', 'International NGO', 'Health', 'Education', 'Arts & Culture', 'Other']
@@ -29,6 +30,7 @@ ProjectSchema.methods.toJSON = function () {
2930
name: this.name,
3031
role: this.role,
3132
email: this.email,
33+
imageUrl: this.imageUrl,
3234
causes: this.causes,
3335
technologies: this.technologies,
3436
applications: this.applications,

server/routes/controllers/projects.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import bindFunctions from '../../lib/bindFunctions'
22
import ProjectModel from '../../database/models/Project'
33
import { NotFoundError, RequestError } from '../../lib/errors'
44
import { presignedPutObject, createBucketIfNecessary } from '../../lib/minio'
5+
import { minioConfig } from '../../config'
6+
7+
const { client } = minioConfig
58

69
const projectsBucket = 'projects'
710

@@ -36,6 +39,7 @@ export default {
3639

3740
async createProject (req, res, next) {
3841
const project = new this.Projects(req.body)
42+
project.imageUrl = `${client.protocol}//${client.host}:${client.port}/${projectsBucket}/${project.imageUrl}`
3943
const newProject = await project.save()
4044

4145
return res.status(200).json(newProject.toJSON())

0 commit comments

Comments
 (0)