Skip to content

Commit

Permalink
use new table in setup. debug setup stages. style filters on explore
Browse files Browse the repository at this point in the history
  • Loading branch information
enjalot committed Apr 25, 2024
1 parent 3929be9 commit 0c0075e
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 245 deletions.
2 changes: 1 addition & 1 deletion latentscope/server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def query():

# Convert DataFrame to a list of dictionaries
rows_json = json.loads(rows[page*per_page:page*per_page+per_page].to_json(orient="records"))
print("ROWS JSON", rows_json)
# print("ROWS JSON", rows_json)

# send back the rows as json
return jsonify({
Expand Down
3 changes: 2 additions & 1 deletion web/src/components/FilterDataTable.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
.filter-data-table {
width: calc(100% - 14px);
display: flex;
flex-direction: column;
padding: 12px 0;
padding-top: 12px;
margin-top: 8px;
border: 1px solid #ccc;
border-radius: 5px;
Expand Down
188 changes: 33 additions & 155 deletions web/src/components/FilterDataTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ FilterDataTable.propTypes = {
indices: PropTypes.array.isRequired,
distances: PropTypes.array,
clusterMap: PropTypes.object,
tagset: PropTypes.object,
clusterLabels: PropTypes.array,
tagset: PropTypes.object,
onTagset: PropTypes.func,
onScope: PropTypes.func,
Expand All @@ -79,8 +79,8 @@ function FilterDataTable({
distances = [],
clusterMap = {},
// clusterIndices = [],
clusterLabels = [],
tagset = {},
clusterLabels,
tagset,
onTagset,
onScope,
onHover,
Expand All @@ -98,7 +98,9 @@ function FilterDataTable({

const [tags, setTags] = useState([])
useEffect(() => {
setTags(Object.keys(tagset))
if(tagset){
setTags(Object.keys(tagset))
}
}, [tagset])

function handleTagClick(tag, index) {
Expand Down Expand Up @@ -128,7 +130,7 @@ function FilterDataTable({
const hydrateIndices = useCallback((indices) => {
// console.log("hydrate!", dataset)
if(dataset && indices.length) {
console.log("fetching query", dataset)
// console.log("fetching query", dataset)
fetch(`${apiUrl}/query`, {
method: 'POST',
headers: {
Expand All @@ -143,47 +145,27 @@ function FilterDataTable({
.then(response => response.json())
.then(data => {
let { rows, totalPages, total } = data;
console.log("rows", rows)
console.log("pages", totalPages, total)
// console.log("rows", rows)
// console.log("pages", totalPages, total)
setPageCount(totalPages)

rows.forEach(r => {
let ri = r["ls_index"]
let cluster = clusterMap[ri]
if(cluster) {
r["ls_cluster"] = cluster
}
})
// if(clusterIndices.length && clusterLabels.length) {
// rows.forEach(r => {
// let ri = r["ls_index"]
// let cli = clusterIndices[ri]
// let cluster = clusterLabels[cli]?.cluster
// r["ls_cluster"] = cluster?.label
// })
// }
if(Object.keys(clusterMap).length){
rows.forEach(r => {
let ri = r["ls_index"]
let cluster = clusterMap[ri]
if(cluster) {
r["ls_cluster"] = cluster
}
})
}

if(distances && distances.length) {
rows.forEach(r => {
let ri = r["ls_index"]
r["ls_distance"] = distances[ri]
})
}

// if(rows.length) {
// let columns = Object.keys(rows[0]).map((c, i) => {
// // console.log("COLUMN", c, i)
// return {
// id: ""+i,
// cell: info => info.getValue(),
// // header: () => "" + c,
// header: c,
// accessorKey: c,
// footer: props => props.column.id,
// }
// })
// console.log("COLUMNS", columns)
// setColumns(columns)
// }
setRows(rows)
})
} else {
Expand All @@ -192,10 +174,15 @@ function FilterDataTable({
}, [dataset, distances, clusterMap, currentPage])

useEffect(() => {
// console.log("refetching hydrate", indices, dataset)
if(dataset && scope) {
if(dataset) {
// console.log("refetching hydrate", indices, dataset)
// console.log("Tagset", tagset)
let columns = ["ls_index", "ls_cluster", "tags", dataset.text_column].concat(dataset.columns.filter(d => d !== dataset.text_column)).map((c, i) => {
let columns = ["ls_index"]
if(scope) columns.push("ls_cluster")
if(tagset && Object.keys(tagset).length) columns.push("tags")
columns.push(dataset.text_column)
columns = columns.concat(dataset.columns.filter(d => d !== dataset.text_column))
let columnDefs = columns.map((c, i) => {
// let columns = dataset.columns.map((c, i) => {
const metadata = dataset.column_metadata ? dataset.column_metadata[c] : null;
// console.log("COLUMN", c, metadata)
Expand Down Expand Up @@ -297,10 +284,12 @@ function FilterDataTable({
footer: props => props.column.id,
}
})
setColumns(columns)
// console.log("COLUMNS", columns, columnDefs)
setColumns(columnDefs)
}
hydrateIndices(indices)
}, [indices, dataset, scope, tagset, tags, currentPage, clusterLabels]) // hydrateIndicies
// }, [ indices, dataset, scope, tagset, tags, currentPage, clusterLabels]) // hydrateIndicies
}, [dataset, indices, tags, scope, tagset, currentPage, clusterLabels])


const [columnFilters, setColumnFilters] = useState([])
Expand Down Expand Up @@ -389,7 +378,6 @@ function FilterDataTable({
// Start: Code to synchronize horizontal scroll
const syncHorizontalScroll = () => {
if (headerRef.current && bodyRef.current) {
console.log("body", bodyRef.current.scrollLeft, "header", headerRef.current.scrollLeft)
headerRef.current.scrollLeft = bodyRef.current.scrollLeft;
}
};
Expand Down Expand Up @@ -490,9 +478,9 @@ function FilterDataTable({
return (
<tr key={row.id}
onMouseEnter={() => {
onHover(row.getValue("0"))
onHover && onHover(row.getValue("0"))
}}
onClick={() => onClick(row.getValue("0"))}
onClick={() => onClick && onClick(row.getValue("0"))}
>
{row.getVisibleCells().map(cell => {
return (
Expand Down Expand Up @@ -531,113 +519,3 @@ function FilterDataTable({
)
}
export default FilterDataTable;

Filter.propTypes = {
column: PropTypes.object.isRequired,
table: PropTypes.object.isRequired,
};

function Filter({ column, table }) {
const firstValue = table
.getPreFilteredRowModel()
.flatRows[0]?.getValue(column.id);
const columnFilterValue = column.getFilterValue();
const sortedUniqueValues = useMemo(
() =>
typeof firstValue === 'number'
? []
: Array.from(column.getFacetedUniqueValues().keys()).sort(),
[column.getFacetedUniqueValues()]
);

return typeof firstValue === 'number' ? (
<div>
<div className="flex space-x-2">
<DebouncedInput
type="number"
min={Number(column.getFacetedMinMaxValues()?.[0] ?? '')}
max={Number(column.getFacetedMinMaxValues()?.[1] ?? '')}
value={(columnFilterValue || [])[0] ?? ''}
onChange={(value) =>
column.setFilterValue((old = []) => [value, old[1]])
}
placeholder={`Min ${
column.getFacetedMinMaxValues()?.[0]
? `(${column.getFacetedMinMaxValues()?.[0]})`
: ''
}`}
className="w-24 border shadow rounded"
/>
<DebouncedInput
type="number"
min={Number(column.getFacetedMinMaxValues()?.[0] ?? '')}
max={Number(column.getFacetedMinMaxValues()?.[1] ?? '')}
value={(columnFilterValue || [])[1] ?? ''}
onChange={(value) =>
column.setFilterValue((old = []) => [old[0], value])
}
placeholder={`Max ${
column.getFacetedMinMaxValues()?.[1]
? `(${column.getFacetedMinMaxValues()?.[1]})`
: ''
}`}
className="w-24 border shadow rounded"
/>
</div>
<div className="h-1" />
</div>
) : (
<>
<datalist id={column.id + 'list'}>
{sortedUniqueValues.slice(0, 5000).map((value) => (
<option value={value} key={value} />
))}
</datalist>
<DebouncedInput
type="text"
value={(columnFilterValue ?? '') + ''}
onChange={(value) => column.setFilterValue(value)}
placeholder={`Search... (${column.getFacetedUniqueValues().size})`}
className="w-36 border shadow rounded"
list={column.id + 'list'}
/>
<div className="h-1" />
</>
);
}


// A debounced input react component
DebouncedInput.propTypes = {
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
onChange: PropTypes.func.isRequired,
debounce: PropTypes.number,
// This is a catch-all for any other props not explicitly defined above but passed to <input />
// It's important for flexibility and usability of the DebouncedInput component in various contexts.
props: PropTypes.object
};

function DebouncedInput({
value: initialValue,
onChange,
debounce = 500,
...props
}) {
const [value, setValue] = useState(initialValue)

useEffect(() => {
setValue(initialValue)
}, [initialValue])

useEffect(() => {
const timeout = setTimeout(() => {
onChange(value)
}, debounce)

return () => clearTimeout(timeout)
}, [value])

return (
<input {...props} value={value} onChange={e => setValue(e.target.value)} />
)
}
19 changes: 11 additions & 8 deletions web/src/components/Setup/Cluster.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ function Cluster({ dataset, cluster, umap, onNew, onChange}) {
const { startJob: startClusterJob } = useStartJobPolling(dataset, setClusterJob, `${apiUrl}/jobs/cluster`);
const { startJob: deleteClusterJob } = useStartJobPolling(dataset, setClusterJob, `${apiUrl}/jobs/delete/cluster`);

const [clusters, setClusters] = useState([]);
const [localCluster, setLocalCluster] = useState(cluster)
useEffect(() => {
setLocalCluster(cluster)
}, [cluster])
if(cluster) {
setLocalCluster(cluster)
} else {
setLocalCluster(clusters[0])
}
}, [cluster, clusters])

const [clusters, setClusters] = useState([]);

function fetchClusters(datasetId, callback) {
fetch(`${apiUrl}/datasets/${datasetId}/clusters`)
Expand All @@ -52,25 +56,24 @@ function Cluster({ dataset, cluster, umap, onNew, onChange}) {
fetchClusters(dataset.id, (clstrs) => {
setClusters(clstrs)
onNew(clstrs)
if(!cluster) setLocalCluster(clstrs[0])
})
}, [dataset, onNew, cluster]);
}, [dataset, onNew]);

useEffect(() => {
if(clusterJob?.status == "completed") {
fetchClusters(dataset.id, (clstrs) => {
setClusters(clstrs)
let cls;
if(clusterJob.job_name == "cluster"){
cls = clstrs.find(d => d.id == clusterJob.run_id)
} else if(clusterJob.job_name == "rm") {
cls = clstrs[0]
}
setLocalCluster(cls)
setClusters(clstrs)
onNew(clstrs)
if(!cluster) setLocalCluster(cls)
})
}
}, [clusterJob, dataset, setClusters, onNew, cluster, setLocalCluster]);
}, [clusterJob, dataset, setClusters, onNew]);

const handleNewCluster = useCallback((e) => {
e.preventDefault()
Expand Down
24 changes: 13 additions & 11 deletions web/src/components/Setup/ClusterLabels.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,19 @@ function ClusterLabels({ dataset, cluster, embedding, selectedLabelId, onChange,
data.cluster_id = cluster.id
setClusterLabels(data)
}).catch(err => {
console.log(err)
console.log("ERROR", err)
setClusterLabels([])
})
} else {
setClusterLabels([])
}
}, [localSelected, setClusterLabels, dataset, cluster, clusterLabelSets])
} else {
setClusterLabels([])
}
}, [localSelected, dataset, cluster, clusterLabelSets])

useEffect(() => {
if(clusterLabels?.length) {
onLabels(clusterLabels)
}
}, [clusterLabels, onLabels])

useEffect(() => {
if(cluster) {
Expand Down Expand Up @@ -98,8 +104,8 @@ function ClusterLabels({ dataset, cluster, embedding, selectedLabelId, onChange,
lbl = { id: "default" }
}
// onLabelSets(labelsAvailable, lbl)
onLabelSets(labelsAvailable)
setClusterLabelSets(labelsAvailable)
onLabelSets(labelsAvailable)
}).catch(err => {
console.log(err)
setClusterLabelSets([])
Expand All @@ -111,11 +117,7 @@ function ClusterLabels({ dataset, cluster, embedding, selectedLabelId, onChange,
}
}, [dataset, cluster, clusterLabelsJob, setClusterLabelSets, onLabelSets])

useEffect(() => {
if(clusterLabels?.length) {
onLabels(clusterLabels)
}
}, [clusterLabels, onLabels])



const handleNewLabels= useCallback((e) => {
Expand Down
Loading

0 comments on commit 0c0075e

Please sign in to comment.