Skip to content

Commit

Permalink
First version of OrderableLiteralListField (pending drag&drop)
Browse files Browse the repository at this point in the history
  • Loading branch information
Toni M. Brotons authored and Toni M. Brotons committed Feb 11, 2025
1 parent 3fb6b9a commit 77eb574
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 83 deletions.
9 changes: 1 addition & 8 deletions gui_dev/src/pages/Settings/Settings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,14 @@ import {
FrequencyRangeField,
} from "./components/FrequencyRange";
import { useSettingsStore, useStatusBar } from "@/stores";
import { filterObjectByKeys } from "@/utils";
import { filterObjectByKeys, formatKey } from "@/utils";
import {
NumericField,
StringField,
BooleanField,
} from "./components/PrimitiveComponents";
import { OrderableLiteralListField } from "./components/OrderableLiteralListField";

const formatKey = (key) => {
return key
.split("_")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
};

// Map component types to their respective wrappers
const componentRegistry = {
boolean: BooleanField,
Expand Down
149 changes: 74 additions & 75 deletions gui_dev/src/pages/Settings/components/OrderableLiteralListField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,85 @@ import { Add, Remove } from "@mui/icons-material";
import {
Divider,
IconButton,
Paper,
List,
ListItem,
ListItemText,
Stack,
Typography,
} from "@mui/material";
import { formatKey } from "@/utils";
import { TitledBox } from "@/components";

export const OrderableLiteralListField = ({
label,
value = [],
onChange,
error,
valid_values = [],
}) => {
const ListCard = ({ key, item }) => {
const ref = useRef(null);
const [dragging, setDragging] = useState(false);
//
const ListCard = ({ item, onButtonClick, mode }) => {
const ref = useRef(null);
const [dragging, setDragging] = useState(false);

useEffect(() => {
const el = ref.current;
invariant(el);
useEffect(() => {
const el = ref.current;
invariant(el);

return draggable({
element: el,
onDragStart: () => setDragging(true),
onDrop: () => setDragging(false),
});
}, []);
return draggable({
element: el,
onDragStart: () => setDragging(true),
onDrop: () => setDragging(false),
});
}, []);

return (
let Icon = null;
if (mode === "remove") {
Icon = Remove;
} else if (mode === "add") {
Icon = Add;
}

return (
<Paper elevation={1} bgcolor="background.paper" sx={{ my: 1 }} width="100%">
<ListItem
key={key}
secondaryAction={
<IconButton edge="end" onClick={() => handleRemove(item)}>
<Remove />
<IconButton edge="end" onClick={() => onButtonClick(item)}>
<Icon />
</IconButton>
}
ref={ref}
>
<ListItemText primary={item} />
<ListItemText primary={formatKey(item)} />
</ListItem>
);
};
</Paper>
);
};

const ListContainer = ({ title, mode, items, onButtonClick }) => (
<TitledBox title={title} sx={{ borderRadius: 3 }}>
<List sx={{ m: 0, p: 0, width: "100%" }}>
{items.map((item, index) => (
<ListCard
key={index}
item={item}
mode={mode}
onButtonClick={onButtonClick}
/>
))}
{items.length === 0 && (
<ListItem>
<ListItemText
primary="No items available"
sx={{ color: "text.secondary", fontStyle: "italic" }}
/>
</ListItem>
)}
</List>
</TitledBox>
);

export const OrderableLiteralListField = ({
label,
value = [],
onChange,
error,
valid_values = [],
}) => {
// Create sets for faster lookup
const selectedSet = new Set(value);

Expand All @@ -68,57 +103,21 @@ export const OrderableLiteralListField = ({
};

return (
<Stack spacing={2}>
<Stack>
<Typography variant="h6">{label}</Typography>

<div>
<Typography variant="subtitle1" color="primary" sx={{ mb: 1 }}>
Selected Items
</Typography>
<List>
{selectedItems.map((item, index) => (
<ListCard key={index} item={item} />
))}
{selectedItems.length === 0 && (
<ListItem>
<ListItemText
primary="No items selected"
sx={{ color: "text.secondary", fontStyle: "italic" }}
/>
</ListItem>
)}
</List>
</div>

<Divider />

<div>
<Typography variant="subtitle1" color="primary" sx={{ mb: 1 }}>
Available Items
</Typography>
<List>
{availableItems.map((item) => (
<ListItem
key={item}
secondaryAction={
<IconButton edge="end" onClick={() => handleAdd(item)}>
<Add />
</IconButton>
}
>
<ListItemText primary={item} />
</ListItem>
))}
{availableItems.length === 0 && (
<ListItem>
<ListItemText
primary="No items available"
sx={{ color: "text.secondary", fontStyle: "italic" }}
/>
</ListItem>
)}
</List>
</div>
<ListContainer
title="Selected"
mode="remove"
items={selectedItems}
onButtonClick={handleRemove}
/>
<ListContainer
title="Available"
mode="add"
items={availableItems}
onButtonClick={handleAdd}
/>

{error && (
<Typography color="error" variant="caption">
Expand Down
7 changes: 7 additions & 0 deletions gui_dev/src/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,10 @@ export const getPyNMDirectory = async () => {

return data.pynm_dir;
};

export const formatKey = (key) => {
return key
.split("_")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
};

0 comments on commit 77eb574

Please sign in to comment.