Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | 5x 96x 96x 96x 91x 158x 158x 158x 158x 158x 88x 158x 158x 88x 158x 13x 13x 13x 13x 158x | import { useCallback, useState, type ReactNode } from "react";
import { useCurrentUser, hasRole } from "main/utils/currentUser";
import {
DEFAULT_STAFF_TOOL_SETTINGS,
StaffToolsContext,
type StaffToolSettings,
} from "main/utils/staffToolsContext";
const STORAGE_KEY = "staffTools";
function readStoredSettings(): StaffToolSettings {
try {
const parsed = JSON.parse(sessionStorage.getItem(STORAGE_KEY) ?? "");
return {
debugMode: parsed.debugMode === true,
enableEditing: parsed.enableEditing === true,
};
} catch {
// No stored value, corrupt JSON, or sessionStorage unavailable
// (e.g. blocked by browser settings): start from the defaults.
return DEFAULT_STAFF_TOOL_SETTINGS;
}
}
// Provides the session-scoped Admin/Instructor tool toggles (see
// StaffToolSettings). Mount it only on the pages whose content the tools act
// on (the concept-graph pages); everywhere else the context's default keeps
// the tools off and the Footer toggles hidden. The flags are clamped to false
// for regular users even if sessionStorage says otherwise, and the toggles
// persist for the lifetime of the browser tab (sessionStorage), never
// server-side.
export function StaffToolsProvider({ children }: { children: ReactNode }) {
const currentUser = useCurrentUser();
const canUseStaffTools =
hasRole(currentUser, "ROLE_ADMIN") ||
hasRole(currentUser, "ROLE_INSTRUCTOR");
const [settings, setSettings] =
useState<StaffToolSettings>(readStoredSettings);
const [newConceptHandler, setNewConceptHandler] = useState<
(() => void) | null
>(null);
const registerNewConceptHandler = useCallback(
(handler: (() => void) | null) => {
setNewConceptHandler(() => handler);
},
[],
);
const [realignConceptsHandler, setRealignConceptsHandler] = useState<
(() => void) | null
>(null);
const registerRealignConceptsHandler = useCallback(
(handler: (() => void) | null) => {
setRealignConceptsHandler(() => handler);
},
[],
);
const setStaffTool = (tool: keyof StaffToolSettings, value: boolean) => {
const next = { ...settings, [tool]: value };
try {
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(next));
} catch {
// sessionStorage not available; the toggle still works for this render
// tree, it just won't survive a reload.
}
setSettings(next);
};
return (
<StaffToolsContext.Provider
value={{
debugMode: canUseStaffTools && settings.debugMode,
enableEditing: canUseStaffTools && settings.enableEditing,
canUseStaffTools,
setStaffTool,
newConceptHandler,
registerNewConceptHandler,
realignConceptsHandler,
registerRealignConceptsHandler,
}}
>
{children}
</StaffToolsContext.Provider>
);
}
|