Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 8 additions & 12 deletions src/components/useUndoRedo.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
import { useState } from 'react';

import { useState,useEffect } from 'react';

function useUndoRedo<T>(initialValue: T, onChange?: (value: T) => void) {
function useUndoRedo<T>(initialValue: T, onChange?: (value: T) => void, onSync?: (value: T) => Promise<void>) {
const [past, setPast] = useState<T[]>([]);
const [present, setPresent] = useState<T>(initialValue);
const [future, setFuture] = useState<T[]>([]);

useEffect(() => {
setPresent(initialValue);
setPast([]);
setFuture([]);
}, [initialValue]);

const setValue = (newValue: T) => {
setPast((prevPast) => [...prevPast, present]);
setPresent(newValue);
setFuture([]);
if (onChange) onChange(newValue); // Sync with store
if (onChange) onChange(newValue); // Update editor state
if (onSync) onSync(newValue); // Sync to main state and rebuild
};

const undo = () => {
Expand All @@ -25,7 +19,8 @@ function useUndoRedo<T>(initialValue: T, onChange?: (value: T) => void) {
setPast((prevPast) => prevPast.slice(0, -1));
setFuture((prevFuture) => [present, ...prevFuture]);
setPresent(previous);
if (onChange) onChange(previous);
if (onChange) onChange(previous); // Update editor state
if (onSync) onSync(previous); // Sync to main state and rebuild
};

const redo = () => {
Expand All @@ -34,7 +29,8 @@ function useUndoRedo<T>(initialValue: T, onChange?: (value: T) => void) {
setFuture((prevFuture) => prevFuture.slice(1));
setPast((prevPast) => [...prevPast, present]);
setPresent(next);
if (onChange) onChange(next);
if (onChange) onChange(next); // Update editor state
if (onSync) onSync(next); // Sync to main state and rebuild
};

return { value: present, setValue, undo, redo };
Expand Down
14 changes: 9 additions & 5 deletions src/editors/editorsContainer/AgreementData.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import JSONEditor from "../JSONEditor";
import useAppStore from "../../store/store";
import useUndoRedo from "../../components/useUndoRedo";

import { FaUndo, FaRedo } from "react-icons/fa";

function AgreementData() {
const textColor = useAppStore((state) => state.textColor);
const editorAgreementData = useAppStore((state) => state.editorAgreementData);
const setEditorAgreementData = useAppStore((state) => state.setEditorAgreementData);
const setData = useAppStore((state) => state.setData);
const { value, setValue, undo, redo } = useUndoRedo(
useAppStore((state) => state.data),
setData
editorAgreementData,
setEditorAgreementData,
setData // Sync to main state and rebuild
);

const handleChange = (value: string | undefined) => {
if (value !== undefined) {
setValue(value);
setValue(value); // Update editor state and sync
setData(value);
}
};

return (
<div className="column" >
<div className="column">
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
<h3 style={{ color: textColor }}>Data</h3>
<div>
Expand All @@ -28,7 +32,7 @@ function AgreementData() {
</div>
</div>
<p style={{ color: textColor }}>
JSON data (an instance of the Concerto model) used to preview output from the template.
JSON data (an instance of the Concerto model) used to preview output from the template.
</p>
<JSONEditor value={value} onChange={handleChange} />
</div>
Expand Down
11 changes: 7 additions & 4 deletions src/editors/editorsContainer/TemplateMarkdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@ import { FaUndo, FaRedo } from "react-icons/fa";
function TemplateMarkdown() {
const textColor = useAppStore((state) => state.textColor);
const backgroundColor = useAppStore((state) => state.backgroundColor);
const editorValue = useAppStore((state) => state.editorValue);
const setEditorValue = useAppStore((state) => state.setEditorValue);
const setTemplateMarkdown = useAppStore((state) => state.setTemplateMarkdown);
const { value, setValue, undo, redo } = useUndoRedo(
useAppStore((state) => state.templateMarkdown),
setTemplateMarkdown
editorValue,
setEditorValue,
setTemplateMarkdown // Sync to main state and rebuild
);

const handleChange = (value: string | undefined) => {
if (value !== undefined) {
setValue(value);
setTemplateMarkdown(value);
setValue(value); // Update editor state and sync
setTemplateMarkdown(value);
}
};

Expand Down
12 changes: 8 additions & 4 deletions src/editors/editorsContainer/TemplateModel.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import ConcertoEditor from "../ConcertoEditor";
import useAppStore from "../../store/store";
import useUndoRedo from "../../components/useUndoRedo";

import { FaUndo, FaRedo } from "react-icons/fa";

function TemplateModel() {
const textColor = useAppStore((state) => state.textColor);
const editorModelCto = useAppStore((state) => state.editorModelCto);
const setEditorModelCto = useAppStore((state) => state.setEditorModelCto);
const setModelCto = useAppStore((state) => state.setModelCto);
const { value, setValue, undo, redo } = useUndoRedo(
useAppStore((state) => state.modelCto),
setModelCto
editorModelCto,
setEditorModelCto,
setModelCto // Sync to main state and rebuild
);

const handleChange = (value: string | undefined) => {
if (value !== undefined) {
setValue(value);
setValue(value); // Update editor state and sync
setModelCto(value);
}
};
Expand Down
49 changes: 34 additions & 15 deletions src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,23 @@ import { compress, decompress } from "../utils/compression/compression";

interface AppState {
templateMarkdown: string;
editorValue: string;
modelCto: string;
editorModelCto: string;
data: string;
editorAgreementData: string;
agreementHtml: string;
error: string | undefined;
samples: Array<Sample>;
sampleName: string;
backgroundColor: string;
textColor: string;
setTemplateMarkdown: (template: string) => Promise<void>;
setEditorValue: (value: string) => void;
setModelCto: (model: string) => Promise<void>;
setEditorModelCto: (value: string) => void;
setData: (data: string) => Promise<void>;
setEditorAgreementData: (value: string) => void;
rebuild: () => Promise<void>;
init: () => Promise<void>;
loadSample: (name: string) => Promise<void>;
Expand Down Expand Up @@ -70,8 +76,11 @@ const useAppStore = create<AppState>()(
textColor: '#121212',
sampleName: playground.NAME,
templateMarkdown: playground.TEMPLATE,
editorValue: playground.TEMPLATE,
modelCto: playground.MODEL,
editorModelCto: playground.MODEL,
data: JSON.stringify(playground.DATA, null, 2),
editorAgreementData: JSON.stringify(playground.DATA, null, 2),
agreementHtml: "",
error: undefined,
samples: SAMPLES,
Expand All @@ -92,8 +101,11 @@ const useAppStore = create<AppState>()(
agreementHtml: undefined,
error: undefined,
templateMarkdown: sample.TEMPLATE,
editorValue: sample.TEMPLATE,
modelCto: sample.MODEL,
editorModelCto: sample.MODEL,
data: JSON.stringify(sample.DATA, null, 2),
editorAgreementData: JSON.stringify(sample.DATA, null, 2),
}));
await get().rebuild();
}
Expand All @@ -102,58 +114,61 @@ const useAppStore = create<AppState>()(
const { templateMarkdown, modelCto, data } = get();
try {
const result = await rebuildDeBounce(templateMarkdown, modelCto, data);
set(() => ({ agreementHtml: result, error: undefined }));
set(() => ({ agreementHtml: result, error: undefined })); // Clear error on success
} catch (error: any) {
set(() => ({ error: formatError(error) }));
}
},
setTemplateMarkdown: async (template: string) => {
set(() => ({ templateMarkdown: template }));
const { modelCto, data } = get();
try {
const result = await rebuildDeBounce(template, modelCto, data);
set(() => ({
templateMarkdown: template,
agreementHtml: result,
error: undefined,
}));
set(() => ({ agreementHtml: result, error: undefined })); // Clear error on success
} catch (error: any) {
set(() => ({ error: formatError(error) }));
}
},
setEditorValue: (value: string) => {
set(() => ({ editorValue: value }));
},
setModelCto: async (model: string) => {
set(() => ({ modelCto: model }));
const { templateMarkdown, data } = get();
try {
const result = await rebuildDeBounce(templateMarkdown, model, data);
set(() => ({
modelCto: model,
agreementHtml: result,
error: undefined,
}));
set(() => ({ agreementHtml: result, error: undefined })); // Clear error on success
} catch (error: any) {
set(() => ({ error: formatError(error) }));
}
},
setEditorModelCto: (value: string) => {
set(() => ({ editorModelCto: value }));
},
setData: async (data: string) => {
set(() => ({ data }));
try {
const result = await rebuildDeBounce(
get().templateMarkdown,
get().modelCto,
data
);
set(() => ({ agreementHtml: result, error: undefined, data }));
set(() => ({ agreementHtml: result, error: undefined })); // Clear error on success
} catch (error: any) {
set(() => ({ error: formatError(error) }));
}
},
setEditorAgreementData: (value: string) => {
set(() => ({ editorAgreementData: value }));
},
generateShareableLink: () => {
const state = get();
const dataToShare = {
const compressedData = compress({
templateMarkdown: state.templateMarkdown,
modelCto: state.modelCto,
data: state.data,
agreementHtml: state.agreementHtml,
};
const compressedData = compress(dataToShare);
});
return `${window.location.origin}?data=${compressedData}`;
},
loadFromLink: async (compressedData: string) => {
Expand All @@ -164,8 +179,11 @@ const useAppStore = create<AppState>()(
}
set(() => ({
templateMarkdown,
editorValue: templateMarkdown,
modelCto,
editorModelCto: modelCto,
data,
editorAgreementData: data,
agreementHtml,
error: undefined,
}));
Expand All @@ -189,6 +207,7 @@ const useAppStore = create<AppState>()(
)
);


export default useAppStore;

function formatError(error: any): string {
Expand Down