Skip to content

Commit 3e575df

Browse files
committed
feat(editor): add undo redo icons to editor - I204
Signed-off-by: Dharma Teja <dteja2468@gmail.com>
1 parent 7ae2812 commit 3e575df

File tree

4 files changed

+85
-37
lines changed

4 files changed

+85
-37
lines changed

src/components/useUndoRedo.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { useState } from "react";
2+
3+
4+
function useUndoRedo<T>(initialValue: T) {
5+
const [past, setPast] = useState<T[]>([]);
6+
const [present, setPresent] = useState<T>(initialValue);
7+
const [future, setFuture] = useState<T[]>([]);
8+
9+
// Function to update the present state and track past states
10+
const set = (newValue: T) => {
11+
setPast((prevPast) => [...prevPast, present]);
12+
setPresent(newValue);
13+
setFuture([]); // Clear future when new change is made
14+
};
15+
16+
const undo = () => {
17+
if (past.length === 0) return;
18+
const previous = past[past.length - 1];
19+
setPast((prevPast) => prevPast.slice(0, -1));
20+
setFuture((prevFuture) => [present, ...prevFuture]);
21+
setPresent(previous);
22+
};
23+
24+
const redo = () => {
25+
if (future.length === 0) return;
26+
const next = future[0];
27+
setFuture((prevFuture) => prevFuture.slice(1));
28+
setPast((prevPast) => [...prevPast, present]);
29+
setPresent(next);
30+
};
31+
32+
return { value: present, set, undo, redo };
33+
}
34+
35+
export default useUndoRedo;
Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import JSONEditor from "../JSONEditor";
22
import useAppStore from "../../store/store";
3+
import useUndoRedo from "../../components/useUndoRedo";
34
import { useCallback } from "react";
45
import { debounce } from "ts-debounce";
6+
import { FaUndo, FaRedo } from "react-icons/fa";
57

68
function AgreementData() {
7-
const editorAgreementData = useAppStore((state) => state.editorAgreementData);
8-
const setEditorAgreementData = useAppStore(
9-
(state) => state.setEditorAgreementData
10-
);
11-
const setData = useAppStore((state) => state.setData);
129
const textColor = useAppStore((state) => state.textColor);
10+
const setData = useAppStore((state) => state.setData);
11+
const { value, set, undo, redo } = useUndoRedo(useAppStore((state) => state.editorAgreementData));
1312

1413
const debouncedSetData = useCallback(
1514
debounce((value: string) => {
@@ -20,23 +19,26 @@ function AgreementData() {
2019

2120
const handleChange = (value: string | undefined) => {
2221
if (value !== undefined) {
23-
setEditorAgreementData(value); // Immediate state update
24-
debouncedSetData(value); // Debounced state update
22+
set(value);
23+
debouncedSetData(value);
2524
}
2625
};
2726

2827
return (
29-
<div className="column">
30-
<div className="tooltip">
28+
<div className="column" >
29+
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
3130
<h3 style={{ color: textColor }}>Data</h3>
32-
<span style={{ color: textColor }} className="tooltiptext">
33-
JSON data (an instance of the Concerto model) used to preview output
34-
from the template.
35-
</span>
31+
<div>
32+
<FaUndo onClick={undo} style={{ cursor: "pointer", color: textColor, marginRight: "8px" }} />
33+
<FaRedo onClick={redo} style={{ cursor: "pointer", color: textColor }} />
34+
</div>
3635
</div>
37-
<JSONEditor value={editorAgreementData} onChange={handleChange} />
36+
<p style={{ color: textColor }}>
37+
JSON data (an instance of the Concerto model) used to preview output from the template.
38+
</p>
39+
<JSONEditor value={value} onChange={handleChange} />
3840
</div>
3941
);
4042
}
4143

42-
export default AgreementData;
44+
export default AgreementData;
Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,45 @@
11
import MarkdownEditor from "../MarkdownEditor";
22
import useAppStore from "../../store/store";
3+
import useUndoRedo from "../../components/useUndoRedo";
34
import { useCallback } from "react";
45
import { debounce } from "ts-debounce";
6+
import { FaUndo, FaRedo } from "react-icons/fa";
57

68
function TemplateMarkdown() {
7-
const editorValue = useAppStore((state) => state.editorValue);
8-
const setEditorValue = useAppStore((state) => state.setEditorValue);
9-
const setTemplateMarkdown = useAppStore((state) => state.setTemplateMarkdown);
10-
const backgroundColor = useAppStore((state) => state.backgroundColor);
119
const textColor = useAppStore((state) => state.textColor);
10+
const backgroundColor = useAppStore((state) => state.backgroundColor);
11+
const setTemplateMarkdown = useAppStore((state) => state.setTemplateMarkdown);
12+
const { value, set, undo, redo } = useUndoRedo(useAppStore((state) => state.editorValue));
1213

1314
const debouncedSetTemplateMarkdown = useCallback(
1415
debounce((value: string) => {
1516
void setTemplateMarkdown(value);
1617
}, 500),
17-
[]
18+
[setTemplateMarkdown]
1819
);
1920

2021
const handleChange = (value: string | undefined) => {
2122
if (value !== undefined) {
22-
setEditorValue(value);
23+
set(value);
2324
debouncedSetTemplateMarkdown(value);
2425
}
2526
};
2627

2728
return (
28-
<div className="column" style={{ backgroundColor: backgroundColor }}>
29-
<h2 style={{ color: textColor }}>TemplateMark</h2>
29+
<div className="column" style={{ backgroundColor }}>
30+
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
31+
<h3 style={{ color: textColor }}>TemplateMark</h3>
32+
<div>
33+
<FaUndo onClick={undo} style={{ cursor: "pointer", color: textColor, marginRight: "8px" }} />
34+
<FaRedo onClick={redo} style={{ cursor: "pointer", color: textColor }} />
35+
</div>
36+
</div>
3037
<p style={{ color: textColor }}>
31-
A natural language template with embedded variables, conditional
32-
sections, and TypeScript code.
38+
A natural language template with embedded variables, conditional sections, and TypeScript code.
3339
</p>
34-
<MarkdownEditor value={editorValue} onChange={handleChange} />
40+
<MarkdownEditor value={value} onChange={handleChange} />
3541
</div>
3642
);
3743
}
3844

39-
export default TemplateMarkdown;
45+
export default TemplateMarkdown;
Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import ConcertoEditor from "../ConcertoEditor";
22
import useAppStore from "../../store/store";
3+
import useUndoRedo from "../../components/useUndoRedo";
34
import { useCallback } from "react";
45
import { debounce } from "ts-debounce";
6+
import { FaUndo, FaRedo } from "react-icons/fa";
57

68
function TemplateModel() {
7-
const editorModelCto = useAppStore((state) => state.editorModelCto);
8-
const setEditorModelCto = useAppStore((state) => state.setEditorModelCto);
9-
const setModelCto = useAppStore((state) => state.setModelCto);
109
const textColor = useAppStore((state) => state.textColor);
10+
const setModelCto = useAppStore((state) => state.setModelCto);
11+
const { value, set, undo, redo } = useUndoRedo(useAppStore((state) => state.editorModelCto));
1112

1213
const debouncedSetModelCto = useCallback(
1314
debounce((value: string) => {
@@ -18,22 +19,26 @@ function TemplateModel() {
1819

1920
const handleChange = (value: string | undefined) => {
2021
if (value !== undefined) {
21-
setEditorModelCto(value);
22+
set(value);
2223
debouncedSetModelCto(value);
2324
}
2425
};
2526

2627
return (
2728
<div className="column">
28-
<div className="tooltip">
29+
<div className="tooltip" style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
2930
<h3 style={{ color: textColor }}>Concerto Model</h3>
30-
<span style={{ color: textColor }} className="tooltiptext">
31-
Defines the data model for the template and its logic.
32-
</span>
31+
<div>
32+
<FaUndo onClick={undo} style={{ cursor: "pointer", color: textColor, marginRight: "8px" }} />
33+
<FaRedo onClick={redo} style={{ cursor: "pointer", color: textColor }} />
34+
</div>
3335
</div>
34-
<ConcertoEditor value={editorModelCto} onChange={handleChange} />
36+
<span style={{ color: textColor }} className="tooltiptext">
37+
Defines the data model for the template and its logic.
38+
</span>
39+
<ConcertoEditor value={value} onChange={handleChange} />
3540
</div>
3641
);
3742
}
3843

39-
export default TemplateModel;
44+
export default TemplateModel;

0 commit comments

Comments
 (0)