Skip to content

Commit aed9474

Browse files
committed
timetravel modernization -- sage worksheets
1 parent 416599d commit aed9474

File tree

5 files changed

+133
-168
lines changed

5 files changed

+133
-168
lines changed

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

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,17 @@
33
* License: MS-RSL – see LICENSE.md for details
44
*/
55

6-
import { Rendered, Component } from "../../app-framework";
76
import { Button } from "antd";
8-
import { TimeTravelActions } from "./actions";
97
import { Icon } from "../../components";
108

11-
interface Props {
12-
actions: TimeTravelActions;
13-
}
14-
15-
export class OpenFile extends Component<Props> {
16-
public render(): Rendered {
17-
// TODO: make the icon be the way for the given type of file
18-
return (
19-
<Button
20-
onClick={() => this.props.actions.open_file()}
21-
title={"Open the file whose history you are viewing"}
22-
>
23-
<Icon name="file-code" /> Open
24-
</Button>
25-
);
26-
}
9+
export function OpenFile({ actions }) {
10+
// TODO: make the icon be the right one for the given type of file
11+
return (
12+
<Button
13+
onClick={() => actions.open_file()}
14+
title={"Open the file whose history you are viewing"}
15+
>
16+
<Icon name="file-code" /> Open
17+
</Button>
18+
);
2719
}

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

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,21 @@
1111
*/
1212

1313
import { Button } from "antd";
14-
import { Rendered, Component } from "@cocalc/frontend/app-framework";
15-
import { TimeTravelActions } from "./actions";
1614
import { Icon } from "@cocalc/frontend/components";
1715
import track from "@cocalc/frontend/user-tracking";
1816

19-
interface Props {
20-
actions: TimeTravelActions;
21-
}
22-
23-
export class OpenSnapshots extends Component<Props> {
24-
public render(): Rendered {
25-
return (
26-
<Button
27-
onClick={() => {
28-
this.props.actions.open_snapshots();
29-
track("snapshots", { action: "open", where: "time-travel" });
30-
}}
31-
title={
32-
"Open the file system snapshots of this project, which may also be helpful in recovering past versions."
33-
}
34-
>
35-
<Icon name={"life-ring"} /> Backups
36-
</Button>
37-
);
38-
}
17+
export function OpenSnapshots({ actions }) {
18+
return (
19+
<Button
20+
onClick={() => {
21+
actions.open_snapshots();
22+
track("snapshots", { action: "open", where: "time-travel" });
23+
}}
24+
title={
25+
"Open the file system snapshots of this project, which may also be helpful in recovering past versions."
26+
}
27+
>
28+
<Icon name={"life-ring"} /> Backups
29+
</Button>
30+
);
3931
}

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

Lines changed: 48 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ code to get this done for now.
1010

1111
import { debounce } from "lodash";
1212
import * as CodeMirror from "codemirror";
13-
import { Component, React, Rendered } from "../../app-framework";
1413
import { Map } from "immutable";
15-
14+
import { useEffect, useRef, MutableRefObject } from "react";
1615
const { codemirror_editor } = require("../../editor");
1716
const { SynchronizedWorksheet } = require("../../sagews/sagews");
17+
import { useFrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame-context";
1818

1919
interface Props {
2020
content: string;
@@ -24,72 +24,66 @@ interface Props {
2424
editor_settings: Map<string, any>;
2525
}
2626

27-
export class SagewsCodemirror extends Component<Props> {
28-
private update: Function;
29-
private view_doc: any;
30-
private worksheet: any;
31-
private cm: CodeMirror.Editor;
32-
private div_ref: React.RefObject<HTMLDivElement> = React.createRef<
33-
HTMLDivElement
34-
>();
27+
export function SagewsCodemirror(props: Props) {
28+
const { isVisible } = useFrameContext();
29+
const updateRef = useRef<Function>(null) as MutableRefObject<Function>;
30+
const cmRef = useRef<CodeMirror.Editor | null>(
31+
null,
32+
) as MutableRefObject<CodeMirror.Editor | null>;
33+
const viewDocRef = useRef<any>(null);
34+
const divRef = useRef<any>(null);
3535

36-
private init_sagews(): void {
37-
const div = this.div_ref.current;
38-
if (div == null) return; // can't happen
36+
const initSagews = (): void => {
37+
const div = divRef.current;
38+
if (div == null) {
39+
// this better not happen
40+
return;
41+
}
3942

4043
const opts = { mode: "sagews", read_only: true };
41-
this.view_doc = codemirror_editor(
42-
this.props.project_id,
43-
this.props.path,
44-
opts
45-
);
46-
this.cm = this.view_doc.codemirror;
44+
viewDocRef.current = codemirror_editor(props.project_id, props.path, opts);
45+
cmRef.current = viewDocRef.current.codemirror;
4746
// insert it into the dom.
48-
$(this.view_doc.element).appendTo($(div));
47+
$(viewDocRef.current.element).appendTo($(div));
4948
// remove the second codemirror editor
50-
$(this.view_doc.codemirror1.getWrapperElement()).remove();
49+
$(viewDocRef.current.codemirror1.getWrapperElement()).remove();
5150

5251
const opts0 = {
5352
allow_javascript_eval: false,
5453
static_viewer: true,
5554
};
56-
this.worksheet = new SynchronizedWorksheet(this.view_doc, opts0);
55+
const worksheet = new SynchronizedWorksheet(viewDocRef.current, opts0);
5756

5857
const f = (content: string): void => {
59-
if (this.view_doc == null) return;
60-
this.cm.setValueNoJump(content);
61-
this.worksheet.process_sage_updates();
58+
if (viewDocRef.current == null) {
59+
return;
60+
}
61+
cmRef.current?.setValueNoJump(content);
62+
worksheet.process_sage_updates();
6263
};
63-
f(this.props.content);
64-
this.update = debounce(f, 100);
65-
}
66-
67-
public componentDidMount(): void {
68-
this.init_sagews();
69-
}
64+
f(props.content);
65+
updateRef.current = debounce(f, 100);
66+
};
7067

71-
public componentWillUnmount(): void {
72-
if (this.view_doc == null) return;
73-
this.view_doc.remove();
74-
delete this.view_doc;
75-
delete this.worksheet;
76-
}
68+
useEffect(() => {
69+
initSagews();
70+
return () => {
71+
if (viewDocRef.current == null) {
72+
return;
73+
}
74+
viewDocRef.current.remove();
75+
};
76+
}, []);
7777

78-
public UNSAFE_componentWillReceiveProps(props): void {
79-
if (props.content != this.props.content) {
80-
this.update(props.content);
81-
}
82-
if (props.font_size != this.props.font_size) {
83-
this.view_doc.set_font_size(this.cm, props.font_size);
84-
}
85-
this.cm.refresh();
86-
}
78+
useEffect(() => {
79+
updateRef.current?.(props.content);
80+
viewDocRef.current?.set_font_size(cmRef.current, props.font_size);
81+
cmRef.current?.refresh();
82+
}, [props.font_size, props.content, isVisible]);
8783

88-
public render(): Rendered {
89-
return (
90-
<div className="smc-vfill" style={{ overflow: "auto" }}>
91-
<div ref={this.div_ref} />
92-
</div>
93-
);
94-
}
84+
return (
85+
<div className="smc-vfill" style={{ overflow: "auto" }}>
86+
<div ref={divRef} />
87+
</div>
88+
);
9589
}

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

Lines changed: 48 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ code to get this done for now.
1010

1111
import { debounce } from "lodash";
1212
import * as CodeMirror from "codemirror";
13-
import { Component, React, Rendered } from "../../app-framework";
1413
import { Map } from "immutable";
14+
import { useEffect, useRef, MutableRefObject } from "react";
1515
import { set_cm_line_diff } from "./diff-util";
16-
1716
const { codemirror_editor } = require("../../editor");
1817
const { SynchronizedWorksheet } = require("../../sagews/sagews");
18+
import { useFrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame-context";
1919

2020
interface Props {
2121
v0: string;
@@ -26,74 +26,66 @@ interface Props {
2626
editor_settings: Map<string, any>;
2727
}
2828

29-
export class SagewsDiff extends Component<Props> {
30-
private update: Function;
31-
private view_doc: any;
32-
private worksheet: any;
33-
private cm: CodeMirror.Editor;
34-
private div_ref: React.RefObject<HTMLDivElement> = React.createRef<
35-
HTMLDivElement
36-
>();
29+
export function SagewsDiff(props: Props) {
30+
const { isVisible } = useFrameContext();
31+
const updateRef = useRef<Function>(null) as MutableRefObject<Function>;
32+
const cmRef = useRef<CodeMirror.Editor | null>(
33+
null,
34+
) as MutableRefObject<CodeMirror.Editor | null>;
35+
const viewDocRef = useRef<any>(null);
36+
const divRef = useRef<any>(null);
3737

38-
private init_sagews(): void {
39-
const div = this.div_ref.current;
40-
if (div == null) return; // can't happen
38+
const initSagews = (): void => {
39+
const div = divRef.current;
40+
if (div == null) {
41+
// this better not happen
42+
return;
43+
}
4144

4245
const opts = { mode: "sagews", read_only: true };
43-
this.view_doc = codemirror_editor(
44-
this.props.project_id,
45-
this.props.path,
46-
opts
47-
);
48-
this.cm = this.view_doc.codemirror;
49-
this.view_doc.set_font_size(this.cm, this.props.font_size);
50-
46+
viewDocRef.current = codemirror_editor(props.project_id, props.path, opts);
47+
cmRef.current = viewDocRef.current.codemirror;
5148
// insert it into the dom.
52-
$(this.view_doc.element).appendTo($(div));
49+
$(viewDocRef.current.element).appendTo($(div));
5350
// remove the second codemirror editor
54-
$(this.view_doc.codemirror1.getWrapperElement()).remove();
51+
$(viewDocRef.current.codemirror1.getWrapperElement()).remove();
5552

5653
const opts0 = {
5754
allow_javascript_eval: false,
5855
static_viewer: true,
5956
};
60-
this.worksheet = new SynchronizedWorksheet(this.view_doc, opts0);
57+
const worksheet = new SynchronizedWorksheet(viewDocRef.current, opts0);
6158

6259
const f = (v0: string, v1: string): void => {
63-
if (this.view_doc == null) return;
64-
set_cm_line_diff(this.cm, v0, v1);
65-
this.worksheet.process_sage_updates();
60+
if (viewDocRef.current == null || cmRef.current == null) {
61+
return;
62+
}
63+
set_cm_line_diff(cmRef.current, v0, v1);
64+
worksheet.process_sage_updates();
6665
};
67-
f(this.props.v0, this.props.v1);
68-
this.update = debounce(f, 300);
69-
}
70-
71-
public componentDidMount(): void {
72-
this.init_sagews();
73-
}
66+
f(props.v0, props.v1);
67+
updateRef.current = debounce(f, 100);
68+
};
7469

75-
public componentWillUnmount(): void {
76-
if (this.view_doc == null) return;
77-
this.view_doc.remove();
78-
delete this.view_doc;
79-
delete this.worksheet;
80-
}
70+
useEffect(() => {
71+
initSagews();
72+
return () => {
73+
if (viewDocRef.current == null) {
74+
return;
75+
}
76+
viewDocRef.current.remove();
77+
};
78+
}, []);
8179

82-
public UNSAFE_componentWillReceiveProps(props): void {
83-
if (props.v0 != this.props.v0 || props.v1 != this.props.v1) {
84-
this.update(props.v0, props.v1);
85-
}
86-
if (props.font_size != this.props.font_size) {
87-
this.view_doc.set_font_size(this.cm, props.font_size);
88-
}
89-
this.cm.refresh();
90-
}
80+
useEffect(() => {
81+
updateRef.current?.(props.v0, props.v1);
82+
viewDocRef.current?.set_font_size(cmRef.current, props.font_size);
83+
cmRef.current?.refresh();
84+
}, [props.font_size, isVisible, props.v0, props.v1]);
9185

92-
public render(): Rendered {
93-
return (
94-
<div className="smc-vfill" style={{ overflow: "auto" }}>
95-
<div ref={this.div_ref} />
96-
</div>
97-
);
98-
}
86+
return (
87+
<div className="smc-vfill" style={{ overflow: "auto" }}>
88+
<div ref={divRef} />
89+
</div>
90+
);
9991
}

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

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,24 @@ out a range.
1515
import { SyncDoc } from "@cocalc/sync/editor/generic/sync-doc";
1616
import Worksheet from "../../sagews/worksheet";
1717
import { parse_sagews } from "../../sagews/parse-sagews";
18-
import { Rendered, Component } from "../../app-framework";
1918

2019
interface Props {
2120
syncdoc: SyncDoc; // syncdoc corresponding to a Sage worksheet
2221
version: Date;
2322
}
2423

25-
export class SageWorksheetHistory extends Component<Props> {
26-
public shouldComponentUpdate(props): boolean {
27-
return this.props.version != props.version;
28-
}
29-
30-
public render(): Rendered {
31-
const v = this.props.syncdoc.version(this.props.version);
32-
if (v == null) return <span />;
33-
const content: string = v.to_str();
34-
return (
35-
<div
36-
className="smc-vfill"
37-
style={{ overflowY: "scroll", margin: "30px 30px 0 30px" }}
38-
>
39-
<Worksheet sagews={parse_sagews(content)} />
40-
</div>
41-
);
24+
export function SageWorksheetHistory({ syncdoc, version }: Props) {
25+
const v = syncdoc.version(version);
26+
if (v == null) {
27+
return <span />;
4228
}
29+
const content: string = v.to_str();
30+
return (
31+
<div
32+
className="smc-vfill"
33+
style={{ overflowY: "scroll", margin: "30px 30px 0 30px" }}
34+
>
35+
<Worksheet sagews={parse_sagews(content)} />
36+
</div>
37+
);
4338
}

0 commit comments

Comments
 (0)