initial commit
This commit is contained in:
90
web/src/templates/template-editor-store.tsx
Normal file
90
web/src/templates/template-editor-store.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { create, createStore, useStore } from "zustand";
|
||||
import type { Template } from "./types";
|
||||
import { createContext, useContext } from "react";
|
||||
import { buildTemplate } from "./api";
|
||||
|
||||
interface TemplateEditorState {
|
||||
template: Template;
|
||||
currentFilePath: string;
|
||||
isBuildInProgress: boolean;
|
||||
isBuildOutputVisible: boolean;
|
||||
buildOutput: string;
|
||||
|
||||
startBuild: ({ imageTag }: { imageTag: string }) => Promise<void>;
|
||||
|
||||
setCurrentFilePath: (path: string) => void;
|
||||
|
||||
addBuildOutputChunk: (chunk: string) => void;
|
||||
|
||||
toggleBuildOutput: () => void;
|
||||
}
|
||||
|
||||
type TemplateEditorStore = ReturnType<typeof createTemplateEditorStore>;
|
||||
|
||||
function createTemplateEditorStore({
|
||||
template,
|
||||
currentFilePath,
|
||||
}: { template: Template; currentFilePath: string }) {
|
||||
return createStore<TemplateEditorState>()((set, get) => ({
|
||||
template,
|
||||
currentFilePath,
|
||||
isBuildInProgress: false,
|
||||
isBuildOutputVisible: false,
|
||||
buildOutput: "",
|
||||
|
||||
startBuild: async ({ imageTag }) => {
|
||||
const state = get();
|
||||
|
||||
set({
|
||||
isBuildInProgress: true,
|
||||
isBuildOutputVisible: true,
|
||||
buildOutput: "",
|
||||
});
|
||||
|
||||
try {
|
||||
await buildTemplate({
|
||||
imageTag,
|
||||
templateName: state.template.name,
|
||||
onBuildOutput: state.addBuildOutputChunk,
|
||||
});
|
||||
} catch {
|
||||
// TODO: handle build error
|
||||
} finally {
|
||||
set({ isBuildInProgress: false });
|
||||
}
|
||||
},
|
||||
|
||||
setCurrentFilePath: (path) => set({ currentFilePath: path }),
|
||||
|
||||
addBuildOutputChunk: (chunk) =>
|
||||
set((state) => ({
|
||||
...state,
|
||||
buildOutput: state.buildOutput + chunk,
|
||||
})),
|
||||
|
||||
toggleBuildOutput: () =>
|
||||
set((state) => ({
|
||||
...state,
|
||||
isBuildOutputVisible: !state.isBuildOutputVisible,
|
||||
})),
|
||||
}));
|
||||
}
|
||||
|
||||
const TemplateEditorStoreContext = createContext<TemplateEditorStore | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
function useTemplateEditorStore<T>(
|
||||
selector: (state: TemplateEditorState) => T,
|
||||
): T {
|
||||
const store = useContext(TemplateEditorStoreContext);
|
||||
if (!store) throw new Error("TemplateEditorStore not in context");
|
||||
return useStore(store, selector);
|
||||
}
|
||||
|
||||
export {
|
||||
TemplateEditorStoreContext,
|
||||
createTemplateEditorStore,
|
||||
useTemplateEditorStore,
|
||||
};
|
||||
export type { TemplateEditorStore, TemplateEditorState };
|
Reference in New Issue
Block a user