>;
}): JSX.Element {
- const { samples, loadSample } = useStoreWithEqualityFn(
+ const { samples, loadSample, sampleName } = useStoreWithEqualityFn(
useAppStore,
(state) => ({
samples: state.samples,
loadSample: state.loadSample as (key: string) => Promise
,
+ sampleName: state.sampleName
}),
shallow
);
- const [selectedSample, setSelectedSample] = useState(null);
+
const items: MenuProps["items"] = useMemo(
() =>
@@ -37,7 +39,7 @@ function SampleDropdown({
try {
await loadSample(e.key);
void message.info(`Loaded ${e.key} sample`);
- setSelectedSample(e.key);
+
} catch (error) {
void message.error("Failed to load sample");
} finally {
@@ -54,12 +56,11 @@ function SampleDropdown({
void handleMenuClick(e) }} trigger={["click"]}>
);
}
-
export default SampleDropdown;
diff --git a/src/store/store.ts b/src/store/store.ts
index 52d697f..083cef9 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -23,6 +23,7 @@ interface AppState {
sampleName: string;
backgroundColor: string;
textColor: string;
+ isLoading: boolean;
setTemplateMarkdown: (template: string) => Promise;
setEditorValue: (value: string) => void;
setModelCto: (model: string) => Promise;
@@ -44,8 +45,6 @@ export interface DecompressedData {
agreementHtml: string;
}
-const rebuildDeBounce = debounce(rebuild, 500);
-
async function rebuild(template: string, model: string, dataString: string) {
const modelManager = new ModelManager({ strict: true });
modelManager.addCTOModel(model, undefined, true);
@@ -69,6 +68,11 @@ async function rebuild(template: string, model: string, dataString: string) {
);
}
+const rebuildDeBounce = debounce(async (template: string, model: string, data: string) => {
+ const result = await rebuild(template, model, data);
+ return result;
+}, 500);
+
const useAppStore = create()(
immer(
devtools((set, get) => ({
@@ -83,6 +87,7 @@ const useAppStore = create()(
editorAgreementData: JSON.stringify(playground.DATA, null, 2),
agreementHtml: "",
error: undefined,
+ isLoading: false,
samples: SAMPLES,
init: async () => {
const params = new URLSearchParams(window.location.search);
@@ -90,7 +95,7 @@ const useAppStore = create()(
if (compressedData) {
await get().loadFromLink(compressedData);
} else {
- await get().rebuild();
+ await get().loadSample(playground.NAME);
}
},
loadSample: async (name: string) => {
@@ -107,24 +112,33 @@ const useAppStore = create()(
data: JSON.stringify(sample.DATA, null, 2),
editorAgreementData: JSON.stringify(sample.DATA, null, 2),
}));
- await get().rebuild();
+ get().rebuild();
}
},
rebuild: async () => {
- const { templateMarkdown, modelCto, data } = get();
+ set(() => ({ isLoading: true }));
try {
- const result = await rebuildDeBounce(templateMarkdown, modelCto, data);
- set(() => ({ agreementHtml: result, error: undefined })); // Clear error on success
+ const result = await rebuildDeBounce(
+ get().templateMarkdown,
+ get().modelCto,
+ get().data
+ );
+ set(() => ({ agreementHtml: result, error: undefined }));
} catch (error: any) {
set(() => ({ error: formatError(error) }));
+ } finally {
+ set(() => ({ isLoading: false }));
}
},
setTemplateMarkdown: async (template: string) => {
- set(() => ({ templateMarkdown: template }));
+ set(() => ({
+ templateMarkdown: template,
+ editorValue: template
+}));
const { modelCto, data } = get();
try {
const result = await rebuildDeBounce(template, modelCto, data);
- set(() => ({ agreementHtml: result, error: undefined })); // Clear error on success
+ set(() => ({ agreementHtml: result, error: undefined }));
} catch (error: any) {
set(() => ({ error: formatError(error) }));
}
@@ -133,11 +147,14 @@ const useAppStore = create()(
set(() => ({ editorValue: value }));
},
setModelCto: async (model: string) => {
- set(() => ({ modelCto: model }));
+ set(() => ({
+ modelCto: model,
+ editorModelCto: model
+}));
const { templateMarkdown, data } = get();
try {
const result = await rebuildDeBounce(templateMarkdown, model, data);
- set(() => ({ agreementHtml: result, error: undefined })); // Clear error on success
+ set(() => ({ agreementHtml: result, error: undefined }));
} catch (error: any) {
set(() => ({ error: formatError(error) }));
}
@@ -146,14 +163,17 @@ const useAppStore = create()(
set(() => ({ editorModelCto: value }));
},
setData: async (data: string) => {
- set(() => ({ data }));
+ set(() => ({
+ data,
+ editorAgreementData: data
+}));
try {
const result = await rebuildDeBounce(
get().templateMarkdown,
get().modelCto,
data
);
- set(() => ({ agreementHtml: result, error: undefined })); // Clear error on success
+ set(() => ({ agreementHtml: result, error: undefined }));
} catch (error: any) {
set(() => ({ error: formatError(error) }));
}
@@ -162,21 +182,27 @@ const useAppStore = create()(
set(() => ({ editorAgreementData: value }));
},
generateShareableLink: () => {
- const state = get();
- const compressedData = compress({
- templateMarkdown: state.templateMarkdown,
- modelCto: state.modelCto,
- data: state.data,
- agreementHtml: state.agreementHtml,
- });
- return `${window.location.origin}?data=${compressedData}`;
+ try {
+ const state = get();
+ const compressedData = compress({
+ templateMarkdown: state.templateMarkdown,
+ modelCto: state.modelCto,
+ data: state.data,
+ agreementHtml: state.agreementHtml,
+ });
+ return `${window.location.origin}?data=${compressedData}`;
+ } catch (error) {
+ set(() => ({ error: 'Failed to generate share link: ' + (error instanceof Error ? error.message : 'Unknown error') }));
+ return window.location.href;
+ }
},
loadFromLink: async (compressedData: string) => {
try {
- const { templateMarkdown, modelCto, data, agreementHtml } = decompress(compressedData);
- if (!templateMarkdown || !modelCto || !data) {
- throw new Error("Invalid share link data");
+ const decompressed = decompress(compressedData);
+ if (!decompressed?.templateMarkdown || !decompressed?.modelCto || !decompressed?.data) {
+ throw new Error("Invalid share link - missing required fields");
}
+ const { templateMarkdown, modelCto, data, agreementHtml } = decompressed;
set(() => ({
templateMarkdown,
editorValue: templateMarkdown,
@@ -185,9 +211,9 @@ const useAppStore = create()(
data,
editorAgreementData: data,
agreementHtml,
- error: undefined,
+ error: undefined
}));
- await get().rebuild();
+
} catch (error) {
set(() => ({
error: "Failed to load shared content: " + (error instanceof Error ? error.message : "Unknown error"),