Commit bd3b5f1e authored by Timothy J. Baek's avatar Timothy J. Baek
Browse files

feat: csv user import frontend

parent e5703a58
import logging import logging
from fastapi import Request from fastapi import Request, UploadFile, File
from fastapi import Depends, HTTPException, status from fastapi import Depends, HTTPException, status
from fastapi import APIRouter from fastapi import APIRouter
from pydantic import BaseModel from pydantic import BaseModel
import re import re
import uuid import uuid
import csv
from apps.web.models.auths import ( from apps.web.models.auths import (
SigninForm, SigninForm,
...@@ -212,7 +214,7 @@ async def signup(request: Request, form_data: SignupForm): ...@@ -212,7 +214,7 @@ async def signup(request: Request, form_data: SignupForm):
@router.post("/add", response_model=SigninResponse) @router.post("/add", response_model=SigninResponse)
async def signup(form_data: AddUserForm, user=Depends(get_admin_user)): async def add_user(form_data: AddUserForm, user=Depends(get_admin_user)):
if not validate_email_format(form_data.email.lower()): if not validate_email_format(form_data.email.lower()):
raise HTTPException( raise HTTPException(
...@@ -251,6 +253,76 @@ async def signup(form_data: AddUserForm, user=Depends(get_admin_user)): ...@@ -251,6 +253,76 @@ async def signup(form_data: AddUserForm, user=Depends(get_admin_user)):
raise HTTPException(500, detail=ERROR_MESSAGES.DEFAULT(err)) raise HTTPException(500, detail=ERROR_MESSAGES.DEFAULT(err))
@router.post("/add/import", response_model=SigninResponse)
async def add_user_csv_import(
file: UploadFile = File(...), user=Depends(get_admin_user)
):
try:
# Check if the file is a CSV file
if file.filename.endswith(".csv"):
# Read the contents of the CSV file
contents = await file.read()
# Decode the contents from bytes to string
decoded_content = contents.decode("utf-8")
# Split the CSV content into lines
csv_lines = decoded_content.split("\n")
# Parse CSV
csv_data = []
csv_reader = csv.reader(csv_lines)
for row in csv_reader:
csv_data.append(row)
# Print the CSV data
for row in csv_data:
print(row)
return {"message": "CSV file uploaded successfully."}
else:
raise "File must be a CSV."
except Exception as err:
raise HTTPException(500, detail=ERROR_MESSAGES.DEFAULT(err))
# if not validate_email_format(form_data.email.lower()):
# raise HTTPException(
# status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.INVALID_EMAIL_FORMAT
# )
# if Users.get_user_by_email(form_data.email.lower()):
# raise HTTPException(400, detail=ERROR_MESSAGES.EMAIL_TAKEN)
# try:
# print(form_data)
# hashed = get_password_hash(form_data.password)
# user = Auths.insert_new_auth(
# form_data.email.lower(),
# hashed,
# form_data.name,
# form_data.profile_image_url,
# form_data.role,
# )
# if user:
# token = create_token(data={"id": user.id})
# return {
# "token": token,
# "token_type": "Bearer",
# "id": user.id,
# "email": user.email,
# "name": user.name,
# "role": user.role,
# "profile_image_url": user.profile_image_url,
# }
# else:
# raise HTTPException(500, detail=ERROR_MESSAGES.CREATE_USER_ERROR)
# except Exception as err:
# raise HTTPException(500, detail=ERROR_MESSAGES.DEFAULT(err))
############################ ############################
# ToggleSignUp # ToggleSignUp
############################ ############################
......
Name,Email,Password,Role
...@@ -5,12 +5,16 @@ ...@@ -5,12 +5,16 @@
import { addUser } from '$lib/apis/auths'; import { addUser } from '$lib/apis/auths';
import Modal from '../common/Modal.svelte'; import Modal from '../common/Modal.svelte';
import { WEBUI_BASE_URL } from '$lib/constants';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
export let show = false; export let show = false;
let tab = '';
let inputFiles;
let _user = { let _user = {
name: '', name: '',
email: '', email: '',
...@@ -76,7 +80,25 @@ ...@@ -76,7 +80,25 @@
submitHandler(); submitHandler();
}} }}
> >
<div class=" "> <div class="flex text-center text-sm font-medium rounded-xl bg-transparent/10 p-1 mb-2">
<button
class="w-full rounded-lg p-1.5 {tab === '' ? 'bg-gray-50 dark:bg-gray-850' : ''}"
type="button"
on:click={() => {
tab = '';
}}>Form</button
>
<button
class="w-full rounded-lg p-1 {tab === 'import' ? 'bg-gray-50 dark:bg-gray-850' : ''}"
type="button"
on:click={() => {
tab = 'import';
}}>CSV Import</button
>
</div>
<div class="px-1">
{#if tab === ''}
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Role')}</div> <div class=" mb-1 text-xs text-gray-500">{$i18n.t('Role')}</div>
...@@ -139,6 +161,45 @@ ...@@ -139,6 +161,45 @@
/> />
</div> </div>
</div> </div>
{:else if tab === 'import'}
<div>
<div class="mb-3 w-full">
<input
id="upload-user-csv-input"
hidden
bind:files={inputFiles}
type="file"
accept=".csv"
/>
<button
class="w-full text-sm font-medium py-3 bg-transparent hover:bg-gray-100 border border-dashed dark:border-gray-800 dark:hover:bg-gray-850 text-center rounded-xl"
type="button"
on:click={() => {
document.getElementById('upload-user-csv-input')?.click();
}}
>
{#if inputFiles}
{inputFiles.length > 0 ? `${inputFiles.length}` : ''} document(s) selected.
{:else}
{$i18n.t('Click here to select a csv file.')}
{/if}
</button>
</div>
<div class=" text-xs text-gray-500">
ⓘ {$i18n.t(
'Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.'
)}
<a
class="underline dark:text-gray-200"
href="{WEBUI_BASE_URL}/static/user-import.csv"
>
Click here to download user import template file.
</a>
</div>
</div>
{/if}
</div> </div>
<div class="flex justify-end pt-3 text-sm font-medium"> <div class="flex justify-end pt-3 text-sm font-medium">
......
...@@ -154,7 +154,7 @@ ...@@ -154,7 +154,7 @@
if (isCtrlPressed && event.key === '.') { if (isCtrlPressed && event.key === '.') {
event.preventDefault(); event.preventDefault();
console.log('openSettings'); console.log('openSettings');
document.getElementById('open-settings-button')?.click(); showSettings.set(!$showSettings);
} }
// Check if Ctrl + / is pressed // Check if Ctrl + / is pressed
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment