Wednesday, 19 June 2019

django 48 react post files

the end of all albums

click add album

complete form with file input

new album is added

detailed file info and form data

//partials/body

import React, { Component } from 'react';
import '../App.css';
import { Switch, Route } from 'react-router-dom';
import Albums from '../pages/albums';
import Login from '../pages/login';
import Logout from '../pages/logout';
import AlbumDetail from '../pages/albumDetail';
import AlbumForm from '../pages/albumForm';

export default class Body extends Component {

    render() {
        return (
            <main className='Body-Background'>
                <Switch>
                    <Route exact path='/' component={Albums} />
                    <Route path='/login/' component={Login} />
                    <Route path='/logout/' component={Logout} />
                    <Route path='/albumDetail/' component={AlbumDetail} />
                    <Route path='/addAlbum/' component={AlbumForm} />
                </Switch>
            </main>
        );
    }
}

--------------------------------
//pages/albumForm

import React, { Component } from 'react';
import '../App.css';
import { Input } from 'antd';
import { FaOpencart, FaLyft, FaSignature } from "react-icons/fa";
import { Button } from 'reactstrap';
import { connect } from 'react-redux';
import { postAlbum } from '../redux/actions/postAlbum'
import { Redirect } from 'react-router-dom';
import { getAlbums } from '../redux/actions/getAlbums';
import { getUsers } from '../redux/actions/getUser';

class albumForm extends Component {
    constructor(props) {
        super(props);

        this.state = {
            artist: '',
            album_title: '',
            genre: '',
            album_logo: null,
            message: <p></p>,
        };
    }

    componentDidMount() {
        if (this.props.loggedin) {
            if (!this.props.gotUsers) {
                this.props.dispatch(getUsers(this.props.token));
            }
            if (!this.props.gotAlbums) {
                this.props.dispatch(getAlbums(this.props.token));
            }
        }
    }

    inputChange = (e, p) => {
        this.setState({ [p]: e.target.value });
    }

    fileChange = (e) => {
        console.log(e.target.files);
        this.setState({ album_logo: e.target.files[0] })
    }

    formSubmit = (e) => {
        e.preventDefault();

        const data = {
            artist: this.state.artist,
            album_title: this.state.album_title,
            genre: this.state.genre,
            author: this.props.users.filter(user => user.username == this.props.username)[0].id,
            album_logo: this.state.album_logo,
        }

        console.log(data);

        const formData = new FormData();
        formData.set('artist', data.artist);
        formData.set('album_title', data.album_title);
        formData.set('genre', data.genre);
        formData.set('author', data.author);
        formData.append('album_logo', data.album_logo);

        this.props.dispatch(postAlbum(this.props.token, formData))

        //wait for 5sec, check every sec to see if post successful
        let i = 0;
        const waitPost = setInterval(() => {
            if (this.props.added) {
                this.setState({ message: <p style={{ color: 'green' }}>Post successful</p> })
                clearInterval(waitPost);
            }
            if (i == 5) {
                this.setState({ message: <p style={{ color: 'red' }}>Post timeout</p> })
                clearInterval(waitPost);
            }
            i++;
        }, 1000)
    }

    render() {
        if (!this.props.loggedin) {
            return <Redirect to='/login' />
        }

        return (
            <form style={{ marginLeft: '10px', width: '300px' }}
                onSubmit={(e) => this.formSubmit(e)}>
                <legend>Album Form</legend>
                <hr />
                <p style={{ color: 'red' }}>{this.props.error}</p>
                {this.state.message}

                <Input placeholder="artist" required='required'
                    prefix={<FaOpencart style={{ color: 'rgba(0,0,0,.25)' }} />}
                    onChange={(e) => this.inputChange(e, 'artist')}
                    style={{ marginTop: '5px' }}
                />
                <Input placeholder="album title" required='required'
                    prefix={<FaSignature style={{ color: 'rgba(0,0,0,.25)' }} />}
                    onChange={(e) => this.inputChange(e, 'album_title')}
                    style={{ marginTop: '15px' }}
                />
                <Input placeholder="genre" required='required'
                    prefix={<FaLyft style={{ color: 'rgba(0,0,0,.25)' }} />}
                    onChange={(e) => this.inputChange(e, 'genre')}
                    style={{ marginTop: '15px' }}
                />
                <div style={{ marginTop: '15px' }}>
                    Album Logo: <input type='file' required='required'
                        onChange={(e) => this.fileChange(e)} />
                </div>
                <Button color="success" type='submit' size='sm'
                    style={{ marginTop: '15px' }}
                >Submit</Button>
            </form>
        );
    }
}

export default connect(
    (store) => {
        return {
            token: store.login.token,
            loggedin: store.login.fetched,
            added: store.albums.added,
            gotAlbums: store.albums.fetched,
            albums: store.albums.albums,
            gotUsers: store.users.fetched,
            users: store.users.users,
            username: store.login.username,
            error: store.albums.error
        };
    }
)(albumForm);

---------------------------------------
//redux/actions/postAlbum

import axios from 'axios';

export function postAlbum(token, data) {
    return {
        type: "add_album",
        payload: axios({
            method: 'post',
            url: 'http://127.0.0.1:8000/api/album_list/',
            headers: {
                Authorization: 'Token ' + token,
            },
            data: data,
        })
    }
}

--------------------------------
//redux/reducers/albumReducer

export default function reducer(
    state = {
        albums: [],
        fetching: false,
        fetched: false,
        adding: false,
        added: false,
        error: ''
    },
    action
) {
    switch (action.type) {
        case "fetch_albums_PENDING": {
            return { ...state, fetching: true, fetched: false, error: '' }
        }

        case "fetch_albums_FULFILLED": {
            return {
                ...state,
                fetching: false,
                fetched: true,
                albums: action.payload.data,
                error: ''
            }
        }

        case "fetch_albums_REJECTED": {
            return {
                ...state,
                fetching: false,
                error: action.payload.toString()
            }
        }

        case "add_album_PENDING": {
            return { ...state, adding: true, added: false, error: '' }
        }

        case "add_album_FULFILLED": {
            return {
                ...state,
                adding: false,
                added: true,
                albums: [...state.albums].concat(action.payload.data),
                error: ''
            }
        }

        case "add_album_REJECTED": {
            return {
                ...state,
                adding: false,
                error: action.payload.toString()
            }
        }

        default:
            break;
    }
    return state;
}

reference:
https://gist.github.com/AshikNesin/e44b1950f6a24cfcd85330ffc1713513
https://stackoverflow.com/questions/47630163/axios-post-request-to-send-form-data

No comments:

Post a Comment