Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions imports/client/components/PuzzleListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -364,13 +364,10 @@ const PuzzleListView = ({
retainedIds,
);
listComponent = puzzleGroups.map((g) => {
const suppressedTagIds = [];
if (g.sharedTag) {
suppressedTagIds.push(g.sharedTag._id);
}
const suppressedTagIds = g.sharedTags.map((tag) => tag._id);
return (
<RelatedPuzzleGroup
key={g.sharedTag ? g.sharedTag._id : "ungrouped"}
key={suppressedTagIds.join("-") || "ungrouped"}
huntId={huntId}
group={g}
noSharedTagLabel={`(${t("puzzleList.noGroupSpecified", "no group specified")})`}
Expand Down Expand Up @@ -428,7 +425,7 @@ const PuzzleListView = ({
<RelatedPuzzleList
key="bookmarked"
relatedPuzzles={bookmarkedPuzzles}
sharedTag={undefined}
sharedTags={[]}
bookmarked={bookmarked}
allTags={allTags}
canUpdate={canUpdate}
Expand All @@ -441,7 +438,11 @@ const PuzzleListView = ({
<RelatedPuzzleGroup
key="deleted"
huntId={huntId}
group={{ puzzles: retainedDeletedPuzzles, subgroups: [] }}
group={{
puzzles: retainedDeletedPuzzles,
subgroups: [],
sharedTags: [],
}}
noSharedTagLabel={t(
"puzzleList.deletedPuzzlesGroup",
"Deleted puzzles (operator only)",
Expand Down
37 changes: 23 additions & 14 deletions imports/client/components/RelatedPuzzleGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const RelatedPuzzleGroup = ({
const [persistentCollapsed, setPersistentCollapsed] =
useHuntPuzzleListCollapseGroup(
huntId,
group.sharedTag?._id ?? noSharedTagLabel,
suppressedTagIds.join("-") || noSharedTagLabel,
);
const [nonPersistentCollapsed, setNonPersistentCollapsed] = useState(false);
const lastTrackPersistentExpand = useRef(trackPersistentExpand);
Expand All @@ -86,26 +86,33 @@ const RelatedPuzzleGroup = ({
? persistentCollapsed
: nonPersistentCollapsed;

const { puzzles: relatedPuzzles, sharedTag } = group;
const { puzzles: relatedPuzzles, sharedTags } = group;

const puzzlePlural = relatedPuzzles.length === 1 ? "puzzle" : "puzzles";
const countString = `(${relatedPuzzles.length} other ${puzzlePlural})`;
const allSuppressedTagIds = [...suppressedTagIds];
if (sharedTag) {
allSuppressedTagIds.push(sharedTag._id);
}
const allSuppressedTagIds = [
...suppressedTagIds,
...sharedTags.map((tag) => tag._id),
];
return (
<PuzzleGroupDiv>
<PuzzleGroupHeader
data-group-name={sharedTag?.name}
data-group-name={sharedTags.map((tag) => tag.name).join("&")}
onClick={toggleCollapse}
>
<FontAwesomeIcon
fixedWidth
icon={collapsed ? faCaretRight : faCaretDown}
/>
{sharedTag ? (
<Tag tag={sharedTag} linkToSearch={false} popoverRelated={false} />
{sharedTags.length ? (
sharedTags.map((sharedTag) => (
<Tag
tag={sharedTag}
key={sharedTag._id}
linkToSearch={false}
popoverRelated={false}
/>
))
) : (
<NoSharedTagLabel>{noSharedTagLabel}</NoSharedTagLabel>
)}
Expand All @@ -118,17 +125,19 @@ const RelatedPuzzleGroup = ({
bookmarked={bookmarked}
allTags={allTags}
canUpdate={canUpdate}
sharedTag={sharedTag}
sharedTags={sharedTags}
suppressedTagIds={allSuppressedTagIds}
/>
{group.subgroups.map((subgroup) => {
const subgroupSuppressedTagIds = [...allSuppressedTagIds];
if (subgroup.sharedTag) {
subgroupSuppressedTagIds.push(subgroup.sharedTag._id);
}
subgroupSuppressedTagIds.push(
...subgroup.sharedTags.map((tag) => tag._id),
);
return (
<RelatedPuzzleGroup
key={subgroup.sharedTag ? subgroup.sharedTag._id : "ungrouped"}
key={
subgroup.sharedTags.map((t) => t._id).join("-") || "ungrouped"
}
huntId={huntId}
group={subgroup}
noSharedTagLabel={noSharedTagLabel}
Expand Down
6 changes: 3 additions & 3 deletions imports/client/components/RelatedPuzzleList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ const RelatedPuzzleList = React.memo(
bookmarked,
allTags,
canUpdate,
sharedTag,
sharedTags,
suppressedTagIds,
segmentAnswers,
}: {
relatedPuzzles: PuzzleType[];
bookmarked: Set<string>;
allTags: TagType[];
canUpdate: boolean;
sharedTag: TagType | undefined;
sharedTags: TagType[];
suppressedTagIds: string[];
segmentAnswers?: boolean;
}) => {
Expand All @@ -29,7 +29,7 @@ const RelatedPuzzleList = React.memo(
const tagIndex = indexedById(allTags);
const sortedPuzzles = sortPuzzlesByRelevanceWithinPuzzleGroup(
relatedPuzzles,
sharedTag,
sharedTags,
tagIndex,
);
return (
Expand Down
6 changes: 3 additions & 3 deletions imports/client/components/RelatedPuzzleTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ const RelatedPuzzleTable = React.memo(
({
relatedPuzzles,
allTags,
sharedTag,
sharedTags,
segmentAnswers,
}: {
relatedPuzzles: PuzzleType[];
allTags: TagType[];
sharedTag: TagType | undefined;
sharedTags: TagType[];
segmentAnswers?: boolean;
}) => {
// Sort the puzzles within each tag group by interestingness. For instance, metas
Expand All @@ -23,7 +23,7 @@ const RelatedPuzzleTable = React.memo(
const tagIndex = indexedById(allTags);
const sortedPuzzles = sortPuzzlesByRelevanceWithinPuzzleGroup(
relatedPuzzles,
sharedTag,
sharedTags,
tagIndex,
);
return (
Expand Down
8 changes: 5 additions & 3 deletions imports/client/components/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -278,10 +278,12 @@ const Tag = (props: TagProps) => {
}
const tagIndex = indexedById(allTagsIfPresent!);
const sharedTagName = getRelatedPuzzlesSharedTagName(props.tag.name);
const sharedTag = allTagsIfPresent!.find((t) => t.name === sharedTagName);
const sharedTags = allTagsIfPresent!.filter(
(t) => t.name === sharedTagName,
);
const relatedPuzzles = sortPuzzlesByRelevanceWithinPuzzleGroup(
getRelatedPuzzles(),
sharedTag,
sharedTags,
tagIndex,
);
const clipboardData = relatedPuzzles
Expand Down Expand Up @@ -410,7 +412,7 @@ const Tag = (props: TagProps) => {
<RelatedPuzzleTable
relatedPuzzles={relatedPuzzles}
allTags={props.allTags}
sharedTag={props.tag}
sharedTags={[props.tag]}
segmentAnswers={segmentAnswers}
/>
</Popover.Body>
Expand Down
16 changes: 16 additions & 0 deletions imports/lib/listUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@ interface ObjectWithId {
_id: string;
}

export function indexedBy<T>(
list: T[],
k: keyof T | ((val: T) => string),
allowDuplicates = false,
): Map<string, T> {
const retval = new Map();
list.forEach((item) => {
const key = k instanceof Function ? k(item) : item[k];
if (!allowDuplicates && retval.has(key)) {
throw new Error(`Duplicate ${String(k)} ${key} passed to indexedBy`);
}
retval.set(key, item);
});
return retval;
}

export function indexedById<T extends ObjectWithId>(list: T[]): Map<string, T> {
const retval = new Map();
list.forEach((item) => {
Expand Down
Loading