Skip to content

Commit db9969a

Browse files
committed
Delete data source
1 parent b68c910 commit db9969a

File tree

6 files changed

+54
-38
lines changed

6 files changed

+54
-38
lines changed

app/api/data_source.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ async def delete_data_source(data_source_id: int):
7070

7171

7272
@router.post("")
73-
async def add_integration(dto: AddDataSource, background_tasks: BackgroundTasks):
73+
async def add_integration(dto: AddDataSource, background_tasks: BackgroundTasks) -> int:
7474
data_source = DataSourceContext.create_data_source(name=dto.name, config=dto.config)
7575

7676
# in main.py we have a background task that runs every 5 minutes and indexes the data source
7777
# but here we want to index the data source immediately
7878
background_tasks.add_task(data_source.index)
7979

80-
return {"success": "Data source added successfully"}
80+
return data_source.get_id()

app/data_source/api/base_data_source.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ def __init__(self, config: Dict, data_source_id: int, last_index_time: datetime
8383
self._last_index_time = last_index_time
8484
self._last_task_time = None
8585

86+
def get_id(self):
87+
return self._data_source_id
88+
8689
def _save_index_time_in_db(self) -> None:
8790
"""
8891
Sets the index time in the database, to be now

app/indexing/bm25_index.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import os
22
import pickle
3+
from typing import List
4+
35
import nltk
46
import numpy as np
57
from rank_bm25 import BM25Okapi
6-
from sqlalchemy import Connection
7-
from typing import List
88

99
from db_engine import Session
10-
from schemas import Paragraph
1110
from paths import BM25_INDEX_PATH
12-
13-
11+
from schemas import Paragraph
1412

1513

1614
def _add_metadata_for_indexing(paragraph: Paragraph) -> str:
@@ -60,13 +58,13 @@ def _update(self, session):
6058
self.index = BM25Okapi(corpus)
6159
self.id_map = id_map
6260

63-
def update(self, session = None):
61+
def update(self, session=None):
6462
if session is None:
6563
with Session() as session:
6664
self._update(session)
6765
else:
6866
self._update(session)
69-
67+
7068
self._save()
7169

7270
def search(self, query: str, top_k: int) -> List[int]:
@@ -87,4 +85,4 @@ def clear(self):
8785

8886
def _save(self):
8987
with open(BM25_INDEX_PATH, 'wb') as f:
90-
pickle.dump(self, f)
88+
pickle.dump(self, f)

ui/src/App.tsx

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ import 'react-toastify/dist/ReactToastify.css';
2222
import { ClipLoader } from "react-spinners";
2323
import { FiSettings } from "react-icons/fi";
2424
import {AiFillWarning} from "react-icons/ai";
25-
import { ConnectedDataSourceType, DataSourceType } from "./data-source";
25+
import { ConnectedDataSource, DataSourceType } from "./data-source";
2626

2727
export interface AppState {
2828
query: string
2929
results: SearchResultDetails[]
3030
searchDuration: number
3131
dataSourceTypes: DataSourceType[]
3232
dataSourceTypesDict: { [key: string]: DataSourceType }
33-
connectedDataSources: string[]
33+
connectedDataSources: ConnectedDataSource[]
3434
isLoading: boolean
3535
isNoResults: boolean
3636
isModalOpen: boolean
@@ -137,9 +137,8 @@ export default class App extends React.Component <{}, AppState>{
137137

138138
async listConnectedDataSources() {
139139
try {
140-
const response = await api.get<ConnectedDataSourceType[]>('/data-sources/connected');
141-
let nameList = response.data.map((dataSource) => dataSource.name);
142-
this.setState({ connectedDataSources: nameList })
140+
const response = await api.get<ConnectedDataSource[]>('/data-sources/connected');
141+
this.setState({ connectedDataSources: response.data });
143142
} catch (error) {
144143
}
145144
}
@@ -168,7 +167,7 @@ export default class App extends React.Component <{}, AppState>{
168167
}
169168

170169
this.setState({isServerDown: false, docsLeftToIndex: res.data.docs_left_to_index,
171-
docsInIndexing: res.data.docs_in_indexing, isPreparingIndexing: isPreparingIndexing});
170+
docsInIndexing: res.data.docs_in_indexing, isPreparingIndexing: isPreparingIndexing});
172171

173172
let timeToSleep = isPreparingIndexing ? 1000 : successSleepSeconds * 1000;
174173
setTimeout(() => this.fetchStatsusForever(), timeToSleep);
@@ -184,7 +183,7 @@ export default class App extends React.Component <{}, AppState>{
184183
})
185184
}
186185

187-
shouldShowIndexingStatus() {
186+
inIndexing() {
188187
return this.state.isPreparingIndexing || this.state.docsInIndexing > 0 || this.state.docsLeftToIndex > 0;
189188
}
190189

@@ -261,8 +260,8 @@ export default class App extends React.Component <{}, AppState>{
261260
toast.success("Code accepted. Welcome!", {autoClose: 3000});
262261
}
263262

264-
dataSourcesAdded = (dataSourceType: string) => {
265-
this.setState({isPreparingIndexing: true, connectedDataSources: [...this.state.connectedDataSources, dataSourceType]});
263+
dataSourcesAdded = (newlyConnected: ConnectedDataSource) => {
264+
this.setState({isPreparingIndexing: true, connectedDataSources: [...this.state.connectedDataSources, newlyConnected]});
266265
// if had no data from server, show toast after 30 seconds
267266
setTimeout(() => {
268267
if (this.state.isPreparingIndexing) {
@@ -272,6 +271,10 @@ export default class App extends React.Component <{}, AppState>{
272271
}, 1000 * 120);
273272
}
274273

274+
dataSourceRemoved = (removed: ConnectedDataSource) => {
275+
this.setState({connectedDataSources: this.state.connectedDataSources.filter((ds) => ds.id !== removed.id)});
276+
}
277+
275278
render() {
276279
return (
277280
<div>
@@ -280,7 +283,7 @@ export default class App extends React.Component <{}, AppState>{
280283
className="absolute right-0 z-30 float-right mr-6 mt-6 text-[42px] hover:cursor-pointer hover:rotate-90 transition-all duration-300 hover:drop-shadow-2xl">
281284
</FiSettings>
282285
{
283-
this.shouldShowIndexingStatus() &&
286+
this.inIndexing() &&
284287
<div className="absolute mx-auto left-0 right-0 w-fit z-20 top-6">
285288
<div className="text-xs bg-[#191919] border-[#4F4F4F] border-[.8px] rounded-full inline-block px-3 py-1">
286289
<div className="text-[#E4E4E4] font-medium font-inter text-sm flex flex-row justify-center items-center">
@@ -348,7 +351,8 @@ export default class App extends React.Component <{}, AppState>{
348351
contentLabel="Example Modal"
349352
style={customStyles}>
350353
<DataSourcePanel onClose={this.closeModal} connectedDataSources={this.state.connectedDataSources}
351-
onAdded={this.dataSourcesAdded} dataSourceTypesDict={this.state.dataSourceTypesDict}/>
354+
inIndexing={this.inIndexing()}
355+
onAdded={this.dataSourcesAdded} dataSourceTypesDict={this.state.dataSourceTypesDict} onRemoved={this.dataSourceRemoved} />
352356
</Modal>
353357

354358
{/* front search page*/}

ui/src/components/data-source-panel.tsx

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import copy from 'copy-to-clipboard';
55
import CopyThis from '../assets/images/copy-this.png';
66
import LeftPane from '../assets/images/left-pane-instructions.png';
77

8-
import { BsFillPencilFill } from 'react-icons/bs';
8+
import { FaRegEdit } from "react-icons/fa";
99
import { AiFillCheckCircle } from "react-icons/ai";
1010
import { BiLinkExternal } from 'react-icons/bi';
1111
import { IoMdClose, IoMdCloseCircle } from "react-icons/io";
@@ -14,7 +14,7 @@ import { RxCopy } from 'react-icons/rx';
1414
import { ClipLoader } from "react-spinners";
1515
import { toast } from 'react-toastify';
1616
import { api } from "../api";
17-
import { ConfigField, DataSourceType } from "../data-source";
17+
import { ConfigField, ConnectedDataSource, DataSourceType } from "../data-source";
1818

1919

2020
export interface SelectOption {
@@ -34,8 +34,10 @@ export interface DataSourcePanelState {
3434

3535
export interface DataSourcePanelProps {
3636
dataSourceTypesDict: { [key: string]: DataSourceType }
37-
connectedDataSources: string[]
38-
onAdded: (dataSourceType: string) => void
37+
connectedDataSources: ConnectedDataSource[]
38+
inIndexing: boolean
39+
onAdded: (newlyConnected: ConnectedDataSource) => void
40+
onRemoved: (removed: ConnectedDataSource) => void
3941
onClose: () => void
4042
}
4143

@@ -136,19 +138,19 @@ export default class DataSourcePanel extends React.Component<DataSourcePanelProp
136138
!this.state.isAdding && (
137139
<div className="w-full">
138140
<h1 className="text-2xl block text-white mb-4">
139-
{this.props.connectedDataSources.length > 0 ? 'Active data sources:' : 'No Active Data Sources. Add Now!'}
140-
<BsFillPencilFill key="pencil" onClick={this.swithcMode} className='text-white float-right inline hover:text-[#9875d4] hover:cursor-pointer' />
141+
{this.props.connectedDataSources.length > 0 ? (this.state.editMode ? 'Edit mode:' : 'Active data sources:') : 'No Active Data Sources. Add Now!'}
142+
{this.props.connectedDataSources.length > 0 && <FaRegEdit key="pencil" onClick={this.swithcMode} className='text-white mt-1 float-right inline hover:text-[#9875d4] hover:cursor-pointer' />}
141143
</h1>
142144
<div className="flex flex-row w-[100%] flex-wrap">
143-
{this.props.connectedDataSources.map((data_source) => {
145+
{this.props.connectedDataSources.map((dataSource) => {
144146
return (
145147
// connected data source
146148
<div className="flex py-2 pl-5 pr-3 m-2 flex-row items-center justify-center bg-[#352C45] hover:shadow-inner shadow-blue-500/50 rounded-lg font-poppins leading-[28px] border-b-[#916CCD] border-b-2">
147-
<img alt="data-source" className={"mr-2 h-[20px]"} src={this.props.dataSourceTypesDict[data_source].image_base64}></img>
148-
<h1 className="text-white width-full">{this.props.dataSourceTypesDict[data_source].display_name}</h1>
149+
<img alt="data-source" className={"mr-2 h-[20px]"} src={this.props.dataSourceTypesDict[dataSource.name].image_base64}></img>
150+
<h1 className="text-white width-full">{this.props.dataSourceTypesDict[dataSource.name].display_name}</h1>
149151

150152
{this.state.editMode ? (
151-
<IoMdCloseCircle onClick={this.removeDataSource} className="ml-6 fill-[#df335e] text-2xl hover:fill-[#ff85c2]" />
153+
<IoMdCloseCircle onClick={() => this.removeDataSource(dataSource)} className="transition duration-150 ease-in-out ml-6 fill-[#7d4ac3] hover:cursor-pointer text-2xl hover:fill-[#d80b0b]" />
152154
) : (
153155
<AiFillCheckCircle className="ml-6 text-[#9875d4] text-2xl" />
154156
)
@@ -161,7 +163,7 @@ export default class DataSourcePanel extends React.Component<DataSourcePanelProp
161163
{
162164
Object.keys(this.props.dataSourceTypesDict).map((key) => {
163165
let dataSource = this.props.dataSourceTypesDict[key];
164-
if (!this.props.connectedDataSources.includes(dataSource.name) && !this.state.editMode) {
166+
if (!this.state.editMode && !this.props.connectedDataSources.find((connectedDataSource) => connectedDataSource.name === dataSource.name)) {
165167
return (
166168
// unconnected data source
167169
<div onClick={() => this.dataSourceToAddSelected(dataSource)} className="flex hover:text-[#9875d4] py-2 pl-5 pr-3 m-2 flex-row items-center justify-center bg-[#36323b] hover:border-[#9875d4] rounded-lg font-poppins leading-[28px] border-[#777777] border-b-[.5px] transition duration-300 ease-in-out">
@@ -407,7 +409,7 @@ export default class DataSourcePanel extends React.Component<DataSourcePanelProp
407409
field.value = '';
408410
});
409411
this.setState({ selectedDataSource: selectedDataSource });
410-
this.props.onAdded(this.state.selectedDataSource.value);
412+
this.props.onAdded({name: this.state.selectedDataSource.value, id: response.data});
411413
this.setState({ isAddingLoading: false, isAdding: false, selectedDataSource: this.state.selectOptions[0] });
412414
}).catch(error => {
413415
toast.error("Error adding data source: " + error.response.data, { autoClose: 10000 });
@@ -419,10 +421,19 @@ export default class DataSourcePanel extends React.Component<DataSourcePanelProp
419421
this.setState({ selectedDataSource: event })
420422
}
421423

422-
removeDataSource = () => {
423-
let connected = this.props.connectedDataSources;
424-
let index = connected.indexOf(this.state.selectedDataSource.value);
425-
connected.splice(index, 1);
424+
removeDataSource = (connectedDataSource: ConnectedDataSource) => {
425+
if (this.props.inIndexing) {
426+
toast.error("Cannot remove data source while indexing is in progress");
427+
return;
428+
}
429+
430+
api.delete(`/data-sources/${connectedDataSource.id}`).then(response => {
431+
toast.success(`${this.capitilize(connectedDataSource.name)} removed.`);
432+
this.props.onRemoved(connectedDataSource);
433+
}).catch(error => {
434+
toast.error("Error adding data source: " + error.response.data, { autoClose: 10000 });
435+
this.setState({ isAddingLoading: false });
436+
});
426437
}
427438

428439

ui/src/data-source.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface DataSourceType {
2020
image_base64: string
2121
}
2222

23-
export interface ConnectedDataSourceType {
23+
export interface ConnectedDataSource {
2424
id: number
2525
name: string
2626
}

0 commit comments

Comments
 (0)