Skip to content

Commit

Permalink
Replace antd components with MUI and delete unused code (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
vegito22 authored Sep 15, 2023
1 parent 071ec3e commit 9cf09a6
Show file tree
Hide file tree
Showing 30 changed files with 861 additions and 2,472 deletions.
149 changes: 149 additions & 0 deletions base/management/commands/deletetempvectordata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import json
import re
from datetime import datetime
from typing import Any
from typing import Dict
from typing import List
from typing import Optional

import requests
import weaviate
from django.core.management.base import BaseCommand
from pydantic import BaseModel
from pydantic import Field
from django.conf import settings


WEAVIATE_URL = settings.WEAVIATE_URL
DEFAULT_TIME_CUTOFF_MINS = 24 * 60

client = weaviate.Client(WEAVIATE_URL)


class WeaviateClassObject(BaseModel):
className: str = Field(..., alias='class')
creationTimeUnix: int = Field(..., alias='creationTimeUnix')
id: str = Field(..., alias='id')
lastUpdateTimeUnix: int = Field(..., alias='lastUpdateTimeUnix')
properties: Dict[str, Any]
vectorWeights: Optional[Dict[str, Any]] = None
vector: Optional[List[Any]]


class WeaviateClass(BaseModel):
className: str = Field(..., alias='class')
description: Optional[str] = None
invertedIndexConfig: Optional[Dict] = None
moduleConfig: Optional[Dict] = None
properties: Optional[List[Any]] = None
replicationConfig: Optional[Dict] = None
shardingConfig: Optional[Dict] = None
vectorIndexConfig: Optional[Dict] = None
vectorIndexType: Optional[str] = None
vectorizer: Optional[str] = None
objects: Optional[List[WeaviateClassObject]] = None


class WeaviateSchema(BaseModel):
classes: List[WeaviateClass]


def get_schema():
url = f'{WEAVIATE_URL}/v1/schema'
return requests.get(url).json()


def get_objects(class_name, limit=1000, last_document_id=None):
if last_document_id:
url = f'{WEAVIATE_URL}/v1/objects/?class={class_name}&limit={limit}&after={last_document_id}&include=classification,vector'
else:
url = f'{WEAVIATE_URL}/v1/objects/?class={class_name}&limit={limit}&include=classification,vector'
result = requests.get(url).json()
if len(result['objects']) > 0:
last_document_id = result['objects'][-1]['id']
result['objects'] += get_objects(class_name, limit, last_document_id)
return result['objects']


def get_class(class_name):
return get_objects(class_name)


class Command(BaseCommand):
help = 'Delete temp data from vector store.'

def add_arguments(self, parser):
parser.add_argument(
'--not-dry-run', action='store_true',
help='Do not perform any actions, just print what would be done.',
)

parser.add_argument(
'--duration',
type=str,
default='7 days',
help='Specify the duration in the format "X days" or "Y mins".'
)

def parse_duration(self, duration_str):
# Use regular expressions to parse the input duration string
match = re.match(r'^(\d+)\s*(days?|mins?)$', duration_str, re.IGNORECASE)
if not match:
raise ValueError('Invalid duration format. Use "X days" or "Y mins".')

value, unit = match.groups()
value = int(value)
if unit.lower() == 'mins':
return value * 60 # Convert minutes to seconds
elif unit.lower() == 'days':
return value * 86400 # Convert days to seconds

def handle(self, *args, **options):
dry_run = not options['not_dry_run']
duration_str = options.get('duration', '')

if dry_run:
self.stdout.write('Running in dry-run mode.')

if duration_str:
try:
duration_seconds = self.parse_duration(duration_str)
duration_minutes = int(duration_seconds / 60)
self.stdout.write(f'Duration: {duration_minutes} minutes.')
except ValueError as e:
self.stderr.write(str(e))
return

now = int(datetime.utcnow().timestamp()) * 1000
weaviate_schema = WeaviateSchema(**get_schema())
for wclass in weaviate_schema.classes:
objects = list(
map(
lambda x: WeaviateClassObject(
**x,
), get_class(wclass.className),
),
)
wclass.objects = objects

for wclass in weaviate_schema.classes:
if wclass.className.startswith('Temp_'):
lastUpdateTimestamps = []
object_ids = []
for object in wclass.objects:
# add delta in minutes
object_ids.append(object.id)
lastUpdateTimestamps.append(int((now - object.lastUpdateTimeUnix) / 1000 / 60))
lastUpdateTimestamps.sort()
if len(lastUpdateTimestamps) > 0 and lastUpdateTimestamps[0] > duration_minutes:
self.stdout.write(f'Deleting {wclass.className}...')
self.stdout.write(f'Deleting Objects {" ".join(object_ids)}..."')
result = client.batch.delete_objects(class_name=wclass.className, where={
'path': ['source'],
'operator': 'Like',
'valueString': '*'
}, dry_run=dry_run)
self.stdout.write(json.dumps(result, indent=2))



108 changes: 65 additions & 43 deletions client/src/components/ApiBackendSelector.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import { useEffect } from "react";
import { Col, Select, Row } from "antd";

import {
Grid,
Select,
MenuItem,
Box,
FormControl,
InputLabel,
} from "@mui/material";
import {
useRecoilValue,
useRecoilState,
useSetRecoilState,
useResetRecoilState,
} from "recoil";

import {
apiProviderDropdownListState,
apiBackendDropdownListState,
Expand Down Expand Up @@ -75,49 +84,62 @@ export default function ApiBackendSelector() {
]);

return (
<Col id="apibackendselector">
<Row>
<Select
style={{ width: "auto" }}
options={apiprovidersDropdown}
onChange={(x) => {
setApiProviderSelected(x);
setApiBackendSelected(null);
setendpointConfigValueState({});
resetInputValueState();
}}
value={
apiProviderSelected ? apiProviderSelected : "Select API Provider"
}
/>
<Grid item id="apibackendselector">
<Grid container direction="row">
<Box sx={{ minWidth: 150 }}>
<FormControl fullWidth>
<InputLabel id="select-api-provider-label">API Provider</InputLabel>
<Select
style={{ width: "auto" }}
onChange={(e) => {
setApiProviderSelected(e.target.value);
setApiBackendSelected(null);
setendpointConfigValueState({});
resetInputValueState();
}}
value={apiProviderSelected ? apiProviderSelected : ""}
label="Select API Provider"
>
{apiprovidersDropdown.map((option, index) => (
<MenuItem key={index} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
</Box>

{apiProviderSelected && (
<Select
style={{ width: 150 }}
options={
apiProviderSelected
? apibackendsDropdown.filter(
(x) => x.provider === apiProviderSelected,
)
: apibackendsDropdown
}
onChange={(x) => {
setApiBackendSelected(
apibackends.find((backend) => backend.id === x),
);
setendpointConfigValueState({});
resetEndpointConfigValueState();
resetInputValueState();
}}
value={
apiBackendSelected
? apibackendsDropdown.find(
(x) => x.value === apiBackendSelected.id,
)
: "Select Backend"
}
/>
<Box sx={{ minWidth: 150 }}>
<FormControl fullWidth>
<InputLabel id="select-api-backend-label">API Backend</InputLabel>
<Select
style={{ width: 150 }}
onChange={(e) => {
setApiBackendSelected(
apibackends.find(
(backend) => backend.id === e.target.value,
),
);
setendpointConfigValueState({});
resetEndpointConfigValueState();
resetInputValueState();
}}
value={apiBackendSelected ? apiBackendSelected.id : ""}
label="Select API Backend"
>
{apibackendsDropdown
.filter((x) => x.provider === apiProviderSelected)
.map((option, index) => (
<MenuItem key={index} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
</Box>
)}
</Row>
</Col>
</Grid>
</Grid>
);
}
75 changes: 37 additions & 38 deletions client/src/components/ConfigForm.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { Empty, Tabs } from "antd";
import * as React from "react";

import { Box, Tab } from "@mui/material";
import { TabContext, TabList, TabPanel } from "@mui/lab";

import { useRecoilState } from "recoil";
import AceEditor from "react-ace";
import validator from "@rjsf/validator-ajv8";
Expand All @@ -8,6 +12,7 @@ import "ace-builds/src-noconflict/theme-chrome";
import ThemedJsonForm from "./ThemedJsonForm";
import { endpointConfigValueState } from "../data/atoms";
import CustomObjectFieldTemplate from "../components/ConfigurationFormObjectFieldTemplate";
import { Empty as EmptyComponent } from "../components/form/Empty";

export function ThemedForm(props) {
const [data, setData] = useRecoilState(endpointConfigValueState);
Expand Down Expand Up @@ -47,17 +52,9 @@ export function ThemedJsonEditor() {
);
}

function EmptyComponent(props) {
return (
<Empty
image={Empty.PRESENTED_IMAGE_DEFAULT}
description={props.emptyMessage ? props.emptyMessage : "Schema not found"}
style={{ color: "#838383" }}
/>
);
}

export default function ConfigForm(props) {
const [value, setValue] = React.useState("form");

let schema = props.schema ? JSON.parse(JSON.stringify(props.schema)) : {};

if (props?.schema?.title) {
Expand All @@ -67,32 +64,34 @@ export default function ConfigForm(props) {
}

return (
<Tabs
type="card"
style={{ width: "100%" }}
defaultActiveKey="1"
items={[
{
key: "1",
label: "Config Form",
children:
Object.keys(props.schema).length === 0 ? (
<EmptyComponent {...props} />
) : (
<ThemedForm schema={schema} uiSchema={props.uiSchema} />
),
},
{
key: "2",
label: "JSON",
children:
Object.keys(props.schema).length === 0 ? (
<EmptyComponent {...props} />
) : (
<ThemedJsonEditor {...props} />
),
},
]}
/>
<Box sx={{ width: "100%" }}>
<TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<TabList
onChange={(event, newValue) => {
setValue(newValue);
}}
aria-label="Config form tabs"
>
<Tab label="Config Form" value="form" />
<Tab label="JSON" value="json" />
</TabList>
</Box>
<TabPanel value="form" sx={{ padding: "4px" }}>
{Object.keys(props.schema).length === 0 ? (
<EmptyComponent {...props} />
) : (
<ThemedForm schema={schema} uiSchema={props.uiSchema} />
)}
</TabPanel>
<TabPanel value="json" sx={{ padding: "4px" }}>
{Object.keys(props.schema).length === 0 ? (
<EmptyComponent {...props} />
) : (
<ThemedJsonEditor {...props} />
)}
</TabPanel>
</TabContext>
</Box>
);
}
Loading

0 comments on commit 9cf09a6

Please sign in to comment.