Created
February 5, 2020 20:13
-
-
Save DDavis1025/5e76f6689b9b2a210b6d1fafb3dbd541 to your computer and use it in GitHub Desktop.
Downloading songs to a list and album's input fields to a database
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from "react"; | |
import ReactDOM from "react-dom"; | |
import styled from 'styled-components'; | |
import { Delete } from 'styled-icons/typicons/Delete'; | |
import Downloaded from './downloaded'; | |
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; | |
import { ButtonToggle } from "reactstrap"; | |
import { Container, Row, Col } from 'reactstrap'; | |
const reorder = (list, startIndex, endIndex) => { | |
const result = Array.from(list); | |
const [removed] = result.splice(startIndex, 1); | |
result.splice(endIndex, 0, removed); | |
return result; | |
}; | |
const grid = 8; | |
const getItemStyle = (isDragging, draggableStyle) => ({ | |
userSelect: "none", | |
padding: grid * 2, | |
margin: `0 0 ${grid}px 0`, | |
background: isDragging ? "blue" : "white", | |
...draggableStyle | |
}); | |
const getListStyle = isDraggingOver => ({ | |
background: isDraggingOver ? "lightgrey" : "lightgrey", | |
padding: grid, | |
width: 700, | |
}); | |
const Handle = styled.div` | |
width: 20px; | |
height: 20px; | |
margin-top: 7.5px; | |
background-color: gray; | |
border-radius: 4px; | |
float: left; | |
` | |
const LIDelete = styled(Delete)` | |
width: 20px; | |
height: 20px; | |
color: gray; | |
float: right; | |
margin-top: -28px; | |
` | |
let id = 0; | |
let clicked = false; | |
class AddAlbum extends Component { | |
constructor(props) { | |
super(props); | |
this.handleClick = this.handleClick.bind(this); | |
this.replaceClick = this.replaceClick.bind(this); | |
this.save = this.save.bind(this); | |
this.onDragEnd = this.onDragEnd.bind(this); | |
this.secondInputClick = this.secondInputClick.bind(this); | |
this.clickFileInput = this.clickFileInput.bind(this); | |
this.replaceInput = this.replaceInput.bind(this); | |
this.clickAddFiles = this.clickAddFiles.bind(this); | |
this.handleChange = this.handleChange.bind(this); | |
this.downloadChange = this.downloadChange.bind(this); | |
this.replaceInputRef = React.createRef(); | |
this.fileRef = React.createRef(); | |
this.inputRef = React.createRef(); | |
this.addFiles = React.createRef(); | |
this.removeItem = this.removeItem.bind(this) | |
this.state = { | |
files: [], | |
albums: [{title:"", date:"", description:""}], | |
}; | |
} | |
componentDidMount() { | |
const { match: { params} } = this.props; | |
console.log('COMPONENT HAS MOUNTED'); | |
let files = this.state.files; | |
let albums = this.state.albums; | |
fetch(`http://localhost:3000/albums/${params.albumId}/songs`) | |
.then((response) => | |
response.json()) | |
.then((data) => { | |
console.log(data) | |
this.setState({ files : data }); | |
console.log(this.state.files) | |
}).catch((error) => { | |
console.log("Error " + error) | |
}) | |
fetch(`http://localhost:3000/albums/${params.albumId}`) | |
.then((response) => | |
response.json()) | |
.then((data) => { | |
console.log(data) | |
console.log(this.state.albums) | |
if (data.length != 0) { | |
this.setState({albums: data}); | |
console.log(this.state) | |
} | |
console.log(this.state.albums) | |
console.log(this.state.albums[0].title) | |
}).catch((error) => { | |
console.log("Error " + error) | |
}) | |
} | |
downloadChange (event) { | |
const { name, value } = event.target; | |
this.setState(prevState => ({ | |
albums: [{...prevState.albums[0], [name]: value}] | |
})); | |
console.log(this.state) | |
} | |
changeCursor = (e) => { | |
e.target.style.background = 'red'; | |
} | |
handleClick = event => { | |
// Helper code to read file and return promise | |
const readFile = (file) => { | |
// const fileList = []; | |
const fileReader = new FileReader(); | |
// create the promise and return it | |
return new Promise((resolve, reject) => { | |
// if file reader has an error, report it | |
fileReader.onerror = (error) => { | |
reject({ error }) | |
} | |
// if success, resolve the promise | |
fileReader.onload = (e) => { | |
resolve({ | |
name: file.name.replace( /_|\.mp3/gi, " "), | |
link: e.target.result, | |
id: id++, | |
}) | |
} | |
// start reading the file | |
fileReader.readAsDataURL(file); | |
}) | |
} | |
// create all the file reader promises | |
// create an array from the files list and use map to generate | |
// an array of promises | |
const allReaders = Array.from(event.target.files).map(readFile) | |
// Now handle the array of promises we just created | |
Promise.all(allReaders) | |
.then(fileList => { | |
console.log(this.state.files) | |
// set the state that we have all the files | |
this.setState({ files: fileList }); | |
}) | |
.catch(error => { | |
console.error(error) | |
}); | |
} | |
replaceClick = event => { | |
const readFile = (file) => { | |
// const fileList = []; | |
const fileReader = new FileReader(); | |
// create the promise and return it | |
return new Promise((resolve, reject) => { | |
// if file reader has an error, report it | |
fileReader.onerror = (error) => { | |
reject({ error }) | |
} | |
// if success, resolve the promise | |
fileReader.onload = (e) => { | |
resolve({ | |
name: file.name.replace( /_|\.mp3/gi, " "), | |
link: e.target.result, | |
id: id++, | |
}) | |
} | |
// start reading the file | |
fileReader.readAsDataURL(file); | |
}) | |
} | |
// create all the file reader promises | |
// create an array from the files list and use map to generate | |
// an array of promises | |
const allReaders = Array.from(event.target.files).map(readFile) | |
// Now handle the array of promises we just created | |
Promise.all(allReaders) | |
.then(fileList => { | |
console.log(this.state.files) | |
// set the state that we have all the files | |
this.setState({ files: fileList }); | |
}) | |
.catch(error => { | |
console.error(error) | |
}); | |
clicked = true; | |
} | |
secondInputClick = event => { | |
// Helper code to read file and return promise | |
const readFile = (file) => { | |
// const fileList = []; | |
const fileReader = new FileReader(); | |
// create the promise and return it | |
return new Promise((resolve, reject) => { | |
// if file reader has an error, report it | |
fileReader.onerror = (error) => { | |
reject({ error }) | |
} | |
// if success, resolve the promise | |
fileReader.onload = (e) => { | |
resolve({ | |
name: file.name.replace( /_|\.mp3/gi, " "), | |
link: e.target.result, | |
id: id++, | |
}) | |
} | |
// start reading the file | |
fileReader.readAsDataURL(file); | |
}) | |
} | |
// create all the file reader promises | |
// create an array from the files list and use map to generate | |
// an array of promises | |
const allReaders = Array.from(event.target.files).map(readFile) | |
// Now handle the array of promises we just created | |
Promise.all(allReaders) | |
.then(fileList => { | |
console.log(this.state.files) | |
// set the state that we have all the files | |
this.setState(prevState => ({ ...prevState, files: [...prevState.files, ...fileList ]})); | |
}) | |
.catch(error => { | |
console.error(error) | |
}); | |
} | |
save(event) { | |
event.preventDefault(); | |
let files = this.state.files; | |
let albums = this.state.albums; | |
let other = this.props.title; | |
const { match: { params} } = this.props; | |
console.log(albums); | |
console.log(this.state) | |
let p = new Promise((resolve, reject) => { | |
resolve('Success'); | |
}) | |
.then(() => { | |
if(clicked === true) { | |
console.log("replace click"); | |
clicked = false; | |
let dltRequest = new Request(`http://localhost:3000/albums/${params.albumId}/songs/${id}`, { | |
method: 'DELETE', | |
headers: new Headers({ 'Content-Type': 'application/json' }), | |
}); | |
fetch(dltRequest) | |
.then((response) => | |
response.json()) | |
.then((data) => { | |
}) | |
.catch((error) => { | |
console.log(error) | |
}) | |
} | |
}).then(() => { | |
let data = files.map(( { name }, index, album_id ) => ({ name, index : index, album_id: params.albumId })); | |
let request = new Request(`http://localhost:3000/albums/${params.albumId}/songs`, { | |
method: 'POST', | |
headers: new Headers({ 'Content-Type': 'application/json' }), | |
body: JSON.stringify(data), | |
}); | |
fetch(request) | |
.then((response) => | |
response.json()) | |
.then((data) => { | |
}) | |
.catch((error) => { | |
console.log(error) | |
}) | |
let albumData = files.map(( id ) => ({ id: params.albumId })); | |
let albumRequest = new Request(`http://localhost:3000/albums/`, { | |
method: 'POST', | |
headers: new Headers({ 'Content-Type': 'application/json' }), | |
body: JSON.stringify(albumData), | |
}); | |
console.log(albums); | |
fetch(albumRequest) | |
.then((response) => | |
response.json()) | |
.then((data) => { | |
console.log(data) | |
}) | |
.catch((error) => { | |
console.log(error) | |
}) | |
let putRequest = new Request(`http://localhost:3000/songs/${id}`, { | |
method: 'PUT', | |
headers: new Headers({ 'Content-Type': 'application/json' }), | |
body: JSON.stringify(data) | |
}); | |
fetch(putRequest) | |
.then((response) => | |
response.json()) | |
.then((data) => { | |
}) | |
.catch((error) => { | |
console.log(error) | |
}) | |
let albumPutRequest = new Request(`http://localhost:3000/albums/${params.albumId}`, { | |
method: 'PUT', | |
headers: new Headers({ 'Content-Type': 'application/json' }), | |
body: JSON.stringify(albumData) | |
}); | |
fetch(albumPutRequest) | |
.then((response) => | |
response.json()) | |
.then((data) => { | |
}) | |
.catch((error) => { | |
console.log(error) | |
}) | |
}) | |
} | |
onDragEnd(result) { | |
if (!result.destination) { | |
return; | |
} | |
const files = reorder( | |
this.state.files, | |
result.source.index, | |
result.destination.index | |
); | |
this.setState({ | |
files | |
}); | |
} | |
removeItem = (index) => { | |
this.setState(({ files }) => ({ | |
files: files.filter((_, ind) => ind !== index) })); | |
} | |
clickFileInput() { | |
this.inputRef.current.click(); | |
} | |
replaceInput() { | |
this.replaceInputRef.current.click(); | |
} | |
clickAddFiles () { | |
this.addFiles.current.click(); | |
} | |
handleChange(index, event) { | |
let files = this.state.files.slice(); | |
files[index].name = event.target.value; | |
this.setState({ files: files }); | |
} | |
render() { | |
console.log(this.state) | |
const filesExist = this.state.files; | |
return ( | |
<div className="downloadMusic"> | |
<Container> | |
<Row> | |
<Col> | |
<div> | |
{filesExist != 0 ? ( | |
<ButtonToggle onClick={this.replaceInput} color="secondary">Replace Music Files | |
</ButtonToggle> | |
) : ( | |
<ButtonToggle onClick={this.clickFileInput} color="secondary">Upload Files | |
</ButtonToggle> | |
)} | |
</div> | |
<div className="input"> | |
<input | |
accept="audio/*" | |
id="upload-file" | |
onChange={this.handleClick} | |
className="inputName" | |
type="file" | |
multiple | |
style={{display:"none"}} | |
ref={this.inputRef} | |
/> | |
<input | |
accept="audio/*" | |
id="upload-file" | |
onChange={this.replaceClick} | |
className="inputName" | |
type="file" | |
multiple | |
style={{display:"none"}} | |
ref={this.replaceInputRef} | |
/> | |
</div> | |
</Col> | |
</Row> | |
</Container> | |
<div>{this.state.files.length > 0 && this.state.albums.map(album => ( | |
<Downloaded | |
key={album.id} | |
album={album} | |
downloadChange={this.downloadChange} | |
/> | |
))}</div> | |
<Container> | |
<Row> | |
<Col> | |
<DragDropContext onDragEnd={this.onDragEnd}> | |
<Droppable droppableId="droppable"> | |
{(provided, snapshot) => ( | |
<div | |
{...provided.droppableProps} | |
ref={provided.innerRef} | |
style={getListStyle(snapshot.isDraggingOver)} | |
> | |
{this.state.files.map((file, index) => ( | |
<Draggable key={file.id.toString()} draggableId={file.id.toString()} index={index} style={{marginTop:"400px"}}> | |
{(provided, snapshot) => ( | |
<div | |
ref={provided.innerRef} | |
{...provided.draggableProps} | |
style={getItemStyle( | |
snapshot.isDragging, | |
provided.draggableProps.style | |
)} | |
> | |
<div className="handle"> | |
<Handle {...provided.dragHandleProps}/> | |
</div> | |
<div> | |
<form> | |
<label> | |
<p> <input type="text" value={file.name} onChange={this.handleChange.bind(this, index)} name="name" ref={this.fileRef} style={{width:'600px', height:'30px', fontSize: '16px'}} /></p> | |
</label> | |
</form> | |
</div> | |
<div className="delete"> | |
<LIDelete onClick = {() => this.removeItem(index)}/> | |
</div> | |
</div> | |
)} | |
</Draggable> | |
))} | |
{provided.placeholder} | |
</div> | |
)} | |
</Droppable> | |
</DragDropContext> | |
</Col> | |
</Row> | |
</Container> | |
<Container> | |
<div className="belowList">{this.state.files.length > 0 && <div> | |
<Row> | |
<Col> | |
<ButtonToggle onClick={this.clickAddFiles} color="secondary">Add More Files | |
</ButtonToggle> | |
<input | |
accept="audio/*" | |
onChange={this.secondInputClick} | |
id="second-input" | |
className="inputName" | |
type="file" | |
multiple | |
style={{display:"none"}} | |
ref={this.addFiles} | |
/> | |
</Col> | |
</Row> | |
</div> | |
}</div> | |
<Row> | |
<Col> | |
<ButtonToggle onClick={this.save} color="success">Save | |
</ButtonToggle> | |
</Col> | |
</Row> | |
</Container> | |
</div> | |
); | |
} | |
} | |
export default AddAlbum; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from "react"; | |
import ReactDOM from "react-dom"; | |
import { Link } from 'react-router-dom'; | |
import ImageUpload from './image-upload'; | |
import AddAlbum from './add-album'; | |
import { Container, Row, Col } from 'reactstrap'; | |
import { Button, Form, FormGroup, Label, Input, FormText } from 'reactstrap'; | |
class Downloaded extends Component { | |
constructor(props) { | |
super(props); | |
} | |
render() { | |
return( | |
<div className="main-content"> | |
<Container> | |
<div className="container"> | |
<div className="downloaded"> | |
<Row xs="2" className="downloaded-row"> | |
<Col xs="7" sm="10" md="6" lg="5" className=""> | |
<div className="image"><ImageUpload/></div> | |
</Col> | |
<Col xs="6" sm="2" md="5" lg="5" className=""> | |
<Form className="form"> | |
<FormGroup row> | |
<Label for="title">Title:</Label> | |
<Input type="text" name="title" id="title" placeholder="Title" value={this.props.album.title} onChange={this.props.downloadChange}/> | |
</FormGroup> | |
<FormGroup row> | |
<Label for="date">Date:</Label> | |
<Input type="date" name="date" id="date" placeholder="Date" value={this.props.album.date} required pattern="\d{1,2}-\d{1,2}-\d{4}" onChange={this.props.downloadChange}/> | |
</FormGroup> | |
<FormGroup row> | |
<Label for="description">Description:</Label> | |
<Input type="textarea" name="description" id="description" placeholder="Description" value={this.props.album.description} onChange={this.props.downloadChange}/> | |
</FormGroup> | |
</Form> | |
</Col> | |
</Row> | |
</div> | |
</div> | |
</Container> | |
</div> | |
); | |
} | |
}; | |
export default Downloaded; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment