Skip to content

Instantly share code, notes, and snippets.

@DDavis1025
Created February 5, 2020 20:13
Show Gist options
  • Save DDavis1025/5e76f6689b9b2a210b6d1fafb3dbd541 to your computer and use it in GitHub Desktop.
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
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> &nbsp;<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;
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