Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Upload Component #73

Merged
merged 20 commits into from
Oct 14, 2017
Merged

Upload Component #73

merged 20 commits into from
Oct 14, 2017

Conversation

chriddyp
Copy link
Member

@chriddyp
Copy link
Member Author

chriddyp commented Sep 12, 2017

Usage (15 lines of app code! 😻 )

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import dash_table_experiments as dt
import pandas as pd
import io

app = dash.Dash()

app.layout = html.Div([
    html.H1('Dash Upload Component'),
    dcc.Upload(id='upload'),
    dt.DataTable(
        id='datatable',
        rows=[{}]
    ),
], className="container")

@app.callback(
    Output('datatable', 'rows'),
    [Input('upload', 'contents')])
def update_figure(content):
    if not content:
        return []
    dff = pd.read_csv(io.StringIO(content))
    return dff.to_dict('records')

app.css.append_css({"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"})

if __name__ == '__main__':
    app.run_server(debug=True)

upload-component

@chriddyp
Copy link
Member Author

cc @dhhagan @alishobeiri

@chriddyp
Copy link
Member Author

chriddyp commented Sep 12, 2017

I've published this on the prerelease channel. Try this out with:

pip install dash-core-components==0.13.0rc1

@chriddyp
Copy link
Member Author

chriddyp commented Sep 13, 2017

Just published another release with properties:

pip install dash-core-components==0.13.0rc2

Some examples:

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import dash_table_experiments as dt

import json
import pandas as pd
import plotly
import io

app = dash.Dash()

app.scripts.config.serve_locally = True

app.layout = html.Div([
    html.H1('Dash Upload Component'),

    html.Hr(),
    html.H3('Default'),
    dcc.Upload(id='upload'),

    html.Hr(),
    html.H3('Custom Style with Children'),
    dcc.Upload(
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select a File')
        ]),
        style={
            'width': '100%',
            'height': '60px',
            'lineHeight': '60px',
            'borderWidth': '1px',
            'borderStyle': 'dashed',
            'borderRadius': '5px',
            'textAlign': 'center'
        }
    ),

    html.Hr(),
    html.H3('Styled as a Button'),
    dcc.Upload(
        html.Button('Upload'),
        style={}
    ),

    html.Hr(),

], className="container")


app.css.append_css({
    "external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"
})

if __name__ == '__main__':
    app.run_server(debug=True)

image

@chriddyp
Copy link
Member Author

I think that I will initialize the style to be {} and offer the html.Button and the dashed-style dropzone syntax as the canonical examples

@chriddyp
Copy link
Member Author

chriddyp commented Sep 13, 2017

I have published v0.13.0-rc3. Upgrade with:

pip install dash-core-components==0.13.0rc3

This prerelease changes the default styles and changes the format of the content property into a base64 encoded string. Here's the new usage:

upload-component

Usage (Python 2)

import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table_experiments as dt

import base64
import json
import pandas as pd
import plotly
import io

app = dash.Dash()

app.scripts.config.serve_locally = True

app.layout = html.Div([
    html.Div(id='waitfor'),
    dcc.Upload(
        id='upload',
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select a File')
        ]),
        style={
            'width': '100%',
            'height': '60px',
            'lineHeight': '60px',
            'borderWidth': '1px',
            'borderStyle': 'dashed',
            'borderRadius': '5px',
            'textAlign': 'center',
            'margin': '10px'
        }
    ),
    html.Div(id='output'),
    html.Div(dt.DataTable(rows=[{}]), style={'display': 'none'})
])

pre_style = {
    'whiteSpace': 'pre-wrap',
    'wordBreak': 'break-all',
    'whiteSpace': 'normal'
}


@app.callback(Output('output', 'children'),
              [Input('upload', 'contents')])
def update_output(contents):
    if contents is not None:
        content_type, content_string = contents.split(',')
        if 'csv' in content_type:
            df = pd.read_csv(io.StringIO(base64.b64decode(content_string).decode('utf-8')))
            return html.Div([
                dt.DataTable(rows=df.to_dict('records')),
                html.Hr(),
                html.Div('Raw Content'),
                html.Pre(contents, style=pre_style)
            ])
        elif 'image' in content_type:
            return html.Div([
                html.Img(src=contents),
                html.Hr(),
                html.Div('Raw Content'),
                html.Pre(contents, style=pre_style)
            ])
        else:
            # xlsx will have 'spreadsheet' in `content_type` but `xls` won't
            # have anything
            try:
                df = pd.read_excel(io.BytesIO(base64.b64decode(content_string)))
                return html.Div([
                    dt.DataTable(rows=df.to_dict('records')),
                    html.Hr(),
                    html.Div('Raw Content'),
                    html.Pre(contents, style=pre_style)
                ])
            except:
                return html.Div([
                    html.Hr(),
                    html.Div('Raw Content'),
                    html.Pre(contents, style=pre_style)
                ])



app.css.append_css({
    "external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"
})

if __name__ == '__main__':
    app.run_server(debug=True)

@chriddyp
Copy link
Member Author

chriddyp commented Sep 13, 2017

I'm pretty happy with this. I'll keep this PR open for a few days and solicit feedback before I merge it in.

"required": false,
"description": "ID of the component. Used to identify component\nin Dash callback functions."
},
"contents": {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to add a "filename(s)" property here to indicated which file or files have been dropped? Then set the property on line 35 of src/components/Upload.react.js, and add to Upload.propTypes? Or is there a way to get the filename that I'm not seeing?

Thanks

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea @kevinchiang ! Added this in dfa51bd

@jspablo
Copy link

jspablo commented Sep 22, 2017

Is possible to get the path from the input file?

Thank you

@chriddyp chriddyp merged commit b7f776f into master Oct 14, 2017
@chriddyp
Copy link
Member Author

This is now available in dash-core-components==0.14.0. Docs available at: https://plot.ly/dash/dash-core-components/upload

@tantrev
Copy link

tantrev commented Jul 19, 2018

It would also be super nice if the upload could support input from an external URL.

@Marc-Andre-Rivet Marc-Andre-Rivet deleted the upload branch September 25, 2019 10:01
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants