From 7cb3263736eb52901cce7b2e9c2b865368df6075 Mon Sep 17 00:00:00 2001 From: Nathan Pinsker Date: Tue, 9 Jan 2024 12:23:37 -0800 Subject: [PATCH] css ribbons + meta spacing changes (#738) * merge tags column into puzzle name; bit of CSS * re-add missing filter * add color sidebars & separate top-level meta rounds * hide meta tags * add color gradients on top of round * prettier * remove varying font sizes for meta names * spin tags out to its own column again; show meta tags if puzzle has 2+ metas; address comments * hide meta tags * prettier --- cardboard/static/style.css | 16 ++++ hunts/src/HuntViewMain.js | 7 +- hunts/src/NameCell.js | 164 +++++++++++++++++++++++-------------- hunts/src/TagCell.js | 26 ++---- hunts/src/TagPill.js | 25 ------ hunts/src/puzzle-table.js | 95 +++++++++++++++------ 6 files changed, 202 insertions(+), 131 deletions(-) diff --git a/cardboard/static/style.css b/cardboard/static/style.css index d8f4c2e5..4a3377c8 100644 --- a/cardboard/static/style.css +++ b/cardboard/static/style.css @@ -71,6 +71,22 @@ body { border-color: var(--table-row-danger-border); } +#app .table.table-sm thead th { + border-bottom: none; +} + +#app .table-top-colorbar { + height: 4px; + padding: 0rem; + border: none; +} + +#app .table-side-colorbar { + width: 4px; + padding: 0rem; + border: none; +} + .bootstrap-dark a { color: #007bff; } diff --git a/hunts/src/HuntViewMain.js b/hunts/src/HuntViewMain.js index 184ef163..26034edf 100644 --- a/hunts/src/HuntViewMain.js +++ b/hunts/src/HuntViewMain.js @@ -73,7 +73,8 @@ export const HuntViewMain = (props) => {
{ id={id} puzzleId={null} key={name} - onDelete={() => - dispatch(toggleFilterTag({ name, color, id })) - } + onClick={() => dispatch(toggleFilterTag({ name, color, id }))} /> ); })} diff --git a/hunts/src/NameCell.js b/hunts/src/NameCell.js index bd6f07b6..749be7f0 100644 --- a/hunts/src/NameCell.js +++ b/hunts/src/NameCell.js @@ -1,19 +1,17 @@ import React from "react"; import Badge from "react-bootstrap/Badge"; import { useSelector, useDispatch } from "react-redux"; -import { faEdit, faTrashAlt } from "@fortawesome/free-regular-svg-icons"; +import { faTrashAlt } from "@fortawesome/free-regular-svg-icons"; +import { faWrench, faTag } from "@fortawesome/free-solid-svg-icons"; import { showModal } from "./modalSlice"; +import TagCell from "./TagCell"; import ClickableIcon from "./ClickableIcon"; import { toggleCollapsed } from "./collapsedPuzzlesSlice"; import { IconChevronDown, IconChevronRight } from "@tabler/icons"; const useToggleRowExpandedProps = (row) => { const dispatch = useDispatch(); - const originalProps = row.getToggleRowExpandedProps({ - style: { - paddingLeft: `${row.depth * 2}rem`, - }, - }); + const originalProps = row.getToggleRowExpandedProps({}); return { ...originalProps, @@ -29,69 +27,113 @@ export default function NameCell({ row, value }) { const [uiHovered, setUiHovered] = React.useState(false); const toggleRowExpandedProps = useToggleRowExpandedProps(row); const dispatch = useDispatch(); + + const nameText = ( + + {value} + + ); + return (
{ - setUiHovered(true); - }} - onMouseLeave={() => { - setUiHovered(false); + style={{ + paddingLeft: `${row.depth * 2}rem`, }} > - {row.canExpand ? ( - - {row.isExpanded ? : } - {value} - - ) : ( - - {value} - - )}{" "} - {row.values.is_meta ? ( - <> - META{" "} - - ) : null}
{ + setUiHovered(true); + }} + onMouseLeave={() => { + setUiHovered(false); + }} style={{ - display: "inline-block", - visibility: uiHovered ? "visible" : "hidden", + marginBottom: "3px", }} > - - 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, - }, - }) - ) - } - />{" "} - - dispatch( - showModal({ - type: "DELETE_PUZZLE", - props: { - huntId, - puzzleId: row.values.id, - puzzleName: value, - }, - }) - ) - } - /> + {row.canExpand ? ( + + {row.isExpanded ? : } + {nameText} + + ) : ( + {nameText} + )}{" "} + {row.values.is_meta ? ( + <> + META{" "} + + ) : null} +
+ + 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, + }, + }) + ) + } + />{" "} + + dispatch( + showModal({ + type: "EDIT_TAGS", + props: { + huntId, + puzzleId: row.values.id, + puzzleName: row.values.name, + }, + }) + ) + } + />{" "} + + dispatch( + showModal({ + type: "EDIT_TAGS", + props: { + huntId, + puzzleId: row.values.id, + puzzleName: row.values.name, + }, + }) + ) + } + />{" "} + + dispatch( + showModal({ + type: "DELETE_PUZZLE", + props: { + huntId, + puzzleId: row.values.id, + puzzleName: value, + }, + }) + ) + } + /> +
); diff --git a/hunts/src/TagCell.js b/hunts/src/TagCell.js index 3f4f2174..297159dd 100644 --- a/hunts/src/TagCell.js +++ b/hunts/src/TagCell.js @@ -1,18 +1,23 @@ import React from "react"; import { useDispatch, useSelector } from "react-redux"; -import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { showModal } from "./modalSlice"; import { toggleFilterTag } from "./filterSlice"; import TagPill from "./TagPill"; -import ClickableIcon from "./ClickableIcon"; function TagCell({ row }) { const dispatch = useDispatch(); const { id: huntId } = useSelector((state) => state.hunt); const puzzleId = row.original.id; + + const shouldShowMetaTags = + row.original.tags.filter((t) => t.is_meta).length > 1; + const tagsToShow = shouldShowMetaTags + ? row.original.tags + : row.original.tags.filter((t) => !t.is_meta); + return ( <> - {row.original.tags.map(({ name, color, id }) => ( + {tagsToShow.map(({ name, color, id }) => ( dispatch(toggleFilterTag({ name, color, id }))} /> ))}{" "} - - dispatch( - showModal({ - type: "EDIT_TAGS", - props: { - huntId, - puzzleId: row.values.id, - puzzleName: row.values.name, - }, - }) - ) - } - /> ); } diff --git a/hunts/src/TagPill.js b/hunts/src/TagPill.js index e1359ece..bccc62b8 100644 --- a/hunts/src/TagPill.js +++ b/hunts/src/TagPill.js @@ -13,7 +13,6 @@ function TagPill({ selected = false, faded = false, editable = true, - onDelete = null, onClick = null, }) { const { id: huntId } = useSelector((state) => state.hunt); @@ -32,30 +31,6 @@ function TagPill({ return ( {name} - {onDelete || editable ? ( - { - e.stopPropagation(); - dispatch(deletePuzzleTag({ puzzleId, tagId: id })).then( - (action) => { - if (action.payload && action.payload.is_meta) { - // Deleting meta tags may affect the state of other puzzles - // (specifically their feeders) - // So just trigger a full fetch here. - // Alternatively we could try to duplicate the logic on the client - dispatch(fetchPuzzles(huntId)); - } - } - ); - }) - } - style={{ marginLeft: "5px", cursor: "pointer" }} - > - - - ) : null} ); } diff --git a/hunts/src/puzzle-table.js b/hunts/src/puzzle-table.js index ebfb4bc2..dbf648b3 100644 --- a/hunts/src/puzzle-table.js +++ b/hunts/src/puzzle-table.js @@ -26,7 +26,15 @@ const TABLE_COLUMNS = [ Header: "Name", accessor: "name", Cell: NameCell, - className: "col-4", + className: "col-3", + }, + { + Header: "Tags", + id: "tags", + Cell: TagCell, + className: "col-3", + accessor: (row) => row.tags.map(({ name }) => name).join(" "), + filter: "tagsFilter", }, { Header: "", @@ -63,14 +71,6 @@ const TABLE_COLUMNS = [ Cell: CreationCell, className: "col-1", }, - { - Header: "Tags/Metas", - id: "tags", - accessor: (row) => row.tags.map(({ name }) => name).join(" "), - Cell: TagCell, - filter: "tagsFilter", - className: "col-3", - }, { accessor: "is_meta", id: "is_meta", @@ -190,11 +190,73 @@ export const PuzzleTable = React.memo(({ data, filterSolved, filterTags }) => { setFilter("tags", filterTags); }, [filterTags]); + let rowsList = []; + const roundColors = [ + "crimson", + "dodgerblue", + "forestgreen", + "darkorchid", + "darkorange", + "goldenrod", + "coral", + "darkslategray", + "powderblue", + "aquamarine", + "palevioletred", + "indigo", + "olive", + "violet", + ]; + + const topLevelId = (row) => parseInt(row.id.split(".")[0]); + + rows.forEach((row, i) => { + prepareRow(row); + + // Add coloring and space between top-level metas + if (i == 0 || topLevelId(row) != topLevelId(rows[i - 1])) { + if (i > 0) { + rowsList.push( + + ); + } + + rowsList.push( + + + + ); + } + + rowsList.push( + + + {row.cells.map((cell) => { + return {cell.render("Cell")}; + })} + + ); + }); + return ( <> + {allColumns.map((column) => column.isVisible ? ( - - {rows.map((row) => { - prepareRow(row); - return ( - - {row.cells.map((cell) => { - return ( - - ); - })} - - ); - })} - + {rowsList}
@@ -204,20 +266,7 @@ export const PuzzleTable = React.memo(({ data, filterSolved, filterTags }) => { )}
{cell.render("Cell")}
);