Skip to content

Commit 1413dee

Browse files
committed
timetravel git - much more works now
1 parent 364049c commit 1413dee

File tree

5 files changed

+160
-141
lines changed

5 files changed

+160
-141
lines changed

src/packages/frontend/frame-editors/time-travel-editor/actions.ts

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
6363
private docpath: string;
6464
private docext: string;
6565
private syncpath: string;
66-
public syncdoc?: SyncDoc;
66+
syncdoc?: SyncDoc;
6767
private first_load: boolean = true;
68-
public ambient_actions?: CodeEditorActions;
68+
ambient_actions?: CodeEditorActions;
6969
private gitTimestampToHash: { [t: number]: string } = {};
7070

71-
public _init2(): void {
71+
_init2(): void {
7272
const { head, tail } = path_split(this.path);
7373
this.docpath = tail.slice(1, tail.length - EXTENSION.length);
7474
if (head != "") {
@@ -90,19 +90,19 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
9090
this.updateGitVersions();
9191
}
9292

93-
public _raw_default_frame_tree(): FrameTree {
93+
_raw_default_frame_tree(): FrameTree {
9494
return { type: "time_travel" };
9595
}
9696

97-
private async init_syncdoc(): Promise<void> {
97+
private init_syncdoc = async (): Promise<void> => {
9898
const persistent = this.docext == "ipynb" || this.docext == "sagews"; // ugly for now (?)
9999
this.syncdoc = await webapp_client.sync_client.open_existing_sync_document({
100100
project_id: this.project_id,
101101
path: this.syncpath,
102102
persistent,
103103
});
104104
if (this.syncdoc == null) return;
105-
this.syncdoc.on("change", debounce(this.syncdoc_changed.bind(this), 1000));
105+
this.syncdoc.on("change", debounce(this.syncdoc_changed, 1000));
106106
if (this.syncdoc.get_state() != "ready") {
107107
await once(this.syncdoc, "ready");
108108
}
@@ -115,7 +115,7 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
115115
loading: false,
116116
has_full_history: this.syncdoc.has_full_history(),
117117
});
118-
}
118+
};
119119

120120
init_frame_tree = () => {
121121
this.ensureSelectedVersionsAreConsistent();
@@ -166,7 +166,7 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
166166
}
167167
};
168168

169-
public async load_full_history(): Promise<void> {
169+
load_full_history = async (): Promise<void> => {
170170
if (
171171
this.store.get("has_full_history") ||
172172
this.syncdoc == null ||
@@ -176,9 +176,9 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
176176
await this.syncdoc.load_full_history(); // todo -- error reporting ...?
177177
this.setState({ has_full_history: true });
178178
this.syncdoc_changed(); // load new versions list.
179-
}
179+
};
180180

181-
private syncdoc_changed(): void {
181+
private syncdoc_changed = (): void => {
182182
if (this.syncdoc == null) return;
183183
if (this.syncdoc?.get_state() != "ready") {
184184
return;
@@ -197,28 +197,28 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
197197
this.first_load = false;
198198
this.ensureSelectedVersionsAreConsistent({ versions });
199199
}
200-
}
200+
};
201201

202202
// For each store version in a frame node, check to see
203203
// if the Date changes from the current versions to the new
204204
// ones and if so, fix it. We do this because if you're looking
205205
// at time t at position p, and somebody inserts a new version
206206
// before position p ... then suddenly position p is no longer
207207
// time t, which would be confusing.
208-
private ensure_versions_are_stable(new_versions): void {
208+
private ensure_versions_are_stable = (new_versions): void => {
209209
// TODO
210210
new_versions = new_versions;
211-
}
211+
};
212212

213213
// Get the given version of the document.
214-
public get_doc(version: Date): Document | undefined {
214+
get_doc = (version: Date): Document | undefined => {
215215
if (this.syncdoc == null) return;
216216
const state = this.syncdoc.get_state();
217217
if (state != "ready") return;
218218
return this.syncdoc.version(version);
219-
}
219+
};
220220

221-
public get_account_ids(version0: number, version1: number): string[] {
221+
get_account_ids = (version0: number, version1: number): string[] => {
222222
if (this.syncdoc == null) return [];
223223
const versions = this.store.get("versions");
224224
if (versions == null || versions.size == 0) return [];
@@ -234,16 +234,16 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
234234
}
235235
}
236236
return keys(account_ids);
237-
}
237+
};
238238

239-
private get_frame_node_global(id: string) {
239+
private getFrameNodeGlobal = (id: string) => {
240240
for (const actions of [this, this.ambient_actions]) {
241241
if (actions == null) continue;
242242
const node = actions._get_frame_node(id);
243243
if (node != null) return node;
244244
}
245245
throw Error(`BUG -- no node with id ${id}`);
246-
}
246+
};
247247

248248
set_version = (id: string, version: number): void => {
249249
for (const actions of [this, this.ambient_actions]) {
@@ -270,17 +270,19 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
270270
}
271271
};
272272

273-
public step(id: string, delta: number): void {
274-
const node = this.get_frame_node_global(id);
273+
step = (id: string, delta: number): void => {
274+
const node = this.getFrameNodeGlobal(id);
275275
if (node.get("changes_mode")) {
276-
this.set_versions(
276+
this.setVersions(
277277
id,
278278
node.get("version0") + delta,
279279
node.get("version1") + delta,
280280
);
281281
return;
282282
}
283-
const versions = this.store.get("versions");
283+
const versions = node.get("git_mode")
284+
? this.store.get("git_versions")
285+
: this.store.get("versions");
284286
if (versions == null || versions.size == 0) return;
285287
let version = node.get("version");
286288
if (version == null) {
@@ -293,9 +295,9 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
293295
version += versions.size;
294296
}
295297
this.set_version(id, version);
296-
}
298+
};
297299

298-
public set_changes_mode(id: string, changes_mode: boolean): void {
300+
set_changes_mode = (id: string, changes_mode: boolean): void => {
299301
for (const actions of [this, this.ambient_actions]) {
300302
if (actions == null) continue;
301303
const node = actions._get_frame_node(id);
@@ -320,9 +322,9 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
320322
}
321323
return;
322324
}
323-
}
325+
};
324326

325-
public setTextMode(id: string, text_mode: boolean): void {
327+
setTextMode = (id: string, text_mode: boolean): void => {
326328
for (const actions of [this, this.ambient_actions]) {
327329
if (actions == null) continue;
328330
const node = actions._get_frame_node(id);
@@ -331,9 +333,9 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
331333
actions.set_frame_tree({ id, text_mode });
332334
break;
333335
}
334-
}
336+
};
335337

336-
public setGitMode(id: string, git_mode: boolean): void {
338+
setGitMode = (id: string, git_mode: boolean): void => {
337339
for (const actions of [this, this.ambient_actions]) {
338340
if (actions == null) continue;
339341
const node = actions._get_frame_node(id);
@@ -343,44 +345,61 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
343345
break;
344346
}
345347
this.updateGitVersions();
346-
}
348+
};
347349

348-
public set_versions(id: string, version0: number, version1: number): void {
350+
setVersions = (id: string, version0: number, version1: number): void => {
349351
for (const actions of [this, this.ambient_actions]) {
350-
if (actions == null || actions._get_frame_node(id) == null) continue;
351-
const versions = this.store.get("versions");
352+
const node = actions?._get_frame_node(id);
353+
if (node == null) {
354+
continue;
355+
}
356+
const versions = node.get("git_mode")
357+
? this.store.get("git_versions")
358+
: this.store.get("versions");
359+
if (versions == null) {
360+
// not configured.
361+
return;
362+
}
352363
if (version0 >= version1) {
353364
version0 = version1 - 1;
354365
}
355-
if (version0 >= versions.size) version0 = versions.size - 1;
356-
if (version0 < 0) version0 = 0;
357-
if (version1 >= versions.size) version1 = versions.size - 1;
358-
if (version1 < 0) version1 = 0;
359-
actions.set_frame_tree({ id, version0, version1 });
366+
if (version0 >= versions.size) {
367+
version0 = versions.size - 1;
368+
}
369+
if (version0 < 0) {
370+
version0 = 0;
371+
}
372+
if (version1 >= versions.size) {
373+
version1 = versions.size - 1;
374+
}
375+
if (version1 < 0) {
376+
version1 = 0;
377+
}
378+
actions?.set_frame_tree({ id, version0, version1 });
360379
return;
361380
}
362-
}
381+
};
363382

364-
public async open_file(): Promise<void> {
383+
open_file = async (): Promise<void> => {
365384
const actions = this.redux.getProjectActions(this.project_id);
366385
await actions.open_file({ path: this.docpath, foreground: true });
367-
}
386+
};
368387

369388
// Revert the live version of the document to a specific version */
370-
public async revert(version: Date): Promise<void> {
389+
revert = async (version: Date): Promise<void> => {
371390
if (this.syncdoc == null) return;
372391
this.syncdoc.revert(version);
373392
this.syncdoc.commit();
374393
await this.open_file();
375394
if (this.syncdoc == null) return;
376395
this.syncdoc.emit("change");
377-
}
396+
};
378397

379-
public open_snapshots(): void {
398+
open_snapshots = (): void => {
380399
this.redux.getProjectActions(this.project_id).open_directory(".snapshots");
381-
}
400+
};
382401

383-
public async export(): Promise<string> {
402+
exportEditHistory = async (): Promise<string> => {
384403
const path = await export_to_json(
385404
this.syncdoc,
386405
this.docpath,
@@ -389,7 +408,7 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
389408
const actions = this.redux.getProjectActions(this.project_id);
390409
await actions.open_file({ path, foreground: true });
391410
return path;
392-
}
411+
};
393412

394413
// We have not implemented any way to do programmatical_goto_line this for time travel yet.
395414
// It will be very interesting and useful, because it will allow for

src/packages/frontend/frame-editors/time-travel-editor/export.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ interface Props {
1919
export function Export({ actions }: Props) {
2020
return (
2121
<Button
22-
onClick={() => actions.export()}
22+
onClick={() => actions.exportEditHistory()}
2323
title="Export information about edit history to a JSON file"
2424
>
2525
<Icon name={"file-export"} /> Export

src/packages/frontend/frame-editors/time-travel-editor/navigation-buttons.tsx

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,45 @@ import { TimeTravelActions } from "./actions";
1919
interface Props {
2020
id: string;
2121
actions: TimeTravelActions;
22-
version0: number;
23-
version1: number;
22+
version0?: number;
23+
version1?: number;
2424
max: number;
2525
}
2626

27-
export function NavigationButtons(props: Props) {
28-
const { version0, version1, max } = props;
27+
export function NavigationButtons({
28+
id,
29+
actions,
30+
version0,
31+
version1,
32+
max,
33+
}: Props) {
2934
return (
3035
<div style={{ display: "inline-flex" }}>
3136
<Button
3237
title={"First version"}
33-
onClick={() => props.actions.step(props.id, -version0)}
34-
disabled={version0 != null && version0 <= 0}
38+
onClick={() => actions.step(id, -(version0 ?? 0))}
39+
disabled={version0 == null || version0 <= 0}
3540
>
3641
<Icon name="backward" />
3742
</Button>
3843
<Button
3944
title={"Previous version"}
40-
onClick={() => props.actions.step(props.id, -1)}
41-
disabled={version0 != null && version0 <= 0}
45+
onClick={() => actions.step(id, -1)}
46+
disabled={version0 == null || version0 <= 0}
4247
>
4348
<Icon name="step-backward" />
4449
</Button>
4550
<Button
4651
title={"Next version"}
47-
onClick={() => props.actions.step(props.id, 1)}
48-
disabled={version1 != null && version1 >= max}
52+
onClick={() => actions.step(id, 1)}
53+
disabled={version1 == null || version1 >= max}
4954
>
5055
<Icon name="step-forward" />
5156
</Button>
5257
<Button
5358
title={"Most recent version"}
54-
onClick={() => props.actions.step(props.id, max - version1)}
55-
disabled={version1 != null && version1 >= max}
59+
onClick={() => actions.step(id, max - (version1 ?? 0))}
60+
disabled={version1 == null || version1 >= max}
5661
>
5762
<Icon name="forward" />
5863
</Button>

src/packages/frontend/frame-editors/time-travel-editor/range-slider.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ import { useFrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame
1818
interface Props {
1919
id: string;
2020
actions: TimeTravelActions;
21-
versions?: List<Date>;
22-
version0?: number;
23-
version1?: number;
21+
versions: List<Date>;
22+
version0: number;
23+
version1: number;
2424
}
2525

2626
export function RangeSlider({
@@ -34,22 +34,20 @@ export function RangeSlider({
3434

3535
// Have to hide when isVisible because tooltip stays ALWAYS visible otherwise.
3636
if (
37-
versions == null ||
3837
!isVisible ||
39-
version0 == null ||
40-
version1 == null ||
4138
versions.size == 0 ||
4239
version0 < 0 ||
43-
version1 > versions.size - 1
40+
version1 >= versions.size
4441
) {
42+
// invalid input
4543
return <div />;
4644
}
4745

4846
const handleChange = (values: number[]): void => {
4947
if (values[0] == null || values[1] == null) {
5048
throw Error("invalid values");
5149
}
52-
actions.set_versions(id, values[0], values[1]);
50+
actions.setVersions(id, values[0], values[1]);
5351
};
5452

5553
const renderTooltip = (index) => {

0 commit comments

Comments
 (0)