Skip to content
Open

v.2.4.3 #1226

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
a97ef2e
Refine startup error handling
JackWilb Mar 20, 2026
1d18108
Handle startup storage fallback and resume alerts
JackWilb Mar 30, 2026
7215614
Inline Shell startup helpers
JackWilb Mar 30, 2026
0e0510e
Guard Shell startup participant lookup fallback
JackWilb Mar 30, 2026
5040df6
Fix typo in library calvi question description
jaykim1213 Apr 10, 2026
ba350aa
Fix UI break when user rejects audio recording
jaykim1213 Apr 10, 2026
42fabb0
Add aria-disabled and tab index -1 to mic error icon
jaykim1213 Apr 10, 2026
9be9e0b
Revert record screen field in library-screen-recording
jaykim1213 Apr 10, 2026
4854c4f
Add screen recording icon to timeline
jaykim1213 Apr 10, 2026
7a07855
Address PR comment
jaykim1213 Apr 10, 2026
4fcf44f
Merge branch 'dev' into jk/fixMicPermissionBug
jaykim1213 Apr 20, 2026
503a9c7
Fix mic icon bug if mic permission is disabled
jaykim1213 Apr 20, 2026
96c1761
Fix back button enabled in the study replay
jaykim1213 Apr 20, 2026
b5ee544
Fix replay task bug
jaykim1213 Apr 20, 2026
51743cd
Bump the npm_and_yarn group across 1 directory with 2 updates
dependabot[bot] Apr 28, 2026
4cc9d14
Speed up first load by clearing the hot path from un-necessary awaits
JackWilb May 1, 2026
9ad7f67
Prevent metadata writes in demo mode
JackWilb May 7, 2026
cb034d6
Fix showing app header warning
jaykim1213 May 12, 2026
539579b
Merge branch 'dev' into jk/fixMicPermissionBug
jaykim1213 May 12, 2026
e9f1f18
Merge branch 'dev' into jk/fixReplayBug
jaykim1213 May 12, 2026
dde8728
Address PR comments
jaykim1213 May 12, 2026
342494b
Refactor GlobalConfigParser to reduce config fetches
JackWilb May 12, 2026
32a97ad
Enhance Shell component with loading overlay and completion check logic
JackWilb May 13, 2026
d1d7704
Add error handling and user feedback for participant completion check…
JackWilb May 13, 2026
6b84aaf
Refactor Shell component to improve loading state handling and simpli…
JackWilb May 13, 2026
84c582b
Refactor AuthProvider to enhance loading state handling and condition…
JackWilb May 13, 2026
d87b94e
Eliminate unnecessary await
JackWilb May 13, 2026
f32fbf6
Handle transient completion-status lookup failures to allow study entry
JackWilb May 13, 2026
aa021ce
Merge pull request #1222 from revisit-studies/speedup-first-load
JackWilb May 13, 2026
056dcbe
Merge branch 'dev' into disconnected-errors
JackWilb May 13, 2026
1702f50
Fix small issue with operators
JackWilb May 13, 2026
df8a9ab
Refactor isStorageStartupFailure function to simplify logic and remov…
JackWilb May 13, 2026
29824f6
Merge pull request #1164 from revisit-studies/disconnected-errors
JackWilb May 13, 2026
903b777
Fix microphone permission handling in AppHeader component tests
JackWilb May 13, 2026
aa41937
Merge pull request #1196 from revisit-studies/jk/fixMicPermissionBug
JackWilb May 13, 2026
e27d57f
Merge pull request #1215 from revisit-studies/dependabot/npm_and_yarn…
JackWilb May 13, 2026
75c8f12
Fix replay previous-step navigation
JackWilb May 13, 2026
622b459
Fix replay bug and remove test fixture
JackWilb May 14, 2026
a0eb2d0
Merge branch 'dev' into jk/fixReplayBug
JackWilb May 14, 2026
e77cca1
Remove currentTrial query param plumbing
JackWilb May 14, 2026
a2b6f1e
Fix dynamic backward navigation
JackWilb May 14, 2026
8e5726d
Refactor tests to preserve dynamic child routes from pathname and imp…
JackWilb May 14, 2026
46ae2c4
Merge pull request #1214 from revisit-studies/jk/fixReplayBug
JackWilb May 14, 2026
0a0717a
Initial plan
Copilot May 14, 2026
e3f2b46
feat: add component auto-advance timeout options
Copilot May 14, 2026
1778c8f
test: refine timeout warning messaging
Copilot May 14, 2026
5babc03
fix: handle auto-advance warning placeholders consistently
Copilot May 14, 2026
f7b45d5
refactor: simplify NextButton and useNextStep hooks
JackWilb May 15, 2026
6e9bf73
fix: correct E2E test setup for timeout component study
JackWilb May 15, 2026
a2099fd
Address feedback from review
JackWilb May 21, 2026
26214e5
Merge pull request #1227 from revisit-studies/copilot/add-timeout-opt…
JackWilb May 21, 2026
3af76fb
Separating provenance data from answers (#1230)
ZachCutler04 May 22, 2026
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ supabase/volumes/*
!supabase/volumes/db/
supabase/volumes/db/data
!supabase/volumes/api/

coverage/
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"typedoc": "^0.28.13",
"typedoc-plugin-markdown": "^4.9.0",
"use-deep-compare-effect": "^1.8.1",
"uuid": "^11.0.5",
"uuid": "^14.0.0",
"vega": "^6.2.0",
"vega-lite": "^5.23.0",
"vite": "^7.3.2",
Expand Down Expand Up @@ -113,6 +113,7 @@
"eslint-plugin-react-hooks": "^5.2.0",
"globals": "^16.4.0",
"husky": "^9.1.7",
"jsdom": "^29.1.1",
"lint-staged": "^16.1.6",
"typescript": "^5.9.2",
"vitest": "^3.2.4",
Expand Down
29 changes: 17 additions & 12 deletions public/global.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@
"test-device-restriction",
"test-library",
"test-likert-matrix",
"test-parser-errors",
"test-randomization",
"test-skip-logic",
"test-step-logic"
"test-parser-errors",
"test-randomization",
"test-component-timeout",
"test-skip-logic",
"test-step-logic"
],
"configs": {
"tutorial": {
Expand Down Expand Up @@ -210,13 +211,17 @@
"path": "test-parser-errors/config.json",
"test": true
},
"test-randomization": {
"path": "test-randomization/config.json",
"test": true
},
"test-skip-logic": {
"path": "test-skip-logic/config.json",
"test": true
"test-randomization": {
"path": "test-randomization/config.json",
"test": true
},
"test-component-timeout": {
"path": "test-component-timeout/config.json",
"test": true
},
"test-skip-logic": {
"path": "test-skip-logic/config.json",
"test": true
},
"test-step-logic": {
"path": "test-step-logic/config.json",
Expand All @@ -239,4 +244,4 @@
"test": true
}
}
}
}
2 changes: 1 addition & 1 deletion public/libraries/calvi/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"reference": "Lily W. Ge, Yuan Cui, and Matthew Kay. 2023. CALVI: Critical Thinking Assessment for Literacy in Visualizations. In Proceedings of the 2023 CHI Conference on Human Factors in Computing Systems (CHI '23). Association for Computing Machinery, New York, NY, USA, Article 815, 1-18.",
"components": {
"N1": {
"description": "Audio test",
"description": "Visitors at Movie Theaters in 2001",
"type": "image",
"path": "libraries/calvi/assets/questions/normal/N1.jpg",
"nextButtonLocation": "sidebar",
Expand Down
1 change: 1 addition & 0 deletions public/libraries/mic-check/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"path": "libraries/mic-check/assets/AudioTest.tsx",
"nextButtonLocation": "belowStimulus",
"nextButtonText": "Continue",
"recordAudio": true,
"response": [
{
"id": "audioTest",
Expand Down
18 changes: 10 additions & 8 deletions public/libraries/screen-recording/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
"path": "libraries/screen-recording/assets/ScreenRecording.tsx",
"nextButtonLocation": "belowStimulus",
"nextButtonText": "Continue",
"recordAudio": false,
"response": [{
"hidden": true,
"type": "reactive",
"id": "screenRecordingPermission",
"prompt": "Screen recording enabled"
}]
"recordScreen": true,
"response": [
{
"hidden": true,
"type": "reactive",
"id": "screenRecordingPermission",
"prompt": "Screen recording enabled"
}
]
}
},
"sequences": {}
}
}
58 changes: 58 additions & 0 deletions public/test-component-timeout/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"$schema": "https://raw.githubusercontent.com/revisit-studies/study/v2.4.2/src/parser/StudyConfigSchema.json",
"studyMetadata": {
"title": "Component Timeout Auto-Advance Test",
"version": "pilot",
"authors": [
"The reVISit Team"
],
"date": "2026-05-14",
"description": "A test study for component-level auto-advance timeouts.",
"organizations": [
"The reVISit Team"
]
},
"uiConfig": {
"contactEmail": "contact@revisit.dev",
"logoPath": "revisitAssets/revisitLogoSquare.svg",
"withProgressBar": true,
"autoDownloadStudy": false,
"withSidebar": true,
"studyEndMsg": "Timeout auto-advance test complete."
},
"baseComponents": {
"timed-question": {
"type": "questionnaire",
"instruction": "Do not answer this question. It should automatically advance.",
"response": [
{
"id": "timeout-response",
"prompt": "Optional answer",
"location": "belowStimulus",
"type": "shortText",
"required": false
}
],
"nextButtonAutoAdvanceTime": 2500,
"nextButtonAutoAdvanceWarningTime": 1500,
"nextButtonAutoAdvanceWarningMessage": "Custom timeout warning: advancing in {seconds} {unit} without saving this component."
}
},
"components": {
"introduction": {
"type": "questionnaire",
"instruction": "Press next to begin the timeout auto-advance test.",
"response": []
},
"timeout-question": {
"baseComponent": "timed-question"
}
},
"sequence": {
"order": "fixed",
"components": [
"introduction",
"timeout-question"
]
}
}
67 changes: 44 additions & 23 deletions src/GlobalConfigParser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,72 @@ async function fetchGlobalConfigArray() {
return parseGlobalConfig(configs);
}

export function GlobalConfigParser() {
const [globalConfig, setGlobalConfig] = useState<Nullable<GlobalConfig>>(null);
function HomeRoute({ globalConfig }: { globalConfig: GlobalConfig }) {
const [studyConfigs, setStudyConfigs] = useState<Record<string, ParsedConfig<StudyConfig> | null>>({});

useEffect(() => {
async function fetchData() {
if (globalConfig) {
setStudyConfigs(await fetchStudyConfigs(globalConfig));
let cancelled = false;

async function fetchData(currentGlobalConfig: GlobalConfig) {
const configs = await fetchStudyConfigs(currentGlobalConfig);
if (!cancelled) {
setStudyConfigs(configs);
}
}
fetchData();

fetchData(globalConfig);

return () => {
cancelled = true;
};
}, [globalConfig]);

return (
<>
<PageTitle title="ReVISit | Home" />
<AppShell
padding="md"
header={{ height: 70 }}
>
<AppHeader studyIds={globalConfig.configsList} />
<ConfigSwitcher
globalConfig={globalConfig}
studyConfigs={studyConfigs}
/>
</AppShell>
</>
);
}

export function GlobalConfigParser() {
const [globalConfig, setGlobalConfig] = useState<Nullable<GlobalConfig>>(null);

useEffect(() => {
if (globalConfig) return;
if (globalConfig) {
return undefined;
}

fetchGlobalConfigArray().then((gc) => {
setGlobalConfig(gc);
});

return undefined;
}, [globalConfig]);

// Initialize storage engine
const { storageEngine, setStorageEngine } = useStorageEngine();
useEffect(() => {
if (storageEngine !== undefined) return;
if (storageEngine !== undefined) {
return undefined;
}

async function fn() {
const _storageEngine = await initializeStorageEngine();
setStorageEngine(_storageEngine);
}
fn();

return undefined;
}, [setStorageEngine, storageEngine]);

const analysisProtectedCallback = async (studyId: string) => {
Expand All @@ -76,21 +111,7 @@ export function GlobalConfigParser() {
<Routes>
<Route
path="/"
element={(
<>
<PageTitle title="ReVISit | Home" />
<AppShell
padding="md"
header={{ height: 70 }}
>
<AppHeader studyIds={globalConfig.configsList} />
<ConfigSwitcher
globalConfig={globalConfig}
studyConfigs={studyConfigs}
/>
</AppShell>
</>
)}
element={<HomeRoute globalConfig={globalConfig} />}
/>
<Route
path="/:studyId/*"
Expand Down
3 changes: 2 additions & 1 deletion src/analysis/individualStudy/replay/AllTasksTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export function AllTasksTimeline({
const isCorrect = componentAnswersAreCorrect(answer.answer, answer.correctAnswer, resolvedComponent?.response);
const hasCorrect = !!((resolvedComponent && resolvedComponent.correctAnswer) || answer.correctAnswer.length > 0);
const hasAudio = resolvedComponent?.recordAudio ?? studyConfig?.uiConfig?.recordAudio ?? false;
const hasScreenRecording = resolvedComponent?.recordScreen ?? studyConfig?.uiConfig?.recordScreen ?? false;

return {
line: <SingleTaskLabelLines key={name} labelHeight={currentHeight * LABEL_GAP} height={maxHeight} xScale={scale} scaleStart={scaleStart} />,
Expand Down Expand Up @@ -147,7 +148,7 @@ export function AllTasksTimeline({
)}
>
<g>
<SingleTask incomplete={answer.startTime === 0} isCorrect={isCorrect} hasCorrect={hasCorrect} hasAudio={hasAudio} key={name} labelHeight={currentHeight * LABEL_GAP} height={maxHeight} name={name} xScale={scale} scaleStart={scaleStart} scaleEnd={scaleEnd} trialOrder={answer.trialOrder} participantId={participantData.participantId} studyId={studyId} condition={conditionParam} />
<SingleTask incomplete={answer.startTime === 0} isCorrect={isCorrect} hasCorrect={hasCorrect} hasAudio={hasAudio} hasScreenRecording={hasScreenRecording} key={name} labelHeight={currentHeight * LABEL_GAP} height={maxHeight} name={name} xScale={scale} scaleStart={scaleStart} scaleEnd={scaleEnd} trialOrder={answer.trialOrder} participantId={participantData.participantId} studyId={studyId} condition={conditionParam} />
</g>
</Tooltip>),
};
Expand Down
12 changes: 10 additions & 2 deletions src/analysis/individualStudy/replay/SingleTask.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as d3 from 'd3';

import { useResizeObserver } from '@mantine/hooks';
import {
IconCheck, IconMicrophone, IconProgress, IconX,
IconCheck, IconDeviceDesktop, IconMicrophone, IconProgress, IconX,
} from '@tabler/icons-react';
import { useNavigateToTrial } from '../../../utils/useNavigateToTrial';

Expand All @@ -24,6 +24,7 @@ export function SingleTask({
isCorrect,
hasCorrect,
hasAudio,
hasScreenRecording,
scaleStart,
scaleEnd,
incomplete,
Expand All @@ -39,6 +40,7 @@ export function SingleTask({
isCorrect: boolean,
hasCorrect: boolean,
hasAudio: boolean,
hasScreenRecording: boolean,
scaleStart: number,
scaleEnd: number,
incomplete: boolean,
Expand All @@ -52,7 +54,7 @@ export function SingleTask({
const [ref, { width: labelWidth }] = useResizeObserver();

const navigateToTrial = useNavigateToTrial();
const iconCount = (incomplete || hasCorrect ? 1 : 0) + (hasAudio ? 1 : 0);
const iconCount = (incomplete || hasCorrect ? 1 : 0) + (hasAudio ? 1 : 0) + (hasScreenRecording ? 1 : 0);
const iconsWidth = iconCount * (ICON_SIZE + ICON_GAP);

return (
Expand Down Expand Up @@ -93,6 +95,12 @@ export function SingleTask({
<Text lineClamp={1} ref={ref} mx={0} style={{ width: 'fit-content', fontWeight: 600 }} size="12px">
{name}
</Text>
{hasScreenRecording && (
<IconDeviceDesktop
color="orange"
size="14"
/>
)}
{hasAudio && (
<IconMicrophone
color="orange"
Expand Down
6 changes: 0 additions & 6 deletions src/analysis/individualStudy/summary/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,6 @@ function createMockAnswer(overrides: {
incorrectAnswers: {},
startTime: overrides.startTime,
endTime: overrides.endTime,
provenanceGraph: {
sidebar: undefined,
aboveStimulus: undefined,
belowStimulus: undefined,
stimulus: undefined,
},
windowEvents: [],
timedOut: false,
helpButtonClickedCount: 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ export function ThinkAloudAnalysis({ visibleParticipants, storageEngine } : { vi
if (!participantId && visibleParticipants.length > 0) {
setSearchParams((params) => {
params.set('participantId', visibleParticipants[0].participantId);
params.delete('currentTrial');
return params;
});
}
Expand Down
Loading
Loading