mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
start adding response parsing & ui elements
This commit is contained in:
39
hyperglass/ui/components/Table/MainTable.js
Normal file
39
hyperglass/ui/components/Table/MainTable.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/*@jsx jsx*/
|
||||
import { jsx } from "@emotion/core";
|
||||
import { Box, css, useTheme, useColorMode } from "@chakra-ui/core";
|
||||
|
||||
const scrollbar = { dark: "whiteAlpha.300", light: "blackAlpha.300" };
|
||||
const scrollbarHover = { dark: "whiteAlpha.400", light: "blackAlpha.400" };
|
||||
const scrollbarBg = { dark: "whiteAlpha.50", light: "blackAlpha.50" };
|
||||
|
||||
const MainTable = ({ children, ...props }) => {
|
||||
const theme = useTheme();
|
||||
const { colorMode } = useColorMode();
|
||||
return (
|
||||
<Box
|
||||
css={css({
|
||||
"&::-webkit-scrollbar": { height: "5px" },
|
||||
"&::-webkit-scrollbar-track": {
|
||||
backgroundColor: scrollbarBg[colorMode]
|
||||
},
|
||||
"&::-webkit-scrollbar-thumb": {
|
||||
backgroundColor: scrollbar[colorMode]
|
||||
},
|
||||
"&::-webkit-scrollbar-thumb:hover": {
|
||||
backgroundColor: scrollbarHover[colorMode]
|
||||
},
|
||||
|
||||
"-ms-overflow-style": { display: "none" }
|
||||
})(theme)}
|
||||
overflow="auto"
|
||||
borderRadius="md"
|
||||
boxSizing="border-box"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
MainTable.displayName = "MainTable";
|
||||
export default MainTable;
|
24
hyperglass/ui/components/Table/TableBody.js
Normal file
24
hyperglass/ui/components/Table/TableBody.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import * as React from "react";
|
||||
import { Box } from "@chakra-ui/core";
|
||||
import css from "@styled-system/css";
|
||||
|
||||
const TableBody = ({ children, ...props }) => {
|
||||
return (
|
||||
<Box
|
||||
as="tbody"
|
||||
overflowY="scroll"
|
||||
css={css({
|
||||
"&::-webkit-scrollbar": { display: "none" },
|
||||
"&": { "-ms-overflow-style": "none" }
|
||||
})}
|
||||
overflowX="hidden"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
TableBody.displayName = "TableBody";
|
||||
|
||||
export default TableBody;
|
52
hyperglass/ui/components/Table/TableCell.js
Normal file
52
hyperglass/ui/components/Table/TableCell.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import * as React from "react";
|
||||
import { Box, useColorMode } from "@chakra-ui/core";
|
||||
|
||||
// export const TableCell = styled("div")`
|
||||
// ${space};
|
||||
// ${color};
|
||||
// ${justifyContent};
|
||||
// flex: 1;
|
||||
// display: flex;
|
||||
// min-width: 150px;
|
||||
// align-items: center;
|
||||
// border-bottom-width: 1px;
|
||||
// overflow: hidden;
|
||||
// text-overflow: ellipsis;
|
||||
// `;
|
||||
|
||||
const cellBorder = {
|
||||
dark: { borderLeft: "1px", borderLeftColor: "whiteAlpha.100" },
|
||||
light: { borderLeft: "1px", borderLeftColor: "blackAlpha.100" }
|
||||
};
|
||||
|
||||
const TableCell = ({
|
||||
bordersVertical = [false, 0, 0],
|
||||
align,
|
||||
cell,
|
||||
children,
|
||||
...props
|
||||
}) => {
|
||||
const { colorMode } = useColorMode();
|
||||
const [doVerticalBorders, index] = bordersVertical;
|
||||
let borderProps = {};
|
||||
if (doVerticalBorders && index !== 0) {
|
||||
borderProps = cellBorder[colorMode];
|
||||
}
|
||||
return (
|
||||
<Box
|
||||
as="td"
|
||||
p={4}
|
||||
m={0}
|
||||
w="1%"
|
||||
whiteSpace="nowrap"
|
||||
{...borderProps}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
TableCell.displayName = "TableCell";
|
||||
|
||||
export default TableCell;
|
29
hyperglass/ui/components/Table/TableHead.js
Normal file
29
hyperglass/ui/components/Table/TableHead.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import * as React from "react";
|
||||
import { Box, useColorMode } from "@chakra-ui/core";
|
||||
|
||||
// export const TableHead = styled.div`
|
||||
// ${space};
|
||||
// display: flex;
|
||||
// flex-direction: row;
|
||||
// `;
|
||||
|
||||
const bg = { dark: "whiteAlpha.100", light: "blackAlpha.100" };
|
||||
|
||||
const TableHead = ({ children, ...props }) => {
|
||||
const { colorMode } = useColorMode();
|
||||
return (
|
||||
<Box
|
||||
as="thead"
|
||||
overflowX="hidden"
|
||||
overflowY="auto"
|
||||
bg={bg[colorMode]}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
TableHead.displayName = "TableHead";
|
||||
|
||||
export default TableHead;
|
51
hyperglass/ui/components/Table/TableIconButton.js
Normal file
51
hyperglass/ui/components/Table/TableIconButton.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import * as React from "react";
|
||||
import { IconButton } from "@chakra-ui/core";
|
||||
|
||||
// export const TableIconButton = ({ icon, onClick, isDisabled, children, variantColor, ...rest }) => {
|
||||
// return (
|
||||
// <IconButton
|
||||
// size="sm"
|
||||
// {...rest}
|
||||
// icon={icon}
|
||||
// borderWidth={1}
|
||||
// onClick={onClick}
|
||||
// variantColor={variantColor}
|
||||
// isDisabled={isDisabled}
|
||||
// aria-label="Table Icon button"
|
||||
// >
|
||||
// {children}
|
||||
// </IconButton>
|
||||
// );
|
||||
// };
|
||||
|
||||
// TableIconButton.defaultProps = {
|
||||
// variantColor: "gray",
|
||||
// };
|
||||
|
||||
const TableIconButton = ({
|
||||
icon,
|
||||
onClick,
|
||||
isDisabled,
|
||||
color,
|
||||
children,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<IconButton
|
||||
size="sm"
|
||||
icon={icon}
|
||||
borderWidth={1}
|
||||
onClick={onClick}
|
||||
variantColor={color}
|
||||
isDisabled={isDisabled}
|
||||
aria-label="Table Icon Button"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</IconButton>
|
||||
);
|
||||
};
|
||||
|
||||
TableIconButton.displayName = "TableIconButton";
|
||||
|
||||
export default TableIconButton;
|
65
hyperglass/ui/components/Table/TableRow.js
Normal file
65
hyperglass/ui/components/Table/TableRow.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import * as React from "react";
|
||||
import { PseudoBox, useColorMode, useTheme } from "@chakra-ui/core";
|
||||
import { opposingColor } from "~/util";
|
||||
|
||||
// export const TableRow = styled(Flex)`
|
||||
// &:hover {
|
||||
// cursor: pointer;
|
||||
// background-color: rgba(0, 0, 0, 0.01);
|
||||
// }
|
||||
// `;
|
||||
|
||||
const hoverBg = { dark: "whiteAlpha.100", light: "blackAlpha.100" };
|
||||
const bgStripe = { dark: "whiteAlpha.50", light: "blackAlpha.50" };
|
||||
const rowBorder = {
|
||||
dark: { borderTop: "1px", borderTopColor: "whiteAlpha.100" },
|
||||
light: { borderTop: "1px", borderTopColor: "blackAlpha.100" }
|
||||
};
|
||||
const alphaMap = { dark: "200", light: "100" };
|
||||
const alphaMapHover = { dark: "100", light: "200" };
|
||||
|
||||
const TableRow = ({
|
||||
highlight = false,
|
||||
highlightBg = "primary",
|
||||
doStripe = false,
|
||||
doHorizontalBorders = false,
|
||||
index = 0,
|
||||
children = false,
|
||||
...props
|
||||
}) => {
|
||||
const { colorMode } = useColorMode();
|
||||
const theme = useTheme();
|
||||
|
||||
let bg = null;
|
||||
if (highlight) {
|
||||
bg = `${highlightBg}.${alphaMap[colorMode]}`;
|
||||
} else if (doStripe && index % 2 !== 0) {
|
||||
bg = bgStripe[colorMode];
|
||||
}
|
||||
const color = highlight ? opposingColor(theme, bg) : null;
|
||||
|
||||
const borderProps =
|
||||
doHorizontalBorders && index !== 0 ? rowBorder[colorMode] : {};
|
||||
return (
|
||||
<PseudoBox
|
||||
as="tr"
|
||||
_hover={{
|
||||
cursor: "pointer",
|
||||
backgroundColor: highlight
|
||||
? `${highlightBg}.${alphaMapHover[colorMode]}`
|
||||
: hoverBg[colorMode]
|
||||
}}
|
||||
bg={bg}
|
||||
color={color}
|
||||
fontWeight={highlight ? "bold" : null}
|
||||
{...borderProps}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</PseudoBox>
|
||||
);
|
||||
};
|
||||
|
||||
TableRow.displayName = "TableRow";
|
||||
|
||||
export default TableRow;
|
32
hyperglass/ui/components/Table/TableSelectShow.js
Normal file
32
hyperglass/ui/components/Table/TableSelectShow.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import * as React from "react";
|
||||
import { Select } from "@chakra-ui/core";
|
||||
|
||||
{
|
||||
/* <select
|
||||
value={pageSize}
|
||||
onChange={e => {setPageSize(Number(e.target.value))}}
|
||||
>
|
||||
{[5, 10, 20, 30, 40, 50].map(pageSize => (
|
||||
<option key={pageSize} value={pageSize}>
|
||||
Show {pageSize}
|
||||
</option>
|
||||
))}
|
||||
</select> */
|
||||
}
|
||||
|
||||
const TableSelectShow = ({ value, onChange, children, ...props }) => {
|
||||
return (
|
||||
<Select onChange={onChange} {...props}>
|
||||
{[5, 10, 20, 30, 40, 50].map(value => (
|
||||
<option key={value} value={value}>
|
||||
Show {value}
|
||||
</option>
|
||||
))}
|
||||
{children}
|
||||
</Select>
|
||||
);
|
||||
};
|
||||
|
||||
TableSelectShow.displayName = "TableSelectShow";
|
||||
|
||||
export default TableSelectShow;
|
191
hyperglass/ui/components/Table/index.js
Normal file
191
hyperglass/ui/components/Table/index.js
Normal file
@@ -0,0 +1,191 @@
|
||||
import * as React from "react";
|
||||
import { useMemo } from "react";
|
||||
import { Flex, Icon, Text } from "@chakra-ui/core";
|
||||
import useMedia from "~/components/MediaProvider";
|
||||
import { usePagination, useSortBy, useTable } from "react-table";
|
||||
import Card from "~/components/Card";
|
||||
import BottomSection from "~/components/Card/CardFooter";
|
||||
import TopSection from "~/components/Card/CardHeader";
|
||||
import MainTable from "./MainTable";
|
||||
import TableCell from "./TableCell";
|
||||
import TableHead from "./TableHead";
|
||||
import TableRow from "./TableRow";
|
||||
import TableBody from "./TableBody";
|
||||
import TableIconButton from "./TableIconButton";
|
||||
import TableSelectShow from "./TableSelectShow";
|
||||
|
||||
const Table = ({
|
||||
columns,
|
||||
data,
|
||||
tableHeading,
|
||||
initialPageSize = 10,
|
||||
onRowClick,
|
||||
striped = false,
|
||||
bordersVertical = false,
|
||||
bordersHorizontal = false,
|
||||
cellRender = null,
|
||||
rowHighlightProp,
|
||||
rowHighlightBg,
|
||||
rowHighlightColor
|
||||
}) => {
|
||||
const tableColumns = useMemo(() => columns, [columns]);
|
||||
|
||||
const { isSm, isMd } = useMedia();
|
||||
|
||||
const isTabletOrMobile = isSm ? true : isMd ? true : false;
|
||||
|
||||
const defaultColumn = useMemo(
|
||||
() => ({
|
||||
minWidth: 100,
|
||||
width: 150,
|
||||
maxWidth: 300
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
const {
|
||||
getTableProps,
|
||||
headerGroups,
|
||||
prepareRow,
|
||||
page,
|
||||
canPreviousPage,
|
||||
canNextPage,
|
||||
pageOptions,
|
||||
pageCount,
|
||||
gotoPage,
|
||||
nextPage,
|
||||
previousPage,
|
||||
setPageSize,
|
||||
state: { pageIndex, pageSize }
|
||||
} = useTable(
|
||||
{
|
||||
columns: tableColumns,
|
||||
defaultColumn,
|
||||
data,
|
||||
initialState: { pageIndex: 0, pageSize: initialPageSize }
|
||||
},
|
||||
useSortBy,
|
||||
usePagination
|
||||
);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
{!!tableHeading && <TopSection>{tableHeading}</TopSection>}
|
||||
<MainTable {...getTableProps()}>
|
||||
<TableHead>
|
||||
{headerGroups.map(headerGroup => (
|
||||
<TableRow
|
||||
key={headerGroup.id}
|
||||
{...headerGroup.getHeaderGroupProps()}
|
||||
>
|
||||
{headerGroup.headers.map(column => (
|
||||
<TableCell
|
||||
as="th"
|
||||
align={column.align}
|
||||
key={column.id}
|
||||
{...column.getHeaderProps()}
|
||||
{...column.getSortByToggleProps()}
|
||||
>
|
||||
<Text fontSize="sm" fontWeight="bold" display="inline-block">
|
||||
{column.render("Header")}
|
||||
</Text>
|
||||
{column.isSorted ? (
|
||||
column.isSortedDesc ? (
|
||||
<Icon name="chevron-down" size={4} ml={1} />
|
||||
) : (
|
||||
<Icon name="chevron-up" size={4} ml={1} />
|
||||
)
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{page.map(
|
||||
(row, key) =>
|
||||
prepareRow(row) || (
|
||||
<TableRow
|
||||
index={key}
|
||||
doStripe={striped}
|
||||
doHorizontalBorders={bordersHorizontal}
|
||||
onClick={() => onRowClick && onRowClick(row)}
|
||||
key={key}
|
||||
highlight={row.values[rowHighlightProp] ?? false}
|
||||
highlightBg={rowHighlightBg}
|
||||
highlightColor={rowHighlightColor}
|
||||
{...row.getRowProps()}
|
||||
>
|
||||
{row.cells.map((cell, i) => {
|
||||
return (
|
||||
<TableCell
|
||||
align={cell.column.align}
|
||||
cell={cell}
|
||||
bordersVertical={[bordersVertical, i]}
|
||||
key={cell.row.index}
|
||||
{...cell.getCellProps()}
|
||||
>
|
||||
{cell.render(cellRender ?? "Cell")}
|
||||
</TableCell>
|
||||
);
|
||||
})}
|
||||
</TableRow>
|
||||
)
|
||||
)}
|
||||
</TableBody>
|
||||
</MainTable>
|
||||
<BottomSection>
|
||||
<Flex direction="row">
|
||||
<TableIconButton
|
||||
mr={2}
|
||||
onClick={() => gotoPage(0)}
|
||||
isDisabled={!canPreviousPage}
|
||||
icon={() => <Icon name="arrow-left" size={3} />}
|
||||
/>
|
||||
<TableIconButton
|
||||
mr={2}
|
||||
onClick={() => previousPage()}
|
||||
isDisabled={!canPreviousPage}
|
||||
icon={() => <Icon name="chevron-left" size={6} />}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex justifyContent="center" alignItems="center">
|
||||
<Text mr={4} whiteSpace="nowrap">
|
||||
Page{" "}
|
||||
<strong>
|
||||
{pageIndex + 1} of {pageOptions.length}
|
||||
</strong>{" "}
|
||||
</Text>
|
||||
{!isTabletOrMobile && (
|
||||
<TableSelectShow
|
||||
value={pageSize}
|
||||
onChange={e => {
|
||||
setPageSize(Number(e.target.value));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
<Flex direction="row">
|
||||
<TableIconButton
|
||||
ml={2}
|
||||
isDisabled={!canNextPage}
|
||||
onClick={() => nextPage()}
|
||||
icon={() => <Icon name="chevron-right" size={6} />}
|
||||
/>
|
||||
<TableIconButton
|
||||
ml={2}
|
||||
onClick={() => gotoPage(pageCount ? pageCount - 1 : 1)}
|
||||
isDisabled={!canNextPage}
|
||||
icon={() => <Icon name="arrow-right" size={3} />}
|
||||
/>
|
||||
</Flex>
|
||||
</BottomSection>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
Table.displayName = "Table";
|
||||
|
||||
export default Table;
|
35
hyperglass/ui/components/Table/makeData.js
Normal file
35
hyperglass/ui/components/Table/makeData.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { generate } from "namor";
|
||||
|
||||
const range = (len) => {
|
||||
const arr = [];
|
||||
for (let i = 0; i < len; i++) {
|
||||
arr.push(i);
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
export const newPerson = () => {
|
||||
const statusChance = Math.random();
|
||||
return {
|
||||
name: generate({ words: 2, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
visits: Math.floor(Math.random() * 100),
|
||||
progress: Math.floor(Math.random() * 100),
|
||||
status:
|
||||
statusChance > 0.66 ? "relationship" : statusChance > 0.33 ? "complicated" : "single",
|
||||
};
|
||||
};
|
||||
|
||||
export default function makeData(...lens) {
|
||||
const makeDataLevel = (depth = 0) => {
|
||||
const len = lens[depth];
|
||||
return range(len).map((d) => {
|
||||
return {
|
||||
...newPerson(),
|
||||
subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
return makeDataLevel();
|
||||
}
|
70
hyperglass/ui/components/Table/styles.js
Normal file
70
hyperglass/ui/components/Table/styles.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import React from "react";
|
||||
import { Flex, IconButton } from "@chakra-ui/core";
|
||||
import styled from "@emotion/styled";
|
||||
import {
|
||||
color,
|
||||
ColorProps,
|
||||
justifyContent,
|
||||
JustifyContentProps,
|
||||
space,
|
||||
SpaceProps,
|
||||
} from "styled-system";
|
||||
|
||||
export const StyledTable = styled.div`
|
||||
${space};
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
border-radius: 4px;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
`;
|
||||
|
||||
export const TableHead = styled.div`
|
||||
${space};
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
`;
|
||||
|
||||
export const TableCell = styled("div")`
|
||||
${space};
|
||||
${color};
|
||||
${justifyContent};
|
||||
flex: 1;
|
||||
display: flex;
|
||||
min-width: 150px;
|
||||
align-items: center;
|
||||
border-bottom-width: 1px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
`;
|
||||
|
||||
export const TableRow = styled(Flex)`
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: rgba(0, 0, 0, 0.01);
|
||||
}
|
||||
`;
|
||||
|
||||
export const TableIconButton = ({ icon, onClick, isDisabled, children, variantColor, ...rest }) => {
|
||||
return (
|
||||
<IconButton
|
||||
size="sm"
|
||||
{...rest}
|
||||
icon={icon}
|
||||
borderWidth={1}
|
||||
onClick={onClick}
|
||||
variantColor={variantColor}
|
||||
isDisabled={isDisabled}
|
||||
aria-label="Table Icon button"
|
||||
>
|
||||
{children}
|
||||
</IconButton>
|
||||
);
|
||||
};
|
||||
|
||||
TableIconButton.defaultProps = {
|
||||
variantColor: "gray",
|
||||
};
|
Reference in New Issue
Block a user