Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

csv editor #40

Open
Isaac-Flath opened this issue Sep 10, 2024 · 3 comments
Open

csv editor #40

Isaac-Flath opened this issue Sep 10, 2024 · 3 comments

Comments

@Isaac-Flath
Copy link
Collaborator

Add as simple app. Written by Hamel

from fasthtml.common import *

db = database(':memory:')
tbl = None
hdrs = (Style('''
button,input { margin: 0 1rem; }
[role="group"] { border: 1px solid #ccc; }
'''), )
app, rt = fast_app(live=True, hdrs=hdrs)

@rt("/")
async def get():
    return Titled("CSV Uploader",
        Group(
            Input(type="file", name="csv_file", accept=".csv"),
            Button("Upload", hx_post="/upload", hx_target="#results",
                   hx_encoding="multipart/form-data", hx_include='previous input'),
            A('Download', href='/download', type="button")
        ),
        Div(id="results"))

def render_row(row):
    vals = [Td(Input(value=v, name=k)) for k,v in row.items()]
    vals.append(Td(Group(Button('delete', hx_get=remove.rt(id=row['id'])),
                   Button('update', hx_post='/update', hx_include="closest tr"))))
    return Tr(*vals, hx_target='closest tr', hx_swap='outerHTML')

@rt
async def download():
    csv_data = [",".join(map(str, tbl.columns_dict))]
    csv_data += [",".join(map(str, row.values())) for row in tbl()]
    headers = {'Content-Disposition': 'attachment; filename="data.csv"'}
    return Response("\n".join(csv_data), media_type="text/csv", headers=headers)

@rt('/update')
def post(d:dict): return render_row(tbl.update(d))

@rt
def remove(id:int): tbl.delete(id)

@rt("/upload")
async def post(csv_file: UploadFile):
    global tbl
    if not csv_file.filename.endswith('.csv'): return "Please upload a CSV file"
    tbl = db.import_file('test', await csv_file.read(), pk='id')
    header = Tr(*map(Th, tbl.columns_dict))
    vals = [render_row(row) for row in tbl()]
    return Table(Thead(header), Tbody(*vals))

serve()
@dgwyer
Copy link

dgwyer commented Sep 10, 2024

I'm trying to understand the proper usage of async/await in Python. My only experience of this in in JS.

In the example above there are three async definitions but only one of them has an associated await. Should the other two async keywords be removed or are they semantically correct?

@Isaac-Flath
Copy link
Collaborator Author

Isaac-Flath commented Sep 10, 2024

You are correct. Async doesn't do anything if nothing is awaited. So, the other two will be removed because they don't do anything (though they don't particularly much either).

@Isaac-Flath
Copy link
Collaborator Author

Isaac-Flath commented Sep 12, 2024

Steps to complete:

  • Remove global state so it works for multiple users
  • Remove CSV merge type functionality, each upload clears prior csv data and starts fresh
  • Add test File download for people to use to try it out easier
  • Add CSV upload file limit to 50 rows for demo purposes (I tried it with first csv I had handy and it was big enough to cause issues)
  • Subapp Routing
  • Screenshot/GIF
  • Make metadata file
  • Add Navbar to App

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants