Skip to content

Commit

Permalink
Merge pull request #42 from Agenta-AI/delete-dataset
Browse files Browse the repository at this point in the history
delete dataset
  • Loading branch information
aakrem authored May 31, 2023
2 parents 3323614 + 74c6aa7 commit 31149f1
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 89 deletions.
9 changes: 7 additions & 2 deletions agenta-backend/agenta_backend/models/api/dataset_model.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from pydantic import BaseModel, Field
from typing import Any
from typing import Any, Optional, List


class DatasetModel(BaseModel):
column_name: str = Field(...)
Expand All @@ -20,4 +21,8 @@ class Config:
class UploadResponse(BaseModel):
id: str
name: str
created_date: str
created_at: str


class DeleteDatasets(BaseModel):
dataset_ids: List[str]
40 changes: 33 additions & 7 deletions agenta-backend/agenta_backend/routers/dataset_router.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import os
from fastapi import HTTPException, APIRouter, UploadFile, File, Form
from fastapi import HTTPException, APIRouter, UploadFile, File, Form, Body
from agenta_backend.services.db_mongo import datasets
from agenta_backend.models.api.dataset_model import DatasetModel, UploadResponse
from agenta_backend.models.api.dataset_model import UploadResponse, DeleteDatasets
from datetime import datetime
from typing import Optional
from typing import Optional, List
from bson import ObjectId
import csv

Expand All @@ -13,7 +13,7 @@


@router.post('/upload', response_model=UploadResponse)
async def upload_file(file: UploadFile = File(...), dataset_name: Optional[str] = File(...), app_name:str = Form(None)):
async def upload_file(file: UploadFile = File(...), dataset_name: Optional[str] = File(None), app_name:str = Form(None)):
"""
Uploads a CSV file and saves its data to MongoDB.
Expand All @@ -33,7 +33,7 @@ async def upload_file(file: UploadFile = File(...), dataset_name: Optional[str]

# Create a document with the CSV data
document = {
"created_date": datetime.now().isoformat(),
"created_at": datetime.now().isoformat(),
"name": dataset_name if dataset_name else file.filename,
"app_name": app_name,
"csvdata": []
Expand All @@ -51,7 +51,7 @@ async def upload_file(file: UploadFile = File(...), dataset_name: Optional[str]
return UploadResponse(
id=str(result.inserted_id),
name=document["name"],
created_date=document["created_date"]
created_at=document["created_at"]
)
except Exception as e:
print(e)
Expand All @@ -71,7 +71,7 @@ async def get_datasets(app_name: Optional[str] = None):
Raises:
- `HTTPException` with status code 404 if no datasets are found.
"""
cursor = datasets.find({"app_name": app_name}, {"_id": 1, "name": 1, "created_date": 1})
cursor = datasets.find({"app_name": app_name}, {"_id": 1, "name": 1, "created_at": 1})
documents = await cursor.to_list(length=100)
for document in documents:
document['_id'] = str(document['_id'])
Expand All @@ -96,3 +96,29 @@ async def get_dataset(dataset_id: str):
return dataset
else:
raise HTTPException(status_code=404, detail=f"dataset with id {dataset_id} not found")


@router.delete("/", response_model=List[str])
async def delete_datasets(deleteDatasets: DeleteDatasets):
"""
Delete specific datasets based on their unique IDs.
Args:
dataset_ids (List[str]): The unique identifiers of the datasets to delete.
Returns:
A list of the deleted datasets' IDs.
"""
deleted_ids = []

for dataset_id in deleteDatasets.dataset_ids:
dataset = await datasets.find_one({'_id': ObjectId(dataset_id)})

if dataset is not None:
result = await datasets.delete_one({'_id': ObjectId(dataset_id)})
if result:
deleted_ids.append(dataset_id)
else:
raise HTTPException(status_code=404, detail=f"Dataset {dataset_id} not found")

return deleted_ids
4 changes: 2 additions & 2 deletions agenta-web/src/lib/Types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export interface Dataset {
id: string;
_id: string;
name: string;
created_date?: string;
created_at: string;
}

export interface AppVariant {
Expand Down
15 changes: 15 additions & 0 deletions agenta-web/src/lib/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,21 @@ export const loadDatasetsList = (app_name: string) => {
}
};

export const deleteDatasets = async (ids: string[]) => {
try {
const response = await axios({
method: 'delete',
url: `${API_BASE_URL}/api/datasets`,
data: { dataset_ids: ids },
});
if (response.status === 200) {
return response.data;
}
} catch (error) {
console.error(`Error deleting entity: ${error}`);
throw error;
}
};

const eval_endpoint = axios.create({
baseURL: `${API_BASE_URL}/api/app_evaluations`,
Expand Down
65 changes: 0 additions & 65 deletions agenta-web/src/pages/apps/[app_name]/datasets/DatasetsTable.tsx

This file was deleted.

124 changes: 113 additions & 11 deletions agenta-web/src/pages/apps/[app_name]/datasets/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,132 @@

import { UploadOutlined } from "@ant-design/icons";
import { Button, Form, Input, Select, Spin, Upload, message } from "antd";
import { useState } from 'react';
import DatasetsTable from "./DatasetsTable";
import { Button, Spin, Table } from "antd";

import { Dataset } from "@/lib/Types";
import Link from "next/link";
import { useRouter } from "next/router";
import { ColumnsType } from 'antd/es/table';
import { useState, useEffect } from 'react';
import { formatDate } from '@/lib/helpers/dateTimeHelper';
import { DeleteOutlined } from "@ant-design/icons";
import { deleteDatasets } from "@/lib/services/api";

type DatasetTableDatatype = {
key: string;
created_at: string;
name: string;
}

const fetchData = async (url: string): Promise<any> => {
const response = await fetch(url);
return response.json();
}

export default function Datasets() {
const router = useRouter();
const [dataset, setDataset] = useState<Dataset>({
id: '1',
name: 'Example Dataset',
});
const { app_name } = router.query;
const [datasetsList, setDatasetsList] = useState<DatasetTableDatatype[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const [selectionType, setSelectionType] = useState<'checkbox' | 'radio'>('checkbox');
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);

useEffect(() => {
if (!app_name) {
return;
}
fetchData(`http://localhost/api/datasets?app_name=${app_name}`)
.then(data => {
console.log(data);
let newDatasetsList = data.map((obj:Dataset) => {

let newObj:DatasetTableDatatype = {
key: obj._id,
created_at: obj.created_at,
name: obj.name
}
return newObj;
});
console.log(newDatasetsList);
setLoading(false);
setDatasetsList(newDatasetsList);
}).
catch(error => {
console.log(error);
});
}, [app_name]);

const columns: ColumnsType<DatasetTableDatatype> = [
{
title: 'Name',
dataIndex: 'name',
key: 'name'
},
{
title: 'Creation date',
dataIndex: 'created_at',
key: 'created_at',
render: (date: string) => {
return formatDate(date);
}
},
];

const rowSelection = {
onChange: (selectedRowKeys: React.Key[], selectedRows: DatasetTableDatatype[]) => {
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
setSelectedRowKeys(selectedRowKeys);
},
getCheckboxProps: (record: DatasetTableDatatype) => ({
disabled: record.name === 'Disabled User', // Column configuration not to be checked
name: record.name,
}),
};

const onDelete = async () => {
const datasetsIds = selectedRowKeys.map(key => key.toString());
setLoading(true);
try {
const deletedIds = await deleteDatasets(datasetsIds);
setDatasetsList(prevDatasetsList => prevDatasetsList.filter(dataset => !deletedIds.includes(dataset.key)));

setSelectedRowKeys([]);
} catch (e) {
console.log(e)
} finally {
setLoading(false);
}
};

return (
<div>
<div style={{ marginBottom: 40 }}>
<Link href={`${router.asPath}/new`}>
<Button >Add a dataset</Button>
</Link>
{
selectedRowKeys.length > 0 && (
<Button style={{marginLeft: 10}} onClick={onDelete}>
<DeleteOutlined key="delete" style={{ color: 'red' }} />
Delete
</Button>
)
}
</div>

<DatasetsTable dataset={dataset} />
<div>
{loading ? (
<Spin />
) : (
<Table
rowSelection={{
type: selectionType,
...rowSelection,
}}
columns={columns}
dataSource={datasetsList}
loading={loading}
/>
)}
</div>
</div>


);
}
4 changes: 2 additions & 2 deletions agenta-web/src/pages/apps/[app_name]/datasets/new/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
\import { UploadOutlined } from "@ant-design/icons";
import { UploadOutlined } from "@ant-design/icons";
import { Alert, Button, Form, Input, Space, Spin, Upload, message } from "antd";
import { useState } from "react";
import axios from 'axios';
Expand All @@ -23,8 +23,8 @@ export default function AddANewDataset() {
formData.append('file', file[0].originFileObj);
if (values.datasetName && values.datasetName.trim() !== "") {
formData.append('dataset_name', values.datasetName);
formData.append('app_name', app_name?.toString() || '');
}
formData.append('app_name', app_name?.toString() || '');

try {
setUploadLoading(true);
Expand Down

0 comments on commit 31149f1

Please sign in to comment.