Skip to content

Commit

Permalink
revert to dash-uploader
Browse files Browse the repository at this point in the history
  • Loading branch information
gcroci2 committed Jul 19, 2024
1 parent 6ebbfaa commit 3a7cc0f
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 196 deletions.
Binary file added app/__pycache__/__init__.cpython-310.pyc
Binary file not shown.
Binary file added app/__pycache__/app.cpython-310-pytest-8.2.2.pyc
Binary file not shown.
151 changes: 31 additions & 120 deletions app/app.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,18 @@
import os
import pickle
import tempfile
import uuid
import dash_bootstrap_components as dbc
import dash_uploader as du
from dash import Dash
from dash import Input
from dash import Output
from dash import clientside_callback
from dash import html
from flask import Flask
from flask import jsonify
from flask import request


UPLOAD_FOLDER = "uploads" # Folder where uploaded files will be stored
server = Flask(__name__)
server.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER

dbc_css = "https://cdn.jsdelivr.net/gh/AnnMarieW/dash-bootstrap-templates/dbc.min.css"
app = Dash(
__name__,
server=server,
external_stylesheets=[dbc.themes.UNITED, dbc_css, dbc.icons.FONT_AWESOME],
)

src = app.get_asset_url("uploadform.html")
STATUS_FAILED = "failed"
STATUS_SUCCESS = "success"
app = Dash(__name__, external_stylesheets=[dbc.themes.UNITED, dbc_css, dbc.icons.FONT_AWESOME])

# ------------------ Nav Bar ------------------ #
color_mode_switch = html.Span(
Expand Down Expand Up @@ -69,6 +57,24 @@
TEMP_DIR = tempfile.mkdtemp()
du.configure_upload(app, TEMP_DIR)

uploader = dbc.Row(
dbc.Col(
html.Div(
[
du.Upload(
id="dash-uploader",
text="Import Data",
text_completed="Uploaded: ",
filetypes=["pkl"],
upload_id=uuid.uuid1(), # Unique session id
cancel_button=True,
max_files=1,
),
],
),
className="p-5 ml-5 mr-5",
),
)

# ------------------ Tabs ------------------ #
# gm tab content
Expand Down Expand Up @@ -108,9 +114,7 @@
className="p-5",
)

uploader_flask = html.Iframe(src=src)

app.layout = dbc.Container([navbar, uploader_flask, tabs], fluid=True, className="p-0")
app.layout = dbc.Container([navbar, uploader, tabs], fluid=True, className="p-0")

clientside_callback(
"""
Expand All @@ -123,109 +127,16 @@
Input("color-mode-switch", "value"),
)

# TODO: Verify if this is the correct way to handle file upload
# @server.route("/upload", methods=["POST"])
# def upload_file():
# try:
# file_chunk_size = 1024 * 1024 # 1 MB chunk size
# file_path = None

# # Ensure the uploads folder exists
# os.makedirs(server.config["UPLOAD_FOLDER"], exist_ok=True)

# # Retrieve the uploaded file from the request
# if "file" not in request.files:
# return jsonify({"error": "No file part in the request."}), 400

# uploaded_file = request.files["file"]

# # Save the uploaded file to disk
# file_path = os.path.join(server.config["UPLOAD_FOLDER"], uploaded_file.filename)
# print(file_path)
# with open(file_path, "wb") as f:
# while True:
# chunk = uploaded_file.stream.read(file_chunk_size)
# if not chunk:
# break
# f.write(chunk)
# file = request.files["file"]
# file.save(file_path)
# with open(file_path, "rb") as f:
# decoded_data = base64.b64decode(f.read())
# try:
# decoded_text = decoded_data.decode("utf-8")
# except Exception as e:
# print(e)
# print(len(decoded_data))
# print(decoded_data)
# with open(file_path, "rb") as f:
# file_content = f.read()
# print(type(file_content))
# decoded_content = base64.b64decode(file_content)
# print(type(decoded_content))
# try:
# data = pickle.loads(io.BytesIO(decoded_content))
# except Exception as e:
# print(e)
# return jsonify({"file_path": file_path}), 200

# except Exception as e:
# return jsonify({"error": str(e)}), 500


@server.route("/upload", methods=["POST"])
def upload_file():
# check if the post request has the file part
print(request.values)
# print(type(request.values))
# print(len(request.values))
# print(request.files)
# print(type(request.files))
# print(request.files["file"])

return jsonify(status=STATUS_SUCCESS)


# TODO: add callback to handle file upload
# @app.callback(
# Output("output-data-upload", "children"),
# [Input("upload-data", "contents")],
# [State("upload-data", "filename"), State("upload-data", "last_modified")],
# )
# def update_output(contents, filename, last_modified):
# if contents is not None:
# try:
# # Perform upload via Flask route /upload
# upload_response = requests.post(
# "http://127.0.0.1:8050/upload", # Update with your server address
# files={"file": (filename, contents.encode())},
# )
# if upload_response.status_code == 200:
# file_path = upload_response.json()["file_path"]
# # Read and process the uploaded file
# with open(file_path, "rb") as f:
# # print(type(f))
# # file_content = f.read()
# # print(type(file_content))
# # # Example: Read data from pickle file
# # # _, content_string = contents.split(",")
# # decoded = base64.b64decode(file_content)
# # type(dec)
# # # if filename.endswith(".pkl"):
# # data = pickle.load(io.BytesIO(decoded))
# # data = pickle.load(f)
# # return html.Div([html.H5(f"File selected: {filename}"), html.P(f"File contents: {data}")])
# return html.Div(
# [html.H5(f"File uploaded: {filename}"), html.P(f"File path: {file_path}")]
# )
# else:
# return html.Div(["Error uploading file."])

# except Exception as e:
# return html.Div([f"Error: {e}"])
@du.callback(
id="dash-uploader",
output=Output("dash-uploader-output", "children"),
)
def upload_data(status: du.UploadStatus): # noqa: D103
with open(status.latest_file, "rb") as f:
pickle.load(f)
return f"Successfully uploaded file `{os.path.basename(status.latest_file)}` of size {round(status.uploaded_size_mb, 2)} MB."

# else:
# return html.Div(["No file selected"])

# TODO: add tests

Expand Down
63 changes: 0 additions & 63 deletions app/assets/jquery-3.7.1.min.js

This file was deleted.

11 changes: 0 additions & 11 deletions app/assets/uploadform.html

This file was deleted.

26 changes: 24 additions & 2 deletions tests/test_app.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,24 @@
def test_always_passes():
assert True
from contextvars import copy_context
from dash._callback_context import context_value
from dash._utils import AttributeDict

# Import the names of callback functions you want to test
from app.app import upload_data


TEST_DATA = "/Users/giuliacrocioni/Desktop/docs/eScience/projects/NPLinker/nplinker-webapp/nplinker_quickstart/output/npl.pkl"
def test_update_callback():
output = upload_data(1, 0)
assert output == "button 1: 1 & button 2: 0"


def test_display_callback():
def run_callback():
context_value.set(
AttributeDict(**{"triggered_inputs": [{"prop_id": "btn-1-ctx-example.n_clicks"}]})
)
return display(1, 0, 0)

ctx = copy_context()
output = ctx.run(run_callback)
assert output == "You last clicked button with ID btn-1-ctx-example"

0 comments on commit 3a7cc0f

Please sign in to comment.