Skip to content

Commit e3e34b8

Browse files
authored
Fix bug in print statement controller session grouping; add scroll to (#118)
backup
1 parent 03e287f commit e3e34b8

2 files changed

Lines changed: 35 additions & 11 deletions

File tree

src/snapshots-app/app/controllers/api/debugging/print_statements_controller.rb

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,17 +102,19 @@ def show
102102
end
103103

104104
# Identify the indices of backups that contain prints
105-
print_indices = all_data.each_index.select { |i| all_data[i][:has_print] }
105+
# TODO investigate why problem name can be empty. perhaps they just ran `python3 ok` without specifying a problem?
106+
print_indices = all_data.each_index.select { |i| all_data[i][:has_print] and all_data[i][:problem] != "" }
106107

107108
return render json: [] if print_indices.empty?
108109

109-
# Group consecutive print indices into sessions
110+
# Group consecutive print indices and same problem name into sessions
110111
# e.g., [1, 2, 5, 6, 7] -> [[1, 2], [5, 6, 7]]
111112
sessions = []
112113
if print_indices.any?
113114
current_session = [ print_indices.first ]
114115
print_indices[1..].each do |idx|
115-
if idx == current_session.last + 1
116+
prev_idx = current_session.last
117+
if idx == prev_idx + 1 and all_data[prev_idx][:problem] == all_data[idx][:problem]
116118
current_session << idx
117119
else
118120
sessions << current_session
@@ -122,15 +124,19 @@ def show
122124
sessions << current_session
123125
end
124126

125-
# Expand sessions to include +/- 5 backups and flatten/deduplicate
127+
# Expand sessions to include +/- 5 backups with the same problem and flatten/deduplicate
126128
# Use a Set to ensure that if sessions overlap (within 10 backups of each other),
127129
# we don't include the same backup twice.
128130
final_indices = Set.new
129131
sessions.each do |session_range|
130132
start_idx = [ 0, session_range.min - 5 ].max
131133
end_idx = [ all_data.length - 1, session_range.max + 5 ].min
132134

133-
(start_idx..end_idx).each { |i| final_indices.add(i) }
135+
(start_idx..end_idx).each do |i|
136+
if all_data[i][:problem] == all_data[session_range[0]][:problem]
137+
final_indices.add(i)
138+
end
139+
end
134140
end
135141

136142
# Extract the data for the final indices and sort by timestamp

src/snapshots-app/client/bundles/components/submission/tabs/timeline/Timeline.jsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { useCopyToClipboard } from "react-use";
1717

1818
import { getOkpyCommand, areArraysEqual } from "../../utils";
1919

20-
function TimelineButton({ backup, selected, index, handleBackupSelect }) {
20+
function TimelineButton({ backup, selected, index, handleBackupSelect, ref }) {
2121
function getQuestionsWorkedOn() {
2222
return backup.question_display_names.join(" ");
2323
}
@@ -106,6 +106,7 @@ function TimelineButton({ backup, selected, index, handleBackupSelect }) {
106106
return (
107107
<Tooltip title={getTooltipTitle()} placement="right">
108108
<Button
109+
ref={ref}
109110
key={backup.id}
110111
variant={selected ? "contained" : "outlined"}
111112
onClick={() => handleBackupSelect(index)}
@@ -123,6 +124,7 @@ function TimelineButtonGroup({
123124
handleBackupSelect,
124125
absoluteStartIndex,
125126
setIsSnackbarOpen,
127+
selectedRef,
126128
}) {
127129
const [_, copyOkpyCommand] = useCopyToClipboard();
128130
const okpyCommand = getOkpyCommand(
@@ -169,14 +171,17 @@ function TimelineButtonGroup({
169171
aria-label="Vertical button group"
170172
style={{ width: "100%" }}
171173
>
172-
{backups.map((backup, relativeIndex) => (
173-
<TimelineButton
174+
{backups.map((backup, relativeIndex) => {
175+
const isSelected = relativeIndex + absoluteStartIndex === selectedBackup;
176+
177+
return (<TimelineButton
174178
backup={backup}
175-
selected={relativeIndex + absoluteStartIndex === selectedBackup}
179+
selected={isSelected}
176180
index={relativeIndex + absoluteStartIndex}
177181
handleBackupSelect={handleBackupSelect}
178-
/>
179-
))}
182+
ref={isSelected ? selectedRef : null}
183+
/>);
184+
})}
180185
</ButtonGroup>
181186
</div>
182187
);
@@ -187,6 +192,18 @@ function Timeline({ backups, selectedBackup, handleBackupSelect }) {
187192
"A timeline of this student's OkPy backups, most recent backup first. A backup is formed every time they run unlocking or coding tests for a particular question.";
188193

189194
const [isSnackbarOpen, setIsSnackbarOpen] = React.useState(false);
195+
const selectedRef = React.useRef(null);
196+
197+
// Add an effect that scrolls when selectedBackup changes or on initial load
198+
// TODO only scroll left sidebar, not entire page
199+
useEffect(() => {
200+
if (selectedRef.current) {
201+
selectedRef.current.scrollIntoView({
202+
behavior: "smooth", // Use "auto" for instant jump on page load
203+
block: "center", // Centers the button in the viewport
204+
});
205+
}
206+
}, [selectedBackup]); // Re-run if the selection changes
190207

191208
const handleSnackbarClose = (event, reason) => {
192209
if (reason === "clickaway") {
@@ -269,6 +286,7 @@ function Timeline({ backups, selectedBackup, handleBackupSelect }) {
269286
handleBackupSelect={handleBackupSelect}
270287
absoluteStartIndex={absoluteStartIndex}
271288
setIsSnackbarOpen={setIsSnackbarOpen}
289+
selectedRef={selectedRef}
272290
/>,
273291
);
274292
absoluteStartIndex += backupGroup.length;

0 commit comments

Comments
 (0)