Skip to content

Commit

Permalink
menu/UI cleanup #3: click-to-edit on some columns (#851)
Browse files Browse the repository at this point in the history
* just click on cells to edit them

* tweaks
  • Loading branch information
npinsker authored Jan 16, 2025
1 parent 2b1db7c commit 02eead3
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 88 deletions.
52 changes: 25 additions & 27 deletions hunts/src/NameCell.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import React from "react";
import { Badge, Popover, OverlayTrigger } from "react-bootstrap";
import { useSelector, useDispatch } from "react-redux";
import { faWrench } from "@fortawesome/free-solid-svg-icons";
import { showModal } from "./modalSlice";
import ClickableIcon from "./ClickableIcon";
import { toggleCollapsed } from "./collapsedPuzzlesSlice";
import { IconChevronDown, IconChevronRight } from "@tabler/icons";
import { faCircle } from "@fortawesome/free-solid-svg-icons";
Expand Down Expand Up @@ -84,6 +82,7 @@ const useToggleRowExpandedProps = (row: Row<Puzzle>) => {
...originalProps,
onClick: (e: MouseEvent) => {
dispatch(toggleCollapsed({ rowId: row.id, huntId: CURRENT_HUNT_ID }));
e.stopPropagation();
return originalProps.onClick(e);
},
};
Expand All @@ -109,8 +108,32 @@ export default function NameCell({

return (
<div
onMouseEnter={() => {
setUiHovered(true);
}}
onMouseLeave={() => {
setUiHovered(false);
}}
onClick={() => {
dispatch(
showModal({
type: "EDIT_PUZZLE",
props: {
huntId,
puzzleId: row.values.id,
name: row.values.name,
url: row.values.url,
isMeta: row.values.is_meta,
hasChannels: !!row.original.chat_room?.text_channel_url,
},
})
);
}}
style={{
// TODO: abstract these properties out into their own CSS class
paddingLeft: `${row.depth * 2}rem`,
minHeight: '1.4rem', cursor: 'pointer',
backgroundColor: uiHovered ? '#ffe579' : undefined
}}
>
<div
Expand Down Expand Up @@ -147,31 +170,6 @@ export default function NameCell({
<Badge bg="dark" text="white">META</Badge>{" "}
</>
) : null}
<div
style={{
display: "inline-block",
visibility: uiHovered ? "visible" : "hidden",
}}
>
<ClickableIcon
icon={faWrench}
onClick={() =>
dispatch(
showModal({
type: "EDIT_PUZZLE",
props: {
huntId,
puzzleId: row.values.id,
name: row.values.name,
url: row.values.url,
isMeta: row.values.is_meta,
hasChannels: !!row.original.chat_room?.text_channel_url,
},
})
)
}
/>
</div>
</div>
</div>
);
Expand Down
103 changes: 61 additions & 42 deletions hunts/src/NotesCell.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,76 @@
import React from "react";
import { showModal } from "./modalSlice";
import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { faWrench, faTag } from "@fortawesome/free-solid-svg-icons";
import ClickableIcon from "./ClickableIcon";
import { editNotes } from "./puzzlesSlice";

import huntReducer from "./huntSlice";

import type { RootState } from "./store";
import type { Dispatch, RootState } from "./store";
import type { Hunt, Row } from "./types";

export default function NotesCell({ row, value }: { row: Row; value: string }) {
const { id: huntId } = useSelector<RootState, Hunt>((state) => state.hunt);
const [uiHovered, setUiHovered] = React.useState(false);
const dispatch = useDispatch();
const [uiHovered, setUiHovered] = useState(false);
const [ editing, setEditing ] = useState(false);
const [ editedNotesValue, setEditedNotesValue ] = useState(value);
const dispatch = useDispatch<Dispatch>();

return (
<div
onMouseEnter={() => {
setUiHovered(true);
}}
onMouseLeave={() => {
setUiHovered(false);
}}
onMouseEnter={() => {
setUiHovered(true);
}}
onMouseLeave={() => {
setUiHovered(false);
}}
onClick={() => {
if (!editing) {
setEditing(true);
setEditedNotesValue(value);
}
}}
// TODO: abstract these properties out into their own CSS class
style={{width: "100%", minHeight: '1.4rem', cursor: !editing ? 'pointer' : undefined, backgroundColor: uiHovered && !editing ? '#ffe579' : undefined}}
>
{value}
<div
style={{
display: "inline-block",
visibility: uiHovered ? "visible" : "hidden",
}}
onMouseEnter={() => {
setUiHovered(true);
}}
onMouseLeave={() => {
setUiHovered(false);
}}
>
<ClickableIcon
icon={faWrench}
onClick={() =>
dispatch(
showModal({
type: "EDIT_NOTES",
props: {
huntId,
{editing ?
<div style={{ display: 'flex' }}>
<textarea
autoFocus
value={editedNotesValue}
style={{ minHeight: '70px' }}
onChange={(e) => {
setEditedNotesValue(e.target.value);
}}
onKeyDown={(e) => {
if (e.key === "Enter" && (e.ctrlKey || e.shiftKey || e.metaKey)) {
dispatch(
editNotes({
puzzleId: row.values.id,
text: row.values.notes,
},
})
)
}
body: { text: editedNotesValue },
})
).finally(() => {
setEditing(false);
});
} else if (e.key == "Escape") {
setEditedNotesValue("");
setEditing(false);
}
}}
/>
<div
style={{ cursor: 'pointer' }}
onClick={() => {
dispatch(
editNotes({
puzzleId: row.values.id,
body: { text: editedNotesValue },
})
).finally(() => {
setEditing(false);
});
}}
>
</div>
</div>
: value }
</div>
</div>
);
}
47 changes: 28 additions & 19 deletions hunts/src/TagCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { RootState } from "./store";
import type { Hunt, Puzzle, Row } from "./types";

function TagCell({ row }: { row: Row<Puzzle> }) {
const [uiHovered, setUiHovered] = React.useState(false);
const dispatch = useDispatch();
const { id: huntId } = useSelector<RootState, Hunt>((state) => state.hunt);
const puzzleId = row.original.id;
Expand All @@ -21,32 +22,40 @@ function TagCell({ row }: { row: Row<Puzzle> }) {
: row.original.tags.filter((t) => !t.is_meta && t.name !== row.original.name);

return (
<>
<div
onMouseEnter={() => {
setUiHovered(true);
}}
onMouseLeave={() => {
setUiHovered(false);
}}
onClick={() => {
dispatch(
showModal({
type: "EDIT_TAGS",
props: {
huntId,
puzzleId: row.values.id,
puzzleName: row.values.name,
},
})
);
}}
style={{
// TODO: abstract these properties out into their own CSS class
cursor: 'pointer',
minHeight: '1.4rem',
backgroundColor: uiHovered ? '#ffe579' : undefined
}}>
{tagsToShow.map(({ name, color, id }) => (
<TagPill
name={name}
color={color}
key={name}
onClick={() => dispatch(toggleFilterTag({ name, color, id }))}
/>
))}{" "}

<ClickableIcon
icon={faTag}
onClick={() =>
dispatch(
showModal({
type: "EDIT_TAGS",
props: {
huntId,
puzzleId: row.values.id,
puzzleName: row.values.name,
},
})
)
}
/>{" "}
</>
))}
</div>
);
}

Expand Down

0 comments on commit 02eead3

Please sign in to comment.