Skip to content

Commit

Permalink
GUI related modification[Implemented Filter, Sorting and Loader widge…
Browse files Browse the repository at this point in the history
…t, Fixed Scrollbar alignment issue and SVG image related issue] and removed cmf server related functions from public api doc (#205)

* Added loader, filter and sorting functionality inside GUI

* Fixed scroll bar issue

* Fixed loader issue inside lineage section

* Removing server side API's from cmf.md

* Modified css for loader component

* Fixed svg related lineage image for artifact and execution tree

* Added loader, filter and sorting functionality inside GUI

* Fixed scroll bar issue

* Fixed loader issue inside lineage section

* Removing server side API's from cmf.md

* Modified css for loader component

* Fixed svg related lineage image for artifact and execution tree

* Resolved sorting arrow related issue

* Changed css related sorting arrow
  • Loading branch information
AyeshaSanadi authored Oct 14, 2024
1 parent e559799 commit 7ead2ba
Show file tree
Hide file tree
Showing 12 changed files with 380 additions and 282 deletions.
6 changes: 0 additions & 6 deletions docs/api/public/cmf.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,12 @@
members:
- __init__
- create_context
- merge_created_context
- create_execution
- update_execution
- merge_created__execution
- log_dataset
- log_dataset_with_version
- log_model
- log_model_with_version
- log_execution_metrics_from_client
- log_execution_metrics
- log_metric
- commit_existing_metrics
- create_dataslice
- update_dataslice

Expand Down
2 changes: 1 addition & 1 deletion ui/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<div id="root" style="overflow-x: hidden; overflow-y: scroll;"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
Expand Down
62 changes: 32 additions & 30 deletions ui/src/components/ArtifactTable/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,11 @@ import config from "../../config";

const client = new FastAPIClient(config);

const ArtifactTable = ({ artifacts, ArtifactType, onSort, onFilter }) => {
const ArtifactTable = ({ artifacts, ArtifactType, onSort }) => {

// Default sorting order
const [sortOrder, setSortOrder] = useState("Context_Type");

// Local filter value state
const [filterValue, setFilterValue] = useState("");
const [sortOrder, setSortOrder] = useState(onSort);
const [sortedData, setSortedData] = useState([]);

const [expandedRow, setExpandedRow] = useState(null);
const [showPopup, setShowPopup] = useState(false);
Expand All @@ -41,20 +39,25 @@ const ArtifactTable = ({ artifacts, ArtifactType, onSort, onFilter }) => {

useEffect(() => {
// Set initial sorting order when component mounts
setSortOrder("asc");
}, []);
setSortedData([...artifacts]);
}, [artifacts]);

const handleSort = () => {
const newSortOrder = sortOrder === "asc" ? "desc" : "asc";
// Initially all data is in mixed format
// After the data is in asc order
// then it is in desc order
const newSortOrder = sortOrder === "desc" ? "asc" : sortOrder === "asc" ? "desc" : "asc";
setSortOrder(newSortOrder);
onSort("name", newSortOrder); // Notify parent component about sorting change
const sorted = [...artifacts].sort((a, b) => {
if(newSortOrder === "asc"){
return a.name.localeCompare(b.name);
}else{
return b.name.localeCompare(a.name);
}
});
setSortedData(sorted); // Notify parent component about sorting change
};

const handleFilterChange = (event) => {
const value = event.target.value;
setFilterValue(value);
onFilter("name", value); // Notify parent component about filter change
};

const toggleRow = (rowId) => {
if (expandedRow === rowId) {
Expand All @@ -75,19 +78,19 @@ const ArtifactTable = ({ artifacts, ArtifactType, onSort, onFilter }) => {
const handleClosePopup = () => {
setShowPopup(false);
};


const renderArrow = () => {
if (sortOrder === "desc"){
return <span className="text-2xl cursor-pointer">&#8595;</span> //data is in desc order ---> ↓
} else if (sortOrder === "asc"){
return <span className="text-2xl cursor-pointer">&#8593;</span> //data is in asc order ----> ↑
} else{
return <span className="text-2xl cursor-pointer">&#8597;</span> //data is in initial order -----------> ↕
}
}

return (
<div className="container flex flex-col mx-auto p-6 mr-4">
<div className="flex flex-col items-end m-1">
<input
type="text"
value={filterValue}
onChange={handleFilterChange}
placeholder="Filter by Name"
className="w-64 px-1 border-2 border-gray"
/>
</div>
<div className="container flex flex-col">
<div className="overflow-x-auto">
<div className="p-1.5 w-full inline-block align-middle">
<table className="min-w-full divide-y divide-gray-200 border-4">
Expand All @@ -102,8 +105,7 @@ const ArtifactTable = ({ artifacts, ArtifactType, onSort, onFilter }) => {
onClick={handleSort}
className="name px-6 py-3"
>
name {sortOrder === "asc" && <span className="arrow">&#8593;</span>}
{sortOrder === "desc" && <span className="arrow">&#8595;</span>}
name&nbsp; {renderArrow()}
</th>
{ArtifactType === "Model" && (
<th scope="col" className="model_card px-6 py-3">
Expand All @@ -129,13 +131,13 @@ const ArtifactTable = ({ artifacts, ArtifactType, onSort, onFilter }) => {
</tr>
</thead>
<tbody className="body divide-y divide-gray-200">
{artifacts.length > 0 && artifacts.map((data, index) => (
{sortedData.length > 0 && sortedData.map((data, index) => (
<React.Fragment key={index}>
<tr
key={index}
className="text-sm font-medium text-gray-800"
>
<td className="px-6 py-4" onClick={() => toggleRow(index)}>
<td className="px-6 py-4 cursor-pointer" onClick={() => toggleRow(index)}>
{expandedRow === index ? "-" : "+"}
</td>
<td className="px-6 py-4">{data.id}</td>
Expand Down Expand Up @@ -190,4 +192,4 @@ const ArtifactTable = ({ artifacts, ArtifactType, onSort, onFilter }) => {
);
};

export default ArtifactTable;
export default ArtifactTable;
47 changes: 32 additions & 15 deletions ui/src/components/ExecutionTable/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,34 @@
import React, { useState, useEffect } from "react";
import "./index.css";

const ExecutionTable = ({ executions, onSort, onFilter }) => {

// Default sorting order
const [sortOrder, setSortOrder] = useState("Context_Type");
const ExecutionTable = ({ executions, onSort, onFilter}) => {

// Default sorting order
const [sortOrder, setSortOrder] = useState(onSort);
const [sortedData, setSortedData] = useState([]);
// Local filter value state
const [filterValue, setFilterValue] = useState("");

const [expandedRow, setExpandedRow] = useState(null);

const consistentColumns = [];

useEffect(() => {
// Set initial sorting order when component mounts
setSortOrder("asc");
}, []);
setSortedData([...executions]);
}, [executions]);


const handleSort = () => {
const newSortOrder = sortOrder === "asc" ? "desc" : "asc";
const newSortOrder = sortOrder === "desc" ? "asc" : sortOrder === "asc" ? "desc" : "asc";
setSortOrder(newSortOrder);
onSort("Context_Type", newSortOrder); // Notify parent component about sorting change
const sorted = [...executions].sort((a, b) => {
if(newSortOrder === "asc"){
return a.Context_Type.localeCompare(b.Context_Type);
}else{
return b.Context_Type.localeCompare(a.Context_Type);
}
});
setSortedData(sorted); // Notify parent component about sorting change
};

const handleFilterChange = (event) => {
Expand All @@ -56,13 +63,24 @@ const ExecutionTable = ({ executions, onSort, onFilter }) => {
}
};

const renderArrow = () => {
if (sortOrder === "desc"){
return <span className="text-2xl cursor-pointer">&#8595;</span> //data is in desc order ---> ↓
} else if (sortOrder === "asc"){
return <span className="text-2xl cursor-pointer">&#8593;</span> //data is in asc order ----> ↑
} else{
return <span className="text-2xl cursor-pointer">&#8597;</span> //data is in initial order -----------> ↕
}
}

return (
<div className="flex flex-col">
<div
style={{
display: "flex",
justifyContent: "flex-end",
marginBottom: "1rem",
marginBottom: "0.5rem",
marginTop: "0.5rem",
}}
>
<input
Expand All @@ -88,8 +106,7 @@ const ExecutionTable = ({ executions, onSort, onFilter }) => {
onClick={handleSort}
className="px-6 py-3 Context_Type"
>
Context_Type {sortOrder === "asc" && <span className="arrow">&#8593;</span>}
{sortOrder === "desc" && <span className="arrow">&#8595;</span>}
Context_Type&nbsp; {renderArrow()}
</th>
<th scope="col" className="px-6 py-3 Execution">
Execution
Expand All @@ -106,14 +123,14 @@ const ExecutionTable = ({ executions, onSort, onFilter }) => {
</tr>
</thead>
<tbody className="body divide-y divide-gray-200">
{executions.map((data, index) => (
{sortedData.map((data, index) => (
<React.Fragment key={index}>
<tr
key={index}
onClick={() => toggleRow(index)}
className="text-sm font-medium text-gray-800"
>
<td classname="px-6 py-4">
<td className="px-6 py-4 cursor-pointer">
{expandedRow === index ? "-" : "+"}
</td>
<td className="px-6 py-4">{data.Context_Type}</td>
Expand Down Expand Up @@ -160,4 +177,4 @@ const ExecutionTable = ({ executions, onSort, onFilter }) => {
);
};

export default ExecutionTable;
export default ExecutionTable;
3 changes: 1 addition & 2 deletions ui/src/components/ExecutionTree/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ const constructTangleLayout = (levels, options = {}) => {
l.xt = l.target.x;
l.yt = l.target.y + l.target.bundles_index[l.bundle.id].i * metro_d - (l.target.bundles.length * metro_d) / 2 + metro_d / 2;
l.xb = l.bundle.x;
l.yb = l.bundle.y;
l.xs = l.source.x;
l.ys = l.source.y;
});
Expand All @@ -130,7 +129,7 @@ const constructTangleLayout = (levels, options = {}) => {
links.forEach(l => {
l.yt = l.target.y + l.target.bundles_index[l.bundle.id].i * metro_d - (l.target.bundles.length * metro_d) / 2 + metro_d / 2;
l.ys = l.source.y;
l.c1 = l.source.level - l.target.level > 1 ? Math.min(options.bigc, l.xb - l.xt, l.yb - l.yt) - c : c;
l.c1 = c;
l.c2 = c;
});

Expand Down
29 changes: 29 additions & 0 deletions ui/src/components/Loader/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.loader-container {
position: relative; /* Relative positioning for the loader to be placed absolutely inside */
width: 100%;
height: 100%; /* Ensure it takes the full height of its parent */
}

/* Loader is absolutely positioned within the loader-container */
.loader {
position: absolute;
top: 100%;
left: 50%;
transform: translate(-50%, -50%); /* Center the loader */
border: 8px solid #f3f3f3;
border-top: 8px solid #3498db;
border-radius: 50%;
width: 100px; /* Size of the loader */
height: 100px; /* Size of the loader */
animation: spin 1.5s linear infinite;
z-index: 9999; /* Ensure it appears on top */
}

@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
21 changes: 8 additions & 13 deletions ui/src/components/Loader/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,14 @@
***/


import React from "react";
import React from 'react';
import './index.css';

function Loader() {
return (
<div className="flex justify-center items-center h-screen w-screen bg-white">
<img
src="https://thumbs.gfycat.com/HugeDeliciousArchaeocete-max-1mb.gif"
alt="Test data"
width={"auto"}
height={"auto"}
/>
</div>
);
}
const Loader = () => (
<div className="loader-container">
<div className="loader"></div>
</div>
);

export default Loader;

10 changes: 6 additions & 4 deletions ui/src/components/TangledTree/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,12 @@ const constructTangleLayout = (levels, options = {}) => {
i += l.length;
});

// establish the basic structure and position
links.forEach(l => {
l.xt = l.target.x;
l.yt = l.target.y + l.target.bundles_index[l.bundle.id].i * metro_d - (l.target.bundles.length * metro_d) / 2 + metro_d / 2;
l.xb = l.bundle.x;
l.yb = l.bundle.y;
l.xs = l.source.x;
l.ys = l.source.y;
});

var y_negative_offset = 0;
Expand All @@ -127,10 +126,11 @@ const constructTangleLayout = (levels, options = {}) => {
l.forEach(n => (n.y -= y_negative_offset));
});

// Fine tune the visual appearance of link (how the links need to display in svg)
links.forEach(l => {
l.yt = l.target.y + l.target.bundles_index[l.bundle.id].i * metro_d - (l.target.bundles.length * metro_d) / 2 + metro_d / 2;
l.ys = l.source.y;
l.c1 = l.source.level - l.target.level > 1 ? Math.min(options.bigc, l.xb - l.xt, l.yb - l.yt) - c : c;
l.c1 = c;
l.c2 = c;
});

Expand All @@ -151,10 +151,12 @@ const renderChart = (data, options = {}) => {
options.background_color ||= 'white'; // Default background color

const tangleLayout = constructTangleLayout(_.cloneDeep(data), options);

tangled_width = tangleLayout.layout.width;
tangled_height = tangleLayout.layout.height;
const textPadding = 12;
const labelOffset = 4;
const svg_width = (tangled_width + textPadding * 10) < 1000 ? `${tangled_width + textPadding * 50}` : `${tangled_width + textPadding * 10}`;
return (
<>
<style>
Expand All @@ -171,7 +173,7 @@ const renderChart = (data, options = {}) => {
}
`}
</style>
<svg width={tangled_width + textPadding * 10} height={tangled_height + textPadding * 10}>
<svg width={svg_width} height={tangled_height + textPadding * 10}>
{tangleLayout.bundles.map((b, i) => {
let d = b.links
.map(
Expand Down
Loading

0 comments on commit 7ead2ba

Please sign in to comment.