Skip to content

Commit

Permalink
refactor: better soc & feat: keyboard shortcuts
Browse files Browse the repository at this point in the history
  • Loading branch information
levinkerschberger committed Nov 21, 2024
1 parent c423b88 commit 756d2d4
Show file tree
Hide file tree
Showing 14 changed files with 354 additions and 259 deletions.
4 changes: 1 addition & 3 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import tseslint from 'typescript-eslint'
import react from 'eslint-plugin-react'

export default tseslint.config(
{ ignores: ['dist'] },
{ ignores: ['dist', 'coverage', 'src/**/shadcn/**'] },
{
settings: {
react: {
Expand Down Expand Up @@ -42,7 +42,5 @@ export default tseslint.config(
'react/prop-types': [2, { ignore: ['className', 'orientation'] }],
'@typescript-eslint/no-confusing-void-expression': 'off',
},
ignores: ['src/**/shadcn/**']

},
)
26 changes: 9 additions & 17 deletions frontend/src/components/features/connections/ConnectionsView.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { Connection } from "@/types/Connection";
import { useState } from "react";
import { ConnectionsTableColumns } from "./table/ConnectionsTableColumns";
import ConnectionTable from "./table/ConnectionTable";
import {
Page,
Expand All @@ -9,6 +7,9 @@ import {
PageHeader,
PageTitle,
} from "@/components/ui/page";
import useConnectionTable from "@/hooks/features/connections/useConnectionTable";
import ConnectionFilters from "./filter/ConnectionFilters";
import TablePagination from "@/components/ui/table-pagination";

interface ConnectionsViewProps {
connections: Connection[];
Expand All @@ -17,27 +18,18 @@ interface ConnectionsViewProps {
export default function ConnectionsView({
connections,
}: Readonly<ConnectionsViewProps>) {
const [globalFilter, setGlobalFilter] = useState("");
// const { setQuery } = useConnectionQueryStore();

const [expanded, setExpanded] = useState<true | Record<string, boolean>>({});

const table = useConnectionTable(connections);
return (
<Page>
<PageHeader>
<PageTitle>Connections</PageTitle>
<PageDescription>All currently connected agents.</PageDescription>
<PageDescription>
<ConnectionFilters table={table} />
</PageDescription>
</PageHeader>
<PageContent>
{/* <QuickSearch /> */}
<ConnectionTable
columns={ConnectionsTableColumns}
data={connections}
setGlobalFilter={setGlobalFilter}
globalFilter={globalFilter}
setExpanded={setExpanded}
expanded={expanded}
/>
<ConnectionTable table={table} />
<TablePagination table={table} />{" "}
</PageContent>
</Page>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Button } from "@/components/ui/shadcn/button";
import { Input } from "@/components/ui/shadcn/input";
import { useKeyboardShortcut } from "@/hooks/ui/useKeyboardShortcuts";

import { Attribute } from "@/types/Attribute";
import { X } from "lucide-react";
import { useEffect, useRef, useState } from "react";

interface AttributeFilterFormProps {
addAttribute: (attribute: Attribute) => boolean;
closeForm: () => void;
containerRef: React.RefObject<HTMLDivElement>;
}

export default function AttributesFilterForm({
addAttribute,
closeForm,
containerRef,
}: AttributeFilterFormProps) {
const [key, setKey] = useState("");
const [value, setValue] = useState("");
const keyInputRef = useRef<HTMLInputElement>(null);

const handleSubmitAttribute = () => {
const attribute: Attribute = { key, value };
const added = addAttribute(attribute);
if (added) {
closeForm();
}
};

useKeyboardShortcut(
[
{ key: "Enter", callback: handleSubmitAttribute },
{ key: "Escape", callback: closeForm },
],
containerRef.current
);

useEffect(() => {
if (keyInputRef.current) {
keyInputRef.current.focus();
}
}, []);

return (
<div className="flex items-center gap-4">
<Input
className="w-20"
ref={keyInputRef}
onChange={(e) => setKey(e.target.value)}
placeholder="key"
/>
<Input
className="w-20"
onChange={(e) => setValue(e.target.value)}
placeholder="value"
/>

{/* <Switch id="regex-mode" /> */}
{/* <Label className="font-thin" htmlFor="regex-mode">
Regex
</Label> */}
<div className="flex items-end gap-2">
<Button size={"sm"} onClick={handleSubmitAttribute}>
Add
</Button>
<Button size={"sm"} onClick={closeForm}>
<X />
</Button>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Button } from "@/components/ui/shadcn/button";
import { Attribute } from "@/types/Attribute";
import { X } from "lucide-react";

interface AttributeFilterListProps {
attributes: Attribute[];
removeAttribute: (attribute: Attribute) => void;
}

export default function AttributeFilterList({
attributes,
removeAttribute,
}: Readonly<AttributeFilterListProps>) {
return (
<>
{attributes.map((attribute, index) => (
<div
key={`${attribute.key}_${index.toString()}`}
className="flex gap-2 mt-2"
>
<Button
onClick={() => removeAttribute(attribute)}
size="sm"
variant="secondary"
>
{attribute.key}={attribute.value}
<X />
</Button>
</div>
))}
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { useReducer, useRef } from "react";
import { Attribute } from "@/types/Attribute";
import { Column } from "@tanstack/react-table";
import { Connection } from "@/types/Connection";
import { useAttributeFilter } from "@/hooks/features/connections/useAttributeFilter";
import AttributeFilterList from "./AttributeFilterList";
import AttributesFilterButton from "./AttributesFilterButton";
import AttributesFilterForm from "./AttributeFilterForm";

interface AttributesFilterProps {
column: Column<Connection>;
}

interface FilterState {
isOpen: boolean;
currentAttribute: Attribute;
}

export type FilterAction =
| { type: "OPEN_FILTER" }
| { type: "CLOSE_FILTER" }
| { type: "SET_ATTRIBUTE"; payload: Attribute }
| { type: "CLEAR_ATTRIBUTE" };

const filterReducer = (
state: FilterState,
action: FilterAction
): FilterState => {
switch (action.type) {
case "OPEN_FILTER":
return { ...state, isOpen: true };
case "CLOSE_FILTER":
return { ...state, isOpen: false };
case "SET_ATTRIBUTE":
return { ...state, currentAttribute: action.payload };
case "CLEAR_ATTRIBUTE":
return { ...state, currentAttribute: { key: "", value: "" } };
default:
return state;
}
};

export default function AttributesFilter({
column,
}: Readonly<AttributesFilterProps>) {
const [state, dispatch] = useReducer(filterReducer, {
isOpen: false,
currentAttribute: { key: "", value: "" },
});

const { attributes, addAttribute, removeAttribute } =
useAttributeFilter(column);

const containerRef = useRef<HTMLDivElement>(null);

return (
<div className="flex gap-2 items-end" tabIndex={-1} ref={containerRef}>
<div className="flex gap-2">
{!state.isOpen && (
<AttributesFilterButton
onClick={() => dispatch({ type: "OPEN_FILTER" })}
/>
)}

{state.isOpen && (
<AttributesFilterForm
addAttribute={addAttribute}
closeForm={() => dispatch({ type: "CLOSE_FILTER" })}
containerRef={containerRef}
/>
)}
</div>

<AttributeFilterList
attributes={attributes}
removeAttribute={removeAttribute}
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Button } from "@/components/ui/shadcn/button";

interface ConnectionAttributesButtonProps {
onClick: () => void;
}

export default function ConnectionAttributesButton({
onClick,
}: ConnectionAttributesButtonProps) {
return (
<Button size={"sm"} onClick={onClick}>
New Attribute Filter
</Button>
);
}

This file was deleted.

Loading

0 comments on commit 756d2d4

Please sign in to comment.