Skip to content
Snippets Groups Projects
Commit fcce6ff0 authored by Marcos Pieras's avatar Marcos Pieras Committed by Scott
Browse files

feat(0D_vis): add table visualization of row-node

solves #DEV-209, #DEV-218
parent 1413734f
No related branches found
No related tags found
No related merge requests found
import React , { useRef } from 'react';
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
interface PaginationProps {
currentPage: number;
totalPages: number;
onPageChange: (page: number) => void;
itemsPerPageInput: number;
numItemsArrayReal: number;
totalItems : number;
}
const Pagination: React.FC<PaginationProps> = ({ currentPage,
totalPages,
onPageChange,
itemsPerPageInput,
numItemsArrayReal,
totalItems }) => {
const pageNumbers = Array.from({ length: totalPages }, (_, index) => index + 1);
const firstItem = (currentPage - 1) * itemsPerPageInput + 1;
const lastItem = Math.min(currentPage * itemsPerPageInput, totalPages);
const goToPreviousPage = () => {
if (currentPage > 1) {
onPageChange(currentPage - 1);
}
};
const goToNextPage = () => {
if (currentPage < totalPages) {
onPageChange(currentPage + 1);
}
};
return (
<div className="table-pagination">
<span className="inline-block m-2 max-w-32 min-w-32">
{`${firstItem}-${numItemsArrayReal} of ${totalItems}`}
</span>
<button className = "m-1 border-4 border-solid border-neutral p-2 w-11 text-primary" onClick={goToPreviousPage} disabled={currentPage === 1}>
<ArrowBackIosIcon />
</button>
<button className = "m-1 border-4 border-solid border-neutral p-2 w-11 text-primary" onClick={goToNextPage} disabled={currentPage === totalPages}>
<ArrowForwardIosIcon />
</button>
</div>
);
};
export default Pagination;
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import Pagination from './Pagination';
interface TableProps {
data: any[];
itemsPerPage: number;
}
const Table: React.FC<TableProps> = ({ data, itemsPerPage }) => {
const originalData = [...data];
const [sortedData, setSortedData] = useState<any[]>(data);
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('asc');
const [sortColumn, setSortColumn] = useState<string | null>(null);
const [currentPage, setCurrentPage] = useState<number>(1);
const keys = Object.keys(data[0]);
const totalPages = Math.ceil(sortedData.length / itemsPerPage);
useEffect(() => {
if (sortColumn !== null) {
const sorted = [...data].sort((a, b) => {
if (sortOrder === 'asc') {
return a[sortColumn] < b[sortColumn] ? -1 : 1;
} else {
return a[sortColumn] > b[sortColumn] ? -1 : 1;
}
});
setSortedData(sorted);
}
}, [sortOrder, data, sortColumn]);
useEffect(() => {
setCurrentPage(1); // Reset to the first page when sorting or itemsPerPage changes
}, [sortColumn, sortOrder, itemsPerPage]);
const onPageChange = (page: number) => {
setCurrentPage(page);
};
const toggleSort = (column: string) => {
if (sortColumn === column) {
if (sortOrder === 'asc') {
setSortOrder('desc');
setSortedData([...sortedData].reverse()); // Reverse the sorted data
} else if (sortOrder === 'desc') {
setSortColumn(null);
setSortOrder('asc');
setSortedData(originalData); // Reset to the original order
}
} else {
setSortColumn(column);
setSortOrder('asc');
const sorted = [...originalData].sort((a, b) => {
return a[column] < b[column] ? -1 : 1;
});
setSortedData(sorted);
}
};
// Calculate the startIndex and endIndex based on currentPage and itemsPerPage
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const currentData = sortedData.slice(startIndex, endIndex);
function isString(value: any): boolean {
return typeof value === 'string';
}
return (
<div className = "text-center font-inter text-primary">
<table className="text-center my-2 mx-auto table-fixed w-11/12" >
<thead className="thead">
<tr className="bg-white text-center p-0 pl-2 border-0 h-2 font-weight: 700">
{keys.map((item, index) => (
<th
className="th"
key={index}
onClick={() => toggleSort(item)}
>
{item}{' '}
{sortColumn === item && (
<span>{sortOrder === 'asc' ? '' : ''}</span>
)
}
</th>
))}
</tr>
</thead>
<tbody className="border-l-2 border-t-2 border-r-2 border-b-2 border-white w-20">
{currentData.map((obj, index) => (
<tr key={index} className={index % 2 === 0 ? "bg-secondary" : "bg-base-100"}>
{keys.map((item, index) => (
<td className={`${isString(obj[item]) ? 'text-left' : 'text-center'} px-1 py-0.5 border border-white m-0 overflow-x-hidden truncate`}
key={index}
>
{obj[item]}
</td>
))
}
</tr>
))}
</tbody>
</table>
<Pagination
currentPage={currentPage}
totalPages={totalPages}
onPageChange={onPageChange}
itemsPerPageInput = {itemsPerPage}
numItemsArrayReal = {startIndex+currentData.length}
totalItems={sortedData.length}
/>
</div>
);
};
export default Table;
import { useGraphQueryResult } from '../../data-access/store';
import React, { useRef } from 'react';
import Table from './components/Table';
export const SimpleTableVis = React.memo(() => {
const ref = useRef<HTMLDivElement>(null);
const graphQueryResult = useGraphQueryResult();
const nodes = graphQueryResult.nodes;
const attributesArray = nodes.map((node) => node.attributes);
return (
<>
<div className="h-full w-full overflow-hidden" ref={ref}>
{attributesArray.length > 0 && <Table data={attributesArray} itemsPerPage ={10} />}
</div>
</>
);
});
SimpleTableVis.displayName = 'SimepleTableVis';
export default SimpleTableVis;
import React from 'react';
import { Meta } from '@storybook/react';
import { SimpleTableVis } from './simpleTable';
import { assignNewGraphQueryResult, graphQueryResultSlice, resetGraphQueryResults, store } from '../../data-access/store';
import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import { big2ndChamberQueryResult, smallFlightsQueryResults, mockLargeQueryResults, bigMockQueryResults } from '../../mock-data';
const Component: Meta<typeof SimpleTableVis> = {
/* 👇 The title prop is optional.
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
* to learn how to generate automatic titles
*/
title: 'Components/Visualizations/SimpleTableVis',
component: SimpleTableVis,
decorators: [
(story) => (
<Provider store={Mockstore}>
<div
style={{
width: '100%',
height: '100vh',
}}
>
{story()}
</div>
</Provider>
),
],
};
const Mockstore = configureStore({
reducer: {
graphQueryResult: graphQueryResultSlice.reducer,
},
});
export const TestWithBig2ndChamber = {
args: { loading: false },
play: async () => {
const dispatch = Mockstore.dispatch;
dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: big2ndChamberQueryResult } }));
},
};
export default Component;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment