Skip to content

Commit

Permalink
feat: config list page - Search function, sortable table columns
Browse files Browse the repository at this point in the history
  • Loading branch information
johnflank committed Mar 28, 2022
1 parent 220c81b commit 544ccb5
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 139 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
import dayjs from "dayjs";

export const defaultTableColumns = [
{
Header: "Type",
accessor: "type",
cellClass: `px-5 py-2`
},
{
Header: "Name",
accessor: "name",
cellClass: `px-5 py-2`
},
{
Header: "Tags",
accessor: "tags",
Cell: TagsCell,
cellClass: `px-5 py-2`
},
{
Header: "ID",
accessor: "id",
cellClass: `px-5 py-2`
},
{
Header: "Created",
accessor: "created_at",
Cell: DateCell,
cellClass: `px-5 py-2`
},
{
Header: "Last Updated",
accessor: "updated_at",
Cell: DateCell,
cellClass: `px-5 py-2`
}
];

export function TagsCell({ row, column }) {
const tags = row?.values[column.id];
return (
Expand Down
101 changes: 101 additions & 0 deletions src/components/ConfigViewer/table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { TiArrowSortedDown, TiArrowSortedUp } from "react-icons/ti";
import { useSortBy, useTable } from "react-table";

const tableStyles = {
outerDivClass: "border border-b-0 border-gray-300",
tableClass: "min-w-full border-separate",
theadClass: "bg-white z-10",
theadRowClass: "z-10",
theadHeaderClass:
"px-5 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider border-b border-gray-300",
tbodyClass: "rounded-md",
tbodyRowClass: "border cursor-pointer text-sm",
tbodyDataClass: "whitespace-nowrap border-gray-300 border-b p-2"
};

export const ConfigListTable = ({
columns,
data,
handleRowClick,
tableStyle,
isLoading,
...rest
}) => {
const tableInstance = useTable({ columns, data }, useSortBy);

const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } =
tableInstance;

return (
<div className={tableStyles.outerDivClass} {...rest}>
<table
className={tableStyles.tableClass}
style={tableStyle}
{...getTableProps()}
>
<thead className={tableStyles.theadClass}>
{headerGroups.map((headerGroup) => (
<tr
key={headerGroup.getHeaderGroupProps().key}
className={tableStyles.theadRowClass}
{...headerGroup.getHeaderGroupProps()}
>
{headerGroup.headers.map((column) => (
<th
key={column.Header}
className={tableStyles.theadHeaderClass}
{...column.getHeaderProps(column.getSortByToggleProps())}
>
<div className="flex select-none">
{column.render("Header")}
{column.isSorted ? (
<span className="ml-2">
{column.isSortedDesc ? (
<TiArrowSortedUp />
) : (
<TiArrowSortedDown />
)}
</span>
) : (
""
)}
</div>
</th>
))}
</tr>
))}
</thead>
<tbody className={tableStyles.tbodyClass} {...getTableBodyProps()}>
{rows.map((row) => {
prepareRow(row);
return (
<tr
key={row.id}
className={tableStyles.tbodyRowClass}
{...row.getRowProps()}
onClick={handleRowClick ? () => handleRowClick(row) : () => {}}
>
{row.cells.map((cell) => (
<td
key={cell.column.Header}
className={`${tableStyles.tbodyDataClass} ${
cell.column.cellClass || ""
}`}
{...cell.getCellProps()}
>
{cell.render("Cell")}
</td>
))}
</tr>
);
})}
</tbody>
</table>
{rows.length <= 0 && (
<div className="flex items-center justify-center py-20 px-2 border-b border-gray-300 text-center text-gray-400">
{isLoading ? "Loading data.." : "No data available"}
</div>
)}
</div>
);
};
25 changes: 25 additions & 0 deletions src/components/ConfigViewer/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { isEmpty } from "lodash";

export function filterConfigsByText(configs, textQuery) {
if (configs == null) {
return [];
}
if (isEmpty(textQuery)) {
return configs;
}
const text = textQuery.toLowerCase();
const filtered = [...configs].filter((config) => {
const match =
hasStringMatch(text, config.name?.toLowerCase()) ||
hasStringMatch(text, config.namespace?.toLowerCase());
return match;
});
return filtered;
}

export function hasStringMatch(pattern, text) {
if (text == null) {
return false;
}
return text.indexOf(pattern) >= 0;
}
10 changes: 2 additions & 8 deletions src/components/TextInputClearable/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { IoCloseCircle } from "react-icons/io5";
export function TextInputClearable({
className,
defaultValue,
value,
onChange = () => {},
onSubmit = () => {},
inputClassName,
Expand All @@ -19,23 +18,18 @@ export function TextInputClearable({
}) {
const [textValue, setTextValue] = useState(defaultValue || "");

useEffect(() => {
if (onChange) {
onChange(value);
}
}, [onChange, value]);

return (
<div className={`flex ${className}`}>
<div className={`relative flex-grow ${inputOuterClassName}`}>
<input
value={value}
defaultValue={defaultValue}
onChange={onChange}
type="text"
className={`h-full w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block py-1 sm:text-sm border-gray-300 ${
hideButton ? "rounded-md" : "rounded-l-md"
} ${inputClassName}`}
placeholder={placeholder}
{...rest}
/>
{!hideClearButton && textValue && (
<div className="absolute inset-y-0 right-0 pr-2 flex items-center">
Expand Down
Loading

0 comments on commit 544ccb5

Please sign in to comment.