+ {isPhy && isQuestion &&
+
+
+ }
{isPhy && helpModalId &&
}
{above['sm'](deviceSize) && <>
diff --git a/src/app/components/elements/list-groups/AbstractListViewItem.tsx b/src/app/components/elements/list-groups/AbstractListViewItem.tsx
index 974fb4ab88..0dd3716fd9 100644
--- a/src/app/components/elements/list-groups/AbstractListViewItem.tsx
+++ b/src/app/components/elements/list-groups/AbstractListViewItem.tsx
@@ -5,7 +5,7 @@ import { ViewingContext} from "../../../../IsaacAppTypes";
import classNames from "classnames";
import { Badge, Button, Col, ListGroupItem, ListGroupItemProps } from "reactstrap";
import { CompletionState, GameboardDTO } from "../../../../IsaacApiTypes";
-import { above, below, isAda, isDefined, isPhy, isStaff, isTeacherOrAbove, siteSpecific, Subject, useDeviceSize } from "../../../services";
+import { above, below, isAda, isDefined, isLoggedIn, isPhy, isStaff, isTeacherOrAbove, siteSpecific, Subject, useDeviceSize } from "../../../services";
import { TitleIcon, TitleIconProps } from "../PageTitle";
import { Markup } from "../markup";
import { closeActiveModal, openActiveModal, selectors, useAppDispatch, useAppSelector, useLazyGetGroupsQuery, useLazyGetMySetAssignmentsQuery, useUnassignGameboardMutation } from "../../../state";
@@ -16,6 +16,8 @@ import { ContentPropertyTags } from "../ContentPropertyTags";
import { LLMFreeTextQuestionIndicator } from "../LLMFreeTextQuestionIndicator";
import { CrossTopicQuestionIndicator } from "../CrossTopicQuestionIndicator";
import { SupersededDeprecatedBoardContentWarning } from "../../navigation/SupersededDeprecatedWarning";
+import { useBookmarks } from "../../../services/bookmarks";
+import { FeatureFlag, useFeatureFlag } from "../../../services/featureFlag";
const Breadcrumb = ({breadcrumb}: {breadcrumb: string[]}) => {
return <>
@@ -134,6 +136,7 @@ type ALVIType = {
quizTag?: string; // this is for quick quizzes only, which are currently just gameboards; may change in future
hasCaret?: boolean;
linkTags?: ListViewTagProps[];
+ allowBookmarking?: boolean; // if set, displays a bookmark for logged-in users that will save the alvi to the user's bookmarks on click
} | {
// quizzes – have exclusive "preview" and "view test" buttons
alviType: "quiz";
@@ -180,8 +183,13 @@ export type AbstractListViewProps = ALVILayout & {
export const AbstractListViewItem = ({title, icon, subject, subtitle, breadcrumb, tags, style, url, state, className, componentTag, ...typedProps}: AbstractListViewItemProps & AbstractListViewProps) => {
const deviceSize = useDeviceSize();
+ const { isBookmarked, bookmarkItem } = useBookmarks();
const user = useAppSelector(selectors.user.orNull);
+ const bookmarksFeatureFlag = useFeatureFlag(FeatureFlag.ENABLE_SCI_BOOKMARKS);
+
+ const contentId = (url?.includes("/questions/") || url?.includes("/concepts/")) && url.split("/").slice(-1)[0];
+
const isItem = typedProps.alviType === "item";
const isGameboard = typedProps.alviType === "gameboard";
const isQuiz = typedProps.alviType === "quiz";
@@ -273,6 +281,10 @@ export const AbstractListViewItem = ({title, icon, subject, subtitle, breadcrumb
{isQuiz &&
}
+ {isItem && contentId && typedProps.allowBookmarking && isLoggedIn(user) && bookmarksFeatureFlag &&